From ff11ba4baf93260883c56a3857990bc7885e9d03 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Tue, 21 Oct 2014 08:53:02 -0500 Subject: [PATCH] Bug 1014614 - Add GLBlitHelper::BlitImageToFramebuffer and support SurfaceTexture images r=jgilbert --HG-- extra : rebase_source : e823897f3ff6593af7286432903618dc483877dd --- gfx/gl/GLBlitHelper.cpp | 143 +++++++++++++++++++++++++++++++--------- gfx/gl/GLBlitHelper.h | 10 +++ 2 files changed, 122 insertions(+), 31 deletions(-) diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp index a49fad64606..7e47f0b2d75 100644 --- a/gfx/gl/GLBlitHelper.cpp +++ b/gfx/gl/GLBlitHelper.cpp @@ -10,12 +10,18 @@ #include "mozilla/Preferences.h" #include "ImageContainer.h" #include "HeapCopyOfStackArray.h" +#include "mozilla/gfx/Matrix.h" #ifdef MOZ_WIDGET_GONK #include "GrallocImages.h" #include "GLLibraryEGL.h" #endif +#ifdef MOZ_WIDGET_ANDROID +#include "AndroidSurfaceTexture.h" +#include "GLImages.h" +#endif + using mozilla::layers::PlanarYCbCrImage; using mozilla::layers::PlanarYCbCrData; @@ -144,6 +150,7 @@ GLBlitHelper::GLBlitHelper(GLContext* gl) , mTex2DBlit_Program(0) , mTex2DRectBlit_Program(0) , mYFlipLoc(-1) + , mTextureTransformLoc(-1) , mTexExternalBlit_FragShader(0) , mTexYUVPlanarBlit_FragShader(0) , mTexExternalBlit_Program(0) @@ -238,21 +245,23 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) vTexCoord * uTexCoordMult); \n\ } \n\ "; -#ifdef MOZ_WIDGET_GONK +#ifdef ANDROID /* MOZ_WIDGET_ANDROID || MOZ_WIDGET_GONK */ const char kTexExternalBlit_FragShaderSource[] = "\ - #extension GL_OES_EGL_image_external : require \n\ - #ifdef GL_FRAGMENT_PRECISION_HIGH \n\ - precision highp float; \n\ - #else \n\ - precision mediump float; \n\ - #endif \n\ - varying vec2 vTexCoord; \n\ - uniform samplerExternalOES uTexUnit; \n\ - \n\ - void main() \n\ - { \n\ - gl_FragColor = texture2D(uTexUnit, vTexCoord); \n\ - } \n\ + #extension GL_OES_EGL_image_external : require \n\ + #ifdef GL_FRAGMENT_PRECISION_HIGH \n\ + precision highp float; \n\ + #else \n\ + precision mediump float; \n\ + #endif \n\ + varying vec2 vTexCoord; \n\ + uniform mat4 uTextureTransform; \n\ + uniform samplerExternalOES uTexUnit; \n\ + \n\ + void main() \n\ + { \n\ + gl_FragColor = texture2D(uTexUnit, \n\ + (uTextureTransform * vec4(vTexCoord, 0.0, 1.0)).xy); \n\ + } \n\ "; #endif /* From Rec601: @@ -306,7 +315,8 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) fragShaderPtr = &mTex2DRectBlit_FragShader; fragShaderSource = kTex2DRectBlit_FragShaderSource; break; -#ifdef MOZ_WIDGET_GONK +#ifdef ANDROID + case ConvertSurfaceTexture: case ConvertGralloc: programPtr = &mTexExternalBlit_Program; fragShaderPtr = &mTexExternalBlit_FragShader; @@ -441,8 +451,9 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) switch (target) { case BlitTex2D: case BlitTexRect: + case ConvertSurfaceTexture: case ConvertGralloc: { -#ifdef MOZ_WIDGET_GONK +#ifdef ANDROID GLint texUnitLoc = mGL->fGetUniformLocation(program, "uTexUnit"); MOZ_ASSERT(texUnitLoc != -1, "uniform uTexUnit not found"); mGL->fUniform1i(texUnitLoc, 0); @@ -472,6 +483,12 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0); mYFlipLoc = mGL->fGetUniformLocation(program, "uYflip"); MOZ_ASSERT(mYFlipLoc != -1, "uniform: uYflip not found"); + mTextureTransformLoc = mGL->fGetUniformLocation(program, "uTextureTransform"); + if (mTextureTransformLoc >= 0) { + // Set identity matrix as default + gfx::Matrix4x4 identity; + mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &identity._11); + } success = true; } while (false); @@ -700,6 +717,42 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) } #endif +#ifdef MOZ_WIDGET_ANDROID + +bool +GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage) +{ + AndroidSurfaceTexture* surfaceTexture = stImage->GetData()->mSurfTex; + bool yFlip = stImage->GetData()->mInverted; + + ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); + mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT); + + if (!surfaceTexture->Attach(mGL)) { + return false; + } + + // UpdateTexImage() changes the EXTERNAL binding, so save it here + // so we can restore it after. + int oldBinding = 0; + mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldBinding); + + surfaceTexture->UpdateTexImage(); + + gfx::Matrix4x4 transform; + surfaceTexture->GetTransformMatrix(transform); + + mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &transform._11); + mGL->fUniform1f(mYFlipLoc, yFlip ? 1.0f : 0.0f); + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + + surfaceTexture->Detach(); + + mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, oldBinding); + return true; +} +#endif + bool GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip) { @@ -738,15 +791,14 @@ GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFli } bool -GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, - const gfx::IntSize& destSize, - GLuint destTex, - GLenum destTarget, - bool yFlip, - GLuint xoffset, - GLuint yoffset, - GLuint cropWidth, - GLuint cropHeight) +GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage, + const gfx::IntSize& destSize, + GLuint destFB, + bool yFlip, + GLuint xoffset, + GLuint yoffset, + GLuint cropWidth, + GLuint cropHeight) { ScopedGLDrawState autoStates(mGL); @@ -759,6 +811,11 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, #ifdef MOZ_WIDGET_GONK type = ConvertGralloc; break; +#endif +#ifdef MOZ_WIDGET_ANDROID + case ImageFormat::SURFACE_TEXTURE: + type = ConvertSurfaceTexture; + break; #endif default: return false; @@ -769,12 +826,7 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, return false; } - if (!mFBO) { - mGL->fGenFramebuffers(1, &mFBO); - } - - ScopedBindFramebuffer boundFB(mGL, mFBO); - mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, destTarget, destTex, 0); + ScopedBindFramebuffer boundFB(mGL, destFB); mGL->fColorMask(LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE); mGL->fViewport(0, 0, destSize.width, destSize.height); if (xoffset != 0 && yoffset != 0 && cropWidth != 0 && cropHeight != 0) { @@ -793,10 +845,39 @@ GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, PlanarYCbCrImage* yuvImage = static_cast(srcImage); return BlitPlanarYCbCrImage(yuvImage, yFlip); } +#ifdef MOZ_WIDGET_ANDROID + if (type == ConvertSurfaceTexture) { + layers::SurfaceTextureImage* stImage = static_cast(srcImage); + return BlitSurfaceTextureImage(stImage); + } +#endif return false; } +bool +GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, + const gfx::IntSize& destSize, + GLuint destTex, + GLenum destTarget, + bool yFlip, + GLuint xoffset, + GLuint yoffset, + GLuint cropWidth, + GLuint cropHeight) +{ + ScopedGLDrawState autoStates(mGL); + + if (!mFBO) { + mGL->fGenFramebuffers(1, &mFBO); + } + + ScopedBindFramebuffer boundFB(mGL, mFBO); + mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, destTarget, destTex, 0); + return BlitImageToFramebuffer(srcImage, destSize, mFBO, yFlip, xoffset, yoffset, + cropWidth, cropHeight); +} + void GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB, const gfx::IntSize& srcSize, diff --git a/gfx/gl/GLBlitHelper.h b/gfx/gl/GLBlitHelper.h index b989d84475e..a5e42acad23 100644 --- a/gfx/gl/GLBlitHelper.h +++ b/gfx/gl/GLBlitHelper.h @@ -19,6 +19,7 @@ namespace layers { class Image; class PlanarYCbCrImage; class GrallocImage; +class SurfaceTextureImage; } namespace gl { @@ -97,6 +98,7 @@ class GLBlitHelper MOZ_FINAL BlitTexRect, ConvertGralloc, ConvertPlanarYCbCr, + ConvertSurfaceTexture }; // The GLContext is the sole owner of the GLBlitHelper. GLContext* mGL; @@ -110,6 +112,8 @@ class GLBlitHelper MOZ_FINAL GLint mYFlipLoc; + GLint mTextureTransformLoc; + // Data for image blit path GLuint mTexExternalBlit_FragShader; GLuint mTexYUVPlanarBlit_FragShader; @@ -142,6 +146,9 @@ class GLBlitHelper MOZ_FINAL bool BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip = false); #endif bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip = false); +#ifdef MOZ_WIDGET_ANDROID + bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage); +#endif public: @@ -175,6 +182,9 @@ public: const gfx::IntSize& destSize, GLenum srcTarget = LOCAL_GL_TEXTURE_2D, GLenum destTarget = LOCAL_GL_TEXTURE_2D); + bool BlitImageToFramebuffer(layers::Image* srcImage, const gfx::IntSize& destSize, + GLuint destFB, bool yFlip = false, GLuint xoffset = 0, + GLuint yoffset = 0, GLuint width = 0, GLuint height = 0); bool BlitImageToTexture(layers::Image* srcImage, const gfx::IntSize& destSize, GLuint destTex, GLenum destTarget, bool yFlip = false, GLuint xoffset = 0, GLuint yoffset = 0, GLuint width = 0, GLuint height = 0);