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_LayerManagerComposite_H michael@0: #define GFX_LayerManagerComposite_H michael@0: michael@0: #include // for int32_t, uint32_t michael@0: #include "GLDefs.h" // for GLenum michael@0: #include "Layers.h" michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc michael@0: #include "mozilla/Attributes.h" // for MOZ_OVERRIDE michael@0: #include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef michael@0: #include "mozilla/gfx/2D.h" michael@0: #include "mozilla/gfx/Point.h" // for IntSize michael@0: #include "mozilla/gfx/Rect.h" // for Rect michael@0: #include "mozilla/gfx/Types.h" // for SurfaceFormat michael@0: #include "mozilla/layers/CompositorTypes.h" michael@0: #include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc michael@0: #include "mozilla/RefPtr.h" michael@0: #include "nsAString.h" michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsCOMPtr.h" // for already_AddRefed michael@0: #include "nsDebug.h" // for NS_ASSERTION michael@0: #include "nsISupportsImpl.h" // for Layer::AddRef, etc michael@0: #include "nsRect.h" // for nsIntRect michael@0: #include "nsRegion.h" // for nsIntRegion michael@0: #include "nscore.h" // for nsAString, etc michael@0: #include "LayerTreeInvalidation.h" michael@0: michael@0: class gfxContext; michael@0: struct nsIntPoint; michael@0: struct nsIntSize; michael@0: michael@0: #ifdef XP_WIN michael@0: #include michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: class DrawTarget; michael@0: } michael@0: michael@0: namespace gl { michael@0: class GLContext; michael@0: class TextureImage; michael@0: } michael@0: michael@0: namespace layers { michael@0: michael@0: class CanvasLayerComposite; michael@0: class ColorLayerComposite; michael@0: class CompositableHost; michael@0: class Compositor; michael@0: class ContainerLayerComposite; michael@0: class EffectChain; michael@0: class ImageLayer; michael@0: class ImageLayerComposite; michael@0: class LayerComposite; michael@0: class RefLayerComposite; michael@0: class SurfaceDescriptor; michael@0: class ThebesLayerComposite; michael@0: class TiledLayerComposer; michael@0: class TextRenderer; michael@0: struct FPSState; michael@0: michael@0: class LayerManagerComposite : public LayerManager michael@0: { michael@0: typedef mozilla::gfx::DrawTarget DrawTarget; michael@0: typedef mozilla::gfx::IntSize IntSize; michael@0: typedef mozilla::gfx::SurfaceFormat SurfaceFormat; michael@0: michael@0: public: michael@0: LayerManagerComposite(Compositor* aCompositor); michael@0: ~LayerManagerComposite(); michael@0: michael@0: virtual void Destroy() MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * return True if initialization was succesful, false when it was not. michael@0: */ michael@0: bool Initialize(); michael@0: michael@0: /** michael@0: * Sets the clipping region for this layer manager. This is important on michael@0: * windows because using OGL we no longer have GDI's native clipping. Therefor michael@0: * widget must tell us what part of the screen is being invalidated, michael@0: * and we should clip to this. michael@0: * michael@0: * \param aClippingRegion Region to clip to. Setting an empty region michael@0: * will disable clipping. michael@0: */ michael@0: void SetClippingRegion(const nsIntRegion& aClippingRegion) michael@0: { michael@0: mClippingRegion = aClippingRegion; michael@0: } michael@0: michael@0: /** michael@0: * LayerManager implementation. michael@0: */ michael@0: virtual LayerManagerComposite* AsLayerManagerComposite() MOZ_OVERRIDE michael@0: { michael@0: return this; michael@0: } michael@0: michael@0: void UpdateRenderBounds(const nsIntRect& aRect); michael@0: michael@0: virtual void BeginTransaction() MOZ_OVERRIDE; michael@0: virtual void BeginTransactionWithTarget(gfxContext* aTarget) MOZ_OVERRIDE michael@0: { michael@0: MOZ_CRASH("Use BeginTransactionWithDrawTarget"); michael@0: } michael@0: void BeginTransactionWithDrawTarget(gfx::DrawTarget* aTarget); michael@0: michael@0: virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) MOZ_OVERRIDE; michael@0: virtual void EndTransaction(DrawThebesLayerCallback aCallback, michael@0: void* aCallbackData, michael@0: EndTransactionFlags aFlags = END_DEFAULT) MOZ_OVERRIDE; michael@0: michael@0: virtual void SetRoot(Layer* aLayer) MOZ_OVERRIDE { mRoot = aLayer; } michael@0: michael@0: // XXX[nrc]: never called, we should move this logic to ClientLayerManager michael@0: // (bug 946926). michael@0: virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE; michael@0: michael@0: virtual int32_t GetMaxTextureSize() const MOZ_OVERRIDE michael@0: { michael@0: MOZ_CRASH("Call on compositor, not LayerManagerComposite"); michael@0: } michael@0: michael@0: virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE; michael@0: michael@0: virtual already_AddRefed CreateThebesLayer() MOZ_OVERRIDE; michael@0: virtual already_AddRefed CreateContainerLayer() MOZ_OVERRIDE; michael@0: virtual already_AddRefed CreateImageLayer() MOZ_OVERRIDE; michael@0: virtual already_AddRefed CreateColorLayer() MOZ_OVERRIDE; michael@0: virtual already_AddRefed CreateCanvasLayer() MOZ_OVERRIDE; michael@0: already_AddRefed CreateThebesLayerComposite(); michael@0: already_AddRefed CreateContainerLayerComposite(); michael@0: already_AddRefed CreateImageLayerComposite(); michael@0: already_AddRefed CreateColorLayerComposite(); michael@0: already_AddRefed CreateCanvasLayerComposite(); michael@0: already_AddRefed CreateRefLayerComposite(); michael@0: michael@0: virtual LayersBackend GetBackendType() MOZ_OVERRIDE michael@0: { michael@0: MOZ_CRASH("Shouldn't be called for composited layer manager"); michael@0: } michael@0: virtual void GetBackendName(nsAString& name) MOZ_OVERRIDE michael@0: { michael@0: MOZ_CRASH("Shouldn't be called for composited layer manager"); michael@0: } michael@0: michael@0: virtual TemporaryRef michael@0: CreateOptimalMaskDrawTarget(const IntSize &aSize) MOZ_OVERRIDE; michael@0: michael@0: virtual const char* Name() const MOZ_OVERRIDE { return ""; } michael@0: michael@0: enum WorldTransforPolicy { michael@0: ApplyWorldTransform, michael@0: DontApplyWorldTransform michael@0: }; michael@0: michael@0: /** michael@0: * Setup World transform matrix. michael@0: * Transform will be ignored if it is not PreservesAxisAlignedRectangles michael@0: * or has non integer scale michael@0: */ michael@0: void SetWorldTransform(const gfx::Matrix& aMatrix); michael@0: gfx::Matrix& GetWorldTransform(void); michael@0: michael@0: /** michael@0: * RAII helper class to add a mask effect with the compositable from aMaskLayer michael@0: * to the EffectChain aEffect and notify the compositable when we are done. michael@0: */ michael@0: class AutoAddMaskEffect michael@0: { michael@0: public: michael@0: AutoAddMaskEffect(Layer* aMaskLayer, michael@0: EffectChain& aEffect, michael@0: bool aIs3D = false); michael@0: ~AutoAddMaskEffect(); michael@0: michael@0: private: michael@0: CompositableHost* mCompositable; michael@0: }; michael@0: michael@0: /** michael@0: * Creates a DrawTarget which is optimized for inter-operating with this michael@0: * layermanager. michael@0: */ michael@0: virtual TemporaryRef michael@0: CreateDrawTarget(const mozilla::gfx::IntSize& aSize, michael@0: mozilla::gfx::SurfaceFormat aFormat) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * Calculates the 'completeness' of the rendering that intersected with the michael@0: * screen on the last render. This is only useful when progressive tile michael@0: * drawing is enabled, otherwise this will always return 1.0. michael@0: * This function's expense scales with the size of the layer tree and the michael@0: * complexity of individual layers' valid regions. michael@0: */ michael@0: float ComputeRenderIntegrity(); michael@0: michael@0: /** michael@0: * returns true if PlatformAllocBuffer will return a buffer that supports michael@0: * direct texturing michael@0: */ michael@0: static bool SupportsDirectTexturing(); michael@0: michael@0: static void PlatformSyncBeforeReplyUpdate(); michael@0: michael@0: void AddInvalidRegion(const nsIntRegion& aRegion) michael@0: { michael@0: mInvalidRegion.Or(mInvalidRegion, aRegion); michael@0: } michael@0: michael@0: Compositor* GetCompositor() const michael@0: { michael@0: return mCompositor; michael@0: } michael@0: michael@0: /** michael@0: * LayerManagerComposite provides sophisticated debug overlays michael@0: * that can request a next frame. michael@0: */ michael@0: bool DebugOverlayWantsNextFrame() { return mDebugOverlayWantsNextFrame; } michael@0: void SetDebugOverlayWantsNextFrame(bool aVal) michael@0: { mDebugOverlayWantsNextFrame = aVal; } michael@0: michael@0: void NotifyShadowTreeTransaction(); michael@0: michael@0: TextRenderer* GetTextRenderer() { return mTextRenderer; } michael@0: michael@0: private: michael@0: /** Region we're clipping our current drawing to. */ michael@0: nsIntRegion mClippingRegion; michael@0: nsIntRect mRenderBounds; michael@0: michael@0: /** Current root layer. */ michael@0: LayerComposite* RootLayer() const; michael@0: michael@0: /** michael@0: * Recursive helper method for use by ComputeRenderIntegrity. Subtracts michael@0: * any incomplete rendering on aLayer from aScreenRegion. Any low-precision michael@0: * rendering is included in aLowPrecisionScreenRegion. aTransform is the michael@0: * accumulated transform of intermediate surfaces beneath aLayer. michael@0: */ michael@0: static void ComputeRenderIntegrityInternal(Layer* aLayer, michael@0: nsIntRegion& aScreenRegion, michael@0: nsIntRegion& aLowPrecisionScreenRegion, michael@0: const gfx3DMatrix& aTransform); michael@0: michael@0: /** michael@0: * Render the current layer tree to the active target. michael@0: */ michael@0: void Render(); michael@0: michael@0: /** michael@0: * Render debug overlays such as the FPS/FrameCounter above the frame. michael@0: */ michael@0: void RenderDebugOverlay(const gfx::Rect& aBounds); michael@0: michael@0: void WorldTransformRect(nsIntRect& aRect); michael@0: michael@0: RefPtr mCompositor; michael@0: nsAutoPtr mClonedLayerTreeProperties; michael@0: michael@0: /** michael@0: * Context target, nullptr when drawing directly to our swap chain. michael@0: */ michael@0: RefPtr mTarget; michael@0: michael@0: gfx::Matrix mWorldMatrix; michael@0: nsIntRegion mInvalidRegion; michael@0: nsAutoPtr mFPS; michael@0: michael@0: bool mInTransaction; michael@0: bool mIsCompositorReady; michael@0: bool mDebugOverlayWantsNextFrame; michael@0: michael@0: RefPtr mTextRenderer; michael@0: bool mGeometryChanged; michael@0: }; michael@0: michael@0: /** michael@0: * Composite layers are for use with OMTC on the compositor thread only. There michael@0: * must be corresponding Basic layers on the content thread. For composite michael@0: * layers, the layer manager only maintains the layer tree, all rendering is michael@0: * done by a Compositor (see Compositor.h). As such, composite layers are michael@0: * platform-independent and can be used on any platform for which there is a michael@0: * Compositor implementation. michael@0: * michael@0: * The composite layer tree reflects exactly the basic layer tree. To michael@0: * composite to screen, the layer manager walks the layer tree calling render michael@0: * methods which in turn call into their CompositableHosts' Composite methods. michael@0: * These call Compositor::DrawQuad to do the rendering. michael@0: * michael@0: * Mostly, layers are updated during the layers transaction. This is done from michael@0: * CompositableClient to CompositableHost without interacting with the layer. michael@0: * michael@0: * A reference to the Compositor is stored in LayerManagerComposite. michael@0: */ michael@0: class LayerComposite michael@0: { michael@0: public: michael@0: LayerComposite(LayerManagerComposite* aManager); michael@0: michael@0: virtual ~LayerComposite(); michael@0: michael@0: virtual LayerComposite* GetFirstChildComposite() michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: /* Do NOT call this from the generic LayerComposite destructor. Only from the michael@0: * concrete class destructor michael@0: */ michael@0: virtual void Destroy(); michael@0: michael@0: virtual Layer* GetLayer() = 0; michael@0: michael@0: virtual void RenderLayer(const nsIntRect& aClipRect) = 0; michael@0: michael@0: virtual bool SetCompositableHost(CompositableHost*) michael@0: { michael@0: // We must handle this gracefully, see bug 967824 michael@0: NS_WARNING("called SetCompositableHost for a layer type not accepting a compositable"); michael@0: return false; michael@0: } michael@0: virtual CompositableHost* GetCompositableHost() = 0; michael@0: michael@0: virtual void CleanupResources() = 0; michael@0: michael@0: virtual TiledLayerComposer* GetTiledLayerComposer() { return nullptr; } michael@0: michael@0: michael@0: virtual void DestroyFrontBuffer() { } michael@0: michael@0: /** michael@0: * The following methods are michael@0: * michael@0: * CONSTRUCTION PHASE ONLY michael@0: * michael@0: * They are analogous to the Layer interface. michael@0: */ michael@0: void SetShadowVisibleRegion(const nsIntRegion& aRegion) michael@0: { michael@0: mShadowVisibleRegion = aRegion; michael@0: } michael@0: michael@0: void SetShadowOpacity(float aOpacity) michael@0: { michael@0: mShadowOpacity = aOpacity; michael@0: } michael@0: michael@0: void SetShadowClipRect(const nsIntRect* aRect) michael@0: { michael@0: mUseShadowClipRect = aRect != nullptr; michael@0: if (aRect) { michael@0: mShadowClipRect = *aRect; michael@0: } michael@0: } michael@0: michael@0: void SetShadowTransform(const gfx::Matrix4x4& aMatrix) michael@0: { michael@0: mShadowTransform = aMatrix; michael@0: } michael@0: void SetShadowTransformSetByAnimation(bool aSetByAnimation) michael@0: { michael@0: mShadowTransformSetByAnimation = aSetByAnimation; michael@0: } michael@0: michael@0: void SetLayerComposited(bool value) michael@0: { michael@0: mLayerComposited = value; michael@0: } michael@0: michael@0: void SetClearRect(const nsIntRect& aRect) michael@0: { michael@0: mClearRect = aRect; michael@0: } michael@0: michael@0: // These getters can be used anytime. michael@0: float GetShadowOpacity() { return mShadowOpacity; } michael@0: const nsIntRect* GetShadowClipRect() { return mUseShadowClipRect ? &mShadowClipRect : nullptr; } michael@0: const nsIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; } michael@0: const gfx::Matrix4x4& GetShadowTransform() { return mShadowTransform; } michael@0: bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; } michael@0: bool HasLayerBeenComposited() { return mLayerComposited; } michael@0: nsIntRect GetClearRect() { return mClearRect; } michael@0: michael@0: protected: michael@0: gfx::Matrix4x4 mShadowTransform; michael@0: nsIntRegion mShadowVisibleRegion; michael@0: nsIntRect mShadowClipRect; michael@0: LayerManagerComposite* mCompositeManager; michael@0: RefPtr mCompositor; michael@0: float mShadowOpacity; michael@0: bool mUseShadowClipRect; michael@0: bool mShadowTransformSetByAnimation; michael@0: bool mDestroyed; michael@0: bool mLayerComposited; michael@0: nsIntRect mClearRect; michael@0: }; michael@0: michael@0: michael@0: } /* layers */ michael@0: } /* mozilla */ michael@0: michael@0: #endif /* GFX_LayerManagerComposite_H */