From 75e8427d57cf9dbab486b9c0269556dcfcdb2042 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 2 Aug 2013 22:59:49 -0400 Subject: [PATCH] Bug 893302 - Implement CanvasClient2D on top of NewTextures. r=nical --- gfx/layers/client/CanvasClient.cpp | 45 ++++++++++++++++++++++++++- gfx/layers/client/CanvasClient.h | 30 ++++++++++++++++++ gfx/layers/client/ClientCanvasLayer.h | 1 + gfx/layers/client/TextureClient.cpp | 13 ++++++++ gfx/layers/client/TextureClient.h | 3 ++ 5 files changed, 91 insertions(+), 1 deletion(-) diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index 9d3b4a44b375..c04793b0b90a 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -30,7 +30,50 @@ CanvasClient::CreateCanvasClient(CanvasClientType aType, 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 surface = mBuffer->AsTextureClientSurface()->GetAsSurface(); + if (surface) { + aLayer->UpdateSurface(surface); + } + + mBuffer->Unlock(); + + if (surface) { + GetForwarder()->UpdatedTexture(this, mBuffer, nullptr); + GetForwarder()->UseTexture(this, mBuffer); + } } void diff --git a/gfx/layers/client/CanvasClient.h b/gfx/layers/client/CanvasClient.h index a9427702074e..023bddc7e340 100644 --- a/gfx/layers/client/CanvasClient.h +++ b/gfx/layers/client/CanvasClient.h @@ -51,6 +51,36 @@ protected: }; // 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 mBuffer; +}; class DeprecatedCanvasClient2D : public CanvasClient { public: diff --git a/gfx/layers/client/ClientCanvasLayer.h b/gfx/layers/client/ClientCanvasLayer.h index 19ee2c94e4fd..67bdaf64dfd1 100644 --- a/gfx/layers/client/ClientCanvasLayer.h +++ b/gfx/layers/client/ClientCanvasLayer.h @@ -87,6 +87,7 @@ protected: RefPtr mCanvasClient; friend class DeprecatedCanvasClient2D; + friend class CanvasClient2D; friend class DeprecatedCanvasClientSurfaceStream; }; } diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 85978384bd28..6eacbc0c3de0 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -175,6 +175,19 @@ BufferTextureClient::UpdateSurface(gfxASurface* aSurface) return true; } +already_AddRefed +BufferTextureClient::GetAsSurface() +{ + ImageDataSerializer serializer(GetBuffer()); + if (!serializer.IsValid()) { + return nullptr; + } + + RefPtr surf = serializer.GetAsThebesSurface(); + nsRefPtr result = surf.get(); + return result.forget(); +} + bool BufferTextureClient::AllocateForSurface(gfx::IntSize aSize) { diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index 4bb8f9ab6947..8e50ef70ed28 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -44,6 +44,7 @@ class TextureClientSurface { public: virtual bool UpdateSurface(gfxASurface* aSurface) = 0; + virtual already_AddRefed GetAsSurface() = 0; virtual bool AllocateForSurface(gfx::IntSize aSize) = 0; }; @@ -203,6 +204,8 @@ public: virtual bool UpdateSurface(gfxASurface* aSurface) MOZ_OVERRIDE; + virtual already_AddRefed GetAsSurface() MOZ_OVERRIDE; + virtual bool AllocateForSurface(gfx::IntSize aSize) MOZ_OVERRIDE; // TextureClientYCbCr