diff --git a/gfx/gl/ScopedGLHelpers.cpp b/gfx/gl/ScopedGLHelpers.cpp index 18ae2d122e6..73706eb92eb 100644 --- a/gfx/gl/ScopedGLHelpers.cpp +++ b/gfx/gl/ScopedGLHelpers.cpp @@ -124,7 +124,6 @@ ScopedBindTexture::Init(GLenum aTarget) GLenum bindingTarget = (aTarget == LOCAL_GL_TEXTURE_2D) ? LOCAL_GL_TEXTURE_BINDING_2D : (aTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) ? LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB : (aTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? LOCAL_GL_TEXTURE_BINDING_CUBE_MAP - : (aTarget == LOCAL_GL_TEXTURE_EXTERNAL) ? LOCAL_GL_TEXTURE_EXTERNAL : LOCAL_GL_NONE; MOZ_ASSERT(bindingTarget != LOCAL_GL_NONE); mGL->GetUIntegerv(bindingTarget, &mOldTex); diff --git a/gfx/gl/SharedSurfaceEGL.cpp b/gfx/gl/SharedSurfaceEGL.cpp index e8ced12a185..0e502cde7a4 100644 --- a/gfx/gl/SharedSurfaceEGL.cpp +++ b/gfx/gl/SharedSurfaceEGL.cpp @@ -27,30 +27,18 @@ SharedSurface_EGLImage::Create(GLContext* prodGL, { GLLibraryEGL* egl = &sEGLLibrary; MOZ_ASSERT(egl); - MOZ_ASSERT(context); - if (!HasExtensions(egl, prodGL)) { + if (!HasExtensions(egl, prodGL)) return nullptr; - } MOZ_ALWAYS_TRUE(prodGL->MakeCurrent()); GLuint prodTex = CreateTextureForOffscreen(prodGL, formats, size); - if (!prodTex) { + if (!prodTex) return nullptr; - } - - EGLClientBuffer buffer = reinterpret_cast(prodTex); - EGLImage image = egl->fCreateImage(egl->Display(), context, - LOCAL_EGL_GL_TEXTURE_2D, buffer, - nullptr); - if (!image) { - prodGL->fDeleteTextures(1, &prodTex); - return nullptr; - } return new SharedSurface_EGLImage(prodGL, egl, size, hasAlpha, - formats, prodTex, image); + formats, prodTex); } @@ -59,7 +47,7 @@ SharedSurface_EGLImage::HasExtensions(GLLibraryEGL* egl, GLContext* gl) { return egl->HasKHRImageBase() && egl->IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image) && - gl->IsExtensionSupported(GLContext::OES_EGL_image_external); + gl->IsExtensionSupported(GLContext::OES_EGL_image); } SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl, @@ -67,8 +55,7 @@ SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl, const gfx::IntSize& size, bool hasAlpha, const GLFormats& formats, - GLuint prodTex, - EGLImage image) + GLuint prodTex) : SharedSurface_GL(SharedSurfaceType::EGLImageShare, AttachmentType::GLTexture, gl, @@ -78,10 +65,14 @@ SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl, , mEGL(egl) , mFormats(formats) , mProdTex(prodTex) - , mImage(image) + , mProdTexForPipe(0) + , mImage(0) , mCurConsGL(nullptr) , mConsTex(0) , mSync(0) + , mPipeFailed(false) + , mPipeComplete(false) + , mPipeActive(false) {} SharedSurface_EGLImage::~SharedSurface_EGLImage() @@ -93,6 +84,11 @@ SharedSurface_EGLImage::~SharedSurface_EGLImage() mGL->fDeleteTextures(1, &mProdTex); mProdTex = 0; + if (mProdTexForPipe) { + mGL->fDeleteTextures(1, &mProdTexForPipe); + mProdTexForPipe = 0; + } + if (mConsTex) { MOZ_ASSERT(mGarbageBin); mGarbageBin->Trash(mConsTex); @@ -107,12 +103,94 @@ SharedSurface_EGLImage::~SharedSurface_EGLImage() } } +void +SharedSurface_EGLImage::LockProdImpl() +{ + MutexAutoLock lock(mMutex); + + if (!mPipeComplete) + return; + + if (mPipeActive) + return; + + mGL->BlitHelper()->BlitTextureToTexture(mProdTex, mProdTexForPipe, Size(), Size()); + mGL->fDeleteTextures(1, &mProdTex); + mProdTex = mProdTexForPipe; + mProdTexForPipe = 0; + mPipeActive = true; +} + +static bool +CreateTexturePipe(GLLibraryEGL* const egl, GLContext* const gl, + const GLFormats& formats, const gfx::IntSize& size, + GLuint* const out_tex, EGLImage* const out_image) +{ + MOZ_ASSERT(out_tex && out_image); + *out_tex = 0; + *out_image = 0; + + GLuint tex = CreateTextureForOffscreen(gl, formats, size); + if (!tex) + return false; + + EGLContext context = GLContextEGL::Cast(gl)->GetEGLContext(); + MOZ_ASSERT(context); + EGLClientBuffer buffer = reinterpret_cast(tex); + EGLImage image = egl->fCreateImage(egl->Display(), context, + LOCAL_EGL_GL_TEXTURE_2D, buffer, + nullptr); + if (!image) { + gl->fDeleteTextures(1, &tex); + return false; + } + + // Success. + *out_tex = tex; + *out_image = image; + return true; +} + void SharedSurface_EGLImage::Fence() { MutexAutoLock lock(mMutex); mGL->MakeCurrent(); + if (!mPipeActive) { + MOZ_ASSERT(!mSync); + MOZ_ASSERT(!mPipeComplete); + + if (!mPipeFailed) { + if (!CreateTexturePipe(mEGL, mGL, mFormats, Size(), + &mProdTexForPipe, &mImage)) + { + mPipeFailed = true; + } + } + + if (!mPixels) { + SurfaceFormat format = + HasAlpha() ? SurfaceFormat::B8G8R8A8 + : SurfaceFormat::B8G8R8X8; + mPixels = Factory::CreateDataSourceSurface(Size(), format); + } + + DataSourceSurface::MappedSurface map; + mPixels->Map(DataSourceSurface::MapType::WRITE, &map); + + nsRefPtr wrappedData = + new gfxImageSurface(map.mData, + ThebesIntSize(mPixels->GetSize()), + map.mStride, + SurfaceFormatToImageFormat(mPixels->GetFormat())); + ReadScreenIntoImageSurface(mGL, wrappedData); + mPixels->Unmap(); + return; + } + MOZ_ASSERT(mPipeActive); + MOZ_ASSERT(mCurConsGL); + if (mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) && mGL->IsExtensionSupported(GLContext::OES_EGL_sync)) { @@ -171,28 +249,42 @@ SharedSurface_EGLImage::Display() const return mEGL->Display(); } -void -SharedSurface_EGLImage::AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target) +GLuint +SharedSurface_EGLImage::AcquireConsumerTexture(GLContext* consGL) { MutexAutoLock lock(mMutex); MOZ_ASSERT(!mCurConsGL || consGL == mCurConsGL); + if (mPipeFailed) + return 0; + + if (mPipeActive) { + MOZ_ASSERT(mConsTex); + + return mConsTex; + } if (!mConsTex) { consGL->fGenTextures(1, &mConsTex); - MOZ_ASSERT(mConsTex); - - ScopedBindTexture autoTex(consGL, mConsTex, LOCAL_GL_TEXTURE_EXTERNAL); - consGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL, mImage); + ScopedBindTexture autoTex(consGL, mConsTex); + consGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, mImage); + mPipeComplete = true; mCurConsGL = consGL; mGarbageBin = consGL->TexGarbageBin(); } MOZ_ASSERT(consGL == mCurConsGL); - *out_texture = mConsTex; - *out_target = LOCAL_GL_TEXTURE_EXTERNAL; + return 0; } +DataSourceSurface* +SharedSurface_EGLImage::GetPixels() const +{ + MutexAutoLock lock(mMutex); + return mPixels; +} + + SurfaceFactory_EGLImage* SurfaceFactory_EGLImage::Create(GLContext* prodGL, diff --git a/gfx/gl/SharedSurfaceEGL.h b/gfx/gl/SharedSurfaceEGL.h index 3a55983f3bd..03339f44bb7 100644 --- a/gfx/gl/SharedSurfaceEGL.h +++ b/gfx/gl/SharedSurfaceEGL.h @@ -40,19 +40,23 @@ protected: GLLibraryEGL* const mEGL; const GLFormats mFormats; GLuint mProdTex; + RefPtr mPixels; + GLuint mProdTexForPipe; // Moves to mProdTex when mPipeActive becomes true. EGLImage mImage; GLContext* mCurConsGL; GLuint mConsTex; nsRefPtr mGarbageBin; EGLSync mSync; + bool mPipeFailed; // Pipe creation failed, and has been abandoned. + bool mPipeComplete; // Pipe connects (mPipeActive ? mProdTex : mProdTexForPipe) to mConsTex. + bool mPipeActive; // Pipe is complete and in use for production. SharedSurface_EGLImage(GLContext* gl, GLLibraryEGL* egl, const gfx::IntSize& size, bool hasAlpha, const GLFormats& formats, - GLuint prodTex, - EGLImage image); + GLuint prodTex); EGLDisplay Display() const; @@ -61,7 +65,7 @@ protected: public: virtual ~SharedSurface_EGLImage(); - virtual void LockProdImpl() {} + virtual void LockProdImpl(); virtual void UnlockProdImpl() {} @@ -74,8 +78,11 @@ public: } // Implementation-specific functions below: - // Returns texture and target - void AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target); + // Returns 0 if the pipe isn't ready. If 0, use GetPixels below. + GLuint AcquireConsumerTexture(GLContext* consGL); + + // Will be void if AcquireConsumerTexture returns non-zero. + gfx::DataSourceSurface* GetPixels() const; }; diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index 1d3faa2735b..a227405921a 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -515,10 +515,15 @@ StreamTextureSourceOGL::RetrieveTextureFromStream() SharedSurface_EGLImage* eglImageSurf = SharedSurface_EGLImage::Cast(sharedSurf); - eglImageSurf->AcquireConsumerTexture(gl(), &mTextureHandle, &mTextureTarget); - MOZ_ASSERT(mTextureHandle); - mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8 - : SurfaceFormat::R8G8B8X8; + mTextureHandle = eglImageSurf->AcquireConsumerTexture(gl()); + mTextureTarget = eglImageSurf->TextureTarget(); + if (!mTextureHandle) { + toUpload = eglImageSurf->GetPixels(); + MOZ_ASSERT(toUpload); + } else { + mFormat = sharedSurf->HasAlpha() ? SurfaceFormat::R8G8B8A8 + : SurfaceFormat::R8G8B8X8; + } break; } #ifdef XP_MACOSX