summaryrefslogtreecommitdiffstats
path: root/gfx/layers/client/SingleTiledContentClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/client/SingleTiledContentClient.cpp')
-rw-r--r--gfx/layers/client/SingleTiledContentClient.cpp263
1 files changed, 263 insertions, 0 deletions
diff --git a/gfx/layers/client/SingleTiledContentClient.cpp b/gfx/layers/client/SingleTiledContentClient.cpp
new file mode 100644
index 000000000..bcc8691cf
--- /dev/null
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/layers/SingleTiledContentClient.h"
+
+#include "ClientTiledPaintedLayer.h"
+
+namespace mozilla {
+namespace layers {
+
+
+SingleTiledContentClient::SingleTiledContentClient(ClientTiledPaintedLayer& aPaintedLayer,
+ ClientLayerManager* aManager)
+ : TiledContentClient(aManager, "Single")
+{
+ MOZ_COUNT_CTOR(SingleTiledContentClient);
+
+ mTiledBuffer = new ClientSingleTiledLayerBuffer(aPaintedLayer, *this, aManager);
+}
+
+void
+SingleTiledContentClient::ClearCachedResources()
+{
+ CompositableClient::ClearCachedResources();
+ mTiledBuffer->DiscardBuffers();
+}
+
+void
+SingleTiledContentClient::UpdatedBuffer(TiledBufferType aType)
+{
+ mForwarder->UseTiledLayerBuffer(this, mTiledBuffer->GetSurfaceDescriptorTiles());
+ mTiledBuffer->ClearPaintedRegion();
+}
+
+/* static */ bool
+SingleTiledContentClient::ClientSupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager)
+{
+ int32_t maxTextureSize = aManager->GetMaxTextureSize();
+ return aSize.width <= maxTextureSize && aSize.height <= maxTextureSize;
+}
+
+ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer,
+ CompositableClient& aCompositableClient,
+ ClientLayerManager* aManager)
+ : ClientTiledLayerBuffer(aPaintedLayer, aCompositableClient)
+ , mWasLastPaintProgressive(false)
+ , mFormat(gfx::SurfaceFormat::UNKNOWN)
+{
+}
+
+void
+ClientSingleTiledLayerBuffer::ReleaseTiles()
+{
+ if (!mTile.IsPlaceholderTile()) {
+ mTile.DiscardBuffers();
+ }
+ mTile.SetTextureAllocator(nullptr);
+}
+
+void
+ClientSingleTiledLayerBuffer::DiscardBuffers()
+{
+ if (!mTile.IsPlaceholderTile()) {
+ mTile.DiscardFrontBuffer();
+ mTile.DiscardBackBuffer();
+ }
+}
+
+SurfaceDescriptorTiles
+ClientSingleTiledLayerBuffer::GetSurfaceDescriptorTiles()
+{
+ InfallibleTArray<TileDescriptor> tiles;
+
+ TileDescriptor tileDesc = mTile.GetTileDescriptor();
+ tiles.AppendElement(tileDesc);
+ mTile.mUpdateRect = gfx::IntRect();
+
+ return SurfaceDescriptorTiles(mValidRegion,
+ tiles,
+ mTilingOrigin,
+ mSize,
+ 0, 0, 1, 1,
+ 1.0,
+ mFrameResolution.xScale,
+ mFrameResolution.yScale,
+ mWasLastPaintProgressive);
+}
+
+already_AddRefed<TextureClient>
+ClientSingleTiledLayerBuffer::GetTextureClient()
+{
+ MOZ_ASSERT(mFormat != gfx::SurfaceFormat::UNKNOWN);
+ return mCompositableClient.CreateTextureClientForDrawing(
+ gfx::ImageFormatToSurfaceFormat(mFormat), mSize, BackendSelector::Content,
+ TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD);
+}
+
+void
+ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
+ const nsIntRegion& aPaintRegion,
+ const nsIntRegion& aDirtyRegion,
+ LayerManager::DrawPaintedLayerCallback aCallback,
+ void* aCallbackData,
+ bool aIsProgressive)
+{
+ mWasLastPaintProgressive = aIsProgressive;
+
+ // Compare layer valid region size to current backbuffer size, discard if not matching.
+ gfx::IntSize size = aNewValidRegion.GetBounds().Size();
+ gfx::IntPoint origin = aNewValidRegion.GetBounds().TopLeft();
+ nsIntRegion paintRegion = aPaintRegion;
+
+ RefPtr<TextureClient> discardedFrontBuffer = nullptr;
+ RefPtr<TextureClient> discardedFrontBufferOnWhite = nullptr;
+ nsIntRegion discardedValidRegion;
+
+ if (mSize != size ||
+ mTilingOrigin != origin) {
+ discardedFrontBuffer = mTile.mFrontBuffer;
+ discardedFrontBufferOnWhite = mTile.mFrontBufferOnWhite;
+ discardedValidRegion = mValidRegion;
+
+ TILING_LOG("TILING %p: Single-tile valid region changed. Discarding buffers.\n", &mPaintedLayer)
+;
+ ResetPaintedAndValidState();
+ mSize = size;
+ mTilingOrigin = origin;
+ paintRegion = aNewValidRegion;
+ }
+
+ SurfaceMode mode;
+ gfxContentType content = GetContentType(&mode);
+ mFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(content);
+
+ if (mTile.IsPlaceholderTile()) {
+ mTile.SetTextureAllocator(this);
+ }
+
+ // The dirty region relative to the top-left of the tile.
+ nsIntRegion tileDirtyRegion = paintRegion.MovedBy(-mTilingOrigin);
+
+ nsIntRegion extraPainted;
+ RefPtr<TextureClient> backBufferOnWhite;
+ RefPtr<TextureClient> backBuffer =
+ mTile.GetBackBuffer(mCompositableClient,
+ tileDirtyRegion,
+ content, mode,
+ extraPainted,
+ &backBufferOnWhite);
+
+ mTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
+
+ extraPainted.MoveBy(mTilingOrigin);
+ extraPainted.And(extraPainted, aNewValidRegion);
+ mPaintedRegion.OrWith(paintRegion);
+ mPaintedRegion.OrWith(extraPainted);
+
+ if (!backBuffer) {
+ return;
+ }
+
+ RefPtr<gfx::DrawTarget> dt = backBuffer->BorrowDrawTarget();
+ RefPtr<gfx::DrawTarget> dtOnWhite;
+ if (backBufferOnWhite) {
+ dtOnWhite = backBufferOnWhite->BorrowDrawTarget();
+ }
+
+ if (mode != SurfaceMode::SURFACE_OPAQUE) {
+ for (auto iter = tileDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const gfx::IntRect& rect = iter.Get();
+ if (dtOnWhite) {
+ dt->FillRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height),
+ gfx::ColorPattern(gfx::Color(0.0, 0.0, 0.0, 1.0)));
+ dtOnWhite->FillRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height),
+ gfx::ColorPattern(gfx::Color(1.0, 1.0, 1.0, 1.0)));
+ } else {
+ dt->ClearRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height));
+ }
+ }
+ }
+
+ // If the old frontbuffer was discarded then attempt to copy what we
+ // can from it to the new backbuffer.
+ if (discardedFrontBuffer) {
+ nsIntRegion copyableRegion;
+ copyableRegion.And(aNewValidRegion, discardedValidRegion);
+ copyableRegion.SubOut(aDirtyRegion);
+
+ if (!copyableRegion.IsEmpty()) {
+ TextureClientAutoLock frontLock(discardedFrontBuffer,
+ OpenMode::OPEN_READ);
+ if (frontLock.Succeeded()) {
+ for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
+ const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
+ discardedFrontBuffer->CopyToTextureClient(backBuffer, &rect, &dest);
+ }
+ }
+
+ if (discardedFrontBufferOnWhite && backBufferOnWhite) {
+ TextureClientAutoLock frontOnWhiteLock(discardedFrontBufferOnWhite,
+ OpenMode::OPEN_READ);
+ if (frontOnWhiteLock.Succeeded()) {
+ for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
+ const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
+
+ discardedFrontBufferOnWhite->CopyToTextureClient(backBufferOnWhite,
+ &rect, &dest);
+ }
+ }
+ }
+
+ TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
+
+ // We don't need to repaint valid content that was just copied.
+ paintRegion.SubOut(copyableRegion);
+ }
+ }
+
+ if (dtOnWhite) {
+ dt = gfx::Factory::CreateDualDrawTarget(dt, dtOnWhite);
+ dtOnWhite = nullptr;
+ }
+
+ {
+ RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
+ if (!ctx) {
+ gfxDevCrash(gfx::LogReason::InvalidContext) << "SingleTiledContextClient context problem " << gfx::hexa(dt);
+ return;
+ }
+ ctx->SetMatrix(ctx->CurrentMatrix().Translate(-mTilingOrigin.x, -mTilingOrigin.y));
+
+ aCallback(&mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
+ }
+
+ // Mark the area we just drew into the back buffer as invalid in the front buffer as they're
+ // now out of sync.
+ mTile.mInvalidFront.OrWith(tileDirtyRegion);
+
+ // The new buffer is now validated, remove the dirty region from it.
+ mTile.mInvalidBack.SubOut(tileDirtyRegion);
+
+ dt = nullptr;
+
+ mTile.Flip();
+ UnlockTile(mTile);
+
+ if (backBuffer->HasIntermediateBuffer()) {
+ // If our new buffer has an internal buffer, we don't want to keep another
+ // TextureClient around unnecessarily, so discard the back-buffer.
+ mTile.DiscardBackBuffer();
+ }
+
+ mValidRegion = aNewValidRegion;
+ mLastPaintSurfaceMode = mode;
+ mLastPaintContentType = content;
+}
+
+} // namespace layers
+} // namespace mozilla