summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/ImageBridgeChild.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/ipc/ImageBridgeChild.h')
-rw-r--r--gfx/layers/ipc/ImageBridgeChild.h400
1 files changed, 400 insertions, 0 deletions
diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h
new file mode 100644
index 000000000..f068149f7
--- /dev/null
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -0,0 +1,400 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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_IMAGEBRIDGECHILD_H
+#define MOZILLA_GFX_IMAGEBRIDGECHILD_H
+
+#include <stddef.h> // for size_t
+#include <stdint.h> // for uint32_t, uint64_t
+#include "mozilla/Attributes.h" // for override
+#include "mozilla/Atomics.h"
+#include "mozilla/RefPtr.h" // for already_AddRefed
+#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
+#include "mozilla/layers/CanvasClient.h"
+#include "mozilla/layers/CompositableForwarder.h"
+#include "mozilla/layers/CompositorTypes.h"
+#include "mozilla/layers/PImageBridgeChild.h"
+#include "mozilla/Mutex.h"
+#include "nsDebug.h" // for NS_RUNTIMEABORT
+#include "nsIObserver.h"
+#include "nsRegion.h" // for nsIntRegion
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc
+
+class MessageLoop;
+
+namespace base {
+class Thread;
+} // namespace base
+
+namespace mozilla {
+namespace ipc {
+class Shmem;
+} // namespace ipc
+
+namespace layers {
+
+class AsyncCanvasRenderer;
+class ImageClient;
+class ImageContainer;
+class ImageContainerChild;
+class ImageBridgeParent;
+class CompositableClient;
+struct CompositableTransaction;
+class Image;
+class TextureClient;
+class SynchronousTask;
+struct AllocShmemParams;
+
+/**
+ * Returns true if the current thread is the ImageBrdigeChild's thread.
+ *
+ * Can be called from any thread.
+ */
+bool InImageBridgeChildThread();
+
+/**
+ * The ImageBridge protocol is meant to allow ImageContainers to forward images
+ * directly to the compositor thread/process without using the main thread.
+ *
+ * ImageBridgeChild is a CompositableForwarder just like ShadowLayerForwarder.
+ * This means it also does transactions with the compositor thread/process,
+ * except that the transactions are restricted to operations on the Compositables
+ * and cannot contain messages affecting layers directly.
+ *
+ * ImageBridgeChild is also a ISurfaceAllocator. It can be used to allocate or
+ * deallocate data that is shared with the compositor. The main differerence
+ * with other ISurfaceAllocators is that some of its overriden methods can be
+ * invoked from any thread.
+ *
+ * There are three important phases in the ImageBridge protocol. These three steps
+ * can do different things depending if (A) the ImageContainer uses ImageBridge
+ * or (B) it does not use ImageBridge:
+ *
+ * - When an ImageContainer calls its method SetCurrentImage:
+ * - (A) The image is sent directly to the compositor process through the
+ * ImageBridge IPDL protocol.
+ * On the compositor side the image is stored in a global table that associates
+ * the image with an ID corresponding to the ImageContainer, and a composition is
+ * triggered.
+ * - (B) Since it does not have an ImageBridge, the image is not sent yet.
+ * instead the will be sent to the compositor during the next layer transaction
+ * (on the main thread).
+ *
+ * - During a Layer transaction:
+ * - (A) The ImageContainer uses ImageBridge. The image is already available to the
+ * compositor process because it has been sent with SetCurrentImage. Yet, the
+ * CompositableHost on the compositor side will needs the ID referring to the
+ * ImageContainer to access the Image. So during the Swap operation that happens
+ * in the transaction, we swap the container ID rather than the image data.
+ * - (B) Since the ImageContainer does not use ImageBridge, the image data is swaped.
+ *
+ * - During composition:
+ * - (A) The CompositableHost has an AsyncID, it looks up the ID in the
+ * global table to see if there is an image. If there is no image, nothing is rendered.
+ * - (B) The CompositableHost has image data rather than an ID (meaning it is not
+ * using ImageBridge), then it just composites the image data normally.
+ *
+ * This means that there might be a possibility for the ImageBridge to send the first
+ * frame before the first layer transaction that will pass the container ID to the
+ * CompositableHost happens. In this (unlikely) case the layer is not composited
+ * until the layer transaction happens. This means this scenario is not harmful.
+ *
+ * Since sending an image through imageBridge triggers compositing, the main thread is
+ * not used at all (except for the very first transaction that provides the
+ * CompositableHost with an AsyncID).
+ */
+class ImageBridgeChild final : public PImageBridgeChild
+ , public CompositableForwarder
+ , public TextureForwarder
+{
+ friend class ImageContainer;
+
+ typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageBridgeChild, override);
+
+ TextureForwarder* GetTextureForwarder() override { return this; }
+ LayersIPCActor* GetLayersIPCActor() override { return this; }
+
+ /**
+ * Creates the image bridge with a dedicated thread for ImageBridgeChild.
+ *
+ * We may want to use a specifi thread in the future. In this case, use
+ * CreateWithThread instead.
+ */
+ static void InitSameProcess();
+
+ static void InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint);
+ static bool InitForContent(Endpoint<PImageBridgeChild>&& aEndpoint);
+ static bool ReinitForContent(Endpoint<PImageBridgeChild>&& aEndpoint);
+
+ /**
+ * Destroys the image bridge by calling DestroyBridge, and destroys the
+ * ImageBridge's thread.
+ *
+ * If you don't want to destroy the thread, call DestroyBridge directly
+ * instead.
+ */
+ static void ShutDown();
+
+ /**
+ * returns the singleton instance.
+ *
+ * can be called from any thread.
+ */
+ static RefPtr<ImageBridgeChild> GetSingleton();
+
+
+ static void IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier);
+
+ void BeginTransaction();
+ void EndTransaction();
+
+ /**
+ * Returns the ImageBridgeChild's thread.
+ *
+ * Can be called from any thread.
+ */
+ base::Thread * GetThread() const;
+
+ /**
+ * Returns the ImageBridgeChild's message loop.
+ *
+ * Can be called from any thread.
+ */
+ virtual MessageLoop * GetMessageLoop() const override;
+
+ virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
+
+ PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo,
+ PImageContainerChild* aChild, uint64_t* aID) override;
+ bool DeallocPCompositableChild(PCompositableChild* aActor) override;
+
+ virtual PTextureChild*
+ AllocPTextureChild(const SurfaceDescriptor& aSharedData, const LayersBackend& aLayersBackend, const TextureFlags& aFlags, const uint64_t& aSerial) override;
+
+ virtual bool
+ DeallocPTextureChild(PTextureChild* actor) override;
+
+ PMediaSystemResourceManagerChild*
+ AllocPMediaSystemResourceManagerChild() override;
+ bool
+ DeallocPMediaSystemResourceManagerChild(PMediaSystemResourceManagerChild* aActor) override;
+
+ virtual PImageContainerChild*
+ AllocPImageContainerChild() override;
+ virtual bool
+ DeallocPImageContainerChild(PImageContainerChild* actor) override;
+
+ virtual bool
+ RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
+
+ virtual bool
+ RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&& aNotifications) override;
+
+ // Create an ImageClient from any thread.
+ RefPtr<ImageClient> CreateImageClient(
+ CompositableType aType,
+ ImageContainer* aImageContainer,
+ ImageContainerChild* aContainerChild);
+
+ // Create an ImageClient from the ImageBridge thread.
+ RefPtr<ImageClient> CreateImageClientNow(
+ CompositableType aType,
+ ImageContainer* aImageContainer,
+ ImageContainerChild* aContainerChild);
+
+ already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClient::CanvasClientType aType,
+ TextureFlags aFlag);
+ void ReleaseImageContainer(RefPtr<ImageContainerChild> aChild);
+ void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient);
+ void UpdateImageClient(RefPtr<ImageClient> aClient, RefPtr<ImageContainer> aContainer);
+ static void DispatchReleaseTextureClient(TextureClient* aClient);
+
+ /**
+ * Flush all Images sent to CompositableHost.
+ */
+ void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer);
+
+ virtual bool IPCOpen() const override { return mCanSend; }
+
+private:
+
+ /**
+ * This must be called by the static function DeleteImageBridgeSync defined
+ * in ImageBridgeChild.cpp ONLY.
+ */
+ ~ImageBridgeChild();
+
+ // Helpers for dispatching.
+ already_AddRefed<CanvasClient> CreateCanvasClientNow(
+ CanvasClient::CanvasClientType aType,
+ TextureFlags aFlags);
+ void CreateCanvasClientSync(
+ SynchronousTask* aTask,
+ CanvasClient::CanvasClientType aType,
+ TextureFlags aFlags,
+ RefPtr<CanvasClient>* const outResult);
+
+ void CreateImageClientSync(
+ SynchronousTask* aTask,
+ RefPtr<ImageClient>* result,
+ CompositableType aType,
+ ImageContainer* aImageContainer,
+ ImageContainerChild* aContainerChild);
+
+ void ReleaseTextureClientNow(TextureClient* aClient);
+
+ void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient);
+ void UpdateAsyncCanvasRendererSync(
+ SynchronousTask* aTask,
+ AsyncCanvasRenderer* aWrapper);
+
+ void FlushAllImagesSync(
+ SynchronousTask* aTask,
+ ImageClient* aClient,
+ ImageContainer* aContainer);
+
+ void ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams);
+ void ProxyDeallocShmemNow(SynchronousTask* aTask, Shmem* aShmem, bool* aResult);
+
+public:
+ // CompositableForwarder
+
+ virtual void Connect(CompositableClient* aCompositable,
+ ImageContainer* aImageContainer) override;
+
+ virtual bool UsesImageBridge() const override { return true; }
+
+ /**
+ * See CompositableForwarder::UseTextures
+ */
+ virtual void UseTextures(CompositableClient* aCompositable,
+ const nsTArray<TimedTextureClient>& aTextures) override;
+ virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
+ TextureClient* aClientOnBlack,
+ TextureClient* aClientOnWhite) override;
+
+ void Destroy(CompositableChild* aCompositable) override;
+
+ /**
+ * Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
+ * Host side's usage is checked via CompositableRef.
+ */
+ void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);
+
+ /**
+ * Notify id of Texture When host side end its use. Transaction id is used to
+ * make sure if there is no newer usage.
+ */
+ void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
+
+ virtual void CancelWaitForRecycle(uint64_t aTextureId) override;
+
+ virtual bool DestroyInTransaction(PTextureChild* aTexture, bool synchronously) override;
+ virtual bool DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously) override;
+
+ virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
+ TextureClient* aTexture) override;
+
+ virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
+ const SurfaceDescriptorTiles& aTileLayerDescriptor) override
+ {
+ NS_RUNTIMEABORT("should not be called");
+ }
+
+ virtual void UpdateTextureRegion(CompositableClient* aCompositable,
+ const ThebesBufferData& aThebesBufferData,
+ const nsIntRegion& aUpdatedRegion) override {
+ NS_RUNTIMEABORT("should not be called");
+ }
+
+ // ISurfaceAllocator
+
+ /**
+ * See ISurfaceAllocator.h
+ * Can be used from any thread.
+ * If used outside the ImageBridgeChild thread, it will proxy a synchronous
+ * call on the ImageBridgeChild thread.
+ */
+ virtual bool AllocUnsafeShmem(size_t aSize,
+ mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
+ mozilla::ipc::Shmem* aShmem) override;
+ virtual bool AllocShmem(size_t aSize,
+ mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
+ mozilla::ipc::Shmem* aShmem) override;
+
+ /**
+ * See ISurfaceAllocator.h
+ * Can be used from any thread.
+ * If used outside the ImageBridgeChild thread, it will proxy a synchronous
+ * call on the ImageBridgeChild thread.
+ */
+ virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
+
+ virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
+ LayersBackend aLayersBackend,
+ TextureFlags aFlags,
+ uint64_t aSerial) override;
+
+ virtual bool IsSameProcess() const override;
+
+ virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; }
+ virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; }
+
+ bool InForwarderThread() override {
+ return InImageBridgeChildThread();
+ }
+
+ virtual void HandleFatalError(const char* aName, const char* aMsg) const override;
+
+protected:
+ ImageBridgeChild();
+ bool DispatchAllocShmemInternal(size_t aSize,
+ SharedMemory::SharedMemoryType aType,
+ Shmem* aShmem,
+ bool aUnsafe);
+
+ void Bind(Endpoint<PImageBridgeChild>&& aEndpoint);
+ void BindSameProcess(RefPtr<ImageBridgeParent> aParent);
+
+ void SendImageBridgeThreadId();
+
+ void WillShutdown();
+ void ShutdownStep1(SynchronousTask* aTask);
+ void ShutdownStep2(SynchronousTask* aTask);
+ void MarkShutDown();
+
+ void ActorDestroy(ActorDestroyReason aWhy) override;
+ void DeallocPImageBridgeChild() override;
+
+ bool CanSend() const;
+
+ static void ShutdownSingleton();
+
+private:
+ CompositableTransaction* mTxn;
+
+ bool mCanSend;
+ bool mCalledClose;
+
+ /**
+ * Transaction id of CompositableForwarder.
+ * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
+ */
+ uint64_t mFwdTransactionId;
+
+ /**
+ * Hold TextureClients refs until end of their usages on host side.
+ * It defer calling of TextureClient recycle callback.
+ */
+ nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingRecycled;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif