Bug 870211 - Make TextureHosts support updating from partial surfaces. r=Bas
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 16 May 2013 15:45:43 +1200
changeset 132404 b37e2bd1c6b8ab86f0d7c9b1e75f8d9b3d4cc650
parent 132403 1989b670347b15f2d4b016205cb5ee66802ac91e
child 132405 a1bb5799f8eec0ca25567920fd83b289c9378b2e
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersBas
bugs870211
milestone24.0a1
Bug 870211 - Make TextureHosts support updating from partial surfaces. r=Bas
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/opengl/TextureHostOGL.cpp
gfx/layers/opengl/TextureHostOGL.h
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -29,17 +29,18 @@ public:
   {
     mCompositor = static_cast<BasicCompositor*>(aCompositor);
   }
 
   virtual const char *Name() { return "TextureSourceBasic"; }
 
 protected:
   virtual void UpdateImpl(const SurfaceDescriptor& aImage,
-                          nsIntRegion *aRegion) MOZ_OVERRIDE
+                          nsIntRegion *aRegion,
+                          nsIntPoint*) MOZ_OVERRIDE
   {
     AutoOpenSurface surf(OPEN_READ_ONLY, aImage);
     mFormat =
       (surf.ContentType() == gfxASurface::CONTENT_COLOR_ALPHA) ? FORMAT_B8G8R8A8 :
                                                                  FORMAT_B8G8R8X8;
     mThebesSurface = ShadowLayerForwarder::OpenDescriptor(OPEN_READ_ONLY, aImage);
     mThebesImage = mThebesSurface->GetAsImageSurface();
     MOZ_ASSERT(mThebesImage);
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -84,19 +84,20 @@ TextureHost::~TextureHost()
     }
     delete mBuffer;
   }
   MOZ_COUNT_DTOR(TextureHost);
 }
 
 void
 TextureHost::Update(const SurfaceDescriptor& aImage,
-                    nsIntRegion* aRegion)
+                    nsIntRegion* aRegion,
+                    nsIntPoint* aOffset)
 {
-  UpdateImpl(aImage, aRegion);
+  UpdateImpl(aImage, aRegion, aOffset);
 }
 
 void
 TextureHost::SwapTextures(const SurfaceDescriptor& aImage,
                           SurfaceDescriptor* aResult,
                           nsIntRegion* aRegion)
 {
   SwapTexturesImpl(aImage, aRegion);
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -169,19 +169,24 @@ public:
   virtual ~TextureHost();
 
   virtual gfx::SurfaceFormat GetFormat() const { return mFormat; }
 
   virtual bool IsValid() const { return true; }
 
   /**
    * Update the texture host using the data from aSurfaceDescriptor.
+   *
+   * @param aImage Source image to update with.
+   * @param aRegion Region of the texture host to update.
+   * @param aOffset Offset in the source to update from
    */
   void Update(const SurfaceDescriptor& aImage,
-              nsIntRegion *aRegion = nullptr);
+              nsIntRegion *aRegion = nullptr,
+              nsIntPoint* aOffset = nullptr);
 
   /**
    * Change the current surface of the texture host to aImage. aResult will return
    * the previous surface.
    */
   void SwapTextures(const SurfaceDescriptor& aImage,
                     SurfaceDescriptor* aResult = nullptr,
                     nsIntRegion *aRegion = nullptr);
@@ -242,18 +247,45 @@ public:
                             mFlags & NeedsYFlip ? LAYER_RENDER_STATE_Y_FLIPPED : 0);
   }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char *Name() = 0;
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 #endif
 
+  /**
+   * TEMPORARY.
+   *
+   * Ensure that a buffer of the given size/type has been allocated so that
+   * we can update it using Update and/or CopyTo.
+   */
+  virtual void EnsureBuffer(const nsIntSize& aSize, gfxASurface::gfxContentType aType)
+  {
+    NS_RUNTIMEABORT("TextureHost doesn't support EnsureBuffer");
+  }
+
+  /**
+   * Copy the contents of this TextureHost to aDest. aDest must already
+   * have a suitable buffer allocated using EnsureBuffer.
+   *
+   * @param aSourceRect Area of this texture host to copy.
+   * @param aDest Destination texture host.
+   * @param aDestRect Destination rect.
+   */
+  virtual void CopyTo(const nsIntRect& aSourceRect,
+                      TextureHost *aDest,
+                      const nsIntRect& aDestRect)
+  {
+    NS_RUNTIMEABORT("TextureHost doesn't support CopyTo");
+  }
+
 
   SurfaceDescriptor* GetBuffer() const { return mBuffer; }
+
   /**
    * Set a SurfaceDescriptor for this texture host. By setting a buffer and
    * allocator/de-allocator for the TextureHost, you cause the TextureHost to
    * retain a SurfaceDescriptor.
    * Ownership of the SurfaceDescriptor passes to this.
    */
   // only made virtual to allow overriding in GrallocTextureHostOGL, for hacky fix in gecko 23 for bug 862324.
   // see bug 865908 about fixing this.
@@ -271,34 +303,35 @@ public:
 protected:
   /**
    * Should be implemented by the backend-specific TextureHost classes
    *
    * It should not take a reference to aImage, unless it knows the data
    * to be thread-safe.
    */
   virtual void UpdateImpl(const SurfaceDescriptor& aImage,
-                          nsIntRegion *aRegion)
+                          nsIntRegion *aRegion,
+                          nsIntPoint *aOffset = nullptr)
   {
     NS_RUNTIMEABORT("Should not be reached");
   }
 
   /**
    * Should be implemented by the backend-specific TextureHost classes.
    *
    * Doesn't need to do the actual surface descriptor swap, just
    * any preparation work required to use the new descriptor.
    *
    * If the implementation doesn't define anything in particular
    * for handling swaps, then we can just do an update instead.
    */
   virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                 nsIntRegion *aRegion)
   {
-    UpdateImpl(aImage, aRegion);
+    UpdateImpl(aImage, aRegion, nullptr);
   }
 
   // An internal identifier for this texture host. Two texture hosts
   // should be considered equal iff their identifiers match. Should
   // not be exposed publicly.
   virtual uint64_t GetIdentifier() const
   {
     return reinterpret_cast<uint64_t>(this);
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -290,17 +290,19 @@ static uint32_t GetRequiredTiles(uint32_
 void
 TextureHostShmemD3D11::SetCompositor(Compositor* aCompositor)
 {
   CompositorD3D11 *d3dCompositor = static_cast<CompositorD3D11*>(aCompositor);
   mDevice = d3dCompositor ? d3dCompositor->GetDevice() : nullptr;
 }
 
 void
-TextureHostShmemD3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion *aRegion)
+TextureHostShmemD3D11::UpdateImpl(const SurfaceDescriptor& aImage,
+                                  nsIntRegion *aRegion,
+                                  nsIntPoint *aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TShmem);
 
   AutoOpenSurface openSurf(OPEN_READ_ONLY, aImage);
 
   nsRefPtr<gfxImageSurface> surf = openSurf.GetAsImage();
 
   gfxIntSize size = surf->GetSize();
@@ -399,17 +401,19 @@ TextureHostDXGID3D11::Lock()
 
 void
 TextureHostDXGID3D11::Unlock()
 {
   ReleaseTexture();
 }
 
 void
-TextureHostDXGID3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion *aRegion)
+TextureHostDXGID3D11::UpdateImpl(const SurfaceDescriptor& aImage,
+                                 nsIntRegion *aRegion,
+                                 nsIntPoint *aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TSurfaceDescriptorD3D10);
 
   mDevice->OpenSharedResource((HANDLE)aImage.get_SurfaceDescriptorD3D10().handle(),
                               __uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)byRef(mTextures[0]));
   mFormat = aImage.get_SurfaceDescriptorD3D10().hasAlpha() ? FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8;
 
   D3D11_TEXTURE2D_DESC desc;
@@ -445,17 +449,19 @@ TextureHostYCbCrD3D11::SetCompositor(Com
 
 IntSize
 TextureHostYCbCrD3D11::GetSize() const
 {
   return TextureSourceD3D11::GetSize();
 }
 
 void
-TextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion *aRegion)
+TextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage,
+                                  nsIntRegion *aRegion,
+                                  nsIntPoint *aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
 
   ShmemYCbCrImage shmemImage(aImage.get_YCbCrImage().data(),
                              aImage.get_YCbCrImage().offset());
 
   gfxIntSize gfxCbCrSize = shmemImage.GetCbCrSize();
 
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -139,17 +139,18 @@ public:
     return (++mCurrentTile < mTileTextures.size());
   }
 
   virtual TileIterator* AsTileIterator() MOZ_OVERRIDE {
     return mIsTiled ? this : nullptr;
   }
 protected:
   virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
-                          nsIntRegion* aRegion) MOZ_OVERRIDE;
+                          nsIntRegion* aRegion,
+                          nsIntPoint *aOffset = nullptr) MOZ_OVERRIDE;
 private:
 
   gfx::IntRect GetTileRect(uint32_t aID) const;
 
   RefPtr<ID3D11Device> mDevice;
   bool mIsTiled;
   std::vector< RefPtr<ID3D11Texture2D> > mTileTextures;
   uint32_t mCurrentTile;
@@ -175,17 +176,18 @@ public:
   virtual void Unlock() MOZ_OVERRIDE;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() { return "TextureHostDXGID3D11"; }
 #endif
 
 protected:
   virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
-                          nsIntRegion* aRegion) MOZ_OVERRIDE;
+                          nsIntRegion* aRegion,
+                          nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
 private:
   void LockTexture();
   void ReleaseTexture();
 
   gfx::IntRect GetTileRect(uint32_t aID) const; // TODO[Bas] not defined anywhere?
 
   RefPtr<ID3D11Device> mDevice;
 };
@@ -209,17 +211,18 @@ public:
   virtual bool IsYCbCrSource() const MOZ_OVERRIDE { return true; }
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() MOZ_OVERRIDE { return "TextureImageTextureHostD3D11"; }
 #endif
 
 protected:
   virtual void UpdateImpl(const SurfaceDescriptor& aSurface,
-                          nsIntRegion* aRegion) MOZ_OVERRIDE;
+                          nsIntRegion* aRegion,
+                          nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
 
 private:
   RefPtr<ID3D11Device> mDevice;
 };
 
 inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)
 {
   int32_t maxTextureSize;
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -155,44 +155,80 @@ TextureImageTextureHostOGL::SetComposito
     // go away.
     if (newGL && mBuffer && IsSurfaceDescriptorValid(*mBuffer)) {
       UpdateImpl(*mBuffer);
     }
   }
 }
 
 void
+TextureImageTextureHostOGL::EnsureBuffer(const nsIntSize& aSize,
+                                         gfxContentType aContentType)
+{
+  if (!mTexture ||
+      mTexture->GetSize() != aSize ||
+      mTexture->GetContentType() != aContentType) {
+    mTexture = mGL->CreateTextureImage(aSize,
+                                       aContentType,
+                                       WrapMode(mGL, mFlags & AllowRepeat),
+                                       FlagsToGLFlags(mFlags));
+  }
+  mTexture->Resize(aSize);
+}
+
+void
+TextureImageTextureHostOGL::CopyTo(const nsIntRect& aSourceRect,
+                                   TextureHost *aDest,
+                                   const nsIntRect& aDestRect)
+{
+  MOZ_ASSERT(aDest->AsSourceOGL(), "Incompatible destination type!");
+  TextureImageTextureHostOGL *dest =
+    aDest->AsSourceOGL()->AsTextureImageTextureHost();
+  MOZ_ASSERT(dest, "Incompatible destination type!");
+
+  mGL->BlitTextureImage(mTexture, aSourceRect,
+                        dest->mTexture, aDestRect);
+  dest->mTexture->MarkValid();
+}
+
+void
 TextureImageTextureHostOGL::UpdateImpl(const SurfaceDescriptor& aImage,
-                                       nsIntRegion* aRegion)
+                                       nsIntRegion* aRegion,
+                                       nsIntPoint* aOffset)
 {
   if (!mGL) {
     NS_WARNING("trying to update TextureImageTextureHostOGL without a compositor?");
     return;
   }
   AutoOpenSurface surf(OPEN_READ_ONLY, aImage);
   nsIntSize size = surf.Size();
 
   if (!mTexture ||
-      mTexture->GetSize() != size ||
+      (mTexture->GetSize() != size && !aOffset) ||
       mTexture->GetContentType() != surf.ContentType()) {
     mTexture = mGL->CreateTextureImage(size,
                                        surf.ContentType(),
                                        WrapMode(mGL, mFlags & AllowRepeat),
                                        FlagsToGLFlags(mFlags));
   }
 
   // XXX this is always just ridiculously slow
   nsIntRegion updateRegion;
 
   if (!aRegion) {
     updateRegion = nsIntRegion(nsIntRect(0, 0, size.width, size.height));
   } else {
     updateRegion = *aRegion;
   }
-  mTexture->DirectUpdate(surf.Get(), updateRegion);
+  nsIntPoint offset;
+  if (aOffset) {
+    offset = *aOffset;
+  }
+  mTexture->DirectUpdate(surf.Get(), updateRegion, offset);
+  mFormat = FormatFromShaderType(mTexture->GetShaderProgramType());
 
   if (mTexture->InUpdate()) {
     mTexture->EndUpdate();
   }
 }
 
 bool
 TextureImageTextureHostOGL::Lock()
@@ -232,17 +268,18 @@ SharedTextureHostOGL::DeleteTextures()
   if (mTextureHandle) {
     mGL->fDeleteTextures(1, &mTextureHandle);
     mTextureHandle = 0;
   }
 }
 
 void
 SharedTextureHostOGL::UpdateImpl(const SurfaceDescriptor& aImage,
-                                 nsIntRegion* aRegion)
+                                 nsIntRegion* aRegion,
+                                 nsIntPoint* aOffset)
 {
   SwapTexturesImpl(aImage, aRegion);
 }
 
 void
 SharedTextureHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                        nsIntRegion* aRegion)
 {
@@ -441,17 +478,18 @@ YCbCrTextureHostOGL::SetCompositor(Compo
     if (newGL && mBuffer && mBuffer->type() == SurfaceDescriptor::TYCbCrImage) {
       UpdateImpl(*mBuffer);
     }
   }
 }
 
 void
 YCbCrTextureHostOGL::UpdateImpl(const SurfaceDescriptor& aImage,
-                                nsIntRegion* aRegion)
+                                nsIntRegion* aRegion,
+                                nsIntPoint* aOffset)
 {
   if (!mGL) {
     return;
   }
   NS_ASSERTION(aImage.type() == SurfaceDescriptor::TYCbCrImage, "SurfaceDescriptor mismatch");
 
   ShmemYCbCrImage shmemImage(aImage.get_YCbCrImage().data(),
                              aImage.get_YCbCrImage().offset());
@@ -696,17 +734,18 @@ RegisterTextureHostAtGrallocBufferActor(
   if (IsSurfaceDescriptorValid(aSurfaceDescriptor)) {
     GrallocBufferActor* actor = static_cast<GrallocBufferActor*>(aSurfaceDescriptor.get_SurfaceDescriptorGralloc().bufferParent());
     actor->SetTextureHost(aTextureHost);
   }
 }
 
 void
 GrallocTextureHostOGL::UpdateImpl(const SurfaceDescriptor& aImage,
-                                 nsIntRegion* aRegion)
+                                 nsIntRegion* aRegion,
+                                 nsIntPoint* aOffset)
 {
   SwapTexturesImpl(aImage, aRegion);
 }
 
 void
 GrallocTextureHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                         nsIntRegion*)
 {
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -15,16 +15,18 @@
 
 #ifdef MOZ_WIDGET_GONK
 #include <ui/GraphicBuffer.h>
 #endif
 
 namespace mozilla {
 namespace layers {
 
+class TextureImageTextureHostOGL;
+
 /*
  * TextureHost implementations for the OpenGL backend.
  *
  * Note that it is important to becareful about the ownership model with
  * the OpenGL backend, due to some widget limitation on Linux: before
  * the nsBaseWidget associated with our OpenGL context has been completely
  * deleted, every resource belonging to the OpenGL context MUST have been
  * released. At the moment the teardown sequence happens in the middle of
@@ -47,16 +49,18 @@ public:
   virtual gfx::IntSize GetSize() const = 0;
   virtual gl::ShaderProgramType GetShaderProgram() const {
     MOZ_NOT_REACHED("unhandled shader type");
   }
   // TODO: Noone's implementing this anymore, should see if we need this.
   virtual GLenum GetTextureTarget() const { return LOCAL_GL_TEXTURE_2D; }
   virtual GLenum GetWrapMode() const = 0;// { return LOCAL_GL_CLAMP_TO_EDGE; } // default
   virtual gfx3DMatrix GetTextureTransform() { return gfx3DMatrix(); }
+
+  virtual TextureImageTextureHostOGL* AsTextureImageTextureHost() { return nullptr; }
 };
 
 inline gl::ShaderProgramType
 GetProgramTypeForTexture(const TextureHost *aTextureHost)
 {
   switch (aTextureHost->GetFormat()) {
   case gfx::FORMAT_B8G8R8A8:
     return gl::BGRALayerProgramType;;
@@ -89,30 +93,42 @@ public:
 
   ~TextureImageTextureHostOGL();
 
   TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE
   {
     return this;
   }
 
+  virtual TextureImageTextureHostOGL* AsTextureImageTextureHost() MOZ_OVERRIDE
+  {
+    return this;
+  }
+
   // This is a hack that is here to not break on-main-thread ThebesLayerBuffer
   // please do not use it anywhere else, use SetCompositor instead.
   void SetGLContext(gl::GLContext* aGL)
   {
     mGL = aGL;
   }
 
   // TextureHost
 
   void UpdateImpl(const SurfaceDescriptor& aImage,
-                  nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
+                  nsIntRegion* aRegion = nullptr,
+                  nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
+  virtual void EnsureBuffer(const nsIntSize& aSize, gfxContentType aType) MOZ_OVERRIDE;
+
+  virtual void CopyTo(const nsIntRect& aSourceRect,
+                      TextureHost *aDest,
+                      const nsIntRect& aDestRect) MOZ_OVERRIDE;
+
   bool IsValid() const MOZ_OVERRIDE
   {
     return !!mTexture;
   }
 
   virtual bool Lock() MOZ_OVERRIDE;
 
   // textureSource
@@ -214,17 +230,18 @@ public:
   ~YCbCrTextureHostOGL()
   {
     MOZ_COUNT_DTOR(YCbCrTextureHostOGL);
   }
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual void UpdateImpl(const SurfaceDescriptor& aImage,
-                          nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
+                          nsIntRegion* aRegion = nullptr,
+                          nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
 
   virtual bool Lock() MOZ_OVERRIDE;
 
   virtual bool IsValid() const MOZ_OVERRIDE
   {
     return mYTexture->IsValid()
         && mCbTexture->IsValid()
         && mCrTexture->IsValid();
@@ -322,17 +339,18 @@ public:
 
   virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
 
   bool IsValid() const MOZ_OVERRIDE { return !!mSharedHandle; }
 
   // override from TextureHost, we support both buffered
   // and unbuffered operation.
   virtual void UpdateImpl(const SurfaceDescriptor& aImage,
-                          nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
+                          nsIntRegion* aRegion = nullptr,
+                          nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
   virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
                                 nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
   virtual bool Lock() MOZ_OVERRIDE;
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; }
   virtual void SetWrapMode(GLenum aMode) { mWrapMode = aMode; }
 
@@ -554,17 +572,18 @@ public:
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual GLuint GetTextureHandle()
   {
     return mGLTexture;
   }
 
   virtual void UpdateImpl(const SurfaceDescriptor& aImage,
-                          nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
+                          nsIntRegion* aRegion = nullptr,
+                          nsIntPoint* aOffset = nullptr) MOZ_OVERRIDE;
   virtual void SwapTexturesImpl(const SurfaceDescriptor& aImage,
                           nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
   virtual bool Lock() MOZ_OVERRIDE;
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE
   {
     return mGraphicBuffer.get() ? gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight()) : gfx::IntSize(0, 0);