Bug 1497294 - P7. Add P016 and P010 surface format support. r=jgilbert
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 10 Oct 2018 22:21:53 +0000
changeset 499200 1b12b56178b666c0f0493d62a8b6aa368d0758b7
parent 499199 227a0a6ae1dfbadd73f96c64a307d001fb351108
child 499201 c2666a1b9efc528357fd2481728f928560e0d3bd
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1497294
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 1497294 - P7. Add P016 and P010 surface format support. r=jgilbert This is only used with DXVA decoder. P016 and P010 are just like NV12 but with 16 bits data.. Depends on D8246 Differential Revision: https://phabricator.services.mozilla.com/D8136
dom/canvas/ImageUtils.cpp
gfx/2d/Types.h
gfx/gl/GLBlitHelperD3D.cpp
gfx/layers/D3D11ShareHandleImage.cpp
gfx/layers/Effects.h
gfx/layers/LayersLogging.cpp
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/MLGDeviceD3D11.cpp
gfx/layers/d3d11/MLGDeviceD3D11.h
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/mlgpu/RenderPassMLGPU.cpp
gfx/webrender_bindings/RenderD3D11TextureHostOGL.cpp
--- a/dom/canvas/ImageUtils.cpp
+++ b/dom/canvas/ImageUtils.cpp
@@ -37,16 +37,18 @@ GetImageBitmapFormatFromSurfaceFromat(Su
     return ImageBitmapFormat::Lab;
   case SurfaceFormat::Depth:
     return ImageBitmapFormat::DEPTH;
   case SurfaceFormat::A8:
     return ImageBitmapFormat::GRAY8;
   case SurfaceFormat::R5G6B5_UINT16:
   case SurfaceFormat::YUV:
   case SurfaceFormat::NV12:
+  case SurfaceFormat::P010:
+  case SurfaceFormat::P016:
   case SurfaceFormat::UNKNOWN:
   default:
     return ImageBitmapFormat::EndGuard_;
   }
 }
 
 static ImageBitmapFormat
 GetImageBitmapFormatFromPlanarYCbCrData(layers::PlanarYCbCrData const *aData)
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -59,17 +59,23 @@ enum class SurfaceFormat : int8_t {
   // This one is a single-byte, so endianness isn't an issue.
   A8,
   A16,
 
   R8G8,
 
   // These ones are their own special cases.
   YUV,
-  NV12,
+  NV12,         // YUV 4:2:0 image with a plane of 8 bit Y samples followed by
+                // an interleaved U/V plane containing 8 bit 2x2 subsampled
+                // colour difference samples.
+  P016,         // Similar to NV12, but with 16 bits plane values
+  P010,         // Identical to P016 but the 6 least significant bits are 0.
+                // With DXGI in theory entirely compatible, however practice has
+                // shown that it's not the case.
   YUV422,
   HSV,
   Lab,
   Depth,
 
   // This represents the unknown format.
   UNKNOWN,
 
@@ -119,16 +125,18 @@ inline bool IsOpaque(SurfaceFormat aForm
   case SurfaceFormat::R8G8B8:
   case SurfaceFormat::B8G8R8:
   case SurfaceFormat::R8G8:
   case SurfaceFormat::HSV:
   case SurfaceFormat::Lab:
   case SurfaceFormat::Depth:
   case SurfaceFormat::YUV:
   case SurfaceFormat::NV12:
+  case SurfaceFormat::P010:
+  case SurfaceFormat::P016:
   case SurfaceFormat::YUV422:
     return true;
   default:
     return false;
   }
 }
 
 enum class ColorDepth : uint8_t {
--- a/gfx/gl/GLBlitHelperD3D.cpp
+++ b/gfx/gl/GLBlitHelperD3D.cpp
@@ -248,20 +248,22 @@ GLBlitHelper::BlitDescriptor(const layer
     const auto& handle = desc.handle();
     const auto& format = desc.format();
     const auto& clipSize = desc.size();
 
     const auto srcOrigin = OriginPos::BottomLeft;
     const gfx::IntRect clipRect(0, 0, clipSize.width, clipSize.height);
     const auto colorSpace = YUVColorSpace::BT601;
 
-    if (format != gfx::SurfaceFormat::NV12) {
+    if (format != gfx::SurfaceFormat::NV12 &&
+        format != gfx::SurfaceFormat::P010 &&
+        format != gfx::SurfaceFormat::P016) {
         gfxCriticalError() << "Non-NV12 format for SurfaceDescriptorD3D10: "
                            << uint32_t(format);
-        return false;
+      return false;
     }
 
     const auto tex = OpenSharedTexture(d3d, handle);
     if (!tex) {
         MOZ_ASSERT(false, "Get a nullptr from OpenSharedResource.");
         return false;
     }
     const RefPtr<ID3D11Texture2D> texList[2] = { tex, tex };
--- a/gfx/layers/D3D11ShareHandleImage.cpp
+++ b/gfx/layers/D3D11ShareHandleImage.cpp
@@ -39,33 +39,49 @@ D3D11ShareHandleImage::AllocateTexture(D
                                        ID3D11Device* aDevice)
 {
   if (aAllocator) {
     if (mSourceFormat == MFVideoFormat_NV12 &&
         gfxPrefs::PDMWMFUseNV12Format() &&
         gfx::DeviceManagerDx::Get()->CanUseNV12()) {
       mTextureClient =
         aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::NV12, mSize);
+    } else if (((mSourceFormat == MFVideoFormat_P010 &&
+                 gfx::DeviceManagerDx::Get()->CanUseP010()) ||
+                (mSourceFormat == MFVideoFormat_P016 &&
+                 gfx::DeviceManagerDx::Get()->CanUseP016())) &&
+               gfxPrefs::PDMWMFUseNV12Format()) {
+      mTextureClient = aAllocator->CreateOrRecycleClient(
+        mSourceFormat == MFVideoFormat_P010 ? gfx::SurfaceFormat::P010
+                                            : gfx::SurfaceFormat::P016,
+        mSize);
     } else {
       mTextureClient =
         aAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8, mSize);
     }
     if (mTextureClient) {
-      mTexture = static_cast<D3D11TextureData*>(mTextureClient->GetInternalData())->GetD3D11Texture();
+      mTexture =
+        static_cast<D3D11TextureData*>(mTextureClient->GetInternalData())
+          ->GetD3D11Texture();
       return true;
     }
     return false;
   } else {
     MOZ_ASSERT(aDevice);
     CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
-                                  mSize.width, mSize.height, 1, 1,
-                                  D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
+                                  mSize.width,
+                                  mSize.height,
+                                  1,
+                                  1,
+                                  D3D11_BIND_RENDER_TARGET |
+                                    D3D11_BIND_SHADER_RESOURCE);
     newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
 
-    HRESULT hr = aDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(mTexture));
+    HRESULT hr =
+      aDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(mTexture));
     return SUCCEEDED(hr);
   }
 }
 
 gfx::IntSize
 D3D11ShareHandleImage::GetSize() const
 {
   return mSize;
@@ -181,17 +197,18 @@ D3D11ShareHandleImage::GetAsSourceSurfac
 
   context->Unmap(softTexture, 0);
   surface->Unmap();
 
   return surface.forget();
 }
 
 ID3D11Texture2D*
-D3D11ShareHandleImage::GetTexture() const {
+D3D11ShareHandleImage::GetTexture() const
+{
   return mTexture;
 }
 
 already_AddRefed<TextureClient>
 D3D11RecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
                                 gfx::IntSize aSize,
                                 BackendSelector aSelector,
                                 TextureFlags aTextureFlags,
--- a/gfx/layers/Effects.h
+++ b/gfx/layers/Effects.h
@@ -247,16 +247,18 @@ CreateTexturedEffect(gfx::SurfaceFormat 
   case gfx::SurfaceFormat::B8G8R8A8:
   case gfx::SurfaceFormat::B8G8R8X8:
   case gfx::SurfaceFormat::R8G8B8X8:
   case gfx::SurfaceFormat::R5G6B5_UINT16:
   case gfx::SurfaceFormat::R8G8B8A8:
     result = new EffectRGB(aSource, isAlphaPremultiplied, aSamplingFilter);
     break;
   case gfx::SurfaceFormat::NV12:
+  case gfx::SurfaceFormat::P010:
+  case gfx::SurfaceFormat::P016:
     result = new EffectNV12(aSource, aSamplingFilter);
     break;
   case gfx::SurfaceFormat::YUV:
     MOZ_ASSERT_UNREACHABLE("gfx::SurfaceFormat::YUV is invalid");
     break;
   default:
     NS_WARNING("unhandled program type");
     break;
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -385,16 +385,18 @@ AppendToString(std::stringstream& aStrea
   case SurfaceFormat::B8G8R8X8:  aStream << "SurfaceFormat::B8G8R8X8"; break;
   case SurfaceFormat::R8G8B8A8:  aStream << "SurfaceFormat::R8G8B8A8"; break;
   case SurfaceFormat::R8G8B8X8:  aStream << "SurfaceFormat::R8G8B8X8"; break;
   case SurfaceFormat::R5G6B5_UINT16:
                                  aStream << "SurfaceFormat::R5G6B5_UINT16"; break;
   case SurfaceFormat::A8:        aStream << "SurfaceFormat::A8"; break;
   case SurfaceFormat::YUV:       aStream << "SurfaceFormat::YUV"; break;
   case SurfaceFormat::NV12:      aStream << "SurfaceFormat::NV12"; break;
+  case SurfaceFormat::P010:      aStream << "SurfaceFormat::P010"; break;
+  case SurfaceFormat::P016:      aStream << "SurfaceFormat::P016"; break;
   case SurfaceFormat::YUV422:    aStream << "SurfaceFormat::YUV422"; break;
   case SurfaceFormat::UNKNOWN:   aStream << "SurfaceFormat::UNKNOWN"; break;
   default:
     NS_ERROR("unknown surface format");
     aStream << "???";
   }
 
   aStream << sfx;
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -843,29 +843,37 @@ CompositorD3D11::DrawGeometry(const Geom
         return;
       }
 
       RefPtr<ID3D11Texture2D> texture = source->GetD3D11Texture();
       if (!texture) {
         NS_WARNING("No texture found in texture source!");
       }
 
+      D3D11_TEXTURE2D_DESC sourceDesc;
+      texture->GetDesc(&sourceDesc);
+      MOZ_DIAGNOSTIC_ASSERT(sourceDesc.Format == DXGI_FORMAT_NV12 ||
+                            sourceDesc.Format == DXGI_FORMAT_P010 ||
+                            sourceDesc.Format == DXGI_FORMAT_P016);
+
       // Might want to cache these for efficiency.
       RefPtr<ID3D11ShaderResourceView> srViewY;
       RefPtr<ID3D11ShaderResourceView> srViewCbCr;
       D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc =
         CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D,
-                                         DXGI_FORMAT_R8_UNORM);
-      mDevice->CreateShaderResourceView(texture,
-                                        &srvDesc,
-                                        getter_AddRefs(srViewY));
-      srvDesc.Format = DXGI_FORMAT_R8G8_UNORM;
-      mDevice->CreateShaderResourceView(texture,
-                                        &srvDesc,
-                                        getter_AddRefs(srViewCbCr));
+                                         sourceDesc.Format == DXGI_FORMAT_NV12
+                                           ? DXGI_FORMAT_R8_UNORM
+                                           : DXGI_FORMAT_R16_UNORM);
+      mDevice->CreateShaderResourceView(
+        texture, &srvDesc, getter_AddRefs(srViewY));
+      srvDesc.Format = sourceDesc.Format == DXGI_FORMAT_NV12
+                         ? DXGI_FORMAT_R8G8_UNORM
+                         : DXGI_FORMAT_R16G16_UNORM;
+      mDevice->CreateShaderResourceView(
+        texture, &srvDesc, getter_AddRefs(srViewCbCr));
 
       ID3D11ShaderResourceView* views[] = { srViewY, srViewCbCr };
       mContext->PSSetShaderResources(TexSlot::Y, 2, views);
 
       const float* yuvToRgb = gfxUtils::YuvToRgbMatrix4x3RowMajor(YUVColorSpace::BT601);
       memcpy(&mPSConstants.yuvColorMatrix, yuvToRgb, sizeof(mPSConstants.yuvColorMatrix));
       // TOTO: need to handle color depth properly. this assumes data is always
       // 8 or 16 bits.
--- a/gfx/layers/d3d11/MLGDeviceD3D11.cpp
+++ b/gfx/layers/d3d11/MLGDeviceD3D11.cpp
@@ -1743,52 +1743,52 @@ MLGDeviceD3D11::MaybeLockTexture(ID3D11T
   } else {
     mLockedTextures.PutEntry(mutex);
   }
 }
 
 void
 MLGDeviceD3D11::SetPSTexturesNV12(uint32_t aSlot, TextureSource* aTexture)
 {
-  MOZ_ASSERT(aTexture->GetFormat() == SurfaceFormat::NV12);
+  MOZ_ASSERT(aTexture->GetFormat() == SurfaceFormat::NV12 ||
+             aTexture->GetFormat() == SurfaceFormat::P010 ||
+             aTexture->GetFormat() == SurfaceFormat::P016);
 
   TextureSourceD3D11* source = aTexture->AsSourceD3D11();
   if (!source) {
     gfxWarning() << "Unknown texture type in SetPSCompoundTexture";
     return;
   }
 
   ID3D11Texture2D* texture = source->GetD3D11Texture();
   if (!texture) {
     gfxWarning() << "TextureSourceD3D11 does not have an ID3D11Texture";
     return;
   }
 
   MaybeLockTexture(texture);
 
-  RefPtr<ID3D11ShaderResourceView> views[2];
-  D3D11_SHADER_RESOURCE_VIEW_DESC desc =
-    CD3D11_SHADER_RESOURCE_VIEW_DESC(
-      D3D11_SRV_DIMENSION_TEXTURE2D,
-      DXGI_FORMAT_R8_UNORM);
+  const bool isNV12 = aTexture->GetFormat() == SurfaceFormat::NV12;
 
-  HRESULT hr = mDevice->CreateShaderResourceView(
-    texture,
-    &desc,
-    getter_AddRefs(views[0]));
+  RefPtr<ID3D11ShaderResourceView> views[2];
+  D3D11_SHADER_RESOURCE_VIEW_DESC desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(
+    D3D11_SRV_DIMENSION_TEXTURE2D,
+    isNV12 ? DXGI_FORMAT_R8_UNORM : DXGI_FORMAT_R16_UNORM);
+
+  HRESULT hr =
+    mDevice->CreateShaderResourceView(texture, &desc, getter_AddRefs(views[0]));
   if (FAILED(hr) || !views[0]) {
-    gfxWarning() << "Could not bind an SRV for Y plane of NV12 texture: " << hexa(hr);
+    gfxWarning() << "Could not bind an SRV for Y plane of NV12 texture: "
+                 << hexa(hr);
     return;
   }
 
-  desc.Format = DXGI_FORMAT_R8G8_UNORM;
-  hr = mDevice->CreateShaderResourceView(
-    texture,
-    &desc,
-    getter_AddRefs(views[1]));
+  desc.Format = isNV12 ? DXGI_FORMAT_R8G8_UNORM : DXGI_FORMAT_R16G16_UNORM;
+  hr =
+    mDevice->CreateShaderResourceView(texture, &desc, getter_AddRefs(views[1]));
   if (FAILED(hr) || !views[1]) {
     gfxWarning() << "Could not bind an SRV for CbCr plane of NV12 texture: " << hexa(hr);
     return;
   }
 
   ID3D11ShaderResourceView* bind[2] = {
     views[0],
     views[1]
--- a/gfx/layers/d3d11/MLGDeviceD3D11.h
+++ b/gfx/layers/d3d11/MLGDeviceD3D11.h
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h 
-#define mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h 
+#ifndef mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
+#define mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
 
 #include <d3d11_1.h>
 
 #include "mozilla/layers/MLGDevice.h"
 #include "mozilla/layers/SyncObject.h"
 #include "mozilla/EnumeratedArray.h"
 #include "nsTHashtable.h"
 #include "nsPrintfCString.h"
@@ -314,17 +314,17 @@ private:
   RefPtr<MLGBuffer> mUnitTriangleVB;
   RefPtr<ID3D11VertexShader> mCurrentVertexShader;
   RefPtr<ID3D11InputLayout> mCurrentInputLayout;
   RefPtr<ID3D11PixelShader> mCurrentPixelShader;
   RefPtr<ID3D11BlendState> mCurrentBlendState;
 
   RefPtr<ID3D11Query> mWaitForPresentQuery;
   RefPtr<ID3D11Query> mNextWaitForPresentQuery;
-  
+
   nsTHashtable<nsRefPtrHashKey<IDXGIKeyedMutex>> mLockedTextures;
   nsTHashtable<nsRefPtrHashKey<IDXGIKeyedMutex>> mLockAttemptedTextures;
 
   typedef EnumeratedArray<PixelShaderID, PixelShaderID::MaxShaders, const ShaderBytes*> LazyPixelShaderArray;
   LazyPixelShaderArray mLazyPixelShaders;
 
   typedef EnumeratedArray<VertexShaderID, VertexShaderID::MaxShaders, const ShaderBytes*> LazyVertexShaderArray;
   LazyVertexShaderArray mLazyVertexShaders;
@@ -332,9 +332,9 @@ private:
   bool mScissored;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 struct ShaderBytes;
 
-#endif // mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h 
+#endif // mozilla_gfx_layers_d3d11_MLGDeviceD3D11_h
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -463,16 +463,20 @@ D3D11TextureData::Create(IntSize aSize, 
   }
 
   CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
                                 aSize.width, aSize.height, 1, 1,
                                 D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
 
   if (aFormat == SurfaceFormat::NV12) {
     newDesc.Format = DXGI_FORMAT_NV12;
+  } else if (aFormat == SurfaceFormat::P010) {
+    newDesc.Format = DXGI_FORMAT_P010;
+  } else if (aFormat == SurfaceFormat::P016) {
+    newDesc.Format = DXGI_FORMAT_P016;
   }
 
   newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
   if (!NS_IsMainThread() || !!(aFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT)) {
     // On the main thread we use the syncobject to handle synchronization.
     if (!(aFlags & ALLOC_MANUAL_SYNCHRONIZATION)) {
       newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
     }
@@ -1080,17 +1084,19 @@ DXGITextureHostD3D11::NumSubTextures() c
 {
   switch (GetFormat()) {
     case gfx::SurfaceFormat::R8G8B8X8:
     case gfx::SurfaceFormat::R8G8B8A8:
     case gfx::SurfaceFormat::B8G8R8A8:
     case gfx::SurfaceFormat::B8G8R8X8: {
       return 1;
     }
-    case gfx::SurfaceFormat::NV12: {
+    case gfx::SurfaceFormat::NV12:
+    case gfx::SurfaceFormat::P010:
+    case gfx::SurfaceFormat::P016: {
       return 2;
     }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected format");
       return 1;
     }
   }
 }
@@ -1164,16 +1170,29 @@ DXGITextureHostD3D11::PushDisplayItems(w
                              true,
                              aImageKeys[0],
                              aImageKeys[1],
                              wr::ColorDepth::Color8,
                              wr::ToWrYuvColorSpace(YUVColorSpace::BT601),
                              aFilter);
       break;
     }
+    case gfx::SurfaceFormat::P010:
+    case gfx::SurfaceFormat::P016: {
+      MOZ_ASSERT(aImageKeys.length() == 2);
+      aBuilder.PushNV12Image(aBounds,
+                             aClip,
+                             true,
+                             aImageKeys[0],
+                             aImageKeys[1],
+                             wr::ColorDepth::Color16,
+                             wr::ToWrYuvColorSpace(YUVColorSpace::BT601),
+                             aFilter);
+      break;
+    }
     default: {
       MOZ_ASSERT_UNREACHABLE("unexpected to be called");
     }
   }
 }
 
 DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
   const SurfaceDescriptorDXGIYCbCr& aDescriptor)
--- a/gfx/layers/mlgpu/RenderPassMLGPU.cpp
+++ b/gfx/layers/mlgpu/RenderPassMLGPU.cpp
@@ -115,18 +115,19 @@ RenderPassMLGPU::GetPreferredPassType(Fr
     return RenderPassType::SingleTexture;
   }
   case Layer::TYPE_CANVAS:
     return RenderPassType::SingleTexture;
   case Layer::TYPE_IMAGE: {
     ImageHost* host = layer->AsTexturedLayerMLGPU()->GetImageHost();
     TextureHost* texture = host->CurrentTextureHost();
     if (texture->GetReadFormat() == SurfaceFormat::YUV ||
-        texture->GetReadFormat() == SurfaceFormat::NV12)
-    {
+        texture->GetReadFormat() == SurfaceFormat::NV12 ||
+        texture->GetReadFormat() == SurfaceFormat::P010 ||
+        texture->GetReadFormat() == SurfaceFormat::P016) {
       return RenderPassType::Video;
     }
     return RenderPassType::SingleTexture;
   }
   case Layer::TYPE_CONTAINER:
     return RenderPassType::RenderView;
   default:
     return RenderPassType::Unknown;
@@ -800,16 +801,19 @@ VideoRenderPass::SetupPipeline()
 {
   YUVColorSpace colorSpace = YUVColorSpace::UNKNOWN;
   switch (mHost->GetReadFormat()) {
   case SurfaceFormat::YUV: {
     colorSpace = mHost->GetYUVColorSpace();
     break;
   }
   case SurfaceFormat::NV12:
+  case SurfaceFormat::P010:
+  case SurfaceFormat::P016:
+    // TODO. BT601 is very unlikely to be the right value for high-def content.
     colorSpace = YUVColorSpace::BT601;
     break;
   default:
     MOZ_ASSERT_UNREACHABLE("Unexpected surface format in VideoRenderPass");
     break;
   }
   MOZ_ASSERT(colorSpace != YUVColorSpace::UNKNOWN);
 
@@ -836,16 +840,18 @@ VideoRenderPass::SetupPipeline()
     if (mGeometry == GeometryMode::UnitQuad)
       mDevice->SetPixelShader(PixelShaderID::TexturedQuadIMC4);
     else
       mDevice->SetPixelShader(PixelShaderID::TexturedVertexIMC4);
     mDevice->SetPSTexturesYUV(0, mTexture);
     break;
   }
   case SurfaceFormat::NV12:
+  case SurfaceFormat::P010:
+  case SurfaceFormat::P016:
     if (mGeometry == GeometryMode::UnitQuad)
       mDevice->SetPixelShader(PixelShaderID::TexturedQuadNV12);
     else
       mDevice->SetPixelShader(PixelShaderID::TexturedVertexNV12);
     mDevice->SetPSTexturesNV12(0, mTexture);
     break;
   default:
     MOZ_ASSERT_UNREACHABLE("Unknown video format");
--- a/gfx/webrender_bindings/RenderD3D11TextureHostOGL.cpp
+++ b/gfx/webrender_bindings/RenderD3D11TextureHostOGL.cpp
@@ -24,17 +24,19 @@ RenderDXGITextureHostOGL::RenderDXGIText
   , mSurface(0)
   , mStream(0)
   , mTextureHandle{0}
   , mFormat(aFormat)
   , mSize(aSize)
   , mLocked(false)
 {
   MOZ_COUNT_CTOR_INHERITED(RenderDXGITextureHostOGL, RenderTextureHostOGL);
-  MOZ_ASSERT(mFormat != gfx::SurfaceFormat::NV12 ||
+  MOZ_ASSERT((mFormat != gfx::SurfaceFormat::NV12 &&
+              mFormat != gfx::SurfaceFormat::P010 &&
+              mFormat != gfx::SurfaceFormat::P016) ||
              (mSize.width % 2 == 0 && mSize.height % 2 == 0));
   MOZ_ASSERT(aHandle);
 }
 
 RenderDXGITextureHostOGL::~RenderDXGITextureHostOGL()
 {
   MOZ_COUNT_DTOR_INHERITED(RenderDXGITextureHostOGL, RenderTextureHostOGL);
   DeleteTextureHandle();
@@ -48,18 +50,20 @@ RenderDXGITextureHostOGL::EnsureLockable
     if (IsFilterUpdateNecessary(aRendering)) {
       ActivateBindAndTexParameteri(mGL,
                                    LOCAL_GL_TEXTURE0,
                                    LOCAL_GL_TEXTURE_EXTERNAL_OES,
                                    mTextureHandle[0],
                                    aRendering);
       // Cache new rendering filter.
       mCachedRendering = aRendering;
-      // NV12 uses two handles.
-      if (mFormat == gfx::SurfaceFormat::NV12) {
+      // NV12 and P016 uses two handles.
+      if (mFormat == gfx::SurfaceFormat::NV12 ||
+          mFormat == gfx::SurfaceFormat::P010 ||
+          mFormat == gfx::SurfaceFormat::P016) {
         ActivateBindAndTexParameteri(mGL,
                                      LOCAL_GL_TEXTURE1,
                                      LOCAL_GL_TEXTURE_EXTERNAL_OES,
                                      mTextureHandle[1],
                                      aRendering);
       }
     }
     return true;
@@ -95,31 +99,33 @@ RenderDXGITextureHostOGL::EnsureLockable
   }
 
   mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
 
   // Create the EGLStream.
   mStream = egl->fCreateStreamKHR(egl->Display(), nullptr);
   MOZ_ASSERT(mStream);
 
-  if (mFormat != gfx::SurfaceFormat::NV12) {
+  if (mFormat != gfx::SurfaceFormat::NV12 &&
+      mFormat != gfx::SurfaceFormat::P010 &&
+      mFormat != gfx::SurfaceFormat::P016) {
     // The non-nv12 format.
 
     mGL->fGenTextures(1, mTextureHandle);
     ActivateBindAndTexParameteri(mGL,
                                  LOCAL_GL_TEXTURE0,
                                  LOCAL_GL_TEXTURE_EXTERNAL_OES,
                                  mTextureHandle[0],
                                  aRendering);
     // Cache new rendering filter.
     mCachedRendering = aRendering;
     MOZ_ALWAYS_TRUE(egl->fStreamConsumerGLTextureExternalAttribsNV(egl->Display(), mStream, nullptr));
     MOZ_ALWAYS_TRUE(egl->fCreateStreamProducerD3DTextureANGLE(egl->Display(), mStream, nullptr));
   } else {
-    // The nv12 format.
+    // The nv12/p016 format.
 
     // Setup the NV12 stream consumer/producer.
     EGLAttrib consumerAttributes[] = {
         LOCAL_EGL_COLOR_BUFFER_TYPE,
         LOCAL_EGL_YUV_BUFFER_EXT,
         LOCAL_EGL_YUV_NUMBER_OF_PLANES_EXT,
         2,
         LOCAL_EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
@@ -231,27 +237,32 @@ RenderDXGITextureHostOGL::DeleteTextureH
 
   mTexture = nullptr;
   mKeyedMutex = nullptr;
 }
 
 GLuint
 RenderDXGITextureHostOGL::GetGLHandle(uint8_t aChannelIndex) const
 {
-  MOZ_ASSERT(mFormat != gfx::SurfaceFormat::NV12 || aChannelIndex < 2);
-  MOZ_ASSERT(mFormat == gfx::SurfaceFormat::NV12 || aChannelIndex < 1);
-
+  MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
+               mFormat == gfx::SurfaceFormat::P010 ||
+               mFormat == gfx::SurfaceFormat::P016) &&
+              aChannelIndex < 2) ||
+             aChannelIndex < 1);
   return mTextureHandle[aChannelIndex];
 }
 
 gfx::IntSize
 RenderDXGITextureHostOGL::GetSize(uint8_t aChannelIndex) const
 {
-  MOZ_ASSERT(mFormat != gfx::SurfaceFormat::NV12 || aChannelIndex < 2);
-  MOZ_ASSERT(mFormat == gfx::SurfaceFormat::NV12 || aChannelIndex < 1);
+  MOZ_ASSERT(((mFormat == gfx::SurfaceFormat::NV12 ||
+               mFormat == gfx::SurfaceFormat::P010 ||
+               mFormat == gfx::SurfaceFormat::P016) &&
+              aChannelIndex < 2) ||
+             aChannelIndex < 1);
 
   if (aChannelIndex == 0) {
     return mSize;
   } else {
     // The CbCr channel size is a half of Y channel size in NV12 format.
     return mSize / 2;
   }
 }