Bug 1022205 - disable sync fence on AdrenoTM200 r=jgilbert
[gecko.git] / gfx / gl / SharedSurfaceGralloc.cpp
blobc7662746299a516f77e75614ef957a2589366dc0
1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/Preferences.h"
8 #include "SharedSurfaceGralloc.h"
10 #include "GLContext.h"
11 #include "SharedSurfaceGL.h"
12 #include "SurfaceFactory.h"
13 #include "GLLibraryEGL.h"
14 #include "mozilla/layers/GrallocTextureClient.h"
15 #include "mozilla/layers/ShadowLayers.h"
17 #include "ui/GraphicBuffer.h"
18 #include "../layers/ipc/ShadowLayers.h"
19 #include "ScopedGLHelpers.h"
21 #include "gfxPlatform.h"
22 #include "gfx2DGlue.h"
23 #include "gfxPrefs.h"
25 #define DEBUG_GRALLOC
26 #ifdef DEBUG_GRALLOC
27 #define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0)
28 #else
29 #define DEBUG_PRINT(...) do { } while (0)
30 #endif
32 namespace mozilla {
33 namespace gl {
35 using namespace mozilla::gfx;
36 using namespace mozilla::layers;
37 using namespace android;
39 SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
40 const SurfaceCaps& caps,
41 layers::ISurfaceAllocator* allocator)
42 : SurfaceFactory_GL(prodGL, SharedSurfaceType::Gralloc, caps)
44 if (caps.surfaceAllocator) {
45 allocator = caps.surfaceAllocator;
48 MOZ_ASSERT(allocator);
50 mAllocator = allocator;
53 SharedSurface_Gralloc*
54 SharedSurface_Gralloc::Create(GLContext* prodGL,
55 const GLFormats& formats,
56 const gfx::IntSize& size,
57 bool hasAlpha,
58 ISurfaceAllocator* allocator)
60 GLLibraryEGL* egl = &sEGLLibrary;
61 MOZ_ASSERT(egl);
63 DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
65 if (!HasExtensions(egl, prodGL))
66 return nullptr;
68 gfxContentType type = hasAlpha ? gfxContentType::COLOR_ALPHA
69 : gfxContentType::COLOR;
71 gfxImageFormat format
72 = gfxPlatform::GetPlatform()->OptimalFormatForContent(type);
74 RefPtr<GrallocTextureClientOGL> grallocTC =
75 new GrallocTextureClientOGL(
76 allocator,
77 gfx::ImageFormatToSurfaceFormat(format),
78 gfx::BackendType::NONE, // we don't need to use it with a DrawTarget
79 layers::TextureFlags::DEFAULT);
81 if (!grallocTC->AllocateForGLRendering(size)) {
82 return nullptr;
85 sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer();
87 EGLDisplay display = egl->Display();
88 EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
89 EGLint attrs[] = {
90 LOCAL_EGL_NONE, LOCAL_EGL_NONE
92 EGLImage image = egl->fCreateImage(display,
93 EGL_NO_CONTEXT,
94 LOCAL_EGL_NATIVE_BUFFER_ANDROID,
95 clientBuffer, attrs);
96 if (!image) {
97 return nullptr;
100 prodGL->MakeCurrent();
101 GLuint prodTex = 0;
102 prodGL->fGenTextures(1, &prodTex);
103 ScopedBindTexture autoTex(prodGL, prodTex);
105 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
106 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
107 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
108 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
110 prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
112 egl->fDestroyImage(display, image);
114 SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, grallocTC, prodTex);
116 DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p, GraphicBuffer %p.\n", surf, buffer.get());
118 return surf;
122 SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext* prodGL,
123 const gfx::IntSize& size,
124 bool hasAlpha,
125 GLLibraryEGL* egl,
126 layers::ISurfaceAllocator* allocator,
127 layers::GrallocTextureClientOGL* textureClient,
128 GLuint prodTex)
129 : SharedSurface_GL(SharedSurfaceType::Gralloc,
130 AttachmentType::GLTexture,
131 prodGL,
132 size,
133 hasAlpha)
134 , mEGL(egl)
135 , mSync(0)
136 , mAllocator(allocator)
137 , mTextureClient(textureClient)
138 , mProdTex(prodTex)
143 bool
144 SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
146 return egl->HasKHRImageBase() &&
147 gl->IsExtensionSupported(GLContext::OES_EGL_image);
150 SharedSurface_Gralloc::~SharedSurface_Gralloc()
153 DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
155 mGL->MakeCurrent();
156 mGL->fDeleteTextures(1, &mProdTex);
158 if (mSync) {
159 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
160 mSync = 0;
164 void
165 SharedSurface_Gralloc::Fence()
167 if (mSync) {
168 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
169 mSync = 0;
172 bool disableSyncFence = false;
173 // Disable sync fence on AdrenoTM200.
174 // AdrenoTM200's sync fence does not work correctly. See Bug 1022205.
175 if (mGL->Renderer() == GLRenderer::AdrenoTM200) {
176 disableSyncFence = true;
179 // When Android native fences are available, try
180 // them first since they're more likely to work.
181 // Android native fences are also likely to perform better.
182 if (!disableSyncFence &&
183 mEGL->IsExtensionSupported(GLLibraryEGL::ANDROID_native_fence_sync))
185 mGL->MakeCurrent();
186 EGLSync sync = mEGL->fCreateSync(mEGL->Display(),
187 LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID,
188 nullptr);
189 if (sync) {
190 mGL->fFlush();
191 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
192 int fenceFd = mEGL->fDupNativeFenceFDANDROID(mEGL->Display(), sync);
193 if (fenceFd != -1) {
194 mEGL->fDestroySync(mEGL->Display(), sync);
195 android::sp<android::Fence> fence(new android::Fence(fenceFd));
196 FenceHandle handle = FenceHandle(fence);
197 mTextureClient->SetAcquireFenceHandle(handle);
198 } else {
199 mSync = sync;
201 #else
202 mSync = sync;
203 #endif
204 return;
208 if (!disableSyncFence &&
209 mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync))
211 mGL->MakeCurrent();
212 mSync = mEGL->fCreateSync(mEGL->Display(),
213 LOCAL_EGL_SYNC_FENCE,
214 nullptr);
215 if (mSync) {
216 mGL->fFlush();
217 return;
221 // We should be able to rely on genlock write locks/read locks.
222 // But they're broken on some configs, and even a glFinish doesn't
223 // work. glReadPixels seems to, though.
224 if (gfxPrefs::GrallocFenceWithReadPixels()) {
225 mGL->MakeCurrent();
226 ScopedDeleteArray<char> buf(new char[4]);
227 mGL->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf);
231 bool
232 SharedSurface_Gralloc::WaitSync()
234 if (!mSync) {
235 // We must not be needed.
236 return true;
238 MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
240 EGLint status = mEGL->fClientWaitSync(mEGL->Display(),
241 mSync,
243 LOCAL_EGL_FOREVER);
245 if (status != LOCAL_EGL_CONDITION_SATISFIED) {
246 return false;
249 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
250 mSync = 0;
252 return true;
255 void
256 SharedSurface_Gralloc::WaitForBufferOwnership()
258 mTextureClient->WaitForBufferOwnership();