diff options
Diffstat (limited to 'gfx/layers/ipc/SharedSurfacesChild.h')
-rw-r--r-- | gfx/layers/ipc/SharedSurfacesChild.h | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/gfx/layers/ipc/SharedSurfacesChild.h b/gfx/layers/ipc/SharedSurfacesChild.h new file mode 100644 index 0000000000..6fb40931fb --- /dev/null +++ b/gfx/layers/ipc/SharedSurfacesChild.h @@ -0,0 +1,250 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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_SHAREDSURFACESCHILD_H +#define MOZILLA_GFX_SHAREDSURFACESCHILD_H + +#include <stdint.h> // for uint32_t, uint64_t +#include "mozilla/Attributes.h" // for override +#include "mozilla/Maybe.h" // for Maybe +#include "mozilla/RefPtr.h" // for already_AddRefed +#include "mozilla/StaticPtr.h" // for StaticRefPtr +#include "mozilla/gfx/UserData.h" // for UserDataKey +#include "mozilla/webrender/WebRenderTypes.h" // for wr::ImageKey +#include "nsTArray.h" // for AutoTArray +#include "nsThreadUtils.h" // for Runnable +#include "ImageTypes.h" // for ContainerProducerID + +namespace mozilla { +namespace layers { +class AnimationImageKeyData; +} // namespace layers +} // namespace mozilla + +template <> +struct nsTArray_RelocationStrategy<mozilla::layers::AnimationImageKeyData> { + typedef nsTArray_RelocateUsingMoveConstructor< + mozilla::layers::AnimationImageKeyData> + Type; +}; + +namespace mozilla { +namespace gfx { +class SourceSurface; +class SourceSurfaceSharedData; +} // namespace gfx + +namespace wr { +class IpcResourceUpdateQueue; +} // namespace wr + +namespace layers { + +class CompositorManagerChild; +class RenderRootStateManager; + +class SharedSurfacesChild { + public: + /** + * Request that the surface be mapped into the compositor thread's memory + * space. This is useful for when the caller itself has no present need for + * the surface to be mapped, but knows there will be such a need in the + * future. This may be called from any thread, but it may cause a dispatch to + * the main thread. + */ + static void Share(gfx::SourceSurfaceSharedData* aSurface); + + /** + * Request that the surface be mapped into the compositor thread's memory + * space, and a valid ExternalImageId be generated for it for use with + * WebRender. This must be called from the main thread. + */ + static nsresult Share(gfx::SourceSurface* aSurface, wr::ExternalImageId& aId); + + /** + * Request that the surface be mapped into the compositor thread's memory + * space, and a valid ImageKey be generated for it for use with WebRender. + * This must be called from the main thread. + */ + static nsresult Share(gfx::SourceSurfaceSharedData* aSurface, + RenderRootStateManager* aManager, + wr::IpcResourceUpdateQueue& aResources, + wr::ImageKey& aKey); + + /** + * Request that the surface be mapped into the compositor thread's memory + * space, and a valid ImageKey be generated for it for use with WebRender. + * This must be called from the main thread. + */ + static nsresult Share(gfx::SourceSurface* aSurface, + RenderRootStateManager* aManager, + wr::IpcResourceUpdateQueue& aResources, + wr::ImageKey& aKey); + + /** + * Get the external ID, if any, bound to the shared surface. Used for memory + * reporting purposes. + */ + static Maybe<wr::ExternalImageId> GetExternalId( + const gfx::SourceSurfaceSharedData* aSurface); + + /** + * Get the surface (or its underlying surface) as a SourceSurfaceSharedData + * pointer, if valid. + */ + static gfx::SourceSurfaceSharedData* AsSourceSurfaceSharedData( + gfx::SourceSurface* aSurface); + + class ImageKeyData { + public: + ImageKeyData(RenderRootStateManager* aManager, + const wr::ImageKey& aImageKey); + virtual ~ImageKeyData(); + + ImageKeyData(ImageKeyData&& aOther); + ImageKeyData& operator=(ImageKeyData&& aOther); + ImageKeyData(const ImageKeyData&) = delete; + ImageKeyData& operator=(const ImageKeyData&) = delete; + + void MergeDirtyRect(const Maybe<gfx::IntRect>& aDirtyRect); + + Maybe<gfx::IntRect> TakeDirtyRect() { return std::move(mDirtyRect); } + + RefPtr<RenderRootStateManager> mManager; + Maybe<gfx::IntRect> mDirtyRect; + wr::ImageKey mImageKey; + }; + + private: + SharedSurfacesChild() = delete; + ~SharedSurfacesChild() = delete; + + friend class SharedSurfacesAnimation; + + class SharedUserData final : public Runnable { + public: + explicit SharedUserData(const wr::ExternalImageId& aId); + virtual ~SharedUserData(); + + SharedUserData(const SharedUserData& aOther) = delete; + SharedUserData& operator=(const SharedUserData& aOther) = delete; + + SharedUserData(SharedUserData&& aOther) = delete; + SharedUserData& operator=(SharedUserData&& aOther) = delete; + + static void Destroy(void* aClosure); + + NS_IMETHOD Run() override; + + const wr::ExternalImageId& Id() const { return mId; } + + void SetId(const wr::ExternalImageId& aId) { + mId = aId; + mKeys.Clear(); + mShared = false; + } + + bool IsShared() const { return mShared; } + + void MarkShared() { + MOZ_ASSERT(!mShared); + mShared = true; + } + + wr::ImageKey UpdateKey(RenderRootStateManager* aManager, + wr::IpcResourceUpdateQueue& aResources, + const Maybe<gfx::IntRect>& aDirtyRect); + + protected: + AutoTArray<ImageKeyData, 1> mKeys; + wr::ExternalImageId mId; + bool mShared : 1; + }; + + static nsresult ShareInternal(gfx::SourceSurfaceSharedData* aSurface, + SharedUserData** aUserData); + + static void Unshare(const wr::ExternalImageId& aId, bool aReleaseId, + nsTArray<ImageKeyData>& aKeys); + + static void DestroySharedUserData(void* aClosure); + + static gfx::UserDataKey sSharedKey; +}; + +class AnimationImageKeyData final : public SharedSurfacesChild::ImageKeyData { + public: + AnimationImageKeyData(RenderRootStateManager* aManager, + const wr::ImageKey& aImageKey); + + virtual ~AnimationImageKeyData(); + + AnimationImageKeyData(AnimationImageKeyData&& aOther); + AnimationImageKeyData& operator=(AnimationImageKeyData&& aOther); + + AutoTArray<RefPtr<gfx::SourceSurfaceSharedData>, 2> mPendingRelease; +}; + +/** + * This helper class owns a single ImageKey which will map to different external + * image IDs representing different frames in an animation. + */ +class SharedSurfacesAnimation final { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedSurfacesAnimation) + + SharedSurfacesAnimation() = default; + + void Destroy(); + + /** + * Set the animation to display the given frame. + * @param aSurface The current frame. + * @param aDirtyRect Dirty rect representing the change between the new frame + * and the previous frame. We will request only the delta + * be reuploaded by WebRender. + */ + nsresult SetCurrentFrame(gfx::SourceSurfaceSharedData* aSurface, + const gfx::IntRect& aDirtyRect); + + /** + * Generate an ImageKey for the given frame. + * @param aSurface The current frame. This should match what was cached via + * SetCurrentFrame, but if it does not, it will need to + * regenerate the cached ImageKey. + */ + nsresult UpdateKey(gfx::SourceSurfaceSharedData* aSurface, + RenderRootStateManager* aManager, + wr::IpcResourceUpdateQueue& aResources, + wr::ImageKey& aKey); + + /** + * Release our reference to all frames up to and including the frame which + * has an external image ID which matches aId. + */ + void ReleasePreviousFrame(RenderRootStateManager* aManager, + const wr::ExternalImageId& aId); + + /** + * Destroy any state information bound for the given layer manager. Any + * image keys are already invalid. + */ + void Invalidate(RenderRootStateManager* aManager); + + private: + ~SharedSurfacesAnimation(); + + void HoldSurfaceForRecycling(AnimationImageKeyData& aEntry, + gfx::SourceSurfaceSharedData* aSurface); + + AutoTArray<AnimationImageKeyData, 1> mKeys; + wr::ExternalImageId mId; +}; + +} // namespace layers +} // namespace mozilla + +#endif |