michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set sw=4 ts=8 et tw=80 : */ 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 mozilla_layers_CompositorParent_h michael@0: #define mozilla_layers_CompositorParent_h michael@0: michael@0: // Enable this pref to turn on compositor performance warning. michael@0: // This will print warnings if the compositor isn't meeting michael@0: // its responsiveness objectives: michael@0: // 1) Compose a frame within 15ms of receiving a ScheduleCompositeCall michael@0: // 2) Unless a frame was composited within the throttle threshold in michael@0: // which the deadline will be 15ms + throttle threshold michael@0: //#define COMPOSITOR_PERFORMANCE_WARNING michael@0: michael@0: #include // for uint64_t michael@0: #include "Layers.h" // for Layer michael@0: #include "ShadowLayersManager.h" // for ShadowLayersManager michael@0: #include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS michael@0: #include "base/platform_thread.h" // for PlatformThreadId michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 michael@0: #include "mozilla/Attributes.h" // for MOZ_OVERRIDE michael@0: #include "mozilla/Monitor.h" // for Monitor michael@0: #include "mozilla/RefPtr.h" // for RefPtr michael@0: #include "mozilla/TimeStamp.h" // for TimeStamp michael@0: #include "mozilla/ipc/ProtocolUtils.h" michael@0: #include "mozilla/layers/GeckoContentController.h" michael@0: #include "mozilla/layers/LayersMessages.h" // for TargetConfig michael@0: #include "mozilla/layers/PCompositorParent.h" michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsISupportsImpl.h" michael@0: #include "nsSize.h" // for nsIntSize michael@0: michael@0: class CancelableTask; michael@0: class MessageLoop; michael@0: class gfxContext; michael@0: class nsIWidget; michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: class DrawTarget; michael@0: } michael@0: michael@0: namespace layers { michael@0: michael@0: class APZCTreeManager; michael@0: class AsyncCompositionManager; michael@0: class Compositor; michael@0: class LayerManagerComposite; michael@0: class LayerTransactionParent; michael@0: michael@0: struct ScopedLayerTreeRegistration michael@0: { michael@0: ScopedLayerTreeRegistration(uint64_t aLayersId, michael@0: Layer* aRoot, michael@0: GeckoContentController* aController); michael@0: ~ScopedLayerTreeRegistration(); michael@0: michael@0: private: michael@0: uint64_t mLayersId; michael@0: }; michael@0: michael@0: class CompositorParent MOZ_FINAL : public PCompositorParent, michael@0: public ShadowLayersManager michael@0: { michael@0: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorParent) michael@0: michael@0: public: michael@0: CompositorParent(nsIWidget* aWidget, michael@0: bool aUseExternalSurfaceSize = false, michael@0: int aSurfaceWidth = -1, int aSurfaceHeight = -1); michael@0: michael@0: // IToplevelProtocol::CloneToplevel() michael@0: virtual IToplevelProtocol* michael@0: CloneToplevel(const InfallibleTArray& aFds, michael@0: base::ProcessHandle aPeerProcess, michael@0: mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE; michael@0: michael@0: virtual bool RecvWillStop() MOZ_OVERRIDE; michael@0: virtual bool RecvStop() MOZ_OVERRIDE; michael@0: virtual bool RecvPause() MOZ_OVERRIDE; michael@0: virtual bool RecvResume() MOZ_OVERRIDE; michael@0: virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE; michael@0: virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot, michael@0: SurfaceDescriptor* aOutSnapshot) MOZ_OVERRIDE; michael@0: virtual bool RecvFlushRendering() MOZ_OVERRIDE; michael@0: michael@0: virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) MOZ_OVERRIDE; michael@0: virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE; michael@0: virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray* intervals) MOZ_OVERRIDE; michael@0: michael@0: virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; michael@0: michael@0: virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree, michael@0: const TargetConfig& aTargetConfig, michael@0: bool aIsFirstPaint, michael@0: bool aScheduleComposite) MOZ_OVERRIDE; michael@0: virtual void ForceComposite(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE; michael@0: virtual bool SetTestSampleTime(LayerTransactionParent* aLayerTree, michael@0: const TimeStamp& aTime) MOZ_OVERRIDE; michael@0: virtual void LeaveTestMode(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE; michael@0: virtual AsyncCompositionManager* GetCompositionManager(LayerTransactionParent* aLayerTree) MOZ_OVERRIDE { return mCompositionManager; } michael@0: michael@0: /** michael@0: * This forces the is-first-paint flag to true. This is intended to michael@0: * be called by the widget code when it loses its viewport information michael@0: * (or for whatever reason wants to refresh the viewport information). michael@0: * The information refresh happens because the compositor will call michael@0: * SetFirstPaintViewport on the next frame of composition. michael@0: */ michael@0: void ForceIsFirstPaint(); michael@0: void Destroy(); michael@0: michael@0: void NotifyChildCreated(uint64_t aChild); michael@0: michael@0: void AsyncRender(); michael@0: michael@0: // Can be called from any thread michael@0: void ScheduleRenderOnCompositorThread(); michael@0: void SchedulePauseOnCompositorThread(); michael@0: /** michael@0: * Returns true if a surface was obtained and the resume succeeded; false michael@0: * otherwise. michael@0: */ michael@0: bool ScheduleResumeOnCompositorThread(int width, int height); michael@0: michael@0: virtual void ScheduleComposition(); michael@0: void NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint, bool aScheduleComposite); michael@0: michael@0: /** michael@0: * Returns the unique layer tree identifier that corresponds to the root michael@0: * tree of this compositor. michael@0: */ michael@0: uint64_t RootLayerTreeId(); michael@0: michael@0: /** michael@0: * Returns a pointer to the compositor corresponding to the given ID. michael@0: */ michael@0: static CompositorParent* GetCompositor(uint64_t id); michael@0: michael@0: /** michael@0: * Returns the compositor thread's message loop. michael@0: * michael@0: * This message loop is used by CompositorParent and ImageBridgeParent. michael@0: */ michael@0: static MessageLoop* CompositorLoop(); michael@0: michael@0: /** michael@0: * Creates the compositor thread and the global compositor map. michael@0: */ michael@0: static void StartUp(); michael@0: michael@0: /** michael@0: * Destroys the compositor thread and the global compositor map. michael@0: */ michael@0: static void ShutDown(); michael@0: michael@0: /** michael@0: * Allocate an ID that can be used to refer to a layer tree and michael@0: * associated resources that live only on the compositor thread. michael@0: * michael@0: * Must run on the content main thread. michael@0: */ michael@0: static uint64_t AllocateLayerTreeId(); michael@0: /** michael@0: * Release compositor-thread resources referred to by |aID|. michael@0: * michael@0: * Must run on the content main thread. michael@0: */ michael@0: static void DeallocateLayerTreeId(uint64_t aId); michael@0: michael@0: /** michael@0: * Set aController as the pan/zoom callback for the subtree referred michael@0: * to by aLayersId. michael@0: * michael@0: * Must run on content main thread. michael@0: */ michael@0: static void SetControllerForLayerTree(uint64_t aLayersId, michael@0: GeckoContentController* aController); michael@0: michael@0: /** michael@0: * This returns a reference to the APZCTreeManager to which michael@0: * pan/zoom-related events can be sent. michael@0: */ michael@0: static APZCTreeManager* GetAPZCTreeManager(uint64_t aLayersId); michael@0: michael@0: /** michael@0: * A new child process has been configured to push transactions michael@0: * directly to us. Transport is to its thread context. michael@0: */ michael@0: static PCompositorParent* michael@0: Create(Transport* aTransport, ProcessId aOtherProcess); michael@0: michael@0: /** michael@0: * Setup external message loop and thread ID for Compositor. michael@0: * Should be used when CompositorParent should work in existing thread/MessageLoop, michael@0: * for example moving Compositor into native toolkit main thread will allow to avoid michael@0: * extra synchronization and call ::Composite() right from toolkit::Paint event michael@0: */ michael@0: static void StartUpWithExistingThread(MessageLoop* aMsgLoop, michael@0: PlatformThreadId aThreadID); michael@0: michael@0: struct LayerTreeState { michael@0: LayerTreeState(); michael@0: nsRefPtr mRoot; michael@0: nsRefPtr mController; michael@0: CompositorParent* mParent; michael@0: LayerManagerComposite* mLayerManager; michael@0: // Pointer to the CrossProcessCompositorParent. Used by APZCs to share michael@0: // their FrameMetrics with the corresponding child process that holds michael@0: // the PCompositorChild michael@0: PCompositorParent* mCrossProcessParent; michael@0: TargetConfig mTargetConfig; michael@0: }; michael@0: michael@0: /** michael@0: * Lookup the indirect shadow tree for |aId| and return it if it michael@0: * exists. Otherwise null is returned. This must only be called on michael@0: * the compositor thread. michael@0: */ michael@0: static const LayerTreeState* GetIndirectShadowTree(uint64_t aId); michael@0: michael@0: float ComputeRenderIntegrity(); michael@0: michael@0: /** michael@0: * Returns true if the calling thread is the compositor thread. michael@0: */ michael@0: static bool IsInCompositorThread(); michael@0: michael@0: private: michael@0: // Private destructor, to discourage deletion outside of Release(): michael@0: virtual ~CompositorParent(); michael@0: michael@0: virtual PLayerTransactionParent* michael@0: AllocPLayerTransactionParent(const nsTArray& aBackendHints, michael@0: const uint64_t& aId, michael@0: TextureFactoryIdentifier* aTextureFactoryIdentifier, michael@0: bool* aSuccess) MOZ_OVERRIDE; michael@0: virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE; michael@0: virtual void ScheduleTask(CancelableTask*, int); michael@0: void Composite(); michael@0: void CompositeToTarget(gfx::DrawTarget* aTarget); michael@0: void ForceComposeToTarget(gfx::DrawTarget* aTarget); michael@0: michael@0: void SetEGLSurfaceSize(int width, int height); michael@0: michael@0: void InitializeLayerManager(const nsTArray& aBackendHints); michael@0: void PauseComposition(); michael@0: void ResumeComposition(); michael@0: void ResumeCompositionAndResize(int width, int height); michael@0: void ForceComposition(); michael@0: void CancelCurrentCompositeTask(); michael@0: michael@0: inline static PlatformThreadId CompositorThreadID(); michael@0: michael@0: /** michael@0: * Creates a global map referencing each compositor by ID. michael@0: * michael@0: * This map is used by the ImageBridge protocol to trigger michael@0: * compositions without having to keep references to the michael@0: * compositor michael@0: */ michael@0: static void CreateCompositorMap(); michael@0: static void DestroyCompositorMap(); michael@0: michael@0: /** michael@0: * Creates the compositor thread. michael@0: * michael@0: * All compositors live on the same thread. michael@0: * The thread is not lazily created on first access to avoid dealing with michael@0: * thread safety. Therefore it's best to create and destroy the thread when michael@0: * we know we areb't using it (So creating/destroying along with gfxPlatform michael@0: * looks like a good place). michael@0: */ michael@0: static bool CreateThread(); michael@0: michael@0: /** michael@0: * Destroys the compositor thread. michael@0: * michael@0: * It is safe to call this fucntion more than once, although the second call michael@0: * will have no effect. michael@0: * This function is not thread-safe. michael@0: */ michael@0: static void DestroyThread(); michael@0: michael@0: /** michael@0: * Add a compositor to the global compositor map. michael@0: */ michael@0: static void AddCompositor(CompositorParent* compositor, uint64_t* id); michael@0: /** michael@0: * Remove a compositor from the global compositor map. michael@0: */ michael@0: static CompositorParent* RemoveCompositor(uint64_t id); michael@0: michael@0: /** michael@0: * Return true if current state allows compositing, that is michael@0: * finishing a layers transaction. michael@0: */ michael@0: bool CanComposite(); michael@0: michael@0: void DidComposite(); michael@0: michael@0: nsRefPtr mLayerManager; michael@0: nsRefPtr mCompositor; michael@0: RefPtr mCompositionManager; michael@0: nsIWidget* mWidget; michael@0: CancelableTask *mCurrentCompositeTask; michael@0: TimeStamp mLastCompose; michael@0: TimeStamp mTestTime; michael@0: bool mIsTesting; michael@0: #ifdef COMPOSITOR_PERFORMANCE_WARNING michael@0: TimeStamp mExpectedComposeStartTime; michael@0: #endif michael@0: michael@0: bool mPaused; michael@0: michael@0: bool mUseExternalSurfaceSize; michael@0: nsIntSize mEGLSurfaceSize; michael@0: michael@0: mozilla::Monitor mPauseCompositionMonitor; michael@0: mozilla::Monitor mResumeCompositionMonitor; michael@0: michael@0: uint64_t mCompositorID; michael@0: uint64_t mRootLayerTreeID; michael@0: michael@0: bool mOverrideComposeReadiness; michael@0: CancelableTask* mForceCompositionTask; michael@0: michael@0: nsRefPtr mApzcTreeManager; michael@0: michael@0: bool mWantDidCompositeEvent; michael@0: michael@0: DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); michael@0: }; michael@0: michael@0: } // layers michael@0: } // mozilla michael@0: michael@0: #endif // mozilla_layers_CompositorParent_h