b=854539 - Implement AllocateAndGetNewBuffer for SharedPlanarYCbCrImage. r=nical
authorIvaylo Dimitrov <freemangordon@abv.bg>
Fri, 05 Apr 2013 19:24:58 +0200
changeset 127854 1aa5e2d8cd87d903a5f5ed22a68feeddc9310790
parent 127853 282de3fcc0cddc0ee75b441983a2a567f62bda4c
child 127855 722d438e10724aa09bf55b73afd18abd67c151dd
push id24513
push userphilringnalda@gmail.com
push dateSat, 06 Apr 2013 03:53:52 +0000
treeherdermozilla-central@768af8d8fad4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs854539
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
b=854539 - Implement AllocateAndGetNewBuffer for SharedPlanarYCbCrImage. r=nical
gfx/layers/ipc/ImageContainerChild.cpp
gfx/layers/ipc/ShmemYCbCrImage.cpp
gfx/layers/ipc/ShmemYCbCrImage.h
--- a/gfx/layers/ipc/ImageContainerChild.cpp
+++ b/gfx/layers/ipc/ImageContainerChild.cpp
@@ -24,52 +24,52 @@ namespace layers {
 /*
  * - POOL_MAX_SHARED_IMAGES is the maximum number number of shared images to
  * store in the ImageContainerChild's pool.
  *
  * - MAX_ACTIVE_SHARED_IMAGES is the maximum number of active shared images.
  * the number of active shared images for a given ImageContainerChild is equal
  * to the number of shared images allocated minus the number of shared images
  * dealocated by this ImageContainerChild. What can happen is that the compositor
- * hangs for a moment, while the ImageBridgeChild keep sending images. In such a 
- * scenario the compositor is not sending back shared images so the 
- * ImageContinerChild allocates new ones, and if the compositor hangs for too 
+ * hangs for a moment, while the ImageBridgeChild keep sending images. In such a
+ * scenario the compositor is not sending back shared images so the
+ * ImageContinerChild allocates new ones, and if the compositor hangs for too
  * long, we can run out of shared memory. MAX_ACTIVE_SHARED_IMAGES is there to
- * throttle that. So when the child side wants to allocate a new shared image 
+ * throttle that. So when the child side wants to allocate a new shared image
  * but is already at its maximum of active shared images, it just discards the
  * image (which is therefore not allocated and not sent to the compositor).
  *
- * The values for the two constants are arbitrary and should be tweaked if it 
+ * The values for the two constants are arbitrary and should be tweaked if it
  * happens that we run into shared memory problems.
  */
 static const unsigned int POOL_MAX_SHARED_IMAGES = 5;
 static const unsigned int MAX_ACTIVE_SHARED_IMAGES = 10;
 
 ImageContainerChild::ImageContainerChild()
 : mImageContainerID(0), mActiveImageCount(0),
-  mStop(false), mDispatchedDestroy(false) 
+  mStop(false), mDispatchedDestroy(false)
 {
   MOZ_COUNT_CTOR(ImageContainerChild);
-  // the Release corresponding to this AddRef is in 
+  // the Release corresponding to this AddRef is in
   // ImageBridgeChild::DeallocPImageContainer
   AddRef();
 }
 
 ImageContainerChild::~ImageContainerChild()
 {
   MOZ_COUNT_DTOR(ImageContainerChild);
 }
 
 void ImageContainerChild::DispatchStop()
 {
   GetMessageLoop()->PostTask(FROM_HERE,
                   NewRunnableMethod(this, &ImageContainerChild::StopChildAndParent));
 }
 
-void ImageContainerChild::SetIdleNow() 
+void ImageContainerChild::SetIdleNow()
 {
   if (mStop) return;
 
   SendFlush();
   ClearSharedImagePool();
   mImageQueue.Clear();
 }
 
@@ -89,41 +89,41 @@ void ImageContainerChild::SetIdle()
   if (InImageBridgeChildThread()) {
     return SetIdleNow();
   }
 
   Monitor barrier("SetIdle Lock");
   MonitorAutoLock autoMon(barrier);
   bool done = false;
 
-  GetMessageLoop()->PostTask(FROM_HERE, 
+  GetMessageLoop()->PostTask(FROM_HERE,
                     NewRunnableMethod(this, &ImageContainerChild::SetIdleSync, &barrier, &done));
 
   while (!done) {
     barrier.Wait();
   }
 }
 
 void ImageContainerChild::StopChildAndParent()
 {
   if (mStop) {
     return;
   }
-  mStop = true;    
+  mStop = true;
 
   SendStop(); // IPC message
   DispatchDestroy();
 }
 
 void ImageContainerChild::StopChild()
 {
   if (mStop) {
     return;
   }
-  mStop = true;    
+  mStop = true;
 
   DispatchDestroy();
 }
 
 bool ImageContainerChild::RecvReturnImage(const SharedImage& aImage)
 {
   SharedImage* img = new SharedImage(aImage);
   // Hold the image because removing it from the image queue
@@ -163,17 +163,17 @@ void ImageContainerChild::DestroySharedI
                     "Should be in ImageBridgeChild thread.");
 
   --mActiveImageCount;
   DeallocSharedImageData(this, aImage);
 }
 
 bool ImageContainerChild::CopyDataIntoSharedImage(Image* src, SharedImage* dest)
 {
-  if ((src->GetFormat() == PLANAR_YCBCR) && 
+  if ((src->GetFormat() == PLANAR_YCBCR) &&
       (dest->type() == SharedImage::TYCbCrImage)) {
     PlanarYCbCrImage *planarYCbCrImage = static_cast<PlanarYCbCrImage*>(src);
     const PlanarYCbCrImage::Data *data = planarYCbCrImage->GetData();
     NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
     YCbCrImage& yuv = dest->get_YCbCrImage();
 
     ShmemYCbCrImage shmemImage(yuv.data(), yuv.offset());
 
@@ -255,17 +255,17 @@ void ImageContainerChild::RecycleSharedI
   GetMessageLoop()->PostTask(FROM_HERE,
                              NewRunnableMethod(this,
                                                &ImageContainerChild::RecycleSharedImageNow,
                                                aImage));
 }
 
 bool ImageContainerChild::AddSharedImageToPool(SharedImage* img)
 {
-  NS_ABORT_IF_FALSE(InImageBridgeChildThread(), 
+  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                     "AddSharedImageToPool must be called in the ImageBridgeChild thread");
   if (mStop) {
     return false;
   }
 
   if (mSharedImagePool.Length() >= POOL_MAX_SHARED_IMAGES) {
     return false;
   }
@@ -370,23 +370,23 @@ void ImageContainerChild::SendImageNow(I
   }
   delete img;
   return;
 }
 
 class ImageBridgeCopyAndSendTask : public Task
 {
 public:
-  ImageBridgeCopyAndSendTask(ImageContainerChild * child, 
-                             ImageContainer * aContainer, 
+  ImageBridgeCopyAndSendTask(ImageContainerChild * child,
+                             ImageContainer * aContainer,
                              Image * aImage)
   : mChild(child), mImageContainer(aContainer), mImage(aImage) {}
 
   void Run()
-  { 
+  {
     mChild->SendImageNow(mImage);
   }
 
   ImageContainerChild* mChild;
   nsRefPtr<ImageContainer> mImageContainer;
   nsRefPtr<Image> mImage;
 };
 
@@ -401,19 +401,19 @@ void ImageContainerChild::SendImageAsync
     return;
   }
 
   if (InImageBridgeChildThread()) {
     SendImageNow(aImage);
     return;
   }
 
-  // Sending images and (potentially) allocating shmems must be done 
+  // Sending images and (potentially) allocating shmems must be done
   // on the ImageBridgeChild thread.
-  Task *t = new ImageBridgeCopyAndSendTask(this, aContainer, aImage);   
+  Task *t = new ImageBridgeCopyAndSendTask(this, aContainer, aImage);
   GetMessageLoop()->PostTask(FROM_HERE, t);
 }
 
 void ImageContainerChild::DestroyNow()
 {
   NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                     "Should be in ImageBridgeChild thread.");
   NS_ABORT_IF_FALSE(mDispatchedDestroy,
@@ -431,17 +431,17 @@ void ImageContainerChild::DispatchDestro
 {
   NS_ABORT_IF_FALSE(mStop, "The state should be 'stopped' when destroying");
 
   if (mDispatchedDestroy) {
     return;
   }
   mDispatchedDestroy = true;
   AddRef(); // corresponds to the Release in DestroyNow
-  GetMessageLoop()->PostTask(FROM_HERE, 
+  GetMessageLoop()->PostTask(FROM_HERE,
                     NewRunnableMethod(this, &ImageContainerChild::DestroyNow));
 }
 
 // We can't pass more than 6 parameters to a 'NewRunableFunction' so some
 // parameters are stored in a struct passed by pointer
 struct CreateShmemParams
 {
   ImageContainerChild* mProtocol;
@@ -567,27 +567,61 @@ public:
                          aData.mYSkip, aData.mCbSkip)) {
       NS_WARNING("Failed to copy image data!");
     }
     mData.mYChannel = shmImg.GetYData();
     mData.mCbChannel = shmImg.GetCbData();
     mData.mCrChannel = shmImg.GetCrData();
   }
 
-  virtual bool Allocate(PlanarYCbCrImage::Data& aData)
+  // needs to be overriden because the parent class sets mBuffer which we
+  // do not want to happen.
+  uint8_t* AllocateAndGetNewBuffer(uint32_t aSize) MOZ_OVERRIDE
+  {
+    size_t size = ShmemYCbCrImage::ComputeMinBufferSize(aSize);
+    // update buffer size
+    mBufferSize = size;
+
+    // get new buffer _without_ setting mBuffer.
+    AllocateBuffer(mBufferSize);
+    ShmemYCbCrImage shmImg(mShmem);
+
+    return shmImg.GetData();
+  }
+
+  virtual void
+  SetDataNoCopy(const Data &aData) MOZ_OVERRIDE
+  {
+    mData = aData;
+    mSize = aData.mPicSize;
+    ShmemYCbCrImage::InitializeBufferInfo(mShmem.get<uint8_t>(),
+                                          aData.mYSize,
+                                          aData.mCbCrSize);
+  }
+
+  virtual uint8_t* AllocateBuffer(uint32_t aSize) MOZ_OVERRIDE
   {
     NS_ABORT_IF_FALSE(!mAllocated, "This image already has allocated data");
+    SharedMemory::SharedMemoryType shmType = OptimalShmemType();
+    if (!mImageContainerChild->AllocUnsafeShmemSync(aSize, shmType, &mShmem)) {
+      return nullptr;
+    }
+    mAllocated = true;
+    return mShmem.get<uint8_t>();
+  }
 
-    SharedMemory::SharedMemoryType shmType = OptimalShmemType();
+  virtual bool Allocate(PlanarYCbCrImage::Data& aData)
+  {
     size_t size = ShmemYCbCrImage::ComputeMinBufferSize(aData.mYSize,
                                                         aData.mCbCrSize);
 
-    if (!mImageContainerChild->AllocUnsafeShmemSync(size, shmType, &mShmem)) {
+    if (AllocateBuffer(static_cast<uint32_t>(size)) == nullptr) {
       return false;
     }
+
     ShmemYCbCrImage::InitializeBufferInfo(mShmem.get<uint8_t>(),
                                           aData.mYSize,
                                           aData.mCbCrSize);
     ShmemYCbCrImage shmImg(mShmem);
     if (!shmImg.IsValid() || mShmem.Size<uint8_t>() < size) {
       mImageContainerChild->DeallocShmemAsync(mShmem);
       return false;
     }
@@ -609,17 +643,16 @@ public:
     // those members are not always equal to aData's, due to potentially different
     // packing.
     mData.mYSkip = 0;
     mData.mCbSkip = 0;
     mData.mCrSkip = 0;
     mData.mYStride = mData.mYSize.width;
     mData.mCbCrStride = mData.mCbCrSize.width;
 
-    mAllocated = true;
     return true;
   }
 
   virtual bool IsValid() MOZ_OVERRIDE {
     return mAllocated;
   }
 
   SharedImage* ToSharedImage() {
--- a/gfx/layers/ipc/ShmemYCbCrImage.cpp
+++ b/gfx/layers/ipc/ShmemYCbCrImage.cpp
@@ -63,16 +63,22 @@ uint8_t* ShmemYCbCrImage::GetCbData()
 }
 
 uint8_t* ShmemYCbCrImage::GetCrData()
 {
   YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
   return reinterpret_cast<uint8_t*>(info) + info->mCrOffset;
 }
 
+uint8_t* ShmemYCbCrImage::GetData()
+{
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  return (reinterpret_cast<uint8_t*>(info)) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
+}
+
 uint32_t ShmemYCbCrImage::GetYStride()
 {
   YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
   return info->mYWidth;
 }
 
 uint32_t ShmemYCbCrImage::GetCbCrStride()
 {
@@ -114,16 +120,29 @@ size_t ShmemYCbCrImage::ComputeMinBuffer
   uint32_t yStride = aYSize.width;
   uint32_t CbCrStride = aCbCrSize.width;
 
   return ComputeOffset(aYSize.height, yStride)
          + 2 * ComputeOffset(aCbCrSize.height, CbCrStride)
          + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
 }
 
+// Offset in bytes
+static size_t ComputeOffset(uint32_t aSize)
+{
+  return MOZ_ALIGN_WORD(aSize);
+}
+
+// Minimum required shmem size in bytes
+size_t ShmemYCbCrImage::ComputeMinBufferSize(uint32_t aSize)
+{
+
+  return ComputeOffset(aSize) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
+}
+
 void ShmemYCbCrImage::InitializeBufferInfo(uint8_t* aBuffer,
                                            const gfxIntSize& aYSize,
                                            const gfxIntSize& aCbCrSize)
 {
   YCbCrBufferInfo* info = reinterpret_cast<YCbCrBufferInfo*>(aBuffer);
   info->mYOffset = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
   info->mCbOffset = info->mYOffset
                   + MOZ_ALIGN_WORD(aYSize.width * aYSize.height);
--- a/gfx/layers/ipc/ShmemYCbCrImage.h
+++ b/gfx/layers/ipc/ShmemYCbCrImage.h
@@ -39,21 +39,22 @@ public:
 
   ShmemYCbCrImage(Shmem& shm, size_t offset = 0) {
     DebugOnly<bool> status = Open(shm,offset);
     NS_ASSERTION(status, "Invalid data in the shmem");
   }
 
   /**
    * This function is meant as a helper to know how much shared memory we need
-   * to allocate in a shmem in order to place a shared YCbCr image blob of 
+   * to allocate in a shmem in order to place a shared YCbCr image blob of
    * given dimensions.
    */
   static size_t ComputeMinBufferSize(const gfxIntSize& aYSize,
                                      const gfxIntSize& aCbCrSize);
+  static size_t ComputeMinBufferSize(uint32_t aSize);
   /**
    * Write the image informations in a buffer for given dimensions.
    * The provided pointer should point to the beginning of the (chunk of)
    * buffer on which we want to store th image.
    */
   static void InitializeBufferInfo(uint8_t* aBuffer,
                                    const gfxIntSize& aYSize,
                                    const gfxIntSize& aCbCrSize);
@@ -91,16 +92,21 @@ public:
   gfxIntSize GetYSize();
 
   /**
    * Returns the dimensions of the Cb and Cr Channel.
    */
   gfxIntSize GetCbCrSize();
 
   /**
+   * Return a pointer to the begining of the data buffer.
+   */
+  uint8_t* GetData();
+
+  /**
    * Copies the data passed in parameter into the shmem.
    */
   bool CopyData(const uint8_t* aYData,
                 const uint8_t* aCbData, const uint8_t* aCrData,
                 gfxIntSize aYSize, uint32_t aYStride,
                 gfxIntSize aCbCrSize, uint32_t aCbCrStride,
                 uint32_t aYSkip, uint32_t aCbCrSkip);