Bug 1143575. Pass a picture rect with OpUseOverlaySource and OpUseTexture, and eliminate OpUpdatePictureRect. r=nical draft
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 11 May 2015 21:34:13 +1200
changeset 275577 73b13f328e398167d94cdce8c97b8a8b8aaa3dc4
parent 275576 439bfa84977b11c6b1cfd963be54bb7b865c90c2
child 275578 67483b98feb7df82211d07afb6371540eaa577a8
push id3189
push userrocallahan@mozilla.com
push dateFri, 03 Jul 2015 11:12:01 +0000
reviewersnical
bugs1143575
milestone42.0a1
Bug 1143575. Pass a picture rect with OpUseOverlaySource and OpUseTexture, and eliminate OpUpdatePictureRect. r=nical The picture rect logically belongs with the texture, and later patches will make OpUseTexture take multiple textures, each of which needs its own picture rect.
gfx/layers/client/ImageClient.cpp
gfx/layers/client/ImageClient.h
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/CompositableHost.h
gfx/layers/composite/ContentHost.cpp
gfx/layers/composite/ContentHost.h
gfx/layers/composite/ImageHost.cpp
gfx/layers/composite/ImageHost.h
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/CompositableTransactionParent.cpp
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -240,19 +240,18 @@ ImageClientSingle::UpdateImage(ImageCont
       texture->Unlock();
     }
   }
   if (!texture || !AddTextureClient(texture)) {
     return false;
   }
 
   mFrontBuffer = texture;
-  GetForwarder()->UseTexture(this, texture);
-
-  UpdatePictureRect(image->GetPictureRect());
+  IntRect pictureRect = image->GetPictureRect();
+  GetForwarder()->UseTexture(this, texture, &pictureRect);
 
   mLastPaintedImageSerial = image->GetSerial();
   aContainer->NotifyPaintedImage(image);
 
   texture->SyncWithObject(GetForwarder()->GetSyncObject());
 
   return true;
 }
@@ -273,27 +272,16 @@ ImageClientSingle::OnDetach()
 ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
                          CompositableType aType)
 : CompositableClient(aFwd, aFlags)
 , mLayer(nullptr)
 , mType(aType)
 , mLastPaintedImageSerial(0)
 {}
 
-void
-ImageClient::UpdatePictureRect(IntRect aRect)
-{
-  if (mPictureRect == aRect) {
-    return;
-  }
-  mPictureRect = aRect;
-  MOZ_ASSERT(mForwarder);
-  GetForwarder()->UpdatePictureRect(this, aRect);
-}
-
 ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
                                      TextureFlags aFlags)
 : ImageClient(aFwd, aFlags, CompositableType::IMAGE_BRIDGE)
 , mAsyncContainerID(0)
 {
 }
 
 bool
@@ -359,19 +347,18 @@ ImageClientOverlay::UpdateImage(ImageCon
   if (image->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
     OverlayImage* overlayImage = static_cast<OverlayImage*>(image);
     uint32_t overlayId = overlayImage->GetOverlayId();
     gfx::IntSize size = overlayImage->GetSize();
 
     OverlaySource source;
     source.handle() = OverlayHandle(overlayId);
     source.size() = size;
-    GetForwarder()->UseOverlaySource(this, source);
+    GetForwarder()->UseOverlaySource(this, source, image->GetPictureRect());
   }
-  UpdatePictureRect(image->GetPictureRect());
   return true;
 }
 
 already_AddRefed<Image>
 ImageClientOverlay::CreateImage(ImageFormat aFormat)
 {
   nsRefPtr<Image> img;
   switch (aFormat) {
--- a/gfx/layers/client/ImageClient.h
+++ b/gfx/layers/client/ImageClient.h
@@ -51,22 +51,16 @@ public:
 
   /**
    * Update this ImageClient from aContainer in aLayer
    * returns false if this is the wrong kind of ImageClient for aContainer.
    * Note that returning true does not necessarily imply success
    */
   virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags) = 0;
 
-  /**
-   * The picture rect is the area of the texture which makes up the image. That
-   * is, the area that should be composited. In texture space.
-   */
-  virtual void UpdatePictureRect(gfx::IntRect aPictureRect);
-
   virtual already_AddRefed<Image> CreateImage(ImageFormat aFormat) = 0;
 
   void SetLayer(ClientLayer* aLayer) { mLayer = aLayer; }
   ClientLayer* GetLayer() const { return mLayer; }
 
   /**
    * Create AsyncTransactionTracker that is used for FlushAllImagesAsync().
    */
@@ -86,17 +80,16 @@ public:
 
 protected:
   ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
               CompositableType aType);
 
   ClientLayer* mLayer;
   CompositableType mType;
   int32_t mLastPaintedImageSerial;
-  gfx::IntRect mPictureRect;
 };
 
 /**
  * An image client which uses a single texture client.
  */
 class ImageClientSingle : public ImageClient
 {
 public:
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -15,16 +15,19 @@
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
 #include "nsRefPtr.h"                   // for nsRefPtr
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "mozilla/layers/PCompositableParent.h"
 
 namespace mozilla {
+
+using namespace gfx;
+
 namespace layers {
 
 class Compositor;
 
 /**
  * IPDL actor used by CompositableHost to match with its corresponding
  * CompositableClient on the content side.
  *
@@ -99,17 +102,18 @@ CompositableHost::DestroyIPDLActor(PComp
 CompositableHost*
 CompositableHost::FromIPDLActor(PCompositableParent* aActor)
 {
   MOZ_ASSERT(aActor);
   return static_cast<CompositableParent*>(aActor)->mHost;
 }
 
 void
-CompositableHost::UseTextureHost(TextureHost* aTexture)
+CompositableHost::UseTextureHost(TextureHost* aTexture,
+                                 const IntRect& aPictureRect)
 {
   if (!aTexture) {
     return;
   }
   if (GetCompositor()) {
     aTexture->SetCompositor(GetCompositor());
   }
 }
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -93,26 +93,25 @@ public:
                             nsIntRegion* aUpdatedRegionBack)
   {
     NS_ERROR("should be implemented or not used");
     return false;
   }
 
   /**
    * Returns the front buffer.
+   * *aPictureRect (if non-null, and the returned TextureHost is non-null)
+   * is set to the picture rect.
    */
-  virtual TextureHost* GetAsTextureHost() { return nullptr; }
+  virtual TextureHost* GetAsTextureHost(gfx::IntRect* aPictureRect = nullptr) {
+    return nullptr;
+  }
 
   virtual LayerRenderState GetRenderState() = 0;
 
-  virtual void SetPictureRect(const gfx::IntRect& aPictureRect)
-  {
-    MOZ_ASSERT(false, "Should have been overridden");
-  }
-
   virtual gfx::IntSize GetImageSize() const
   {
     MOZ_ASSERT(false, "Should have been overridden");
     return gfx::IntSize();
   }
 
   /**
    * Adds a mask effect using this texture as the mask, if possible.
@@ -148,19 +147,20 @@ public:
     NS_ASSERTION(aFlags & ALLOW_REATTACH || !mAttached,
                  "Re-attaching compositables must be explicitly authorised");
     SetCompositor(aCompositor);
     SetLayer(aLayer);
     mAttached = true;
     mKeepAttached = aFlags & KEEP_ATTACHED;
 
     // If we already have a textureHost before, use that in this moment.
-    RefPtr<TextureHost> frontBuffer = GetAsTextureHost();
+    gfx::IntRect pictureRect;
+    RefPtr<TextureHost> frontBuffer = GetAsTextureHost(&pictureRect);
     if (frontBuffer) {
-      UseTextureHost(frontBuffer);
+      UseTextureHost(frontBuffer, pictureRect);
     }
   }
   // Detach this compositable host from its layer.
   // If we are used for async video, then it is not safe to blindly detach since
   // we might be re-attached to a different layer. aLayer is the layer which the
   // caller expects us to be attached to, we will only detach if we are in fact
   // attached to that layer. If we are part of a normal layer, then we will be
   // detached in any case. if aLayer is null, then we will only detach if we are
@@ -182,20 +182,22 @@ public:
                     const char* aPrefix="",
                     bool aDumpHtml=false) { }
   static void DumpTextureHost(std::stringstream& aStream, TextureHost* aTexture);
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0;
 
-  virtual void UseTextureHost(TextureHost* aTexture);
+  virtual void UseTextureHost(TextureHost* aTexture,
+                              const gfx::IntRect& aPictureRect);
   virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
                                          TextureHost* aTextureOnWhite);
-  virtual void UseOverlaySource(OverlaySource aOverlay) { }
+  virtual void UseOverlaySource(OverlaySource aOverlay,
+                                const gfx::IntRect& aPictureRect) { }
 
   virtual void RemoveTextureHost(TextureHost* aTexture);
 
   // Called every time this is composited
   void BumpFlashCounter() {
     mFlashCounter = mFlashCounter >= DIAGNOSTIC_FLASH_COUNTER_MAX
                   ? DIAGNOSTIC_FLASH_COUNTER_MAX : mFlashCounter + 1;
   }
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -213,19 +213,23 @@ ContentHostTexture::Composite(EffectChai
   if (iterOnWhite) {
     diagnostics |= DiagnosticFlags::COMPONENT_ALPHA;
   }
   GetCompositor()->DrawDiagnostics(diagnostics, nsIntRegion(mBufferRect), aClipRect,
                                    aTransform, mFlashCounter);
 }
 
 void
-ContentHostTexture::UseTextureHost(TextureHost* aTexture)
+ContentHostTexture::UseTextureHost(TextureHost* aTexture,
+                                   const nsIntRect& aPictureRect)
 {
-  ContentHostBase::UseTextureHost(aTexture);
+  ContentHostBase::UseTextureHost(aTexture, aPictureRect);
+  MOZ_ASSERT(aPictureRect.IsEqualInterior(
+      nsIntRect(nsIntPoint(0, 0), nsIntSize(aTexture->GetSize()))),
+      "Only default picture rect supported");
   mTextureHost = aTexture;
   mTextureHostOnWhite = nullptr;
   mTextureSourceOnWhite = nullptr;
   if (mTextureHost) {
     mTextureHost->PrepareTextureSource(mTextureSource);
   }
 }
 
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -126,17 +126,18 @@ public:
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
 
   virtual void Dump(std::stringstream& aStream,
                     const char* aPrefix="",
                     bool aDumpHtml=false) override;
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
-  virtual void UseTextureHost(TextureHost* aTexture) override;
+  virtual void UseTextureHost(TextureHost* aTexture,
+                              const nsIntRect& aPictureRect) override;
   virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
                                          TextureHost* aTextureOnWhite) override;
 
   virtual bool Lock() override {
     MOZ_ASSERT(!mLocked);
     if (!mTextureHost) {
       return false;
     }
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -24,48 +24,52 @@ class Matrix4x4;
 using namespace gfx;
 
 namespace layers {
 
 class ISurfaceAllocator;
 
 ImageHost::ImageHost(const TextureInfo& aTextureInfo)
   : CompositableHost(aTextureInfo)
-  , mHasPictureRect(false)
   , mLocked(false)
 {}
 
 ImageHost::~ImageHost()
 {}
 
 void
-ImageHost::UseTextureHost(TextureHost* aTexture)
+ImageHost::UseTextureHost(TextureHost* aTexture,
+                          const nsIntRect& aPictureRect)
 {
-  CompositableHost::UseTextureHost(aTexture);
+  CompositableHost::UseTextureHost(aTexture, aPictureRect);
   mFrontBuffer = aTexture;
   if (mFrontBuffer) {
     mFrontBuffer->Updated();
     mFrontBuffer->PrepareTextureSource(mTextureSource);
   }
+  mPictureRect = aPictureRect;
 }
 
 void
 ImageHost::RemoveTextureHost(TextureHost* aTexture)
 {
   CompositableHost::RemoveTextureHost(aTexture);
   if (aTexture && mFrontBuffer == aTexture) {
     mFrontBuffer->UnbindTextureSource();
     mTextureSource = nullptr;
     mFrontBuffer = nullptr;
   }
 }
 
 TextureHost*
-ImageHost::GetAsTextureHost()
+ImageHost::GetAsTextureHost(IntRect* aPictureRect)
 {
+  if (aPictureRect) {
+    *aPictureRect = mPictureRect;
+  }
   return mFrontBuffer;
 }
 
 void
 ImageHost::Composite(EffectChain& aEffectChain,
                      float aOpacity,
                      const gfx::Matrix4x4& aTransform,
                      const gfx::Filter& aFilter,
@@ -107,24 +111,17 @@ ImageHost::Composite(EffectChain& aEffec
                                                        aFilter,
                                                        isAlphaPremultiplied,
                                                        GetRenderState());
   if (!effect) {
     return;
   }
 
   aEffectChain.mPrimaryEffect = effect;
-  IntSize textureSize = mTextureSource->GetSize();
-  gfx::Rect gfxPictureRect
-    = mHasPictureRect ? gfx::Rect(0, 0, mPictureRect.width, mPictureRect.height)
-                      : gfx::Rect(0, 0, textureSize.width, textureSize.height);
-
-  gfx::Rect pictureRect(0, 0,
-                        mPictureRect.width,
-                        mPictureRect.height);
+  gfx::Rect pictureRect(0, 0, mPictureRect.width, mPictureRect.height);
   BigImageIterator* it = mTextureSource->AsBigImageIterator();
   if (it) {
 
     // This iteration does not work if we have multiple texture sources here
     // (e.g. 3 YCbCr textures). There's nothing preventing the different
     // planes from having different resolutions or tile sizes. For example, a
     // YCbCr frame could have Cb and Cr planes that are half the resolution of
     // the Y plane, in such a way that the Y plane overflows the maximum
@@ -138,62 +135,50 @@ ImageHost::Composite(EffectChain& aEffec
     // DrawQuad currently assumes that all planes use the same texture coords.
     MOZ_ASSERT(it->GetTileCount() == 1 || !mTextureSource->GetNextSibling(),
                "Can't handle multi-plane BigImages");
 
     it->BeginBigImageIteration();
     do {
       IntRect tileRect = it->GetTileRect();
       gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
-      if (mHasPictureRect) {
-        rect = rect.Intersect(pictureRect);
-        effect->mTextureCoords = Rect(Float(rect.x - tileRect.x)/ tileRect.width,
-                                      Float(rect.y - tileRect.y) / tileRect.height,
-                                      Float(rect.width) / tileRect.width,
-                                      Float(rect.height) / tileRect.height);
-      } else {
-        effect->mTextureCoords = Rect(0, 0, 1, 1);
-      }
+      rect = rect.Intersect(pictureRect);
+      effect->mTextureCoords = Rect(Float(rect.x - tileRect.x) / tileRect.width,
+                                    Float(rect.y - tileRect.y) / tileRect.height,
+                                    Float(rect.width) / tileRect.width,
+                                    Float(rect.height) / tileRect.height);
       if (mFrontBuffer->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT) {
         effect->mTextureCoords.y = effect->mTextureCoords.YMost();
         effect->mTextureCoords.height = -effect->mTextureCoords.height;
       }
       GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
                                 aOpacity, aTransform);
       GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE | DiagnosticFlags::BIGIMAGE,
                                        rect, aClipRect, aTransform, mFlashCounter);
     } while (it->NextTile());
     it->EndBigImageIteration();
     // layer border
-    GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE,
-                                     gfxPictureRect, aClipRect,
-                                     aTransform, mFlashCounter);
+    GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE, pictureRect,
+                                     aClipRect, aTransform, mFlashCounter);
   } else {
     IntSize textureSize = mTextureSource->GetSize();
-    gfx::Rect rect;
-    if (mHasPictureRect) {
-      effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width,
-                                    Float(mPictureRect.y) / textureSize.height,
-                                    Float(mPictureRect.width) / textureSize.width,
-                                    Float(mPictureRect.height) / textureSize.height);
-      rect = pictureRect;
-    } else {
-      effect->mTextureCoords = Rect(0, 0, 1, 1);
-      rect = gfx::Rect(0, 0, textureSize.width, textureSize.height);
-    }
+    effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width,
+                                  Float(mPictureRect.y) / textureSize.height,
+                                  Float(mPictureRect.width) / textureSize.width,
+                                  Float(mPictureRect.height) / textureSize.height);
 
     if (mFrontBuffer->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT) {
       effect->mTextureCoords.y = effect->mTextureCoords.YMost();
       effect->mTextureCoords.height = -effect->mTextureCoords.height;
     }
 
-    GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
+    GetCompositor()->DrawQuad(pictureRect, aClipRect, aEffectChain,
                               aOpacity, aTransform);
     GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE,
-                                     rect, aClipRect,
+                                     pictureRect, aClipRect,
                                      aTransform, mFlashCounter);
   }
 }
 
 void
 ImageHost::SetCompositor(Compositor* aCompositor)
 {
   if (mFrontBuffer && mCompositor != aCompositor) {
@@ -269,24 +254,19 @@ ImageHost::Unlock()
     mFrontBuffer->Unlock();
   }
   mLocked = false;
 }
 
 IntSize
 ImageHost::GetImageSize() const
 {
-  if (mHasPictureRect) {
+  if (mFrontBuffer) {
     return IntSize(mPictureRect.width, mPictureRect.height);
   }
-
-  if (mFrontBuffer) {
-    return mFrontBuffer->GetSize();
-  }
-
   return IntSize();
 }
 
 already_AddRefed<TexturedEffect>
 ImageHost::GenEffect(const gfx::Filter& aFilter)
 {
   if (!mFrontBuffer->BindTextureSource(mTextureSource)) {
     return nullptr;
@@ -300,17 +280,16 @@ ImageHost::GenEffect(const gfx::Filter& 
                               aFilter,
                               isAlphaPremultiplied,
                               GetRenderState());
 }
 
 #ifdef MOZ_WIDGET_GONK
 ImageHostOverlay::ImageHostOverlay(const TextureInfo& aTextureInfo)
   : CompositableHost(aTextureInfo)
-  , mHasPictureRect(false)
 {
 }
 
 ImageHostOverlay::~ImageHostOverlay()
 {
 }
 
 void
@@ -329,23 +308,18 @@ ImageHostOverlay::Composite(EffectChain&
     return;
   Color hollow(0.0f, 0.0f, 0.0f, 0.0f);
   aEffectChain.mPrimaryEffect = new EffectSolidColor(hollow);
   aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE] = new EffectBlendMode(CompositionOp::OP_SOURCE);
 
   gfx::Rect rect;
   gfx::Rect clipRect(aClipRect.x, aClipRect.y,
                      aClipRect.width, aClipRect.height);
-  if (mHasPictureRect) {
-    rect.SetRect(mPictureRect.x, mPictureRect.y,
-                 mPictureRect.width, mPictureRect.height);
-  } else {
-    rect.SetRect(0, 0,
-                 mOverlay.size().width, mOverlay.size().height);
-  }
+  rect.SetRect(mPictureRect.x, mPictureRect.y,
+               mPictureRect.width, mPictureRect.height);
 
   mCompositor->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform);
   mCompositor->DrawDiagnostics(DiagnosticFlags::IMAGE | DiagnosticFlags::BIGIMAGE,
                                rect, aClipRect, aTransform, mFlashCounter);
 }
 
 LayerRenderState
 ImageHostOverlay::GetRenderState()
@@ -353,19 +327,21 @@ ImageHostOverlay::GetRenderState()
   LayerRenderState state;
   if (mOverlay.handle().type() == OverlayHandle::Tint32_t) {
     state.SetOverlayId(mOverlay.handle().get_int32_t());
   }
   return state;
 }
 
 void
-ImageHostOverlay::UseOverlaySource(OverlaySource aOverlay)
+ImageHostOverlay::UseOverlaySource(OverlaySource aOverlay,
+                                   const nsIntRect& aPictureRect)
 {
   mOverlay = aOverlay;
+  mPictureRect = aPictureRect;
 }
 
 IntSize
 ImageHostOverlay::GetImageSize() const
 {
   if (mHasPictureRect) {
     return IntSize(mPictureRect.width, mPictureRect.height);
   }
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -46,30 +46,25 @@ public:
 
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr) override;
 
-  virtual void UseTextureHost(TextureHost* aTexture) override;
+  virtual void UseTextureHost(TextureHost* aTexture,
+                              const nsIntRect& aPictureRect) override;
 
   virtual void RemoveTextureHost(TextureHost* aTexture) override;
 
-  virtual TextureHost* GetAsTextureHost() override;
+  virtual TextureHost* GetAsTextureHost(gfx::IntRect* aPictureRect = nullptr) override;
 
   virtual void SetCompositor(Compositor* aCompositor) override;
 
-  virtual void SetPictureRect(const gfx::IntRect& aPictureRect) override
-  {
-    mPictureRect = aPictureRect;
-    mHasPictureRect = true;
-  }
-
   gfx::IntSize GetImageSize() const override;
 
   virtual LayerRenderState GetRenderState() override;
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
   virtual void Dump(std::stringstream& aStream,
                     const char* aPrefix = "",
@@ -83,17 +78,16 @@ public:
 
   virtual already_AddRefed<TexturedEffect> GenEffect(const gfx::Filter& aFilter) override;
 
 protected:
 
   CompositableTextureHostRef mFrontBuffer;
   CompositableTextureSourceRef mTextureSource;
   gfx::IntRect mPictureRect;
-  bool mHasPictureRect;
   bool mLocked;
 };
 
 #ifdef MOZ_WIDGET_GONK
 
 /**
  * ImageHostOverlay works with ImageClientOverlay
  */
@@ -106,27 +100,22 @@ public:
 
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr) override;
   virtual LayerRenderState GetRenderState() override;
-  virtual void UseOverlaySource(OverlaySource aOverlay) override;
+  virtual void UseOverlaySource(OverlaySource aOverlay,
+                                const gfx::IntRect& aPictureRect) override;
   virtual gfx::IntSize GetImageSize() const override;
-  virtual void SetPictureRect(const nsIntRect& aPictureRect) override
-  {
-    mPictureRect = aPictureRect;
-    mHasPictureRect = true;
-  }
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
 protected:
   gfx::IntRect mPictureRect;
-  bool mHasPictureRect;
   OverlaySource mOverlay;
 };
 
 #endif
 
 }
 }
 
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -67,25 +67,20 @@ public:
   /**
    * Communicate to the compositor that aRegion in the texture identified by
    * aCompositable and aIdentifier has been updated to aThebesBuffer.
    */
   virtual void UpdateTextureRegion(CompositableClient* aCompositable,
                                    const ThebesBufferData& aThebesBufferData,
                                    const nsIntRegion& aUpdatedRegion) = 0;
 
-  /**
-   * Communicate the picture rect of a YUV image in aLayer to the compositor
-   */
-  virtual void UpdatePictureRect(CompositableClient* aCompositable,
-                                 const gfx::IntRect& aRect) = 0;
-
 #ifdef MOZ_WIDGET_GONK
   virtual void UseOverlaySource(CompositableClient* aCompositabl,
-                                const OverlaySource& aOverlay) = 0;
+                                const OverlaySource& aOverlay,
+                                const gfx::IntRect& aPictureRect) = 0;
 #endif
 
   /**
    * Tell the CompositableHost on the compositor side to remove the texture
    * from the CompositableHost.
    * This function does not delete the TextureHost corresponding to the
    * TextureClient passed in parameter.
    * When the TextureClient has TEXTURE_DEALLOCATE_CLIENT flag,
@@ -131,19 +126,23 @@ public:
   virtual void RemoveTexturesIfNecessary()
   {
     mTexturesToRemove.Clear();
   }
 
   /**
    * Tell the CompositableHost on the compositor side what texture to use for
    * the next composition.
+   * If non-null, aPictureRect is the area of the texture which makes up the
+   * image. That is, the area that should be composited. In texture space.
+   * When aPictureRect is null, the entire area of the texture is used.
    */
   virtual void UseTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) = 0;
+                          TextureClient* aClient,
+                          const nsIntRect* aPictureRect = nullptr) = 0;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) = 0;
 
   virtual void SendPendingAsyncMessges() = 0;
 
   void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
 
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -63,16 +63,25 @@ bool ScheduleComposition(const T& op)
   CompositorParent* cp = CompositorParent::GetCompositor(id);
   if (!cp) {
     return false;
   }
   cp->ScheduleComposition();
   return true;
 }
 
+#if defined(DEBUG) || defined(MOZ_WIDGET_GONK)
+static bool ValidatePictureRect(const mozilla::gfx::IntSize& aSize,
+                                const nsIntRect& aPictureRect)
+{
+  return nsIntRect(0, 0, aSize.width, aSize.height).Contains(aPictureRect) &&
+      !aPictureRect.IsEmpty();
+}
+#endif
+
 bool
 CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit,
                                                      EditReplyVector& replyv)
 {
   switch (aEdit.type()) {
     case CompositableOperation::TOpPaintTextureRegion: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint PaintedLayer"));
 
@@ -97,23 +106,16 @@ CompositableParentManager::ReceiveCompos
         return false;
       }
       replyv.push_back(
         OpContentBufferSwap(op.compositableParent(), nullptr, frontUpdatedRegion));
 
       RenderTraceInvalidateEnd(thebes, "FF00FF");
       break;
     }
-    case CompositableOperation::TOpUpdatePictureRect: {
-      const OpUpdatePictureRect& op = aEdit.get_OpUpdatePictureRect();
-      CompositableHost* compositable = AsCompositable(op);
-      MOZ_ASSERT(compositable);
-      compositable->SetPictureRect(op.picture());
-      break;
-    }
     case CompositableOperation::TOpUseTiledLayerBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
       const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer();
       TiledContentHost* compositable = AsCompositable(op)->AsTiledContentHost();
 
       NS_ASSERTION(compositable, "The compositable is not tiled");
 
       const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
@@ -167,17 +169,20 @@ CompositableParentManager::ReceiveCompos
       break;
     }
     case CompositableOperation::TOpUseTexture: {
       const OpUseTexture& op = aEdit.get_OpUseTexture();
       CompositableHost* compositable = AsCompositable(op);
       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
-      compositable->UseTextureHost(tex);
+      if (!ValidatePictureRect(tex->GetSize(), op.picture())) {
+        return false;
+      }
+      compositable->UseTextureHost(tex, op.picture());
 
       MaybeFence maybeFence = op.fence();
       if (maybeFence.type() == MaybeFence::TFenceHandle) {
         FenceHandle fence = maybeFence.get_FenceHandle();
         if (fence.IsValid() && tex) {
           tex->SetAcquireFenceHandle(fence);
         }
       }
@@ -204,17 +209,20 @@ CompositableParentManager::ReceiveCompos
       }
       break;
     }
 #ifdef MOZ_WIDGET_GONK
     case CompositableOperation::TOpUseOverlaySource: {
       const OpUseOverlaySource& op = aEdit.get_OpUseOverlaySource();
       CompositableHost* compositable = AsCompositable(op);
       MOZ_ASSERT(compositable->GetType() == CompositableType::IMAGE_OVERLAY, "Invalid operation!");
-      compositable->UseOverlaySource(op.overlay());
+      if (!ValidatePictureRect(op.overlay().size(), op.picture())) {
+        return false;
+      }
+      compositable->UseOverlaySource(op.overlay(), op.picture());
       break;
     }
 #endif
     default: {
       MOZ_ASSERT(false, "bad type");
     }
   }
 
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -100,27 +100,31 @@ struct CompositableTransaction
 struct AutoEndTransaction {
   explicit AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
   ~AutoEndTransaction() { mTxn->End(); }
   CompositableTransaction* mTxn;
 };
 
 void
 ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
-                             TextureClient* aTexture)
+                             TextureClient* aTexture,
+                             const gfx::IntRect* aPictureRect)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aTexture->GetIPDLActor());
 
   FenceHandle fence = aTexture->GetAcquireFenceHandle();
+  IntRect pictureRect = aPictureRect ? *aPictureRect :
+      IntRect(IntPoint(0, 0), IntSize(aTexture->GetSize()));
   mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
                                    nullptr, aTexture->GetIPDLActor(),
-                                   fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t())));
+                                   fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
+                                   pictureRect));
 }
 
 void
 ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
                                             TextureClient* aTextureOnBlack,
                                             TextureClient* aTextureOnWhite)
 {
   MOZ_ASSERT(aCompositable);
@@ -133,32 +137,25 @@ ImageBridgeChild::UseComponentAlphaTextu
   mTxn->AddNoSwapEdit(OpUseComponentAlphaTextures(nullptr, aCompositable->GetIPDLActor(),
                                                   nullptr, aTextureOnBlack->GetIPDLActor(),
                                                   nullptr, aTextureOnWhite->GetIPDLActor()));
 }
 
 #ifdef MOZ_WIDGET_GONK
 void
 ImageBridgeChild::UseOverlaySource(CompositableClient* aCompositable,
-                                   const OverlaySource& aOverlay)
+                                   const OverlaySource& aOverlay,
+                                   const nsIntRect& aPictureRect)
 {
   MOZ_ASSERT(aCompositable);
-  mTxn->AddEdit(OpUseOverlaySource(nullptr, aCompositable->GetIPDLActor(), aOverlay));
+  mTxn->AddEdit(OpUseOverlaySource(nullptr, aCompositable->GetIPDLActor(),
+      aOverlay, aPictureRect));
 }
 #endif
 
-void
-ImageBridgeChild::UpdatePictureRect(CompositableClient* aCompositable,
-                                    const gfx::IntRect& aRect)
-{
-  MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(aCompositable->GetIPDLActor());
-  mTxn->AddNoSwapEdit(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect));
-}
-
 // Singleton
 static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
 static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
 static Thread *sImageBridgeChildThread = nullptr;
 
 void ReleaseImageBridgeParentSingleton() {
   sImageBridgeParentSingleton = nullptr;
 }
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -209,23 +209,25 @@ public:
   virtual void Connect(CompositableClient* aCompositable) override;
 
   virtual bool IsImageBridgeChild() const override { return true; }
 
   /**
    * See CompositableForwarder::UseTexture
    */
   virtual void UseTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) override;
+                          TextureClient* aClient,
+                          const nsIntRect* aPictureRect = nullptr) override;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) override;
 #ifdef MOZ_WIDGET_GONK
   virtual void UseOverlaySource(CompositableClient* aCompositable,
-                                const OverlaySource& aOverlay) override;
+                                const OverlaySource& aOverlay,
+                                const nsIntRect& aPictureRect) override;
 #endif
 
   virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                              TextureClient* aTexture) override;
 
   virtual void RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aAsyncTransactionTracker,
                                                   CompositableClient* aCompositable,
                                                   TextureClient* aTexture) override;
@@ -233,23 +235,16 @@ public:
   virtual void RemoveTexture(TextureClient* aTexture) override;
 
   virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
                                    const SurfaceDescriptorTiles& aTileLayerDescriptor) override
   {
     NS_RUNTIMEABORT("should not be called");
   }
 
-  /**
-   * Communicate the picture rect of a YUV image in aLayer to the compositor
-   */
-  virtual void UpdatePictureRect(CompositableClient* aCompositable,
-                                 const gfx::IntRect& aRect) override;
-
-
   virtual void UpdateTextureRegion(CompositableClient* aCompositable,
                                    const ThebesBufferData& aThebesBufferData,
                                    const nsIntRegion& aUpdatedRegion) override {
     NS_RUNTIMEABORT("should not be called");
   }
 
   // ISurfaceAllocator
 
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -344,29 +344,25 @@ struct SurfaceDescriptorTiles {
 struct OpUseTiledLayerBuffer {
   PCompositable compositable;
   SurfaceDescriptorTiles tileLayerDescriptor;
 };
 
 struct OpUseOverlaySource {
   PCompositable compositable;
   OverlaySource overlay;
+  IntRect picture;
 };
 
 struct OpPaintTextureRegion {
   PCompositable compositable;
   ThebesBufferData bufferData;
   nsIntRegion updatedRegion;
 };
 
-struct OpUpdatePictureRect {
-  PCompositable compositable;
-  IntRect picture;
-};
-
 /**
  * Tells the CompositableHost to remove the corresponding TextureHost
  */
 struct OpRemoveTexture {
   PCompositable compositable;
   PTexture texture;
 };
 
@@ -390,16 +386,17 @@ union MaybeFence {
 /**
  * Tells the compositor-side which texture to use (for example, as front buffer
  * if there is several textures for double buffering)
  */
 struct OpUseTexture {
   PCompositable compositable;
   PTexture texture;
   MaybeFence fence;
+  IntRect picture;
 };
 
 struct OpUseComponentAlphaTextures {
   PCompositable compositable;
   PTexture textureOnBlack;
   PTexture textureOnWhite;
 };
 
@@ -415,18 +412,16 @@ struct OpDeliverFence {
 
 struct OpDeliverFenceToTracker {
   uint64_t destHolderId;
   uint64_t destTransactionId;
   FenceHandle fence;
 };
 
 union CompositableOperation {
-  OpUpdatePictureRect;
-
   OpPaintTextureRegion;
 
   OpUseTiledLayerBuffer;
 
   OpRemoveTexture;
   OpRemoveTextureAsync;
 
   OpUseTexture;
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -34,18 +34,19 @@
 
 namespace mozilla {
 namespace ipc {
 class Shmem;
 }
 
 namespace layers {
 
+using namespace mozilla::gfx;
+using namespace mozilla::gl;
 using namespace mozilla::ipc;
-using namespace mozilla::gl;
 
 class ClientTiledLayerBuffer;
 
 typedef nsTArray<SurfaceDescriptor> BufferArray;
 typedef std::vector<Edit> EditVector;
 typedef std::set<ShadowableLayer*> ShadowableLayerSet;
 
 class Transaction
@@ -344,37 +345,32 @@ ShadowLayerForwarder::UpdateTextureRegio
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   mTxn->AddPaint(OpPaintTextureRegion(nullptr, aCompositable->GetIPDLActor(),
                                       aThebesBufferData,
                                       aUpdatedRegion));
 }
 
 void
-ShadowLayerForwarder::UpdatePictureRect(CompositableClient* aCompositable,
-                                        const gfx::IntRect& aRect)
-{
-  MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(aCompositable->GetIPDLActor());
-  mTxn->AddNoSwapPaint(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect));
-}
-
-void
 ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable,
-                                 TextureClient* aTexture)
+                                 TextureClient* aTexture,
+                                 const nsIntRect* aPictureRect)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aTexture->GetIPDLActor());
 
   FenceHandle fence = aTexture->GetAcquireFenceHandle();
+  IntRect pictureRect = aPictureRect ? *aPictureRect :
+      IntRect(nsIntPoint(0, 0), IntSize(aTexture->GetSize()));
   mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
                              nullptr, aTexture->GetIPDLActor(),
-                             fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t())));
+                             fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
+                             pictureRect));
   if (aTexture->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD
       && aTexture->HasInternalBuffer()) {
     // We use IMMEDIATE_UPLOAD when we want to be sure that the upload cannot
     // race with updates on the main thread. In this case we want the transaction
     // to be synchronous.
     mTxn->MarkSyncTransaction();
   }
 }
@@ -394,20 +390,22 @@ ShadowLayerForwarder::UseComponentAlphaT
   mTxn->AddEdit(OpUseComponentAlphaTextures(nullptr, aCompositable->GetIPDLActor(),
                                             nullptr, aTextureOnBlack->GetIPDLActor(),
                                             nullptr, aTextureOnWhite->GetIPDLActor()));
 }
 
 #ifdef MOZ_WIDGET_GONK
 void
 ShadowLayerForwarder::UseOverlaySource(CompositableClient* aCompositable,
-                                       const OverlaySource& aOverlay)
+                                       const OverlaySource& aOverlay,
+                                       const nsIntRect& aPictureRect)
 {
   MOZ_ASSERT(aCompositable);
-  mTxn->AddEdit(OpUseOverlaySource(nullptr, aCompositable->GetIPDLActor(), aOverlay));
+  mTxn->AddEdit(OpUseOverlaySource(nullptr, aCompositable->GetIPDLActor(),
+      aOverlay, aPictureRect));
 }
 #endif
 
 void
 ShadowLayerForwarder::RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                                     TextureClient* aTexture)
 {
   MOZ_ASSERT(aCompositable);
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -224,32 +224,28 @@ public:
    * Communicate to the compositor that aRegion in the texture identified by aLayer
    * and aIdentifier has been updated to aThebesBuffer.
    */
   virtual void UpdateTextureRegion(CompositableClient* aCompositable,
                                    const ThebesBufferData& aThebesBufferData,
                                    const nsIntRegion& aUpdatedRegion) override;
 
   /**
-   * Communicate the picture rect of an image to the compositor
-   */
-  void UpdatePictureRect(CompositableClient* aCompositable,
-                         const gfx::IntRect& aRect) override;
-
-  /**
    * See CompositableForwarder::UseTexture
    */
   virtual void UseTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient) override;
+                          TextureClient* aClient,
+                          const nsIntRect* aPictureRect = nullptr) override;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) override;
 #ifdef MOZ_WIDGET_GONK
   virtual void UseOverlaySource(CompositableClient* aCompositable,
-                                const OverlaySource& aOverlay) override;
+                                const OverlaySource& aOverlay,
+                                const nsIntRect& aPictureRect) override;
 #endif
 
   /**
    * End the current transaction and forward it to LayerManagerComposite.
    * |aReplies| are directions from the LayerManagerComposite to the
    * caller of EndTransaction().
    */
   bool EndTransaction(InfallibleTArray<EditReply>* aReplies,