Back out bug 656185 due to windows compile failures
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 27 Jun 2011 15:21:22 +1200
changeset 71820 05058eacd33ae47c88f3171ca01f6e64c719cd01
parent 71819 3657ab7434b7cd72db494f0ebd9239951acf23a6
child 71821 aee9017b0b4fb4e5c962d83d0ae8d038a2df62f0
push id20613
push usermlamouri@mozilla.com
push dateMon, 27 Jun 2011 09:03:51 +0000
treeherdermozilla-central@aee9017b0b4f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs656185
milestone7.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
Back out bug 656185 due to windows compile failures
gfx/layers/ImageLayers.h
gfx/layers/Layers.cpp
gfx/layers/basic/BasicImages.cpp
gfx/layers/basic/BasicLayers.cpp
gfx/layers/d3d10/ImageLayerD3D10.cpp
gfx/layers/d3d10/ImageLayerD3D10.h
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/ImageLayerD3D9.h
gfx/layers/ipc/PLayers.ipdl
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.h
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/LayerManagerOGL.h
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/thebes/GLContext.cpp
gfx/ycbcr/README
gfx/ycbcr/TypeFromSize.patch
gfx/ycbcr/update.sh
gfx/ycbcr/yuv_convert.cpp
gfx/ycbcr/yuv_convert.h
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -402,22 +402,16 @@ public:
     PRUint8* mCrChannel;
     PRInt32 mCbCrStride;
     gfxIntSize mCbCrSize;
     // Picture region
     PRUint32 mPicX;
     PRUint32 mPicY;
     gfxIntSize mPicSize;
     StereoMode mStereoMode;
-
-    nsIntRect GetPictureRect() const {
-      return nsIntRect(mPicX, mPicY,
-                       mPicSize.width,
-                       mPicSize.height);
-    }
   };
 
   enum {
     MAX_DIMENSION = 16384
   };
 
   /**
    * This makes a copy of the data buffers.
@@ -434,30 +428,16 @@ public:
    */
   virtual void SetDelayedConversion(PRBool aDelayed) { }
 
   /**
    * Grab the original YUV data. This is optional.
    */
   virtual const Data* GetData() { return nsnull; }
 
-  /**
-   * Make a copy of the YCbCr data.
-   *
-   * @param aDest           Data object to store the plane data in.
-   * @param aDestSize       Size of the Y plane that was copied.
-   * @param aDestBufferSize Number of bytes allocated for storage.
-   * @param aData           Input image data.
-   * @return                Raw data pointer for the planes or nsnull on failure.
-   */
-  PRUint8 *CopyData(Data& aDest, gfxIntSize& aDestSize,
-                    PRUint32& aDestBufferSize, const Data& aData);
-
-  virtual PRUint8* AllocateBuffer(PRUint32 aSize) { return new (mozilla::fallible_t()) PRUint8[aSize]; };
-
 protected:
   PlanarYCbCrImage(void* aImplData) : Image(aImplData, PLANAR_YCBCR) {}
 };
 
 /**
  * Currently, the data in a CairoImage surface is treated as being in the
  * device output color space.
  */
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -476,59 +476,16 @@ ContainerLayer::DidRemoveChild(Layer* aL
 void
 ContainerLayer::DidInsertChild(Layer* aLayer)
 {
   if (aLayer->GetType() == TYPE_READBACK) {
     mMayHaveReadbackChild = PR_TRUE;
   }
 }
 
-PRUint8*
-PlanarYCbCrImage::CopyData(Data& aDest, gfxIntSize& aDestSize,
-                           PRUint32& aDestBufferSize, const Data& aData)
-{
-  aDest = aData;
-
-  /* We always have a multiple of 16 width so we can force the stride */
-  aDest.mYStride = aDest.mYSize.width;
-  aDest.mCbCrStride = aDest.mCbCrSize.width;
-
-  // update buffer size
-  aDestBufferSize = aDest.mCbCrStride * aDest.mCbCrSize.height * 2 +
-                    aDest.mYStride * aDest.mYSize.height;
-
-  // get new buffer
-  PRUint8* buffer = AllocateBuffer(aDestBufferSize); 
-  if (!buffer)
-    return nsnull;
-
-  aDest.mYChannel = buffer;
-  aDest.mCbChannel = aDest.mYChannel + aDest.mYStride * aDest.mYSize.height;
-  aDest.mCrChannel = aDest.mCbChannel + aDest.mCbCrStride * aDest.mCbCrSize.height;
-
-  for (int i = 0; i < aDest.mYSize.height; i++) {
-    memcpy(aDest.mYChannel + i * aDest.mYStride,
-           aData.mYChannel + i * aData.mYStride,
-           aDest.mYStride);
-  }
-  for (int i = 0; i < aDest.mCbCrSize.height; i++) {
-    memcpy(aDest.mCbChannel + i * aDest.mCbCrStride,
-           aData.mCbChannel + i * aData.mCbCrStride,
-           aDest.mCbCrStride);
-    memcpy(aDest.mCrChannel + i * aDest.mCbCrStride,
-           aData.mCrChannel + i * aData.mCbCrStride,
-           aDest.mCbCrStride);
-  }
-
-  aDestSize = aData.mPicSize;
-  return buffer;
-}
-                         
-
-
 #ifdef MOZ_LAYERS_HAVE_LOG
 
 static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);
 
 void
 Layer::Dump(FILE* aFile, const char* aPrefix)
 {
   DumpSelf(aFile, aPrefix);
--- a/gfx/layers/basic/BasicImages.cpp
+++ b/gfx/layers/basic/BasicImages.cpp
@@ -144,26 +144,88 @@ void
 BasicPlanarYCbCrImage::SetData(const Data& aData)
 {
   // Do some sanity checks to prevent integer overflow
   if (aData.mYSize.width > 16384 || aData.mYSize.height > 16384) {
     NS_ERROR("Illegal width or height");
     return;
   }
   
+  gfx::YUVType type = gfx::YV12;
+  int width_shift = 0;
+  int height_shift = 0;
+  if (aData.mYSize.width == aData.mCbCrSize.width &&
+      aData.mYSize.height == aData.mCbCrSize.height) {
+    type = gfx::YV24;
+    width_shift = 0;
+    height_shift = 0;
+  }
+  else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+           aData.mYSize.height == aData.mCbCrSize.height) {
+    type = gfx::YV16;
+    width_shift = 1;
+    height_shift = 0;
+  }
+  else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+           aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
+    type = gfx::YV12;
+    width_shift = 1;
+    height_shift = 1;
+  }
+  else {
+    NS_ERROR("YCbCr format not supported");
+  }
+
   if (mDelayedConversion) {
-    mBuffer = CopyData(mData, mSize, mBufferSize, aData);
+
+    mData = aData;
+    mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
+    // Round up the values for width and height to make sure we sample enough data
+    // for the last pixel - See bug 590735
+    if (width_shift && (aData.mPicSize.width & 1)) {
+      mData.mCbCrStride++;
+      mData.mCbCrSize.width++;
+    }
+    mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
+    if (height_shift && (aData.mPicSize.height & 1)) {
+        mData.mCbCrSize.height++;
+    }
+    mData.mYSize = aData.mPicSize;
+    mData.mYStride = mData.mYSize.width;
+    mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+                  mData.mYStride * mData.mYSize.height;
+    mBuffer = new PRUint8[mBufferSize];
+    
+    mData.mYChannel = mBuffer;
+    mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+    mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+    int cbcr_x = aData.mPicX >> width_shift;
+    int cbcr_y = aData.mPicY >> height_shift;
+
+    for (int i = 0; i < mData.mYSize.height; i++) {
+      memcpy(mData.mYChannel + i * mData.mYStride,
+             aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
+             mData.mYStride);
+    }
+    for (int i = 0; i < mData.mCbCrSize.height; i++) {
+      memcpy(mData.mCbChannel + i * mData.mCbCrStride,
+             aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+             mData.mCbCrStride);
+    }
+    for (int i = 0; i < mData.mCbCrSize.height; i++) {
+      memcpy(mData.mCrChannel + i * mData.mCbCrStride,
+             aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+             mData.mCbCrStride);
+    }
+
+    // Fix picture rect to be correct
+    mData.mPicX = mData.mPicY = 0;
+    mSize = aData.mPicSize;
     return;
   }
-  
-  gfx::YUVType type = 
-    gfx::TypeFromSize(aData.mYSize.width,
-                      aData.mYSize.height,
-                      aData.mCbCrSize.width,
-                      aData.mCbCrSize.height);
 
   gfxASurface::gfxImageFormat format = GetOffscreenFormat();
 
   // 'prescale' is true if the scaling is to be done as part of the
   // YCbCr to RGB conversion rather than on the RGB data when rendered.
   PRBool prescale = mScaleHint.width > 0 && mScaleHint.height > 0 &&
                     mScaleHint != aData.mPicSize;
   if (format == gfxASurface::ImageFormatRGB16_565) {
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -2218,43 +2218,37 @@ BasicShadowableImageLayer::Paint(gfxCont
       if (!BasicManager()->AllocDoubleBuffer(
             mCbCrSize,
             gfxASurface::CONTENT_ALPHA,
             getter_AddRefs(tmpVSurface), getter_AddRefs(mBackBufferV)))
         NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
 
       YUVImage yuv(tmpYSurface->GetShmem(),
                    tmpUSurface->GetShmem(),
-                   tmpVSurface->GetShmem(),
-                   data->GetPictureRect());
+                   tmpVSurface->GetShmem());
 
       BasicManager()->CreatedImageBuffer(BasicManager()->Hold(this),
                                          nsIntSize(mSize.width, mSize.height),
                                          yuv);
 
     }
       
-    for (int i = 0; i < data->mYSize.height; i++) {
-      memcpy(mBackBufferY->Data() + i * mBackBufferY->Stride(),
-             data->mYChannel + i * data->mYStride,
-             data->mYSize.width);
-    }
-    for (int i = 0; i < data->mCbCrSize.height; i++) {
-      memcpy(mBackBufferU->Data() + i * mBackBufferU->Stride(),
-             data->mCbChannel + i * data->mCbCrStride,
-             data->mCbCrSize.width);
-      memcpy(mBackBufferV->Data() + i * mBackBufferV->Stride(),
-             data->mCrChannel + i * data->mCbCrStride,
-             data->mCbCrSize.width);
-    }
+    memcpy(mBackBufferY->Data(), 
+           data->mYChannel, 
+           data->mYStride * mSize.height);
+    memcpy(mBackBufferU->Data(), 
+           data->mCbChannel, 
+           data->mCbCrStride * mCbCrSize.height);
+    memcpy(mBackBufferV->Data(), 
+           data->mCrChannel, 
+           data->mCbCrStride * mCbCrSize.height);
       
     YUVImage yuv(mBackBufferY->GetShmem(),
                  mBackBufferU->GetShmem(),
-                 mBackBufferV->GetShmem(),
-                 data->GetPictureRect());
+                 mBackBufferV->GetShmem());
   
     BasicManager()->PaintedImage(BasicManager()->Hold(this),
                                  yuv);
 
     return;
   }
 
   gfxIntSize oldSize = mSize;
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -343,49 +343,103 @@ ImageLayerD3D10::RenderLayer()
 
     effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
       ShaderConstantRectD3D10(
         (float)0,
         (float)0,
         (float)yuvImage->mSize.width,
         (float)yuvImage->mSize.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)
-       );
   }
 
   technique->GetPassByIndex(0)->Apply(0);
   device()->Draw(4, 0);
 
-  if (image->GetFormat() == Image::PLANAR_YCBCR) {
-    effect()->GetVariableByName("vTextureCoords")->AsVector()->
-      SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
-  }
-
   GetContainer()->NotifyPaintedImage(image);
 }
 
 PlanarYCbCrImageD3D10::PlanarYCbCrImageD3D10(ID3D10Device1 *aDevice)
   : PlanarYCbCrImage(static_cast<ImageD3D10*>(this))
   , mDevice(aDevice)
   , mHasData(PR_FALSE)
 {
 }
 
 void
 PlanarYCbCrImageD3D10::SetData(const PlanarYCbCrImage::Data &aData)
 {
-  PRUint32 dummy;
-  mBuffer = CopyData(mData, mSize, dummy, aData);
+  // XXX - For D3D10Ex we really should just copy to systemmem surfaces here.
+  // For now, we copy the data
+  int width_shift = 0;
+  int height_shift = 0;
+  if (aData.mYSize.width == aData.mCbCrSize.width &&
+      aData.mYSize.height == aData.mCbCrSize.height) {
+     // YV24 format
+     width_shift = 0;
+     height_shift = 0;
+     mType = gfx::YV24;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height == aData.mCbCrSize.height) {
+    // YV16 format
+    width_shift = 1;
+    height_shift = 0;
+    mType = gfx::YV16;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
+      // YV12 format
+    width_shift = 1;
+    height_shift = 1;
+    mType = gfx::YV12;
+  } else {
+    NS_ERROR("YCbCr format not supported");
+  }
+
+  mData = aData;
+  mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
+  // Round up the values for width and height to make sure we sample enough data
+  // for the last pixel - See bug 590735
+  if (width_shift && (aData.mPicSize.width & 1)) {
+    mData.mCbCrStride++;
+    mData.mCbCrSize.width++;
+  }
+  mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
+  if (height_shift && (aData.mPicSize.height & 1)) {
+      mData.mCbCrSize.height++;
+  }
+  mData.mYSize = aData.mPicSize;
+  mData.mYStride = mData.mYSize.width;
+
+  mBuffer = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+                        mData.mYStride * mData.mYSize.height];
+  mData.mYChannel = mBuffer;
+  mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+  mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+
+  int cbcr_x = aData.mPicX >> width_shift;
+  int cbcr_y = aData.mPicY >> height_shift;
+
+  for (int i = 0; i < mData.mYSize.height; i++) {
+    memcpy(mData.mYChannel + i * mData.mYStride,
+           aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
+           mData.mYStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCbChannel + i * mData.mCbCrStride,
+           aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCrChannel + i * mData.mCbCrStride,
+           aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+
+  // Fix picture rect to be correct
+  mData.mPicX = mData.mPicY = 0;
+  mSize = aData.mPicSize;
 
   AllocateTextures();
 
   mHasData = PR_TRUE;
 }
 
 void
 PlanarYCbCrImageD3D10::AllocateTextures()
@@ -417,36 +471,30 @@ PlanarYCbCrImageD3D10::AllocateTextures(
   mDevice->CreateShaderResourceView(mCrTexture, NULL, getter_AddRefs(mCrView));
 }
 
 already_AddRefed<gfxASurface>
 PlanarYCbCrImageD3D10::GetAsSurface()
 {
   nsRefPtr<gfxImageSurface> imageSurface =
     new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
-  
-  gfx::YUVType type = 
-    gfx::TypeFromSize(mData.mYSize.width,
-                      mData.mYSize.height,
-                      mData.mCbCrSize.width,
-                      mData.mCbCrSize.height);
 
   // Convert from YCbCr to RGB now
   gfx::ConvertYCbCrToRGB32(mData.mYChannel,
                            mData.mCbChannel,
                            mData.mCrChannel,
                            imageSurface->Data(),
-                           mData.mPicX,
-                           mData.mPicY,
-                           mData.mPicSize.width,
-                           mData.mPicSize.height,
+                           0,
+                           0,
+                           mSize.width,
+                           mSize.height,
                            mData.mYStride,
                            mData.mCbCrStride,
                            imageSurface->Stride(),
-                           type);
+                           mType);
 
   return imageSurface.forget().get();
 }
 
 CairoImageD3D10::~CairoImageD3D10()
 {
 }
 
--- a/gfx/layers/d3d10/ImageLayerD3D10.h
+++ b/gfx/layers/d3d10/ImageLayerD3D10.h
@@ -122,16 +122,17 @@ public:
   gfxIntSize mSize;
   nsRefPtr<ID3D10Texture2D> mYTexture;
   nsRefPtr<ID3D10Texture2D> mCrTexture;
   nsRefPtr<ID3D10Texture2D> mCbTexture;
   nsRefPtr<ID3D10ShaderResourceView> mYView;
   nsRefPtr<ID3D10ShaderResourceView> mCbView;
   nsRefPtr<ID3D10ShaderResourceView> mCrView;
   PRPackedBool mHasData;
+  gfx::YUVType mType; 
 };
 
 
 class THEBES_API CairoImageD3D10 : public CairoImage,
                                    public ImageD3D10
 {
 public:
   CairoImageD3D10(ID3D10Device1 *aDevice)
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -282,25 +282,16 @@ ImageLayerD3D9::RenderLayer()
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(0,
                                                           0,
                                                           yuvImage->mSize.width,
                                                           yuvImage->mSize.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
-      ),
-      1);
-
     mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER);
 
     /*
      * Send 3d control data and metadata
      */
     if (mD3DManager->GetNv3DVUtils()) {
       Nv_Stereo_Mode mode;
       switch (yuvImage->mData.mStereoMode) {
@@ -338,19 +329,16 @@ ImageLayerD3D9::RenderLayer()
     // presumably even with point filtering we'll still want chroma upsampling
     // to be linear. In the current approach we can't.
     device()->SetTexture(0, yuvImage->mYTexture);
     device()->SetTexture(1, yuvImage->mCbTexture);
     device()->SetTexture(2, yuvImage->mCrTexture);
 
     device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
 
-    device()->SetVertexShaderConstantF(CBvTextureCoords,
-      ShaderConstantRect(0, 0, 1.0f, 1.0f), 1);
-
   } else if (image->GetFormat() == Image::CAIRO_SURFACE) {
     CairoImageD3D9 *cairoImage =
       static_cast<CairoImageD3D9*>(image.get());
     ImageContainerD3D9 *container =
       static_cast<ImageContainerD3D9*>(GetContainer());
 
     if (container->device() != device()) {
       // Ensure future images get created with the right device.
@@ -393,18 +381,85 @@ PlanarYCbCrImageD3D9::PlanarYCbCrImageD3
   : PlanarYCbCrImage(static_cast<ImageD3D9*>(this))
   , mHasData(PR_FALSE)
 {
 }
 
 void
 PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
 {
-  PRUint32 dummy;
-  mBuffer = CopyData(mData, mSize, dummy, aData);
+  // XXX - For D3D9Ex we really should just copy to systemmem surfaces here.
+  // For now, we copy the data
+  int width_shift = 0;
+  int height_shift = 0;
+  if (aData.mYSize.width == aData.mCbCrSize.width &&
+      aData.mYSize.height == aData.mCbCrSize.height) {
+     // YV24 format
+     width_shift = 0;
+     height_shift = 0;
+     mType = gfx::YV24;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height == aData.mCbCrSize.height) {
+    // YV16 format
+    width_shift = 1;
+    height_shift = 0;
+    mType = gfx::YV16;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
+      // YV12 format
+    width_shift = 1;
+    height_shift = 1;
+    mType = gfx::YV12;
+  } else {
+    NS_ERROR("YCbCr format not supported");
+  }
+
+  mData = aData;
+  mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
+  // Round up the values for width and height to make sure we sample enough data
+  // for the last pixel - See bug 590735
+  if (width_shift && (aData.mPicSize.width & 1)) {
+    mData.mCbCrStride++;
+    mData.mCbCrSize.width++;
+  }
+  mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
+  if (height_shift && (aData.mPicSize.height & 1)) {
+      mData.mCbCrSize.height++;
+  }
+  mData.mYSize = aData.mPicSize;
+  mData.mYStride = mData.mYSize.width;
+
+  mBuffer = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+                        mData.mYStride * mData.mYSize.height];
+  mData.mYChannel = mBuffer;
+  mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+  mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+
+  int cbcr_x = aData.mPicX >> width_shift;
+  int cbcr_y = aData.mPicY >> height_shift;
+
+  for (int i = 0; i < mData.mYSize.height; i++) {
+    memcpy(mData.mYChannel + i * mData.mYStride,
+           aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
+           mData.mYStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCbChannel + i * mData.mCbCrStride,
+           aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCrChannel + i * mData.mCbCrStride,
+           aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+
+  // Fix picture rect to be correct
+  mData.mPicX = mData.mPicY = 0;
+  mSize = aData.mPicSize;
 
   mHasData = PR_TRUE;
 }
 
 void
 PlanarYCbCrImageD3D9::AllocateTextures(IDirect3DDevice9 *aDevice)
 {
   D3DLOCKED_RECT lockrectY;
@@ -527,36 +582,30 @@ PlanarYCbCrImageD3D9::FreeTextures()
 {
 }
 
 already_AddRefed<gfxASurface>
 PlanarYCbCrImageD3D9::GetAsSurface()
 {
   nsRefPtr<gfxImageSurface> imageSurface =
     new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
-  
-  gfx::YUVType type = 
-    gfx::TypeFromSize(mData.mYSize.width,
-                      mData.mYSize.height,
-                      mData.mCbCrSize.width,
-                      mData.mCbCrSize.height);
 
   // Convert from YCbCr to RGB now
   gfx::ConvertYCbCrToRGB32(mData.mYChannel,
                            mData.mCbChannel,
                            mData.mCrChannel,
                            imageSurface->Data(),
-                           mData.mPicX,
-                           mData.mPicY,
-                           mData.mPicSize.width,
-                           mData.mPicSize.height,
+                           0,
+                           0,
+                           mSize.width,
+                           mSize.height,
                            mData.mYStride,
                            mData.mCbCrStride,
                            imageSurface->Stride(),
-                           type);
+                           mType);
 
   return imageSurface.forget().get();
 }
 
 CairoImageD3D9::~CairoImageD3D9()
 {
 }
 
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -127,16 +127,17 @@ public:
   nsAutoArrayPtr<PRUint8> mBuffer;
   LayerManagerD3D9 *mManager;
   Data mData;
   gfxIntSize mSize;
   nsRefPtr<IDirect3DTexture9> mYTexture;
   nsRefPtr<IDirect3DTexture9> mCrTexture;
   nsRefPtr<IDirect3DTexture9> mCbTexture;
   PRPackedBool mHasData;
+  gfx::YUVType mType; 
 };
 
 
 class THEBES_API CairoImageD3D9 : public CairoImage,
                                   public ImageD3D9
 {
 public:
   CairoImageD3D9(IDirect3DDevice9 *aDevice)
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -82,17 +82,16 @@ union SurfaceDescriptor {
   Shmem;
   SurfaceDescriptorX11;
 };
 
 struct YUVImage {
   Shmem Ydata;
   Shmem Udata;
   Shmem Vdata;
-  nsIntRect picture;
 };
 
 union SharedImage {
   SurfaceDescriptor;
   YUVImage;
 };
 
 struct ThebesBuffer {
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -271,39 +271,33 @@ ImageContainerOGL::GetCurrentAsSurface(g
   if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
     PlanarYCbCrImageOGL *yuvImage =
       static_cast<PlanarYCbCrImageOGL*>(mActiveImage.get());
     if (!yuvImage->HasData()) {
       *aSize = gfxIntSize(0, 0);
       return nsnull;
     }
 
-    size = yuvImage->mData.mPicSize;
+    size = yuvImage->mSize;
 
     nsRefPtr<gfxImageSurface> imageSurface =
       new gfxImageSurface(size, gfxASurface::ImageFormatRGB24);
-  
-    gfx::YUVType type = 
-      gfx::TypeFromSize(yuvImage->mData.mYSize.width,
-                        yuvImage->mData.mYSize.height,
-                        yuvImage->mData.mCbCrSize.width,
-                        yuvImage->mData.mCbCrSize.height);
 
     gfx::ConvertYCbCrToRGB32(yuvImage->mData.mYChannel,
                              yuvImage->mData.mCbChannel,
                              yuvImage->mData.mCrChannel,
                              imageSurface->Data(),
-                             yuvImage->mData.mPicX,
-                             yuvImage->mData.mPicY,
+                             0,
+                             0,
                              size.width,
                              size.height,
                              yuvImage->mData.mYStride,
                              yuvImage->mData.mCbCrStride,
                              imageSurface->Stride(),
-                             type);
+                             yuvImage->mType);
 
     *aSize = size;
     return imageSurface.forget().get();
   }
 
   if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
     CairoImageOGL *cairoImage =
       static_cast<CairoImageOGL*>(mActiveImage.get());
@@ -433,20 +427,17 @@ ImageLayerOGL::RenderLayer(int,
     program->SetLayerQuadRect(nsIntRect(0, 0,
                                         yuvImage->mSize.width,
                                         yuvImage->mSize.height));
     program->SetLayerTransform(GetEffectiveTransform());
     program->SetLayerOpacity(GetEffectiveOpacity());
     program->SetRenderOffset(aOffset);
     program->SetYCbCrTextureUnits(0, 1, 2);
 
-    mOGLManager->BindAndDrawQuadWithTextureRect(program,
-                                                yuvImage->mData.GetPictureRect(),
-                                                nsIntSize(yuvImage->mData.mYSize.width,
-                                                          yuvImage->mData.mYSize.height));
+    mOGLManager->BindAndDrawQuad(program);
 
     // 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() == Image::CAIRO_SURFACE) {
     CairoImageOGL *cairoImage =
       static_cast<CairoImageOGL*>(image.get());
 
@@ -666,21 +657,94 @@ PlanarYCbCrImageOGL::~PlanarYCbCrImageOG
     mRecycleBin->RecycleTexture(&mTextures[1], RecycleBin::TEXTURE_C, mData.mCbCrSize);
     mRecycleBin->RecycleTexture(&mTextures[2], RecycleBin::TEXTURE_C, mData.mCbCrSize);
   }
 }
 
 void
 PlanarYCbCrImageOGL::SetData(const PlanarYCbCrImage::Data &aData)
 {
+  // For now, we copy the data
+  int width_shift = 0;
+  int height_shift = 0;
+  if (aData.mYSize.width == aData.mCbCrSize.width &&
+      aData.mYSize.height == aData.mCbCrSize.height) {
+     // YV24 format
+     width_shift = 0;
+     height_shift = 0;
+     mType = gfx::YV24;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height == aData.mCbCrSize.height) {
+    // YV16 format
+    width_shift = 1;
+    height_shift = 0;
+    mType = gfx::YV16;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
+      // YV12 format
+    width_shift = 1;
+    height_shift = 1;
+    mType = gfx::YV12;
+  } else {
+    NS_ERROR("YCbCr format not supported");
+  }
+  
+  mData = aData;
+  mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
+  // Round up the values for width and height to make sure we sample enough data
+  // for the last pixel - See bug 590735
+  if (width_shift && (aData.mPicSize.width & 1)) {
+    mData.mCbCrStride++;
+    mData.mCbCrSize.width++;
+  }
+  mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
+  if (height_shift && (aData.mPicSize.height & 1)) {
+      mData.mCbCrSize.height++;
+  }
+  mData.mYSize = aData.mPicSize;
+  mData.mYStride = mData.mYSize.width;
+
   // Recycle the previous image main-memory buffer now that we're about to get a new buffer
   if (mBuffer)
     mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
-  
-  mBuffer = CopyData(mData, mSize, mBufferSize, aData);
+
+  // update buffer size
+  mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+                mData.mYStride * mData.mYSize.height;
+
+  // get new buffer
+  mBuffer = mRecycleBin->GetBuffer(mBufferSize);
+  if (!mBuffer)
+    return;
+
+  mData.mYChannel = mBuffer;
+  mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+  mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+  int cbcr_x = aData.mPicX >> width_shift;
+  int cbcr_y = aData.mPicY >> height_shift;
+
+  for (int i = 0; i < mData.mYSize.height; i++) {
+    memcpy(mData.mYChannel + i * mData.mYStride,
+           aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
+           mData.mYStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCbChannel + i * mData.mCbCrStride,
+           aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCrChannel + i * mData.mCbCrStride,
+           aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+
+  // Fix picture rect to be correct
+  mData.mPicX = mData.mPicY = 0;
+  mSize = aData.mPicSize;
 
   mHasData = PR_TRUE;
 }
 
 void
 PlanarYCbCrImageOGL::AllocateTextures(mozilla::gl::GLContext *gl)
 {
   gl->MakeCurrent();
@@ -696,38 +760,70 @@ PlanarYCbCrImageOGL::AllocateTextures(mo
 }
 
 static void
 UploadYUVToTexture(GLContext* gl, const PlanarYCbCrImage::Data& aData, 
                    GLTexture* aYTexture,
                    GLTexture* aUTexture,
                    GLTexture* aVTexture)
 {
-  nsIntRect size(0, 0, aData.mYSize.width, aData.mYSize.height);
-  GLuint texture = aYTexture->GetTextureID();
-  nsRefPtr<gfxASurface> surf = new gfxImageSurface(aData.mYChannel,
-                                                   aData.mYSize,
-                                                   aData.mYStride,
-                                                   gfxASurface::ImageFormatA8);
-  gl->UploadSurfaceToTexture(surf, size, texture, true);
+  GLint alignment;
+
+  if (!((ptrdiff_t)aData.mYStride & 0x7) && !((ptrdiff_t)aData.mYChannel & 0x7)) {
+    alignment = 8;
+  } else if (!((ptrdiff_t)aData.mYStride & 0x3)) {
+    alignment = 4;
+  } else if (!((ptrdiff_t)aData.mYStride & 0x1)) {
+    alignment = 2;
+  } else {
+    alignment = 1;
+  }
+
+  // Set texture alignment for Y plane.
+  gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment);
+
+  gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aYTexture->GetTextureID());
+  gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
+                     0, 0, aData.mYSize.width, aData.mYSize.height,
+                     LOCAL_GL_LUMINANCE,
+                     LOCAL_GL_UNSIGNED_BYTE,
+                     aData.mYChannel);
+
+  if (!((ptrdiff_t)aData.mCbCrStride & 0x7) && 
+      !((ptrdiff_t)aData.mCbChannel & 0x7) &&
+      !((ptrdiff_t)aData.mCrChannel & 0x7))
+  {
+    alignment = 8;
+  } else if (!((ptrdiff_t)aData.mCbCrStride & 0x3)) {
+    alignment = 4;
+  } else if (!((ptrdiff_t)aData.mCbCrStride & 0x1)) {
+    alignment = 2;
+  } else {
+    alignment = 1;
+  }
   
-  size = nsIntRect(0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height);
-  texture = aUTexture->GetTextureID();
-  surf = new gfxImageSurface(aData.mCbChannel,
-                             aData.mCbCrSize,
-                             aData.mCbCrStride,
-                             gfxASurface::ImageFormatA8);
-  gl->UploadSurfaceToTexture(surf, size, texture, true);
+  // Set texture alignment for Cb/Cr plane
+  gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, alignment);
+
+  gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aUTexture->GetTextureID());
+  gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
+                     0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height,
+                     LOCAL_GL_LUMINANCE,
+                     LOCAL_GL_UNSIGNED_BYTE,
+                     aData.mCbChannel);
 
-  texture = aVTexture->GetTextureID();
-  surf = new gfxImageSurface(aData.mCrChannel,
-                             aData.mCbCrSize,
-                             aData.mCbCrStride,
-                             gfxASurface::ImageFormatA8);
-  gl->UploadSurfaceToTexture(surf, size, texture, true);
+  gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aVTexture->GetTextureID());
+  gl->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0,
+                     0, 0, aData.mCbCrSize.width, aData.mCbCrSize.height,
+                     LOCAL_GL_LUMINANCE,
+                     LOCAL_GL_UNSIGNED_BYTE,
+                     aData.mCrChannel);
+
+  // Reset alignment to default
+  gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
 }
 
 void
 PlanarYCbCrImageOGL::UpdateTextures(GLContext *gl)
 {
   if (!mBuffer || !mHasData)
     return;
 
@@ -876,19 +972,16 @@ ShadowImageLayerOGL::Swap(const SharedIm
       const YUVImage& yuv = aNewFront.get_YUVImage();
     
       nsRefPtr<gfxSharedImageSurface> surfY =
         gfxSharedImageSurface::Open(yuv.Ydata());
       nsRefPtr<gfxSharedImageSurface> surfU =
         gfxSharedImageSurface::Open(yuv.Udata());
       nsRefPtr<gfxSharedImageSurface> surfV =
         gfxSharedImageSurface::Open(yuv.Vdata());
-
-      mPictureRect = yuv.picture();
-      mSize = surfY->GetSize();
  
       PlanarYCbCrImage::Data data;
       data.mYChannel = surfY->Data();
       data.mYStride = surfY->Stride();
       data.mYSize = surfY->GetSize();
       data.mCbChannel = surfU->Data();
       data.mCrChannel = surfV->Data();
       data.mCbCrStride = surfU->Stride();
@@ -958,30 +1051,21 @@ ShadowImageLayerOGL::RenderLayer(int aPr
     gl()->fActiveTexture(LOCAL_GL_TEXTURE2);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mYUVTexture[2].GetTextureID());
     ApplyFilter(mFilter);
     
     YCbCrTextureLayerProgram *yuvProgram = mOGLManager->GetYCbCrLayerProgram();
 
     yuvProgram->Activate();
     yuvProgram->SetLayerQuadRect(nsIntRect(0, 0,
-                                           mPictureRect.width,
-                                           mPictureRect.height));
+                                           mSize.width,
+                                           mSize.height));
     yuvProgram->SetYCbCrTextureUnits(0, 1, 2);
 
     program = yuvProgram;
-    program->SetLayerTransform(GetEffectiveTransform());
-    program->SetLayerOpacity(GetEffectiveOpacity());
-    program->SetRenderOffset(aOffset);
-
-    mOGLManager->BindAndDrawQuadWithTextureRect(program,
-                                                mPictureRect,
-                                                nsIntSize(mSize.width, mSize.height));
-
-    return;
   }
 
   program->SetLayerTransform(GetEffectiveTransform());
   program->SetLayerOpacity(GetEffectiveOpacity());
   program->SetRenderOffset(aOffset);
 
   mOGLManager->BindAndDrawQuad(program);
 }
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -202,27 +202,24 @@ public:
 
   PRBool HasData() { return mHasData; }
   PRBool HasTextures()
   {
     return mTextures[0].IsAllocated() && mTextures[1].IsAllocated() &&
            mTextures[2].IsAllocated();
   }
 
-  PRUint8* AllocateBuffer(PRUint32 aSize) {
-    return mRecycleBin->GetBuffer(aSize);
-  }
-
   nsAutoArrayPtr<PRUint8> mBuffer;
   PRUint32 mBufferSize;
   nsRefPtr<RecycleBin> mRecycleBin;
   GLTexture mTextures[3];
   Data mData;
   gfxIntSize mSize;
   PRPackedBool mHasData;
+  gfx::YUVType mType; 
 };
 
 
 class THEBES_API CairoImageOGL : public CairoImage
 {
   typedef mozilla::gl::GLContext GLContext;
 
 public:
@@ -266,14 +263,13 @@ public:
 
   virtual void RenderLayer(int aPreviousFrameBuffer,
                            const nsIntPoint& aOffset);
 
 private:
   nsRefPtr<TextureImage> mTexImage;
   GLTexture mYUVTexture[3];
   gfxIntSize mSize;
-  nsIntRect mPictureRect;
 };
 
 } /* layers */
 } /* mozilla */
 #endif /* GFX_IMAGELAYEROGL_H */
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -665,83 +665,16 @@ LayerManagerOGL::FPSState::DrawFPS(GLCon
   context->fVertexAttribPointer(tcattr,
                                 2, LOCAL_GL_FLOAT,
                                 LOCAL_GL_FALSE,
                                 0, texCoords);
 
   context->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 12);
 }
 
-// |aTexCoordRect| is the rectangle from the texture that we want to
-// draw using the given program.  The program already has a necessary
-// offset and scale, so the geometry that needs to be drawn is a unit
-// square from 0,0 to 1,1.
-//
-// |aTexSize| is the actual size of the texture, as it can be larger
-// than the rectangle given by |aTexCoordRect|.
-void 
-LayerManagerOGL::BindAndDrawQuadWithTextureRect(LayerProgram *aProg,
-                                                const nsIntRect& aTexCoordRect,
-                                                const nsIntSize& aTexSize,
-                                                GLenum aWrapMode)
-{
-  GLuint vertAttribIndex =
-    aProg->AttribLocation(LayerProgram::VertexAttrib);
-  GLuint texCoordAttribIndex =
-    aProg->AttribLocation(LayerProgram::TexCoordAttrib);
-  NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?");
-
-  // clear any bound VBO so that glVertexAttribPointer() goes back to
-  // "pointer mode"
-  mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
-
-  // Given what we know about these textures and coordinates, we can
-  // compute fmod(t, 1.0f) to get the same texture coordinate out.  If
-  // the texCoordRect dimension is < 0 or > width/height, then we have
-  // wraparound that we need to deal with by drawing multiple quads,
-  // because we can't rely on full non-power-of-two texture support
-  // (which is required for the REPEAT wrap mode).
-
-  GLContext::RectTriangles rects;
-
-  if (aWrapMode == LOCAL_GL_REPEAT) {
-    rects.addRect(/* dest rectangle */
-                  0.0f, 0.0f, 1.0f, 1.0f,
-                  /* tex coords */
-                  aTexCoordRect.x / GLfloat(aTexSize.width),
-                  aTexCoordRect.y / GLfloat(aTexSize.height),
-                  aTexCoordRect.XMost() / GLfloat(aTexSize.width),
-                  aTexCoordRect.YMost() / GLfloat(aTexSize.height));
-  } else {
-    GLContext::DecomposeIntoNoRepeatTriangles(aTexCoordRect, aTexSize, rects);
-  }
-
-  // vertex position buffer is 2 floats, not normalized, 0 stride.
-  mGLContext->fVertexAttribPointer(vertAttribIndex, 2,
-                                   LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
-                                   rects.vertexPointer());
-
-  // texture coord buffer is 2 floats, not normalized, 0 stride.
-  mGLContext->fVertexAttribPointer(texCoordAttribIndex, 2,
-                                   LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
-                                   rects.texCoordPointer());
-
-  {
-    mGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
-    {
-      mGLContext->fEnableVertexAttribArray(vertAttribIndex);
-
-      mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
-
-      mGLContext->fDisableVertexAttribArray(vertAttribIndex);
-    }
-    mGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
-  }
-}
-
 void
 LayerManagerOGL::Render()
 {
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -355,22 +355,16 @@ public:
   void BindAndDrawQuad(LayerProgram *aProg,
                        bool aFlipped = false)
   {
     BindAndDrawQuad(aProg->AttribLocation(LayerProgram::VertexAttrib),
                     aProg->AttribLocation(LayerProgram::TexCoordAttrib),
                     aFlipped);
   }
 
-  void BindAndDrawQuadWithTextureRect(LayerProgram *aProg,
-                                      const nsIntRect& aTexCoordRect,
-                                      const nsIntSize& aTexSize,
-                                      GLenum aWrapMode = LOCAL_GL_REPEAT);
-                                      
-
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() const { return "OGL"; }
 #endif // MOZ_LAYERS_HAVE_LOG
 
   const nsIntSize& GetWigetSize() {
     return mWidgetSize;
   }
 
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -70,16 +70,84 @@ CreateClampOrRepeatTextureImage(GLContex
        aGl->IsExtensionSupported(GLContext::OES_texture_npot)))
   {
     wrapMode = LOCAL_GL_REPEAT;
   }
 
   return aGl->CreateTextureImage(aSize, aContentType, wrapMode);
 }
 
+// |aTexCoordRect| is the rectangle from the texture that we want to
+// draw using the given program.  The program already has a necessary
+// offset and scale, so the geometry that needs to be drawn is a unit
+// square from 0,0 to 1,1.
+//
+// |aTexSize| is the actual size of the texture, as it can be larger
+// than the rectangle given by |aTexCoordRect|.
+static void
+BindAndDrawQuadWithTextureRect(GLContext* aGl,
+                               LayerProgram *aProg,
+                               const nsIntRect& aTexCoordRect,
+                               const nsIntSize& aTexSize,
+                               GLenum aWrapMode)
+{
+  GLuint vertAttribIndex =
+    aProg->AttribLocation(LayerProgram::VertexAttrib);
+  GLuint texCoordAttribIndex =
+    aProg->AttribLocation(LayerProgram::TexCoordAttrib);
+  NS_ASSERTION(texCoordAttribIndex != GLuint(-1), "no texture coords?");
+
+  // clear any bound VBO so that glVertexAttribPointer() goes back to
+  // "pointer mode"
+  aGl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
+
+  // Given what we know about these textures and coordinates, we can
+  // compute fmod(t, 1.0f) to get the same texture coordinate out.  If
+  // the texCoordRect dimension is < 0 or > width/height, then we have
+  // wraparound that we need to deal with by drawing multiple quads,
+  // because we can't rely on full non-power-of-two texture support
+  // (which is required for the REPEAT wrap mode).
+
+  GLContext::RectTriangles rects;
+
+  if (aWrapMode == LOCAL_GL_REPEAT) {
+    rects.addRect(/* dest rectangle */
+                  0.0f, 0.0f, 1.0f, 1.0f,
+                  /* tex coords */
+                  aTexCoordRect.x / GLfloat(aTexSize.width),
+                  aTexCoordRect.y / GLfloat(aTexSize.height),
+                  aTexCoordRect.XMost() / GLfloat(aTexSize.width),
+                  aTexCoordRect.YMost() / GLfloat(aTexSize.height));
+  } else {
+    GLContext::DecomposeIntoNoRepeatTriangles(aTexCoordRect, aTexSize, rects);
+  }
+
+  // vertex position buffer is 2 floats, not normalized, 0 stride.
+  aGl->fVertexAttribPointer(vertAttribIndex, 2,
+                            LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
+                            rects.vertexPointer());
+
+  // texture coord buffer is 2 floats, not normalized, 0 stride.
+  aGl->fVertexAttribPointer(texCoordAttribIndex, 2,
+                            LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
+                            rects.texCoordPointer());
+
+  {
+    aGl->fEnableVertexAttribArray(texCoordAttribIndex);
+    {
+      aGl->fEnableVertexAttribArray(vertAttribIndex);
+
+      aGl->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
+
+      aGl->fDisableVertexAttribArray(vertAttribIndex);
+    }
+    aGl->fDisableVertexAttribArray(texCoordAttribIndex);
+  }
+}
+
 static void
 SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
 {
   nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
   if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) {
     // Destination doesn't have alpha channel; no need to set any special flags
     return;
   }
@@ -196,19 +264,19 @@ ThebesLayerBufferOGL::RenderTo(const nsI
     }
     nsIntRegionRectIterator iter(*renderRegion);
     while (const nsIntRect *iterRect = iter.Next()) {
       nsIntRect quadRect = *iterRect;
       program->SetLayerQuadRect(quadRect);
 
       quadRect.MoveBy(-GetOriginOffset());
 
-      aManager->BindAndDrawQuadWithTextureRect(program, quadRect,
-                                               mTexImage->GetSize(),
-                                               mTexImage->GetWrapMode());
+      BindAndDrawQuadWithTextureRect(gl(), program, quadRect,
+                                     mTexImage->GetSize(),
+                                     mTexImage->GetWrapMode());
     }
   }
 
   if (mTexImageOnWhite) {
     // Restore defaults
     gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                              LOCAL_GL_ONE, LOCAL_GL_ONE);
   }
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -1377,18 +1377,17 @@ GLContext::UploadSurfaceToTexture(gfxASu
     }
 
     nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
     unsigned char* data = NULL;
 
     if (!imageSurface || 
         (imageSurface->Format() != gfxASurface::ImageFormatARGB32 &&
          imageSurface->Format() != gfxASurface::ImageFormatRGB24 &&
-         imageSurface->Format() != gfxASurface::ImageFormatRGB16_565 &&
-         imageSurface->Format() != gfxASurface::ImageFormatA8)) {
+         imageSurface->Format() != gfxASurface::ImageFormatRGB16_565)) {
         // We can't get suitable pixel data for the surface, make a copy
         nsIntRect bounds = aDstRegion.GetBounds();
         imageSurface = 
           new gfxImageSurface(gfxIntSize(bounds.width, bounds.height), 
                               gfxASurface::ImageFormatARGB32);
   
         nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
 
@@ -1426,22 +1425,16 @@ GLContext::UploadSurfaceToTexture(gfxASu
             type = LOCAL_GL_UNSIGNED_BYTE;
             shader = BGRXLayerProgramType;
             break;
         case gfxASurface::ImageFormatRGB16_565:
             format = LOCAL_GL_RGB;
             type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
             shader = RGBALayerProgramType;
             break;
-        case gfxASurface::ImageFormatA8:
-            format = LOCAL_GL_LUMINANCE;
-            type = LOCAL_GL_UNSIGNED_BYTE;
-            // We don't have a specific luminance shader
-            shader = ShaderProgramType(0);
-            break;
         default:
             NS_ASSERTION(false, "Unhandled image surface format!");
             format = 0;
             type = 0;
             shader = ShaderProgramType(0);
     }
 
 #ifndef USE_GLES2
--- a/gfx/ycbcr/README
+++ b/gfx/ycbcr/README
@@ -18,10 +18,8 @@ convert.patch contains the following cha
   * Change Chromium code to allow a picture region.
   * The YUV conversion will convert within this picture region only.
   * Add YCbCr 4:4:4 support
   * Bug 619178 - Update CPU detection in yuv_convert to new SSE.h interface.
   * Bug 616778 - Split yuv_convert FilterRows vectorized code into separate files so it can
     be properly guarded with cpuid() calls.
 
 win64.patch: SSE2 optimization for Microsoft Visual C++ x64 version
-
-TypeFromSize.patch: Bug 656185 - Add a method to detect YUVType from plane sizes.
deleted file mode 100644
--- a/gfx/ycbcr/TypeFromSize.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
---- a/gfx/ycbcr/yuv_convert.cpp
-+++ b/gfx/ycbcr/yuv_convert.cpp
-@@ -26,16 +26,32 @@ namespace mozilla {
- 
- namespace gfx {
-  
- // 16.16 fixed point arithmetic
- const int kFractionBits = 16;
- const int kFractionMax = 1 << kFractionBits;
- const int kFractionMask = ((1 << kFractionBits) - 1);
- 
-+NS_GFX_(YUVType) TypeFromSize(int ywidth, 
-+                              int yheight, 
-+                              int cbcrwidth, 
-+                              int cbcrheight)
-+{
-+  if (ywidth == cbcrwidth && yheight == cbcrheight) {
-+    return YV24;
-+  }
-+  else if (ywidth / 2 == cbcrwidth && yheight == cbcrheight) {
-+    return YV16;
-+  }
-+  else {
-+    return YV12;
-+  }
-+}
-+
- // Convert a frame of YUV to 32 bit ARGB.
- NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
-                                   const uint8* u_buf,
-                                   const uint8* v_buf,
-                                   uint8* rgb_buf,
-                                   int pic_x,
-                                   int pic_y,
-                                   int pic_width,
-diff --git a/gfx/ycbcr/yuv_convert.h b/gfx/ycbcr/yuv_convert.h
---- a/gfx/ycbcr/yuv_convert.h
-+++ b/gfx/ycbcr/yuv_convert.h
-@@ -36,16 +36,18 @@ enum Rotate {
- // Filter affects how scaling looks.
- enum ScaleFilter {
-   FILTER_NONE = 0,        // No filter (point sampled).
-   FILTER_BILINEAR_H = 1,  // Bilinear horizontal filter.
-   FILTER_BILINEAR_V = 2,  // Bilinear vertical filter.
-   FILTER_BILINEAR = 3     // Bilinear filter.
- };
- 
-+NS_GFX_(YUVType) TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight);
-+
- // Convert a frame of YUV to 32 bit ARGB.
- // Pass in YV16/YV12 depending on source format
- NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane,
-                                   const uint8* uplane,
-                                   const uint8* vplane,
-                                   uint8* rgbframe,
-                                   int pic_x,
-                                   int pic_y,
--- a/gfx/ycbcr/update.sh
+++ b/gfx/ycbcr/update.sh
@@ -3,9 +3,8 @@ cp $1/media/base/yuv_convert.h .
 cp $1/media/base/yuv_convert.cc yuv_convert.cpp
 cp $1/media/base/yuv_row.h .
 cp $1/media/base/yuv_row_table.cc yuv_row_table.cpp
 cp $1/media/base/yuv_row_posix.cc yuv_row_posix.cpp
 cp $1/media/base/yuv_row_win.cc yuv_row_win.cpp
 cp $1/media/base/yuv_row_posix.cc yuv_row_c.cpp
 patch -p3 <convert.patch
 patch -p3 <win64.patch
-patch -p3 <TypeFromSize.patch
--- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp
@@ -26,32 +26,16 @@ namespace mozilla {
 
 namespace gfx {
  
 // 16.16 fixed point arithmetic
 const int kFractionBits = 16;
 const int kFractionMax = 1 << kFractionBits;
 const int kFractionMask = ((1 << kFractionBits) - 1);
 
-NS_GFX_(YUVType) TypeFromSize(int ywidth, 
-                              int yheight, 
-                              int cbcrwidth, 
-                              int cbcrheight)
-{
-  if (ywidth == cbcrwidth && yheight == cbcrheight) {
-    return YV24;
-  }
-  else if (ywidth / 2 == cbcrwidth && yheight == cbcrheight) {
-    return YV16;
-  }
-  else {
-    return YV12;
-  }
-}
-
 // Convert a frame of YUV to 32 bit ARGB.
 NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* y_buf,
                                   const uint8* u_buf,
                                   const uint8* v_buf,
                                   uint8* rgb_buf,
                                   int pic_x,
                                   int pic_y,
                                   int pic_width,
--- a/gfx/ycbcr/yuv_convert.h
+++ b/gfx/ycbcr/yuv_convert.h
@@ -36,18 +36,16 @@ enum Rotate {
 // Filter affects how scaling looks.
 enum ScaleFilter {
   FILTER_NONE = 0,        // No filter (point sampled).
   FILTER_BILINEAR_H = 1,  // Bilinear horizontal filter.
   FILTER_BILINEAR_V = 2,  // Bilinear vertical filter.
   FILTER_BILINEAR = 3     // Bilinear filter.
 };
 
-NS_GFX_(YUVType) TypeFromSize(int ywidth, int yheight, int cbcrwidth, int cbcrheight);
-
 // Convert a frame of YUV to 32 bit ARGB.
 // Pass in YV16/YV12 depending on source format
 NS_GFX_(void) ConvertYCbCrToRGB32(const uint8* yplane,
                                   const uint8* uplane,
                                   const uint8* vplane,
                                   uint8* rgbframe,
                                   int pic_x,
                                   int pic_y,