1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
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 "SharedSurfaceEGL.h"
8 #include "GLBlitHelper.h"
9 #include "GLContextEGL.h"
10 #include "GLContextProvider.h"
11 #include "GLLibraryEGL.h"
12 #include "GLReadTexImageHelper.h"
13 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
14 #include "SharedSurface.h"
20 UniquePtr
<SharedSurface_EGLImage
> SharedSurface_EGLImage::Create(
21 GLContext
* prodGL
, const GLFormats
& formats
, const gfx::IntSize
& size
,
22 bool hasAlpha
, EGLContext context
) {
23 auto* egl
= gl::GLLibraryEGL::Get();
27 UniquePtr
<SharedSurface_EGLImage
> ret
;
29 if (!HasExtensions(egl
, prodGL
)) {
33 MOZ_ALWAYS_TRUE(prodGL
->MakeCurrent());
34 GLuint prodTex
= CreateTextureForOffscreen(prodGL
, formats
, size
);
39 EGLClientBuffer buffer
=
40 reinterpret_cast<EGLClientBuffer
>(uintptr_t(prodTex
));
41 EGLImage image
= egl
->fCreateImage(egl
->Display(), context
,
42 LOCAL_EGL_GL_TEXTURE_2D
, buffer
, nullptr);
44 prodGL
->fDeleteTextures(1, &prodTex
);
48 ret
.reset(new SharedSurface_EGLImage(prodGL
, egl
, size
, hasAlpha
, formats
,
53 bool SharedSurface_EGLImage::HasExtensions(GLLibraryEGL
* egl
, GLContext
* gl
) {
54 return egl
->HasKHRImageBase() &&
55 egl
->IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image
) &&
56 (gl
->IsExtensionSupported(GLContext::OES_EGL_image_external
) ||
57 gl
->IsExtensionSupported(GLContext::OES_EGL_image
));
60 SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext
* gl
, GLLibraryEGL
* egl
,
61 const gfx::IntSize
& size
,
63 const GLFormats
& formats
,
64 GLuint prodTex
, EGLImage image
)
66 SharedSurfaceType::EGLImageShare
, AttachmentType::GLTexture
, gl
, size
,
68 false) // Can't recycle, as mSync changes never update TextureHost.
70 mMutex("SharedSurface_EGLImage mutex"),
77 SharedSurface_EGLImage::~SharedSurface_EGLImage() {
78 mEGL
->fDestroyImage(Display(), mImage
);
81 // We can't call this unless we have the ext, but we will always have
82 // the ext if we have something to destroy.
83 mEGL
->fDestroySync(Display(), mSync
);
87 if (!mGL
|| !mGL
->MakeCurrent()) return;
89 mGL
->fDeleteTextures(1, &mProdTex
);
93 void SharedSurface_EGLImage::ProducerReleaseImpl() {
94 MutexAutoLock
lock(mMutex
);
97 if (mEGL
->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync
) &&
98 mGL
->IsExtensionSupported(GLContext::OES_EGL_sync
)) {
100 MOZ_RELEASE_ASSERT(false, "GFX: Non-recycleable should not Fence twice.");
101 MOZ_ALWAYS_TRUE(mEGL
->fDestroySync(Display(), mSync
));
105 mSync
= mEGL
->fCreateSync(Display(), LOCAL_EGL_SYNC_FENCE
, nullptr);
116 void SharedSurface_EGLImage::ProducerReadAcquireImpl() {
117 // Wait on the fence, because presumably we're going to want to read this
120 mEGL
->fClientWaitSync(Display(), mSync
, 0, LOCAL_EGL_FOREVER
);
124 EGLDisplay
SharedSurface_EGLImage::Display() const { return mEGL
->Display(); }
126 bool SharedSurface_EGLImage::ToSurfaceDescriptor(
127 layers::SurfaceDescriptor
* const out_descriptor
) {
128 *out_descriptor
= layers::EGLImageDescriptor(
129 (uintptr_t)mImage
, (uintptr_t)mSync
, mSize
, mHasAlpha
);
133 bool SharedSurface_EGLImage::ReadbackBySharedHandle(
134 gfx::DataSourceSurface
* out_surface
) {
135 MOZ_ASSERT(out_surface
);
136 MOZ_ASSERT(NS_IsMainThread());
137 auto* egl
= gl::GLLibraryEGL::Get();
138 return egl
->ReadbackEGLImage(mImage
, out_surface
);
141 ////////////////////////////////////////////////////////////////////////
144 UniquePtr
<SurfaceFactory_EGLImage
> SurfaceFactory_EGLImage::Create(
145 GLContext
* prodGL
, const SurfaceCaps
& caps
,
146 const RefPtr
<layers::LayersIPCChannel
>& allocator
,
147 const layers::TextureFlags
& flags
) {
148 EGLContext context
= GLContextEGL::Cast(prodGL
)->mContext
;
150 typedef SurfaceFactory_EGLImage ptrT
;
153 auto* egl
= gl::GLLibraryEGL::Get();
154 if (SharedSurface_EGLImage::HasExtensions(egl
, prodGL
)) {
155 ret
.reset(new ptrT(prodGL
, caps
, allocator
, flags
, context
));
161 ////////////////////////////////////////////////////////////////////////
163 #ifdef MOZ_WIDGET_ANDROID
166 UniquePtr
<SharedSurface_SurfaceTexture
> SharedSurface_SurfaceTexture::Create(
167 GLContext
* prodGL
, const GLFormats
& formats
, const gfx::IntSize
& size
,
168 bool hasAlpha
, java::GeckoSurface::Param surface
) {
171 UniquePtr
<SharedSurface_SurfaceTexture
> ret
;
173 AndroidNativeWindow
window(surface
);
174 GLContextEGL
* egl
= GLContextEGL::Cast(prodGL
);
176 EGLSurface eglSurface
= egl
->CreateCompatibleSurface(window
.NativeWindow());
181 ret
.reset(new SharedSurface_SurfaceTexture(prodGL
, size
, hasAlpha
, formats
,
182 surface
, eglSurface
));
186 SharedSurface_SurfaceTexture::SharedSurface_SurfaceTexture(
187 GLContext
* gl
, const gfx::IntSize
& size
, bool hasAlpha
,
188 const GLFormats
& formats
, java::GeckoSurface::Param surface
,
189 EGLSurface eglSurface
)
190 : SharedSurface(SharedSurfaceType::AndroidSurfaceTexture
,
191 AttachmentType::Screen
, gl
, size
, hasAlpha
, true),
193 mEglSurface(eglSurface
) {}
195 SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture() {
196 GLContextProviderEGL::DestroyEGLSurface(mEglSurface
);
197 java::SurfaceAllocator::DisposeSurface(mSurface
);
200 void SharedSurface_SurfaceTexture::LockProdImpl() {
201 MOZ_RELEASE_ASSERT(mSurface
->GetAvailable());
203 GLContextEGL
* gl
= GLContextEGL::Cast(mGL
);
204 mOrigEglSurface
= gl
->GetEGLSurfaceOverride();
205 gl
->SetEGLSurfaceOverride(mEglSurface
);
208 void SharedSurface_SurfaceTexture::UnlockProdImpl() {
209 MOZ_RELEASE_ASSERT(mSurface
->GetAvailable());
211 GLContextEGL
* gl
= GLContextEGL::Cast(mGL
);
212 MOZ_ASSERT(gl
->GetEGLSurfaceOverride() == mEglSurface
);
214 gl
->SetEGLSurfaceOverride(mOrigEglSurface
);
215 mOrigEglSurface
= nullptr;
218 void SharedSurface_SurfaceTexture::Commit() {
219 MOZ_RELEASE_ASSERT(mSurface
->GetAvailable());
224 mSurface
->SetAvailable(false);
227 void SharedSurface_SurfaceTexture::WaitForBufferOwnership() {
228 mSurface
->SetAvailable(true);
231 bool SharedSurface_SurfaceTexture::IsBufferAvailable() const {
232 return mSurface
->GetAvailable();
235 bool SharedSurface_SurfaceTexture::ToSurfaceDescriptor(
236 layers::SurfaceDescriptor
* const out_descriptor
) {
237 *out_descriptor
= layers::SurfaceTextureDescriptor(
238 mSurface
->GetHandle(), mSize
, gfx::SurfaceFormat::R8G8B8A8
,
239 false /* NOT continuous */, false /* Do not ignore transform */);
243 ////////////////////////////////////////////////////////////////////////
246 UniquePtr
<SurfaceFactory_SurfaceTexture
> SurfaceFactory_SurfaceTexture::Create(
247 GLContext
* prodGL
, const SurfaceCaps
& caps
,
248 const RefPtr
<layers::LayersIPCChannel
>& allocator
,
249 const layers::TextureFlags
& flags
) {
250 UniquePtr
<SurfaceFactory_SurfaceTexture
> ret(
251 new SurfaceFactory_SurfaceTexture(prodGL
, caps
, allocator
, flags
));
255 UniquePtr
<SharedSurface
> SurfaceFactory_SurfaceTexture::CreateShared(
256 const gfx::IntSize
& size
) {
257 bool hasAlpha
= mReadCaps
.alpha
;
259 jni::Object::LocalRef surface
=
260 java::SurfaceAllocator::AcquireSurface(size
.width
, size
.height
, true);
262 // Try multi-buffer mode
264 java::SurfaceAllocator::AcquireSurface(size
.width
, size
.height
, false);
267 NS_WARNING("Failed to allocate SurfaceTexture!");
272 return SharedSurface_SurfaceTexture::Create(
273 mGL
, mFormats
, size
, hasAlpha
, java::GeckoSurface::Ref::From(surface
));
276 #endif // MOZ_WIDGET_ANDROID
280 } /* namespace mozilla */