Bug 1167799 - Part 2: Add EGL_ANDROID_image_crop support. r=nical, r=jgilbert, a=jocheng
☠☠ backed out by 4cff5605633b ☠ ☠
authorSotaro Ikeda <sikeda@mozilla.com>
Thu, 23 Jul 2015 07:25:00 -0400
changeset 238731 0ba9636b385462b27748d50ce01432e95b83b1e0
parent 238730 5981fda08dea3c5c1d8e69d208cd4b90b734cca5
child 238732 4cff5605633b00ecc0ff84334badcad4e9d76240
push id750
push userryanvm@gmail.com
push dateThu, 23 Jul 2015 20:26:36 +0000
treeherdermozilla-b2g37_v2_2@0ba9636b3854 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical, jgilbert, jocheng
bugs1167799
milestone37.0
Bug 1167799 - Part 2: Add EGL_ANDROID_image_crop support. r=nical, r=jgilbert, a=jocheng
gfx/gl/GLDefs.h
gfx/gl/GLLibraryEGL.cpp
gfx/gl/GLLibraryEGL.h
gfx/layers/client/ImageClient.cpp
gfx/layers/composite/ImageHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/opengl/EGLImageHelpers.cpp
gfx/layers/opengl/EGLImageHelpers.h
gfx/layers/opengl/GrallocTextureHost.cpp
gfx/layers/opengl/GrallocTextureHost.h
--- a/gfx/gl/GLDefs.h
+++ b/gfx/gl/GLDefs.h
@@ -39,16 +39,22 @@
 // EGL_KHR_image_base (not supplied by EGL_KHR_image!)
 #define LOCAL_EGL_IMAGE_PRESERVED                       0x30D2
 
 // AMD_compressed_ATC_texture
 #define LOCAL_GL_ATC_RGB                                0x8C92
 #define LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA                0x8C93
 #define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA            0x87EE
 
+// EGL_ANDROID_image_crop
+#define LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID               0x3148
+#define LOCAL_EGL_IMAGE_CROP_TOP_ANDROID                0x3149
+#define LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID              0x314A
+#define LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID             0x314B
+
 // Others
 #define LOCAL_EGL_PRESERVED_RESOURCES                   0x3030
 #define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
 
 #define LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
 #define LOCAL_GL_CONTEXT_LOST                           0x9242
 #define LOCAL_GL_CONTEXT_FLAGS_ARB                      0x2094
 #define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT_ARB           0x00000001
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -31,16 +31,17 @@ static const char *sEGLExtensionNames[] 
     "EGL_KHR_image_pixmap",
     "EGL_KHR_gl_texture_2D_image",
     "EGL_KHR_lock_surface",
     "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
     "EGL_EXT_create_context_robustness",
     "EGL_KHR_image",
     "EGL_KHR_fence_sync",
     "EGL_ANDROID_native_fence_sync",
+    "EGL_ANDROID_image_crop",
     nullptr
 };
 
 #if defined(ANDROID)
 
 static PRLibrary* LoadApitraceLibrary()
 {
     if (!gfxPrefs::UseApitrace()) {
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -125,16 +125,17 @@ public:
         KHR_image_pixmap,
         KHR_gl_texture_2D_image,
         KHR_lock_surface,
         ANGLE_surface_d3d_texture_2d_share_handle,
         EXT_create_context_robustness,
         KHR_image,
         KHR_fence_sync,
         ANDROID_native_fence_sync,
+        EGL_ANDROID_image_crop,
         Extensions_Max
     };
 
     bool IsExtensionSupported(EGLExtensions aKnownExtension) const {
         return mAvailableExtensions[aKnownExtension];
     }
 
     void MarkExtensionUnsupported(EGLExtensions aKnownExtension) {
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -237,21 +237,20 @@ ImageClientSingle::UpdateImage(ImageCont
       texture->Unlock();
     }
   }
   if (!texture || !AddTextureClient(texture)) {
     return false;
   }
 
   mFrontBuffer = texture;
+  UpdatePictureRect(image->GetPictureRect());
   GetForwarder()->UpdatedTexture(this, texture, nullptr);
   GetForwarder()->UseTexture(this, texture);
 
-  UpdatePictureRect(image->GetPictureRect());
-
   mLastPaintedImageSerial = image->GetSerial();
   aContainer->NotifyPaintedImage(image);
 
   texture->SyncWithObject(GetForwarder()->GetSyncObject());
 
   return true;
 }
 
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -38,16 +38,19 @@ ImageHost::~ImageHost()
 }
 
 void
 ImageHost::UseTextureHost(TextureHost* aTexture)
 {
   CompositableHost::UseTextureHost(aTexture);
   mFrontBuffer = aTexture;
   if (mFrontBuffer) {
+    // SetCropRect() affects only on a specific platform.
+    // If it is not implemented, it does nothing.
+    mFrontBuffer->SetCropRect(mPictureRect);
     mFrontBuffer->PrepareTextureSource(mTextureSource);
   }
 }
 
 void
 ImageHost::RemoveTextureHost(TextureHost* aTexture)
 {
   CompositableHost::RemoveTextureHost(aTexture);
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -444,16 +444,21 @@ public:
    *
    * This is important to ensure the correctness of the deallocation protocol.
    */
   virtual void ForgetSharedData() {}
 
   virtual gfx::IntSize GetSize() const = 0;
 
   /**
+   * Should be overridden if TextureHost supports crop rect.
+   */
+  virtual void SetCropRect(nsIntRect aCropRect) {}
+
+  /**
    * Debug facility.
    * XXX - cool kids use Moz2D. See bug 882113.
    */
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() = 0;
 
   /**
    * XXX - Flags should only be set at creation time, this will be removed.
    */
--- a/gfx/layers/opengl/EGLImageHelpers.cpp
+++ b/gfx/layers/opengl/EGLImageHelpers.cpp
@@ -10,27 +10,42 @@
 
 namespace mozilla
 {
 namespace layers {
 
 using namespace gl;
 
 EGLImage
-EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer)
+EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize)
 {
     EGLint attrs[] = {
         LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
-        LOCAL_EGL_NONE, LOCAL_EGL_NONE
+        LOCAL_EGL_NONE, LOCAL_EGL_NONE,
     };
 
+    EGLint cropAttrs[] = {
+        LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
+        LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID, 0,
+        LOCAL_EGL_IMAGE_CROP_TOP_ANDROID, 0,
+        LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID, aCropSize.width,
+        LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID, aCropSize.height,
+        LOCAL_EGL_NONE, LOCAL_EGL_NONE,
+    };
+
+    bool hasCropRect = (aCropSize.width != 0 && aCropSize.height != 0);
+    EGLint* usedAttrs = attrs;
+    if (hasCropRect && sEGLLibrary.IsExtensionSupported(GLLibraryEGL::EGL_ANDROID_image_crop)) {
+        usedAttrs = cropAttrs;
+    }
+
     return sEGLLibrary.fCreateImage(sEGLLibrary.Display(),
                                      EGL_NO_CONTEXT,
                                      LOCAL_EGL_NATIVE_BUFFER_ANDROID,
-                                     aBuffer, attrs);
+                                     aBuffer, usedAttrs);
 }
 
 void
 EGLImageDestroy(GLContext* aGL, EGLImage aImage)
 {
     sEGLLibrary.fDestroyImage(sEGLLibrary.Display(), aImage);
 }
 
--- a/gfx/layers/opengl/EGLImageHelpers.h
+++ b/gfx/layers/opengl/EGLImageHelpers.h
@@ -2,24 +2,26 @@
 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef EGLIMAGEHELPERS_H_
 #define EGLIMAGEHELPERS_H_
 
+#include "mozilla/gfx/Point.h"
+
 typedef void* EGLImage;
 
 namespace mozilla {
 namespace gl {
     class GLContext;
 }
 
 namespace layers {
 
-EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer);
+EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize);
 void EGLImageDestroy(gl::GLContext* aGL, EGLImage aImage);
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // EGLIMAGEHELPERS_H_
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -343,18 +343,22 @@ GrallocTextureHostOGL::PrepareTextureSou
 
   gl::GLContext* gl = GetGLContext();
   if (!gl || !gl->MakeCurrent()) {
     mGLTextureSource = nullptr;
     return;
   }
 
   if (mEGLImage == EGL_NO_IMAGE) {
+    gfx::IntSize cropSize(0, 0);
+    if (mCropSize != mSize) {
+      cropSize = mCropSize;
+    }
     // Should only happen the first time.
-    mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer());
+    mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer(), cropSize);
   }
 
   GLenum textureTarget = GetTextureTarget(gl, graphicBuffer->getPixelFormat());
 
   GLTextureSource* glSource = aTextureSource.get() ?
     aTextureSource->AsSourceOGL()->AsGLTextureSource() : nullptr;
 
   bool shouldCreateTextureSource = !glSource  || !glSource->IsValid()
@@ -377,16 +381,33 @@ GrallocTextureHostOGL::PrepareTextureSou
 
     gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
     glSource->SetSize(mSize);
     glSource->SetFormat(mFormat);
     mGLTextureSource = glSource;
   }
 }
 
+void
+GrallocTextureHostOGL::SetCropRect(nsIntRect aCropRect)
+{
+  MOZ_ASSERT(aCropRect.TopLeft() == nsIntPoint(0, 0));
+  MOZ_ASSERT(!aCropRect.IsEmpty());
+  MOZ_ASSERT(aCropRect.width <= mSize.width);
+  MOZ_ASSERT(aCropRect.height <= mSize.height);
+
+  gfx::IntSize cropSize(aCropRect.width, aCropRect.height);
+  if (mCropSize == cropSize) {
+    return;
+  }
+
+  mCropSize = cropSize;
+  mGLTextureSource = nullptr;
+}
+
 bool
 GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureSource)
 {
   // This happens at composition time.
 
   // If mGLTextureSource is null it means PrepareTextureSource failed.
   if (!mGLTextureSource) {
     return false;
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -59,16 +59,18 @@ public:
   virtual TextureHostOGL* AsHostOGL() MOZ_OVERRIDE
   {
     return this;
   }
 #endif
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
 
+  virtual void SetCropRect(nsIntRect aCropRect) MOZ_OVERRIDE;
+
   bool IsValid() const;
 
   virtual const char* Name() MOZ_OVERRIDE { return "GrallocTextureHostOGL"; }
 
   gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; }
 
 private:
   void DestroyEGLImage();