Bug 1493198 - P4. Add support for 10/12 bits YUV image to WebRender (bindings) r=mattwoodrow
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 26 Sep 2018 14:58:25 +0000
changeset 438310 ca2d75deffe675929d377270dd65619ae1af91c7
parent 438309 c9e9863b9e202a7eaeaa1ca48b163a833eab2767
child 438311 32bb9ea9e273fa55241bcd2d9b2c399bc7f5b2bc
push id34716
push usershindli@mozilla.com
push dateWed, 26 Sep 2018 21:51:41 +0000
treeherdermozilla-central@f8b2114ab512 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1493198
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1493198 - P4. Add support for 10/12 bits YUV image to WebRender (bindings) r=mattwoodrow Depends on D6663 Differential Revision: https://phabricator.services.mozilla.com/D6688
gfx/layers/composite/TextureHost.cpp
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -651,18 +651,24 @@ BufferTextureHost::PushResourceUpdates(w
     wr::ImageDescriptor descriptor(GetSize(),
                                    ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width),
                                    GetFormat());
     (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
   } else {
     MOZ_ASSERT(aImageKeys.length() == 3);
 
     const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
-    wr::ImageDescriptor yDescriptor(desc.ySize(), desc.yStride(), gfx::SurfaceFormat::A8);
-    wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrStride(), gfx::SurfaceFormat::A8);
+    wr::ImageDescriptor yDescriptor(
+      desc.ySize(),
+      desc.yStride(),
+      SurfaceFormatForColorDepth(desc.colorDepth()));
+    wr::ImageDescriptor cbcrDescriptor(
+      desc.cbCrSize(),
+      desc.cbCrStride(),
+      SurfaceFormatForColorDepth(desc.colorDepth()));
     (aResources.*method)(aImageKeys[0], yDescriptor, aExtID, bufferType, 0);
     (aResources.*method)(aImageKeys[1], cbcrDescriptor, aExtID, bufferType, 1);
     (aResources.*method)(aImageKeys[2], cbcrDescriptor, aExtID, bufferType, 2);
   }
 }
 
 void
 BufferTextureHost::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
@@ -678,16 +684,17 @@ BufferTextureHost::PushDisplayItems(wr::
     MOZ_ASSERT(aImageKeys.length() == 3);
     const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
     aBuilder.PushYCbCrPlanarImage(aBounds,
                                   aClip,
                                   true,
                                   aImageKeys[0],
                                   aImageKeys[1],
                                   aImageKeys[2],
+                                  wr::ToWrColorDepth(desc.colorDepth()),
                                   wr::ToWrYuvColorSpace(desc.yUVColorSpace()),
                                   aFilter);
   }
 }
 
 void
 TextureHost::DeserializeReadLock(const ReadLockDescriptor& aDesc,
                                  ISurfaceAllocator* aAllocator)
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -1159,16 +1159,17 @@ DXGITextureHostD3D11::PushDisplayItems(w
     }
     case gfx::SurfaceFormat::NV12: {
       MOZ_ASSERT(aImageKeys.length() == 2);
       aBuilder.PushNV12Image(aBounds,
                              aClip,
                              true,
                              aImageKeys[0],
                              aImageKeys[1],
+                             wr::ColorDepth::Color8,
                              wr::ToWrYuvColorSpace(YUVColorSpace::BT601),
                              aFilter);
       break;
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
@@ -1391,16 +1392,17 @@ DXGIYCbCrTextureHostD3D11::PushDisplayIt
   MOZ_ASSERT(aImageKeys.length() == 3);
 
   aBuilder.PushYCbCrPlanarImage(aBounds,
                                 aClip,
                                 true,
                                 aImageKeys[0],
                                 aImageKeys[1],
                                 aImageKeys[2],
+                                wr::ToWrColorDepth(mColorDepth),
                                 wr::ToWrYuvColorSpace(mYUVColorSpace),
                                 aFilter);
 }
 
 bool
 DXGIYCbCrTextureHostD3D11::AcquireTextureSource(CompositableTextureSourceRef& aTexture)
 {
   if (!EnsureTextureSource()) {
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
@@ -223,32 +223,38 @@ MacIOSurfaceTextureHostOGL::PushDisplayI
       MOZ_ASSERT(aImageKeys.length() == 1);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
       aBuilder.PushImage(aBounds, aClip, true, aFilter, aImageKeys[0], !(mFlags & TextureFlags::NON_PREMULTIPLIED));
       break;
     }
     case gfx::SurfaceFormat::YUV422: {
       MOZ_ASSERT(aImageKeys.length() == 1);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
+      // Those images can only be generated at present by the Apple H264 decoder
+      // which only supports 8 bits color depth.
       aBuilder.PushYCbCrInterleavedImage(aBounds,
                                          aClip,
                                          true,
                                          aImageKeys[0],
+                                         wr::ColorDepth::Color8,
                                          wr::ToWrYuvColorSpace(YUVColorSpace::BT601),
                                          aFilter);
       break;
     }
     case gfx::SurfaceFormat::NV12: {
       MOZ_ASSERT(aImageKeys.length() == 2);
       MOZ_ASSERT(mSurface->GetPlaneCount() == 2);
+      // Those images can only be generated at present by the Apple H264 decoder
+      // which only supports 8 bits color depth.
       aBuilder.PushNV12Image(aBounds,
                              aClip,
                              true,
                              aImageKeys[0],
                              aImageKeys[1],
+                             wr::ColorDepth::Color8,
                              wr::ToWrYuvColorSpace(YUVColorSpace::BT601),
                              aFilter);
       break;
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -1117,62 +1117,68 @@ DisplayListBuilder::PushImage(const wr::
 
 void
 DisplayListBuilder::PushYCbCrPlanarImage(const wr::LayoutRect& aBounds,
                                          const wr::LayoutRect& aClip,
                                          bool aIsBackfaceVisible,
                                          wr::ImageKey aImageChannel0,
                                          wr::ImageKey aImageChannel1,
                                          wr::ImageKey aImageChannel2,
+                                         wr::WrColorDepth aColorDepth,
                                          wr::WrYuvColorSpace aColorSpace,
                                          wr::ImageRendering aRendering)
 {
   wr_dp_push_yuv_planar_image(mWrState,
                               aBounds,
                               MergeClipLeaf(aClip),
                               aIsBackfaceVisible,
                               aImageChannel0,
                               aImageChannel1,
                               aImageChannel2,
+                              aColorDepth,
                               aColorSpace,
                               aRendering);
 }
 
 void
 DisplayListBuilder::PushNV12Image(const wr::LayoutRect& aBounds,
                                   const wr::LayoutRect& aClip,
                                   bool aIsBackfaceVisible,
                                   wr::ImageKey aImageChannel0,
                                   wr::ImageKey aImageChannel1,
+                                  wr::WrColorDepth aColorDepth,
                                   wr::WrYuvColorSpace aColorSpace,
                                   wr::ImageRendering aRendering)
 {
   wr_dp_push_yuv_NV12_image(mWrState,
                             aBounds,
                             MergeClipLeaf(aClip),
                             aIsBackfaceVisible,
                             aImageChannel0,
                             aImageChannel1,
+                            aColorDepth,
                             aColorSpace,
                             aRendering);
 }
 
 void
 DisplayListBuilder::PushYCbCrInterleavedImage(const wr::LayoutRect& aBounds,
                                               const wr::LayoutRect& aClip,
                                               bool aIsBackfaceVisible,
                                               wr::ImageKey aImageChannel0,
+                                              wr::WrColorDepth aColorDepth,
                                               wr::WrYuvColorSpace aColorSpace,
                                               wr::ImageRendering aRendering)
 {
   wr_dp_push_yuv_interleaved_image(mWrState,
                                    aBounds,
                                    MergeClipLeaf(aClip),
                                    aIsBackfaceVisible,
                                    aImageChannel0,
+                                   aColorDepth,
                                    aColorSpace,
                                    aRendering);
 }
 
 void
 DisplayListBuilder::PushIFrame(const wr::LayoutRect& aBounds,
                                bool aIsBackfaceVisible,
                                PipelineId aPipeline,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -403,31 +403,34 @@ public:
                  const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f});
 
   void PushYCbCrPlanarImage(const wr::LayoutRect& aBounds,
                             const wr::LayoutRect& aClip,
                             bool aIsBackfaceVisible,
                             wr::ImageKey aImageChannel0,
                             wr::ImageKey aImageChannel1,
                             wr::ImageKey aImageChannel2,
+                            wr::WrColorDepth aColorDepth,
                             wr::WrYuvColorSpace aColorSpace,
                             wr::ImageRendering aFilter);
 
   void PushNV12Image(const wr::LayoutRect& aBounds,
                      const wr::LayoutRect& aClip,
                      bool aIsBackfaceVisible,
                      wr::ImageKey aImageChannel0,
                      wr::ImageKey aImageChannel1,
+                     wr::WrColorDepth aColorDepth,
                      wr::WrYuvColorSpace aColorSpace,
                      wr::ImageRendering aFilter);
 
   void PushYCbCrInterleavedImage(const wr::LayoutRect& aBounds,
                                  const wr::LayoutRect& aClip,
                                  bool aIsBackfaceVisible,
                                  wr::ImageKey aImageChannel0,
+                                 wr::WrColorDepth aColorDepth,
                                  wr::WrYuvColorSpace aColorSpace,
                                  wr::ImageRendering aFilter);
 
   void PushIFrame(const wr::LayoutRect& aBounds,
                   bool aIsBackfaceVisible,
                   wr::PipelineId aPipeline,
                   bool aIgnoreMissingPipeline);
 
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -68,31 +68,35 @@ SurfaceFormatToImageFormat(gfx::SurfaceF
       return Nothing();
     case gfx::SurfaceFormat::B8G8R8X8:
       // TODO: WebRender will have a BGRA + opaque flag for this but does not
       // have it yet (cf. issue #732).
     case gfx::SurfaceFormat::B8G8R8A8:
       return Some(wr::ImageFormat::BGRA8);
     case gfx::SurfaceFormat::A8:
       return Some(wr::ImageFormat::R8);
+    case gfx::SurfaceFormat::A16:
+      return Some(wr::ImageFormat::R16);
     case gfx::SurfaceFormat::R8G8:
       return Some(wr::ImageFormat::RG8);
     case gfx::SurfaceFormat::UNKNOWN:
     default:
       return Nothing();
   }
 }
 
 inline gfx::SurfaceFormat
 ImageFormatToSurfaceFormat(ImageFormat aFormat) {
   switch (aFormat) {
     case ImageFormat::BGRA8:
       return gfx::SurfaceFormat::B8G8R8A8;
     case ImageFormat::R8:
       return gfx::SurfaceFormat::A8;
+    case ImageFormat::R16:
+      return gfx::SurfaceFormat::A16;
     default:
       return gfx::SurfaceFormat::UNKNOWN;
   }
 }
 
 struct ImageDescriptor: public wr::WrImageDescriptor {
   // We need a default constructor for ipdl serialization.
   ImageDescriptor()
@@ -839,16 +843,30 @@ static inline wr::WrYuvColorSpace ToWrYu
     case YUVColorSpace::BT709:
       return wr::WrYuvColorSpace::Rec709;
     default:
       MOZ_ASSERT_UNREACHABLE("Tried to convert invalid YUVColorSpace.");
   }
   return wr::WrYuvColorSpace::Rec601;
 }
 
+static inline wr::WrColorDepth ToWrColorDepth(gfx::ColorDepth aColorDepth) {
+  switch (aColorDepth) {
+    case gfx::ColorDepth::COLOR_8:
+      return wr::WrColorDepth::Color8;
+    case gfx::ColorDepth::COLOR_10:
+      return wr::WrColorDepth::Color10;
+    case gfx::ColorDepth::COLOR_12:
+      return wr::WrColorDepth::Color12;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Tried to convert invalid color depth value.");
+  }
+  return wr::WrColorDepth::Color8;
+}
+
 static inline wr::SyntheticItalics DegreesToSyntheticItalics(float aDegrees) {
   wr::SyntheticItalics synthetic_italics;
   synthetic_italics.angle = int16_t(std::min(std::max(aDegrees, -89.0f), 89.0f) * 256.0f);
   return synthetic_italics;
 }
 
 } // namespace wr
 } // namespace mozilla
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -79,16 +79,18 @@ type WrPipelineId = PipelineId;
 /// cbindgen:derive-neq=true
 type WrImageKey = ImageKey;
 /// cbindgen:field-names=[mNamespace, mHandle]
 pub type WrFontKey = FontKey;
 /// cbindgen:field-names=[mNamespace, mHandle]
 pub type WrFontInstanceKey = FontInstanceKey;
 /// cbindgen:field-names=[mNamespace, mHandle]
 type WrYuvColorSpace = YuvColorSpace;
+/// cbindgen:field-names=[mNamespace, mHandle]
+type WrColorDepth = ColorDepth;
 
 fn make_slice<'a, T>(ptr: *const T, len: usize) -> &'a [T] {
     if ptr.is_null() {
         &[]
     } else {
         unsafe { slice::from_raw_parts(ptr, len) }
     }
 }
@@ -2042,75 +2044,78 @@ pub extern "C" fn wr_dp_push_image(state
 #[no_mangle]
 pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,
                                               bounds: LayoutRect,
                                               clip: LayoutRect,
                                               is_backface_visible: bool,
                                               image_key_0: WrImageKey,
                                               image_key_1: WrImageKey,
                                               image_key_2: WrImageKey,
+                                              color_depth: WrColorDepth,
                                               color_space: WrYuvColorSpace,
                                               image_rendering: ImageRendering) {
     debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
 
     let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
     prim_info.is_backface_visible = is_backface_visible;
     prim_info.tag = state.current_tag;
     state.frame_builder
          .dl_builder
          .push_yuv_image(&prim_info,
                          YuvData::PlanarYCbCr(image_key_0, image_key_1, image_key_2),
-                         ColorDepth::Color8,
+                         color_depth,
                          color_space,
                          image_rendering);
 }
 
 /// Push a 2 planar NV12 image.
 #[no_mangle]
 pub extern "C" fn wr_dp_push_yuv_NV12_image(state: &mut WrState,
                                             bounds: LayoutRect,
                                             clip: LayoutRect,
                                             is_backface_visible: bool,
                                             image_key_0: WrImageKey,
                                             image_key_1: WrImageKey,
+                                            color_depth: WrColorDepth,
                                             color_space: WrYuvColorSpace,
                                             image_rendering: ImageRendering) {
     debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
 
     let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
     prim_info.is_backface_visible = is_backface_visible;
     prim_info.tag = state.current_tag;
     state.frame_builder
          .dl_builder
          .push_yuv_image(&prim_info,
                          YuvData::NV12(image_key_0, image_key_1),
-                         ColorDepth::Color8,
+                         color_depth,
                          color_space,
                          image_rendering);
 }
 
 /// Push a yuv interleaved image.
 #[no_mangle]
 pub extern "C" fn wr_dp_push_yuv_interleaved_image(state: &mut WrState,
                                                    bounds: LayoutRect,
                                                    clip: LayoutRect,
                                                    is_backface_visible: bool,
                                                    image_key_0: WrImageKey,
+                                                   color_depth: WrColorDepth,
                                                    color_space: WrYuvColorSpace,
                                                    image_rendering: ImageRendering) {
     debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
 
     let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
     prim_info.is_backface_visible = is_backface_visible;
     prim_info.tag = state.current_tag;
     state.frame_builder
          .dl_builder
          .push_yuv_image(&prim_info,
                          YuvData::InterleavedYCbCr(image_key_0),
-                         ColorDepth::Color8,
+                         color_depth,
                          color_space,
                          image_rendering);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_text(state: &mut WrState,
                                   bounds: LayoutRect,
                                   clip: LayoutRect,
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -56,16 +56,28 @@ enum class Checkpoint : uint32_t {
 
 enum class ClipMode {
   Clip,
   ClipOut,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
+// Specifies the color depth of an image. Currently only used for YUV images.
+enum class ColorDepth : uint8_t {
+  // 8 bits image (most common)
+  Color8,
+  // 10 bits image
+  Color10,
+  // 12 bits image
+  Color12,
+
+  Sentinel /* this must be last for serialization purposes. */
+};
+
 enum class ExtendMode : uint32_t {
   Clamp,
   Repeat,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
 #if !(defined(XP_MACOSX) || defined(XP_WIN))
@@ -929,16 +941,18 @@ struct GlyphOptions {
   FontInstanceFlags flags;
 
   bool operator==(const GlyphOptions& aOther) const {
     return render_mode == aOther.render_mode &&
            flags == aOther.flags;
   }
 };
 
+using WrColorDepth = ColorDepth;
+
 using WrYuvColorSpace = YuvColorSpace;
 
 struct ByteSlice {
   const uint8_t *buffer;
   uintptr_t len;
 
   bool operator==(const ByteSlice& aOther) const {
     return buffer == aOther.buffer &&
@@ -1485,40 +1499,43 @@ WR_FUNC;
 // Push a 2 planar NV12 image.
 WR_INLINE
 void wr_dp_push_yuv_NV12_image(WrState *aState,
                                LayoutRect aBounds,
                                LayoutRect aClip,
                                bool aIsBackfaceVisible,
                                WrImageKey aImageKey0,
                                WrImageKey aImageKey1,
+                               WrColorDepth aColorDepth,
                                WrYuvColorSpace aColorSpace,
                                ImageRendering aImageRendering)
 WR_FUNC;
 
 // Push a yuv interleaved image.
 WR_INLINE
 void wr_dp_push_yuv_interleaved_image(WrState *aState,
                                       LayoutRect aBounds,
                                       LayoutRect aClip,
                                       bool aIsBackfaceVisible,
                                       WrImageKey aImageKey0,
+                                      WrColorDepth aColorDepth,
                                       WrYuvColorSpace aColorSpace,
                                       ImageRendering aImageRendering)
 WR_FUNC;
 
 // Push a 3 planar yuv image.
 WR_INLINE
 void wr_dp_push_yuv_planar_image(WrState *aState,
                                  LayoutRect aBounds,
                                  LayoutRect aClip,
                                  bool aIsBackfaceVisible,
                                  WrImageKey aImageKey0,
                                  WrImageKey aImageKey1,
                                  WrImageKey aImageKey2,
+                                 WrColorDepth aColorDepth,
                                  WrYuvColorSpace aColorSpace,
                                  ImageRendering aImageRendering)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_restore(WrState *aState)
 WR_FUNC;