Bug 767480 - PlanarYCbCrImage refactoring. r=roc
authorKan-Ru Chen (陳侃如) <kanru@kanru.info>
Tue, 21 Aug 2012 17:31:36 +0800
changeset 108388 17ec4e01c12695d80dd0af6d14d8ea9dee93bcaa
parent 108387 e6fe39185cd4ec7880c445b1524368091b79a81b
child 108389 c8f7bace9cf901c983648de962a21a46975f683e
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs767480
milestone17.0a1
Bug 767480 - PlanarYCbCrImage refactoring. r=roc
content/media/nsBuiltinDecoderReader.cpp
gfx/layers/ImageContainer.cpp
gfx/layers/ImageContainer.h
gfx/layers/d3d10/ImageLayerD3D10.cpp
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/opengl/ImageLayerOGL.cpp
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -197,29 +197,32 @@ VideoData* VideoData::Create(nsVideoInfo
   PlanarYCbCrImage::Data data;
   const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
   const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
   const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
 
   data.mYChannel = Y.mData;
   data.mYSize = gfxIntSize(Y.mWidth, Y.mHeight);
   data.mYStride = Y.mStride;
+  data.mYOffset = Y.mOffset;
+  data.mYSkip = Y.mSkip;
   data.mCbChannel = Cb.mData;
   data.mCrChannel = Cr.mData;
   data.mCbCrSize = gfxIntSize(Cb.mWidth, Cb.mHeight);
   data.mCbCrStride = Cb.mStride;
+  data.mCbOffset = Cb.mOffset;
+  data.mCbSkip = Cb.mSkip;
+  data.mCrOffset = Cr.mOffset;
+  data.mCrSkip = Cr.mSkip;
   data.mPicX = aPicture.x;
   data.mPicY = aPicture.y;
   data.mPicSize = gfxIntSize(aPicture.width, aPicture.height);
   data.mStereoMode = aInfo.mStereoMode;
 
-  videoImage->CopyData(data,
-                       Y.mOffset, Y.mSkip,
-                       Cb.mOffset, Cb.mSkip,
-                       Cr.mOffset, Cr.mSkip);
+  videoImage->CopyData(data);
   return v.forget();
 }
 
 void* nsBuiltinDecoderReader::VideoQueueMemoryFunctor::operator()(void* anObject) {
   const VideoData* v = static_cast<const VideoData*>(anObject);
   if (!v->mImage) {
     return nullptr;
   }
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -418,20 +418,17 @@ CopyPlane(PRUint8 *aDst, PRUint8 *aSrc,
       }
       aSrc += aStride;
       aDst += aStride;
     }
   }
 }
 
 void
-PlanarYCbCrImage::CopyData(const Data& aData,
-                           PRInt32 aYOffset, PRInt32 aYSkip,
-                           PRInt32 aCbOffset, PRInt32 aCbSkip,
-                           PRInt32 aCrOffset, PRInt32 aCrSkip)
+PlanarYCbCrImage::CopyData(const Data& aData)
 {
   mData = aData;
 
   // update buffer size
   mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
                 mData.mYStride * mData.mYSize.height;
 
   // get new buffer
@@ -440,23 +437,23 @@ PlanarYCbCrImage::CopyData(const Data& a
     return;
 
   mData.mYChannel = mBuffer;
   mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
   mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
 
   CopyPlane(mData.mYChannel, aData.mYChannel,
             mData.mYSize, mData.mYStride,
-            aYOffset, aYSkip);
+            mData.mYOffset, mData.mYSkip);
   CopyPlane(mData.mCbChannel, aData.mCbChannel,
             mData.mCbCrSize, mData.mCbCrStride,
-            aCbOffset, aCbSkip);
+            mData.mCbOffset, mData.mCbSkip);
   CopyPlane(mData.mCrChannel, aData.mCrChannel,
             mData.mCbCrSize, mData.mCbCrStride,
-            aCrOffset, aCrSkip);
+            mData.mCrOffset, mData.mCrSkip);
 
   mSize = aData.mPicSize;
 }
 
 void
 PlanarYCbCrImage::SetData(const Data &aData)
 {
   CopyData(aData);
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -598,29 +598,40 @@ private:
  * 4:2:0 - CbCr width and height is half that of Y.
  *
  * The color format is detected based on the height/width ratios
  * defined above.
  * 
  * The Image that is rendered is the picture region defined by
  * mPicX, mPicY and mPicSize. The size of the rendered image is
  * mPicSize, not mYSize or mCbCrSize.
+ *
+ * mYOffset, mYSkip, mCbOffset, mCbSkip, mCrOffset, mCrSkip are added
+ * to support various output formats from hardware decoder. m*Offset
+ * are the extra left stride and m*Skip are per-pixel skips in the
+ * source image.
  */
 class THEBES_API PlanarYCbCrImage : public Image {
 public:
   struct Data {
     // Luminance buffer
     PRUint8* mYChannel;
     PRInt32 mYStride;
     gfxIntSize mYSize;
+    PRInt32 mYOffset;
+    PRInt32 mYSkip;
     // Chroma buffers
     PRUint8* mCbChannel;
     PRUint8* mCrChannel;
     PRInt32 mCbCrStride;
     gfxIntSize mCbCrSize;
+    PRInt32 mCbOffset;
+    PRInt32 mCbSkip;
+    PRInt32 mCrOffset;
+    PRInt32 mCrSkip;
     // Picture region
     PRUint32 mPicX;
     PRUint32 mPicY;
     gfxIntSize mPicSize;
     StereoMode mStereoMode;
 
     nsIntRect GetPictureRect() const {
       return nsIntRect(mPicX, mPicY,
@@ -649,60 +660,53 @@ public:
   virtual void SetDelayedConversion(bool aDelayed) { }
 
   /**
    * Grab the original YUV data. This is optional.
    */
   virtual const Data* GetData() { return &mData; }
 
   /**
+   * Return the number of bytes of heap memory used to store this image.
+   */
+  virtual PRUint32 GetDataSize() { return mBufferSize; }
+
+  virtual bool IsValid() { return !!mBufferSize; }
+
+  virtual gfxIntSize GetSize() { return mSize; }
+
+  PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
+
+protected:
+  /**
    * Make a copy of the YCbCr data into local storage.
    *
    * @param aData           Input image data.
-   * @param aYOffset        Pixels to skip between lines in the Y plane.
-   * @param aYSkip          Pixels to skip between pixels in the Y plane.
-   * @param aCbOffset       Pixels to skip between lines in the Cb plane.
-   * @param aCbSkip         Pixels to skip between pixels in the Cb plane.
-   * @param aCrOffset       Pixels to skip between lines in the Cr plane.
-   * @param aCrSkip         Pixels to skip between pixels in the Cr plane.
    */
-  void CopyData(const Data& aData,
-                PRInt32 aYOffset = 0, PRInt32 aYSkip = 0,
-                PRInt32 aCbOffset = 0, PRInt32 aCbSkip = 0,
-                PRInt32 aCrOffset = 0, PRInt32 aCrSkip = 0);
+  void CopyData(const Data& aData);
 
   /**
    * Return a buffer to store image data in.
    * The default implementation returns memory that can
    * be freed wit delete[]
    */
   virtual PRUint8* AllocateBuffer(PRUint32 aSize);
 
-  /**
-   * Return the number of bytes of heap memory used to store this image.
-   */
-  virtual PRUint32 GetDataSize() { return mBufferSize; }
-
   already_AddRefed<gfxASurface> GetAsSurface();
 
-  virtual gfxIntSize GetSize() { return mSize; }
-
   void SetOffscreenFormat(gfxASurface::gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
   gfxASurface::gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
 
-  // XXX - not easy to protect these sadly.
   nsAutoArrayPtr<PRUint8> mBuffer;
   PRUint32 mBufferSize;
   Data mData;
   gfxIntSize mSize;
   gfxASurface::gfxImageFormat mOffscreenFormat;
   nsCountedRef<nsMainThreadSurfaceRef> mSurface;
   nsRefPtr<BufferRecycleBin> mRecycleBin;
-
-  PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
 };
 
 /**
  * Currently, the data in a CairoImage surface is treated as being in the
  * device output color space. This class is very simple as all backends
  * have to know about how to deal with drawing a cairo image.
  */
 class THEBES_API CairoImage : public Image {
@@ -822,9 +826,9 @@ public:
   gfxIntSize mSize;
   RemoteImageData::Format mFormat;
 };
 
 
 } //namespace
 } //namespace
 
-#endif
\ No newline at end of file
+#endif
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -219,17 +219,17 @@ ImageLayerD3D10::RenderLayer()
         (float)0,
         (float)size.width,
         (float)size.height)
       );
   } else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
     PlanarYCbCrImage *yuvImage =
       static_cast<PlanarYCbCrImage*>(image);
 
-    if (!yuvImage->mBufferSize) {
+    if (!yuvImage->IsValid()) {
       return;
     }
 
     if (!yuvImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
       AllocateTexturesYCbCr(yuvImage);
     }
 
     PlanarYCbCrD3D10BackendData *data =
@@ -256,17 +256,17 @@ ImageLayerD3D10::RenderLayer()
     effect()->GetVariableByName("tCb")->AsShaderResource()->SetResource(data->mCbView);
     effect()->GetVariableByName("tCr")->AsShaderResource()->SetResource(data->mCrView);
 
     /*
      * Send 3d control data and metadata to NV3DVUtils
      */
     if (GetNv3DVUtils()) {
       Nv_Stereo_Mode mode;
-      switch (yuvImage->mData.mStereoMode) {
+      switch (yuvImage->GetData()->mStereoMode) {
       case STEREO_MODE_LEFT_RIGHT:
         mode = NV_STEREO_MODE_LEFT_RIGHT;
         break;
       case STEREO_MODE_RIGHT_LEFT:
         mode = NV_STEREO_MODE_RIGHT_LEFT;
         break;
       case STEREO_MODE_BOTTOM_TOP:
         mode = NV_STEREO_MODE_BOTTOM_TOP;
@@ -277,37 +277,37 @@ ImageLayerD3D10::RenderLayer()
       case STEREO_MODE_MONO:
         mode = NV_STEREO_MODE_MONO;
         break;
       }
       
       // Send control data even in mono case so driver knows to leave stereo mode.
       GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
 
-      if (yuvImage->mData.mStereoMode != STEREO_MODE_MONO) {
+      if (yuvImage->GetData()->mStereoMode != STEREO_MODE_MONO) {
         // Dst resource is optional
-        GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->mData.mYSize.width, 
-                                           (unsigned int)yuvImage->mData.mYSize.height, (HANDLE)(data->mYTexture), (HANDLE)(NULL));
+        GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->GetData()->mYSize.width,
+                                           (unsigned int)yuvImage->GetData()->mYSize.height, (HANDLE)(data->mYTexture), (HANDLE)(NULL));
       }
     }
 
     effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
       ShaderConstantRectD3D10(
         (float)0,
         (float)0,
         (float)size.width,
         (float)size.height)
       );
 
     effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
       ShaderConstantRectD3D10(
-        (float)yuvImage->mData.mPicX / yuvImage->mData.mYSize.width,
-        (float)yuvImage->mData.mPicY / yuvImage->mData.mYSize.height,
-        (float)yuvImage->mData.mPicSize.width / yuvImage->mData.mYSize.width,
-        (float)yuvImage->mData.mPicSize.height / yuvImage->mData.mYSize.height)
+        (float)yuvImage->GetData()->mPicX / yuvImage->GetData()->mYSize.width,
+        (float)yuvImage->GetData()->mPicY / yuvImage->GetData()->mYSize.height,
+        (float)yuvImage->GetData()->mPicSize.width / yuvImage->GetData()->mYSize.width,
+        (float)yuvImage->GetData()->mPicSize.height / yuvImage->GetData()->mYSize.height)
        );
   }
   
   bool resetTexCoords = image->GetFormat() == ImageFormat::PLANAR_YCBCR;
   image = nullptr;
   autoLock.Unlock();
 
   technique->GetPassByIndex(0)->Apply(0);
@@ -325,36 +325,36 @@ ImageLayerD3D10::RenderLayer()
   GetContainer()->NotifyPaintedImage(image);
 }
 
 void ImageLayerD3D10::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage)
 {
   nsAutoPtr<PlanarYCbCrD3D10BackendData> backendData(
     new PlanarYCbCrD3D10BackendData);
 
-  PlanarYCbCrImage::Data &data = aImage->mData;
+  const PlanarYCbCrImage::Data *data = aImage->GetData();
 
   D3D10_SUBRESOURCE_DATA dataY;
   D3D10_SUBRESOURCE_DATA dataCb;
   D3D10_SUBRESOURCE_DATA dataCr;
   CD3D10_TEXTURE2D_DESC descY(DXGI_FORMAT_R8_UNORM,
-                              data.mYSize.width,
-                              data.mYSize.height, 1, 1);
+                              data->mYSize.width,
+                              data->mYSize.height, 1, 1);
   CD3D10_TEXTURE2D_DESC descCbCr(DXGI_FORMAT_R8_UNORM,
-                                 data.mCbCrSize.width,
-                                 data.mCbCrSize.height, 1, 1);
+                                 data->mCbCrSize.width,
+                                 data->mCbCrSize.height, 1, 1);
 
   descY.Usage = descCbCr.Usage = D3D10_USAGE_IMMUTABLE;
 
-  dataY.pSysMem = data.mYChannel;
-  dataY.SysMemPitch = data.mYStride;
-  dataCb.pSysMem = data.mCbChannel;
-  dataCb.SysMemPitch = data.mCbCrStride;
-  dataCr.pSysMem = data.mCrChannel;
-  dataCr.SysMemPitch = data.mCbCrStride;
+  dataY.pSysMem = data->mYChannel;
+  dataY.SysMemPitch = data->mYStride;
+  dataCb.pSysMem = data->mCbChannel;
+  dataCb.SysMemPitch = data->mCbCrStride;
+  dataCr.pSysMem = data->mCrChannel;
+  dataCr.SysMemPitch = data->mCbCrStride;
 
   HRESULT hr = device()->CreateTexture2D(&descY, &dataY, getter_AddRefs(backendData->mYTexture));
   if (!FAILED(hr)) {
       hr = device()->CreateTexture2D(&descCbCr, &dataCb, getter_AddRefs(backendData->mCbTexture));
   }
   if (!FAILED(hr)) {
       hr = device()->CreateTexture2D(&descCbCr, &dataCr, getter_AddRefs(backendData->mCrTexture));
   }
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -128,17 +128,17 @@ SurfaceToTexture(IDirect3DDevice9 *aDevi
 
 static void AllocateTexturesYCbCr(PlanarYCbCrImage *aImage,
                                   IDirect3DDevice9 *aDevice,
                                   LayerManagerD3D9 *aManager)
 {
   nsAutoPtr<PlanarYCbCrD3D9BackendData> backendData(
     new PlanarYCbCrD3D9BackendData);
 
-  PlanarYCbCrImage::Data &data = aImage->mData;
+  const PlanarYCbCrImage::Data *data = aImage->GetData();
 
   D3DLOCKED_RECT lockrectY;
   D3DLOCKED_RECT lockrectCb;
   D3DLOCKED_RECT lockrectCr;
   PRUint8* src;
   PRUint8* dest;
 
   nsRefPtr<IDirect3DSurface9> tmpSurfaceY;
@@ -155,41 +155,41 @@ static void AllocateTexturesYCbCr(Planar
     nsRefPtr<IDirect3DTexture9> tmpYTexture;
     nsRefPtr<IDirect3DTexture9> tmpCbTexture;
     nsRefPtr<IDirect3DTexture9> tmpCrTexture;
     // D3D9Ex does not support the managed pool, could use dynamic textures
     // here. But since an Image is immutable static textures are probably a
     // better idea.
 
     HRESULT hr;
-    hr = aDevice->CreateTexture(data.mYSize.width, data.mYSize.height,
+    hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height,
                                 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
                                 getter_AddRefs(backendData->mYTexture), NULL);
     if (!FAILED(hr)) {
-      hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
+      hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height,
                                   1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
                                   getter_AddRefs(backendData->mCbTexture), NULL);
     }
     if (!FAILED(hr)) {
-      hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
+      hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height,
                                   1, 0, D3DFMT_L8, D3DPOOL_DEFAULT,
                                   getter_AddRefs(backendData->mCrTexture), NULL);
     }
     if (!FAILED(hr)) {
-      hr = aDevice->CreateTexture(data.mYSize.width, data.mYSize.height,
+      hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height,
                                   1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
                                   getter_AddRefs(tmpYTexture), NULL);
     }
     if (!FAILED(hr)) {
-      hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
+      hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height,
                                   1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
                                   getter_AddRefs(tmpCbTexture), NULL);
     }
     if (!FAILED(hr)) {
-      hr = aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
+      hr = aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height,
                                   1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM,
                                   getter_AddRefs(tmpCrTexture), NULL);
     }
 
     if (FAILED(hr)) {
       aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (isD3D9Ex)"),
                               hr);
       return;
@@ -198,73 +198,73 @@ static void AllocateTexturesYCbCr(Planar
     tmpYTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceY));
     tmpCbTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCb));
     tmpCrTexture->GetSurfaceLevel(0, getter_AddRefs(tmpSurfaceCr));
     tmpSurfaceY->LockRect(&lockrectY, NULL, 0);
     tmpSurfaceCb->LockRect(&lockrectCb, NULL, 0);
     tmpSurfaceCr->LockRect(&lockrectCr, NULL, 0);
   } else {
     HRESULT hr;
-    hr = aDevice->CreateTexture(data.mYSize.width, data.mYSize.height,
+    hr = aDevice->CreateTexture(data->mYSize.width, data->mYSize.height,
                                 1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
                                 getter_AddRefs(backendData->mYTexture), NULL);
     if (!FAILED(hr)) {
-      aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
+      aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height,
                              1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
                              getter_AddRefs(backendData->mCbTexture), NULL);
     }
     if (!FAILED(hr)) {
-      aDevice->CreateTexture(data.mCbCrSize.width, data.mCbCrSize.height,
+      aDevice->CreateTexture(data->mCbCrSize.width, data->mCbCrSize.height,
                              1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
                              getter_AddRefs(backendData->mCrTexture), NULL);
     }
 
     if (FAILED(hr)) {
       aManager->ReportFailure(NS_LITERAL_CSTRING("PlanarYCbCrImageD3D9::AllocateTextures(): Failed to create texture (!isD3D9Ex)"),
                               hr);
       return;
     }
 
     /* lock the entire texture */
     backendData->mYTexture->LockRect(0, &lockrectY, NULL, 0);
     backendData->mCbTexture->LockRect(0, &lockrectCb, NULL, 0);
     backendData->mCrTexture->LockRect(0, &lockrectCr, NULL, 0);
   }
 
-  src  = data.mYChannel;
+  src  = data->mYChannel;
   //FIX cast
   dest = (PRUint8*)lockrectY.pBits;
 
   // copy over data
-  for (int h=0; h<data.mYSize.height; h++) {
-    memcpy(dest, src, data.mYSize.width);
+  for (int h=0; h<data->mYSize.height; h++) {
+    memcpy(dest, src, data->mYSize.width);
     dest += lockrectY.Pitch;
-    src += data.mYStride;
+    src += data->mYStride;
   }
 
-  src  = data.mCbChannel;
+  src  = data->mCbChannel;
   //FIX cast
   dest = (PRUint8*)lockrectCb.pBits;
 
   // copy over data
-  for (int h=0; h<data.mCbCrSize.height; h++) {
-    memcpy(dest, src, data.mCbCrSize.width);
+  for (int h=0; h<data->mCbCrSize.height; h++) {
+    memcpy(dest, src, data->mCbCrSize.width);
     dest += lockrectCb.Pitch;
-    src += data.mCbCrStride;
+    src += data->mCbCrStride;
   }
 
-  src  = data.mCrChannel;
+  src  = data->mCrChannel;
   //FIX cast
   dest = (PRUint8*)lockrectCr.pBits;
 
   // copy over data
-  for (int h=0; h<data.mCbCrSize.height; h++) {
-    memcpy(dest, src, data.mCbCrSize.width);
+  for (int h=0; h<data->mCbCrSize.height; h++) {
+    memcpy(dest, src, data->mCbCrSize.width);
     dest += lockrectCr.Pitch;
-    src += data.mCbCrStride;
+    src += data->mCbCrStride;
   }
 
   if (isD3D9Ex) {
     tmpSurfaceY->UnlockRect();
     tmpSurfaceCb->UnlockRect();
     tmpSurfaceCr->UnlockRect();
     nsRefPtr<IDirect3DSurface9> dstSurface;
     backendData->mYTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
@@ -295,30 +295,30 @@ ImageLayerD3D9::GetLayer()
   * If successful, aHasAlpha will be set to true if the texture has an
   * alpha component, false otherwise.
   */
 IDirect3DTexture9*
 ImageLayerD3D9::GetTexture(Image *aImage, bool& aHasAlpha)
 {
   NS_ASSERTION(aImage, "Null image.");
 
-  if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
+  if (aImage->GetFormat() == REMOTE_IMAGE_BITMAP) {
     RemoteBitmapImage *remoteImage =
       static_cast<RemoteBitmapImage*>(aImage);
       
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData());
       dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize, D3DFMT_A8R8G8B8);
       if (dat->mTexture) {
         aImage->SetBackendData(mozilla::layers::LAYERS_D3D9, dat.forget());
       }
     }
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
-  } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
+  } else if (aImage->GetFormat() == CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(aImage);
 
     if (!cairoImage->mSurface) {
       return nullptr;
     }
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
@@ -365,20 +365,20 @@ ImageLayerD3D9::RenderLayer()
   if (!image) {
     return;
   }
 
   SetShaderTransformAndOpacity();
 
   gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
 
-  if (image->GetFormat() == ImageFormat::CAIRO_SURFACE ||
-      image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP)
+  if (image->GetFormat() == CAIRO_SURFACE ||
+      image->GetFormat() == REMOTE_IMAGE_BITMAP)
   {
-    NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
+    NS_ASSERTION(image->GetFormat() != CAIRO_SURFACE ||
                  !static_cast<CairoImage*>(image)->mSurface ||
                  static_cast<CairoImage*>(image)->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
                  "Image layer has alpha image");
 
     bool hasAlpha = false;
     nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha);
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
@@ -407,17 +407,17 @@ ImageLayerD3D9::RenderLayer()
     if (mFilter == gfxPattern::FILTER_NEAREST) {
       device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
       device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     }
   } else {
     PlanarYCbCrImage *yuvImage =
       static_cast<PlanarYCbCrImage*>(image);
 
-    if (!yuvImage->mBufferSize) {
+    if (!yuvImage->IsValid()) {
       return;
     }
 
     if (!yuvImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       AllocateTexturesYCbCr(yuvImage, device(), mD3DManager);
     }
 
     PlanarYCbCrD3D9BackendData *data =
@@ -437,31 +437,31 @@ ImageLayerD3D9::RenderLayer()
                                        ShaderConstantRect(0,
                                                           0,
                                                           size.width,
                                                           size.height),
                                        1);
 
     device()->SetVertexShaderConstantF(CBvTextureCoords,
       ShaderConstantRect(
-        (float)yuvImage->mData.mPicX / yuvImage->mData.mYSize.width,
-        (float)yuvImage->mData.mPicY / yuvImage->mData.mYSize.height,
-        (float)yuvImage->mData.mPicSize.width / yuvImage->mData.mYSize.width,
-        (float)yuvImage->mData.mPicSize.height / yuvImage->mData.mYSize.height
+        (float)yuvImage->GetData()->mPicX / yuvImage->GetData()->mYSize.width,
+        (float)yuvImage->GetData()->mPicY / yuvImage->GetData()->mYSize.height,
+        (float)yuvImage->GetData()->mPicSize.width / yuvImage->GetData()->mYSize.width,
+        (float)yuvImage->GetData()->mPicSize.height / yuvImage->GetData()->mYSize.height
       ),
       1);
 
     mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, GetMaskLayer());
 
     /*
      * Send 3d control data and metadata
      */
     if (mD3DManager->GetNv3DVUtils()) {
       Nv_Stereo_Mode mode;
-      switch (yuvImage->mData.mStereoMode) {
+      switch (yuvImage->GetData()->mStereoMode) {
       case STEREO_MODE_LEFT_RIGHT:
         mode = NV_STEREO_MODE_LEFT_RIGHT;
         break;
       case STEREO_MODE_RIGHT_LEFT:
         mode = NV_STEREO_MODE_RIGHT_LEFT;
         break;
       case STEREO_MODE_BOTTOM_TOP:
         mode = NV_STEREO_MODE_BOTTOM_TOP;
@@ -472,23 +472,23 @@ ImageLayerD3D9::RenderLayer()
       case STEREO_MODE_MONO:
         mode = NV_STEREO_MODE_MONO;
         break;
       }
 
       // Send control data even in mono case so driver knows to leave stereo mode.
       mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
 
-      if (yuvImage->mData.mStereoMode != STEREO_MODE_MONO) {
+      if (yuvImage->GetData()->mStereoMode != STEREO_MODE_MONO) {
         mD3DManager->GetNv3DVUtils()->SendNv3DVControl(mode, true, FIREFOX_3DV_APP_HANDLE);
 
         nsRefPtr<IDirect3DSurface9> renderTarget;
         device()->GetRenderTarget(0, getter_AddRefs(renderTarget));
-        mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->mSize.width,
-                                                        (unsigned int)yuvImage->mSize.height, (HANDLE)(data->mYTexture), (HANDLE)(renderTarget));
+        mD3DManager->GetNv3DVUtils()->SendNv3DVMetaData((unsigned int)yuvImage->GetSize().width,
+                                                        (unsigned int)yuvImage->GetSize().height, (HANDLE)(data->mYTexture), (HANDLE)(renderTarget));
       }
     }
 
     // Linear scaling is default here, adhering to mFilter is difficult since
     // presumably even with point filtering we'll still want chroma upsampling
     // to be linear. In the current approach we can't.
     device()->SetTexture(0, data->mYTexture);
     device()->SetTexture(1, data->mCbTexture);
@@ -517,18 +517,18 @@ ImageLayerD3D9::GetAsTexture(gfxIntSize*
   AutoLockImage autoLock(GetContainer());
 
   Image *image = autoLock.GetImage();
 
   if (!image) {
     return nullptr;
   }
 
-  if (image->GetFormat() != ImageFormat::CAIRO_SURFACE &&
-      image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP) {
+  if (image->GetFormat() != CAIRO_SURFACE &&
+      image->GetFormat() != REMOTE_IMAGE_BITMAP) {
     return nullptr;
   }
   
   bool dontCare;
   *aSize = image->GetSize();
   nsRefPtr<IDirect3DTexture9> result = GetTexture(image, dontCare);
   return result.forget();
 }
@@ -611,42 +611,42 @@ ShadowImageLayerD3D9::RenderLayer()
 {
   if (mD3DManager->CompositingDisabled()) {
     return;
   }
 
   if (mBuffer) {
     mBuffer->RenderTo(mD3DManager, GetEffectiveVisibleRegion());
   } else if (mYCbCrImage) {
-    if (!mYCbCrImage->mBufferSize) {
+    if (!mYCbCrImage->IsValid()) {
       return;
     }
 
     if (!mYCbCrImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       AllocateTexturesYCbCr(mYCbCrImage, device(), mD3DManager);
     }
 
     PlanarYCbCrD3D9BackendData *data =
       static_cast<PlanarYCbCrD3D9BackendData*>(mYCbCrImage->GetBackendData(mozilla::layers::LAYERS_D3D9));
 
     if (!data) {
       return;
     }
 
-    if (!mYCbCrImage->mBufferSize) {
+    if (!mYCbCrImage->IsValid()) {
       return;
     }
 
     SetShaderTransformAndOpacity();
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(0,
                                                           0,
-                                                          mYCbCrImage->mSize.width,
-                                                          mYCbCrImage->mSize.height),
+                                                          mYCbCrImage->GetSize().width,
+                                                          mYCbCrImage->GetSize().height),
                                        1);
 
     mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, GetMaskLayer());
 
     /*
      * Send 3d control data and metadata
      */
     if (mD3DManager->GetNv3DVUtils()) {
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -248,17 +248,17 @@ ImageLayerOGL::RenderLayer(int,
     "Remote images aren't handled yet in OGL layers!");
   NS_ASSERTION(mScaleMode == SCALE_NONE,
     "Scale modes other than none not handled yet in OGL layers!");
 
   if (image->GetFormat() == PLANAR_YCBCR) {
     PlanarYCbCrImage *yuvImage =
       static_cast<PlanarYCbCrImage*>(image);
 
-    if (!yuvImage->mBufferSize) {
+    if (!yuvImage->IsValid()) {
       return;
     }
 
     PlanarYCbCrOGLBackendData *data =
       static_cast<PlanarYCbCrOGLBackendData*>(yuvImage->GetBackendData(LAYERS_OPENGL));
 
     if (data && data->mTextures->GetGLContext() != gl()) {
       // If these textures were allocated by another layer manager,
@@ -288,28 +288,28 @@ ImageLayerOGL::RenderLayer(int,
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, data->mTextures[0].GetTextureID());
     gl()->ApplyFilterToBoundTexture(mFilter);
     
     ShaderProgramOGL *program = mOGLManager->GetProgram(YCbCrLayerProgramType,
                                                         GetMaskLayer());
 
     program->Activate();
     program->SetLayerQuadRect(nsIntRect(0, 0,
-                                        yuvImage->mSize.width,
-                                        yuvImage->mSize.height));
+                                        yuvImage->GetSize().width,
+                                        yuvImage->GetSize().height));
     program->SetLayerTransform(GetEffectiveTransform());
     program->SetLayerOpacity(GetEffectiveOpacity());
     program->SetRenderOffset(aOffset);
     program->SetYCbCrTextureUnits(0, 1, 2);
     program->LoadMask(GetMaskLayer());
 
     mOGLManager->BindAndDrawQuadWithTextureRect(program,
-                                                yuvImage->mData.GetPictureRect(),
-                                                nsIntSize(yuvImage->mData.mYSize.width,
-                                                          yuvImage->mData.mYSize.height));
+                                                yuvImage->GetData()->GetPictureRect(),
+                                                nsIntSize(yuvImage->GetData()->mYSize.width,
+                                                          yuvImage->GetData()->mYSize.height));
 
     // We shouldn't need to do this, but do it anyway just in case
     // someone else forgets.
     gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
   } else if (image->GetFormat() == CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(image);
 
@@ -527,42 +527,42 @@ ImageLayerOGL::ImageLayerOGL(LayerManage
   , mTextureRecycleBin(new TextureRecycleBin())
 { 
   mImplData = static_cast<LayerOGL*>(this);
 }
 
 void
 ImageLayerOGL::AllocateTexturesYCbCr(PlanarYCbCrImage *aImage)
 {
-  if (!aImage->mBufferSize)
+  if (!aImage->IsValid())
     return;
 
   nsAutoPtr<PlanarYCbCrOGLBackendData> backendData(
     new PlanarYCbCrOGLBackendData);
 
-  PlanarYCbCrImage::Data &data = aImage->mData;
+  const PlanarYCbCrImage::Data *data = aImage->GetData();
 
   gl()->MakeCurrent();
 
-  mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_Y, data.mYSize, gl(), &backendData->mTextures[0]);
+  mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_Y, data->mYSize, gl(), &backendData->mTextures[0]);
   SetClamping(gl(), backendData->mTextures[0].GetTextureID());
 
-  mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data.mCbCrSize, gl(), &backendData->mTextures[1]);
+  mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data->mCbCrSize, gl(), &backendData->mTextures[1]);
   SetClamping(gl(), backendData->mTextures[1].GetTextureID());
 
-  mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data.mCbCrSize, gl(), &backendData->mTextures[2]);
+  mTextureRecycleBin->GetTexture(TextureRecycleBin::TEXTURE_C, data->mCbCrSize, gl(), &backendData->mTextures[2]);
   SetClamping(gl(), backendData->mTextures[2].GetTextureID());
 
-  UploadYUVToTexture(gl(), aImage->mData,
+  UploadYUVToTexture(gl(), *data,
                      &backendData->mTextures[0],
                      &backendData->mTextures[1],
                      &backendData->mTextures[2]);
 
-  backendData->mYSize = aImage->mData.mYSize;
-  backendData->mCbCrSize = aImage->mData.mCbCrSize;
+  backendData->mYSize = data->mYSize;
+  backendData->mCbCrSize = data->mCbCrSize;
   backendData->mTextureRecycleBin = mTextureRecycleBin;
 
   aImage->SetBackendData(LAYERS_OPENGL, backendData.forget());
 }
 
 void
 ImageLayerOGL::AllocateTexturesCairo(CairoImage *aImage)
 {