Bug 1508381 - remove now-unnecessary TASKCLUSTER_* variables r=tomprince
[gecko.git] / gfx / gl / SharedSurfaceEGL.cpp
blob17416deb3c77ef212784a1793d2e1d4a51ed5914
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"
16 namespace mozilla {
17 namespace gl {
19 /*static*/
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();
24 MOZ_ASSERT(egl);
25 MOZ_ASSERT(context);
27 UniquePtr<SharedSurface_EGLImage> ret;
29 if (!HasExtensions(egl, prodGL)) {
30 return ret;
33 MOZ_ALWAYS_TRUE(prodGL->MakeCurrent());
34 GLuint prodTex = CreateTextureForOffscreen(prodGL, formats, size);
35 if (!prodTex) {
36 return ret;
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);
43 if (!image) {
44 prodGL->fDeleteTextures(1, &prodTex);
45 return ret;
48 ret.reset(new SharedSurface_EGLImage(prodGL, egl, size, hasAlpha, formats,
49 prodTex, image));
50 return ret;
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,
62 bool hasAlpha,
63 const GLFormats& formats,
64 GLuint prodTex, EGLImage image)
65 : SharedSurface(
66 SharedSurfaceType::EGLImageShare, AttachmentType::GLTexture, gl, size,
67 hasAlpha,
68 false) // Can't recycle, as mSync changes never update TextureHost.
70 mMutex("SharedSurface_EGLImage mutex"),
71 mEGL(egl),
72 mFormats(formats),
73 mProdTex(prodTex),
74 mImage(image),
75 mSync(0) {}
77 SharedSurface_EGLImage::~SharedSurface_EGLImage() {
78 mEGL->fDestroyImage(Display(), mImage);
80 if (mSync) {
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);
84 mSync = 0;
87 if (!mGL || !mGL->MakeCurrent()) return;
89 mGL->fDeleteTextures(1, &mProdTex);
90 mProdTex = 0;
93 void SharedSurface_EGLImage::ProducerReleaseImpl() {
94 MutexAutoLock lock(mMutex);
95 mGL->MakeCurrent();
97 if (mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) &&
98 mGL->IsExtensionSupported(GLContext::OES_EGL_sync)) {
99 if (mSync) {
100 MOZ_RELEASE_ASSERT(false, "GFX: Non-recycleable should not Fence twice.");
101 MOZ_ALWAYS_TRUE(mEGL->fDestroySync(Display(), mSync));
102 mSync = 0;
105 mSync = mEGL->fCreateSync(Display(), LOCAL_EGL_SYNC_FENCE, nullptr);
106 if (mSync) {
107 mGL->fFlush();
108 return;
112 MOZ_ASSERT(!mSync);
113 mGL->fFinish();
116 void SharedSurface_EGLImage::ProducerReadAcquireImpl() {
117 // Wait on the fence, because presumably we're going to want to read this
118 // surface
119 if (mSync) {
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);
130 return true;
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 ////////////////////////////////////////////////////////////////////////
143 /*static*/
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;
151 UniquePtr<ptrT> ret;
153 auto* egl = gl::GLLibraryEGL::Get();
154 if (SharedSurface_EGLImage::HasExtensions(egl, prodGL)) {
155 ret.reset(new ptrT(prodGL, caps, allocator, flags, context));
158 return ret;
161 ////////////////////////////////////////////////////////////////////////
163 #ifdef MOZ_WIDGET_ANDROID
165 /*static*/
166 UniquePtr<SharedSurface_SurfaceTexture> SharedSurface_SurfaceTexture::Create(
167 GLContext* prodGL, const GLFormats& formats, const gfx::IntSize& size,
168 bool hasAlpha, java::GeckoSurface::Param surface) {
169 MOZ_ASSERT(surface);
171 UniquePtr<SharedSurface_SurfaceTexture> ret;
173 AndroidNativeWindow window(surface);
174 GLContextEGL* egl = GLContextEGL::Cast(prodGL);
175 MOZ_ASSERT(egl);
176 EGLSurface eglSurface = egl->CreateCompatibleSurface(window.NativeWindow());
177 if (!eglSurface) {
178 return ret;
181 ret.reset(new SharedSurface_SurfaceTexture(prodGL, size, hasAlpha, formats,
182 surface, eglSurface));
183 return ret;
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),
192 mSurface(surface),
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());
221 LockProdImpl();
222 mGL->SwapBuffers();
223 UnlockProdImpl();
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 */);
240 return true;
243 ////////////////////////////////////////////////////////////////////////
245 /*static*/
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));
252 return ret;
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);
261 if (!surface) {
262 // Try multi-buffer mode
263 surface =
264 java::SurfaceAllocator::AcquireSurface(size.width, size.height, false);
265 if (!surface) {
266 // Give up
267 NS_WARNING("Failed to allocate SurfaceTexture!");
268 return nullptr;
272 return SharedSurface_SurfaceTexture::Create(
273 mGL, mFormats, size, hasAlpha, java::GeckoSurface::Ref::From(surface));
276 #endif // MOZ_WIDGET_ANDROID
278 } // namespace gl
280 } /* namespace mozilla */