From c4ddbf3f5928bb46624edb52038c30d007ccf6e2 Mon Sep 17 00:00:00 2001 From: "Anthony Jones ext:(%2C%20George%20Wright%20%3Cgwright%40mozilla.com%3E)" Date: Wed, 14 Aug 2013 16:31:05 +1200 Subject: [PATCH] Bug 750434 - Add support for Azure content rendering to ClientTiledThebesLayer. r=mattwoodrow,BenWa --- gfx/layers/client/TiledContentClient.cpp | 94 +++++++++++++++++++----- gfx/layers/client/TiledContentClient.h | 1 + gfx/thebes/gfxPlatform.cpp | 8 +- 3 files changed, 82 insertions(+), 21 deletions(-) diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 1d3170ff104..b4b6e151cf5 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -233,16 +233,34 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, */ if (useSinglePaintBuffer) { + nsRefPtr ctxt; + const nsIntRect bounds = aPaintRegion.GetBounds(); { PROFILER_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferAlloc"); - mSinglePaintBuffer = new gfxImageSurface( - gfxIntSize(ceilf(bounds.width * mResolution), - ceilf(bounds.height * mResolution)), - gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType()), !mThebesLayer->CanUseOpaqueSurface()); + gfxASurface::gfxImageFormat format = + gfxPlatform::GetPlatform()->OptimalFormatForContent( + GetContentType()); + + if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { + mSinglePaintDrawTarget = + gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( + gfx::IntSize(ceilf(bounds.width * mResolution), + ceilf(bounds.height * mResolution)), + gfx::ImageFormatToSurfaceFormat(format)); + + ctxt = new gfxContext(mSinglePaintDrawTarget); + } else { + mSinglePaintBuffer = new gfxImageSurface( + gfxIntSize(ceilf(bounds.width * mResolution), + ceilf(bounds.height * mResolution)), + format, + !mThebesLayer->CanUseOpaqueSurface()); + ctxt = new gfxContext(mSinglePaintBuffer); + } + mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y); } - nsRefPtr ctxt = new gfxContext(mSinglePaintBuffer); ctxt->NewPath(); ctxt->Scale(mResolution, mResolution); ctxt->Translate(gfxPoint(-bounds.x, -bounds.y)); @@ -286,6 +304,7 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, mCallback = nullptr; mCallbackData = nullptr; mSinglePaintBuffer = nullptr; + mSinglePaintDrawTarget = nullptr; } BasicTiledLayerTile @@ -299,24 +318,61 @@ BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile, aTile.mDeprecatedTextureClient = static_cast(textureClient.get()); } aTile.mDeprecatedTextureClient->EnsureAllocated(gfx::IntSize(GetTileLength(), GetTileLength()), GetContentType()); - gfxASurface* writableSurface = aTile.mDeprecatedTextureClient->LockImageSurface(); + gfxImageSurface* writableSurface = aTile.mDeprecatedTextureClient->LockImageSurface(); // Bug 742100, this gfxContext really should live on the stack. - nsRefPtr ctxt = new gfxContext(writableSurface); + nsRefPtr ctxt; - if (mSinglePaintBuffer) { - gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y, - aDirtyRect.width, aDirtyRect.height); + RefPtr writableDrawTarget; + if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { + // TODO: Instead of creating a gfxImageSurface to back the tile we should + // create an offscreen DrawTarget. This would need to be shared cross-thread + // and support copy on write semantics. + gfx::SurfaceFormat format = + gfx::ImageFormatToSurfaceFormat(writableSurface->Format()); + writableDrawTarget = + gfxPlatform::GetPlatform()->CreateDrawTargetForData( + writableSurface->Data(), + gfx::IntSize(writableSurface->Width(), writableSurface->Height()), + writableSurface->Stride(), + format); + ctxt = new gfxContext(writableDrawTarget); + } else { + ctxt = new gfxContext(writableSurface); ctxt->SetOperator(gfxContext::OPERATOR_SOURCE); - ctxt->NewPath(); - ctxt->SetSource(mSinglePaintBuffer.get(), - gfxPoint((mSinglePaintBufferOffset.x - aDirtyRect.x + drawRect.x) * - mResolution, - (mSinglePaintBufferOffset.y - aDirtyRect.y + drawRect.y) * - mResolution)); - drawRect.Scale(mResolution, mResolution); - ctxt->Rectangle(drawRect, true); - ctxt->Fill(); + } + + gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y, + aDirtyRect.width, aDirtyRect.height); + + if (mSinglePaintBuffer || mSinglePaintDrawTarget) { + if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { + gfx::Rect drawRect(aDirtyRect.x - aTileOrigin.x, + aDirtyRect.y - aTileOrigin.y, + aDirtyRect.width, + aDirtyRect.height); + drawRect.Scale(mResolution); + + RefPtr source = mSinglePaintDrawTarget->Snapshot(); + writableDrawTarget->CopySurface( + source, + gfx::IntRect(roundf((aDirtyRect.x - mSinglePaintBufferOffset.x) * mResolution), + roundf((aDirtyRect.y - mSinglePaintBufferOffset.y) * mResolution), + drawRect.width, + drawRect.height), + gfx::IntPoint(roundf(drawRect.x), roundf(drawRect.y))); + } else { + gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y, + aDirtyRect.width, aDirtyRect.height); + drawRect.Scale(mResolution, mResolution); + + ctxt->NewPath(); + ctxt->SetSource(mSinglePaintBuffer.get(), + gfxPoint((mSinglePaintBufferOffset.x - aDirtyRect.x) * mResolution + drawRect.x, + (mSinglePaintBufferOffset.y - aDirtyRect.y) * mResolution + drawRect.y)); + ctxt->SnappedRectangle(drawRect); + ctxt->Fill(); + } } else { ctxt->NewPath(); ctxt->Scale(mResolution, mResolution); diff --git a/gfx/layers/client/TiledContentClient.h b/gfx/layers/client/TiledContentClient.h index 96a648fa3dc..94e3b78f8ba 100644 --- a/gfx/layers/client/TiledContentClient.h +++ b/gfx/layers/client/TiledContentClient.h @@ -230,6 +230,7 @@ private: // The buffer we use when UseSinglePaintBuffer() above is true. nsRefPtr mSinglePaintBuffer; + RefPtr mSinglePaintDrawTarget; nsIntPoint mSinglePaintBufferOffset; BasicTiledLayerTile ValidateTileInternal(BasicTiledLayerTile aTile, diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index a3fc2bed1e2..306381514fb 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -903,8 +903,12 @@ gfxPlatform::CreateOffscreenContentDrawTarget(const IntSize& aSize, SurfaceForma RefPtr gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat) { - NS_ASSERTION(mPreferredCanvasBackend, "No backend."); - return Factory::CreateDrawTargetForData(mPreferredCanvasBackend, aData, aSize, aStride, aFormat); + NS_ASSERTION(mContentBackend, "No backend."); + if (mContentBackend == BACKEND_CAIRO) { + nsRefPtr image = new gfxImageSurface(aData, gfxIntSize(aSize.width, aSize.height), aStride, SurfaceFormatToImageFormat(aFormat)); + return Factory::CreateDrawTargetForCairoSurface(image->CairoSurface(), aSize); + } + return Factory::CreateDrawTargetForData(mContentBackend, aData, aSize, aStride, aFormat); } /* static */ BackendType