Commit ca242391 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

HDR/macOS Tonemapping: Plumb color space

Add plumbing to send the gfx::ColorSpace of the GLImage through to the
HDRCopierLayer.

Bug: 1101041
Change-Id: Ia41022d068b6daea5f1fd17191468cf89c463e37
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352618
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798469}
parent 29289e6c
......@@ -27,6 +27,7 @@ component("metal_util") {
deps = [
"//base",
"//components/crash/core/common:crash_key",
"//ui/gfx",
]
frameworks = [
......
include_rules = [
"+components/crash/core/common/crash_key.h",
"+ui/gfx",
]
......@@ -7,19 +7,29 @@
#include "components/metal_util/metal_util_export.h"
#include <IOSurface/IOSurface.h>
namespace gfx {
class ColorSpace;
} // namespace gfx
@class CALayer;
namespace metal {
// Return true if we should use the HDRCopier for the specified content.
bool METAL_UTIL_EXPORT ShouldUseHDRCopier(IOSurfaceRef buffer,
const gfx::ColorSpace& color_space);
// Create a layer which may have its contents set an HDR IOSurface via
// the -[CALayer setContents:] method.
// - The IOSurface specified to setContents must have pixel format
// kCVPixelFormatType_64RGBAHalf or kCVPixelFormatType_ARGB2101010LEPacked,
// any other pixel formats will be NOTREACHED.
// - This layer will, in setContents, blit the contents of the specified
// IOSurface to an HDR-capable CAMetalLayer.
// UpdateHDRCopierLayer.
CALayer* METAL_UTIL_EXPORT CreateHDRCopierLayer();
// Update the contents of |layer| to the specified IOSurface and color space.
void METAL_UTIL_EXPORT UpdateHDRCopierLayer(CALayer* layer,
IOSurfaceRef buffer,
const gfx::ColorSpace& color_space);
} // namespace metal
#endif // COMPONENTS_METAL_UTIL_HDR_COPIER_LAYER_H_
......@@ -14,6 +14,7 @@
#include "base/notreached.h"
#include "base/strings/sys_string_conversions.h"
#include "components/metal_util/device.h"
#include "ui/gfx/color_space.h"
namespace {
......@@ -67,7 +68,6 @@ MTLPixelFormat IOSurfaceGetMTLPixelFormat(IOSurfaceRef buffer)
default:
break;
}
NOTREACHED();
return MTLPixelFormatInvalid;
}
......@@ -146,7 +146,8 @@ API_AVAILABLE(macos(10.15))
base::scoped_nsprotocol<id<MTLRenderPipelineState>> _render_pipeline_state;
}
- (id)init;
- (void)setContents:(id)contents;
- (void)setHDRContents:(IOSurfaceRef)buffer
withColorSpace:(gfx::ColorSpace)color_space;
@end
@implementation HDRCopierLayer
......@@ -161,9 +162,8 @@ API_AVAILABLE(macos(10.15))
return self;
}
- (void)setContents:(id)contents {
IOSurfaceRef buffer = reinterpret_cast<IOSurfaceRef>(contents);
- (void)setHDRContents:(IOSurfaceRef)buffer
withColorSpace:(gfx::ColorSpace)color_space {
// Retrieve information about the IOSurface.
size_t width = IOSurfaceGetWidth(buffer);
size_t height = IOSurfaceGetHeight(buffer);
......@@ -277,8 +277,29 @@ CALayer* CreateHDRCopierLayer() {
// (HDR content will be clipped, but that would have happened anyway).
if (@available(macos 10.15, *))
return [[HDRCopierLayer alloc] init];
else
return [[CALayer alloc] init];
NOTREACHED();
return nil;
}
void UpdateHDRCopierLayer(CALayer* layer,
IOSurfaceRef buffer,
const gfx::ColorSpace& color_space) {
if (@available(macos 10.15, *)) {
if (auto* hdr_copier_layer = base::mac::ObjCCast<HDRCopierLayer>(layer)) {
[hdr_copier_layer setHDRContents:buffer withColorSpace:color_space];
return;
}
}
NOTREACHED();
}
bool ShouldUseHDRCopier(IOSurfaceRef buffer,
const gfx::ColorSpace& color_space) {
if (@available(macos 10.15, *)) {
return color_space.IsHDR() &&
IOSurfaceGetMTLPixelFormat(buffer) != MTLPixelFormatInvalid;
}
return false;
}
} // namespace metal
......@@ -169,7 +169,7 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
const gfx::RectF& contents_rect,
const gfx::Rect& rect,
unsigned background_color,
bool has_hdr_color_space,
const gfx::ColorSpace& color_space,
unsigned edge_aa_mask,
float opacity,
unsigned filter);
......@@ -191,6 +191,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CARendererLayerTree {
gfx::RectF contents_rect;
gfx::RectF rect;
unsigned background_color = 0;
// The color space of |io_surface|. Used for HDR tonemapping.
gfx::ColorSpace io_surface_color_space;
// Note that the CoreAnimation edge antialiasing mask is not the same as
// the edge antialiasing mask passed to the constructor.
CAEdgeAntialiasingMask ca_edge_aa_mask = 0;
......
......@@ -385,7 +385,7 @@ CARendererLayerTree::ContentLayer::ContentLayer(
const gfx::RectF& contents_rect,
const gfx::Rect& rect_in,
unsigned background_color,
bool has_hdr_color_space,
const gfx::ColorSpace& io_surface_color_space,
unsigned edge_aa_mask,
float opacity,
unsigned filter)
......@@ -394,6 +394,7 @@ CARendererLayerTree::ContentLayer::ContentLayer(
contents_rect(contents_rect),
rect(rect_in),
background_color(background_color),
io_surface_color_space(io_surface_color_space),
ca_edge_aa_mask(0),
opacity(opacity),
ca_filter(filter == GL_LINEAR ? kCAFilterLinear : kCAFilterNearest) {
......@@ -439,14 +440,10 @@ CARendererLayerTree::ContentLayer::ContentLayer(
}
// Determine which type of CALayer subclass we should use.
if (io_surface) {
if (metal::ShouldUseHDRCopier(io_surface, io_surface_color_space)) {
type = CALayerType::kHDRCopier;
} else if (io_surface) {
switch (IOSurfaceGetPixelFormat(io_surface)) {
case kCVPixelFormatType_64RGBAHalf:
case kCVPixelFormatType_ARGB2101010LEPacked:
// HDR content can come in either as half-float or as 10-10-10-2.
if (has_hdr_color_space)
type = CALayerType::kHDRCopier;
break;
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
// Only allow 4:2:0 frames which fill the layer's contents to be
......@@ -496,6 +493,7 @@ CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer)
contents_rect(layer.contents_rect),
rect(layer.rect),
background_color(layer.background_color),
io_surface_color_space(layer.io_surface_color_space),
ca_edge_aa_mask(layer.ca_edge_aa_mask),
opacity(layer.opacity),
ca_filter(layer.ca_filter),
......@@ -571,7 +569,7 @@ void CARendererLayerTree::TransformLayer::AddContentLayer(
const CARendererLayerParams& params) {
base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer;
bool has_hdr_color_space = false;
gfx::ColorSpace io_surface_color_space;
if (params.image) {
gl::GLImageIOSurface* io_surface_image =
gl::GLImageIOSurface::FromGLImage(params.image);
......@@ -585,11 +583,11 @@ void CARendererLayerTree::TransformLayer::AddContentLayer(
// TODO(ccameron): If this indeed causes the bug to disappear, then
// extirpate the CVPixelBufferRef path.
// cv_pixel_buffer = io_surface_image->cv_pixel_buffer();
has_hdr_color_space = params.image->color_space().IsHDR();
io_surface_color_space = params.image->color_space();
}
content_layers.push_back(
ContentLayer(tree, io_surface, cv_pixel_buffer, params.contents_rect,
params.rect, params.background_color, has_hdr_color_space,
params.rect, params.background_color, io_surface_color_space,
params.edge_aa_mask, params.opacity, params.filter));
}
......@@ -809,7 +807,10 @@ void CARendererLayerTree::ContentLayer::CommitToCA(CALayer* superlayer,
switch (type) {
case CALayerType::kHDRCopier:
[ca_layer setContents:static_cast<id>(io_surface.get())];
if (update_contents) {
metal::UpdateHDRCopierLayer(ca_layer.get(), io_surface.get(),
io_surface_color_space);
}
break;
case CALayerType::kVideo:
if (update_contents) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment