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: #ifndef GFX_CLIENTLAYERMANAGER_H michael@0: #define GFX_CLIENTLAYERMANAGER_H michael@0: michael@0: #include // for int32_t michael@0: #include "Layers.h" michael@0: #include "gfxContext.h" // for gfxContext michael@0: #include "mozilla/Attributes.h" // for MOZ_OVERRIDE michael@0: #include "mozilla/LinkedList.h" // For LinkedList michael@0: #include "mozilla/WidgetUtils.h" // for ScreenRotation michael@0: #include "mozilla/gfx/Rect.h" // for Rect michael@0: #include "mozilla/layers/CompositorTypes.h" michael@0: #include "mozilla/layers/LayersTypes.h" // for BufferMode, LayersBackend, etc michael@0: #include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder, etc michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsCOMPtr.h" // for already_AddRefed michael@0: #include "nsDebug.h" // for NS_ABORT_IF_FALSE michael@0: #include "nsISupportsImpl.h" // for Layer::Release, etc michael@0: #include "nsRect.h" // for nsIntRect michael@0: #include "nsTArray.h" // for nsTArray michael@0: #include "nscore.h" // for nsAString michael@0: michael@0: class nsIWidget; michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: class ClientThebesLayer; michael@0: class CompositorChild; michael@0: class ImageLayer; michael@0: class PLayerChild; michael@0: class TextureClientPool; michael@0: class SimpleTextureClientPool; michael@0: michael@0: class ClientLayerManager : public LayerManager michael@0: { michael@0: typedef nsTArray > LayerRefArray; michael@0: michael@0: public: michael@0: ClientLayerManager(nsIWidget* aWidget); michael@0: virtual ~ClientLayerManager(); michael@0: michael@0: virtual ShadowLayerForwarder* AsShadowForwarder() michael@0: { michael@0: return mForwarder; michael@0: } michael@0: michael@0: virtual int32_t GetMaxTextureSize() const; michael@0: michael@0: virtual void SetDefaultTargetConfiguration(BufferMode aDoubleBuffering, ScreenRotation aRotation); michael@0: virtual void BeginTransactionWithTarget(gfxContext* aTarget); michael@0: virtual void BeginTransaction(); michael@0: virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT); michael@0: virtual void EndTransaction(DrawThebesLayerCallback aCallback, michael@0: void* aCallbackData, michael@0: EndTransactionFlags aFlags = END_DEFAULT); michael@0: michael@0: virtual LayersBackend GetBackendType() { return LayersBackend::LAYERS_CLIENT; } michael@0: virtual LayersBackend GetCompositorBackendType() MOZ_OVERRIDE michael@0: { michael@0: return AsShadowForwarder()->GetCompositorBackendType(); michael@0: } michael@0: virtual void GetBackendName(nsAString& name); michael@0: virtual const char* Name() const { return "Client"; } michael@0: michael@0: virtual void SetRoot(Layer* aLayer); michael@0: michael@0: virtual void Mutated(Layer* aLayer); michael@0: michael@0: virtual already_AddRefed CreateThebesLayer(); michael@0: virtual already_AddRefed CreateThebesLayerWithHint(ThebesLayerCreationHint aHint); michael@0: virtual already_AddRefed CreateContainerLayer(); michael@0: virtual already_AddRefed CreateImageLayer(); michael@0: virtual already_AddRefed CreateCanvasLayer(); michael@0: virtual already_AddRefed CreateColorLayer(); michael@0: virtual already_AddRefed CreateRefLayer(); michael@0: michael@0: TextureFactoryIdentifier GetTextureFactoryIdentifier() michael@0: { michael@0: return mForwarder->GetTextureFactoryIdentifier(); michael@0: } michael@0: michael@0: virtual void FlushRendering() MOZ_OVERRIDE; michael@0: void SendInvalidRegion(const nsIntRegion& aRegion); michael@0: michael@0: virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize) MOZ_OVERRIDE; michael@0: michael@0: virtual void StopFrameTimeRecording(uint32_t aStartIndex, michael@0: nsTArray& aFrameIntervals) MOZ_OVERRIDE; michael@0: michael@0: virtual bool NeedsWidgetInvalidation() MOZ_OVERRIDE { return false; } michael@0: michael@0: ShadowableLayer* Hold(Layer* aLayer); michael@0: michael@0: bool HasShadowManager() const { return mForwarder->HasShadowManager(); } michael@0: michael@0: virtual bool IsCompositingCheap(); michael@0: virtual bool HasShadowManagerInternal() const { return HasShadowManager(); } michael@0: michael@0: virtual void SetIsFirstPaint() MOZ_OVERRIDE; michael@0: michael@0: TextureClientPool *GetTexturePool(gfx::SurfaceFormat aFormat); michael@0: SimpleTextureClientPool *GetSimpleTileTexturePool(gfx::SurfaceFormat aFormat); michael@0: michael@0: // Drop cached resources and ask our shadow manager to do the same, michael@0: // if we have one. michael@0: virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE; michael@0: michael@0: void SetRepeatTransaction() { mRepeatTransaction = true; } michael@0: bool GetRepeatTransaction() { return mRepeatTransaction; } michael@0: michael@0: bool IsRepeatTransaction() { return mIsRepeatTransaction; } michael@0: michael@0: void SetTransactionIncomplete() { mTransactionIncomplete = true; } michael@0: michael@0: bool HasShadowTarget() { return !!mShadowTarget; } michael@0: michael@0: void SetShadowTarget(gfxContext *aTarget) { mShadowTarget = aTarget; } michael@0: michael@0: bool CompositorMightResample() { return mCompositorMightResample; } michael@0: michael@0: DrawThebesLayerCallback GetThebesLayerCallback() const michael@0: { return mThebesLayerCallback; } michael@0: michael@0: void* GetThebesLayerCallbackData() const michael@0: { return mThebesLayerCallbackData; } michael@0: michael@0: CompositorChild *GetRemoteRenderer(); michael@0: michael@0: /** michael@0: * Called for each iteration of a progressive tile update. Fills michael@0: * aCompositionBounds and aZoom with the current scale and composition bounds michael@0: * being used to composite the layers in this manager, to determine what area michael@0: * intersects with the target composition bounds. michael@0: * aDrawingCritical will be true if the current drawing operation is using michael@0: * the critical displayport. michael@0: * Returns true if the update should continue, or false if it should be michael@0: * cancelled. michael@0: * This is only called if gfxPlatform::UseProgressiveTilePainting() returns michael@0: * true. michael@0: */ michael@0: bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, michael@0: ParentLayerRect& aCompositionBounds, michael@0: CSSToParentLayerScale& aZoom, michael@0: bool aDrawingCritical); michael@0: michael@0: bool InConstruction() { return mPhase == PHASE_CONSTRUCTION; } michael@0: #ifdef DEBUG michael@0: bool InDrawing() { return mPhase == PHASE_DRAWING; } michael@0: bool InForward() { return mPhase == PHASE_FORWARD; } michael@0: #endif michael@0: bool InTransaction() { return mPhase != PHASE_NONE; } michael@0: michael@0: void SetNeedsComposite(bool aNeedsComposite) michael@0: { michael@0: mNeedsComposite = aNeedsComposite; michael@0: } michael@0: bool NeedsComposite() const { return mNeedsComposite; } michael@0: michael@0: virtual void Composite() MOZ_OVERRIDE; michael@0: michael@0: virtual void DidComposite(); michael@0: michael@0: protected: michael@0: enum TransactionPhase { michael@0: PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD michael@0: }; michael@0: TransactionPhase mPhase; michael@0: michael@0: private: michael@0: /** michael@0: * Forward transaction results to the parent context. michael@0: */ michael@0: void ForwardTransaction(bool aScheduleComposite); michael@0: michael@0: /** michael@0: * Take a snapshot of the parent context, and copy michael@0: * it into mShadowTarget. michael@0: */ michael@0: void MakeSnapshotIfRequired(); michael@0: michael@0: void ClearLayer(Layer* aLayer); michael@0: michael@0: bool EndTransactionInternal(DrawThebesLayerCallback aCallback, michael@0: void* aCallbackData, michael@0: EndTransactionFlags); michael@0: michael@0: // The bounds of |mTarget| in device pixels. michael@0: nsIntRect mTargetBounds; michael@0: michael@0: LayerRefArray mKeepAlive; michael@0: michael@0: nsIWidget* mWidget; michael@0: michael@0: /* Thebes layer callbacks; valid at the end of a transaciton, michael@0: * while rendering */ michael@0: DrawThebesLayerCallback mThebesLayerCallback; michael@0: void *mThebesLayerCallbackData; michael@0: michael@0: // When we're doing a transaction in order to draw to a non-default michael@0: // target, the layers transaction is only performed in order to send michael@0: // a PLayers:Update. We save the original non-default target to michael@0: // mShadowTarget, and then perform the transaction using michael@0: // mDummyTarget as the render target. After the transaction ends, michael@0: // we send a message to our remote side to capture the actual pixels michael@0: // being drawn to the default target, and then copy those pixels michael@0: // back to mShadowTarget. michael@0: nsRefPtr mShadowTarget; michael@0: michael@0: // Sometimes we draw to targets that don't natively support michael@0: // landscape/portrait orientation. When we need to implement that michael@0: // ourselves, |mTargetRotation| describes the induced transform we michael@0: // need to apply when compositing content to our target. michael@0: ScreenRotation mTargetRotation; michael@0: michael@0: // Used to repeat the transaction right away (to avoid rebuilding michael@0: // a display list) to support progressive drawing. michael@0: bool mRepeatTransaction; michael@0: bool mIsRepeatTransaction; michael@0: bool mTransactionIncomplete; michael@0: bool mCompositorMightResample; michael@0: bool mNeedsComposite; michael@0: michael@0: RefPtr mForwarder; michael@0: nsAutoTArray,2> mTexturePools; michael@0: michael@0: // indexed by gfx::SurfaceFormat michael@0: nsTArray > mSimpleTilePools; michael@0: }; michael@0: michael@0: class ClientLayer : public ShadowableLayer michael@0: { michael@0: public: michael@0: ClientLayer() michael@0: { michael@0: MOZ_COUNT_CTOR(ClientLayer); michael@0: } michael@0: michael@0: ~ClientLayer(); michael@0: michael@0: void SetShadow(PLayerChild* aShadow) michael@0: { michael@0: NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)"); michael@0: mShadow = aShadow; michael@0: } michael@0: michael@0: virtual void Disconnect() michael@0: { michael@0: // This is an "emergency Disconnect()", called when the compositing michael@0: // process has died. |mShadow| and our Shmem buffers are michael@0: // automatically managed by IPDL, so we don't need to explicitly michael@0: // free them here (it's hard to get that right on emergency michael@0: // shutdown anyway). michael@0: mShadow = nullptr; michael@0: } michael@0: michael@0: virtual void ClearCachedResources() { } michael@0: michael@0: virtual void RenderLayer() = 0; michael@0: michael@0: virtual ClientThebesLayer* AsThebes() { return nullptr; } michael@0: michael@0: static inline ClientLayer * michael@0: ToClientLayer(Layer* aLayer) michael@0: { michael@0: return static_cast(aLayer->ImplData()); michael@0: } michael@0: }; michael@0: michael@0: // Create a shadow layer (PLayerChild) for aLayer, if we're forwarding michael@0: // our layer tree to a parent process. Record the new layer creation michael@0: // in the current open transaction as a side effect. michael@0: template void michael@0: CreateShadowFor(ClientLayer* aLayer, michael@0: ClientLayerManager* aMgr, michael@0: CreatedMethod aMethod) michael@0: { michael@0: PLayerChild* shadow = aMgr->AsShadowForwarder()->ConstructShadowFor(aLayer); michael@0: // XXX error handling michael@0: NS_ABORT_IF_FALSE(shadow, "failed to create shadow"); michael@0: michael@0: aLayer->SetShadow(shadow); michael@0: (aMgr->AsShadowForwarder()->*aMethod)(aLayer); michael@0: aMgr->Hold(aLayer->AsLayer()); michael@0: } michael@0: michael@0: #define CREATE_SHADOW(_type) \ michael@0: CreateShadowFor(layer, this, \ michael@0: &ShadowLayerForwarder::Created ## _type ## Layer) michael@0: michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif /* GFX_CLIENTLAYERMANAGER_H */