Bug 1042052 - Add TextureClient::CreateSimilar and have component alpha buffer be of the same type. r=sotaro
authorNicolas Silva <nsilva@mozilla.com>
Fri, 25 Jul 2014 11:24:46 +0200
changeset 196132 780188e2dab73e08f9226cb071f3c3bc05bec874
parent 196131 a6758d669350200c3af251f8fe3b12b78719eebd
child 196133 8b56e423374c6cd9db1d4014c8f36f707c4d5627
push id27205
push userkwierso@gmail.com
push dateFri, 25 Jul 2014 22:59:38 +0000
treeherdermozilla-central@e07264876182 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1042052
milestone34.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 1042052 - Add TextureClient::CreateSimilar and have component alpha buffer be of the same type. r=sotaro
gfx/layers/TextureDIB.cpp
gfx/layers/TextureDIB.h
gfx/layers/basic/TextureClientX11.cpp
gfx/layers/basic/TextureClientX11.h
gfx/layers/client/ContentClient.cpp
gfx/layers/client/ContentClient.h
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/d3d9/TextureD3D9.cpp
gfx/layers/d3d9/TextureD3D9.h
gfx/layers/opengl/GrallocTextureClient.cpp
gfx/layers/opengl/GrallocTextureClient.h
gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
gfx/layers/opengl/TextureClientOGL.h
--- a/gfx/layers/TextureDIB.cpp
+++ b/gfx/layers/TextureDIB.cpp
@@ -20,16 +20,29 @@ DIBTextureClient::DIBTextureClient(gfx::
   MOZ_COUNT_CTOR(DIBTextureClient);
 }
 
 DIBTextureClient::~DIBTextureClient()
 {
   MOZ_COUNT_DTOR(DIBTextureClient);
 }
 
+TemporaryRef<TextureClient>
+DIBTextureClient::CreateSimilar(TextureFlags aFlags,
+                                  TextureAllocationFlags aAllocFlags) const
+{
+  RefPtr<TextureClient> tex = new DIBTextureClient(mFormat, mFlags | aFlags);
+
+  if (!tex->AllocateForSurface(mSize, ALLOC_DEFAULT)) {
+    return nullptr;
+  }
+
+  return tex;
+}
+
 bool
 DIBTextureClient::Lock(OpenMode)
 {
   MOZ_ASSERT(!mIsLocked);
   if (!IsValid()) {
     return false;
   }
   mIsLocked = true;
--- a/gfx/layers/TextureDIB.h
+++ b/gfx/layers/TextureDIB.h
@@ -47,16 +47,20 @@ public:
 
   virtual gfx::DrawTarget* BorrowDrawTarget() MOZ_OVERRIDE;
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
     TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
+
 protected:
   nsRefPtr<gfxWindowsSurface> mSurface;
   RefPtr<gfx::DrawTarget> mDrawTarget;
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
   bool mIsLocked;
 };
 
--- a/gfx/layers/basic/TextureClientX11.cpp
+++ b/gfx/layers/basic/TextureClientX11.cpp
@@ -27,16 +27,29 @@ TextureClientX11::TextureClientX11(ISurf
   MOZ_COUNT_CTOR(TextureClientX11);
 }
 
 TextureClientX11::~TextureClientX11()
 {
   MOZ_COUNT_DTOR(TextureClientX11);
 }
 
+TemporaryRef<TextureClient>
+TextureClientX11::CreateSimilar(TextureFlags aFlags,
+                                TextureAllocationFlags aAllocFlags) const
+{
+  RefPtr<TextureClient> tex = new TextureClientX11(mAllocator, mFormat, mFlags);
+
+  if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
+    return nullptr;
+  }
+
+  return tex;
+}
+
 bool
 TextureClientX11::IsAllocated() const
 {
   return !!mSurface;
 }
 
 bool
 TextureClientX11::Lock(OpenMode aMode)
--- a/gfx/layers/basic/TextureClientX11.h
+++ b/gfx/layers/basic/TextureClientX11.h
@@ -42,16 +42,20 @@ class TextureClientX11 : public TextureC
   virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
 
   virtual gfx::DrawTarget* BorrowDrawTarget() MOZ_OVERRIDE;
 
   virtual gfx::SurfaceFormat GetFormat() const { return mFormat; }
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
+
  private:
   gfx::SurfaceFormat mFormat;
   gfx::IntSize mSize;
   RefPtr<gfxXlibSurface> mSurface;
   RefPtr<ISurfaceAllocator> mAllocator;
   RefPtr<gfx::DrawTarget> mDrawTarget;
   bool mLocked;
 };
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -190,48 +190,16 @@ ContentClientRemoteBuffer::EndPaint()
     mTextureClient->Unlock();
   }
   if (mTextureClientOnWhite && mTextureClientOnWhite->IsLocked()) {
     mTextureClientOnWhite->Unlock();
   }
   ContentClientRemote::EndPaint();
 }
 
-bool
-ContentClientRemoteBuffer::CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
-                                                          TextureFlags aFlags)
-{
-  TextureAllocationFlags allocFlags = TextureAllocationFlags::ALLOC_CLEAR_BUFFER;
-  if (aFlags & TextureFlags::ON_WHITE) {
-    allocFlags = TextureAllocationFlags::ALLOC_CLEAR_BUFFER_WHITE;
-  }
-
-  // gfx::BackendType::NONE means fallback to the content backend
-  aClient = CreateTextureClientForDrawing(mSurfaceFormat, mSize,
-                                          gfx::BackendType::NONE,
-                                          mTextureInfo.mTextureFlags | aFlags,
-                                          allocFlags);
-  if (!aClient) {
-    // try with ALLOC_FALLBACK
-    aClient = CreateTextureClientForDrawing(mSurfaceFormat, mSize,
-                                            gfx::BackendType::NONE,
-                                            mTextureInfo.mTextureFlags
-                                            | TextureFlags::ALLOC_FALLBACK
-                                            | aFlags,
-                                            allocFlags);
-  }
-
-  if (!aClient) {
-    return false;
-  }
-
-  NS_WARN_IF_FALSE(aClient->IsValid(), "Created an invalid texture client");
-  return true;
-}
-
 void
 ContentClientRemoteBuffer::BuildTextureClients(SurfaceFormat aFormat,
                                                const nsIntRect& aRect,
                                                uint32_t aFlags)
 {
   // If we hit this assertion, then it might be due to an empty transaction
   // followed by a real transaction. Our buffers should be created (but not
   // painted in the empty transaction) and then painted (but not created) in the
@@ -254,24 +222,42 @@ ContentClientRemoteBuffer::BuildTextureC
   }
 
   CreateBackBuffer(mBufferRect);
 }
 
 void
 ContentClientRemoteBuffer::CreateBackBuffer(const nsIntRect& aBufferRect)
 {
-  if (!CreateAndAllocateTextureClient(mTextureClient, TextureFlags::ON_BLACK) ||
-    !AddTextureClient(mTextureClient)) {
+  // gfx::BackendType::NONE means fallback to the content backend
+  mTextureClient = CreateTextureClientForDrawing(
+    mSurfaceFormat, mSize, gfx::BackendType::NONE,
+    mTextureInfo.mTextureFlags,
+    TextureAllocationFlags::ALLOC_CLEAR_BUFFER
+  );
+  if (!mTextureClient) {
+    // try with ALLOC_FALLBACK
+    mTextureClient = CreateTextureClientForDrawing(
+      mSurfaceFormat, mSize, gfx::BackendType::NONE,
+      mTextureInfo.mTextureFlags | TextureFlags::ALLOC_FALLBACK,
+      TextureAllocationFlags::ALLOC_CLEAR_BUFFER
+    );
+  }
+
+  if (!mTextureClient || !AddTextureClient(mTextureClient)) {
     AbortTextureClientCreation();
     return;
   }
+
   if (mTextureInfo.mTextureFlags & TextureFlags::COMPONENT_ALPHA) {
-    if (!CreateAndAllocateTextureClient(mTextureClientOnWhite, TextureFlags::ON_WHITE) ||
-      !AddTextureClient(mTextureClientOnWhite)) {
+    mTextureClientOnWhite = mTextureClient->CreateSimilar(
+      mTextureInfo.mTextureFlags,
+      TextureAllocationFlags::ALLOC_CLEAR_BUFFER_WHITE
+    );
+    if (!mTextureClientOnWhite || !AddTextureClient(mTextureClientOnWhite)) {
       AbortTextureClientCreation();
       return;
     }
   }
 }
 
 void
 ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -274,19 +274,16 @@ protected:
   // Ensure we have a valid back buffer if we have a valid front buffer (i.e.
   // if a backbuffer has been created.)
   virtual void EnsureBackBufferIfFrontBuffer() {}
 
   // Create the front buffer for the ContentClient/Host pair if necessary
   // and notify the compositor that we have created the buffer(s).
   virtual void DestroyFrontBuffer() {}
 
-  bool CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
-                                      TextureFlags aFlags = TextureFlags::NO_FLAGS);
-
   virtual void AbortTextureClientCreation()
   {
     mTextureClient = nullptr;
     mTextureClientOnWhite = nullptr;
     mIsNewBuffer = false;
   }
 
   RefPtr<TextureClient> mTextureClient;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -645,16 +645,29 @@ BufferTextureClient::BufferTextureClient
   , mBackend(aMoz2DBackend)
   , mOpenMode(OpenMode::OPEN_NONE)
   , mLocked(false)
 {}
 
 BufferTextureClient::~BufferTextureClient()
 {}
 
+TemporaryRef<TextureClient>
+BufferTextureClient::CreateSimilar(TextureFlags aFlags,
+                                   TextureAllocationFlags aAllocFlags) const
+{
+  // This may return null
+  RefPtr<BufferTextureClient> newBufferTex = TextureClient::CreateForRawBufferAccess(
+    mAllocator, mFormat, mSize, mBackend, mFlags | aFlags, aAllocFlags
+  );
+
+  RefPtr<TextureClient> newTex = newBufferTex.get();
+  return newTex;
+}
+
 ISurfaceAllocator*
 BufferTextureClient::GetAllocator() const
 {
   return mAllocator;
 }
 
 bool
 BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -150,16 +150,36 @@ public:
   // pointers) with a certain buffer size. It's unfortunate that we need this.
   // providing format and sizes could let us do more optimization.
   static TemporaryRef<BufferTextureClient>
   CreateWithBufferSize(ISurfaceAllocator* aAllocator,
                        gfx::SurfaceFormat aFormat,
                        size_t aSize,
                        TextureFlags aTextureFlags);
 
+  // Creates and allocates a TextureClient of the same type.
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const = 0;
+
+  /**
+   * Allocates for a given surface size, taking into account the pixel format
+   * which is part of the state of the TextureClient.
+   *
+   * Does not clear the surface by default, clearing the surface can be done
+   * by passing the CLEAR_BUFFER flag.
+   *
+   * TextureClients that can expose a DrawTarget should override this method.
+   */
+  virtual bool AllocateForSurface(gfx::IntSize aSize,
+                                  TextureAllocationFlags flags = ALLOC_DEFAULT)
+  {
+    return false;
+  }
+
   virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
 
   /**
    * Locks the shared data, allowing the caller to get access to it.
    *
    * Please always lock/unlock when accessing the shared data.
    * If Lock() returns false, you should not attempt to access the shared data.
    */
@@ -367,32 +387,16 @@ private:
 protected:
   /**
    * An invalid TextureClient cannot provide access to its shared data
    * anymore. This usually means it will soon be destroyed.
    */
   void MarkInvalid() { mValid = false; }
 
   /**
-   * Allocates for a given surface size, taking into account the pixel format
-   * which is part of the state of the TextureClient.
-   *
-   * Does not clear the surface by default, clearing the surface can be done
-   * by passing the CLEAR_BUFFER flag.
-   *
-   * TextureClients that can expose a DrawTarget should override this method.
-   */
-  virtual bool AllocateForSurface(gfx::IntSize aSize,
-                                  TextureAllocationFlags flags = ALLOC_DEFAULT)
-  {
-    return false;
-  }
-
-
-  /**
    * Should only be called *once* per texture, in TextureClient::InitIPDLActor.
    * Some texture implementations rely on the fact that the descriptor will be
    * deserialized.
    * Calling ToSurfaceDescriptor again after it has already returned true,
    * or never constructing a TextureHost with aDescriptor may result in a memory
    * leak (see CairoTextureClientD3D9 for example).
    */
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
@@ -494,16 +498,20 @@ public:
   virtual bool Allocate(uint32_t aSize) = 0;
 
   virtual size_t GetBufferSize() const = 0;
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
   ISurfaceAllocator* GetAllocator() const;
 
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
+
 protected:
   RefPtr<gfx::DrawTarget> mDrawTarget;
   RefPtr<ISurfaceAllocator> mAllocator;
   gfx::SurfaceFormat mFormat;
   gfx::IntSize mSize;
   gfx::BackendType mBackend;
   OpenMode mOpenMode;
   bool mLocked;
@@ -602,16 +610,22 @@ public:
 
   virtual gfx::IntSize GetSize() const { return gfx::IntSize(); }
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
   {
     return gfx::SurfaceFormat::UNKNOWN;
   }
 
+  // This TextureClient should not be used in a context where we use CreateSimilar
+  // (ex. component alpha) because the underlying texture data is always created by
+  // an external producer.
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE { return nullptr; }
+
   virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) MOZ_OVERRIDE
   {
     MOZ_CRASH("Should never hit this.");
     return false;
   }
 
 protected:
   bool mIsLocked;
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -180,16 +180,29 @@ TextureClientD3D11::~TextureClientD3D11(
     MOZ_ASSERT(mDrawTarget->refCount() == 1);
     LockD3DTexture(mTexture.get());
     mDrawTarget = nullptr;
     UnlockD3DTexture(mTexture.get());
   }
 #endif
 }
 
+TemporaryRef<TextureClient>
+TextureClientD3D11::CreateSimilar(TextureFlags aFlags,
+                                  TextureAllocationFlags aAllocFlags) const
+{
+  RefPtr<TextureClient> tex = new TextureClientD3D11(mFormat, mFlags | aFlags);
+
+  if (!tex->AllocateForSurface(mSize, ALLOC_DEFAULT)) {
+    return nullptr;
+  }
+
+  return tex;
+}
+
 bool
 TextureClientD3D11::Lock(OpenMode aMode)
 {
   if (!mTexture) {
     return false;
   }
   MOZ_ASSERT(!mIsLocked, "The Texture is already locked!");
 
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -54,16 +54,20 @@ public:
 
   virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
 
   virtual gfx::DrawTarget* BorrowDrawTarget() MOZ_OVERRIDE;
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
+
 protected:
   gfx::IntSize mSize;
   RefPtr<ID3D10Texture2D> mTexture;
   RefPtr<gfx::DrawTarget> mDrawTarget;
   gfx::SurfaceFormat mFormat;
   bool mIsLocked;
   bool mNeedsClear;
   bool mNeedsClearWhite;
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -561,16 +561,28 @@ CairoTextureClientD3D9::CairoTextureClie
   MOZ_COUNT_CTOR(CairoTextureClientD3D9);
 }
 
 CairoTextureClientD3D9::~CairoTextureClientD3D9()
 {
   MOZ_COUNT_DTOR(CairoTextureClientD3D9);
 }
 
+TemporaryRef<TextureClient>
+CairoTextureClientD3D9::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
+{
+  RefPtr<TextureClient> tex = new CairoTextureClientD3D9(mFormat, mFlags | aFlags);
+
+  if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
+    return nullptr;
+  }
+
+  return tex;
+}
+
 bool
 CairoTextureClientD3D9::Lock(OpenMode aMode)
 {
   MOZ_ASSERT(!mIsLocked);
   if (!IsValid() || !IsAllocated()) {
     return false;
   }
 
--- a/gfx/layers/d3d9/TextureD3D9.h
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -211,16 +211,20 @@ public:
 
   virtual gfx::DrawTarget* BorrowDrawTarget() MOZ_OVERRIDE;
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
+
 private:
   RefPtr<IDirect3DTexture9> mTexture;
   nsRefPtr<IDirect3DSurface9> mD3D9Surface;
   RefPtr<gfx::DrawTarget> mDrawTarget;
   nsRefPtr<gfxASurface> mSurface;
   gfx::IntSize mSize;
   gfx::SurfaceFormat mFormat;
   bool mIsLocked;
@@ -263,16 +267,22 @@ public:
 
   virtual gfx::IntSize GetSize() const
   {
     return gfx::IntSize(mDesc.Width, mDesc.Height);
   }
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
+  // This TextureClient should not be used in a context where we use CreateSimilar
+  // (ex. component alpha) because the underlying texture data is always created by
+  // an external producer.
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE { return nullptr; }
+
 private:
   RefPtr<IDirect3DTexture9> mTexture;
   gfx::SurfaceFormat mFormat;
   HANDLE mHandle;
   D3DSURFACE_DESC mDesc;
   bool mIsLocked;
 };
 
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -50,16 +50,31 @@ GrallocTextureClientOGL::~GrallocTexture
   ISurfaceAllocator* allocator = GetAllocator();
   if (ShouldDeallocateInDestructor()) {
     allocator->DeallocGrallocBuffer(&mGrallocHandle);
   } else {
     allocator->DropGrallocBuffer(&mGrallocHandle);
   }
 }
 
+TemporaryRef<TextureClient>
+GrallocTextureClientOGL::CreateSimilar(TextureFlags aFlags,
+                                       TextureAllocationFlags aAllocFlags) const
+{
+  RefPtr<TextureClient> tex = new GrallocTextureClientOGL(
+    mAllocator, mFormat, mBackend, mFlags | aFlags
+  );
+
+  if (!tex->AllocateForSurface(mSize, aAllocFlags)) {
+    return nullptr;
+  }
+
+  return tex;
+}
+
 void
 GrallocTextureClientOGL::InitWith(MaybeMagicGrallocBufferHandle aHandle, gfx::IntSize aSize)
 {
   MOZ_ASSERT(!IsAllocated());
   MOZ_ASSERT(IsValid());
   mGrallocHandle = aHandle;
   mGraphicBuffer = GetGraphicBufferFrom(aHandle);
   mSize = aSize;
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -109,16 +109,20 @@ public:
     mMediaBuffer = aMediaBuffer;
   }
 
   android::MediaBuffer* GetMediaBuffer()
   {
     return mMediaBuffer;
   }
 
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
+                TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
+
 protected:
   /**
    * Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
    */
   MaybeMagicGrallocBufferHandle mGrallocHandle;
 
   RefPtr<AsyncTransactionTracker> mRemoveFromCompositableTracker;
 
--- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
+++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
@@ -31,16 +31,22 @@ public:
   virtual bool IsAllocated() const MOZ_OVERRIDE { return !!mSurface; }
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
   virtual gfx::IntSize GetSize() const;
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
+  // This TextureClient should not be used in a context where we use CreateSimilar
+  // (ex. component alpha) because the underlying texture data is always created by
+  // an external producer.
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE { return nullptr; }
+
 protected:
   RefPtr<MacIOSurface> mSurface;
   bool mIsLocked;
 };
 
 }
 }
 
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -55,16 +55,22 @@ public:
 
   virtual gfx::IntSize GetSize() const { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
   {
     return gfx::SurfaceFormat::UNKNOWN;
   }
 
+  // This TextureClient should not be used in a context where we use CreateSimilar
+  // (ex. component alpha) because the underlying texture data is always created by
+  // an external producer.
+  virtual TemporaryRef<TextureClient>
+  CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE { return nullptr; }
+
   virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) MOZ_OVERRIDE
   {
     return false;
   }
 
 protected:
   gl::SharedTextureHandle mHandle;
   gfx::IntSize mSize;