gecko/gfx/layers/ipc/ImageContainerChild.h

272 lines
8.5 KiB
C++

/* -*- 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_IMAGECONTAINERCHILD_H
#define MOZILLA_GFX_IMAGECONTAINERCHILD_H
#include "mozilla/layers/PImageContainerChild.h"
#include "mozilla/layers/ImageBridgeChild.h"
namespace mozilla {
class ReentrantMonitor;
namespace layers {
class ImageBridgeCopyAndSendTask;
class ImageContainer;
/**
* ImageContainerChild is the content-side part of the ImageBridge IPDL protocol
* acting at the ImageContainer level.
*
* There is one ImageContainerChild/Parent
* pair for each ImageContainer that uses the protocol.
* ImageContainers that use the ImageBridge protocol forward frames through
* ImageContainerChild to the compositor without using the main thread whereas
* ImageContainers that don't use it will forward frames in the main thread
* within a transaction.
*
* See ImageBridgeChild.h for more details about the ImageBridge protocol
*/
class ImageContainerChild : public PImageContainerChild
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainerChild)
friend class ImageBridgeChild;
friend class ImageBridgeCopyAndSendTask;
public:
ImageContainerChild();
virtual ~ImageContainerChild();
/**
* Sends an image to the compositor without using the main thread.
*
* This method should be called by ImageContainer only, and can be called
* from any thread.
*/
void SendImageAsync(ImageContainer* aContainer, Image* aImage);
/**
* Each ImageContainerChild is associated to an ID. This ID is used in the
* compositor side to fetch the images without having to keep direct references
* between the ShadowImageLayer and the InmageBridgeParent.
*/
const uint64_t& GetID() const
{
return mImageContainerID;
}
/**
* Overriden from PImageContainerChild.
*
* This methid is called whenever upon reception of an image that is not used by
* the compositor anymore. When receiving shared images, the ImageContainer should
* store them in a pool to reuse them without reallocating shared memory when
* possible, or deallocate them if it can't keep them.
*/
bool RecvReturnImage(const SharedImage& aImage) MOZ_OVERRIDE;
/**
* Puts the ImageContainerChild in a state where it can't send images anymore, to
* avoid races with the upcomming __delete__ message.
* Also SendStop to the parent side.
*
* Must be called from the ImageBridgeChild's thread.
*/
void StopChildAndParent();
/**
* Puts the ImageContainerChild in a state where it can't send images anymore, to
* avoid races with the upcomming __delete__ message, without calling SendStop.
* This version does not send stop to the parent side, because it must be called
* by ImageBridgeChild::StopNow which already send a message that will take care
* of putting all the ImageContainerParents in the correct state. This is done in
* order to avoid having many useless synchronous IPC messages when destroying
* the ImageBridge protocol entirely
*
* Must be called on the ImageBridgeChild's thread.
*/
void StopChild();
/**
* Dispatches StopChildAndParent to the ImageBridgeChild's thread.
*
* Can be called on any thread.
* This is typically called when you want to destroy one ImageContainerChild/Parent
* pair without destroying the protocol entirely.
*/
void DispatchStop();
/**
* Dispatches a task to the ImageBridge Thread, that will destroy the
* ImageContainerChild and associated imageContainerParent asynchonously.
*/
void DispatchDestroy();
/**
* Dispatches a task on the ImageBridgeChild's thread that will call SendFlush
* and deallocate the shared images in the pool.
* Can be called on any thread.
*/
void DispatchSetIdle();
/**
* Must be called on the ImageBridgeChild's thread.
*/
void SetIdleNow();
/**
* Can be called from any thread.
* deallocates or places aImage in a pool.
* If this method is not called on the ImageBridgeChild thread, a task is
* is dispatched and the recycling/deallocation happens asynchronously on
* the ImageBridgeChild thread.
*/
void RecycleSharedImage(SharedImage* aImage);
/**
* Creates a YCbCrImage using shared memory to store its data.
* Use a uint32_t for formats list to avoid #include horribleness.
*/
already_AddRefed<Image> CreateImage(const uint32_t *aFormats,
uint32_t aNumFormats);
/**
* Allocates an unsafe shmem.
* Unlike AllocUnsafeShmem, this method can be called from any thread.
* If the calling thread is not the ImageBridgeChild thread, this method will
* dispatch a synchronous call to AllocUnsafeShmem on the ImageBridgeChild
* thread meaning that the calling thread will be blocked until
* AllocUnsafeShmem returns on the ImageBridgeChild thread.
*/
bool AllocUnsafeShmemSync(size_t aBufSize,
SharedMemory::SharedMemoryType aType,
ipc::Shmem* aShmem);
/**
* Dispatches a task on the ImageBridgeChild thread to deallocate a shmem.
*/
void DeallocShmemAsync(ipc::Shmem& aShmem);
protected:
virtual PGrallocBufferChild*
AllocPGrallocBuffer(const gfxIntSize&, const gfxContentType&,
MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE
{ return nullptr; }
virtual bool
DeallocPGrallocBuffer(PGrallocBufferChild* actor) MOZ_OVERRIDE
{ return false; }
inline MessageLoop* GetMessageLoop() const
{
return ImageBridgeChild::GetSingleton()->GetMessageLoop();
}
/**
* Must be called on the ImageBridgeCHild's thread.
*/
void DestroyNow();
inline void SetID(uint64_t id)
{
mImageContainerID = id;
}
/**
* Must be called on the ImageBirdgeChild thread. (See RecycleSharedImage)
*/
void RecycleSharedImageNow(SharedImage* aImage);
/**
* Deallocates a shared image's shared memory.
* It is the caller's responsibility to delete the SharedImage itself.
*/
void DestroySharedImage(const SharedImage& aSurface);
/**
* Each ImageContainerChild keeps a pool of SharedImages to avoid
* deallocationg/reallocating too often.
* This method is typically called when the a shared image is received from
* the compositor.
*
*/
bool AddSharedImageToPool(SharedImage* img);
/**
* Must be called on the ImageBridgeChild's thread.
*
* creates and sends a shared image containing the same data as the image passed
* in parameter.
* - If the image's data is already in shared memory, this should just acquire
* the data rather tahn copying it
* - If There is an available shared image of the same size in the pool, reuse
* it rather than allocating shared memory.
* - worst case, allocate shared memory and copy the image's data into it.
*/
void SendImageNow(Image* aImage);
/**
* Returns a SharedImage if the image passed in parameter can be shared
* directly without a copy, returns nullptr otherwise.
*/
SharedImage* AsSharedImage(Image* aImage);
/**
* Removes a shared image from the pool and returns it.
* Returns nullptr if the pool is empty.
* The returned image does not contain the image data, a copy still needs to
* be done afterward (see CopyDataIntoSharedImage).
*/
SharedImage* GetSharedImageFor(Image* aImage);
/**
* Allocates a SharedImage.
* Returns nullptr in case of failure.
* The returned image does not contain the image data, a copy still needs to
* be done afterward (see CopyDataIntoSharedImage).
* Must be called on the ImageBridgeChild thread.
*/
SharedImage* AllocateSharedImageFor(Image* aImage);
/**
* Called by ImageToSharedImage.
*/
bool CopyDataIntoSharedImage(Image* src, SharedImage* dest);
/**
* Deallocates all the shared images from the pool and clears the pool.
*/
void ClearSharedImagePool();
private:
uint64_t mImageContainerID;
nsTArray<SharedImage*> mSharedImagePool;
/**
* Save a reference to the outgoing images and remove the reference
* once the image is returned from the compositor.
* GonkIOSurfaceImage needs to know when to return the buffer to the
* producing thread. The buffer is returned when GonkIOSurfaceImage
* destructs.
*/
nsTArray<nsRefPtr<Image> > mImageQueue;
int mActiveImageCount;
bool mStop;
bool mDispatchedDestroy;
};
} // namespace
} // namespace
#endif