Bug 1143575. Pass a picture rect with OpUseOverlaySource and OpUseTexture, and eliminate OpUpdatePictureRect. r=nical
authorRobert O'Callahan <robert@ocallahan.org>
Sat, 04 Jul 2015 10:52:42 +1200
changeset 251632 780ea52b2d360ca75320727a2630fd7e6f8f0746
parent 251631 edc00000dd20d3e73d41f31d4ab8b6fe5d54f6e7
child 251633 30fbb3f4be2efda2ecd8a162de591aad4ba21a62
push id61921
push userrocallahan@mozilla.com
push dateTue, 07 Jul 2015 07:13:27 +0000
treeherdermozilla-inbound@f10665af6c50 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1143575
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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,29 +327,27 @@ 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);
-  }
-
-  return IntSize();
+  return IntSize(mPictureRect.width, mPictureRect.height);
 }
 
 void
 ImageHostOverlay::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   aStream << aPrefix;
   aStream << nsPrintfCString("ImageHost (0x%p)", this).get();
 
--- 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
@@ -103,27 +103,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);
@@ -136,32 +140,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
@@ -215,23 +215,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;
@@ -239,23 +241,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,