/* -*- 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/. */ #ifndef GFX_BASICTHEBESLAYER_H #define GFX_BASICTHEBESLAYER_H #include "mozilla/layers/PLayersParent.h" #include "BasicBuffers.h" namespace mozilla { namespace layers { class BasicThebesLayer : public ThebesLayer, public BasicImplData { public: typedef BasicThebesLayerBuffer Buffer; BasicThebesLayer(BasicLayerManager* aLayerManager) : ThebesLayer(aLayerManager, static_cast(this)), mBuffer(this) { MOZ_COUNT_CTOR(BasicThebesLayer); } virtual ~BasicThebesLayer() { MOZ_COUNT_DTOR(BasicThebesLayer); } virtual void SetVisibleRegion(const nsIntRegion& aRegion) { NS_ASSERTION(BasicManager()->InConstruction(), "Can only set properties in construction phase"); ThebesLayer::SetVisibleRegion(aRegion); } virtual void InvalidateRegion(const nsIntRegion& aRegion) { NS_ASSERTION(BasicManager()->InConstruction(), "Can only set properties in construction phase"); mInvalidRegion.Or(mInvalidRegion, aRegion); mInvalidRegion.SimplifyOutward(10); mValidRegion.Sub(mValidRegion, mInvalidRegion); } virtual void PaintThebes(gfxContext* aContext, Layer* aMaskLayer, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData, ReadbackProcessor* aReadback); virtual void ClearCachedResources() { mBuffer.Clear(); mValidRegion.SetEmpty(); } virtual already_AddRefed CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize); virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) { if (!BasicManager()->IsRetained()) { // Don't do any snapping of our transform, since we're just going to // draw straight through without intermediate buffers. mEffectiveTransform = GetLocalTransform()*aTransformToSurface; if (gfxPoint(0,0) != mResidualTranslation) { mResidualTranslation = gfxPoint(0,0); mValidRegion.SetEmpty(); } ComputeEffectiveTransformForMaskLayer(aTransformToSurface); return; } ThebesLayer::ComputeEffectiveTransforms(aTransformToSurface); } // Sync front/back buffers content virtual void SyncFrontBufferToBackBuffer() {} protected: BasicLayerManager* BasicManager() { return static_cast(mManager); } virtual void PaintBuffer(gfxContext* aContext, const nsIntRegion& aRegionToDraw, const nsIntRegion& aExtendedRegionToDraw, const nsIntRegion& aRegionToInvalidate, bool aDidSelfCopy, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData) { if (!aCallback) { BasicManager()->SetTransactionIncomplete(); return; } aCallback(this, aContext, aExtendedRegionToDraw, aRegionToInvalidate, aCallbackData); // Everything that's visible has been validated. Do this instead of just // OR-ing with aRegionToDraw, since that can lead to a very complex region // here (OR doesn't automatically simplify to the simplest possible // representation of a region.) nsIntRegion tmp; tmp.Or(mVisibleRegion, aExtendedRegionToDraw); mValidRegion.Or(mValidRegion, tmp); } Buffer mBuffer; }; struct AutoBufferTracker; class BasicShadowableThebesLayer : public BasicThebesLayer, public BasicShadowableLayer { friend struct AutoBufferTracker; typedef BasicThebesLayer Base; public: BasicShadowableThebesLayer(BasicShadowLayerManager* aManager) : BasicThebesLayer(aManager) , mBufferTracker(nullptr) , mIsNewBuffer(false) , mFrontAndBackBufferDiffer(false) { MOZ_COUNT_CTOR(BasicShadowableThebesLayer); } virtual ~BasicShadowableThebesLayer(); virtual void PaintThebes(gfxContext* aContext, Layer* aMaskLayer, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData, ReadbackProcessor* aReadback); virtual void ClearCachedResources() MOZ_OVERRIDE { BasicThebesLayer::ClearCachedResources(); DestroyBackBuffer(); // Don't try to read back from this, it soon may be invalid. mROFrontBuffer = null_t(); mFrontAndBackBufferDiffer = false; } virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { aAttrs = ThebesLayerAttributes(GetValidRegion()); } virtual Layer* AsLayer() { return this; } virtual ShadowableLayer* AsShadowableLayer() { return this; } void SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer, const nsIntRegion& aValidRegion, const OptionalThebesBuffer& aReadOnlyFrontBuffer, const nsIntRegion& aFrontUpdatedRegion); virtual void Disconnect(); virtual BasicShadowableThebesLayer* AsThebes() { return this; } virtual void SyncFrontBufferToBackBuffer(); private: BasicShadowLayerManager* BasicManager() { return static_cast(mManager); } virtual void PaintBuffer(gfxContext* aContext, const nsIntRegion& aRegionToDraw, const nsIntRegion& aExtendedRegionToDraw, const nsIntRegion& aRegionToInvalidate, bool aDidSelfCopy, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData) MOZ_OVERRIDE; virtual already_AddRefed CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE; void DestroyBackBuffer() { if (IsSurfaceDescriptorValid(mBackBuffer)) { BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer); } } // This describes the gfxASurface we hand to mBuffer. We keep a // copy of the descriptor here so that we can call // DestroySharedSurface() on the descriptor. SurfaceDescriptor mBackBuffer; nsIntRect mBackBufferRect; nsIntPoint mBackBufferRectRotation; // This helper object lives on the stack during its lifetime and // keeps track of buffers we might have mapped and/or allocated. // When it goes out of scope on the stack, it unmaps whichever // buffers have been mapped (if any). AutoBufferTracker* mBufferTracker; bool mIsNewBuffer; OptionalThebesBuffer mROFrontBuffer; nsIntRegion mFrontUpdatedRegion; bool mFrontAndBackBufferDiffer; }; } } #endif