Bug 874726 -split ShmemYCbCrImage into YCbCrImageDataSerializer and YCbCrImageDataDeserializer. r=jrmuizel
authorNicolas Silva <nical.bugzilla@gmail.com>
Thu, 23 May 2013 09:17:10 +0200
changeset 132745 d88ad8015ae42517f671666943d19dd8e669b8c1
parent 132744 be938f823e770bbc15d688f25f8a5f07b756a363
child 132746 8dc40bbe844e2b9a8742abffbe0476e32ce86095
push id28430
push usernsilva@mozilla.com
push dateThu, 23 May 2013 07:17:16 +0000
treeherdermozilla-inbound@d88ad8015ae4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs874726
milestone24.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
Bug 874726 -split ShmemYCbCrImage into YCbCrImageDataSerializer and YCbCrImageDataDeserializer. r=jrmuizel
gfx/layers/CompositorTypes.h
gfx/layers/Makefile.in
gfx/layers/YCbCrImageDataSerializer.cpp
gfx/layers/YCbCrImageDataSerializer.h
gfx/layers/client/TextureClient.cpp
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
gfx/layers/ipc/ShmemYCbCrImage.cpp
gfx/layers/ipc/ShmemYCbCrImage.h
gfx/layers/moz.build
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.h
gfx/layers/opengl/TextureHostOGL.cpp
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -41,17 +41,17 @@ const TextureFlags ComponentAlpha     = 
  * The kind of memory held by the texture client/host pair. This will
  * determine how the texture client is drawn into and how the memory
  * is shared between client and host.
  */
 enum TextureClientType
 {
   TEXTURE_CONTENT,            // dynamically drawn content
   TEXTURE_SHMEM,              // shared memory
-  TEXTURE_YCBCR,              // ShmemYCbCrImage
+  TEXTURE_YCBCR,              // YCbCr in a shmem
   TEXTURE_SHARED_GL,          // GLContext::SharedTextureHandle
   TEXTURE_SHARED_GL_EXTERNAL, // GLContext::SharedTextureHandle, the ownership of
                               // the SurfaceDescriptor passed to the texture
                               // remains with whoever passed it.
   TEXTURE_STREAM_GL           // WebGL streaming buffer
 };
 
 /**
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -129,28 +129,28 @@ CPPSRCS += \
         ImageBridgeChild.cpp \
         ImageBridgeParent.cpp \
         ShadowLayers.cpp \
         ShadowLayerChild.cpp \
         ShadowLayerParent.cpp \
         LayerTransactionChild.cpp \
         LayerTransactionParent.cpp \
         SharedPlanarYCbCrImage.cpp \
-        ShmemYCbCrImage.cpp \
         SharedRGBImage.cpp \
         TaskThrottler.cpp \
         ImageClient.cpp \
         ImageHost.cpp \
         ISurfaceAllocator.cpp \
         TextureClient.cpp \
         TextureClientOGL.cpp \
         TextureHost.cpp \
         TextureHostOGL.cpp \
         TiledContentClient.cpp \
         TiledContentHost.cpp \
+        YCbCrImageDataSerializer.cpp \
         $(NULL)
 
 ifdef MOZ_X11 #{
 CPPSRCS += ShadowLayerUtilsX11.cpp
 endif #}
 
 ifdef MOZ_ENABLE_D3D10_LAYER
 DEFINES	+= -DMOZ_ENABLE_D3D10_LAYER
rename from gfx/layers/ipc/ShmemYCbCrImage.cpp
rename to gfx/layers/YCbCrImageDataSerializer.cpp
--- a/gfx/layers/ipc/ShmemYCbCrImage.cpp
+++ b/gfx/layers/YCbCrImageDataSerializer.cpp
@@ -1,29 +1,25 @@
 /* -*- 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/. */
 
-#include "ShmemYCbCrImage.h"
+#include "mozilla/layers/YCbCrImageDataSerializer.h"
 
 #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 // The Data is layed out as follows:
 //
-//  +-----------------+   -+   <-- Beginning of the Shmem
-//  |                 |    |
-//  |      ...        |    | offset
-//  |                 |    |
-//  +-----------------+   -++ --+ --+
+//  +-----------------+   -++ --+ --+ <-- Beginning of the buffer
 //  | YCbCrBufferInfo |     |   |   |
 //  +-----------------+   --+   |   |
 //  |      data       |         |   | YCbCrBufferInfo->[mY/mCb/mCr]Offset
 //  +-----------------+   ------+   |
 //  |      data       |             |
 //  +-----------------+   ----------+
 //  |      data       |
 //  +-----------------+
@@ -39,154 +35,156 @@ struct YCbCrBufferInfo
   uint32_t mCbOffset;
   uint32_t mCrOffset;
   uint32_t mYWidth;
   uint32_t mYHeight;
   uint32_t mCbCrWidth;
   uint32_t mCbCrHeight;
 };
 
-static YCbCrBufferInfo* GetYCbCrBufferInfo(Shmem& aShmem, size_t aOffset)
+static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData)
 {
-  return reinterpret_cast<YCbCrBufferInfo*>(aShmem.get<uint8_t>() + aOffset);
+  return reinterpret_cast<YCbCrBufferInfo*>(aData);
 }
 
+bool YCbCrImageDataDeserializerBase::IsValid()
+{
+  if (mData == nullptr) {
+    return false;
+  }
+  size_t bufferInfoSize = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
+  return true;
+}
 
-uint8_t* ShmemYCbCrImage::GetYData()
+uint8_t* YCbCrImageDataDeserializerBase::GetYData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return reinterpret_cast<uint8_t*>(info) + info->mYOffset;
 }
 
-uint8_t* ShmemYCbCrImage::GetCbData()
+uint8_t* YCbCrImageDataDeserializerBase::GetCbData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return reinterpret_cast<uint8_t*>(info) + info->mCbOffset;
 }
 
-uint8_t* ShmemYCbCrImage::GetCrData()
+uint8_t* YCbCrImageDataDeserializerBase::GetCrData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return reinterpret_cast<uint8_t*>(info) + info->mCrOffset;
 }
 
-uint8_t* ShmemYCbCrImage::GetData()
+uint8_t* YCbCrImageDataDeserializerBase::GetData()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return (reinterpret_cast<uint8_t*>(info)) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
 }
 
-uint32_t ShmemYCbCrImage::GetYStride()
+uint32_t YCbCrImageDataDeserializerBase::GetYStride()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return info->mYWidth;
 }
 
-uint32_t ShmemYCbCrImage::GetCbCrStride()
+uint32_t YCbCrImageDataDeserializerBase::GetCbCrStride()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return info->mCbCrWidth;
 }
 
-gfxIntSize ShmemYCbCrImage::GetYSize()
+gfxIntSize YCbCrImageDataDeserializerBase::GetYSize()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return gfxIntSize(info->mYWidth, info->mYHeight);
 }
 
-gfxIntSize ShmemYCbCrImage::GetCbCrSize()
+gfxIntSize YCbCrImageDataDeserializerBase::GetCbCrSize()
 {
-  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mShmem, mOffset);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   return gfxIntSize(info->mCbCrWidth, info->mCbCrHeight);
 }
 
-
-bool ShmemYCbCrImage::Open(Shmem& aShmem, size_t aOffset)
-{
-    mShmem = aShmem;
-    mOffset = aOffset;
-
-    return IsValid();
-}
-
 // Offset in bytes
 static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride)
 {
   return MOZ_ALIGN_WORD(aHeight * aStride);
 }
 
 // Minimum required shmem size in bytes
-size_t ShmemYCbCrImage::ComputeMinBufferSize(const gfxIntSize& aYSize,
-                                              const gfxIntSize& aCbCrSize)
+size_t
+YCbCrImageDataSerializer::ComputeMinBufferSize(const gfx::IntSize& aYSize,
+                                               const gfx::IntSize& aCbCrSize)
 {
   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));
 }
 
+size_t
+YCbCrImageDataSerializer::ComputeMinBufferSize(const gfxIntSize& aYSize,
+                                               const gfxIntSize& aCbCrSize)
+{
+  return ComputeMinBufferSize(gfx::IntSize(aYSize.width, aYSize.height),
+                              gfx::IntSize(aCbCrSize.width, aCbCrSize.height));
+}
 // 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)
+size_t
+YCbCrImageDataSerializer::ComputeMinBufferSize(uint32_t aSize)
 {
-
   return ComputeOffset(aSize) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
 }
 
-void ShmemYCbCrImage::InitializeBufferInfo(uint8_t* aBuffer,
-                                           const gfxIntSize& aYSize,
-                                           const gfxIntSize& aCbCrSize)
+void
+YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize,
+                                               const gfx::IntSize& aCbCrSize)
 {
-  YCbCrBufferInfo* info = reinterpret_cast<YCbCrBufferInfo*>(aBuffer);
+  YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData);
   info->mYOffset = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
   info->mCbOffset = info->mYOffset
                   + MOZ_ALIGN_WORD(aYSize.width * aYSize.height);
   info->mCrOffset = info->mCbOffset
                   + MOZ_ALIGN_WORD(aCbCrSize.width * aCbCrSize.height);
 
   info->mYWidth = aYSize.width;
   info->mYHeight = aYSize.height;
   info->mCbCrWidth = aCbCrSize.width;
   info->mCbCrHeight = aCbCrSize.height;
 }
 
-bool ShmemYCbCrImage::IsValid()
+void
+YCbCrImageDataSerializer::InitializeBufferInfo(const gfxIntSize& aYSize,
+                                               const gfxIntSize& aCbCrSize)
 {
-  if (mShmem == Shmem()) {
-    return false;
-  }
-  size_t bufferInfoSize = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
-  if (mShmem.Size<uint8_t>() < bufferInfoSize ||
-      GetYCbCrBufferInfo(mShmem, mOffset)->mYOffset != bufferInfoSize ||
-      mShmem.Size<uint8_t>() < mOffset + ComputeMinBufferSize(GetYSize(),GetCbCrSize())) {
-    return false;
-  }
-  return true;
+  InitializeBufferInfo(gfx::IntSize(aYSize.width, aYSize.height),
+                       gfx::IntSize(aCbCrSize.width, aCbCrSize.height));
 }
 
 static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) {
   for (uint32_t i = 0; i < len; ++i) {
     *dst = *src;
     src += 1 + skip;
     ++dst;
   }
 }
 
-bool ShmemYCbCrImage::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)
+bool
+YCbCrImageDataSerializer::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)
 {
   if (!IsValid() || GetYSize() != aYSize || GetCbCrSize() != aCbCrSize) {
     return false;
   }
   for (int i = 0; i < aYSize.height; ++i) {
     if (aYSkip == 0) {
       // fast path
       memcpy(GetYData() + i * GetYStride(),
rename from gfx/layers/ipc/ShmemYCbCrImage.h
rename to gfx/layers/YCbCrImageDataSerializer.h
--- a/gfx/layers/ipc/ShmemYCbCrImage.h
+++ b/gfx/layers/YCbCrImageDataSerializer.h
@@ -1,74 +1,38 @@
 /* -*- 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_LAYERS_SHMEMYCBCRIMAGE_H
-#define MOZILLA_LAYERS_SHMEMYCBCRIMAGE_H
+#ifndef MOZILLA_LAYERS_BLOBYCBCRSURFACE_H
+#define MOZILLA_LAYERS_BLOBYCBCRSURFACE_H
 
 #include "mozilla/DebugOnly.h"
 
 #include "base/basictypes.h"
 #include "Shmem.h"
 #include "gfxPoint.h"
 
 namespace mozilla {
 namespace ipc {
   class Shmem;
 }
 namespace layers {
 
 class Image;
 
 /**
- * This class is a view on a YCbCrImage stored in a Shmem at a certain offset.
- * It is only meant as a convenience to access the image data, and does not own
- * the data. The instance can live on the stack and used as follows:
- *
- * const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
- * ShmemYCbCrImage shmImg(yuv.data(), yuv.offset());
- * if (!shmImg.IsValid()) {
- *   // handle error
- * }
- * mYSize = shmImg.GetYSize(); // work with the data, etc...
+ * Convenience class to share code between YCbCrImageDataSerializer
+ * and YCbCrImageDataDeserializer.
+ * Do not use it.
  */
-class ShmemYCbCrImage
+class YCbCrImageDataDeserializerBase
 {
 public:
-  typedef mozilla::ipc::Shmem Shmem;
-
-  ShmemYCbCrImage() : mOffset(0) {}
-
-  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
-   * 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);
-
-  /**
-   * Returns true if the shmem's data blob contains a valid YCbCr image.
-   */
   bool IsValid();
 
   /**
    * Returns the Y channel data pointer.
    */
   uint8_t* GetYData();
   /**
    * Returns the Cb channel data pointer.
@@ -97,29 +61,82 @@ public:
    * Returns the dimensions of the Cb and Cr Channel.
    */
   gfxIntSize GetCbCrSize();
 
   /**
    * Return a pointer to the begining of the data buffer.
    */
   uint8_t* GetData();
+protected:
+  YCbCrImageDataDeserializerBase(uint8_t* aData)
+  : mData (aData) {}
+
+  uint8_t* mData;
+};
+
+/**
+ * A view on a YCbCr image stored with its metadata in a blob of memory.
+ * It is only meant as a convenience to access the image data, and does not own
+ * the data. The instance can live on the stack and used as follows:
+ *
+ * const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
+ * YCbCrImageDataDeserializer deserializer(yuv.data().get<uint8_t>());
+ * if (!deserializer.IsValid()) {
+ *   // handle error
+ * }
+ * size = deserializer.GetYSize(); // work with the data, etc...
+ */
+class MOZ_STACK_CLASS YCbCrImageDataSerializer : public YCbCrImageDataDeserializerBase
+{
+public:
+  YCbCrImageDataSerializer(uint8_t* aData) : YCbCrImageDataDeserializerBase(aData) {}
 
   /**
-   * Copies the data passed in parameter into 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
+   * given dimensions.
    */
+  static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
+                                     const gfx::IntSize& aCbCrSize);
+  static size_t ComputeMinBufferSize(const gfxIntSize& aYSize,
+                                     const gfxIntSize& aCbCrSize);
+  static size_t ComputeMinBufferSize(uint32_t aSize);
+
+  /**
+   * Write the image informations in the buffer for given dimensions.
+   * The provided pointer should point to the beginning of the (chunk of)
+   * buffer on which we want to store the image.
+   */
+  void InitializeBufferInfo(const gfx::IntSize& aYSize,
+                            const gfx::IntSize& aCbCrSize);
+  void InitializeBufferInfo(const gfxIntSize& aYSize,
+                            const gfxIntSize& aCbCrSize);
+
   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);
+};
 
-private:
-  bool Open(Shmem& aShmem, size_t aOffset = 0);
-
-  ipc::Shmem mShmem;
-  size_t mOffset;
+/**
+ * A view on a YCbCr image stored with its metadata in a blob of memory.
+ * It is only meant as a convenience to access the image data, and does not own
+ * the data. The instance can live on the stack and used as follows:
+ *
+ * const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
+ * YCbCrImageDataDeserializer deserializer(yuv.data().get<uint8_t>());
+ * if (!deserializer.IsValid()) {
+ *   // handle error
+ * }
+ * size = deserializer.GetYSize(); // work with the data, etc...
+ */
+class MOZ_STACK_CLASS YCbCrImageDataDeserializer : public YCbCrImageDataDeserializerBase
+{
+public:
+  YCbCrImageDataDeserializer(uint8_t* aData) : YCbCrImageDataDeserializerBase(aData) {}
 };
 
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -8,19 +8,20 @@
 
 #include "mozilla/layers/ImageClient.h"
 #include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/ContentClient.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
 #include "GLContext.h"
 #include "BasicLayers.h" // for PaintContext
-#include "ShmemYCbCrImage.h"
+#include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "gfxReusableSurfaceWrapper.h"
 #include "gfxPlatform.h"
+#include "mozilla/StandardInteger.h"
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 TextureClient::TextureClient(CompositableForwarder* aForwarder,
                              const TextureInfo& aTextureInfo)
@@ -272,18 +273,18 @@ AutoLockYCbCrClient::Update(PlanarYCbCrI
   }
 
   if (!EnsureTextureClient(aImage)) {
     return false;
   }
 
   ipc::Shmem& shmem = mDescriptor->get_YCbCrImage().data();
 
-  ShmemYCbCrImage shmemImage(shmem);
-  if (!shmemImage.CopyData(data->mYChannel, data->mCbChannel, data->mCrChannel,
+  YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
+  if (!serializer.CopyData(data->mYChannel, data->mCbChannel, data->mCrChannel,
                            data->mYSize, data->mYStride,
                            data->mCbCrSize, data->mCbCrStride,
                            data->mYSkip, data->mCbSkip)) {
     NS_WARNING("Failed to copy image data!");
     return false;
   }
   return true;
 }
@@ -301,41 +302,40 @@ bool AutoLockYCbCrClient::EnsureTextureC
     return false;
   }
 
   bool needsAllocation = false;
   if (mDescriptor->type() != SurfaceDescriptor::TYCbCrImage) {
     needsAllocation = true;
   } else {
     ipc::Shmem& shmem = mDescriptor->get_YCbCrImage().data();
-    ShmemYCbCrImage shmemImage(shmem);
-    if (shmemImage.GetYSize() != data->mYSize ||
-        shmemImage.GetCbCrSize() != data->mCbCrSize) {
+    YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
+    if (serializer.GetYSize() != data->mYSize ||
+        serializer.GetCbCrSize() != data->mCbCrSize) {
       needsAllocation = true;
     }
   }
 
   if (!needsAllocation) {
     return true;
   }
 
   mTextureClient->ReleaseResources();
 
   ipc::SharedMemory::SharedMemoryType shmType = OptimalShmemType();
-  size_t size = ShmemYCbCrImage::ComputeMinBufferSize(data->mYSize,
-                                                      data->mCbCrSize);
+  size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(data->mYSize,
+                                                               data->mCbCrSize);
   ipc::Shmem shmem;
   if (!mTextureClient->GetForwarder()->AllocUnsafeShmem(size, shmType, &shmem)) {
     return false;
   }
 
-  ShmemYCbCrImage::InitializeBufferInfo(shmem.get<uint8_t>(),
-                                        data->mYSize,
-                                        data->mCbCrSize);
+  YCbCrImageDataSerializer serializer(shmem.get<uint8_t>());
+  serializer.InitializeBufferInfo(data->mYSize,
+                                  data->mCbCrSize);
 
-
-  *mDescriptor = YCbCrImage(shmem, 0, 0);
+  *mDescriptor = YCbCrImage(shmem, 0);
 
   return true;
 }
 
 }
 }
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TextureD3D11.h"
 #include "CompositorD3D11.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "Effects.h"
 #include "ipc/AutoOpenSurface.h"
-#include "ShmemYCbCrImage.h"
+#include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "gfxWindowsPlatform.h"
 #include "gfxD2DSurface.h"
 
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
@@ -455,39 +455,38 @@ TextureHostYCbCrD3D11::GetSize() const
 
 void
 TextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage,
                                   nsIntRegion *aRegion,
                                   nsIntPoint *aOffset)
 {
   MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage);
 
-  ShmemYCbCrImage shmemImage(aImage.get_YCbCrImage().data(),
-                             aImage.get_YCbCrImage().offset());
+  YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>());
 
-  gfxIntSize gfxCbCrSize = shmemImage.GetCbCrSize();
+  gfxIntSize gfxCbCrSize = yuvDeserializer.GetCbCrSize();
 
-  gfxIntSize size = shmemImage.GetYSize();
+  gfxIntSize size = yuvDeserializer.GetYSize();
 
   D3D11_SUBRESOURCE_DATA initData;
-  initData.pSysMem = shmemImage.GetYData();
-  initData.SysMemPitch = shmemImage.GetYStride();
+  initData.pSysMem = yuvDeserializer.GetYData();
+  initData.SysMemPitch = yuvDeserializer.GetYStride();
 
   CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8_UNORM, size.width, size.height,
                               1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_IMMUTABLE);
 
   mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[0]));
 
-  initData.pSysMem = shmemImage.GetCbData();
-  initData.SysMemPitch = shmemImage.GetCbCrStride();
-  desc.Width = shmemImage.GetCbCrSize().width;
-  desc.Height = shmemImage.GetCbCrSize().height;
+  initData.pSysMem = yuvDeserializer.GetCbData();
+  initData.SysMemPitch = yuvDeserializer.GetCbCrStride();
+  desc.Width = yuvDeserializer.GetCbCrSize().width;
+  desc.Height = yuvDeserializer.GetCbCrSize().height;
 
   mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[1]));
 
-  initData.pSysMem = shmemImage.GetCrData();
+  initData.pSysMem = yuvDeserializer.GetCrData();
   mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[2]));
 
   mSize = IntSize(size.width, size.height);
 }
 
 }
 }
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -66,17 +66,16 @@ struct SurfaceDescriptorGralloc {
 
 struct SurfaceStreamDescriptor {
   SurfaceStreamHandle handle;
   bool yflip;
 };
 
 struct YCbCrImage {
   Shmem data;
-  size_t offset;
   uint64_t owner;
 };
 
 // XXX remove RGBImage (see bug 847914)
 struct RGBImage {
   Shmem data;
   nsIntRect picture;
   uint32_t rgbFormat;
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -1,15 +1,15 @@
 /* -*- 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/. */
 
 #include "SharedPlanarYCbCrImage.h"
-#include "ShmemYCbCrImage.h"
+#include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "ISurfaceAllocator.h"
 #include "mozilla/layers/LayersSurfaces.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::ipc;
 
@@ -35,59 +35,59 @@ SharedPlanarYCbCrImage::SetData(const Pl
     if (!Allocate(data)) {
       return;
     }
   }
 
   // do not set mBuffer like in PlanarYCbCrImage because the later
   // will try to manage this memory without knowing it belongs to a
   // shmem.
-  mBufferSize = ShmemYCbCrImage::ComputeMinBufferSize(mData.mYSize,
-                                                      mData.mCbCrSize);
+  mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
+                                                               mData.mCbCrSize);
   mSize = mData.mPicSize;
 
-  ShmemYCbCrImage shmImg(mShmem);
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
   MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
-  if (!shmImg.CopyData(aData.mYChannel, aData.mCbChannel, aData.mCrChannel,
-                       aData.mYSize, aData.mYStride,
-                       aData.mCbCrSize, aData.mCbCrStride,
-                       aData.mYSkip, aData.mCbSkip)) {
+  if (!serializer.CopyData(aData.mYChannel, aData.mCbChannel, aData.mCrChannel,
+                          aData.mYSize, aData.mYStride,
+                          aData.mCbCrSize, aData.mCbCrStride,
+                          aData.mYSkip, aData.mCbSkip)) {
     NS_WARNING("Failed to copy image data!");
   }
-  mData.mYChannel = shmImg.GetYData();
-  mData.mCbChannel = shmImg.GetCbData();
-  mData.mCrChannel = shmImg.GetCrData();
+  mData.mYChannel = serializer.GetYData();
+  mData.mCbChannel = serializer.GetCbData();
+  mData.mCrChannel = serializer.GetCrData();
 }
 
 // needs to be overriden because the parent class sets mBuffer which we
 // do not want to happen.
 uint8_t*
 SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
 {
   NS_ABORT_IF_FALSE(!mAllocated, "This image already has allocated data");
-  size_t size = ShmemYCbCrImage::ComputeMinBufferSize(aSize);
+  size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aSize);
   // update buffer size
   mBufferSize = size;
 
   // get new buffer _without_ setting mBuffer.
   AllocateBuffer(mBufferSize);
-  ShmemYCbCrImage shmImg(mShmem);
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
 
-  return shmImg.GetData();
+  return serializer.GetData();
 }
 
 
 void
 SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
 {
   mData = aData;
   mSize = aData.mPicSize;
-  ShmemYCbCrImage::InitializeBufferInfo(mShmem.get<uint8_t>(),
-                                        aData.mYSize,
-                                        aData.mCbCrSize);
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
+  serializer.InitializeBufferInfo(aData.mYSize,
+                                  aData.mCbCrSize);
 }
 
 uint8_t* 
 SharedPlanarYCbCrImage::AllocateBuffer(uint32_t aSize)
 {
   NS_ABORT_IF_FALSE(!mAllocated, "This image already has allocated data");
   SharedMemory::SharedMemoryType shmType = OptimalShmemType();
   if (!mSurfaceAllocator->AllocUnsafeShmem(aSize, shmType, &mShmem)) {
@@ -98,35 +98,34 @@ SharedPlanarYCbCrImage::AllocateBuffer(u
 }
 
 
 bool
 SharedPlanarYCbCrImage::Allocate(PlanarYCbCrImage::Data& aData)
 {
   NS_ABORT_IF_FALSE(!mAllocated, "This image already has allocated data");
 
-  size_t size = ShmemYCbCrImage::ComputeMinBufferSize(aData.mYSize,
-                                                      aData.mCbCrSize);
+  size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aData.mYSize,
+                                                               aData.mCbCrSize);
 
   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) {
+  YCbCrImageDataSerializer serializer(mShmem.get<uint8_t>());
+  serializer.InitializeBufferInfo(aData.mYSize,
+                                  aData.mCbCrSize);
+  if (!serializer.IsValid() || mShmem.Size<uint8_t>() < size) {
     mSurfaceAllocator->DeallocShmem(mShmem);
     return false;
   }
 
-  aData.mYChannel = shmImg.GetYData();
-  aData.mCbChannel = shmImg.GetCbData();
-  aData.mCrChannel = shmImg.GetCrData();
+  aData.mYChannel = serializer.GetYData();
+  aData.mCbChannel = serializer.GetCbData();
+  aData.mCrChannel = serializer.GetCrData();
 
   // copy some of aData's values in mData (most of them)
   mData.mYChannel = aData.mYChannel;
   mData.mCbChannel = aData.mCbChannel;
   mData.mCrChannel = aData.mCrChannel;
   mData.mYSize = aData.mYSize;
   mData.mCbCrSize = aData.mCbCrSize;
   mData.mPicX = aData.mPicX;
@@ -145,27 +144,27 @@ SharedPlanarYCbCrImage::Allocate(PlanarY
   return true;
 }
 
 bool
 SharedPlanarYCbCrImage::ToSurfaceDescriptor(SurfaceDescriptor& aDesc) {
   if (!mAllocated) {
     return false;
   }
-  aDesc = YCbCrImage(mShmem, 0, reinterpret_cast<uint64_t>(this));
+  aDesc = YCbCrImage(mShmem, reinterpret_cast<uint64_t>(this));
   this->AddRef();
   return true;
 }
 
 bool
 SharedPlanarYCbCrImage::DropToSurfaceDescriptor(SurfaceDescriptor& aDesc) {
   if (!mAllocated) {
     return false;
   }
-  aDesc = YCbCrImage(mShmem, 0, 0);
+  aDesc = YCbCrImage(mShmem, 0);
   mShmem = Shmem();
   mAllocated = false;
   return true;
 }
 
 SharedPlanarYCbCrImage*
 SharedPlanarYCbCrImage::FromSurfaceDescriptor(const SurfaceDescriptor& aDescriptor)
 {
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -35,17 +35,16 @@ EXPORTS += [
     'LayerManagerOGLShaders.h',
     'LayerSorter.h',
     'LayerTreeInvalidation.h',
     'Layers.h',
     'LayersLogging.h',
     'ReadbackLayer.h',
     'ShadowLayersManager.h',
     'SharedTextureImage.h',
-    'ShmemYCbCrImage.h',
     'TexturePoolOGL.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     if CONFIG['MOZ_ENABLE_D3D9_LAYER']:
         EXPORTS += [
             'DeviceManagerD3D9.h',
             'LayerManagerD3D9.h',
@@ -100,24 +99,24 @@ EXPORTS.mozilla.layers += [
     'LayerTransactionChild.h',
     'LayerTransactionParent.h',
     'LayersTypes.h',
     'RenderTrace.h',
     'ShadowLayers.h',
     'ShadowLayersManager.h',
     'SharedPlanarYCbCrImage.h',
     'SharedRGBImage.h',
-    'ShmemYCbCrImage.h',
     'TaskThrottler.h',
     'TextureClient.h',
     'TextureClientOGL.h',
     'TextureHost.h',
     'TextureHostOGL.h',
     'ThebesLayerComposite.h',
     'TiledContentClient.h',
+    'YCbCrImageDataSerializer.h',
 ]
 
 if CONFIG['MOZ_X11']:
     EXPORTS.mozilla.layers += [
         'ShadowLayerUtilsX11.h'
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -1,17 +1,16 @@
 /* -*- 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/. */
 
 #include "gfxSharedImageSurface.h"
 
 #include "ImageContainer.h" // for PlanarYCBCRImage
-#include "mozilla/layers/ShmemYCbCrImage.h"
 #include "ipc/AutoOpenSurface.h"
 #include "ImageLayerOGL.h"
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
 #include "yuv_convert.h"
 #include "GLContextProvider.h"
 #if defined(GL_PROVIDER_GLX)
 # include "GLXLibrary.h"
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -14,17 +14,17 @@
 #include "yuv_convert.h"
 #include "mozilla/Mutex.h"
 
 namespace mozilla {
 namespace layers {
 
 class CairoImage;
 class PlanarYCbCrImage;
-class ShmemYCbCrImage;
+class BlobYCbCrSurface;
 
 /**
  * This class wraps a GL texture. It includes a GLContext reference
  * so we can use to free the texture when destroyed. The implementation
  * makes sure to always free the texture on the main thread, even if the
  * destructor runs on another thread.
  *
  * We ensure that the GLContext reference is only addrefed and released
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 #include "TextureHostOGL.h"
 #include "ipc/AutoOpenSurface.h"
 #include "gfx2DGlue.h"
-#include "ShmemYCbCrImage.h"
+#include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "GLContext.h"
 #include "gfxImageSurface.h"
 #include "SurfaceStream.h"
 #include "SharedSurface.h"
 #include "SharedSurfaceGL.h"
 #include "SharedSurfaceEGL.h"
 #include "mozilla/layers/CompositorOGL.h"
 
@@ -486,21 +486,20 @@ YCbCrTextureHostOGL::UpdateImpl(const Su
                                 nsIntRegion* aRegion,
                                 nsIntPoint* aOffset)
 {
   if (!mGL) {
     return;
   }
   NS_ASSERTION(aImage.type() == SurfaceDescriptor::TYCbCrImage, "SurfaceDescriptor mismatch");
 
-  ShmemYCbCrImage shmemImage(aImage.get_YCbCrImage().data(),
-                             aImage.get_YCbCrImage().offset());
+  YCbCrImageDataDeserializer deserializer(aImage.get_YCbCrImage().data().get<uint8_t>());
 
-  gfxIntSize gfxSize = shmemImage.GetYSize();
-  gfxIntSize gfxCbCrSize = shmemImage.GetCbCrSize();
+  gfxIntSize gfxSize = deserializer.GetYSize();
+  gfxIntSize gfxCbCrSize = deserializer.GetCbCrSize();
 
   if (!mYTexture->mTexImage || mYTexture->mTexImage->GetSize() != gfxSize) {
     mYTexture->mTexImage = CreateBasicTextureImage(mGL,
                                                    gfxSize,
                                                    gfxASurface::CONTENT_ALPHA,
                                                    WrapMode(mGL, mFlags & AllowRepeat),
                                                    FlagsToGLFlags(mFlags));
   }
@@ -514,24 +513,24 @@ YCbCrTextureHostOGL::UpdateImpl(const Su
   if (!mCrTexture->mTexImage || mCrTexture->mTexImage->GetSize() != gfxCbCrSize) {
     mCrTexture->mTexImage = CreateBasicTextureImage(mGL,
                                                     gfxCbCrSize,
                                                     gfxASurface::CONTENT_ALPHA,
                                                     WrapMode(mGL, mFlags & AllowRepeat),
                                                     FlagsToGLFlags(mFlags));
   }
 
-  RefPtr<gfxImageSurface> tempY = new gfxImageSurface(shmemImage.GetYData(),
-                                      gfxSize, shmemImage.GetYStride(),
-                                      gfxASurface::ImageFormatA8);
-  RefPtr<gfxImageSurface> tempCb = new gfxImageSurface(shmemImage.GetCbData(),
-                                       gfxCbCrSize, shmemImage.GetCbCrStride(),
+  RefPtr<gfxImageSurface> tempY = new gfxImageSurface(deserializer.GetYData(),
+                                       gfxSize, deserializer.GetYStride(),
                                        gfxASurface::ImageFormatA8);
-  RefPtr<gfxImageSurface> tempCr = new gfxImageSurface(shmemImage.GetCrData(),
-                                       gfxCbCrSize, shmemImage.GetCbCrStride(),
+  RefPtr<gfxImageSurface> tempCb = new gfxImageSurface(deserializer.GetCbData(),
+                                       gfxCbCrSize, deserializer.GetCbCrStride(),
+                                       gfxASurface::ImageFormatA8);
+  RefPtr<gfxImageSurface> tempCr = new gfxImageSurface(deserializer.GetCrData(),
+                                       gfxCbCrSize, deserializer.GetCbCrStride(),
                                        gfxASurface::ImageFormatA8);
 
   nsIntRegion yRegion(nsIntRect(0, 0, gfxSize.width, gfxSize.height));
   nsIntRegion cbCrRegion(nsIntRect(0, 0, gfxCbCrSize.width, gfxCbCrSize.height));
 
   mYTexture->mTexImage->DirectUpdate(tempY, yRegion);
   mCbTexture->mTexImage->DirectUpdate(tempCb, cbCrRegion);
   mCrTexture->mTexImage->DirectUpdate(tempCr, cbCrRegion);