/* -*- 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/. */ #ifndef MOZILLA_GFX_PersistentBUFFERPROVIDER_H #define MOZILLA_GFX_PersistentBUFFERPROVIDER_H #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc #include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/ShadowLayers.h" #include "mozilla/gfx/Types.h" #include "mozilla/Vector.h" namespace mozilla { namespace gfx { class SourceSurface; class DrawTarget; } namespace layers { class CopyableCanvasLayer; /** * A PersistentBufferProvider is for users which require the temporary use of * a DrawTarget to draw into. When they're done drawing they return the * DrawTarget, when they later need to continue drawing they get a DrawTarget * from the provider again, the provider will guarantee the contents of the * previously returned DrawTarget is persisted into the one newly returned. */ class PersistentBufferProvider : public RefCounted<PersistentBufferProvider> { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProvider) virtual ~PersistentBufferProvider() { } virtual LayersBackend GetType() { return LayersBackend::LAYERS_NONE; } /** * Get a DrawTarget from the PersistentBufferProvider. * * \param aPersistedRect This indicates the area of the DrawTarget that needs * to have remained the same since the call to * ReturnDrawTarget. */ virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) = 0; /** * Return a DrawTarget to the PersistentBufferProvider and indicate the * contents of this DrawTarget is to be considered current by the * BufferProvider. The caller should forget any references to the DrawTarget. */ virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) = 0; virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() = 0; virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) = 0; virtual TextureClient* GetTextureClient() { return nullptr; } virtual void OnShutdown() {} virtual bool SetForwarder(ShadowLayerForwarder* aFwd) { return true; } /** * Return true if this provider preserves the drawing state (clips, transforms, * etc.) across frames. In practice this means users of the provider can skip * popping all of the clips at the end of the frames and pushing them back at * the beginning of the following frames, which can be costly (cf. bug 1294351). */ virtual bool PreservesDrawingState() const = 0; }; class PersistentBufferProviderBasic : public PersistentBufferProvider { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderBasic, override) static already_AddRefed<PersistentBufferProviderBasic> Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aBackend); explicit PersistentBufferProviderBasic(gfx::DrawTarget* aTarget); virtual LayersBackend GetType() override { return LayersBackend::LAYERS_BASIC; } virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) override; virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override; virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() override; virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override; virtual bool PreservesDrawingState() const override { return true; } private: ~PersistentBufferProviderBasic(); RefPtr<gfx::DrawTarget> mDrawTarget; RefPtr<gfx::SourceSurface> mSnapshot; }; /** * Provides access to a buffer which can be sent to the compositor without * requiring a copy. */ class PersistentBufferProviderShared : public PersistentBufferProvider , public ActiveResource { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderShared, override) static already_AddRefed<PersistentBufferProviderShared> Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, ShadowLayerForwarder* aFwd); virtual LayersBackend GetType() override { return LayersBackend::LAYERS_CLIENT; } virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget(const gfx::IntRect& aPersistedRect) override; virtual bool ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) override; virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() override; virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override; virtual TextureClient* GetTextureClient() override; virtual void NotifyInactive() override; virtual void OnShutdown() override { Destroy(); } virtual bool SetForwarder(ShadowLayerForwarder* aFwd) override; virtual bool PreservesDrawingState() const override { return false; } protected: PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, ShadowLayerForwarder* aFwd, RefPtr<TextureClient>& aTexture); ~PersistentBufferProviderShared(); TextureClient* GetTexture(Maybe<uint32_t> aIndex); bool CheckIndex(uint32_t aIndex) { return aIndex < mTextures.length(); } void Destroy(); gfx::IntSize mSize; gfx::SurfaceFormat mFormat; RefPtr<ShadowLayerForwarder> mFwd; Vector<RefPtr<TextureClient>, 4> mTextures; // Offset of the texture in mTextures that the canvas uses. Maybe<uint32_t> mBack; // Offset of the texture in mTextures that is presented to the compositor. Maybe<uint32_t> mFront; RefPtr<gfx::DrawTarget> mDrawTarget; RefPtr<gfx::SourceSurface > mSnapshot; }; struct AutoReturnSnapshot { PersistentBufferProvider* mBufferProvider; RefPtr<gfx::SourceSurface>* mSnapshot; explicit AutoReturnSnapshot(PersistentBufferProvider* aProvider = nullptr) : mBufferProvider(aProvider) , mSnapshot(nullptr) {} ~AutoReturnSnapshot() { if (mBufferProvider) { mBufferProvider->ReturnSnapshot(mSnapshot ? mSnapshot->forget() : nullptr); } } }; } // namespace layers } // namespace mozilla #endif