Bug 1215089: P4. WIP. r?mattwoodrow draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 29 Jun 2017 23:11:40 +0200
changeset 607752 0f48af211acbdc5d8c09c6ff384cebd72ac79bd5
parent 607751 3c2d7fca564d85a7bc20f14586dafcffd3ad5644
child 607753 3302a7dee6fa973ca4e565cc49046d9a748ac309
push id68099
push userbmo:jyavenard@mozilla.com
push dateWed, 12 Jul 2017 20:25:16 +0000
reviewersmattwoodrow
bugs1215089
milestone56.0a1
Bug 1215089: P4. WIP. r?mattwoodrow MozReview-Commit-ID: 4FWT0U67IxJ
gfx/2d/Tools.h
gfx/2d/Types.h
gfx/gl/GLContext.cpp
gfx/gl/GLUploadHelpers.cpp
gfx/layers/BufferTexture.cpp
gfx/layers/BufferTexture.h
gfx/layers/D3D11YCbCrImage.cpp
gfx/layers/D3D11YCbCrImage.h
gfx/layers/Effects.h
gfx/layers/ImageDataSerializer.cpp
gfx/layers/ImageDataSerializer.h
gfx/layers/client/ImageClient.cpp
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/client/TextureClientRecycleAllocator.cpp
gfx/layers/composite/GPUVideoTextureHost.cpp
gfx/layers/composite/GPUVideoTextureHost.h
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d11/TextureD3D11.h
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/OGLShaderProgram.cpp
gfx/layers/opengl/OGLShaderProgram.h
gfx/layers/wr/WebRenderTextureHost.cpp
gfx/layers/wr/WebRenderTextureHost.h
gfx/tests/gtest/TestTextures.cpp
gfx/tests/gtest/TextureHelper.h
--- a/gfx/2d/Tools.h
+++ b/gfx/2d/Tools.h
@@ -87,30 +87,44 @@ Distance(Point aA, Point aB)
 
 static inline int
 BytesPerPixel(SurfaceFormat aFormat)
 {
   switch (aFormat) {
   case SurfaceFormat::A8:
     return 1;
   case SurfaceFormat::R5G6B5_UINT16:
+  case SurfaceFormat::A16:
     return 2;
   case SurfaceFormat::R8G8B8:
   case SurfaceFormat::B8G8R8:
     return 3;
   case SurfaceFormat::HSV:
   case SurfaceFormat::Lab:
     return 3 * sizeof(float);
   case SurfaceFormat::Depth:
     return sizeof(uint16_t);
   default:
     return 4;
   }
 }
 
+static inline SurfaceFormat
+SurfaceFormatForAlphaDepth(uint32_t aDepth)
+{
+  if (aDepth == 8) {
+    return SurfaceFormat::A8;
+  } else if (aDepth == 10 ||
+             aDepth == 12) {
+    return SurfaceFormat::A16;
+  }
+  MOZ_ASSERT_UNREACHABLE("Unsupported alpha depth");
+  return SurfaceFormat::UNKNOWN;
+}
+
 static inline bool
 IsOpaqueFormat(SurfaceFormat aFormat) {
   switch (aFormat) {
     case SurfaceFormat::B8G8R8X8:
     case SurfaceFormat::R8G8B8X8:
     case SurfaceFormat::X8R8G8B8:
     case SurfaceFormat::YUV:
     case SurfaceFormat::NV12:
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -51,16 +51,17 @@ enum class SurfaceFormat : int8_t {
 
   // The _UINT16 suffix here indicates that the name reflects the layout when
   // viewed as a uint16_t value. In memory these values are stored using native
   // endianness.
   R5G6B5_UINT16,                    // 0bRRRRRGGGGGGBBBBB
 
   // This one is a single-byte, so endianness isn't an issue.
   A8,
+  A16,
 
   R8G8,
 
   // These ones are their own special cases.
   YUV,
   NV12,
   YUV422,
   HSV,
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2984,17 +2984,18 @@ GetBytesPerTexel(GLenum format, GLenum t
             case LOCAL_GL_RGBA:
             case LOCAL_GL_BGRA_EXT:
                 return 4 * multiplier;
             default:
                 break;
         }
     } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
                type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
-               type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
+               type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
+               type == LOCAL_GL_UNSIGNED_SHORT)
     {
         return 2;
     }
 
     gfxCriticalError() << "Unknown texture type " << type << " or format " << format;
     return 0;
 }
 
--- a/gfx/gl/GLUploadHelpers.cpp
+++ b/gfx/gl/GLUploadHelpers.cpp
@@ -459,16 +459,24 @@ UploadImageDataToTexture(GLContext* gl,
             surfaceFormat = SurfaceFormat::R5G6B5_UINT16;
             break;
         case SurfaceFormat::A8:
             internalFormat = format = LOCAL_GL_LUMINANCE;
             type = LOCAL_GL_UNSIGNED_BYTE;
             // We don't have a specific luminance shader
             surfaceFormat = SurfaceFormat::A8;
             break;
+        case SurfaceFormat::A16:
+            format = LOCAL_GL_LUMINANCE;
+            internalFormat = LOCAL_GL_LUMINANCE16;
+            type = LOCAL_GL_UNSIGNED_SHORT;
+            // We don't have a specific luminance shader
+            surfaceFormat = SurfaceFormat::A8;
+            pixelSize = 2;
+            break;
         default:
             NS_ASSERTION(false, "Unhandled image surface format!");
     }
 
     if (aOutUploadSize) {
         *aOutUploadSize = 0;
     }
 
--- a/gfx/layers/BufferTexture.cpp
+++ b/gfx/layers/BufferTexture.cpp
@@ -154,67 +154,83 @@ BufferTextureData::CreateInternal(Layers
     return new ShmemTextureData(aDesc, aMoz2DBackend, shm);
   }
 }
 
 BufferTextureData*
 BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
                                                 int32_t aBufferSize,
                                                 YUVColorSpace aYUVColorSpace,
+                                                uint32_t aDepth,
                                                 TextureFlags aTextureFlags)
 {
   if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) {
     return nullptr;
   }
 
   bool hasIntermediateBuffer = aAllocator ? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
                                                                          aAllocator->GetCompositorBackendType())
                                           : true;
 
   // Initialize the metadata with something, even if it will have to be rewritten
   // afterwards since we don't know the dimensions of the texture at this point.
-  BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(),
+  BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), 0, gfx::IntSize(), 0,
                                           0, 0, 0, StereoMode::MONO,
                                           aYUVColorSpace,
+                                          aDepth,
                                           hasIntermediateBuffer);
 
   return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr,
                        desc, gfx::BackendType::NONE, aBufferSize, aTextureFlags);
 }
 
 BufferTextureData*
 BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator,
                                   gfx::IntSize aYSize,
+                                  uint32_t aYStride,
                                   gfx::IntSize aCbCrSize,
+                                  uint32_t aCbCrStride,
                                   StereoMode aStereoMode,
                                   YUVColorSpace aYUVColorSpace,
+                                  uint32_t aDepth,
                                   TextureFlags aTextureFlags)
 {
-  uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize);
+  uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(
+    aYSize, aYStride, aCbCrSize, aCbCrStride);
   if (bufSize == 0) {
     return nullptr;
   }
 
   uint32_t yOffset;
   uint32_t cbOffset;
   uint32_t crOffset;
-  ImageDataSerializer::ComputeYCbCrOffsets(aYSize.width, aYSize.height,
-                                          aCbCrSize.width, aCbCrSize.height,
-                                          yOffset, cbOffset, crOffset);
+  ImageDataSerializer::ComputeYCbCrOffsets(aYStride, aYSize.height,
+                                           aCbCrStride, aCbCrSize.height,
+                                           yOffset, cbOffset, crOffset);
 
-  bool hasIntermediateBuffer = aAllocator ? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
-                                                                         aAllocator->GetCompositorBackendType())
-                                          : true;
+  bool hasIntermediateBuffer =
+    aAllocator
+      ? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
+                                     aAllocator->GetCompositorBackendType())
+      : true;
 
-  YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset,
-                                               crOffset, aStereoMode, aYUVColorSpace,
+  YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aYStride,
+                                               aCbCrSize, aCbCrStride,
+                                               yOffset, cbOffset, crOffset,
+                                               aStereoMode,
+                                               aYUVColorSpace,
+                                               aDepth,
                                                hasIntermediateBuffer);
 
- return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr, descriptor,
-                       gfx::BackendType::NONE, bufSize, aTextureFlags);
+  return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder()
+                                   : nullptr,
+                        descriptor,
+                        gfx::BackendType::NONE,
+                        bufSize,
+                        aTextureFlags);
 }
 
 void
 BufferTextureData::FillInfo(TextureData::Info& aInfo) const
 {
   aInfo.size = GetSize();
   aInfo.format = GetFormat();
   aInfo.hasSynchronization = false;
@@ -249,16 +265,22 @@ BufferTextureData::GetCbCrSize() const
 }
 
 Maybe<YUVColorSpace>
 BufferTextureData::GetYUVColorSpace() const
 {
   return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor);
 }
 
+Maybe<uint32_t>
+BufferTextureData::GetDepth() const
+{
+  return ImageDataSerializer::DepthFromBufferDescriptor(mDescriptor);
+}
+
 Maybe<StereoMode>
 BufferTextureData::GetStereoMode() const
 {
   return ImageDataSerializer::StereoModeFromBufferDescriptor(mDescriptor);
 }
 
 gfx::SurfaceFormat
 BufferTextureData::GetFormat() const
@@ -346,27 +368,27 @@ BufferTextureData::BorrowMappedYCbCrData
   auto ySize = desc.ySize();
   auto cbCrSize = desc.cbCrSize();
 
   aMap.stereoMode = desc.stereoMode();
   aMap.metadata = nullptr;
 
   aMap.y.data = data + desc.yOffset();
   aMap.y.size = ySize;
-  aMap.y.stride = ySize.width;
+  aMap.y.stride = desc.yStride();
   aMap.y.skip = 0;
 
   aMap.cb.data = data + desc.cbOffset();
   aMap.cb.size = cbCrSize;
-  aMap.cb.stride = cbCrSize.width;
+  aMap.cb.stride = desc.cbCrStride();
   aMap.cb.skip = 0;
 
   aMap.cr.data = data + desc.crOffset();
   aMap.cr.size = cbCrSize;
-  aMap.cr.stride = cbCrSize.width;
+  aMap.cr.stride = desc.cbCrStride();
   aMap.cr.skip = 0;
 
   return true;
 }
 
 bool
 BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
 {
--- a/gfx/layers/BufferTexture.h
+++ b/gfx/layers/BufferTexture.h
@@ -25,27 +25,31 @@ public:
                                    gfx::BackendType aMoz2DBackend,
                                    LayersBackend aLayersBackend,
                                    TextureFlags aFlags,
                                    TextureAllocationFlags aAllocFlags,
                                    LayersIPCChannel* aAllocator);
 
   static BufferTextureData* CreateForYCbCr(KnowsCompositor* aAllocator,
                                            gfx::IntSize aYSize,
+                                           uint32_t aYStride,
                                            gfx::IntSize aCbCrSize,
+                                           uint32_t aCbCrStride,
                                            StereoMode aStereoMode,
                                            YUVColorSpace aYUVColorSpace,
+                                           uint32_t aDepth,
                                            TextureFlags aTextureFlags);
 
   // It is generally better to use CreateForYCbCr instead.
   // This creates a half-initialized texture since we don't know the sizes and
   // offsets in the buffer.
   static BufferTextureData* CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
                                                          int32_t aSize,
                                                          YUVColorSpace aYUVColorSpace,
+                                                         uint32_t aDepth,
                                                          TextureFlags aTextureFlags);
 
   virtual bool Lock(OpenMode aMode) override { return true; }
 
   virtual void Unlock() override {}
 
   virtual void FillInfo(TextureData::Info& aInfo) const override;
 
@@ -62,16 +66,18 @@ public:
 
   // Don't use this.
   void SetDesciptor(const BufferDescriptor& aDesc);
 
   Maybe<gfx::IntSize> GetCbCrSize() const;
 
   Maybe<YUVColorSpace> GetYUVColorSpace() const;
 
+  Maybe<uint32_t> GetDepth() const;
+
   Maybe<StereoMode> GetStereoMode() const;
 
 protected:
   gfx::IntSize GetSize() const;
 
   gfx::SurfaceFormat GetFormat() const;
 
   static BufferTextureData* CreateInternal(LayersIPCChannel* aAllocator,
--- a/gfx/layers/D3D11YCbCrImage.cpp
+++ b/gfx/layers/D3D11YCbCrImage.cpp
@@ -27,25 +27,28 @@ D3D11YCbCrImage::SetData(KnowsCompositor
                          ImageContainer* aContainer,
                          const PlanarYCbCrData& aData)
 {
   mPictureRect = IntRect(
     aData.mPicX, aData.mPicY, aData.mPicSize.width, aData.mPicSize.height);
   mYSize = aData.mYSize;
   mCbCrSize = aData.mCbCrSize;
   mColorSpace = aData.mYUVColorSpace;
+  mDepth = aData.mDepth;
 
   D3D11YCbCrRecycleAllocator* allocator =
     aContainer->GetD3D11YCbCrRecycleAllocator(aAllocator);
   if (!allocator) {
     return false;
   }
   allocator->SetSizes(aData.mYSize, aData.mCbCrSize);
 
-  mTextureClient = allocator->CreateOrRecycle(SurfaceFormat::A8,
+  SurfaceFormat format = SurfaceFormatForAlphaDepth(mDepth);
+
+  mTextureClient = allocator->CreateOrRecycle(format,
                                               mYSize,
                                               BackendSelector::Content,
                                               TextureFlags::DEFAULT);
   if (!mTextureClient) {
     return false;
   }
 
   DXGIYCbCrTextureData *data =
@@ -92,17 +95,17 @@ D3D11YCbCrImage::SetData(KnowsCompositor
                          aData.mCbCrStride * aData.mCbCrSize.height);
   ctx->UpdateSubresource(textureCr,
                          0,
                          nullptr,
                          aData.mCrChannel,
                          aData.mCbCrStride,
                          aData.mCbCrStride * aData.mCbCrSize.height);
 
-  
+
   return true;
 }
 
 IntSize
 D3D11YCbCrImage::GetSize()
 {
   return mPictureRect.Size();
 }
@@ -212,16 +215,17 @@ D3D11YCbCrImage::GetAsSourceSurface()
 
   MOZ_ASSERT(mapCb.RowPitch == mapCr.RowPitch);
 
   data.mPicX = mPictureRect.x;
   data.mPicY = mPictureRect.y;
   data.mPicSize = mPictureRect.Size();
   data.mStereoMode = StereoMode::MONO;
   data.mYUVColorSpace = mColorSpace;
+  data.mDepth = mDepth;
   data.mYSkip = data.mCbSkip = data.mCrSkip = 0;
   data.mYSize = mYSize;
   data.mCbCrSize = mCbCrSize;
   data.mYChannel = static_cast<uint8_t*>(mapY.pData);
   data.mYStride = mapY.RowPitch;
   data.mCbChannel = static_cast<uint8_t*>(mapCb.pData);
   data.mCrChannel = static_cast<uint8_t*>(mapCr.pData);
   data.mCbCrStride = mapCb.RowPitch;
@@ -266,23 +270,28 @@ D3D11YCbCrRecycleAllocator::SetSizes(con
 
 already_AddRefed<TextureClient>
 D3D11YCbCrRecycleAllocator::Allocate(SurfaceFormat aFormat,
                                      IntSize aSize,
                                      BackendSelector aSelector,
                                      TextureFlags aTextureFlags,
                                      TextureAllocationFlags aAllocFlags)
 {
-  MOZ_ASSERT(aFormat == SurfaceFormat::A8);
+  MOZ_ASSERT(aFormat == SurfaceFormat::A8 ||
+             aFormat == SurfaceFormat::A16);
 
   gfx::IntSize YSize = mYSize.refOr(aSize);
   gfx::IntSize CbCrSize =
     mCbCrSize.refOr(gfx::IntSize(YSize.width, YSize.height));
-  CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_R8_UNORM, YSize.width, YSize.height,
-                                1, 1);
+  CD3D11_TEXTURE2D_DESC newDesc(
+    DataTextureSourceD3D11::SurfaceFormatToDXGIFormat(aFormat),
+    YSize.width,
+    YSize.height,
+    1,
+    1);
   newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
 
   RefPtr<ID3D11Texture2D> textureY;
   HRESULT hr =
     mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureY));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   newDesc.Width = CbCrSize.width;
--- a/gfx/layers/D3D11YCbCrImage.h
+++ b/gfx/layers/D3D11YCbCrImage.h
@@ -64,15 +64,17 @@ public:
 
   gfx::IntRect GetPictureRect() override { return mPictureRect; }
 
 private:
   gfx::IntSize mYSize;
   gfx::IntSize mCbCrSize;
   gfx::IntRect mPictureRect;
   YUVColorSpace mColorSpace;
+  uint32_t mDepth;
+
   RefPtr<TextureClient> mTextureClient;
 };
 
 } // namepace layers
 } // namespace mozilla
 
 #endif // GFX_D3D11_YCBCR_IMAGE_H
--- a/gfx/layers/Effects.h
+++ b/gfx/layers/Effects.h
@@ -156,24 +156,26 @@ struct EffectRGB : public TexturedEffect
     : TexturedEffect(EffectTypes::RGB, aTexture, aPremultiplied, aSamplingFilter)
   {}
 
   virtual const char* Name() { return "EffectRGB"; }
 };
 
 struct EffectYCbCr : public TexturedEffect
 {
-  EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, gfx::SamplingFilter aSamplingFilter)
+  EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, uint32_t aDepth, gfx::SamplingFilter aSamplingFilter)
     : TexturedEffect(EffectTypes::YCBCR, aSource, false, aSamplingFilter)
     , mYUVColorSpace(aYUVColorSpace)
+    , mDepth(aDepth)
   {}
 
   virtual const char* Name() { return "EffectYCbCr"; }
 
   YUVColorSpace mYUVColorSpace;
+  uint32_t mDepth;
 };
 
 struct EffectNV12 : public TexturedEffect
 {
   EffectNV12(TextureSource *aSource, gfx::SamplingFilter aSamplingFilter)
     : TexturedEffect(EffectTypes::NV12, aSource, false, aSamplingFilter)
   {}
 
@@ -265,17 +267,18 @@ CreateTexturedEffect(TextureHost* aHost,
                      bool isAlphaPremultiplied)
 {
   MOZ_ASSERT(aHost);
   MOZ_ASSERT(aSource);
 
   RefPtr<TexturedEffect> result;
   if (aHost->GetReadFormat() == gfx::SurfaceFormat::YUV) {
     MOZ_ASSERT(aHost->GetYUVColorSpace() != YUVColorSpace::UNKNOWN);
-    result = new EffectYCbCr(aSource, aHost->GetYUVColorSpace(), aSamplingFilter);
+    result = new EffectYCbCr(
+      aSource, aHost->GetYUVColorSpace(), aHost->GetDepth(), aSamplingFilter);
   } else {
     result = CreateTexturedEffect(aHost->GetReadFormat(),
                                   aSource,
                                   aSamplingFilter,
                                   isAlphaPremultiplied);
   }
   return result.forget();
 }
--- a/gfx/layers/ImageDataSerializer.cpp
+++ b/gfx/layers/ImageDataSerializer.cpp
@@ -66,28 +66,22 @@ ComputeYCbCrBufferSize(const gfx::IntSiz
 {
   MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
 
   if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 ||
       !gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height)) ||
       !gfx::Factory::AllowedSurfaceSize(IntSize(aCbCrStride, aCbCrSize.height))) {
     return 0;
   }
+
   // Overflow checks are performed in AllowedSurfaceSize
   return GetAlignedStride<4>(aYSize.height, aYStride) +
          2 * GetAlignedStride<4>(aCbCrSize.height, aCbCrStride);
 }
 
-// Minimum required shmem size in bytes
-uint32_t
-ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, const gfx::IntSize& aCbCrSize)
-{
-  return ComputeYCbCrBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width);
-}
-
 uint32_t
 ComputeYCbCrBufferSize(uint32_t aBufferSize)
 {
   return GetAlignedStride<4>(aBufferSize, 1);
 }
 
 void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight,
                          int32_t cbCrStride, int32_t cbCrHeight,
@@ -132,37 +126,47 @@ Maybe<gfx::IntSize> CbCrSizeFromBufferDe
       return Some(aDescriptor.get_YCbCrDescriptor().cbCrSize());
     default:
       MOZ_CRASH("GFX:  CbCrSizeFromBufferDescriptor");
   }
 }
 
 Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor)
 {
-{
   switch (aDescriptor.type()) {
     case BufferDescriptor::TRGBDescriptor:
       return Nothing();
     case BufferDescriptor::TYCbCrDescriptor:
       return Some(aDescriptor.get_YCbCrDescriptor().yUVColorSpace());
     default:
-      MOZ_CRASH("GFX:  CbCrSizeFromBufferDescriptor");
+      MOZ_CRASH("GFX:  YUVColorSpaceFromBufferDescriptor");
   }
 }
+
+Maybe<uint32_t> DepthFromBufferDescriptor(const BufferDescriptor& aDescriptor)
+{
+  switch (aDescriptor.type()) {
+    case BufferDescriptor::TRGBDescriptor:
+      return Nothing();
+    case BufferDescriptor::TYCbCrDescriptor:
+      return Some(aDescriptor.get_YCbCrDescriptor().depth());
+    default:
+      MOZ_CRASH("GFX:  DepthFromBufferDescriptor");
+  }
 }
 
 Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
 {
   switch (aDescriptor.type()) {
     case BufferDescriptor::TRGBDescriptor:
       return Nothing();
     case BufferDescriptor::TYCbCrDescriptor:
       return Some(aDescriptor.get_YCbCrDescriptor().stereoMode());
     default:
-      MOZ_CRASH("GFX:  CbCrSizeFromBufferDescriptor");
+      MOZ_CRASH("GFX:  StereoModeFromBufferDescriptor");
   }
 }
 
 uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
 {
   return aBuffer + aDescriptor.yOffset();
 }
 
@@ -175,19 +179,16 @@ uint8_t* GetCrChannel(uint8_t* aBuffer, 
 {
   return aBuffer + aDescriptor.crOffset();
 }
 
 already_AddRefed<DataSourceSurface>
 DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor, gfx::DataSourceSurface* aSurface)
 {
   gfx::IntSize ySize = aDescriptor.ySize();
-  gfx::IntSize cbCrSize = aDescriptor.cbCrSize();
-  int32_t yStride = ySize.width;
-  int32_t cbCrStride = cbCrSize.width;
 
   RefPtr<DataSourceSurface> result;
   if (aSurface) {
     MOZ_ASSERT(aSurface->GetSize() == ySize);
     MOZ_ASSERT(aSurface->GetFormat() == gfx::SurfaceFormat::B8G8R8X8);
     if (aSurface->GetSize() == ySize &&
         aSurface->GetFormat() == gfx::SurfaceFormat::B8G8R8X8) {
       result = aSurface;
@@ -204,24 +205,25 @@ DataSourceSurfaceFromYCbCrDescriptor(uin
 
   DataSourceSurface::MappedSurface map;
   if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) {
     return nullptr;
   }
 
   layers::PlanarYCbCrData ycbcrData;
   ycbcrData.mYChannel     = GetYChannel(aBuffer, aDescriptor);
-  ycbcrData.mYStride      = yStride;
+  ycbcrData.mYStride      = aDescriptor.yStride();
   ycbcrData.mYSize        = ySize;
   ycbcrData.mCbChannel    = GetCbChannel(aBuffer, aDescriptor);
   ycbcrData.mCrChannel    = GetCrChannel(aBuffer, aDescriptor);
-  ycbcrData.mCbCrStride   = cbCrStride;
-  ycbcrData.mCbCrSize     = cbCrSize;
+  ycbcrData.mCbCrStride   = aDescriptor.cbCrStride();
+  ycbcrData.mCbCrSize     = aDescriptor.cbCrSize();
   ycbcrData.mPicSize      = ySize;
   ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
+  ycbcrData.mDepth        = aDescriptor.depth();
 
   gfx::ConvertYCbCrToRGB(ycbcrData,
                          gfx::SurfaceFormat::B8G8R8X8,
                          ySize,
                          map.mData,
                          map.mStride);
 
   result->Unmap();
@@ -232,30 +234,27 @@ void
 ConvertAndScaleFromYCbCrDescriptor(uint8_t* aBuffer,
                                    const YCbCrDescriptor& aDescriptor,
                                    const gfx::SurfaceFormat& aDestFormat,
                                    const gfx::IntSize& aDestSize,
                                    unsigned char* aDestBuffer,
                                    int32_t aStride)
 {
   MOZ_ASSERT(aBuffer);
-  gfx::IntSize ySize = aDescriptor.ySize();
-  gfx::IntSize cbCrSize = aDescriptor.cbCrSize();
-  int32_t yStride = ySize.width;
-  int32_t cbCrStride = cbCrSize.width;
 
   layers::PlanarYCbCrData ycbcrData;
   ycbcrData.mYChannel     = GetYChannel(aBuffer, aDescriptor);
-  ycbcrData.mYStride      = yStride;
-  ycbcrData.mYSize        = ySize;
+  ycbcrData.mYStride      = aDescriptor.yStride();;
+  ycbcrData.mYSize        = aDescriptor.ySize();
   ycbcrData.mCbChannel    = GetCbChannel(aBuffer, aDescriptor);
   ycbcrData.mCrChannel    = GetCrChannel(aBuffer, aDescriptor);
-  ycbcrData.mCbCrStride   = cbCrStride;
-  ycbcrData.mCbCrSize     = cbCrSize;
-  ycbcrData.mPicSize      = ySize;
+  ycbcrData.mCbCrStride   = aDescriptor.cbCrStride();
+  ycbcrData.mCbCrSize     = aDescriptor.cbCrSize();
+  ycbcrData.mPicSize      = aDescriptor.ySize();
   ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
+  ycbcrData.mDepth        = aDescriptor.depth();
 
   gfx::ConvertYCbCrToRGB(ycbcrData, aDestFormat, aDestSize, aDestBuffer, aStride);
 }
 
 } // namespace ImageDataSerializer
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ImageDataSerializer.h
+++ b/gfx/layers/ImageDataSerializer.h
@@ -40,33 +40,32 @@ uint32_t ComputeRGBBufferSize(gfx::IntSi
 
 ///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.
 uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize,
                                 int32_t aYStride,
                                 const gfx::IntSize& aCbCrSize,
                                 int32_t aCbCrStride);
-uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize,
-                                const gfx::IntSize& aCbCrSize);
-
 uint32_t ComputeYCbCrBufferSize(uint32_t aBufferSize);
 
 void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight,
                          int32_t cbCrStride, int32_t cbCrHeight,
                          uint32_t& outYOffset, uint32_t& outCbOffset, uint32_t& outCrOffset);
 
 gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescriptor);
 
 gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
 
 Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
 
 Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor);
 
+Maybe<uint32_t> DepthFromBufferDescriptor(const BufferDescriptor& aDescriptor);
+
 Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
 
 uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
 
 uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
 
 uint8_t* GetCrChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
 
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -98,18 +98,21 @@ ImageClient::CreateTextureClientForImage
   RefPtr<TextureClient> texture;
   if (aImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
     PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(aImage);
     const PlanarYCbCrData* data = ycbcr->GetData();
     if (!data) {
       return nullptr;
     }
     texture = TextureClient::CreateForYCbCr(aForwarder,
-                                            data->mYSize, data->mCbCrSize, data->mStereoMode,
+                                            data->mYSize, data->mYStride,
+                                            data->mCbCrSize, data->mCbCrStride,
+                                            data->mStereoMode,
                                             data->mYUVColorSpace,
+                                            data->mDepth,
                                             TextureFlags::DEFAULT);
     if (!texture) {
       return nullptr;
     }
 
     TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
     if (!autoLock.Succeeded()) {
       return nullptr;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -155,17 +155,17 @@ private:
   // The locking pattern of TextureClient may in some case upset deadlock detection
   // tools such as TSan.
   // Typically our tile rendering code will lock all of its tiles, render into them
   // and unlock them all right after that, which looks something like:
   //
   // Lock tile A
   // Lock tile B
   // Lock tile C
-  // Apply drawing commands to tiles A, B and C 
+  // Apply drawing commands to tiles A, B and C
   // Unlock tile A
   // Unlock tile B
   // Unlock tile C
   //
   // And later, we may end up rendering a tile buffer that has the same tiles,
   // in a different order, for example:
   //
   // Lock tile B
@@ -1240,82 +1240,90 @@ TextureClient::CreateForRawBufferAccess(
 
   return MakeAndAddRef<TextureClient>(texData, aTextureFlags, aAllocator);
 }
 
 // static
 already_AddRefed<TextureClient>
 TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
                               gfx::IntSize aYSize,
+                              uint32_t aYStride,
                               gfx::IntSize aCbCrSize,
+                              uint32_t aCbCrStride,
                               StereoMode aStereoMode,
                               YUVColorSpace aYUVColorSpace,
+                              uint32_t aDepth,
                               TextureFlags aTextureFlags)
 {
   if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
     return nullptr;
   }
 
   if (!gfx::Factory::AllowedSurfaceSize(aYSize)) {
     return nullptr;
   }
 
-  TextureData* data = BufferTextureData::CreateForYCbCr(aAllocator, aYSize, aCbCrSize,
-                                                        aStereoMode, aYUVColorSpace,
-                                                        aTextureFlags);
+  TextureData* data =
+    BufferTextureData::CreateForYCbCr(aAllocator,
+                                      aYSize, aYStride,
+                                      aCbCrSize, aCbCrStride,
+                                      aStereoMode, aYUVColorSpace,
+                                      aDepth, aTextureFlags);
   if (!data) {
     return nullptr;
   }
 
   return MakeAndAddRef<TextureClient>(data, aTextureFlags,
                                       aAllocator->GetTextureForwarder());
 }
 
 // static
 already_AddRefed<TextureClient>
 TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
                                             size_t aSize,
                                             YUVColorSpace aYUVColorSpace,
+                                            uint32_t aDepth,
                                             TextureFlags aTextureFlags)
 {
   if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
     return nullptr;
   }
 
-  TextureData* data =
-    BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aSize, aYUVColorSpace,
-                                                    aTextureFlags);
+  TextureData* data = BufferTextureData::CreateForYCbCrWithBufferSize(
+    aAllocator, aSize, aYUVColorSpace, aDepth, aTextureFlags);
   if (!data) {
     return nullptr;
   }
 
   return MakeAndAddRef<TextureClient>(data, aTextureFlags,
                                       aAllocator->GetTextureForwarder());
 }
 
-TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
-: AtomicRefCountedWithFinalize("TextureClient")
-, mAllocator(aAllocator)
-, mActor(nullptr)
-, mData(aData)
-, mFlags(aFlags)
-, mOpenMode(OpenMode::OPEN_NONE)
+TextureClient::TextureClient(TextureData* aData,
+                             TextureFlags aFlags,
+                             LayersIPCChannel* aAllocator)
+  : AtomicRefCountedWithFinalize("TextureClient")
+  , mAllocator(aAllocator)
+  , mActor(nullptr)
+  , mData(aData)
+  , mFlags(aFlags)
+  , mOpenMode(OpenMode::OPEN_NONE)
 #ifdef DEBUG
-, mExpectedDtRefs(0)
+  , mExpectedDtRefs(0)
 #endif
-, mIsLocked(false)
-, mIsReadLocked(false)
-, mUpdated(false)
-, mAddedToCompositableClient(false)
-, mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
-, mWorkaroundAnnoyingSharedSurfaceOwnershipIssues(false)
-, mFwdTransactionId(0)
-, mSerial(++sSerialCounter)
+  , mIsLocked(false)
+  , mIsReadLocked(false)
+  , mUpdated(false)
+  , mAddedToCompositableClient(false)
+  , mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
+  , mWorkaroundAnnoyingSharedSurfaceOwnershipIssues(false)
+  , mFwdTransactionId(0)
+  , mSerial(++sSerialCounter)
 #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
-, mPoolTracker(nullptr)
+  , mPoolTracker(nullptr)
 #endif
 {
   mData->FillInfo(mInfo);
   mFlags |= mData->GetTextureFlags();
 }
 
 bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
                                         const gfx::IntRect* aRect,
@@ -1714,24 +1722,27 @@ UpdateYCbCrTextureClient(TextureClient* 
     return false;
   }
 
   MappedYCbCrTextureData srcData;
   srcData.y.data = aData.mYChannel;
   srcData.y.size = aData.mYSize;
   srcData.y.stride = aData.mYStride;
   srcData.y.skip = aData.mYSkip;
+  srcData.y.bytesPerPixel = (aData.mDepth > 8) ? 2 : 1;
   srcData.cb.data = aData.mCbChannel;
   srcData.cb.size = aData.mCbCrSize;
   srcData.cb.stride = aData.mCbCrStride;
   srcData.cb.skip = aData.mCbSkip;
+  srcData.cb.bytesPerPixel = (aData.mDepth > 8) ? 2 : 1;
   srcData.cr.data = aData.mCrChannel;
   srcData.cr.size = aData.mCbCrSize;
   srcData.cr.stride = aData.mCbCrStride;
   srcData.cr.skip = aData.mCrSkip;
+  srcData.cr.bytesPerPixel = (aData.mDepth > 8) ? 2 : 1;
   srcData.metadata = nullptr;
 
   if (!srcData.CopyInto(mapped)) {
     NS_WARNING("Failed to copy image data!");
     return false;
   }
 
   if (TextureRequiresLocking(aTexture->GetFlags())) {
@@ -1785,25 +1796,29 @@ MappedYCbCrChannelData::CopyInto(MappedY
     return true;
   }
 
   for (int32_t i = 0; i < size.height; ++i) {
     if (aDst.skip == 0 && skip == 0) {
       // fast-ish path
       memcpy(aDst.data + i * aDst.stride,
              data + i * stride,
-             size.width);
+             size.width * bytesPerPixel);
     } else {
       // slow path
       uint8_t* src = data + i * stride;
       uint8_t* dst = aDst.data + i * aDst.stride;
       for (int32_t j = 0; j < size.width; ++j) {
-        *dst = *src;
-        src += 1 + skip;
-        dst += 1 + aDst.skip;
+        for (uint32_t k = 0; k < bytesPerPixel; ++k) {
+          *dst = *src;
+          src += 1;
+          dst += 1;
+        }
+        src += skip;
+        dst += aDst.skip;
       }
     }
   }
   return true;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -162,16 +162,17 @@ struct MappedTextureData
 };
 
 struct MappedYCbCrChannelData
 {
   uint8_t* data;
   gfx::IntSize size;
   int32_t stride;
   int32_t skip;
+  uint32_t bytesPerPixel;
 
   bool CopyInto(MappedYCbCrChannelData& aDst);
 };
 
 struct MappedYCbCrTextureData {
   MappedYCbCrChannelData y;
   MappedYCbCrChannelData cb;
   MappedYCbCrChannelData cr;
@@ -369,19 +370,22 @@ public:
                     BackendSelector aSelector,
                     TextureFlags aTextureFlags,
                     TextureAllocationFlags aAllocFlags);
 
   // Creates and allocates a TextureClient supporting the YCbCr format.
   static already_AddRefed<TextureClient>
   CreateForYCbCr(KnowsCompositor* aAllocator,
                  gfx::IntSize aYSize,
+                 uint32_t aYStride,
                  gfx::IntSize aCbCrSize,
+                 uint32_t aCbCrStride,
                  StereoMode aStereoMode,
                  YUVColorSpace aYUVColorSpace,
+                 uint32_t aDepth,
                  TextureFlags aTextureFlags);
 
   // Creates and allocates a TextureClient (can be accessed through raw
   // pointers).
   static already_AddRefed<TextureClient>
   CreateForRawBufferAccess(KnowsCompositor* aAllocator,
                            gfx::SurfaceFormat aFormat,
                            gfx::IntSize aSize,
@@ -391,16 +395,17 @@ public:
 
   // Creates and allocates a TextureClient (can beaccessed through raw
   // pointers) with a certain buffer size. It's unfortunate that we need this.
   // providing format and sizes could let us do more optimization.
   static already_AddRefed<TextureClient>
   CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
                                size_t aSize,
                                YUVColorSpace aYUVColorSpace,
+                               uint32_t aDepth,
                                TextureFlags aTextureFlags);
 
   // Creates and allocates a TextureClient of the same type.
   already_AddRefed<TextureClient>
   CreateSimilar(LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
                 TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const;
 
@@ -626,17 +631,17 @@ public:
   const TextureData* GetInternalData() const { return mData; }
 
   uint64_t GetSerial() const { return mSerial; }
 
   void CancelWaitForRecycle();
 
   /**
    * Set last transaction id of CompositableForwarder.
-   * 
+   *
    * Called when TextureClient has TextureFlags::RECYCLE flag.
    * When CompositableForwarder forwards the TextureClient with
    * TextureFlags::RECYCLE, it holds TextureClient's ref until host side
    * releases it. The host side sends TextureClient release message.
    * The id is used to check if the message is for the last TextureClient
    * forwarding.
    */
   void SetLastFwdTransactionId(uint64_t aTransactionId)
@@ -656,32 +661,32 @@ public:
 
   bool TryReadLock();
   void ReadUnlock();
 
   bool SerializeReadLock(ReadLockDescriptor& aDescriptor);
 
 private:
   static void TextureClientRecycleCallback(TextureClient* aClient, void* aClosure);
- 
+
   // Internal helpers for creating texture clients using the actual forwarder instead
   // of KnowsCompositor. TextureClientPool uses these to let it cache texture clients
   // per-process instead of per ShadowLayerForwarder, but everyone else should
   // use the public functions instead.
   friend class TextureClientPool;
   static already_AddRefed<TextureClient>
   CreateForDrawing(TextureForwarder* aAllocator,
                    gfx::SurfaceFormat aFormat,
                    gfx::IntSize aSize,
                    LayersBackend aLayersBackend,
                    int32_t aMaxTextureSize,
                    BackendSelector aSelector,
                    TextureFlags aTextureFlags,
                    TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT);
-  
+
   static already_AddRefed<TextureClient>
   CreateForRawBufferAccess(LayersIPCChannel* aAllocator,
                            gfx::SurfaceFormat aFormat,
                            gfx::IntSize aSize,
                            gfx::BackendType aMoz2dBackend,
                            LayersBackend aLayersBackend,
                            TextureFlags aTextureFlags,
                            TextureAllocationFlags flags = ALLOC_DEFAULT);
--- a/gfx/layers/client/TextureClientRecycleAllocator.cpp
+++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp
@@ -103,30 +103,34 @@ YCbCrTextureClientAllocationHelper::IsCo
 
   BufferTextureData* bufferData = aTextureClient->GetInternalData()->AsBufferTextureData();
   if (!bufferData ||
       aTextureClient->GetSize() != mData.mYSize ||
       bufferData->GetCbCrSize().isNothing() ||
       bufferData->GetCbCrSize().ref() != mData.mCbCrSize ||
       bufferData->GetYUVColorSpace().isNothing() ||
       bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
+      bufferData->GetDepth().isNothing() ||
+      bufferData->GetDepth().ref() != mData.mDepth ||
       bufferData->GetStereoMode().isNothing() ||
       bufferData->GetStereoMode().ref() != mData.mStereoMode) {
     return false;
   }
   return true;
 }
 
 already_AddRefed<TextureClient>
 YCbCrTextureClientAllocationHelper::Allocate(KnowsCompositor* aAllocator)
 {
   return TextureClient::CreateForYCbCr(aAllocator,
-                                       mData.mYSize, mData.mCbCrSize,
+                                       mData.mYSize, mData.mYStride,
+                                       mData.mCbCrSize, mData.mCbCrStride,
                                        mData.mStereoMode,
                                        mData.mYUVColorSpace,
+                                       mData.mDepth,
                                        mTextureFlags);
 }
 
 TextureClientRecycleAllocator::TextureClientRecycleAllocator(KnowsCompositor* aAllocator)
   : mSurfaceAllocator(aAllocator)
   , mMaxPooledSize(kMaxPooledSized)
   , mLock("TextureClientRecycleAllocatorImp.mLock")
   , mIsDestroyed(false)
--- a/gfx/layers/composite/GPUVideoTextureHost.cpp
+++ b/gfx/layers/composite/GPUVideoTextureHost.cpp
@@ -72,16 +72,25 @@ YUVColorSpace
 GPUVideoTextureHost::GetYUVColorSpace() const
 {
   if (mWrappedTextureHost) {
     return mWrappedTextureHost->GetYUVColorSpace();
   }
   return YUVColorSpace::UNKNOWN;
 }
 
+uint32_t
+GPUVideoTextureHost::GetDepth() const
+{
+  if (!mWrappedTextureHost) {
+    return 8;
+  }
+  return mWrappedTextureHost->GetDepth();
+}
+
 gfx::IntSize
 GPUVideoTextureHost::GetSize() const
 {
   if (!mWrappedTextureHost) {
     return gfx::IntSize();
   }
   return mWrappedTextureHost->GetSize();
 }
--- a/gfx/layers/composite/GPUVideoTextureHost.h
+++ b/gfx/layers/composite/GPUVideoTextureHost.h
@@ -33,16 +33,18 @@ public:
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
   {
     return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
   }
 
   virtual YUVColorSpace GetYUVColorSpace() const override;
 
+  virtual uint32_t GetDepth() const override;
+
   virtual gfx::IntSize GetSize() const override;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() override { return "GPUVideoTextureHost"; }
 #endif
 
   virtual bool HasIntermediateBuffer() const override;
 
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -442,17 +442,17 @@ TextureSource::~TextureSource()
 }
 
 const char*
 TextureSource::Name() const
 {
   MOZ_CRASH("GFX: TextureSource without class name");
   return "TextureSource";
 }
-  
+
 BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
                                      TextureFlags aFlags)
 : TextureHost(aFlags)
 , mUpdateSerial(1)
 , mLocked(false)
 , mNeedsFullUpdate(false)
 {
   mDescriptor = aDesc;
@@ -891,16 +891,26 @@ BufferTextureHost::GetYUVColorSpace() co
 {
   if (mFormat == gfx::SurfaceFormat::YUV) {
     const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
     return desc.yUVColorSpace();
   }
   return YUVColorSpace::UNKNOWN;
 }
 
+uint32_t
+BufferTextureHost::GetDepth() const
+{
+  if (mFormat == gfx::SurfaceFormat::YUV) {
+    const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
+    return desc.depth();
+  }
+  return 8;
+}
+
 bool
 BufferTextureHost::UploadIfNeeded()
 {
   return MaybeUpload(!mNeedsFullUpdate ? &mMaybeUpdatedRegion : nullptr);
 }
 
 bool
 BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
@@ -997,29 +1007,29 @@ BufferTextureHost::Upload(nsIntRegion *a
       MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
       srcY = mFirstSource;
       srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
       srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
     }
 
     RefPtr<gfx::DataSourceSurface> tempY =
       gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc),
-                                                    desc.ySize().width,
+                                                    desc.yStride(),
                                                     desc.ySize(),
-                                                    gfx::SurfaceFormat::A8);
+                                                    SurfaceFormatForAlphaDepth(desc.depth()));
     RefPtr<gfx::DataSourceSurface> tempCb =
       gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc),
-                                                    desc.cbCrSize().width,
+                                                    desc.cbCrStride(),
                                                     desc.cbCrSize(),
-                                                    gfx::SurfaceFormat::A8);
+                                                    SurfaceFormatForAlphaDepth(desc.depth()));
     RefPtr<gfx::DataSourceSurface> tempCr =
       gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc),
-                                                    desc.cbCrSize().width,
+                                                    desc.cbCrStride(),
                                                     desc.cbCrSize(),
-                                                    gfx::SurfaceFormat::A8);
+                                                    SurfaceFormatForAlphaDepth(desc.depth()));
     // We don't support partial updates for Y U V textures
     NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
     if (!tempY ||
         !tempCb ||
         !tempCr ||
         !srcY->Update(tempY) ||
         !srcU->Update(tempCb) ||
         !srcV->Update(tempCr)) {
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -432,16 +432,18 @@ public:
   /**
    * Return the format used for reading the texture.
    * Apple's YCBCR_422 is R8G8B8X8.
    */
   virtual gfx::SurfaceFormat GetReadFormat() const { return GetFormat(); }
 
   virtual YUVColorSpace GetYUVColorSpace() const { return YUVColorSpace::UNKNOWN; }
 
+  virtual uint32_t GetDepth() const { return 8; }
+
   /**
    * Called during the transaction. The TextureSource may or may not be composited.
    *
    * Note that this is called outside of lock/unlock.
    */
   virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) {}
 
   /**
@@ -724,16 +726,18 @@ public:
    *
    * If the shared format is YCbCr and the compositor does not support it,
    * GetFormat will be RGB32 (even though mFormat is SurfaceFormat::YUV).
    */
   virtual gfx::SurfaceFormat GetFormat() const override;
 
   virtual YUVColorSpace GetYUVColorSpace() const override;
 
+  virtual uint32_t GetDepth() const override;
+
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
 
   virtual bool HasIntermediateBuffer() const override { return mHasIntermediateBuffer; }
 
   virtual BufferTextureHost* AsBufferTextureHost() override { return this; }
 
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -67,30 +67,32 @@ public:
     }
     return refCnt;
   }
 private:
   int mRefCnt;
   int mMemoryUsed;
 };
 
-static DXGI_FORMAT
-SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat)
+DXGI_FORMAT
+DataTextureSourceD3D11::SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat)
 {
   switch (aFormat) {
     case SurfaceFormat::B8G8R8A8:
       return DXGI_FORMAT_B8G8R8A8_UNORM;
     case SurfaceFormat::B8G8R8X8:
       return DXGI_FORMAT_B8G8R8A8_UNORM;
     case SurfaceFormat::R8G8B8A8:
       return DXGI_FORMAT_R8G8B8A8_UNORM;
     case SurfaceFormat::R8G8B8X8:
       return DXGI_FORMAT_R8G8B8A8_UNORM;
     case SurfaceFormat::A8:
       return DXGI_FORMAT_R8_UNORM;
+    case SurfaceFormat::A16:
+      return DXGI_FORMAT_R16_UNORM;
     default:
       MOZ_ASSERT(false, "unsupported format");
       return DXGI_FORMAT_UNKNOWN;
   }
 }
 
 void
 ReportTextureMemoryUsage(ID3D11Texture2D* aTexture, size_t aBytes)
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -263,16 +263,19 @@ public:
   {
     mIterating = true;
     mCurrentTile = 0;
   }
 
   RefPtr<TextureSource> ExtractCurrentTile() override;
 
   void Reset();
+
+  static DXGI_FORMAT SurfaceFormatToDXGIFormat(gfx::SurfaceFormat aFormat);
+
 protected:
   gfx::IntRect GetTileRect(uint32_t aIndex) const;
 
   std::vector< RefPtr<ID3D11Texture2D> > mTileTextures;
   std::vector< RefPtr<ID3D11ShaderResourceView> > mTileSRVs;
   RefPtr<ID3D11Device> mDevice;
   gfx::SurfaceFormat mFormat;
   TextureFlags mFlags;
@@ -368,16 +371,18 @@ public:
 
   virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
 
   virtual gfx::SurfaceFormat GetFormat() const override{ return gfx::SurfaceFormat::YUV; }
 
   // Bug 1305906 fixes YUVColorSpace handling
   virtual YUVColorSpace GetYUVColorSpace() const override { return YUVColorSpace::BT601; }
 
+  virtual uint32_t GetDepth() const override { return 8; }
+
   virtual bool Lock() override;
 
   virtual void Unlock() override;
 
   virtual gfx::IntSize GetSize() const override { return mSize; }
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
   {
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -87,22 +87,25 @@ struct SurfaceDescriptorGPUVideo {
 struct RGBDescriptor {
   IntSize size;
   SurfaceFormat format;
   bool hasIntermediateBuffer;
 };
 
 struct YCbCrDescriptor {
   IntSize ySize;
+  uint32_t yStride;
   IntSize cbCrSize;
+  uint32_t cbCrStride;
   uint32_t yOffset;
   uint32_t cbOffset;
   uint32_t crOffset;
   StereoMode stereoMode;
   YUVColorSpace yUVColorSpace;
+  uint32_t depth;
   bool hasIntermediateBuffer;
 };
 
 union BufferDescriptor {
   RGBDescriptor;
   YCbCrDescriptor;
 };
 
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -111,20 +111,23 @@ SharedPlanarYCbCrImage::AllocateAndGetNe
 {
   MOZ_ASSERT(!mTextureClient, "This image already has allocated data");
   size_t size = ImageDataSerializer::ComputeYCbCrBufferSize(aSize);
   if (!size) {
     return nullptr;
   }
 
   // XXX Add YUVColorSpace handling. Use YUVColorSpace::BT601 for now.
-  mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(),
-                                                               size,
-                                                               YUVColorSpace::BT601,
-                                                               mCompositable->GetTextureFlags());
+  // XXX Add Depth handling. 8 bits for now.
+  mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(
+    mCompositable->GetForwarder(),
+    size,
+    YUVColorSpace::BT601,
+    8,
+    mCompositable->GetTextureFlags());
 
   // get new buffer _without_ setting mBuffer.
   if (!mTextureClient) {
     return nullptr;
   }
 
   // update buffer size
   mBufferSize = size;
@@ -154,23 +157,31 @@ SharedPlanarYCbCrImage::AdoptData(const 
   mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY);
 
   uint8_t *base = GetBuffer();
   uint32_t yOffset = aData.mYChannel - base;
   uint32_t cbOffset = aData.mCbChannel - base;
   uint32_t crOffset = aData.mCrChannel - base;
 
   auto fwd = mCompositable->GetForwarder();
-  bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
-                                                            fwd->GetCompositorBackendType());
+  bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(
+    gfx::SurfaceFormat::YUV, fwd->GetCompositorBackendType());
 
-  static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor(
-    YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset,
-                    aData.mStereoMode, aData.mYUVColorSpace, hasIntermediateBuffer)
-  );
+  static_cast<BufferTextureData*>(mTextureClient->GetInternalData())
+    ->SetDesciptor(YCbCrDescriptor(aData.mYSize,
+                                   aData.mYStride,
+                                   aData.mCbCrSize,
+                                   aData.mCbCrStride,
+                                   yOffset,
+                                   cbOffset,
+                                   crOffset,
+                                   aData.mStereoMode,
+                                   aData.mYUVColorSpace,
+                                   aData.mDepth,
+                                   hasIntermediateBuffer));
 
   return true;
 }
 
 bool
 SharedPlanarYCbCrImage::IsValid() {
   return mTextureClient && mTextureClient->IsValid();
 }
@@ -216,28 +227,30 @@ SharedPlanarYCbCrImage::Allocate(PlanarY
   mData.mCrChannel = aData.mCrChannel;
   mData.mYSize = aData.mYSize;
   mData.mCbCrSize = aData.mCbCrSize;
   mData.mPicX = aData.mPicX;
   mData.mPicY = aData.mPicY;
   mData.mPicSize = aData.mPicSize;
   mData.mStereoMode = aData.mStereoMode;
   mData.mYUVColorSpace = aData.mYUVColorSpace;
+  mData.mDepth = aData.mDepth;
   // those members are not always equal to aData's, due to potentially different
   // packing.
   mData.mYSkip = 0;
   mData.mCbSkip = 0;
   mData.mCrSkip = 0;
-  mData.mYStride = mData.mYSize.width;
-  mData.mCbCrStride = mData.mCbCrSize.width;
+  mData.mYStride = aData.mYStride;
+  mData.mCbCrStride = aData.mCbCrStride;
 
   // do not set mBuffer like in PlanarYCbCrImage because the later
   // will try to manage this memory without knowing it belongs to a
   // shmem.
-  mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(mData.mYSize, mData.mCbCrSize);
+  mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(
+    mData.mYSize, mData.mYStride, mData.mCbCrSize, mData.mCbCrStride);
   mSize = mData.mPicSize;
   mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY);
 
   mTextureClient->Unlock();
 
   return mBufferSize > 0;
 }
 
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -827,18 +827,25 @@ CompositorOGL::GetShaderConfigFor(Effect
 {
   ShaderConfigOGL config;
 
   switch(aEffect->mType) {
   case EffectTypes::SOLID_COLOR:
     config.SetRenderColor(true);
     break;
   case EffectTypes::YCBCR:
+  {
     config.SetYCbCr(true);
+    EffectYCbCr* effectYCbCr =
+      static_cast<EffectYCbCr*>(aEffect);
+    uint32_t pixelBits = (8 * BytesPerPixel(SurfaceFormatForAlphaDepth(effectYCbCr->mDepth)));
+    uint32_t paddingBits = pixelBits - effectYCbCr->mDepth;
+    config.SetColorMultiplier(pow(2, paddingBits));
     break;
+  }
   case EffectTypes::NV12:
     config.SetNV12(true);
     config.SetTextureTarget(LOCAL_GL_TEXTURE_RECTANGLE_ARB);
     break;
   case EffectTypes::COMPONENT_ALPHA:
   {
     config.SetComponentAlpha(true);
     EffectComponentAlpha* effectComponentAlpha =
--- a/gfx/layers/opengl/OGLShaderProgram.cpp
+++ b/gfx/layers/opengl/OGLShaderProgram.cpp
@@ -110,16 +110,23 @@ ShaderConfigOGL::SetOpacity(bool aEnable
 void
 ShaderConfigOGL::SetYCbCr(bool aEnabled)
 {
   SetFeature(ENABLE_TEXTURE_YCBCR, aEnabled);
   MOZ_ASSERT(!(mFeatures & ENABLE_TEXTURE_NV12));
 }
 
 void
+ShaderConfigOGL::SetColorMultiplier(uint32_t aMultiplier)
+{
+  MOZ_ASSERT(mFeatures & ENABLE_TEXTURE_YCBCR, "Multiplier only supported with YCbCr!");
+  mMultiplier = aMultiplier;
+}
+
+void
 ShaderConfigOGL::SetNV12(bool aEnabled)
 {
   SetFeature(ENABLE_TEXTURE_NV12, aEnabled);
   MOZ_ASSERT(!(mFeatures & ENABLE_TEXTURE_YCBCR));
 }
 
 void
 ShaderConfigOGL::SetComponentAlpha(bool aEnabled)
@@ -417,33 +424,57 @@ ProgramProfileOGL::GetProfileFor(ShaderC
 
   if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
     fs << "vec4 sample(vec2 coord) {" << endl;
     fs << "  vec4 color;" << endl;
     if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR ||
         aConfig.mFeatures & ENABLE_TEXTURE_NV12) {
       if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) {
         if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
-          fs << "  COLOR_PRECISION float y = texture2D(uYTexture, coord * uTexCoordMultiplier).r;" << endl;
-          fs << "  COLOR_PRECISION float cb = texture2D(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
-          fs << "  COLOR_PRECISION float cr = texture2D(uCrTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
+          if (aConfig.mMultiplier == 1.0f) {
+            fs << "  COLOR_PRECISION float y = texture2D(uYTexture, coord * uTexCoordMultiplier).r;" << endl;
+            fs << "  COLOR_PRECISION float cb = texture2D(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
+            fs << "  COLOR_PRECISION float cr = texture2D(uCrTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
+          } else {
+            fs << "  COLOR_PRECISION float y = texture2D(uYTexture, coord * uTexCoordMultiplier).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cb = texture2D(uCbTexture, coord * uCbCrTexCoordMultiplier).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cr = texture2D(uCrTexture, coord * uCbCrTexCoordMultiplier).r * " << aConfig.mMultiplier << ".0;" << endl;
+          }
         } else {
-          fs << "  COLOR_PRECISION float y = texture2D(uYTexture, coord).r;" << endl;
-          fs << "  COLOR_PRECISION float cb = texture2D(uCbTexture, coord).r;" << endl;
-          fs << "  COLOR_PRECISION float cr = texture2D(uCrTexture, coord).r;" << endl;
+          if (aConfig.mMultiplier == 1.0) {
+            fs << "  COLOR_PRECISION float y = texture2D(uYTexture, coord).r;" << endl;
+            fs << "  COLOR_PRECISION float cb = texture2D(uCbTexture, coord).r;" << endl;
+            fs << "  COLOR_PRECISION float cr = texture2D(uCrTexture, coord).r;" << endl;
+          } else {
+            fs << "  COLOR_PRECISION float y = texture2D(uYTexture, coord).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cb = texture2D(uCbTexture, coord).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cr = texture2D(uCrTexture, coord).r * " << aConfig.mMultiplier << ".0;" << endl;
+          }
         }
       } else {
         if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) {
-          fs << "  COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord * uTexCoordMultiplier).r;" << endl;
-          fs << "  COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
-          fs << "  COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).a;" << endl;
+          if (aConfig.mMultiplier == 1.0) {
+            fs << "  COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord * uTexCoordMultiplier).r;" << endl;
+            fs << "  COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).r;" << endl;
+            fs << "  COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).a;" << endl;
+          } else {
+            fs << "  COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord * uTexCoordMultiplier).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord * uCbCrTexCoordMultiplier).a * " << aConfig.mMultiplier << ".0;" << endl;
+          }
         } else {
-          fs << "  COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord).r;" << endl;
-          fs << "  COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord).r;" << endl;
-          fs << "  COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord).a;" << endl;
+          if (aConfig.mMultiplier == 1.0) {
+            fs << "  COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord).r;" << endl;
+            fs << "  COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord).r;" << endl;
+            fs << "  COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord).a;" << endl;
+          } else {
+            fs << "  COLOR_PRECISION float y = " << texture2D << "(uYTexture, coord).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cb = " << texture2D << "(uCbTexture, coord).r * " << aConfig.mMultiplier << ".0;" << endl;
+            fs << "  COLOR_PRECISION float cr = " << texture2D << "(uCbTexture, coord).a * " << aConfig.mMultiplier << ".0;" << endl;
+          }
         }
       }
 
       fs << "  y = y - 0.06275;" << endl;
       fs << "  cb = cb - 0.50196;" << endl;
       fs << "  cr = cr - 0.50196;" << endl;
       fs << "  vec3 yuv = vec3(y, cb, cr);" << endl;
       fs << "  color.rgb = uYuvColorMatrix * yuv;" << endl;
--- a/gfx/layers/opengl/OGLShaderProgram.h
+++ b/gfx/layers/opengl/OGLShaderProgram.h
@@ -209,16 +209,17 @@ public:
   } mValue;
 };
 
 class ShaderConfigOGL
 {
 public:
   ShaderConfigOGL() :
     mFeatures(0),
+    mMultiplier(1.0f),
     mCompositionOp(gfx::CompositionOp::OP_OVER)
   {}
 
   void SetRenderColor(bool aEnabled);
   void SetTextureTarget(GLenum aTarget);
   void SetRBSwap(bool aEnabled);
   void SetNoAlpha(bool aEnabled);
   void SetOpacity(bool aEnabled);
@@ -227,32 +228,37 @@ public:
   void SetComponentAlpha(bool aEnabled);
   void SetColorMatrix(bool aEnabled);
   void SetBlur(bool aEnabled);
   void SetMask(bool aEnabled);
   void SetDEAA(bool aEnabled);
   void SetCompositionOp(gfx::CompositionOp aOp);
   void SetNoPremultipliedAlpha();
   void SetDynamicGeometry(bool aEnabled);
+  void SetColorMultiplier(uint32_t aMultiplier);
 
   bool operator< (const ShaderConfigOGL& other) const {
     return mFeatures < other.mFeatures ||
            (mFeatures == other.mFeatures &&
-            (int)mCompositionOp < (int)other.mCompositionOp);
+            (int)mCompositionOp < (int)other.mCompositionOp) ||
+           (mFeatures == other.mFeatures &&
+            (int)mCompositionOp == (int)other.mCompositionOp &&
+            mMultiplier < other.mMultiplier);
   }
 
 public:
   void SetFeature(int aBitmask, bool aState) {
     if (aState)
       mFeatures |= aBitmask;
     else
       mFeatures &= (~aBitmask);
   }
 
   int mFeatures;
+  uint32_t mMultiplier;
   gfx::CompositionOp mCompositionOp;
 };
 
 static inline ShaderConfigOGL
 ShaderConfigFromTargetAndFormat(GLenum aTarget,
                                 gfx::SurfaceFormat aFormat)
 {
   ShaderConfigOGL config;
--- a/gfx/layers/wr/WebRenderTextureHost.cpp
+++ b/gfx/layers/wr/WebRenderTextureHost.cpp
@@ -108,16 +108,25 @@ YUVColorSpace
 WebRenderTextureHost::GetYUVColorSpace() const
 {
   if (mWrappedTextureHost) {
     return mWrappedTextureHost->GetYUVColorSpace();
   }
   return YUVColorSpace::UNKNOWN;
 }
 
+uint32_t
+WebRenderTextureHost::GetDepth() const
+{
+  if (mWrappedTextureHost) {
+    return mWrappedTextureHost->GetDepth();
+  }
+  return 8;
+}
+
 gfx::IntSize
 WebRenderTextureHost::GetSize() const
 {
   if (!mWrappedTextureHost) {
     return gfx::IntSize();
   }
   return mWrappedTextureHost->GetSize();
 }
--- a/gfx/layers/wr/WebRenderTextureHost.h
+++ b/gfx/layers/wr/WebRenderTextureHost.h
@@ -46,16 +46,18 @@ public:
   virtual gfx::SurfaceFormat GetReadFormat() const override;
 
   virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override;
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
 
   virtual YUVColorSpace GetYUVColorSpace() const override;
 
+  virtual uint32_t GetDepth() const override;
+
   virtual gfx::IntSize GetSize() const override;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
   virtual const char* Name() override { return "WebRenderTextureHost"; }
 #endif
 
   virtual WebRenderTextureHost* AsWebRenderTextureHost() override { return this; }
 
--- a/gfx/tests/gtest/TestTextures.cpp
+++ b/gfx/tests/gtest/TestTextures.cpp
@@ -257,16 +257,17 @@ TEST(Layers, TextureYCbCrSerialization) 
   clientData.mCrChannel = crSurface->Data();
   clientData.mYSize = ySurface->GetSize();
   clientData.mPicSize = ySurface->GetSize();
   clientData.mCbCrSize = cbSurface->GetSize();
   clientData.mYStride = ySurface->Stride();
   clientData.mCbCrStride = cbSurface->Stride();
   clientData.mStereoMode = StereoMode::MONO;
   clientData.mYUVColorSpace = YUVColorSpace::BT601;
+  clientData.mDepth = 8;
   clientData.mYSkip = 0;
   clientData.mCbSkip = 0;
   clientData.mCrSkip = 0;
   clientData.mCrSkip = 0;
   clientData.mPicX = 0;
   clientData.mPicX = 0;
 
   uint32_t namespaceId = 1;
@@ -285,16 +286,16 @@ TEST(Layers, TextureYCbCrSerialization) 
     retry--;
   }
 
   // Skip this testing if IPDL connection is not ready
   if (!retry && !imageBridge->IPCOpen()) {
     return;
   }
 
-  RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(imageBridge, clientData.mYSize, clientData.mCbCrSize,
+  RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(imageBridge, clientData.mYSize, clientData.mYStride, clientData.mCbCrSize, clientData.mCbCrStride,
                                                                StereoMode::MONO, YUVColorSpace::BT601,
-                                                               TextureFlags::DEALLOCATE_CLIENT);
+                                                               8, TextureFlags::DEALLOCATE_CLIENT);
 
   TestTextureClientYCbCr(client, clientData);
 
   // XXX - Test more texture client types.
 }
--- a/gfx/tests/gtest/TextureHelper.h
+++ b/gfx/tests/gtest/TextureHelper.h
@@ -57,19 +57,24 @@ CreateYCbCrTextureClientWithBackend(Laye
   clientData.mCbSkip = 0;
   clientData.mCrSkip = 0;
   clientData.mCrSkip = 0;
   clientData.mPicX = 0;
   clientData.mPicX = 0;
 
   // Create YCbCrTexture for basice backend.
   if (aLayersBackend == LayersBackend::LAYERS_BASIC) {
-    return TextureClient::CreateForYCbCr(nullptr, clientData.mYSize,
-                                         clientData.mCbCrSize, StereoMode::MONO,
+    return TextureClient::CreateForYCbCr(nullptr,
+                                         clientData.mYSize,
+                                         clientData.mYStride,
+                                         clientData.mCbCrSize,
+                                         clientData.mCbCrStride,
+                                         StereoMode::MONO,
                                          YUVColorSpace::BT601,
+                                         8,
                                          TextureFlags::DEALLOCATE_CLIENT);
   }
 
 #ifdef XP_WIN
   RefPtr<ID3D11Device> device = DeviceManagerDx::Get()->GetContentDevice();
 
   if (device && aLayersBackend == LayersBackend::LAYERS_D3D11) {
     // Create YCbCrD3D11TextureData