Bug 1143575. Make ImageClientSingle handle multiple textures. r=nical draft
authorRobert O'Callahan <robert@ocallahan.org>
Fri, 03 Jul 2015 22:37:03 +1200
changeset 275590 5d7b66be05eb0b35c7057c4e0b33c831fc83f478
parent 275589 f1e81e6b486274e9bbfdd5df9ebfebbd5520d9f8
child 275591 897b526bed374966a3b46721ce0561b8878ed4e6
push id3189
push userrocallahan@mozilla.com
push dateFri, 03 Jul 2015 11:12:01 +0000
reviewersnical
bugs1143575
milestone42.0a1
Bug 1143575. Make ImageClientSingle handle multiple textures. r=nical
gfx/layers/ImageContainer.h
gfx/layers/client/CanvasClient.cpp
gfx/layers/client/ContentClient.cpp
gfx/layers/client/ImageClient.cpp
gfx/layers/client/ImageClient.h
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -371,16 +371,17 @@ public:
    * Returns if the container currently has an image.
    * Can be called on any thread. This method takes mReentrantMonitor
    * when accessing thread-shared state.
    */
   bool HasCurrentImage();
 
   struct OwningImage {
     nsRefPtr<Image> mImage;
+    TimeStamp mTimeStamp;
   };
   /**
    * Copy the current Image list to aImages.
    * This has to add references since otherwise there are race conditions
    * where the current image is destroyed before the caller can add
    * a reference.
    * Can be called on any thread.
    * May return an empty list to indicate there is no current image.
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -98,17 +98,21 @@ CanvasClient2D::Update(gfx::IntSize aSiz
   mBuffer->Unlock();
 
   if (bufferCreated && !AddTextureClient(mBuffer)) {
     mBuffer = nullptr;
     return;
   }
 
   if (updated) {
-    GetForwarder()->UseTexture(this, mBuffer);
+    nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
+    CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
+    t->mTextureClient = mBuffer;
+    t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBuffer->GetSize());
+    GetForwarder()->UseTextures(this, textures);
     mBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
   }
 }
 
 already_AddRefed<TextureClient>
 CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
                                              gfx::IntSize aSize,
                                              TextureFlags aFlags,
@@ -375,17 +379,21 @@ CanvasClientSharedSurface::Update(gfx::I
     }
   }
 
   mFront = newFront;
 
   // Add the new TexClient.
   MOZ_ALWAYS_TRUE( AddTextureClient(mFront) );
 
-  forwarder->UseTexture(this, mFront);
+  nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
+  CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
+  t->mTextureClient = mFront;
+  t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize());
+  forwarder->UseTextures(this, textures);
 }
 
 void
 CanvasClientSharedSurface::ClearSurfaces()
 {
   mFront = nullptr;
   mShSurfClient = nullptr;
   mReadbackClient = nullptr;
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -379,17 +379,22 @@ ContentClientRemoteBuffer::Updated(const
                                                aVisibleRegion,
                                                aDidSelfCopy);
 
   MOZ_ASSERT(mTextureClient);
   if (mTextureClientOnWhite) {
     mForwarder->UseComponentAlphaTextures(this, mTextureClient,
                                           mTextureClientOnWhite);
   } else {
-    mForwarder->UseTexture(this, mTextureClient);
+    nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
+    CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
+    t->mTextureClient = mTextureClient;
+    IntSize size = mTextureClient->GetSize();
+    t->mPictureRect = nsIntRect(0, 0, size.width, size.height);
+    GetForwarder()->UseTextures(this, textures);
   }
   mForwarder->UpdateTextureRegion(this,
                                   ThebesBufferData(BufferRect(),
                                                    BufferRotation()),
                                   updatedRegion);
 }
 
 void
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -108,150 +108,182 @@ TextureInfo ImageClientSingle::GetTextur
 {
   return TextureInfo(CompositableType::IMAGE);
 }
 
 void
 ImageClientSingle::FlushAllImages(bool aExceptFront,
                                   AsyncTransactionWaiter* aAsyncTransactionWaiter)
 {
-  if (!aExceptFront && mFrontBuffer) {
-    RemoveTextureWithWaiter(mFrontBuffer, aAsyncTransactionWaiter);
-    mFrontBuffer = nullptr;
+  if (!aExceptFront) {
+    for (auto& b : mBuffers) {
+      RemoveTextureWithWaiter(b.mTextureClient, aAsyncTransactionWaiter);
+    }
+    mBuffers.Clear();
   }
 }
 
 bool
 ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
 {
   nsAutoTArray<ImageContainer::OwningImage,4> images;
   uint32_t generationCounter;
   aContainer->GetCurrentImages(&images, &generationCounter);
 
   if (mLastUpdateGenerationCounter == generationCounter) {
     return true;
   }
   mLastUpdateGenerationCounter = generationCounter;
 
-  Image* image = images[0].mImage;
-  // Don't try to update to an invalid image. We return true because the caller
-  // would attempt to recreate the ImageClient otherwise, and that isn't going
-  // to help.
-  if (!image->IsValid()) {
+  for (int32_t i = images.Length() - 1; i >= 0; --i) {
+    if (!images[i].mImage->IsValid()) {
+      // Don't try to update to an invalid image.
+      images.RemoveElementAt(i);
+    }
+  }
+  if (images.IsEmpty()) {
+    // We return true because the caller would attempt to recreate the
+    // ImageClient otherwise, and that isn't going to help.
     return true;
   }
 
-  RefPtr<TextureClient> texture = image->GetTextureClient(this);
+  nsTArray<Buffer> newBuffers;
+  nsAutoTArray<CompositableForwarder::TimedTextureClient,4> textures;
+
+  for (auto& img : images) {
+    Image* image = img.mImage;
+    RefPtr<TextureClient> texture = image->GetTextureClient(this);
+
+    for (int32_t i = mBuffers.Length() - 1; i >= 0; --i) {
+      if (mBuffers[i].mImageSerial == image->GetSerial()) {
+        if (texture) {
+          MOZ_ASSERT(texture == mBuffers[i].mTextureClient);
+        } else {
+          texture = mBuffers[i].mTextureClient;
+        }
+        // Remove this element from mBuffers so mBuffers only contains
+        // images that aren't present in 'images'
+        mBuffers.RemoveElementAt(i);
+      }
+    }
+
+    if (!texture) {
+      // Slow path, we should not be hitting it very often and if we do it means
+      // we are using an Image class that is not backed by textureClient and we
+      // should fix it.
+      if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
+        PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
+        const PlanarYCbCrData* data = ycbcr->GetData();
+        if (!data) {
+          return false;
+        }
+        texture = TextureClient::CreateForYCbCr(GetForwarder(),
+          data->mYSize, data->mCbCrSize, data->mStereoMode,
+          TextureFlags::DEFAULT | mTextureFlags
+        );
+        if (!texture || !texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
+          return false;
+        }
+        bool status = texture->AsTextureClientYCbCr()->UpdateYCbCr(*data);
+        MOZ_ASSERT(status);
+
+        texture->Unlock();
+        if (!status) {
+          return false;
+        }
+
+      } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
+                 image->GetFormat() == ImageFormat::EGLIMAGE) {
+        gfx::IntSize size = image->GetSize();
 
-  AutoRemoveTexture autoRemoveTexture(this);
-  if (texture != mFrontBuffer) {
-    autoRemoveTexture.mTexture = mFrontBuffer;
-    mFrontBuffer = nullptr;
+        if (image->GetFormat() == ImageFormat::EGLIMAGE) {
+          EGLImageImage* typedImage = static_cast<EGLImageImage*>(image);
+          texture = new EGLImageTextureClient(GetForwarder(),
+                                              mTextureFlags,
+                                              typedImage,
+                                              size);
+#ifdef MOZ_WIDGET_ANDROID
+        } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
+          SurfaceTextureImage* typedImage = static_cast<SurfaceTextureImage*>(image);
+          const SurfaceTextureImage::Data* data = typedImage->GetData();
+          texture = new SurfaceTextureClient(GetForwarder(), mTextureFlags,
+                                             data->mSurfTex, size,
+                                             data->mOriginPos);
+#endif
+        } else {
+          MOZ_ASSERT(false, "Bad ImageFormat.");
+        }
+      } else {
+        RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
+        MOZ_ASSERT(surface);
+        texture = CreateTextureClientForDrawing(surface->GetFormat(), image->GetSize(),
+                                                gfx::BackendType::NONE, mTextureFlags);
+        if (!texture) {
+          return false;
+        }
+
+        MOZ_ASSERT(texture->CanExposeDrawTarget());
+
+        if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
+          return false;
+        }
+
+        {
+          // We must not keep a reference to the DrawTarget after it has been unlocked.
+          DrawTarget* dt = texture->BorrowDrawTarget();
+          if (!dt) {
+            gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
+            return false;
+          }
+          MOZ_ASSERT(surface.get());
+          dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
+        }
+
+        texture->Unlock();
+      }
+    }
+    if (!texture || !AddTextureClient(texture)) {
+      return false;
+    }
+
+
+    CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
+    t->mTextureClient = texture;
+    t->mTimeStamp = img.mTimeStamp;
+    t->mPictureRect = image->GetPictureRect();
+
+    Buffer* newBuf = newBuffers.AppendElement();
+    newBuf->mImageSerial = image->GetSerial();
+    newBuf->mTextureClient = texture;
+
+    aContainer->NotifyPaintedImage(image);
+    texture->SyncWithObject(GetForwarder()->GetSyncObject());
   }
 
-  if (!texture) {
-    // Slow path, we should not be hitting it very often and if we do it means
-    // we are using an Image class that is not backed by textureClient and we
-    // should fix it.
-    if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
-      PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
-      const PlanarYCbCrData* data = ycbcr->GetData();
-      if (!data) {
-        return false;
-      }
-      texture = TextureClient::CreateForYCbCr(GetForwarder(),
-        data->mYSize, data->mCbCrSize, data->mStereoMode,
-        TextureFlags::DEFAULT | mTextureFlags
-      );
-      if (!texture || !texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
-        return false;
-      }
-      bool status = texture->AsTextureClientYCbCr()->UpdateYCbCr(*data);
-      MOZ_ASSERT(status);
-
-      texture->Unlock();
-      if (!status) {
-        return false;
-      }
-
-    } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
-               image->GetFormat() == ImageFormat::EGLIMAGE) {
-      gfx::IntSize size = image->GetSize();
+  GetForwarder()->UseTextures(this, textures);
 
-      if (image->GetFormat() == ImageFormat::EGLIMAGE) {
-        EGLImageImage* typedImage = static_cast<EGLImageImage*>(image);
-        texture = new EGLImageTextureClient(GetForwarder(),
-                                            mTextureFlags,
-                                            typedImage,
-                                            size);
-#ifdef MOZ_WIDGET_ANDROID
-      } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
-        SurfaceTextureImage* typedImage = static_cast<SurfaceTextureImage*>(image);
-        const SurfaceTextureImage::Data* data = typedImage->GetData();
-        texture = new SurfaceTextureClient(GetForwarder(), mTextureFlags,
-                                           data->mSurfTex, size,
-                                           data->mOriginPos);
-#endif
-      } else {
-        MOZ_ASSERT(false, "Bad ImageFormat.");
-      }
-    } else {
-      RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
-      MOZ_ASSERT(surface);
-      texture = CreateTextureClientForDrawing(surface->GetFormat(), image->GetSize(),
-                                              gfx::BackendType::NONE, mTextureFlags);
-      if (!texture) {
-        return false;
-      }
-
-      MOZ_ASSERT(texture->CanExposeDrawTarget());
-
-      if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
-        return false;
-      }
-
-      {
-        // We must not keep a reference to the DrawTarget after it has been unlocked.
-        DrawTarget* dt = texture->BorrowDrawTarget();
-        if (!dt) {
-          gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
-          return false;
-        }
-        MOZ_ASSERT(surface.get());
-        dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
-      }
-
-      texture->Unlock();
-    }
+  for (auto& b : mBuffers) {
+    RemoveTexture(b.mTextureClient);
   }
-  if (!texture || !AddTextureClient(texture)) {
-    return false;
-  }
-
-  mFrontBuffer = texture;
-  IntRect pictureRect = image->GetPictureRect();
-  GetForwarder()->UseTexture(this, texture, &pictureRect);
-
-  aContainer->NotifyPaintedImage(image);
-  texture->SyncWithObject(GetForwarder()->GetSyncObject());
+  mBuffers.SwapElements(newBuffers);
 
   return true;
 }
 
 bool
 ImageClientSingle::AddTextureClient(TextureClient* aTexture)
 {
   MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
   return CompositableClient::AddTextureClient(aTexture);
 }
 
 void
 ImageClientSingle::OnDetach()
 {
-  mFrontBuffer = nullptr;
+  mBuffers.Clear();
 }
 
 ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
                          CompositableType aType)
 : CompositableClient(aFwd, aFlags)
 , mLayer(nullptr)
 , mType(aType)
 , mLastUpdateGenerationCounter(0)
--- a/gfx/layers/client/ImageClient.h
+++ b/gfx/layers/client/ImageClient.h
@@ -101,17 +101,21 @@ public:
   virtual TextureInfo GetTextureInfo() const override;
 
   virtual already_AddRefed<Image> CreateImage(ImageFormat aFormat) override;
 
   virtual void FlushAllImages(bool aExceptFront,
                               AsyncTransactionWaiter* aAsyncTransactionWaiter) override;
 
 protected:
-  RefPtr<TextureClient> mFrontBuffer;
+  struct Buffer {
+    RefPtr<TextureClient> mTextureClient;
+    int32_t mImageSerial;
+  };
+  nsTArray<Buffer> mBuffers;
 };
 
 /**
  * Image class to be used for async image uploads using the image bridge
  * protocol.
  * We store the ImageBridge id in the TextureClientIdentifier.
  */
 class ImageClientBridge : public ImageClient
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -123,26 +123,27 @@ public:
    * Forcibly remove texture data from TextureClient
    * This function needs to be called after a tansaction with Compositor.
    */
   virtual void RemoveTexturesIfNecessary()
   {
     mTexturesToRemove.Clear();
   }
 
+  struct TimedTextureClient {
+    TextureClient* mTextureClient;
+    TimeStamp mTimeStamp;
+    nsIntRect mPictureRect;
+  };
   /**
-   * Tell the CompositableHost on the compositor side what texture to use for
+   * Tell the CompositableHost on the compositor side what textures 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,
-                          const nsIntRect* aPictureRect = nullptr) = 0;
+  virtual void UseTextures(CompositableClient* aCompositable,
+                           const nsTArray<TimedTextureClient>& aTextures) = 0;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) = 0;
 
   virtual void SendPendingAsyncMessges() = 0;
 
   void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
 
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -99,32 +99,32 @@ struct CompositableTransaction
 
 struct AutoEndTransaction {
   explicit AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
   ~AutoEndTransaction() { mTxn->End(); }
   CompositableTransaction* mTxn;
 };
 
 void
-ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
-                             TextureClient* aTexture,
-                             const gfx::IntRect* aPictureRect)
+ImageBridgeChild::UseTextures(CompositableClient* aCompositable,
+                              const nsTArray<TimedTextureClient>& aTextures)
 {
   MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
-  MOZ_ASSERT(aTexture->GetIPDLActor());
+
+  nsAutoTArray<TimedTexture,4> textures;
 
-  FenceHandle fence = aTexture->GetAcquireFenceHandle();
-  IntRect pictureRect = aPictureRect ? *aPictureRect :
-      IntRect(IntPoint(0, 0), IntSize(aTexture->GetSize()));
-  nsAutoTArray<TimedTexture,1> textures;
-  textures.AppendElement(TimedTexture(nullptr, aTexture->GetIPDLActor(),
-                                      fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
-                                      TimeStamp(), pictureRect));
+  for (auto& t : aTextures) {
+    MOZ_ASSERT(t.mTextureClient);
+    MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
+    FenceHandle fence = t.mTextureClient->GetAcquireFenceHandle();
+    textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
+                                        fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
+                                        t.mTimeStamp, t.mPictureRect));
+  }
   mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
                                    textures));
 }
 
 void
 ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
                                             TextureClient* aTextureOnBlack,
                                             TextureClient* aTextureOnWhite)
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -206,21 +206,20 @@ public:
 
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable) override;
 
   virtual bool IsImageBridgeChild() const override { return true; }
 
   /**
-   * See CompositableForwarder::UseTexture
+   * See CompositableForwarder::UseTextures
    */
-  virtual void UseTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient,
-                          const nsIntRect* aPictureRect = nullptr) override;
+  virtual void UseTextures(CompositableClient* aCompositable,
+                           const nsTArray<TimedTextureClient>& aTextures) override;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) override;
 #ifdef MOZ_WIDGET_GONK
   virtual void UseOverlaySource(CompositableClient* aCompositable,
                                 const OverlaySource& aOverlay,
                                 const nsIntRect& aPictureRect) override;
 #endif
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -345,41 +345,42 @@ ShadowLayerForwarder::UpdateTextureRegio
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   mTxn->AddPaint(OpPaintTextureRegion(nullptr, aCompositable->GetIPDLActor(),
                                       aThebesBufferData,
                                       aUpdatedRegion));
 }
 
 void
-ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable,
-                                 TextureClient* aTexture,
-                                 const nsIntRect* aPictureRect)
+ShadowLayerForwarder::UseTextures(CompositableClient* aCompositable,
+                                  const nsTArray<TimedTextureClient>& aTextures)
 {
   MOZ_ASSERT(aCompositable);
-  MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
-  MOZ_ASSERT(aTexture->GetIPDLActor());
+
+  nsAutoTArray<TimedTexture,4> textures;
 
-  FenceHandle fence = aTexture->GetAcquireFenceHandle();
-  IntRect pictureRect = aPictureRect ? *aPictureRect :
-      IntRect(nsIntPoint(0, 0), IntSize(aTexture->GetSize()));
-  nsAutoTArray<TimedTexture,1> textures;
-  textures.AppendElement(TimedTexture(nullptr, aTexture->GetIPDLActor(),
-                                      fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
-                                      TimeStamp(), pictureRect));
+  for (auto& t : aTextures) {
+    MOZ_ASSERT(t.mTextureClient);
+    MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
+    FenceHandle fence = t.mTextureClient->GetAcquireFenceHandle();
+    textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
+                                        fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
+                                        t.mTimeStamp, t.mPictureRect));
+    if ((t.mTextureClient->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD)
+        && t.mTextureClient->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();
+    }
+  }
   mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
                              textures));
-  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();
-  }
 }
 
 void
 ShadowLayerForwarder::UseComponentAlphaTextures(CompositableClient* aCompositable,
                                                 TextureClient* aTextureOnBlack,
                                                 TextureClient* aTextureOnWhite)
 {
   MOZ_ASSERT(aCompositable);
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -224,21 +224,20 @@ 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;
 
   /**
-   * See CompositableForwarder::UseTexture
+   * See CompositableForwarder::UseTextures
    */
-  virtual void UseTexture(CompositableClient* aCompositable,
-                          TextureClient* aClient,
-                          const nsIntRect* aPictureRect = nullptr) override;
+  virtual void UseTextures(CompositableClient* aCompositable,
+                           const nsTArray<TimedTextureClient>& aTextures) override;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) override;
 #ifdef MOZ_WIDGET_GONK
   virtual void UseOverlaySource(CompositableClient* aCompositable,
                                 const OverlaySource& aOverlay,
                                 const nsIntRect& aPictureRect) override;
 #endif