Bumping manifests a=b2g-bump
[gecko.git] / gfx / gl / SharedSurfaceGralloc.cpp
blob0ece2ab1dcf05cd08a1b0cdce39d2e0c9c136ea3
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"
7 #include "mozilla/UniquePtr.h"
9 #include "SharedSurfaceGralloc.h"
11 #include "GLContext.h"
12 #include "SharedSurface.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::layers;
36 using namespace android;
38 SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
39 const SurfaceCaps& caps,
40 layers::ISurfaceAllocator* allocator)
41 : SurfaceFactory(prodGL, SharedSurfaceType::Gralloc, caps)
43 if (caps.surfaceAllocator) {
44 allocator = caps.surfaceAllocator;
47 MOZ_ASSERT(allocator);
49 mAllocator = allocator;
52 /*static*/ UniquePtr<SharedSurface_Gralloc>
53 SharedSurface_Gralloc::Create(GLContext* prodGL,
54 const GLFormats& formats,
55 const gfx::IntSize& size,
56 bool hasAlpha,
57 ISurfaceAllocator* allocator)
59 GLLibraryEGL* egl = &sEGLLibrary;
60 MOZ_ASSERT(egl);
62 UniquePtr<SharedSurface_Gralloc> ret;
64 DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
66 if (!HasExtensions(egl, prodGL))
67 return Move(ret);
69 gfxContentType type = hasAlpha ? gfxContentType::COLOR_ALPHA
70 : gfxContentType::COLOR;
72 gfxImageFormat format
73 = gfxPlatform::GetPlatform()->OptimalFormatForContent(type);
75 RefPtr<GrallocTextureClientOGL> grallocTC =
76 new GrallocTextureClientOGL(
77 allocator,
78 gfx::ImageFormatToSurfaceFormat(format),
79 gfx::BackendType::NONE, // we don't need to use it with a DrawTarget
80 layers::TextureFlags::DEFAULT);
82 if (!grallocTC->AllocateForGLRendering(size)) {
83 return Move(ret);
86 sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer();
88 EGLDisplay display = egl->Display();
89 EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
90 EGLint attrs[] = {
91 LOCAL_EGL_NONE, LOCAL_EGL_NONE
93 EGLImage image = egl->fCreateImage(display,
94 EGL_NO_CONTEXT,
95 LOCAL_EGL_NATIVE_BUFFER_ANDROID,
96 clientBuffer, attrs);
97 if (!image) {
98 return Move(ret);
101 prodGL->MakeCurrent();
102 GLuint prodTex = 0;
103 prodGL->fGenTextures(1, &prodTex);
104 ScopedBindTexture autoTex(prodGL, prodTex);
106 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
107 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
108 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
109 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
111 prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
113 egl->fDestroyImage(display, image);
115 ret.reset( new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl,
116 allocator, grallocTC,
117 prodTex) );
119 DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p,"
120 " GraphicBuffer %p.\n",
121 ret.get(), buffer.get());
123 return Move(ret);
127 SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext* prodGL,
128 const gfx::IntSize& size,
129 bool hasAlpha,
130 GLLibraryEGL* egl,
131 layers::ISurfaceAllocator* allocator,
132 layers::GrallocTextureClientOGL* textureClient,
133 GLuint prodTex)
134 : SharedSurface(SharedSurfaceType::Gralloc,
135 AttachmentType::GLTexture,
136 prodGL,
137 size,
138 hasAlpha)
139 , mEGL(egl)
140 , mSync(0)
141 , mAllocator(allocator)
142 , mTextureClient(textureClient)
143 , mProdTex(prodTex)
148 bool
149 SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
151 return egl->HasKHRImageBase() &&
152 gl->IsExtensionSupported(GLContext::OES_EGL_image);
155 SharedSurface_Gralloc::~SharedSurface_Gralloc()
158 DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
160 mGL->MakeCurrent();
161 mGL->fDeleteTextures(1, &mProdTex);
163 if (mSync) {
164 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
165 mSync = 0;
169 void
170 SharedSurface_Gralloc::Fence()
172 if (mSync) {
173 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
174 mSync = 0;
177 bool disableSyncFence = false;
178 // Disable sync fence on AdrenoTM200.
179 // AdrenoTM200's sync fence does not work correctly. See Bug 1022205.
180 if (mGL->Renderer() == GLRenderer::AdrenoTM200) {
181 disableSyncFence = true;
184 // When Android native fences are available, try
185 // them first since they're more likely to work.
186 // Android native fences are also likely to perform better.
187 if (!disableSyncFence &&
188 mEGL->IsExtensionSupported(GLLibraryEGL::ANDROID_native_fence_sync))
190 mGL->MakeCurrent();
191 EGLSync sync = mEGL->fCreateSync(mEGL->Display(),
192 LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID,
193 nullptr);
194 if (sync) {
195 mGL->fFlush();
196 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
197 int fenceFd = mEGL->fDupNativeFenceFDANDROID(mEGL->Display(), sync);
198 if (fenceFd != -1) {
199 mEGL->fDestroySync(mEGL->Display(), sync);
200 android::sp<android::Fence> fence(new android::Fence(fenceFd));
201 FenceHandle handle = FenceHandle(fence);
202 mTextureClient->SetAcquireFenceHandle(handle);
203 } else {
204 mSync = sync;
206 #else
207 mSync = sync;
208 #endif
209 return;
213 if (!disableSyncFence &&
214 mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync))
216 mGL->MakeCurrent();
217 mSync = mEGL->fCreateSync(mEGL->Display(),
218 LOCAL_EGL_SYNC_FENCE,
219 nullptr);
220 if (mSync) {
221 mGL->fFlush();
222 return;
226 // We should be able to rely on genlock write locks/read locks.
227 // But they're broken on some configs, and even a glFinish doesn't
228 // work. glReadPixels seems to, though.
229 if (gfxPrefs::GrallocFenceWithReadPixels()) {
230 mGL->MakeCurrent();
231 UniquePtr<char[]> buf = MakeUnique<char[]>(4);
232 mGL->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf.get());
236 bool
237 SharedSurface_Gralloc::WaitSync()
239 if (!mSync) {
240 // We must not be needed.
241 return true;
243 MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
245 EGLint status = mEGL->fClientWaitSync(mEGL->Display(),
246 mSync,
248 LOCAL_EGL_FOREVER);
250 if (status != LOCAL_EGL_CONDITION_SATISFIED) {
251 return false;
254 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
255 mSync = 0;
257 return true;
260 bool
261 SharedSurface_Gralloc::PollSync()
263 if (!mSync) {
264 // We must not be needed.
265 return true;
267 MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
269 EGLint status = 0;
270 MOZ_ALWAYS_TRUE( mEGL->fGetSyncAttrib(mEGL->Display(),
271 mSync,
272 LOCAL_EGL_SYNC_STATUS_KHR,
273 &status) );
274 if (status != LOCAL_EGL_SIGNALED_KHR) {
275 return false;
278 MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) );
279 mSync = 0;
281 return true;
284 void
285 SharedSurface_Gralloc::WaitForBufferOwnership()
287 mTextureClient->WaitForBufferOwnership();