MacOS: Enable support for EDR rendering #105662
|
@ -88,6 +88,18 @@ GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual,
|
|||
[m_metalLayer removeAllAnimations];
|
||||
[m_metalLayer setDevice:metalDevice];
|
||||
m_metalLayer.allowsNextDrawableTimeout = NO;
|
||||
|
||||
// Enable EDR support. This is done by:
|
||||
// 1. Using a floating point render target, so that values ouside 0..1 can be used
|
||||
// 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1
|
||||
// 3. Setting the extended sRGB color space so tha the OS knows how to interpret the values
|
||||
m_metalLayer.wantsExtendedDynamicRangeContent = YES;
|
||||
m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float;
|
||||
const CFStringRef name = kCGColorSpaceExtendedSRGB;
|
||||
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name);
|
||||
m_metalLayer.colorspace = colorspace;
|
||||
CGColorSpaceRelease(colorspace);
|
||||
|
||||
metalInit();
|
||||
}
|
||||
else {
|
||||
|
@ -518,7 +530,7 @@ GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()
|
|||
*
|
||||
* Use Metal layer to avoid Viewport lagging on macOS, see #60043. */
|
||||
|
||||
static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatBGRA8Unorm;
|
||||
static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatRGBA16Float;
|
||||
static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT = kCVPixelFormatType_32BGRA;
|
||||
|
||||
void GHOST_ContextCGL::metalInit()
|
||||
|
|
|
@ -343,6 +343,17 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
|
|||
[m_metalLayer setPresentsWithTransaction:NO];
|
||||
[m_metalLayer removeAllAnimations];
|
||||
[m_metalLayer setDevice:metalDevice];
|
||||
|
||||
// Enable EDR support. This is done by:
|
||||
// 1. Using a floating point render target, so that values ouside 0..1 can be used
|
||||
// 2. Informing the OS that we are EDR aware, and intend to use values outside 0..1
|
||||
// 3. Setting the extended sRGB color space so tha the OS knows how to interpret the values
|
||||
m_metalLayer.wantsExtendedDynamicRangeContent = YES;
|
||||
m_metalLayer.pixelFormat = MTLPixelFormatRGBA16Float;
|
||||
const CFStringRef name = kCGColorSpaceExtendedSRGB;
|
||||
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name);
|
||||
m_metalLayer.colorspace = colorspace;
|
||||
CGColorSpaceRelease(colorspace);
|
||||
|
||||
m_metalView = [[CocoaMetalView alloc] initWithFrame:rect];
|
||||
[m_metalView setWantsLayer:YES];
|
||||
|
|
|
@ -169,7 +169,10 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay)
|
|||
* merge UI using alpha blending in the correct color space. */
|
||||
if (parameters.use_overlay) {
|
||||
col.rgb = pow(col.rgb, vec3(parameters.exponent * 2.2));
|
||||
col = clamp(col, 0.0, 1.0);
|
||||
if (!parameters.use_extended) {
|
||||
/* if we're not using an extended colour space, clamp the color 0..1 */
|
||||
brecht marked this conversation as resolved
Outdated
|
||||
col = clamp(col, 0.0, 1.0);
|
||||
}
|
||||
col *= 1.0 - col_overlay.a;
|
||||
fclem marked this conversation as resolved
Outdated
Clément Foucault
commented
Comment style: Capital + fullstop. Comment style: Capital + fullstop.
|
||||
col += col_overlay; /* Assumed unassociated alpha. */
|
||||
col.rgb = pow(col.rgb, vec3(1.0 / 2.2));
|
||||
|
|
|
@ -289,7 +289,8 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
|
|||
const float exponent,
|
||||
const float dither,
|
||||
const bool use_predivide,
|
||||
const bool use_overlay)
|
||||
const bool use_overlay,
|
||||
const bool use_extended)
|
||||
fclem marked this conversation as resolved
Brecht Van Lommel
commented
use_extended -> use_hdr I think is more clear, since that's the name of the option. EDR I guess is a macOS specific term. use_extended -> use_hdr I think is more clear, since that's the name of the option. EDR I guess is a macOS specific term.
|
||||
{
|
||||
return impl->gpuDisplayShaderBind(config,
|
||||
input,
|
||||
|
@ -301,7 +302,8 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
|
|||
exponent,
|
||||
dither,
|
||||
use_predivide,
|
||||
use_overlay);
|
||||
use_overlay,
|
||||
use_extended);
|
||||
}
|
||||
|
||||
void OCIO_gpuDisplayShaderUnbind()
|
||||
|
|
|
@ -196,7 +196,8 @@ bool OCIO_gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
|
|||
const float exponent,
|
||||
const float dither,
|
||||
const bool use_predivide,
|
||||
const bool use_overlay);
|
||||
const bool use_overlay,
|
||||
const bool use_extended);
|
||||
void OCIO_gpuDisplayShaderUnbind(void);
|
||||
void OCIO_gpuCacheFree(void);
|
||||
|
||||
|
|
|
@ -114,7 +114,8 @@ class IOCIOImpl {
|
|||
const float /*exponent*/,
|
||||
const float /*dither*/,
|
||||
const bool /*use_predivide*/,
|
||||
const bool /*use_overlay*/)
|
||||
const bool /*use_overlay*/,
|
||||
const bool /*use_extended*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -317,7 +318,8 @@ class OCIOImpl : public IOCIOImpl {
|
|||
const float exponent,
|
||||
const float dither,
|
||||
const bool use_predivide,
|
||||
const bool use_overlay);
|
||||
const bool use_overlay,
|
||||
const bool use_extended);
|
||||
void gpuDisplayShaderUnbind(void);
|
||||
void gpuCacheFree(void);
|
||||
|
||||
|
|
|
@ -512,7 +512,8 @@ static void updateGPUDisplayParameters(OCIO_GPUShader &shader,
|
|||
float exponent,
|
||||
float dither,
|
||||
bool use_predivide,
|
||||
bool use_overlay)
|
||||
bool use_overlay,
|
||||
bool use_extended)
|
||||
{
|
||||
bool do_update = false;
|
||||
if (shader.parameters_buffer == nullptr) {
|
||||
|
@ -540,6 +541,10 @@ static void updateGPUDisplayParameters(OCIO_GPUShader &shader,
|
|||
data.use_overlay = use_overlay;
|
||||
do_update = true;
|
||||
}
|
||||
if (bool(data.use_extended) != use_extended) {
|
||||
data.use_extended = use_extended;
|
||||
do_update = true;
|
||||
}
|
||||
if (do_update) {
|
||||
GPU_uniformbuf_update(shader.parameters_buffer, &data);
|
||||
}
|
||||
|
@ -678,7 +683,8 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
|
|||
const float exponent,
|
||||
const float dither,
|
||||
const bool use_predivide,
|
||||
const bool use_overlay)
|
||||
const bool use_overlay,
|
||||
const bool use_extended)
|
||||
{
|
||||
/* Get GPU shader from cache or create new one. */
|
||||
OCIO_GPUDisplayShader &display_shader = getGPUDisplayShader(
|
||||
|
@ -713,7 +719,7 @@ bool OCIOImpl::gpuDisplayShaderBind(OCIO_ConstConfigRcPtr *config,
|
|||
GPU_uniformbuf_bind(textures.uniforms_buffer, UNIFORMBUF_SLOT_LUTS);
|
||||
}
|
||||
|
||||
updateGPUDisplayParameters(shader, scale, exponent, dither, use_predivide, use_overlay);
|
||||
updateGPUDisplayParameters(shader, scale, exponent, dither, use_predivide, use_overlay, use_extended);
|
||||
GPU_uniformbuf_bind(shader.parameters_buffer, UNIFORMBUF_SLOT_DISPLAY);
|
||||
|
||||
/* TODO(fclem): remove remains of IMM. */
|
||||
|
|
|
@ -35,7 +35,7 @@ struct OCIO_GPUParameters {
|
|||
float exponent;
|
||||
bool1 use_predivide;
|
||||
bool1 use_overlay;
|
||||
bool1 use_extended;
|
||||
int _pad0;
|
||||
int _pad1;
|
||||
int _pad2;
|
||||
};
|
||||
|
|
|
@ -56,6 +56,8 @@ displays:
|
|||
- !<View> {name: Filmic Log, colorspace: Filmic Log}
|
||||
- !<View> {name: Raw, colorspace: Raw}
|
||||
- !<View> {name: False Color, colorspace: False Color}
|
||||
Extended sRGB:
|
||||
- !<View> {name: Standard, colorspace: sRGB}
|
||||
XYZ:
|
||||
- !<View> {name: Standard, colorspace: XYZ}
|
||||
- !<View> {name: DCI, colorspace: dci_xyz}
|
||||
|
@ -63,7 +65,7 @@ displays:
|
|||
None:
|
||||
- !<View> {name: Standard, colorspace: Raw}
|
||||
|
||||
active_displays: [sRGB, XYZ, None]
|
||||
active_displays: [sRGB, Extended sRGB, XYZ, None]
|
||||
active_views: [Standard, Filmic, Filmic Log, Raw, False Color]
|
||||
|
||||
colorspaces:
|
||||
|
|
|
@ -425,7 +425,7 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
|
|||
void ED_screen_preview_render(const bScreen *screen, int size_x, int size_y, uint *r_rect)
|
||||
{
|
||||
char err_out[256] = "unknown";
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, true, GPU_RGBA8, err_out);
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(size_x, size_y, true, GPU_RGBA16F, err_out);
|
||||
|
||||
GPU_offscreen_bind(offscreen, true);
|
||||
GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
|
|
@ -1887,7 +1887,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
|||
|
||||
if (own_ofs) {
|
||||
/* bind */
|
||||
ofs = GPU_offscreen_create(sizex, sizey, true, GPU_RGBA8, err_out);
|
||||
ofs = GPU_offscreen_create(sizex, sizey, true, GPU_RGBA16F, err_out);
|
||||
if (ofs == nullptr) {
|
||||
DRW_opengl_context_disable();
|
||||
return nullptr;
|
||||
|
|
|
@ -4097,6 +4097,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(
|
|||
const float gamma = applied_view_settings->gamma;
|
||||
const float scale = (exposure == 0.0f) ? 1.0f : powf(2.0f, exposure);
|
||||
const float exponent = (gamma == 1.0f) ? 1.0f : 1.0f / max_ff(FLT_EPSILON, gamma);
|
||||
const bool use_extended = STRPREFIX(display_settings->display_device, "Extended");
|
||||
|
||||
OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
|
||||
|
||||
|
@ -4111,7 +4112,8 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(
|
|||
exponent,
|
||||
dither,
|
||||
predivide,
|
||||
do_overlay_merge);
|
||||
do_overlay_merge,
|
||||
use_extended);
|
||||
|
||||
OCIO_configRelease(config);
|
||||
|
||||
|
|
|
@ -685,7 +685,7 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_
|
|||
* depth or multisample buffers. 3D view creates own buffers with
|
||||
* the data it needs. */
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(
|
||||
region->winx, region->winy, false, GPU_RGBA8, NULL);
|
||||
region->winx, region->winy, false, GPU_RGBA16F, NULL);
|
||||
if (!offscreen) {
|
||||
WM_report(RPT_ERROR, "Region could not be drawn!");
|
||||
return;
|
||||
|
@ -1148,7 +1148,7 @@ static void wm_draw_window(bContext *C, wmWindow *win)
|
|||
* stereo methods, but it's less efficient than drawing directly. */
|
||||
const int width = WM_window_pixels_x(win);
|
||||
const int height = WM_window_pixels_y(win);
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(width, height, false, GPU_RGBA8, NULL);
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(width, height, false, GPU_RGBA16F, NULL);
|
||||
|
||||
if (offscreen) {
|
||||
GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
|
||||
|
@ -1223,7 +1223,7 @@ uint *WM_window_pixels_read_offscreen(bContext *C, wmWindow *win, int r_size[2])
|
|||
r_size[0] = WM_window_pixels_x(win);
|
||||
r_size[1] = WM_window_pixels_y(win);
|
||||
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(r_size[0], r_size[1], false, GPU_RGBA8, NULL);
|
||||
GPUOffScreen *offscreen = GPU_offscreen_create(r_size[0], r_size[1], false, GPU_RGBA16F, NULL);
|
||||
if (UNLIKELY(!offscreen)) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
would still use
clamp(col, 0.0, 1.0)
here. and move themax
inside the else-clauseAs would even go further and suggest to move all clamping inside the if-else clause for clarity.
This way, the code is easier to refactor if we need to change the else clause.