Skip to content

Commit

Permalink
SkiaRenderer: Use bit depth in YUV to RGB conversion
Browse files Browse the repository at this point in the history
In VideoResourceUpdater::CreateForHardwarePlanes, set the
bit depth of the video.

Include bit depth in ColorConversionSkFilterCache parameters.

Apply the workaround that treats 16-bit content as 10-bit to more
places in gfx::ColorSpace.

Bug: 1348566, 1381100
Change-Id: I8383c01eadad2a41547722752d0734b7950e67af
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4002050
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Commit-Queue: ccameron chromium <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1067342}
  • Loading branch information
ccameron-chromium authored and Chromium LUCI CQ committed Nov 4, 2022
1 parent 40f712f commit 3804dfb
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 20 deletions.
10 changes: 6 additions & 4 deletions components/viz/service/display/skia_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2449,7 +2449,7 @@ void SkiaRenderer::DrawTextureQuad(const TextureDrawQuad* quad,
DCHECK(SkColorSpace::Equals(image->colorSpace(),
CurrentRenderPassSkColorSpace().get()));
sk_sp<SkColorFilter> color_filter = GetColorSpaceConversionFilter(
src_color_space, quad->hdr_metadata, dst_color_space);
src_color_space, absl::nullopt, quad->hdr_metadata, dst_color_space);
paint.setColorFilter(color_filter->makeComposed(paint.refColorFilter()));
}

Expand Down Expand Up @@ -2603,8 +2603,8 @@ void SkiaRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad,
quad->ya_tex_coord_rect(), gfx::RectF(quad->rect), params->visible_rect);

sk_sp<SkColorFilter> color_filter = GetColorSpaceConversionFilter(
src_color_space, quad->hdr_metadata, dst_color_space,
quad->resource_offset, quad->resource_multiplier);
src_color_space, quad->bits_per_channel, quad->hdr_metadata,
dst_color_space, quad->resource_offset, quad->resource_multiplier);

auto content_color_filter = GetContentColorFilter();
if (content_color_filter)
Expand Down Expand Up @@ -2768,12 +2768,14 @@ void SkiaRenderer::ScheduleOverlays() {

sk_sp<SkColorFilter> SkiaRenderer::GetColorSpaceConversionFilter(
const gfx::ColorSpace& src,
absl::optional<uint32_t> src_bit_depth,
absl::optional<gfx::HDRMetadata> src_hdr_metadata,
const gfx::ColorSpace& dst,
float resource_offset,
float resource_multiplier) {
return color_filter_cache_.Get(
src, dst, resource_offset, resource_multiplier, src_hdr_metadata,
src, dst, resource_offset, resource_multiplier, src_bit_depth,
src_hdr_metadata,
current_frame()->display_color_spaces.GetSDRMaxLuminanceNits(),
current_frame()->display_color_spaces.GetHDRMaxLuminanceRelative());
}
Expand Down
1 change: 1 addition & 0 deletions components/viz/service/display/skia_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
// quads. The default values perform no adjustment.
sk_sp<SkColorFilter> GetColorSpaceConversionFilter(
const gfx::ColorSpace& src,
absl::optional<uint32_t> src_bit_depth,
absl::optional<gfx::HDRMetadata> src_hdr_metadata,
const gfx::ColorSpace& dst,
float resource_offset = 0.0f,
Expand Down
1 change: 1 addition & 0 deletions media/renderers/video_resource_updater.cc
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
gfx::BufferFormat buffer_formats[VideoFrame::kMaxPlanes];
external_resources.type = ExternalResourceTypeForHardwarePlanes(
*video_frame, target, buffer_formats, use_stream_video_draw_quad_);
external_resources.bits_per_channel = video_frame->BitDepth();

if (external_resources.type == VideoFrameResourceType::NONE) {
DLOG(ERROR) << "Unsupported Texture format"
Expand Down
23 changes: 16 additions & 7 deletions ui/gfx/color_conversion_sk_filter_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ ColorConversionSkFilterCache::~ColorConversionSkFilterCache() = default;

bool ColorConversionSkFilterCache::Key::Key::operator==(
const Key& other) const {
return src == other.src && dst == other.dst &&
return src == other.src && src_bit_depth == other.src_bit_depth &&
dst == other.dst &&
sdr_max_luminance_nits == other.sdr_max_luminance_nits;
}

Expand All @@ -32,20 +33,26 @@ bool ColorConversionSkFilterCache::Key::operator!=(const Key& other) const {
}

bool ColorConversionSkFilterCache::Key::operator<(const Key& other) const {
return std::tie(src, dst, sdr_max_luminance_nits) <
std::tie(other.src, other.dst, other.sdr_max_luminance_nits);
return std::tie(src, src_bit_depth, dst, sdr_max_luminance_nits) <
std::tie(other.src, other.src_bit_depth, other.dst,
other.sdr_max_luminance_nits);
}

ColorConversionSkFilterCache::Key::Key(const gfx::ColorSpace& src,
uint32_t src_bit_depth,
const gfx::ColorSpace& dst,
float sdr_max_luminance_nits)
: src(src), dst(dst), sdr_max_luminance_nits(sdr_max_luminance_nits) {}
: src(src),
src_bit_depth(src_bit_depth),
dst(dst),
sdr_max_luminance_nits(sdr_max_luminance_nits) {}

sk_sp<SkColorFilter> ColorConversionSkFilterCache::Get(
const gfx::ColorSpace& src,
const gfx::ColorSpace& dst,
float resource_offset,
float resource_multiplier,
absl::optional<uint32_t> src_bit_depth,
absl::optional<gfx::HDRMetadata> src_hdr_metadata,
float sdr_max_luminance_nits,
float dst_max_luminance_relative) {
Expand All @@ -65,11 +72,13 @@ sk_sp<SkColorFilter> ColorConversionSkFilterCache::Get(
}
}

const Key key(src, dst, sdr_max_luminance_nits);
const Key key(src, src_bit_depth.value_or(0), dst, sdr_max_luminance_nits);
sk_sp<SkRuntimeEffect>& effect = cache_[key];

gfx::ColorTransform::Options options;
options.tone_map_pq_and_hlg_to_dst = true;
if (src_bit_depth)
options.src_bit_depth = src_bit_depth.value();
options.sdr_max_luminance_nits = sdr_max_luminance_nits;
options.src_hdr_metadata = src_hdr_metadata;
options.dst_max_luminance_relative = dst_max_luminance_relative;
Expand Down Expand Up @@ -142,8 +151,8 @@ sk_sp<SkImage> ColorConversionSkFilterCache::ConvertImage(
sk_sp<SkColorFilter> filter =
Get(image_color_space, gfx::ColorSpace(*target_color_space),
/*resource_offset=*/0, /*resource_multiplier=*/1,
/*src_hdr_metadata=*/absl::nullopt, sdr_max_luminance_nits,
dst_max_luminance_relative);
/*src_bit_depth=*/absl::nullopt, /*src_hdr_metadata=*/absl::nullopt,
sdr_max_luminance_nits, dst_max_luminance_relative);
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc);
paint.setColorFilter(filter);
Expand Down
12 changes: 8 additions & 4 deletions ui/gfx/color_conversion_sk_filter_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@ class COLOR_SPACE_EXPORT ColorConversionSkFilterCache {
delete;
~ColorConversionSkFilterCache();

// Retrieve an SkColorFilter to transform `src` to `dst`. The filter also
// applies the offset `src_resource_offset` and then scales by
// `src_resource_multiplier`. Apply tone mapping of `src` is HLG or PQ,
// using `sdr_max_luminance_nits`, `src_hdr_metadata`, and
// Retrieve an SkColorFilter to transform `src` to `dst`. The bit depth of
// `src` maybe specified in `src_bit_depth` (relevant only for YUV to RGB
// conversion). The filter also applies the offset `src_resource_offset` and
// then scales by `src_resource_multiplier`. Apply tone mapping of `src` is
// HLG or PQ, using `sdr_max_luminance_nits`, `src_hdr_metadata`, and
// `dst_max_luminance_relative` as parameters.
sk_sp<SkColorFilter> Get(const gfx::ColorSpace& src,
const gfx::ColorSpace& dst,
float resource_offset,
float resource_multiplier,
absl::optional<uint32_t> src_bit_depth,
absl::optional<gfx::HDRMetadata> src_hdr_metadata,
float sdr_max_luminance_nits,
float dst_max_luminance_relative);
Expand All @@ -59,10 +61,12 @@ class COLOR_SPACE_EXPORT ColorConversionSkFilterCache {
public:
struct Key {
Key(const gfx::ColorSpace& src,
uint32_t src_bit_depth,
const gfx::ColorSpace& dst,
float sdr_max_luminance_nits);

gfx::ColorSpace src;
uint32_t src_bit_depth = 0;
gfx::ColorSpace dst;
float sdr_max_luminance_nits = 0.f;

Expand Down
17 changes: 12 additions & 5 deletions ui/gfx/color_space.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ namespace gfx {

namespace {

// Videos that are from a 10 or 12 bit source, but are stored in a 16-bit
// format (e.g, PIXEL_FORMAT_P016LE) will report having 16 bits per pixel.
// Assume they have 10 bits per pixel.
// https://crbug.com/1381100
int BitDepthWithWorkaroundApplied(int bit_depth) {
return bit_depth == 16 ? 10 : bit_depth;
}

static bool FloatsEqualWithinTolerance(const float* a,
const float* b,
int n,
Expand Down Expand Up @@ -990,6 +998,7 @@ bool ColorSpace::GetPiecewiseHDRParams(float* sdr_joint,
}

SkM44 ColorSpace::GetTransferMatrix(int bit_depth) const {
bit_depth = BitDepthWithWorkaroundApplied(bit_depth);
DCHECK_GE(bit_depth, 8);
// If chroma samples are real numbers in the range of −0.5 to 0.5, an offset
// of 0.5 is added to get real numbers in the range of 0 to 1. When
Expand Down Expand Up @@ -1090,6 +1099,7 @@ SkM44 ColorSpace::GetTransferMatrix(int bit_depth) const {
}

SkM44 ColorSpace::GetRangeAdjustMatrix(int bit_depth) const {
bit_depth = BitDepthWithWorkaroundApplied(bit_depth);
DCHECK_GE(bit_depth, 8);
switch (range_) {
case RangeID::FULL:
Expand Down Expand Up @@ -1135,6 +1145,7 @@ SkM44 ColorSpace::GetRangeAdjustMatrix(int bit_depth) const {
}

bool ColorSpace::ToSkYUVColorSpace(int bit_depth, SkYUVColorSpace* out) const {
bit_depth = BitDepthWithWorkaroundApplied(bit_depth);
switch (matrix_) {
case MatrixID::BT709:
*out = range_ == RangeID::FULL ? kRec709_Full_SkYUVColorSpace
Expand All @@ -1153,11 +1164,7 @@ bool ColorSpace::ToSkYUVColorSpace(int bit_depth, SkYUVColorSpace* out) const {
: kBT2020_8bit_Limited_SkYUVColorSpace;
return true;
}
// Videos that are from an 8 or 10 bit source, but are stored in a 16-bit
// format (e.g, PIXEL_FORMAT_P016LE) will report having 16 bits per pixel.
// Assume they have 10 bits per pixel.
// https://crbug.com/1381100
if (bit_depth == 10 || bit_depth == 16) {
if (bit_depth == 10) {
*out = range_ == RangeID::FULL ? kBT2020_10bit_Full_SkYUVColorSpace
: kBT2020_10bit_Limited_SkYUVColorSpace;
return true;
Expand Down

0 comments on commit 3804dfb

Please sign in to comment.