diff --git a/gfx/2d/MacIOSurface.cpp b/gfx/2d/MacIOSurface.cpp index 59ecee8a48b6..e8d688fb1f2e 100644 --- a/gfx/2d/MacIOSurface.cpp +++ b/gfx/2d/MacIOSurface.cpp @@ -404,10 +404,21 @@ already_AddRefed MacIOSurface::GetAsDrawTargetLocked( } SurfaceFormat MacIOSurface::GetFormat() const { +#if !defined(MAC_OS_VERSION_10_13) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_10_13 + enum : OSType { + kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange = 'x420', + kCVPixelFormatType_420YpCbCr10BiPlanarFullRange = 'xf20', + }; +#endif + switch (GetPixelFormat()) { case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: return SurfaceFormat::NV12; + case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: + case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: + return SurfaceFormat::P010; case kCVPixelFormatType_422YpCbCr8_yuvs: case kCVPixelFormatType_422YpCbCr8FullRange: return SurfaceFormat::YUV422; @@ -439,6 +450,14 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx, GLenum target, CGLError MacIOSurface::CGLTexImageIOSurface2D( mozilla::gl::GLContext* aGL, CGLContextObj ctx, size_t plane, mozilla::gfx::SurfaceFormat* aOutReadFormat) { +#if !defined(MAC_OS_VERSION_10_13) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_10_13 + enum : OSType { + kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange = 'x420', + kCVPixelFormatType_420YpCbCr10BiPlanarFullRange = 'xf20', + }; +#endif + MOZ_ASSERT(plane >= 0); bool isCompatibilityProfile = aGL->IsCompatibilityProfile(); OSType pixelFormat = GetPixelFormat(); @@ -465,6 +484,25 @@ CGLError MacIOSurface::CGLTexImageIOSurface2D( if (aOutReadFormat) { *aOutReadFormat = mozilla::gfx::SurfaceFormat::NV12; } + } else if (pixelFormat == kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange || + pixelFormat == kCVPixelFormatType_420YpCbCr10BiPlanarFullRange) { + MOZ_ASSERT(GetPlaneCount() == 2); + MOZ_ASSERT(plane < 2); + + // The LOCAL_GL_LUMINANCE and LOCAL_GL_LUMINANCE_ALPHA are the deprecated + // format. So, use LOCAL_GL_RED and LOCAL_GL_RB if we use core profile. + // https://www.khronos.org/opengl/wiki/Image_Format#Legacy_Image_Formats + if (plane == 0) { + internalFormat = format = + (isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE) : (LOCAL_GL_RED); + } else { + internalFormat = format = + (isCompatibilityProfile) ? (LOCAL_GL_LUMINANCE_ALPHA) : (LOCAL_GL_RG); + } + type = LOCAL_GL_UNSIGNED_SHORT; + if (aOutReadFormat) { + *aOutReadFormat = mozilla::gfx::SurfaceFormat::P010; + } } else if (pixelFormat == kCVPixelFormatType_422YpCbCr8_yuvs || pixelFormat == kCVPixelFormatType_422YpCbCr8FullRange) { MOZ_ASSERT(plane == 0); diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index fe0a61827503..023565e800d4 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -1052,6 +1052,11 @@ void DXGITextureHostD3D11::PushDisplayItems( case gfx::SurfaceFormat::P010: case gfx::SurfaceFormat::P016: case gfx::SurfaceFormat::NV12: { + // DXGI_FORMAT_P010 stores its 10 bit value in the most significant bits + // of each 16 bit word with the unused lower bits cleared to zero so that + // it may be handled as if it was DXGI_FORMAT_P016. This is approximately + // perceptually correct. However, due to rounding error, the precise + // quantized value after sampling may be off by 1. MOZ_ASSERT(aImageKeys.length() == 2); aBuilder.PushNV12Image( aBounds, aClip, true, aImageKeys[0], aImageKeys[1], diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp index a2c492dcb16b..dede69c4dcc0 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp @@ -92,7 +92,8 @@ uint32_t MacIOSurfaceTextureHostOGL::NumSubTextures() { case gfx::SurfaceFormat::YUV422: { return 1; } - case gfx::SurfaceFormat::NV12: { + case gfx::SurfaceFormat::NV12: + case gfx::SurfaceFormat::P010: { return 2; } default: { @@ -153,6 +154,21 @@ void MacIOSurfaceTextureHostOGL::PushResourceUpdates( (aResources.*method)(aImageKeys[1], descriptor1, aExtID, imageType, 1); break; } + case gfx::SurfaceFormat::P010: { + MOZ_ASSERT(aImageKeys.length() == 2); + MOZ_ASSERT(mSurface->GetPlaneCount() == 2); + wr::ImageDescriptor descriptor0( + gfx::IntSize(mSurface->GetDevicePixelWidth(0), + mSurface->GetDevicePixelHeight(0)), + gfx::SurfaceFormat::A16); + wr::ImageDescriptor descriptor1( + gfx::IntSize(mSurface->GetDevicePixelWidth(1), + mSurface->GetDevicePixelHeight(1)), + gfx::SurfaceFormat::R16G16); + (aResources.*method)(aImageKeys[0], descriptor0, aExtID, imageType, 0); + (aResources.*method)(aImageKeys[1], descriptor1, aExtID, imageType, 1); + break; + } default: { MOZ_ASSERT_UNREACHABLE("unexpected to be called"); } @@ -191,14 +207,15 @@ void MacIOSurfaceTextureHostOGL::PushDisplayItems( /* aSupportsExternalCompositing */ true); break; } - case gfx::SurfaceFormat::NV12: { + case gfx::SurfaceFormat::NV12: + case gfx::SurfaceFormat::P010: { 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(GetYUVColorSpace()), + GetFormat() == gfx::SurfaceFormat::NV12 ? wr::ColorDepth::Color8 + : wr::ColorDepth::Color10, + wr::ToWrYuvColorSpace(GetYUVColorSpace()), wr::ToWrColorRange(GetColorRange()), aFilter, preferCompositorSurface, /* aSupportsExternalCompositing */ true); break; diff --git a/gfx/wr/webrender_api/src/image.rs b/gfx/wr/webrender_api/src/image.rs index e03a5d88ae18..8d86ef1d7b88 100644 --- a/gfx/wr/webrender_api/src/image.rs +++ b/gfx/wr/webrender_api/src/image.rs @@ -160,7 +160,7 @@ pub enum ImageFormat { /// Two-channels, byte storage. Similar to `R8`, this just means /// "two channels" rather than "red and green". RG8 = 5, - /// Two-channels, byte storage. Similar to `R16`, this just means + /// Two-channels, short storage. Similar to `R16`, this just means /// "two channels" rather than "red and green". RG16 = 6,