Bug 893302 - Implement CanvasClient2D on top of NewTextures. r=nical
authorMatt Woodrow <mwoodrow@mozilla.com>
Sat, 03 Aug 2013 13:29:37 -0400
changeset 148881 760e66b2908e70886892d68a45dbc7045bb5dec9
parent 148880 a525086d0bf298fa8d0d4f751eebb5c9273c6187
child 148882 fa5a3c887c7b07c15877167052705f6854bcfe01
push idunknown
push userunknown
push dateunknown
reviewersnical
bugs893302
milestone25.0a1
Bug 893302 - Implement CanvasClient2D on top of NewTextures. r=nical
gfx/layers/client/CanvasClient.cpp
gfx/layers/client/CanvasClient.h
gfx/layers/client/ClientCanvasLayer.h
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -25,17 +25,60 @@ namespace layers {
 CanvasClient::CreateCanvasClient(CanvasClientType aType,
                                  CompositableForwarder* aForwarder,
                                  TextureFlags aFlags)
 {
   if (aType == CanvasClientGLContext &&
       aForwarder->GetCompositorBackendType() == LAYERS_OPENGL) {
     return new DeprecatedCanvasClientSurfaceStream(aForwarder, aFlags);
   }
-  return new DeprecatedCanvasClient2D(aForwarder, aFlags);
+  if (gfxPlatform::GetPlatform()->UseDeprecatedTextures()) {
+    return new DeprecatedCanvasClient2D(aForwarder, aFlags);
+  }
+  return new CanvasClient2D(aForwarder, aFlags);
+}
+
+void
+CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
+{
+  if (mBuffer &&
+      (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
+    RemoveTextureClient(mBuffer);
+    mBuffer = nullptr;
+  }
+
+  if (!mBuffer) {
+    bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
+    gfxASurface::gfxContentType contentType = isOpaque
+                                                ? gfxASurface::CONTENT_COLOR
+                                                : gfxASurface::CONTENT_COLOR_ALPHA;
+    gfxASurface::gfxImageFormat format
+      = gfxPlatform::GetPlatform()->OptimalFormatForContent(contentType);
+    mBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format));
+    MOZ_ASSERT(mBuffer->AsTextureClientSurface());
+    mBuffer->AsTextureClientSurface()->AllocateForSurface(aSize);
+
+    AddTextureClient(mBuffer);
+  }
+
+  if (!mBuffer->Lock(OPEN_READ_WRITE)) {
+    return;
+  }
+
+  nsRefPtr<gfxASurface> surface = mBuffer->AsTextureClientSurface()->GetAsSurface();
+  if (surface) {
+    aLayer->UpdateSurface(surface);
+  }
+
+  mBuffer->Unlock();
+
+  if (surface) {
+    GetForwarder()->UpdatedTexture(this, mBuffer, nullptr);
+    GetForwarder()->UseTexture(this, mBuffer);
+  }
 }
 
 void
 DeprecatedCanvasClient2D::Updated()
 {
   mForwarder->UpdateTexture(this, 1, mDeprecatedTextureClient->GetDescriptor());
 }
 
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -46,16 +46,46 @@ public:
 
   virtual void Updated() { }
 
 protected:
   TextureInfo mTextureInfo;
 };
 
 // Used for 2D canvases and WebGL canvas on non-GL systems where readback is requried.
+class CanvasClient2D : public CanvasClient
+{
+public:
+  CanvasClient2D(CompositableForwarder* aLayerForwarder,
+                 TextureFlags aFlags)
+    : CanvasClient(aLayerForwarder, aFlags)
+  {
+  }
+
+  TextureInfo GetTextureInfo() const
+  {
+    return TextureInfo(COMPOSITABLE_IMAGE);
+  }
+
+  virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
+
+  virtual void AddTextureClient(TextureClient* aTexture) MOZ_OVERRIDE
+  {
+    aTexture->AddFlags(mTextureInfo.mTextureFlags);
+    CompositableClient::AddTextureClient(aTexture);
+  }
+
+  virtual void Detach() MOZ_OVERRIDE
+  {
+    mBuffer = nullptr;
+  }
+
+private:
+  RefPtr<TextureClient> mBuffer;
+};
 class DeprecatedCanvasClient2D : public CanvasClient
 {
 public:
   DeprecatedCanvasClient2D(CompositableForwarder* aLayerForwarder,
                            TextureFlags aFlags);
 
   TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -82,14 +82,15 @@ protected:
       return CanvasClient::CanvasClientGLContext;
     }
     return CanvasClient::CanvasClientSurface;
   }
 
   RefPtr<CanvasClient> mCanvasClient;
 
   friend class DeprecatedCanvasClient2D;
+  friend class CanvasClient2D;
   friend class DeprecatedCanvasClientSurfaceStream;
 };
 }
 }
 
 #endif
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -170,16 +170,29 @@ BufferTextureClient::UpdateSurface(gfxAS
 
   nsRefPtr<gfxContext> tmpCtx = new gfxContext(surf.get());
   tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
   tmpCtx->DrawSurface(aSurface, gfxSize(serializer.GetSize().width,
                                         serializer.GetSize().height));
   return true;
 }
 
+already_AddRefed<gfxASurface>
+BufferTextureClient::GetAsSurface()
+{
+  ImageDataSerializer serializer(GetBuffer());
+  if (!serializer.IsValid()) {
+    return nullptr;
+  }
+
+  RefPtr<gfxImageSurface> surf = serializer.GetAsThebesSurface();
+  nsRefPtr<gfxASurface> result = surf.get();
+  return result.forget();
+}
+
 bool
 BufferTextureClient::AllocateForSurface(gfx::IntSize aSize)
 {
   MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This textureClient cannot use YCbCr data");
 
   int bufSize
     = ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
   if (!Allocate(bufSize)) {
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -39,16 +39,17 @@ class CompositableClient;
 
 /**
  * Interface for TextureClients that can be updated using a gfxASurface.
  */
 class TextureClientSurface
 {
 public:
   virtual bool UpdateSurface(gfxASurface* aSurface) = 0;
+  virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
   virtual bool AllocateForSurface(gfx::IntSize aSize) = 0;
 };
 
 /**
  * Interface for TextureClients that can be updated using YCbCr data.
  */
 class TextureClientYCbCr
 {
@@ -198,16 +199,18 @@ public:
   virtual gfx::IntSize GetSize() const { return mSize; }
 
   // TextureClientSurface
 
   virtual TextureClientSurface* AsTextureClientSurface() MOZ_OVERRIDE { return this; }
 
   virtual bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE;
 
+  virtual already_AddRefed<gfxASurface> GetAsSurface() MOZ_OVERRIDE;
+
   virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE;
 
   // TextureClientYCbCr
 
   virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; }
 
   virtual bool UpdateYCbCr(const PlanarYCbCrImage::Data& aData) MOZ_OVERRIDE;