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 MOZILLA_GFX_IMAGEBRIDGECHILD_H michael@0: #define MOZILLA_GFX_IMAGEBRIDGECHILD_H michael@0: michael@0: #include // for size_t michael@0: #include // for uint32_t, uint64_t michael@0: #include "mozilla/Attributes.h" // for MOZ_OVERRIDE michael@0: #include "mozilla/RefPtr.h" // for TemporaryRef michael@0: #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc michael@0: #include "mozilla/layers/CompositableForwarder.h" michael@0: #include "mozilla/layers/CompositorTypes.h" // for TextureIdentifier, etc michael@0: #include "mozilla/layers/LayersSurfaces.h" // for PGrallocBufferChild michael@0: #include "mozilla/layers/PImageBridgeChild.h" michael@0: #include "nsDebug.h" // for NS_RUNTIMEABORT michael@0: #include "nsRegion.h" // for nsIntRegion michael@0: class MessageLoop; michael@0: struct nsIntPoint; michael@0: struct nsIntRect; michael@0: michael@0: namespace base { michael@0: class Thread; michael@0: } michael@0: michael@0: namespace mozilla { michael@0: namespace ipc { michael@0: class Shmem; michael@0: } michael@0: michael@0: namespace layers { michael@0: michael@0: class ClientTiledLayerBuffer; michael@0: class ImageClient; michael@0: class ImageContainer; michael@0: class ImageBridgeParent; michael@0: class CompositableClient; michael@0: class CompositableTransaction; michael@0: class Image; michael@0: class TextureClient; michael@0: michael@0: /** michael@0: * Returns true if the current thread is the ImageBrdigeChild's thread. michael@0: * michael@0: * Can be called from any thread. michael@0: */ michael@0: bool InImageBridgeChildThread(); michael@0: michael@0: /** michael@0: * The ImageBridge protocol is meant to allow ImageContainers to forward images michael@0: * directly to the compositor thread/process without using the main thread. michael@0: * michael@0: * ImageBridgeChild is a CompositableForwarder just like ShadowLayerForwarder. michael@0: * This means it also does transactions with the compositor thread/process, michael@0: * except that the transactions are restricted to operations on the Compositables michael@0: * and cannot contain messages affecting layers directly. michael@0: * michael@0: * ImageBridgeChild is also a ISurfaceAllocator. It can be used to allocate or michael@0: * deallocate data that is shared with the compositor. The main differerence michael@0: * with other ISurfaceAllocators is that some of its overriden methods can be michael@0: * invoked from any thread. michael@0: * michael@0: * There are three important phases in the ImageBridge protocol. These three steps michael@0: * can do different things depending if (A) the ImageContainer uses ImageBridge michael@0: * or (B) it does not use ImageBridge: michael@0: * michael@0: * - When an ImageContainer calls its method SetCurrentImage: michael@0: * - (A) The image is sent directly to the compositor process through the michael@0: * ImageBridge IPDL protocol. michael@0: * On the compositor side the image is stored in a global table that associates michael@0: * the image with an ID corresponding to the ImageContainer, and a composition is michael@0: * triggered. michael@0: * - (B) Since it does not have an ImageBridge, the image is not sent yet. michael@0: * instead the will be sent to the compositor during the next layer transaction michael@0: * (on the main thread). michael@0: * michael@0: * - During a Layer transaction: michael@0: * - (A) The ImageContainer uses ImageBridge. The image is already available to the michael@0: * compositor process because it has been sent with SetCurrentImage. Yet, the michael@0: * CompositableHost on the compositor side will needs the ID referring to the michael@0: * ImageContainer to access the Image. So during the Swap operation that happens michael@0: * in the transaction, we swap the container ID rather than the image data. michael@0: * - (B) Since the ImageContainer does not use ImageBridge, the image data is swaped. michael@0: * michael@0: * - During composition: michael@0: * - (A) The CompositableHost has an AsyncID, it looks up the ID in the michael@0: * global table to see if there is an image. If there is no image, nothing is rendered. michael@0: * - (B) The CompositableHost has image data rather than an ID (meaning it is not michael@0: * using ImageBridge), then it just composites the image data normally. michael@0: * michael@0: * This means that there might be a possibility for the ImageBridge to send the first michael@0: * frame before the first layer transaction that will pass the container ID to the michael@0: * CompositableHost happens. In this (unlikely) case the layer is not composited michael@0: * until the layer transaction happens. This means this scenario is not harmful. michael@0: * michael@0: * Since sending an image through imageBridge triggers compositing, the main thread is michael@0: * not used at all (except for the very first transaction that provides the michael@0: * CompositableHost with an AsyncID). michael@0: */ michael@0: class ImageBridgeChild : public PImageBridgeChild michael@0: , public CompositableForwarder michael@0: { michael@0: friend class ImageContainer; michael@0: public: michael@0: michael@0: /** michael@0: * Creates the image bridge with a dedicated thread for ImageBridgeChild. michael@0: * michael@0: * We may want to use a specifi thread in the future. In this case, use michael@0: * CreateWithThread instead. michael@0: */ michael@0: static void StartUp(); michael@0: michael@0: static PImageBridgeChild* michael@0: StartUpInChildProcess(Transport* aTransport, ProcessId aOtherProcess); michael@0: michael@0: /** michael@0: * Destroys the image bridge by calling DestroyBridge, and destroys the michael@0: * ImageBridge's thread. michael@0: * michael@0: * If you don't want to destroy the thread, call DestroyBridge directly michael@0: * instead. michael@0: */ michael@0: static void ShutDown(); michael@0: michael@0: /** michael@0: * Creates the ImageBridgeChild manager protocol. michael@0: */ michael@0: static bool StartUpOnThread(base::Thread* aThread); michael@0: michael@0: /** michael@0: * Returns true if the singleton has been created. michael@0: * michael@0: * Can be called from any thread. michael@0: */ michael@0: static bool IsCreated(); michael@0: michael@0: /** michael@0: * returns the singleton instance. michael@0: * michael@0: * can be called from any thread. michael@0: */ michael@0: static ImageBridgeChild* GetSingleton(); michael@0: michael@0: michael@0: /** michael@0: * Dispatches a task to the ImageBridgeChild thread to do the connection michael@0: */ michael@0: void ConnectAsync(ImageBridgeParent* aParent); michael@0: michael@0: static void IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier); michael@0: michael@0: void BeginTransaction(); michael@0: void EndTransaction(); michael@0: michael@0: /** michael@0: * Returns the ImageBridgeChild's thread. michael@0: * michael@0: * Can be called from any thread. michael@0: */ michael@0: base::Thread * GetThread() const; michael@0: michael@0: /** michael@0: * Returns the ImageBridgeChild's message loop. michael@0: * michael@0: * Can be called from any thread. michael@0: */ michael@0: MessageLoop * GetMessageLoop() const; michael@0: michael@0: PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo, uint64_t* aID) MOZ_OVERRIDE; michael@0: bool DeallocPCompositableChild(PCompositableChild* aActor) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * This must be called by the static function DeleteImageBridgeSync defined michael@0: * in ImageBridgeChild.cpp ONLY. michael@0: */ michael@0: ~ImageBridgeChild(); michael@0: michael@0: virtual PGrallocBufferChild* michael@0: AllocPGrallocBufferChild(const gfx::IntSize&, const uint32_t&, const uint32_t&, michael@0: MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE; michael@0: michael@0: virtual bool michael@0: DeallocPGrallocBufferChild(PGrallocBufferChild* actor) MOZ_OVERRIDE; michael@0: michael@0: virtual PTextureChild* michael@0: AllocPTextureChild(const SurfaceDescriptor& aSharedData, const TextureFlags& aFlags) MOZ_OVERRIDE; michael@0: michael@0: virtual bool michael@0: DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE; michael@0: michael@0: TemporaryRef CreateImageClient(CompositableType aType); michael@0: TemporaryRef CreateImageClientNow(CompositableType aType); michael@0: michael@0: static void DispatchReleaseImageClient(ImageClient* aClient); michael@0: static void DispatchReleaseTextureClient(TextureClient* aClient); michael@0: static void DispatchImageClientUpdate(ImageClient* aClient, ImageContainer* aContainer); michael@0: michael@0: /** michael@0: * Flush all Images sent to CompositableHost. michael@0: */ michael@0: static void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront); michael@0: michael@0: /** michael@0: * Must be called on the ImageBridgeChild's thread. michael@0: */ michael@0: static void FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront); michael@0: michael@0: // CompositableForwarder michael@0: michael@0: virtual void Connect(CompositableClient* aCompositable) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * See CompositableForwarder::UpdatedTexture michael@0: */ michael@0: virtual void UpdatedTexture(CompositableClient* aCompositable, michael@0: TextureClient* aTexture, michael@0: nsIntRegion* aRegion) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * See CompositableForwarder::UseTexture michael@0: */ michael@0: virtual void UseTexture(CompositableClient* aCompositable, michael@0: TextureClient* aClient) MOZ_OVERRIDE; michael@0: virtual void UseComponentAlphaTextures(CompositableClient* aCompositable, michael@0: TextureClient* aClientOnBlack, michael@0: TextureClient* aClientOnWhite) MOZ_OVERRIDE; michael@0: michael@0: virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable, michael@0: TextureClient* aTexture) MOZ_OVERRIDE; michael@0: michael@0: virtual void RemoveTexture(TextureClient* aTexture) MOZ_OVERRIDE; michael@0: michael@0: virtual void UseTiledLayerBuffer(CompositableClient* aCompositable, michael@0: const SurfaceDescriptorTiles& aTileLayerDescriptor) MOZ_OVERRIDE michael@0: { michael@0: NS_RUNTIMEABORT("should not be called"); michael@0: } michael@0: michael@0: virtual void UpdateTextureIncremental(CompositableClient* aCompositable, michael@0: TextureIdentifier aTextureId, michael@0: SurfaceDescriptor& aDescriptor, michael@0: const nsIntRegion& aUpdatedRegion, michael@0: const nsIntRect& aBufferRect, michael@0: const nsIntPoint& aBufferRotation) MOZ_OVERRIDE michael@0: { michael@0: NS_RUNTIMEABORT("should not be called"); michael@0: } michael@0: michael@0: /** michael@0: * Communicate the picture rect of a YUV image in aLayer to the compositor michael@0: */ michael@0: virtual void UpdatePictureRect(CompositableClient* aCompositable, michael@0: const nsIntRect& aRect) MOZ_OVERRIDE; michael@0: michael@0: michael@0: virtual void CreatedIncrementalBuffer(CompositableClient* aCompositable, michael@0: const TextureInfo& aTextureInfo, michael@0: const nsIntRect& aBufferRect) MOZ_OVERRIDE michael@0: { michael@0: NS_RUNTIMEABORT("should not be called"); michael@0: } michael@0: virtual void UpdateTextureRegion(CompositableClient* aCompositable, michael@0: const ThebesBufferData& aThebesBufferData, michael@0: const nsIntRegion& aUpdatedRegion) MOZ_OVERRIDE { michael@0: NS_RUNTIMEABORT("should not be called"); michael@0: } michael@0: michael@0: // ISurfaceAllocator michael@0: michael@0: /** michael@0: * See ISurfaceAllocator.h michael@0: * Can be used from any thread. michael@0: * If used outside the ImageBridgeChild thread, it will proxy a synchronous michael@0: * call on the ImageBridgeChild thread. michael@0: */ michael@0: virtual bool AllocUnsafeShmem(size_t aSize, michael@0: mozilla::ipc::SharedMemory::SharedMemoryType aType, michael@0: mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE; michael@0: /** michael@0: * See ISurfaceAllocator.h michael@0: * Can be used from any thread. michael@0: * If used outside the ImageBridgeChild thread, it will proxy a synchronous michael@0: * call on the ImageBridgeChild thread. michael@0: */ michael@0: virtual bool AllocShmem(size_t aSize, michael@0: mozilla::ipc::SharedMemory::SharedMemoryType aType, michael@0: mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE; michael@0: /** michael@0: * See ISurfaceAllocator.h michael@0: * Can be used from any thread. michael@0: * If used outside the ImageBridgeChild thread, it will proxy a synchronous michael@0: * call on the ImageBridgeChild thread. michael@0: */ michael@0: virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem); michael@0: michael@0: virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData, michael@0: TextureFlags aFlags) MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsSameProcess() const MOZ_OVERRIDE; michael@0: michael@0: void AllocGrallocBufferNow(const gfx::IntSize& aSize, michael@0: uint32_t aFormat, uint32_t aUsage, michael@0: MaybeMagicGrallocBufferHandle* aHandle, michael@0: PGrallocBufferChild** aChild); michael@0: michael@0: void MarkShutDown(); michael@0: protected: michael@0: ImageBridgeChild(); michael@0: bool DispatchAllocShmemInternal(size_t aSize, michael@0: SharedMemory::SharedMemoryType aType, michael@0: Shmem* aShmem, michael@0: bool aUnsafe); michael@0: michael@0: CompositableTransaction* mTxn; michael@0: bool mShuttingDown; michael@0: michael@0: // ISurfaceAllocator michael@0: virtual PGrallocBufferChild* AllocGrallocBuffer(const gfx::IntSize& aSize, michael@0: uint32_t aFormat, uint32_t aUsage, michael@0: MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE; michael@0: michael@0: virtual void DeallocGrallocBuffer(PGrallocBufferChild* aChild) MOZ_OVERRIDE; michael@0: }; michael@0: michael@0: } // layers michael@0: } // mozilla michael@0: michael@0: #endif