Bug 1395497 - Add SurfaceTexture impl in GLBlitHelper r=jgilbert draft
authorJames Willcox <snorp@snorp.net>
Wed, 27 Sep 2017 18:14:53 -0500
changeset 672660 e1deac0b9b0fa4619901f6f8b3479f83fed94a84
parent 672659 005f7929279f81615895ba7886826926bb1dda14
child 672661 debdf331ef325438a79cfd42ffa5d34e0247e25b
push id82325
push userbmo:snorp@snorp.net
push dateFri, 29 Sep 2017 15:30:39 +0000
reviewersjgilbert
bugs1395497
milestone58.0a1
Bug 1395497 - Add SurfaceTexture impl in GLBlitHelper r=jgilbert MozReview-Commit-ID: GnagMHoXk5b
gfx/gl/AndroidSurfaceTexture.cpp
gfx/gl/AndroidSurfaceTexture.h
gfx/gl/GLBlitHelper.cpp
gfx/gl/GLBlitHelper.h
gfx/layers/opengl/TextureHostOGL.cpp
--- a/gfx/gl/AndroidSurfaceTexture.cpp
+++ b/gfx/gl/AndroidSurfaceTexture.cpp
@@ -3,44 +3,44 @@
 #include "AndroidSurfaceTexture.h"
 
 using namespace mozilla;
 
 namespace mozilla {
 namespace gl {
 
 void
-AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
-                                          gfx::Matrix4x4& aMatrix)
+AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::Param surfaceTexture,
+                                          gfx::Matrix4x4* outMatrix)
 {
   JNIEnv* const env = jni::GetEnvForThread();
 
   auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
-  aSurfaceTexture->GetTransformMatrix(jarray);
+  surfaceTexture->GetTransformMatrix(jarray);
 
   jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
 
-  aMatrix._11 = array[0];
-  aMatrix._12 = array[1];
-  aMatrix._13 = array[2];
-  aMatrix._14 = array[3];
+  outMatrix->_11 = array[0];
+  outMatrix->_12 = array[1];
+  outMatrix->_13 = array[2];
+  outMatrix->_14 = array[3];
 
-  aMatrix._21 = array[4];
-  aMatrix._22 = array[5];
-  aMatrix._23 = array[6];
-  aMatrix._24 = array[7];
+  outMatrix->_21 = array[4];
+  outMatrix->_22 = array[5];
+  outMatrix->_23 = array[6];
+  outMatrix->_24 = array[7];
 
-  aMatrix._31 = array[8];
-  aMatrix._32 = array[9];
-  aMatrix._33 = array[10];
-  aMatrix._34 = array[11];
+  outMatrix->_31 = array[8];
+  outMatrix->_32 = array[9];
+  outMatrix->_33 = array[10];
+  outMatrix->_34 = array[11];
 
-  aMatrix._41 = array[12];
-  aMatrix._42 = array[13];
-  aMatrix._43 = array[14];
-  aMatrix._44 = array[15];
+  outMatrix->_41 = array[12];
+  outMatrix->_42 = array[13];
+  outMatrix->_43 = array[14];
+  outMatrix->_44 = array[15];
 
   env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
 }
 
 } // gl
 } // mozilla
 #endif // MOZ_WIDGET_ANDROID
--- a/gfx/gl/AndroidSurfaceTexture.h
+++ b/gfx/gl/AndroidSurfaceTexture.h
@@ -13,18 +13,18 @@
 
 typedef uint32_t AndroidSurfaceTextureHandle;
 
 namespace mozilla {
 namespace gl {
 
 class AndroidSurfaceTexture {
 public:
-  static void GetTransformMatrix(java::sdk::SurfaceTexture::LocalRef aSurfaceTexture,
-                                 mozilla::gfx::Matrix4x4& aMatrix);
+  static void GetTransformMatrix(java::sdk::SurfaceTexture::Param surfaceTexture,
+                                 mozilla::gfx::Matrix4x4* outMatrix);
 
 };
 
 } // gl
 } // mozilla
 
 #endif // MOZ_WIDGET_ANDROID
 #endif // AndroidSurfaceTexture_h__
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -14,16 +14,17 @@
 #include "HeapCopyOfStackArray.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/gfx/Matrix.h"
 #include "mozilla/UniquePtr.h"
 #include "GPUVideoImage.h"
 
 #ifdef MOZ_WIDGET_ANDROID
+#include "GeneratedJNIWrappers.h"
 #include "AndroidSurfaceTexture.h"
 #include "GLImages.h"
 #include "GLLibraryEGL.h"
 #endif
 
 #ifdef XP_MACOSX
 #include "MacIOSurfaceImage.h"
 #include "GLContextCGL.h"
@@ -51,19 +52,34 @@ const char* const kFragHeader_Tex2DRect 
         #define TEXTURE texture                                              \n\
     #else                                                                    \n\
         #define TEXTURE texture2DRect                                        \n\
     #endif                                                                   \n\
 ";
 const char* const kFragHeader_TexExt = "\
     #extension GL_OES_EGL_image_external : require                           \n\
     #define SAMPLER samplerExternalOES                                       \n\
-    #define TEXTURE texture2D                                                \n\
+    #if __VERSION__ >= 130                                                   \n\
+        #define TEXTURE texture                                              \n\
+    #else                                                                    \n\
+        #define TEXTURE texture2D                                            \n\
+    #endif                                                                   \n\
 ";
 
+const char* const kFragBody_RGBATransform = "\
+    VARYING vec2 vTexCoord0;                                                 \n\
+    uniform SAMPLER uTex0;                                                   \n\
+    uniform mat4 uTexTransform;                                              \n\
+                                                                             \n\
+    void main(void)                                                          \n\
+    {                                                                        \n\
+        FRAG_COLOR = TEXTURE(uTex0,                                          \n\
+            (uTexTransform * vec4(vTexCoord0, 0.0, 1.0)).xy);                \n\
+    }                                                                        \n\
+";
 const char* const kFragBody_RGBA = "\
     VARYING vec2 vTexCoord0;                                                 \n\
     uniform SAMPLER uTex0;                                                   \n\
                                                                              \n\
     void main(void)                                                          \n\
     {                                                                        \n\
         FRAG_COLOR = TEXTURE(uTex0, vTexCoord0);                             \n\
     }                                                                        \n\
@@ -295,16 +311,17 @@ DrawBlitProg::DrawBlitProg(const GLBlitH
     : mParent(*parent)
     , mProg(prog)
     , mLoc_u1ForYFlip(mParent.mGL->fGetUniformLocation(mProg, "u1ForYFlip"))
     , mLoc_uSrcRect(mParent.mGL->fGetUniformLocation(mProg, "uSrcRect"))
     , mLoc_uTexSize0(mParent.mGL->fGetUniformLocation(mProg, "uTexSize0"))
     , mLoc_uTexSize1(mParent.mGL->fGetUniformLocation(mProg, "uTexSize1"))
     , mLoc_uDivisors(mParent.mGL->fGetUniformLocation(mProg, "uDivisors"))
     , mLoc_uColorMatrix(mParent.mGL->fGetUniformLocation(mProg, "uColorMatrix"))
+    , mLoc_uTexTransform(mParent.mGL->fGetUniformLocation(mProg, "uTexTransform"))
 {
     MOZ_ASSERT(mLoc_u1ForYFlip != -1);
     MOZ_ASSERT(mLoc_uSrcRect != -1);
     MOZ_ASSERT(mLoc_uTexSize0 != -1);
     if (mLoc_uColorMatrix != -1) {
         MOZ_ASSERT(mLoc_uTexSize1 != -1);
         MOZ_ASSERT(mLoc_uDivisors != -1);
     }
@@ -315,17 +332,18 @@ DrawBlitProg::~DrawBlitProg()
     const auto& gl = mParent.mGL;
     if (!gl->MakeCurrent())
         return;
 
     gl->fDeleteProgram(mProg);
 }
 
 void
-DrawBlitProg::Draw(const BaseArgs& args, const YUVArgs* const argsYUV) const
+DrawBlitProg::Draw(const BaseArgs& args, const YUVArgs* const argsYUV,
+                   const TexTransformArgs* const argsTexTransform) const
 {
     const auto& gl = mParent.mGL;
 
     const SaveRestoreCurrentProgram oldProg(gl);
     gl->fUseProgram(mProg);
 
     // --
 
@@ -338,16 +356,21 @@ DrawBlitProg::Draw(const BaseArgs& args,
     MOZ_ASSERT(bool(argsYUV) == (mLoc_uColorMatrix != -1));
     if (argsYUV) {
         gl->fUniform2f(mLoc_uTexSize1, argsYUV->texSize1.width, argsYUV->texSize1.height);
         gl->fUniform2f(mLoc_uDivisors, argsYUV->divisors.width, argsYUV->divisors.height);
         const auto& colorMatrix = gfxUtils::YuvToRgbMatrix4x4ColumnMajor(argsYUV->colorSpace);
         gl->fUniformMatrix4fv(mLoc_uColorMatrix, 1, false, colorMatrix);
     }
 
+    MOZ_ASSERT(bool(argsTexTransform) == (mLoc_uTexTransform != -1));
+    if (argsTexTransform) {
+        gl->fUniformMatrix4fv(mLoc_uTexTransform, 1, false, &argsTexTransform->transform._11);
+    }
+
     // --
 
     const ScopedDrawBlitState drawState(gl, args.destSize);
 
     GLuint oldVAO;
     GLint vaa0Enabled;
     GLint vaa0Size;
     GLenum vaa0Type;
@@ -629,24 +652,58 @@ GLBlitHelper::BlitImageToFramebuffer(lay
         return false;
     }
 }
 
 // -------------------------------------
 
 #ifdef MOZ_WIDGET_ANDROID
 bool
-GLBlitHelper::BlitImage(layers::SurfaceTextureImage* srcImage, const gfx::IntSize&,
-                        const OriginPos) const
+GLBlitHelper::BlitImage(layers::SurfaceTextureImage* srcImage, const gfx::IntSize& destSize,
+                        const OriginPos destOrigin) const
 {
-    // FIXME
-    const auto& srcOrigin = srcImage->GetOriginPos();
-    (void)srcOrigin;
-    gfxCriticalError() << "BlitImage(SurfaceTextureImage) not implemented.";
-    return false;
+    AndroidSurfaceTextureHandle handle = srcImage->GetHandle();
+    auto surfaceTexture = java::GeckoSurfaceTexture::Lookup(handle);
+
+    if (!surfaceTexture) {
+        return false;
+    }
+
+    ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
+
+    if (!surfaceTexture->IsAttachedToGLContext((int64_t)mGL)) {
+        GLuint tex;
+        mGL->MakeCurrent();
+        mGL->fGenTextures(1, &tex);
+
+        if (NS_FAILED(surfaceTexture->AttachToGLContext((int64_t)mGL, tex))) {
+            mGL->fDeleteTextures(1, &tex);
+            return false;
+        }
+    }
+
+    ScopedBindTexture savedTex(mGL, 0, LOCAL_GL_TEXTURE_EXTERNAL);
+    surfaceTexture->UpdateTexImage();
+
+    gfx::Matrix4x4 transform;
+    AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::Ref::From(surfaceTexture), &transform);
+
+    const auto& prog = GetDrawBlitProg({kFragHeader_TexExt, kFragBody_RGBATransform});
+    MOZ_RELEASE_ASSERT(prog);
+
+    const gfx::IntRect clipRect({0, 0}, srcImage->GetSize());
+    const DrawBlitProg::BaseArgs baseArgs = { destSize, false, clipRect, srcImage->GetSize() };
+    const DrawBlitProg::TexTransformArgs TexTransformArgs = { transform };
+    prog->Draw(baseArgs, nullptr, &TexTransformArgs);
+
+    if (surfaceTexture->IsSingleBuffer()) {
+        surfaceTexture->ReleaseTexImage();
+    }
+
+    return true;
 }
 #endif
 
 // -------------------------------------
 
 bool
 GuessDivisors(const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
               gfx::IntSize* const out_divisors)
--- a/gfx/gl/GLBlitHelper.h
+++ b/gfx/gl/GLBlitHelper.h
@@ -7,16 +7,17 @@
 #ifndef GLBLITHELPER_H_
 #define GLBLITHELPER_H_
 
 #include "GLContextTypes.h"
 #include "GLConsts.h"
 #include "nsSize.h"
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/gfx/Matrix.h"
 #include "mozilla/gfx/Point.h"
 #include "../layers/ImageTypes.h"
 
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 
 namespace mozilla {
@@ -46,16 +47,17 @@ class DrawBlitProg final
     const GLBlitHelper& mParent;
     const GLuint mProg;
     const GLint mLoc_u1ForYFlip;
     const GLint mLoc_uSrcRect;
     const GLint mLoc_uTexSize0;
     const GLint mLoc_uTexSize1;
     const GLint mLoc_uDivisors;
     const GLint mLoc_uColorMatrix;
+    const GLint mLoc_uTexTransform;
 
 public:
     struct Key final {
         const char* fragHeader;
         const char* fragBody;
 
         bool operator <(const Key& x) const {
             if (fragHeader != x.fragHeader)
@@ -73,18 +75,22 @@ public:
         gfx::IntRect srcRect;
         gfx::IntSize texSize0;
     };
     struct YUVArgs final {
         gfx::IntSize texSize1;
         gfx::IntSize divisors;
         YUVColorSpace colorSpace;
     };
+    struct TexTransformArgs final {
+        gfx::Matrix4x4 transform;
+    };
 
-    void Draw(const BaseArgs& args, const YUVArgs* argsYUV = nullptr) const;
+    void Draw(const BaseArgs& args, const YUVArgs* argsYUV = nullptr,
+              const TexTransformArgs* argsTexTransform = nullptr) const;
 };
 
 class ScopedSaveMultiTex final
 {
     GLContext& mGL;
     const uint8_t mTexCount;
     const GLenum mTexTarget;
     const GLuint mOldTexUnit;
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -390,17 +390,17 @@ SurfaceTextureSource::IsValid() const
 gfx::Matrix4x4
 SurfaceTextureSource::GetTextureTransform()
 {
   MOZ_ASSERT(mSurfTex);
 
   gfx::Matrix4x4 ret;
 
   const auto& surf = java::sdk::SurfaceTexture::LocalRef(java::sdk::SurfaceTexture::Ref::From(mSurfTex));
-  AndroidSurfaceTexture::GetTransformMatrix(surf, ret);
+  AndroidSurfaceTexture::GetTransformMatrix(surf, &ret);
 
   return ret;
 }
 
 void
 SurfaceTextureSource::DeallocateDeviceData()
 {
   mSurfTex = nullptr;