Bug 893302 - Implement CanvasClient2D on top of NewTextures. r=nical
authorMatt Woodrow <mwoodrow@mozilla.com>
Sat, 03 Aug 2013 13:29:37 -0400
changeset 153587 760e66b2908e70886892d68a45dbc7045bb5dec9
parent 153586 a525086d0bf298fa8d0d4f751eebb5c9273c6187
child 153588 fa5a3c887c7b07c15877167052705f6854bcfe01
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs893302
milestone25.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 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;