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"
27 #define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0)
29 #define DEBUG_PRINT(...) do { } while (0)
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
,
57 ISurfaceAllocator
* allocator
)
59 GLLibraryEGL
* egl
= &sEGLLibrary
;
62 UniquePtr
<SharedSurface_Gralloc
> ret
;
64 DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
66 if (!HasExtensions(egl
, prodGL
))
69 gfxContentType type
= hasAlpha
? gfxContentType::COLOR_ALPHA
70 : gfxContentType::COLOR
;
73 = gfxPlatform::GetPlatform()->OptimalFormatForContent(type
);
75 RefPtr
<GrallocTextureClientOGL
> grallocTC
=
76 new GrallocTextureClientOGL(
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
)) {
86 sp
<GraphicBuffer
> buffer
= grallocTC
->GetGraphicBuffer();
88 EGLDisplay display
= egl
->Display();
89 EGLClientBuffer clientBuffer
= buffer
->getNativeBuffer();
91 LOCAL_EGL_NONE
, LOCAL_EGL_NONE
93 EGLImage image
= egl
->fCreateImage(display
,
95 LOCAL_EGL_NATIVE_BUFFER_ANDROID
,
101 prodGL
->MakeCurrent();
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
,
119 DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p,"
120 " GraphicBuffer %p.\n",
121 ret
.get(), buffer
.get());
127 SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext
* prodGL
,
128 const gfx::IntSize
& size
,
131 layers::ISurfaceAllocator
* allocator
,
132 layers::GrallocTextureClientOGL
* textureClient
,
134 : SharedSurface(SharedSurfaceType::Gralloc
,
135 AttachmentType::GLTexture
,
141 , mAllocator(allocator
)
142 , mTextureClient(textureClient
)
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);
161 mGL
->fDeleteTextures(1, &mProdTex
);
164 MOZ_ALWAYS_TRUE( mEGL
->fDestroySync(mEGL
->Display(), mSync
) );
170 SharedSurface_Gralloc::Fence()
173 MOZ_ALWAYS_TRUE( mEGL
->fDestroySync(mEGL
->Display(), mSync
) );
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
))
191 EGLSync sync
= mEGL
->fCreateSync(mEGL
->Display(),
192 LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID
,
196 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
197 int fenceFd
= mEGL
->fDupNativeFenceFDANDROID(mEGL
->Display(), sync
);
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
);
213 if (!disableSyncFence
&&
214 mEGL
->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync
))
217 mSync
= mEGL
->fCreateSync(mEGL
->Display(),
218 LOCAL_EGL_SYNC_FENCE
,
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()) {
231 UniquePtr
<char[]> buf
= MakeUnique
<char[]>(4);
232 mGL
->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA
, LOCAL_GL_UNSIGNED_BYTE
, buf
.get());
237 SharedSurface_Gralloc::WaitSync()
240 // We must not be needed.
243 MOZ_ASSERT(mEGL
->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync
));
245 EGLint status
= mEGL
->fClientWaitSync(mEGL
->Display(),
250 if (status
!= LOCAL_EGL_CONDITION_SATISFIED
) {
254 MOZ_ALWAYS_TRUE( mEGL
->fDestroySync(mEGL
->Display(), mSync
) );
261 SharedSurface_Gralloc::PollSync()
264 // We must not be needed.
267 MOZ_ASSERT(mEGL
->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync
));
270 MOZ_ALWAYS_TRUE( mEGL
->fGetSyncAttrib(mEGL
->Display(),
272 LOCAL_EGL_SYNC_STATUS_KHR
,
274 if (status
!= LOCAL_EGL_SIGNALED_KHR
) {
278 MOZ_ALWAYS_TRUE( mEGL
->fDestroySync(mEGL
->Display(), mSync
) );
285 SharedSurface_Gralloc::WaitForBufferOwnership()
287 mTextureClient
->WaitForBufferOwnership();