Bug 1395497 - Add AndroidSurfaceTexture support to GLBlitHelper. - r=snorp draft
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 29 Sep 2017 14:06:35 -0700
changeset 674937 6e884353d16e0f7ddfb43b70a59aa5ba16848b11
parent 674936 eaf08f6eed2942e3a16f23e3b14b57627eb03dc7
child 734458 d4a7994d3fb37d2e88c62f3a6240aaa82e92299d
push id82975
push userbmo:snorp@snorp.net
push dateWed, 04 Oct 2017 15:19:09 +0000
reviewerssnorp
bugs1395497
milestone58.0a1
Bug 1395497 - Add AndroidSurfaceTexture support to GLBlitHelper. - r=snorp MozReview-Commit-ID: JttqOoDCE4O
gfx/gl/AndroidSurfaceTexture.cpp
gfx/gl/AndroidSurfaceTexture.h
gfx/gl/GLBlitHelper.cpp
gfx/layers/opengl/TextureHostOGL.cpp
--- a/gfx/gl/AndroidSurfaceTexture.cpp
+++ b/gfx/gl/AndroidSurfaceTexture.cpp
@@ -3,44 +3,26 @@
 #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];
-
-  aMatrix._21 = array[4];
-  aMatrix._22 = array[5];
-  aMatrix._23 = array[6];
-  aMatrix._24 = array[7];
-
-  aMatrix._31 = array[8];
-  aMatrix._32 = array[9];
-  aMatrix._33 = array[10];
-  aMatrix._34 = array[11];
-
-  aMatrix._41 = array[12];
-  aMatrix._42 = array[13];
-  aMatrix._43 = array[14];
-  aMatrix._44 = array[15];
+  memcpy(&(outMatrix->_11), array, sizeof(float)*16);
 
   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,17 +52,21 @@ 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_RGBA = "\
     VARYING vec2 vTexCoord0;                                                 \n\
     uniform SAMPLER uTex0;                                                   \n\
                                                                              \n\
     void main(void)                                                          \n\
     {                                                                        \n\
@@ -710,24 +715,81 @@ 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();
+    const auto& surfaceTexture = java::GeckoSurfaceTexture::Lookup(handle);
+
+    if (!surfaceTexture) {
+        return false;
+    }
+
+    const 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;
+        }
+    }
+
+    const ScopedBindTexture savedTex(mGL, surfaceTexture->GetTexName(), LOCAL_GL_TEXTURE_EXTERNAL);
+    surfaceTexture->UpdateTexImage();
+
+    gfx::Matrix4x4 transform4;
+    AndroidSurfaceTexture::GetTransformMatrix(java::sdk::SurfaceTexture::Ref::From(surfaceTexture),
+                                              &transform4);
+    Mat3 transform3;
+    transform3.at(0,0) = transform4._11;
+    transform3.at(0,1) = transform4._12;
+    transform3.at(0,2) = transform4._14;
+    transform3.at(1,0) = transform4._21;
+    transform3.at(1,1) = transform4._22;
+    transform3.at(1,2) = transform4._24;
+    transform3.at(2,0) = transform4._41;
+    transform3.at(2,1) = transform4._42;
+    transform3.at(2,2) = transform4._44;
+
+    // We don't do w-divison, so if these aren't what we expect, we're probably doing
+    // something wrong.
+    MOZ_ASSERT(transform3.at(0,2) == 0);
+    MOZ_ASSERT(transform3.at(1,2) == 0);
+    MOZ_ASSERT(transform3.at(2,2) == 1);
+
+    const OriginPos srcOrigin = srcImage->GetOriginPos();
+
+    // I honestly have no idea why this logic is flipped, but changing the
+    // source origin would mean we'd have to flip it in the compositor
+    // which makes just as little sense as this.
+    const bool yFlip = (srcOrigin == destOrigin);
+
+    const auto& prog = GetDrawBlitProg({kFragHeader_TexExt, kFragBody_RGBA});
+    MOZ_RELEASE_ASSERT(prog);
+
+    // There is no padding on these images, so we can use the GetTransformMatrix directly.
+    const DrawBlitProg::BaseArgs baseArgs = { transform3, yFlip, destSize, Nothing() };
+    prog->Draw(baseArgs, nullptr);
+
+    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/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;