michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ClientThebesLayer.h" michael@0: #include "ClientTiledThebesLayer.h" // for ClientTiledThebesLayer michael@0: #include "SimpleTiledContentClient.h" michael@0: #include // for uint32_t michael@0: #include "GeckoProfiler.h" // for PROFILER_LABEL michael@0: #include "client/ClientLayerManager.h" // for ClientLayerManager, etc michael@0: #include "gfxContext.h" // for gfxContext michael@0: #include "gfxRect.h" // for gfxRect michael@0: #include "gfxPrefs.h" // for gfxPrefs michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc michael@0: #include "mozilla/gfx/2D.h" // for DrawTarget michael@0: #include "mozilla/gfx/Matrix.h" // for Matrix michael@0: #include "mozilla/gfx/Rect.h" // for Rect, IntRect michael@0: #include "mozilla/gfx/Types.h" // for Float, etc michael@0: #include "mozilla/layers/LayersTypes.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsCOMPtr.h" // for already_AddRefed michael@0: #include "nsISupportsImpl.h" // for Layer::AddRef, etc michael@0: #include "nsRect.h" // for nsIntRect michael@0: #include "gfx2DGlue.h" michael@0: michael@0: using namespace mozilla::gfx; michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: void michael@0: ClientThebesLayer::PaintThebes() michael@0: { michael@0: PROFILER_LABEL("ClientThebesLayer", "PaintThebes"); michael@0: NS_ASSERTION(ClientManager()->InDrawing(), michael@0: "Can only draw in drawing phase"); michael@0: michael@0: uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED; michael@0: #ifndef MOZ_WIDGET_ANDROID michael@0: if (ClientManager()->CompositorMightResample()) { michael@0: flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE; michael@0: } michael@0: if (!(flags & RotatedContentBuffer::PAINT_WILL_RESAMPLE)) { michael@0: if (MayResample()) { michael@0: flags |= RotatedContentBuffer::PAINT_WILL_RESAMPLE; michael@0: } michael@0: } michael@0: #endif michael@0: PaintState state = michael@0: mContentClient->BeginPaintBuffer(this, flags); michael@0: mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate); michael@0: michael@0: if (!state.mRegionToDraw.IsEmpty() && !ClientManager()->GetThebesLayerCallback()) { michael@0: ClientManager()->SetTransactionIncomplete(); michael@0: return; michael@0: } michael@0: michael@0: // The area that became invalid and is visible needs to be repainted michael@0: // (this could be the whole visible area if our buffer switched michael@0: // from RGB to RGBA, because we might need to repaint with michael@0: // subpixel AA) michael@0: state.mRegionToInvalidate.And(state.mRegionToInvalidate, michael@0: GetEffectiveVisibleRegion()); michael@0: michael@0: bool didUpdate = false; michael@0: RotatedContentBuffer::DrawIterator iter; michael@0: while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) { michael@0: SetAntialiasingFlags(this, target); michael@0: michael@0: nsRefPtr ctx = gfxContext::ContextForDrawTarget(target); michael@0: michael@0: ClientManager()->GetThebesLayerCallback()(this, michael@0: ctx, michael@0: iter.mDrawRegion, michael@0: state.mClip, michael@0: state.mRegionToInvalidate, michael@0: ClientManager()->GetThebesLayerCallbackData()); michael@0: michael@0: ctx = nullptr; michael@0: mContentClient->ReturnDrawTargetToBuffer(target); michael@0: didUpdate = true; michael@0: } michael@0: michael@0: if (didUpdate) { michael@0: Mutated(); michael@0: michael@0: mValidRegion.Or(mValidRegion, state.mRegionToDraw); michael@0: michael@0: ContentClientRemote* contentClientRemote = static_cast(mContentClient.get()); michael@0: MOZ_ASSERT(contentClientRemote->GetIPDLActor()); michael@0: michael@0: // Hold(this) ensures this layer is kept alive through the current transaction michael@0: // The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer), michael@0: // so deleting this Hold for whatever reason will break things. michael@0: ClientManager()->Hold(this); michael@0: contentClientRemote->Updated(state.mRegionToDraw, michael@0: mVisibleRegion, michael@0: state.mDidSelfCopy); michael@0: } michael@0: } michael@0: michael@0: void michael@0: ClientThebesLayer::RenderLayer() michael@0: { michael@0: if (GetMaskLayer()) { michael@0: ToClientLayer(GetMaskLayer())->RenderLayer(); michael@0: } michael@0: michael@0: if (!mContentClient) { michael@0: mContentClient = ContentClient::CreateContentClient(ClientManager()->AsShadowForwarder()); michael@0: if (!mContentClient) { michael@0: return; michael@0: } michael@0: mContentClient->Connect(); michael@0: ClientManager()->AsShadowForwarder()->Attach(mContentClient, this); michael@0: MOZ_ASSERT(mContentClient->GetForwarder()); michael@0: } michael@0: michael@0: mContentClient->BeginPaint(); michael@0: PaintThebes(); michael@0: mContentClient->EndPaint(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: ClientLayerManager::CreateThebesLayer() michael@0: { michael@0: return CreateThebesLayerWithHint(NONE); michael@0: } michael@0: michael@0: already_AddRefed michael@0: ClientLayerManager::CreateThebesLayerWithHint(ThebesLayerCreationHint aHint) michael@0: { michael@0: NS_ASSERTION(InConstruction(), "Only allowed in construction phase"); michael@0: if ( michael@0: #ifdef MOZ_B2G michael@0: aHint == SCROLLABLE && michael@0: #endif michael@0: gfxPrefs::LayersTilesEnabled() && michael@0: (AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL || michael@0: AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9 || michael@0: AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D11)) { michael@0: if (gfxPrefs::LayersUseSimpleTiles()) { michael@0: nsRefPtr layer = michael@0: new SimpleClientTiledThebesLayer(this); michael@0: CREATE_SHADOW(Thebes); michael@0: return layer.forget(); michael@0: } else { michael@0: nsRefPtr layer = michael@0: new ClientTiledThebesLayer(this); michael@0: CREATE_SHADOW(Thebes); michael@0: return layer.forget(); michael@0: } michael@0: } else michael@0: { michael@0: nsRefPtr layer = michael@0: new ClientThebesLayer(this); michael@0: CREATE_SHADOW(Thebes); michael@0: return layer.forget(); michael@0: } michael@0: } michael@0: michael@0: michael@0: } michael@0: }