/* -*- Mode: C++; tab-width: 2; 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 "ClientPaintedLayer.h" #include "ClientTiledPaintedLayer.h" // for ClientTiledPaintedLayer #include <stdint.h> // for uint32_t #include "GeckoProfiler.h" // for PROFILER_LABEL #include "client/ClientLayerManager.h" // for ClientLayerManager, etc #include "gfxContext.h" // for gfxContext #include "gfxRect.h" // for gfxRect #include "gfxPrefs.h" // for gfxPrefs #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/gfx/2D.h" // for DrawTarget #include "mozilla/gfx/Matrix.h" // for Matrix #include "mozilla/gfx/Rect.h" // for Rect, IntRect #include "mozilla/gfx/Types.h" // for Float, etc #include "mozilla/layers/LayersTypes.h" #include "mozilla/Preferences.h" #include "nsCOMPtr.h" // for already_AddRefed #include "nsISupportsImpl.h" // for Layer::AddRef, etc #include "nsRect.h" // for mozilla::gfx::IntRect #include "gfx2DGlue.h" #include "ReadbackProcessor.h" namespace mozilla { namespace layers { using namespace mozilla::gfx; void ClientPaintedLayer::PaintThebes() { PROFILER_LABEL("ClientPaintedLayer", "PaintThebes", js::ProfileEntry::Category::GRAPHICS); NS_ASSERTION(ClientManager()->InDrawing(), "Can only draw in drawing phase"); uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED; #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE if (ClientManager()->CompositorMightResample()) { flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE; } if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) { if (MayResample()) { flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE; } } #endif PaintState state = mContentClient->BeginPaintBuffer(this, flags); mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); if (!state.mRegionToDraw.IsEmpty() && !ClientManager()->GetPaintedLayerCallback()) { ClientManager()->SetTransactionIncomplete(); return; } // The area that became invalid and is visible needs to be repainted // (this could be the whole visible area if our buffer switched // from RGB to RGBA, because we might need to repaint with // subpixel AA) state.mRegionToInvalidate.And(state.mRegionToInvalidate, GetLocalVisibleRegion().ToUnknownRegion()); bool didUpdate = false; RotatedContentBuffer::DrawIterator iter; while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) { if (!target || !target->IsValid()) { if (target) { mContentClient->ReturnDrawTargetToBuffer(target); } continue; } SetAntialiasingFlags(this, target); RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target); MOZ_ASSERT(ctx); // already checked the target above ClientManager()->GetPaintedLayerCallback()(this, ctx, iter.mDrawRegion, iter.mDrawRegion, state.mClip, state.mRegionToInvalidate, ClientManager()->GetPaintedLayerCallbackData()); ctx = nullptr; mContentClient->ReturnDrawTargetToBuffer(target); didUpdate = true; } if (didUpdate) { Mutated(); mValidRegion.Or(mValidRegion, state.mRegionToDraw); ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get()); MOZ_ASSERT(contentClientRemote->GetIPDLActor()); // Hold(this) ensures this layer is kept alive through the current transaction // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer), // so deleting this Hold for whatever reason will break things. ClientManager()->Hold(this); contentClientRemote->Updated(state.mRegionToDraw, mVisibleRegion.ToUnknownRegion(), state.mDidSelfCopy); } } void ClientPaintedLayer::RenderLayerWithReadback(ReadbackProcessor *aReadback) { RenderMaskLayers(this); if (!mContentClient) { mContentClient = ContentClient::CreateContentClient(ClientManager()->AsShadowForwarder()); if (!mContentClient) { return; } mContentClient->Connect(); ClientManager()->AsShadowForwarder()->Attach(mContentClient, this); MOZ_ASSERT(mContentClient->GetForwarder()); } nsTArray<ReadbackProcessor::Update> readbackUpdates; nsIntRegion readbackRegion; if (aReadback && UsedForReadback()) { aReadback->GetPaintedLayerUpdates(this, &readbackUpdates); } IntPoint origin(mVisibleRegion.GetBounds().x, mVisibleRegion.GetBounds().y); mContentClient->BeginPaint(); PaintThebes(); mContentClient->EndPaint(&readbackUpdates); } already_AddRefed<PaintedLayer> ClientLayerManager::CreatePaintedLayer() { return CreatePaintedLayerWithHint(NONE); } already_AddRefed<PaintedLayer> ClientLayerManager::CreatePaintedLayerWithHint(PaintedLayerCreationHint aHint) { NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); if (gfxPrefs::LayersTilesEnabled()) { RefPtr<ClientTiledPaintedLayer> layer = new ClientTiledPaintedLayer(this, aHint); CREATE_SHADOW(Painted); return layer.forget(); } else { RefPtr<ClientPaintedLayer> layer = new ClientPaintedLayer(this, aHint); CREATE_SHADOW(Painted); return layer.forget(); } } void ClientPaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix) { PaintedLayer::PrintInfo(aStream, aPrefix); if (mContentClient) { aStream << "\n"; nsAutoCString pfx(aPrefix); pfx += " "; mContentClient->PrintInfo(aStream, pfx.get()); } } } // namespace layers } // namespace mozilla