michael@0: /* -*- Mode: C++; tab-width: 20; 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: #ifndef GFX_CONTENTHOST_H michael@0: #define GFX_CONTENTHOST_H michael@0: michael@0: #include // for uint32_t michael@0: #include // for FILE michael@0: #include "mozilla-config.h" // for MOZ_DUMP_PAINTING michael@0: #include "CompositableHost.h" // for CompositableHost, etc michael@0: #include "RotatedBuffer.h" // for RotatedContentBuffer, etc michael@0: #include "mozilla/Attributes.h" // for MOZ_OVERRIDE michael@0: #include "mozilla/RefPtr.h" // for RefPtr michael@0: #include "mozilla/gfx/BasePoint.h" // for BasePoint michael@0: #include "mozilla/gfx/Point.h" // for Point michael@0: #include "mozilla/gfx/Rect.h" // for Rect michael@0: #include "mozilla/gfx/Types.h" // for Filter michael@0: #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc michael@0: #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator michael@0: #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor michael@0: #include "mozilla/layers/LayersTypes.h" // for etc michael@0: #include "mozilla/layers/TextureHost.h" // for TextureHost michael@0: #include "mozilla/mozalloc.h" // for operator delete michael@0: #include "nsAutoPtr.h" // for nsAutoPtr michael@0: #include "nsCOMPtr.h" // for already_AddRefed michael@0: #include "nsDebug.h" // for NS_RUNTIMEABORT michael@0: #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc michael@0: #include "nsPoint.h" // for nsIntPoint michael@0: #include "nsRect.h" // for nsIntRect michael@0: #include "nsRegion.h" // for nsIntRegion michael@0: #include "nsTArray.h" // for nsTArray michael@0: #include "nscore.h" // for nsACString michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: class Matrix4x4; michael@0: } michael@0: namespace layers { michael@0: class Compositor; michael@0: class ThebesBufferData; michael@0: class TiledLayerComposer; michael@0: struct EffectChain; michael@0: class TextureImageTextureSourceOGL; michael@0: michael@0: struct TexturedEffect; michael@0: michael@0: /** michael@0: * ContentHosts are used for compositing Thebes layers, always matched by a michael@0: * ContentClient of the same type. michael@0: * michael@0: * ContentHosts support only UpdateThebes(), not Update(). michael@0: */ michael@0: class ContentHost : public CompositableHost michael@0: { michael@0: public: michael@0: // Subclasses should implement this method if they support being used as a michael@0: // tiling. michael@0: virtual TiledLayerComposer* AsTiledLayerComposer() { return nullptr; } michael@0: michael@0: virtual bool UpdateThebes(const ThebesBufferData& aData, michael@0: const nsIntRegion& aUpdated, michael@0: const nsIntRegion& aOldValidRegionBack, michael@0: nsIntRegion* aUpdatedRegionBack) = 0; michael@0: michael@0: virtual void SetPaintWillResample(bool aResample) { } michael@0: michael@0: protected: michael@0: ContentHost(const TextureInfo& aTextureInfo) michael@0: : CompositableHost(aTextureInfo) michael@0: {} michael@0: }; michael@0: michael@0: /** michael@0: * Base class for non-tiled ContentHosts. michael@0: * michael@0: * Ownership of the SurfaceDescriptor and the resources it represents is passed michael@0: * from the ContentClient to the ContentHost when the TextureClient/Hosts are michael@0: * created, that is recevied here by SetTextureHosts which assigns one or two michael@0: * texture hosts (for single and double buffering) to the ContentHost. michael@0: * michael@0: * It is the responsibility of the ContentHost to destroy its resources when michael@0: * they are recreated or the ContentHost dies. michael@0: */ michael@0: class ContentHostBase : public ContentHost michael@0: { michael@0: public: michael@0: typedef RotatedContentBuffer::ContentType ContentType; michael@0: typedef RotatedContentBuffer::PaintState PaintState; michael@0: michael@0: ContentHostBase(const TextureInfo& aTextureInfo); michael@0: virtual ~ContentHostBase(); michael@0: michael@0: virtual void Composite(EffectChain& aEffectChain, michael@0: float aOpacity, michael@0: const gfx::Matrix4x4& aTransform, michael@0: const gfx::Filter& aFilter, michael@0: const gfx::Rect& aClipRect, michael@0: const nsIntRegion* aVisibleRegion = nullptr, michael@0: TiledLayerProperties* aLayerProperties = nullptr); michael@0: michael@0: virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; } michael@0: michael@0: virtual bool Lock() = 0; michael@0: virtual void Unlock() = 0; michael@0: michael@0: virtual NewTextureSource* GetTextureSource() = 0; michael@0: virtual NewTextureSource* GetTextureSourceOnWhite() = 0; michael@0: michael@0: protected: michael@0: virtual nsIntPoint GetOriginOffset() michael@0: { michael@0: return mBufferRect.TopLeft() - mBufferRotation; michael@0: } michael@0: michael@0: bool PaintWillResample() { return mPaintWillResample; } michael@0: michael@0: nsIntRect mBufferRect; michael@0: nsIntPoint mBufferRotation; michael@0: bool mPaintWillResample; michael@0: bool mInitialised; michael@0: }; michael@0: michael@0: /** michael@0: * Shared ContentHostBase implementation for content hosts that michael@0: * use up to two TextureHosts. michael@0: */ michael@0: class ContentHostTexture : public ContentHostBase michael@0: { michael@0: public: michael@0: ContentHostTexture(const TextureInfo& aTextureInfo) michael@0: : ContentHostBase(aTextureInfo) michael@0: , mLocked(false) michael@0: { } michael@0: michael@0: virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; michael@0: michael@0: #ifdef MOZ_DUMP_PAINTING michael@0: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE; michael@0: michael@0: virtual void Dump(FILE* aFile=nullptr, michael@0: const char* aPrefix="", michael@0: bool aDumpHtml=false) MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: virtual void PrintInfo(nsACString& aTo, const char* aPrefix) MOZ_OVERRIDE; michael@0: michael@0: virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE; michael@0: virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack, michael@0: TextureHost* aTextureOnWhite) MOZ_OVERRIDE; michael@0: michael@0: virtual bool Lock() { michael@0: MOZ_ASSERT(!mLocked); michael@0: if (!mTextureHost) { michael@0: return false; michael@0: } michael@0: if (!mTextureHost->Lock()) { michael@0: return false; michael@0: } michael@0: michael@0: if (mTextureHostOnWhite && !mTextureHostOnWhite->Lock()) { michael@0: return false; michael@0: } michael@0: michael@0: mLocked = true; michael@0: return true; michael@0: } michael@0: virtual void Unlock() { michael@0: MOZ_ASSERT(mLocked); michael@0: mTextureHost->Unlock(); michael@0: if (mTextureHostOnWhite) { michael@0: mTextureHostOnWhite->Unlock(); michael@0: } michael@0: mLocked = false; michael@0: } michael@0: michael@0: virtual NewTextureSource* GetTextureSource() { michael@0: MOZ_ASSERT(mLocked); michael@0: return mTextureHost->GetTextureSources(); michael@0: } michael@0: virtual NewTextureSource* GetTextureSourceOnWhite() { michael@0: MOZ_ASSERT(mLocked); michael@0: if (mTextureHostOnWhite) { michael@0: return mTextureHostOnWhite->GetTextureSources(); michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: LayerRenderState GetRenderState(); michael@0: michael@0: protected: michael@0: RefPtr mTextureHost; michael@0: RefPtr mTextureHostOnWhite; michael@0: bool mLocked; michael@0: }; michael@0: michael@0: /** michael@0: * Double buffering is implemented by swapping the front and back TextureHosts. michael@0: * We assume that whenever we use double buffering, then we have michael@0: * render-to-texture and thus no texture upload to do. michael@0: */ michael@0: class ContentHostDoubleBuffered : public ContentHostTexture michael@0: { michael@0: public: michael@0: ContentHostDoubleBuffered(const TextureInfo& aTextureInfo) michael@0: : ContentHostTexture(aTextureInfo) michael@0: {} michael@0: michael@0: virtual ~ContentHostDoubleBuffered() {} michael@0: michael@0: virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_DOUBLE; } michael@0: michael@0: virtual bool UpdateThebes(const ThebesBufferData& aData, michael@0: const nsIntRegion& aUpdated, michael@0: const nsIntRegion& aOldValidRegionBack, michael@0: nsIntRegion* aUpdatedRegionBack); michael@0: michael@0: protected: michael@0: nsIntRegion mValidRegionForNextBackBuffer; michael@0: }; michael@0: michael@0: /** michael@0: * Single buffered, therefore we must synchronously upload the image from the michael@0: * TextureHost in the layers transaction (i.e., in UpdateThebes). michael@0: */ michael@0: class ContentHostSingleBuffered : public ContentHostTexture michael@0: { michael@0: public: michael@0: ContentHostSingleBuffered(const TextureInfo& aTextureInfo) michael@0: : ContentHostTexture(aTextureInfo) michael@0: {} michael@0: virtual ~ContentHostSingleBuffered() {} michael@0: michael@0: virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_SINGLE; } michael@0: michael@0: virtual bool UpdateThebes(const ThebesBufferData& aData, michael@0: const nsIntRegion& aUpdated, michael@0: const nsIntRegion& aOldValidRegionBack, michael@0: nsIntRegion* aUpdatedRegionBack); michael@0: }; michael@0: michael@0: /** michael@0: * Maintains a host-side only texture, and gets provided with michael@0: * surfaces that only cover the changed pixels during an update. michael@0: * michael@0: * Takes ownership of the passed in update surfaces, and must michael@0: * free them once texture upload is complete. michael@0: * michael@0: * Delays texture uploads until the next composite to michael@0: * avoid blocking the main thread. michael@0: */ michael@0: class ContentHostIncremental : public ContentHostBase michael@0: { michael@0: public: michael@0: ContentHostIncremental(const TextureInfo& aTextureInfo); michael@0: ~ContentHostIncremental(); michael@0: michael@0: virtual CompositableType GetType() { return BUFFER_CONTENT_INC; } michael@0: michael@0: virtual LayerRenderState GetRenderState() MOZ_OVERRIDE { return LayerRenderState(); } michael@0: michael@0: virtual bool CreatedIncrementalTexture(ISurfaceAllocator* aAllocator, michael@0: const TextureInfo& aTextureInfo, michael@0: const nsIntRect& aBufferRect) MOZ_OVERRIDE; michael@0: michael@0: virtual void UpdateIncremental(TextureIdentifier aTextureId, michael@0: SurfaceDescriptor& aSurface, michael@0: const nsIntRegion& aUpdated, michael@0: const nsIntRect& aBufferRect, michael@0: const nsIntPoint& aBufferRotation) MOZ_OVERRIDE; michael@0: michael@0: virtual bool UpdateThebes(const ThebesBufferData& aData, michael@0: const nsIntRegion& aUpdated, michael@0: const nsIntRegion& aOldValidRegionBack, michael@0: nsIntRegion* aUpdatedRegionBack) michael@0: { michael@0: NS_ERROR("Shouldn't call this"); michael@0: return false; michael@0: } michael@0: michael@0: virtual bool Lock() { michael@0: MOZ_ASSERT(!mLocked); michael@0: ProcessTextureUpdates(); michael@0: mLocked = true; michael@0: return true; michael@0: } michael@0: michael@0: virtual void Unlock() { michael@0: MOZ_ASSERT(mLocked); michael@0: mLocked = false; michael@0: } michael@0: michael@0: virtual NewTextureSource* GetTextureSource(); michael@0: virtual NewTextureSource* GetTextureSourceOnWhite(); michael@0: michael@0: private: michael@0: michael@0: void FlushUpdateQueue(); michael@0: void ProcessTextureUpdates(); michael@0: michael@0: class Request michael@0: { michael@0: public: michael@0: Request() michael@0: { michael@0: MOZ_COUNT_CTOR(ContentHostIncremental::Request); michael@0: } michael@0: michael@0: virtual ~Request() michael@0: { michael@0: MOZ_COUNT_DTOR(ContentHostIncremental::Request); michael@0: } michael@0: michael@0: virtual void Execute(ContentHostIncremental *aHost) = 0; michael@0: }; michael@0: michael@0: class TextureCreationRequest : public Request michael@0: { michael@0: public: michael@0: TextureCreationRequest(const TextureInfo& aTextureInfo, michael@0: const nsIntRect& aBufferRect) michael@0: : mTextureInfo(aTextureInfo) michael@0: , mBufferRect(aBufferRect) michael@0: {} michael@0: michael@0: virtual void Execute(ContentHostIncremental *aHost); michael@0: michael@0: private: michael@0: TextureInfo mTextureInfo; michael@0: nsIntRect mBufferRect; michael@0: }; michael@0: michael@0: class TextureUpdateRequest : public Request michael@0: { michael@0: public: michael@0: TextureUpdateRequest(ISurfaceAllocator* aDeAllocator, michael@0: TextureIdentifier aTextureId, michael@0: SurfaceDescriptor& aDescriptor, michael@0: const nsIntRegion& aUpdated, michael@0: const nsIntRect& aBufferRect, michael@0: const nsIntPoint& aBufferRotation) michael@0: : mDeAllocator(aDeAllocator) michael@0: , mTextureId(aTextureId) michael@0: , mDescriptor(aDescriptor) michael@0: , mUpdated(aUpdated) michael@0: , mBufferRect(aBufferRect) michael@0: , mBufferRotation(aBufferRotation) michael@0: {} michael@0: michael@0: ~TextureUpdateRequest() michael@0: { michael@0: //TODO: Recycle these? michael@0: mDeAllocator->DestroySharedSurface(&mDescriptor); michael@0: } michael@0: michael@0: virtual void Execute(ContentHostIncremental *aHost); michael@0: michael@0: private: michael@0: enum XSide { michael@0: LEFT, RIGHT michael@0: }; michael@0: enum YSide { michael@0: TOP, BOTTOM michael@0: }; michael@0: michael@0: nsIntRect GetQuadrantRectangle(XSide aXSide, YSide aYSide) const; michael@0: michael@0: RefPtr mDeAllocator; michael@0: TextureIdentifier mTextureId; michael@0: SurfaceDescriptor mDescriptor; michael@0: nsIntRegion mUpdated; michael@0: nsIntRect mBufferRect; michael@0: nsIntPoint mBufferRotation; michael@0: }; michael@0: michael@0: nsTArray > mUpdateList; michael@0: michael@0: // Specific to OGL to avoid exposing methods on TextureSource that only michael@0: // have one implementation. michael@0: RefPtr mSource; michael@0: RefPtr mSourceOnWhite; michael@0: michael@0: RefPtr mDeAllocator; michael@0: bool mLocked; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif