Bug 1866020 - Override buggy colorspace conversion on Pixel devices. r=gw,padenot,geckoview-reviewers,owlish

Pixel 6, 7, and 8 devices running Android 14 are affected by a bug
where video frames with SMPTE 432 color primaries are rendered
incorrectly when sampled from an external texture in GLES. To work
around this, we force these frames to be converted to RGB using BT709
colorspace instead. While this won't look exactly right, it is much
better than the current situation.

When we detect that a frame is decoded with that color space on an
affected device, we set a "ForceBT709" flag which gets passed through
to webrender as a new ImageBufferKind. Rendering this ImageBufferKind
is handled via a new shader feature TEXTURE_EXTERNAL_BT709, which
works much like the existing TEXTURE_EXTERNAL feature, but
additionally uses the EXT_YUV_TARGET extension to override the
colorspace transformation.

This approach could be extended in the future to handle additional
colorspace transformations, but for now only handles the one required
to workaround this particular driver bug.

Differential Revision: https://phabricator.services.mozilla.com/D195800
This commit is contained in:
Jamie Nicol 2023-12-14 10:45:08 +00:00
Родитель 61791160ef
Коммит d20809a078
18 изменённых файлов: 120 добавлений и 33 удалений

Просмотреть файл

@ -67,6 +67,17 @@ class RenderOrReleaseOutput {
java::Sample::GlobalRef mSample; java::Sample::GlobalRef mSample;
}; };
static bool areSmpte432ColorPrimariesBuggy() {
if (jni::GetAPIVersion() >= 34) {
const auto socManufacturer =
java::sdk::Build::SOC_MANUFACTURER()->ToString();
if (socManufacturer.EqualsASCII("Google")) {
return true;
}
}
return false;
}
class RemoteVideoDecoder final : public RemoteDataDecoder { class RemoteVideoDecoder final : public RemoteDataDecoder {
public: public:
// Render the output to the surface when the frame is sent // Render the output to the surface when the frame is sent
@ -402,9 +413,16 @@ class RemoteVideoDecoder final : public RemoteDataDecoder {
} }
if (ok && (size > 0 || presentationTimeUs >= 0)) { if (ok && (size > 0 || presentationTimeUs >= 0)) {
// On certain devices SMPTE 432 color primaries are rendered incorrectly,
// so we force BT709 to be used instead. The magic number 10 comes from
// libstagefright's kColorStandardDCI_P3.
static bool isSmpte432Buggy = areSmpte432ColorPrimariesBuggy();
bool forceBT709ColorSpace = isSmpte432Buggy && mColorSpace == Some(10);
RefPtr<layers::Image> img = new layers::SurfaceTextureImage( RefPtr<layers::Image> img = new layers::SurfaceTextureImage(
mSurfaceHandle, inputInfo.mImageSize, false /* NOT continuous */, mSurfaceHandle, inputInfo.mImageSize, false /* NOT continuous */,
gl::OriginPos::BottomLeft, mConfig.HasAlpha(), mTransformOverride); gl::OriginPos::BottomLeft, mConfig.HasAlpha(), forceBT709ColorSpace,
mTransformOverride);
img->AsSurfaceTextureImage()->RegisterSetCurrentCallback( img->AsSurfaceTextureImage()->RegisterSetCurrentCallback(
std::move(releaseSample)); std::move(releaseSample));

Просмотреть файл

@ -254,7 +254,8 @@ Maybe<layers::SurfaceDescriptor>
SharedSurface_SurfaceTexture::ToSurfaceDescriptor() { SharedSurface_SurfaceTexture::ToSurfaceDescriptor() {
return Some(layers::SurfaceTextureDescriptor( return Some(layers::SurfaceTextureDescriptor(
mSurface->GetHandle(), mDesc.size, gfx::SurfaceFormat::R8G8B8A8, mSurface->GetHandle(), mDesc.size, gfx::SurfaceFormat::R8G8B8A8,
false /* NOT continuous */, Nothing() /* Do not override transform */)); false /* Do NOT override colorspace */, false /* NOT continuous */,
Nothing() /* Do not override transform */));
} }
SurfaceFactory_SurfaceTexture::SurfaceFactory_SurfaceTexture(GLContext& gl) SurfaceFactory_SurfaceTexture::SurfaceFactory_SurfaceTexture(GLContext& gl)

Просмотреть файл

@ -111,13 +111,14 @@ nsresult GLImage::BuildSurfaceDescriptorBuffer(
SurfaceTextureImage::SurfaceTextureImage( SurfaceTextureImage::SurfaceTextureImage(
AndroidSurfaceTextureHandle aHandle, const gfx::IntSize& aSize, AndroidSurfaceTextureHandle aHandle, const gfx::IntSize& aSize,
bool aContinuous, gl::OriginPos aOriginPos, bool aHasAlpha, bool aContinuous, gl::OriginPos aOriginPos, bool aHasAlpha,
Maybe<gfx::Matrix4x4> aTransformOverride) bool aForceBT709ColorSpace, Maybe<gfx::Matrix4x4> aTransformOverride)
: GLImage(ImageFormat::SURFACE_TEXTURE), : GLImage(ImageFormat::SURFACE_TEXTURE),
mHandle(aHandle), mHandle(aHandle),
mSize(aSize), mSize(aSize),
mContinuous(aContinuous), mContinuous(aContinuous),
mOriginPos(aOriginPos), mOriginPos(aOriginPos),
mHasAlpha(aHasAlpha), mHasAlpha(aHasAlpha),
mForceBT709ColorSpace(aForceBT709ColorSpace),
mTransformOverride(aTransformOverride) { mTransformOverride(aTransformOverride) {
MOZ_ASSERT(mHandle); MOZ_ASSERT(mHandle);
} }
@ -126,7 +127,7 @@ Maybe<SurfaceDescriptor> SurfaceTextureImage::GetDesc() {
SurfaceDescriptor sd = SurfaceTextureDescriptor( SurfaceDescriptor sd = SurfaceTextureDescriptor(
mHandle, mSize, mHandle, mSize,
mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8, mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8,
false /* NOT continuous */, mTransformOverride); mForceBT709ColorSpace, false /* NOT continuous */, mTransformOverride);
return Some(sd); return Some(sd);
} }
#endif #endif

Просмотреть файл

@ -54,6 +54,7 @@ class SurfaceTextureImage final : public GLImage {
SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle, SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
const gfx::IntSize& aSize, bool aContinuous, const gfx::IntSize& aSize, bool aContinuous,
gl::OriginPos aOriginPos, bool aHasAlpha, gl::OriginPos aOriginPos, bool aHasAlpha,
bool aForceBT709ColorSpace,
Maybe<gfx::Matrix4x4> aTransformOverride); Maybe<gfx::Matrix4x4> aTransformOverride);
gfx::IntSize GetSize() const override { return mSize; } gfx::IntSize GetSize() const override { return mSize; }
@ -61,6 +62,7 @@ class SurfaceTextureImage final : public GLImage {
bool GetContinuous() const { return mContinuous; } bool GetContinuous() const { return mContinuous; }
gl::OriginPos GetOriginPos() const { return mOriginPos; } gl::OriginPos GetOriginPos() const { return mOriginPos; }
bool GetHasAlpha() const { return mHasAlpha; } bool GetHasAlpha() const { return mHasAlpha; }
bool GetForceBT709ColorSpace() const { return mForceBT709ColorSpace; }
const Maybe<gfx::Matrix4x4>& GetTransformOverride() const { const Maybe<gfx::Matrix4x4>& GetTransformOverride() const {
return mTransformOverride; return mTransformOverride;
} }
@ -102,6 +104,7 @@ class SurfaceTextureImage final : public GLImage {
bool mContinuous; bool mContinuous;
gl::OriginPos mOriginPos; gl::OriginPos mOriginPos;
const bool mHasAlpha; const bool mHasAlpha;
const bool mForceBT709ColorSpace;
const Maybe<gfx::Matrix4x4> mTransformOverride; const Maybe<gfx::Matrix4x4> mTransformOverride;
UniquePtr<SetCurrentCallback> mSetCurrentCallback; UniquePtr<SetCurrentCallback> mSetCurrentCallback;
}; };

Просмотреть файл

@ -120,6 +120,7 @@ already_AddRefed<TextureClient> ImageClient::CreateTextureClientForImage(
texture = AndroidSurfaceTextureData::CreateTextureClient( texture = AndroidSurfaceTextureData::CreateTextureClient(
typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetHandle(), size, typedImage->GetContinuous(),
typedImage->GetOriginPos(), typedImage->GetHasAlpha(), typedImage->GetOriginPos(), typedImage->GetHasAlpha(),
typedImage->GetForceBT709ColorSpace(),
typedImage->GetTransformOverride(), typedImage->GetTransformOverride(),
aKnowsCompositor->GetTextureForwarder(), TextureFlags::DEFAULT); aKnowsCompositor->GetTextureForwarder(), TextureFlags::DEFAULT);
#endif #endif

Просмотреть файл

@ -88,6 +88,7 @@ namespace layers {
IntSize size; IntSize size;
SurfaceFormat format; SurfaceFormat format;
bool continuous; bool continuous;
bool forceBT709ColorSpace;
Matrix4x4? transformOverride; Matrix4x4? transformOverride;
}; };

Просмотреть файл

@ -38,7 +38,7 @@ class CompositableForwarder;
already_AddRefed<TextureClient> AndroidSurfaceTextureData::CreateTextureClient( already_AddRefed<TextureClient> AndroidSurfaceTextureData::CreateTextureClient(
AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous, AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous,
gl::OriginPos aOriginPos, bool aHasAlpha, gl::OriginPos aOriginPos, bool aHasAlpha, bool aForceBT709ColorSpace,
Maybe<gfx::Matrix4x4> aTransformOverride, LayersIPCChannel* aAllocator, Maybe<gfx::Matrix4x4> aTransformOverride, LayersIPCChannel* aAllocator,
TextureFlags aFlags) { TextureFlags aFlags) {
if (aOriginPos == gl::OriginPos::BottomLeft) { if (aOriginPos == gl::OriginPos::BottomLeft) {
@ -47,17 +47,19 @@ already_AddRefed<TextureClient> AndroidSurfaceTextureData::CreateTextureClient(
return TextureClient::CreateWithData( return TextureClient::CreateWithData(
new AndroidSurfaceTextureData(aHandle, aSize, aContinuous, aHasAlpha, new AndroidSurfaceTextureData(aHandle, aSize, aContinuous, aHasAlpha,
aTransformOverride), aForceBT709ColorSpace, aTransformOverride),
aFlags, aAllocator); aFlags, aAllocator);
} }
AndroidSurfaceTextureData::AndroidSurfaceTextureData( AndroidSurfaceTextureData::AndroidSurfaceTextureData(
AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous, AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous,
bool aHasAlpha, Maybe<gfx::Matrix4x4> aTransformOverride) bool aHasAlpha, bool aForceBT709ColorSpace,
Maybe<gfx::Matrix4x4> aTransformOverride)
: mHandle(aHandle), : mHandle(aHandle),
mSize(aSize), mSize(aSize),
mContinuous(aContinuous), mContinuous(aContinuous),
mHasAlpha(aHasAlpha), mHasAlpha(aHasAlpha),
mForceBT709ColorSpace(aForceBT709ColorSpace),
mTransformOverride(aTransformOverride) { mTransformOverride(aTransformOverride) {
MOZ_ASSERT(mHandle); MOZ_ASSERT(mHandle);
} }
@ -76,7 +78,7 @@ bool AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
aOutDescriptor = SurfaceTextureDescriptor( aOutDescriptor = SurfaceTextureDescriptor(
mHandle, mSize, mHandle, mSize,
mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8, mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::R8G8B8X8,
mContinuous, mTransformOverride); mContinuous, mForceBT709ColorSpace, mTransformOverride);
return true; return true;
} }
@ -159,6 +161,7 @@ bool AndroidNativeWindowTextureData::Serialize(
SurfaceDescriptor& aOutDescriptor) { SurfaceDescriptor& aOutDescriptor) {
aOutDescriptor = SurfaceTextureDescriptor( aOutDescriptor = SurfaceTextureDescriptor(
mSurface->GetHandle(), mSize, mFormat, false /* not continuous */, mSurface->GetHandle(), mSize, mFormat, false /* not continuous */,
false /* do not override colorspace */,
Some(gfx::Matrix4x4()) /* always use identity transform */); Some(gfx::Matrix4x4()) /* always use identity transform */);
return true; return true;
} }

Просмотреть файл

@ -41,7 +41,7 @@ class AndroidSurfaceTextureData : public TextureData {
public: public:
static already_AddRefed<TextureClient> CreateTextureClient( static already_AddRefed<TextureClient> CreateTextureClient(
AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous, AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous,
gl::OriginPos aOriginPos, bool aHasAlpha, gl::OriginPos aOriginPos, bool aHasAlpha, bool aForceBT709ColorSpace,
Maybe<gfx::Matrix4x4> aTransformOverride, LayersIPCChannel* aAllocator, Maybe<gfx::Matrix4x4> aTransformOverride, LayersIPCChannel* aAllocator,
TextureFlags aFlags); TextureFlags aFlags);
@ -62,13 +62,14 @@ class AndroidSurfaceTextureData : public TextureData {
protected: protected:
AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle, AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize, bool aContinuous, gfx::IntSize aSize, bool aContinuous,
bool aHasAlpha, bool aHasAlpha, bool aForceBT709ColorSpace,
Maybe<gfx::Matrix4x4> aTransformOverride); Maybe<gfx::Matrix4x4> aTransformOverride);
const AndroidSurfaceTextureHandle mHandle; const AndroidSurfaceTextureHandle mHandle;
const gfx::IntSize mSize; const gfx::IntSize mSize;
const bool mContinuous; const bool mContinuous;
const bool mHasAlpha; const bool mHasAlpha;
const bool mForceBT709ColorSpace;
const Maybe<gfx::Matrix4x4> mTransformOverride; const Maybe<gfx::Matrix4x4> mTransformOverride;
}; };

Просмотреть файл

@ -67,9 +67,9 @@ already_AddRefed<TextureHost> CreateTextureHostOGL(
java::GeckoSurfaceTexture::LocalRef surfaceTexture = java::GeckoSurfaceTexture::LocalRef surfaceTexture =
java::GeckoSurfaceTexture::Lookup(desc.handle()); java::GeckoSurfaceTexture::Lookup(desc.handle());
result = new SurfaceTextureHost(aFlags, surfaceTexture, desc.size(), result = new SurfaceTextureHost(
desc.format(), desc.continuous(), aFlags, surfaceTexture, desc.size(), desc.format(), desc.continuous(),
desc.transformOverride()); desc.forceBT709ColorSpace(), desc.transformOverride());
break; break;
} }
case SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer: { case SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer: {
@ -495,12 +495,13 @@ void SurfaceTextureSource::DeallocateDeviceData() { mSurfTex = nullptr; }
SurfaceTextureHost::SurfaceTextureHost( SurfaceTextureHost::SurfaceTextureHost(
TextureFlags aFlags, mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex, TextureFlags aFlags, mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat, bool aContinuousUpdate, gfx::IntSize aSize, gfx::SurfaceFormat aFormat, bool aContinuousUpdate,
Maybe<Matrix4x4> aTransformOverride) bool aForceBT709ColorSpace, Maybe<Matrix4x4> aTransformOverride)
: TextureHost(TextureHostType::AndroidSurfaceTexture, aFlags), : TextureHost(TextureHostType::AndroidSurfaceTexture, aFlags),
mSurfTex(aSurfTex), mSurfTex(aSurfTex),
mSize(aSize), mSize(aSize),
mFormat(aFormat), mFormat(aFormat),
mContinuousUpdate(aContinuousUpdate), mContinuousUpdate(aContinuousUpdate),
mForceBT709ColorSpace(aForceBT709ColorSpace),
mTransformOverride(aTransformOverride) { mTransformOverride(aTransformOverride) {
if (!mSurfTex) { if (!mSurfTex) {
return; return;
@ -560,11 +561,15 @@ void SurfaceTextureHost::PushResourceUpdates(
TextureHost::NativeTexturePolicy policy = TextureHost::NativeTexturePolicy policy =
TextureHost::BackendNativeTexturePolicy(aResources.GetBackendType(), TextureHost::BackendNativeTexturePolicy(aResources.GetBackendType(),
GetSize()); GetSize());
auto imageType = policy == TextureHost::NativeTexturePolicy::REQUIRE auto imageType = wr::ExternalImageType::TextureHandle(
? wr::ExternalImageType::TextureHandle( wr::ImageBufferKind::TextureExternal);
wr::ImageBufferKind::TextureRect) if (policy == TextureHost::NativeTexturePolicy::REQUIRE) {
: wr::ExternalImageType::TextureHandle( imageType =
wr::ImageBufferKind::TextureExternal); wr::ExternalImageType::TextureHandle(wr::ImageBufferKind::TextureRect);
} else if (mForceBT709ColorSpace) {
imageType = wr::ExternalImageType::TextureHandle(
wr::ImageBufferKind::TextureExternalBT709);
}
switch (GetFormat()) { switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8X8:

Просмотреть файл

@ -387,7 +387,7 @@ class SurfaceTextureHost : public TextureHost {
SurfaceTextureHost(TextureFlags aFlags, SurfaceTextureHost(TextureFlags aFlags,
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex, mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
bool aContinuousUpdate, bool aContinuousUpdate, bool aForceBT709ColorSpace,
Maybe<gfx::Matrix4x4> aTransformOverride); Maybe<gfx::Matrix4x4> aTransformOverride);
virtual ~SurfaceTextureHost(); virtual ~SurfaceTextureHost();
@ -438,6 +438,7 @@ class SurfaceTextureHost : public TextureHost {
const gfx::IntSize mSize; const gfx::IntSize mSize;
const gfx::SurfaceFormat mFormat; const gfx::SurfaceFormat mFormat;
bool mContinuousUpdate; bool mContinuousUpdate;
const bool mForceBT709ColorSpace;
const Maybe<gfx::Matrix4x4> mTransformOverride; const Maybe<gfx::Matrix4x4> mTransformOverride;
RefPtr<CompositorOGL> mCompositor; RefPtr<CompositorOGL> mCompositor;
RefPtr<SurfaceTextureSource> mTextureSource; RefPtr<SurfaceTextureSource> mTextureSource;

Просмотреть файл

@ -150,6 +150,8 @@ fn write_optimized_shaders(
) { ) {
flags.remove(ShaderFeatureFlags::TEXTURE_EXTERNAL_ESSL1); flags.remove(ShaderFeatureFlags::TEXTURE_EXTERNAL_ESSL1);
} }
// The optimizer cannot handle the required EXT_YUV_target extension
flags.remove(ShaderFeatureFlags::TEXTURE_EXTERNAL_BT709);
flags.remove(ShaderFeatureFlags::DITHERING); flags.remove(ShaderFeatureFlags::DITHERING);
for (shader_name, configs) in get_shader_features(flags) { for (shader_name, configs) in get_shader_features(flags) {

Просмотреть файл

@ -15,6 +15,10 @@
#extension GL_OES_EGL_image_external : require #extension GL_OES_EGL_image_external : require
#endif #endif
#ifdef WR_FEATURE_TEXTURE_EXTERNAL_BT709
#extension GL_EXT_YUV_target : require
#endif
#ifdef WR_FEATURE_ADVANCED_BLEND #ifdef WR_FEATURE_ADVANCED_BLEND
#extension GL_KHR_blend_equation_advanced : require #extension GL_KHR_blend_equation_advanced : require
#endif #endif
@ -31,6 +35,9 @@
#if defined(WR_FEATURE_TEXTURE_EXTERNAL_ESSL1) #if defined(WR_FEATURE_TEXTURE_EXTERNAL_ESSL1)
#define TEX_SAMPLE(sampler, tex_coord) texture2D(sampler, tex_coord.xy) #define TEX_SAMPLE(sampler, tex_coord) texture2D(sampler, tex_coord.xy)
#elif defined(WR_FEATURE_TEXTURE_EXTERNAL_BT709)
// Force conversion from yuv to rgb using BT709 colorspace
#define TEX_SAMPLE(sampler, tex_coord) vec4(yuv_2_rgb(texture(sampler, tex_coord.xy).xyz, itu_709), 1.0)
#else #else
#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy) #define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy)
#endif #endif
@ -207,6 +214,10 @@ uniform sampler2DRect sColor2;
uniform samplerExternalOES sColor0; uniform samplerExternalOES sColor0;
uniform samplerExternalOES sColor1; uniform samplerExternalOES sColor1;
uniform samplerExternalOES sColor2; uniform samplerExternalOES sColor2;
#elif defined(WR_FEATURE_TEXTURE_EXTERNAL_BT709)
uniform __samplerExternal2DY2YEXT sColor0;
uniform __samplerExternal2DY2YEXT sColor1;
uniform __samplerExternal2DY2YEXT sColor2;
#endif #endif
#ifdef WR_FEATURE_DITHERING #ifdef WR_FEATURE_DITHERING

Просмотреть файл

@ -155,6 +155,7 @@ pub fn get_gl_target(target: ImageBufferKind) -> gl::GLuint {
ImageBufferKind::Texture2D => gl::TEXTURE_2D, ImageBufferKind::Texture2D => gl::TEXTURE_2D,
ImageBufferKind::TextureRect => gl::TEXTURE_RECTANGLE, ImageBufferKind::TextureRect => gl::TEXTURE_RECTANGLE,
ImageBufferKind::TextureExternal => gl::TEXTURE_EXTERNAL_OES, ImageBufferKind::TextureExternal => gl::TEXTURE_EXTERNAL_OES,
ImageBufferKind::TextureExternalBT709 => gl::TEXTURE_EXTERNAL_OES,
} }
} }

Просмотреть файл

@ -39,23 +39,27 @@ fn get_feature_string(kind: ImageBufferKind, texture_external_version: TextureEx
(ImageBufferKind::TextureRect, _) => "TEXTURE_RECT", (ImageBufferKind::TextureRect, _) => "TEXTURE_RECT",
(ImageBufferKind::TextureExternal, TextureExternalVersion::ESSL3) => "TEXTURE_EXTERNAL", (ImageBufferKind::TextureExternal, TextureExternalVersion::ESSL3) => "TEXTURE_EXTERNAL",
(ImageBufferKind::TextureExternal, TextureExternalVersion::ESSL1) => "TEXTURE_EXTERNAL_ESSL1", (ImageBufferKind::TextureExternal, TextureExternalVersion::ESSL1) => "TEXTURE_EXTERNAL_ESSL1",
(ImageBufferKind::TextureExternalBT709, _) => "TEXTURE_EXTERNAL_BT709",
} }
} }
fn has_platform_support(kind: ImageBufferKind, gl_type: &GlType) -> bool { fn has_platform_support(kind: ImageBufferKind, device: &Device) -> bool {
match (kind, gl_type) { match (kind, device.gl().get_type()) {
(ImageBufferKind::Texture2D, _) => true, (ImageBufferKind::Texture2D, _) => true,
(ImageBufferKind::TextureRect, &GlType::Gles) => false, (ImageBufferKind::TextureRect, GlType::Gles) => false,
(ImageBufferKind::TextureRect, &GlType::Gl) => true, (ImageBufferKind::TextureRect, GlType::Gl) => true,
(ImageBufferKind::TextureExternal, &GlType::Gles) => true, (ImageBufferKind::TextureExternal, GlType::Gles) => true,
(ImageBufferKind::TextureExternal, &GlType::Gl) => false, (ImageBufferKind::TextureExternal, GlType::Gl) => false,
(ImageBufferKind::TextureExternalBT709, GlType::Gles) => device.supports_extension("GL_EXT_YUV_target"),
(ImageBufferKind::TextureExternalBT709, GlType::Gl) => false,
} }
} }
pub const IMAGE_BUFFER_KINDS: [ImageBufferKind; 3] = [ pub const IMAGE_BUFFER_KINDS: [ImageBufferKind; 4] = [
ImageBufferKind::Texture2D, ImageBufferKind::Texture2D,
ImageBufferKind::TextureRect, ImageBufferKind::TextureRect,
ImageBufferKind::TextureExternal, ImageBufferKind::TextureExternal,
ImageBufferKind::TextureExternalBT709,
]; ];
const ADVANCED_BLEND_FEATURE: &str = "ADVANCED_BLEND"; const ADVANCED_BLEND_FEATURE: &str = "ADVANCED_BLEND";
@ -830,7 +834,7 @@ impl Shaders {
cs_scale.push(None); cs_scale.push(None);
} }
for image_buffer_kind in &IMAGE_BUFFER_KINDS { for image_buffer_kind in &IMAGE_BUFFER_KINDS {
if has_platform_support(*image_buffer_kind, &gl_type) { if has_platform_support(*image_buffer_kind, device) {
let feature_string = get_feature_string( let feature_string = get_feature_string(
*image_buffer_kind, *image_buffer_kind,
texture_external_version, texture_external_version,
@ -933,7 +937,7 @@ impl Shaders {
brush_fast_image.push(None); brush_fast_image.push(None);
} }
for buffer_kind in 0 .. IMAGE_BUFFER_KINDS.len() { for buffer_kind in 0 .. IMAGE_BUFFER_KINDS.len() {
if !has_platform_support(IMAGE_BUFFER_KINDS[buffer_kind], &gl_type) if !has_platform_support(IMAGE_BUFFER_KINDS[buffer_kind], device)
// Brush shaders are not ESSL1 compatible // Brush shaders are not ESSL1 compatible
|| (IMAGE_BUFFER_KINDS[buffer_kind] == ImageBufferKind::TextureExternal || (IMAGE_BUFFER_KINDS[buffer_kind] == ImageBufferKind::TextureExternal
&& texture_external_version == TextureExternalVersion::ESSL1) && texture_external_version == TextureExternalVersion::ESSL1)
@ -988,7 +992,7 @@ impl Shaders {
brush_yuv_image.push(None); brush_yuv_image.push(None);
} }
for image_buffer_kind in &IMAGE_BUFFER_KINDS { for image_buffer_kind in &IMAGE_BUFFER_KINDS {
if has_platform_support(*image_buffer_kind, &gl_type) { if has_platform_support(*image_buffer_kind, device) {
yuv_features.push("YUV"); yuv_features.push("YUV");
fast_path_features.push("FAST_PATH"); fast_path_features.push("FAST_PATH");
@ -1361,7 +1365,7 @@ impl CompositorShaders {
} }
for image_buffer_kind in &IMAGE_BUFFER_KINDS { for image_buffer_kind in &IMAGE_BUFFER_KINDS {
if !has_platform_support(*image_buffer_kind, &gl_type) { if !has_platform_support(*image_buffer_kind, device) {
continue; continue;
} }
@ -1486,7 +1490,10 @@ fn get_shader_feature_flags(gl_type: GlType, texture_external_version: TextureEx
GlType::Gl => ShaderFeatureFlags::GL, GlType::Gl => ShaderFeatureFlags::GL,
GlType::Gles => { GlType::Gles => {
let texture_external_flag = match texture_external_version { let texture_external_flag = match texture_external_version {
TextureExternalVersion::ESSL3 => ShaderFeatureFlags::TEXTURE_EXTERNAL, TextureExternalVersion::ESSL3 => {
ShaderFeatureFlags::TEXTURE_EXTERNAL
| ShaderFeatureFlags::TEXTURE_EXTERNAL_BT709
}
TextureExternalVersion::ESSL1 => ShaderFeatureFlags::TEXTURE_EXTERNAL_ESSL1, TextureExternalVersion::ESSL1 => ShaderFeatureFlags::TEXTURE_EXTERNAL_ESSL1,
}; };
ShaderFeatureFlags::GLES | texture_external_flag ShaderFeatureFlags::GLES | texture_external_flag

Просмотреть файл

@ -117,6 +117,10 @@ pub enum ImageBufferKind {
/// understand, particularly YUV. See /// understand, particularly YUV. See
/// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt /// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
TextureExternal = 2, TextureExternal = 2,
/// External texture which is forced to be converted from YUV to RGB using BT709 colorspace.
/// This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, using the EXT_YUV_TARGET extension.
/// https://registry.khronos.org/OpenGL/extensions/EXT/EXT_YUV_target.txt
TextureExternalBT709 = 3,
} }
/// Storage format identifier for externally-managed images. /// Storage format identifier for externally-managed images.

Просмотреть файл

@ -15,7 +15,8 @@ bitflags! {
const DITHERING = 1 << 10; const DITHERING = 1 << 10;
const TEXTURE_EXTERNAL = 1 << 11; const TEXTURE_EXTERNAL = 1 << 11;
const TEXTURE_EXTERNAL_ESSL1 = 1 << 12; const TEXTURE_EXTERNAL_ESSL1 = 1 << 12;
const DEBUG = 1 << 13; const TEXTURE_EXTERNAL_BT709 = 1 << 13;
const DEBUG = 1 << 14;
} }
} }
@ -138,6 +139,9 @@ pub fn get_shader_features(flags: ShaderFeatureFlags) -> ShaderFeatures {
if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL) { if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL) {
texture_types.push("TEXTURE_EXTERNAL"); texture_types.push("TEXTURE_EXTERNAL");
} }
if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL_BT709) {
texture_types.push("TEXTURE_EXTERNAL_BT709");
}
let mut image_features: Vec<String> = Vec::new(); let mut image_features: Vec<String> = Vec::new();
for texture_type in &texture_types { for texture_type in &texture_types {
let mut fast = FeatureList::new(); let mut fast = FeatureList::new();

Просмотреть файл

@ -126,6 +126,8 @@ pub fn test_shaders() {
} }
// glsl-lang crate fails to parse advanced blend shaders // glsl-lang crate fails to parse advanced blend shaders
flags.remove(ShaderFeatureFlags::ADVANCED_BLEND_EQUATION); flags.remove(ShaderFeatureFlags::ADVANCED_BLEND_EQUATION);
// glsl-lang crate fails to parse texture external BT709 shaders
flags.remove(ShaderFeatureFlags::TEXTURE_EXTERNAL_BT709);
for (shader, configs) in get_shader_features(flags) { for (shader, configs) in get_shader_features(flags) {
for config in configs { for config in configs {

Просмотреть файл

@ -5,6 +5,7 @@
package org.mozilla.gecko.media; package org.mozilla.gecko.media;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
@ -26,6 +27,8 @@ import java.nio.ByteBuffer;
* <li>{@link MediaFormat#KEY_I_FRAME_INTERVAL} * <li>{@link MediaFormat#KEY_I_FRAME_INTERVAL}
* <li>{@link MediaFormat#KEY_STRIDE} * <li>{@link MediaFormat#KEY_STRIDE}
* <li>{@link MediaFormat#KEY_SLICE_HEIGHT} * <li>{@link MediaFormat#KEY_SLICE_HEIGHT}
* <li>{@link MediaFormat#KEY_COLOR_RANGE
* <li>{@link MediaFormat#KEY_COLOR_STANDARD}
* <li>"csd-0" * <li>"csd-0"
* <li>"csd-1" * <li>"csd-1"
* </ul> * </ul>
@ -118,6 +121,15 @@ public final class FormatParam implements Parcelable {
if (bundle.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) { if (bundle.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) {
mFormat.setInteger(MediaFormat.KEY_SLICE_HEIGHT, bundle.getInt(MediaFormat.KEY_SLICE_HEIGHT)); mFormat.setInteger(MediaFormat.KEY_SLICE_HEIGHT, bundle.getInt(MediaFormat.KEY_SLICE_HEIGHT));
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (bundle.containsKey(MediaFormat.KEY_COLOR_RANGE)) {
mFormat.setInteger(MediaFormat.KEY_COLOR_RANGE, bundle.getInt(MediaFormat.KEY_COLOR_RANGE));
}
if (bundle.containsKey(MediaFormat.KEY_COLOR_STANDARD)) {
mFormat.setInteger(
MediaFormat.KEY_COLOR_STANDARD, bundle.getInt(MediaFormat.KEY_COLOR_STANDARD));
}
}
} }
@Override @Override
@ -173,6 +185,15 @@ public final class FormatParam implements Parcelable {
if (mFormat.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) { if (mFormat.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) {
bundle.putInt(MediaFormat.KEY_SLICE_HEIGHT, mFormat.getInteger(MediaFormat.KEY_SLICE_HEIGHT)); bundle.putInt(MediaFormat.KEY_SLICE_HEIGHT, mFormat.getInteger(MediaFormat.KEY_SLICE_HEIGHT));
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (mFormat.containsKey(MediaFormat.KEY_COLOR_RANGE)) {
bundle.putInt(MediaFormat.KEY_COLOR_RANGE, mFormat.getInteger(MediaFormat.KEY_COLOR_RANGE));
}
if (mFormat.containsKey(MediaFormat.KEY_COLOR_STANDARD)) {
bundle.putInt(
MediaFormat.KEY_COLOR_STANDARD, mFormat.getInteger(MediaFormat.KEY_COLOR_STANDARD));
}
}
return bundle; return bundle;
} }
} }