Bug 1735097 - Geolocation: use EpochTimeStamp instead of DOMTimeStamp r=saschanaz...
[gecko.git] / gfx / gl / SharedSurfaceEGL.cpp
blobf4a67fcd3235df93f01e6c0dd82c97a35992d0f2
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 "MozFramebuffer.h"
14 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
15 #include "SharedSurface.h"
17 #if defined(MOZ_WIDGET_ANDROID)
18 # include "AndroidNativeWindow.h"
19 # include "mozilla/java/SurfaceAllocatorWrappers.h"
20 # include "mozilla/java/GeckoSurfaceTextureWrappers.h"
21 #endif // defined(MOZ_WIDGET_ANDROID)
23 namespace mozilla {
24 namespace gl {
26 static bool HasEglImageExtensions(const GLContextEGL& gl) {
27 const auto& egl = *(gl.mEgl);
28 return egl.HasKHRImageBase() &&
29 egl.IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image) &&
30 (gl.IsExtensionSupported(GLContext::OES_EGL_image_external) ||
31 gl.IsExtensionSupported(GLContext::OES_EGL_image));
34 /*static*/
35 UniquePtr<SurfaceFactory_EGLImage> SurfaceFactory_EGLImage::Create(
36 GLContext& gl_) {
37 auto& gl = *GLContextEGL::Cast(&gl_);
38 if (!HasEglImageExtensions(gl)) return nullptr;
40 const auto partialDesc = PartialSharedSurfaceDesc{
41 &gl, SharedSurfaceType::EGLImageShare, layers::TextureType::EGLImage,
42 false, // Can't recycle, as mSync changes never update TextureHost.
44 return AsUnique(new SurfaceFactory_EGLImage(partialDesc));
47 // -
49 /*static*/
50 UniquePtr<SharedSurface_EGLImage> SharedSurface_EGLImage::Create(
51 const SharedSurfaceDesc& desc) {
52 const auto& gle = GLContextEGL::Cast(desc.gl);
53 const auto& context = gle->mContext;
54 const auto& egl = *(gle->mEgl);
56 auto fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false);
57 if (!fb) return nullptr;
59 const auto buffer = reinterpret_cast<EGLClientBuffer>(fb->ColorTex());
60 const auto image =
61 egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
62 if (!image) return nullptr;
64 return AsUnique(new SharedSurface_EGLImage(desc, std::move(fb), image));
67 SharedSurface_EGLImage::SharedSurface_EGLImage(const SharedSurfaceDesc& desc,
68 UniquePtr<MozFramebuffer>&& fb,
69 const EGLImage image)
70 : SharedSurface(desc, std::move(fb)),
71 mMutex("SharedSurface_EGLImage mutex"),
72 mImage(image) {}
74 SharedSurface_EGLImage::~SharedSurface_EGLImage() {
75 const auto& gle = GLContextEGL::Cast(mDesc.gl);
76 const auto& egl = gle->mEgl;
77 egl->fDestroyImage(mImage);
79 if (mSync) {
80 // We can't call this unless we have the ext, but we will always have
81 // the ext if we have something to destroy.
82 egl->fDestroySync(mSync);
83 mSync = 0;
87 void SharedSurface_EGLImage::ProducerReleaseImpl() {
88 const auto& gl = GLContextEGL::Cast(mDesc.gl);
89 const auto& egl = gl->mEgl;
91 MutexAutoLock lock(mMutex);
92 gl->MakeCurrent();
94 if (egl->IsExtensionSupported(EGLExtension::KHR_fence_sync) &&
95 gl->IsExtensionSupported(GLContext::OES_EGL_sync)) {
96 if (mSync) {
97 MOZ_RELEASE_ASSERT(false, "GFX: Non-recycleable should not Fence twice.");
98 MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
99 mSync = 0;
102 mSync = egl->fCreateSync(LOCAL_EGL_SYNC_FENCE, nullptr);
103 if (mSync) {
104 gl->fFlush();
105 return;
109 MOZ_ASSERT(!mSync);
110 gl->fFinish();
113 void SharedSurface_EGLImage::ProducerReadAcquireImpl() {
114 const auto& gle = GLContextEGL::Cast(mDesc.gl);
115 const auto& egl = gle->mEgl;
116 // Wait on the fence, because presumably we're going to want to read this
117 // surface
118 if (mSync) {
119 egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
123 Maybe<layers::SurfaceDescriptor> SharedSurface_EGLImage::ToSurfaceDescriptor() {
124 return Some(layers::EGLImageDescriptor((uintptr_t)mImage, (uintptr_t)mSync,
125 mDesc.size, true));
128 ////////////////////////////////////////////////////////////////////////
130 #ifdef MOZ_WIDGET_ANDROID
132 /*static*/
133 UniquePtr<SharedSurface_SurfaceTexture> SharedSurface_SurfaceTexture::Create(
134 const SharedSurfaceDesc& desc) {
135 const auto& size = desc.size;
137 jni::Object::LocalRef surfaceObj;
138 const bool useSingleBuffer =
139 desc.gl->Renderer() != GLRenderer::AndroidEmulator;
141 if (useSingleBuffer) {
142 surfaceObj =
143 java::SurfaceAllocator::AcquireSurface(size.width, size.height, true);
146 if (!surfaceObj) {
147 // Try multi-buffer mode
148 surfaceObj =
149 java::SurfaceAllocator::AcquireSurface(size.width, size.height, false);
152 if (!surfaceObj) {
153 // Give up
154 NS_WARNING("Failed to allocate SurfaceTexture!");
155 return nullptr;
157 const auto surface = java::GeckoSurface::Ref::From(surfaceObj);
159 AndroidNativeWindow window(surface);
160 const auto& gle = GLContextEGL::Cast(desc.gl);
161 MOZ_ASSERT(gle);
162 const auto eglSurface = gle->CreateCompatibleSurface(window.NativeWindow());
163 if (!eglSurface) return nullptr;
165 return AsUnique(new SharedSurface_SurfaceTexture(desc, surface, eglSurface));
168 SharedSurface_SurfaceTexture::SharedSurface_SurfaceTexture(
169 const SharedSurfaceDesc& desc, java::GeckoSurface::Param surface,
170 const EGLSurface eglSurface)
171 : SharedSurface(desc, nullptr),
172 mSurface(surface),
173 mEglSurface(eglSurface),
174 mEglDisplay(GLContextEGL::Cast(desc.gl)->mEgl) {}
176 SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture() {
177 if (mOrigEglSurface) {
178 // We are about to destroy mEglSurface.
179 // Make sure gl->SetEGLSurfaceOverride() doesn't keep a reference
180 // to the surface.
181 UnlockProd();
184 std::shared_ptr<EglDisplay> display = mEglDisplay.lock();
185 if (display) {
186 display->fDestroySurface(mEglSurface);
188 java::SurfaceAllocator::DisposeSurface(mSurface);
191 void SharedSurface_SurfaceTexture::LockProdImpl() {
192 MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
194 GLContextEGL* gl = GLContextEGL::Cast(mDesc.gl);
195 mOrigEglSurface = gl->GetEGLSurfaceOverride();
196 gl->SetEGLSurfaceOverride(mEglSurface);
199 void SharedSurface_SurfaceTexture::UnlockProdImpl() {
200 MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
202 GLContextEGL* gl = GLContextEGL::Cast(mDesc.gl);
203 MOZ_ASSERT(gl->GetEGLSurfaceOverride() == mEglSurface);
205 gl->SetEGLSurfaceOverride(mOrigEglSurface);
206 mOrigEglSurface = nullptr;
209 void SharedSurface_SurfaceTexture::ProducerReadReleaseImpl() {
210 // This GeckoSurfaceTexture is not SurfaceTexture of this class's GeckoSurface
211 // when current process is content process. In this case, SurfaceTexture of
212 // this class's GeckoSurface does not exist in this process. It exists in
213 // compositor's process. Then GeckoSurfaceTexture in this process is a sync
214 // surface that copies back the SurfaceTextrure from compositor's process. It
215 // was added by Bug 1486659. Then SurfaceTexture::UpdateTexImage() becomes
216 // very heavy weight, since it does copy back the SurfaceTextrure from
217 // compositor's process.
218 java::GeckoSurfaceTexture::LocalRef surfaceTexture =
219 java::GeckoSurfaceTexture::Lookup(mSurface->GetHandle());
220 if (!surfaceTexture) {
221 NS_ERROR("Didn't find GeckoSurfaceTexture in ProducerReadReleaseImpl");
222 return;
224 surfaceTexture->UpdateTexImage();
225 // Non single buffer mode Surface does not need ReleaseTexImage() call.
226 // When SurfaceTexture is sync Surface, it might not be single buffer mode.
227 if (surfaceTexture->IsSingleBuffer()) {
228 surfaceTexture->ReleaseTexImage();
232 void SharedSurface_SurfaceTexture::Commit() {
233 MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
235 LockProdImpl();
236 mDesc.gl->SwapBuffers();
237 UnlockProdImpl();
238 mSurface->SetAvailable(false);
241 void SharedSurface_SurfaceTexture::WaitForBufferOwnership() {
242 mSurface->SetAvailable(true);
245 bool SharedSurface_SurfaceTexture::IsBufferAvailable() const {
246 return mSurface->GetAvailable();
249 Maybe<layers::SurfaceDescriptor>
250 SharedSurface_SurfaceTexture::ToSurfaceDescriptor() {
251 return Some(layers::SurfaceTextureDescriptor(
252 mSurface->GetHandle(), mDesc.size, gfx::SurfaceFormat::R8G8B8A8,
253 false /* NOT continuous */, false /* Do not ignore transform */));
256 SurfaceFactory_SurfaceTexture::SurfaceFactory_SurfaceTexture(GLContext& gl)
257 : SurfaceFactory({&gl, SharedSurfaceType::AndroidSurfaceTexture,
258 layers::TextureType::AndroidNativeWindow, true}) {}
260 #endif // MOZ_WIDGET_ANDROID
262 } // namespace gl
264 } /* namespace mozilla */