From 02e008685618173336d6b7cb5f96413c44a5bbf0 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Tue, 8 Feb 2022 02:44:36 +0000 Subject: [PATCH] steamcompmgr: New night mode color toys --- src/drm.cpp | 58 ++++++++++++++++++++++++++++++++++++++------ src/drm.hpp | 4 +++ src/steamcompmgr.cpp | 23 ++++++++++++++++++ src/xwayland_ctx.hpp | 2 ++ 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/drm.cpp b/src/drm.cpp index 4945d22..9da45eb 100644 --- a/src/drm.cpp +++ b/src/drm.cpp @@ -1373,18 +1373,62 @@ bool drm_set_color_gains(struct drm_t *drm, float *gains) return false; } +bool drm_set_color_linear_gains(struct drm_t *drm, float *gains) +{ + for (int i = 0; i < 3; i++) + drm->pending.color_linear_gain[i] = gains[i]; + + for (int i = 0; i < 3; i++) + { + if ( drm->current.color_linear_gain[i] != drm->pending.color_linear_gain[i] ) + return true; + } + return false; +} + +bool drm_set_color_gain_blend(struct drm_t *drm, float blend) +{ + drm->pending.gain_blend = blend; + if ( drm->current.gain_blend != drm->pending.gain_blend ) + return true; + return false; +} + +inline float lerp( float a, float b, float t ) +{ + return a + t * (b - a); +} + +inline uint16_t drm_calc_lut_value( float input, float flLinearGain, float flGain, float flBlend ) +{ + float flValue = lerp( flGain * input, linear_to_srgb( flLinearGain * srgb_to_linear( input ) ), flBlend ); + return (uint16_t)quantize( flValue, (float)UINT16_MAX ); +} + bool drm_update_gamma_lut(struct drm_t *drm) { if (drm->pending.color_gain[0] == drm->current.color_gain[0] && drm->pending.color_gain[1] == drm->current.color_gain[1] && - drm->pending.color_gain[2] == drm->current.color_gain[2]) + drm->pending.color_gain[2] == drm->current.color_gain[2] && + drm->pending.color_linear_gain[0] == drm->current.color_linear_gain[0] && + drm->pending.color_linear_gain[1] == drm->current.color_linear_gain[1] && + drm->pending.color_linear_gain[2] == drm->current.color_linear_gain[2] && + drm->pending.gain_blend == drm->current.gain_blend ) { return true; } - if (drm->pending.color_gain[0] == 1.0f && - drm->pending.color_gain[1] == 1.0f && - drm->pending.color_gain[2] == 1.0f) + bool color_gain_identity = drm->pending.gain_blend == 1.0f || + ( drm->pending.color_gain[0] == 1.0f && + drm->pending.color_gain[1] == 1.0f && + drm->pending.color_gain[2] == 1.0f ); + + bool linear_gain_identity = drm->pending.gain_blend == 0.0f || + ( drm->pending.color_linear_gain[0] == 1.0f && + drm->pending.color_linear_gain[1] == 1.0f && + drm->pending.color_linear_gain[2] == 1.0f ); + + if ( color_gain_identity && linear_gain_identity ) { drm->pending.gamma_lut_id = 0; return true; @@ -1395,9 +1439,9 @@ bool drm_update_gamma_lut(struct drm_t *drm) for ( int i = 0; i < lut_entries; i++ ) { float input = float(i) / float(lut_entries - 1); - gamma_lut[i].red = quantize( linear_to_srgb( drm->pending.color_gain[0] * srgb_to_linear( input ) ), (float)UINT16_MAX ); - gamma_lut[i].green = quantize( linear_to_srgb( drm->pending.color_gain[1] * srgb_to_linear( input ) ), (float)UINT16_MAX ); - gamma_lut[i].blue = quantize( linear_to_srgb( drm->pending.color_gain[2] * srgb_to_linear( input ) ), (float)UINT16_MAX ); + gamma_lut[i].red = drm_calc_lut_value( input, drm->pending.color_linear_gain[0], drm->pending.color_gain[0], drm->pending.gain_blend ); + gamma_lut[i].green = drm_calc_lut_value( input, drm->pending.color_linear_gain[1], drm->pending.color_gain[1], drm->pending.gain_blend ); + gamma_lut[i].blue = drm_calc_lut_value( input, drm->pending.color_linear_gain[2], drm->pending.color_gain[2], drm->pending.gain_blend ); } uint32_t blob_id = 0; diff --git a/src/drm.hpp b/src/drm.hpp index 692790b..d73e5c9 100644 --- a/src/drm.hpp +++ b/src/drm.hpp @@ -97,6 +97,8 @@ struct drm_t { uint32_t mode_id; uint32_t gamma_lut_id; float color_gain[3] = { 1.0f, 1.0f, 1.0f }; + float color_linear_gain[3] = { 1.0f, 1.0f, 1.0f }; + float gain_blend = 0.0f; } current, pending; /* FBs in the atomic request, but not yet submitted to KMS */ @@ -154,7 +156,9 @@ bool drm_set_connector( struct drm_t *drm, struct connector *conn ); bool drm_set_mode( struct drm_t *drm, const drmModeModeInfo *mode ); bool drm_set_refresh( struct drm_t *drm, int refresh ); bool drm_set_resolution( struct drm_t *drm, int width, int height ); +bool drm_set_color_linear_gains(struct drm_t *drm, float *gains); bool drm_set_color_gains(struct drm_t *drm, float *gains); +bool drm_set_color_gain_blend(struct drm_t *drm, float blend); bool drm_update_gamma_lut(struct drm_t *drm); char *find_drm_node_by_devid(dev_t devid); diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 5c752bc..b9546e7 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -3608,9 +3608,30 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev) gains[i] = bit_cast( user_gains[i] ); } + if ( drm_set_color_linear_gains( &g_DRM, gains ) ) + hasRepaint = true; + } + if ( ev->atom == ctx->atoms.gamescopeColorGain ) + { + std::vector< uint32_t > user_gains; + bool bHasColor = get_prop( ctx, ctx->root, ctx->atoms.gamescopeColorGain, user_gains ); + + float gains[3] = { 1.0f, 1.0f, 1.0f }; + if ( bHasColor && user_gains.size() == 3 ) + { + for (int i = 0; i < 3; i++) + gains[i] = bit_cast( user_gains[i] ); + } + if ( drm_set_color_gains( &g_DRM, gains ) ) hasRepaint = true; } + if ( ev->atom == ctx->atoms.gamescopeColorLinearGainBlend ) + { + float flBlend = bit_cast(get_prop(ctx, ctx->root, ctx->atoms.gamescopeColorLinearGainBlend, 0)); + if ( drm_set_color_gain_blend( &g_DRM, flBlend ) ) + hasRepaint = true; + } if ( ev->atom == ctx->atoms.gamescopeXWaylandModeControl ) { std::vector< uint32_t > xwayland_mode_ctl; @@ -4494,6 +4515,8 @@ void init_xwayland_ctx(gamescope_xwayland_server_t *xwayland_server) ctx->atoms.gamescopeFSRSharpness = XInternAtom( ctx->dpy, "GAMESCOPE_FSR_SHARPNESS", false ); ctx->atoms.gamescopeColorLinearGain = XInternAtom( ctx->dpy, "GAMESCOPE_COLOR_LINEARGAIN", false ); + ctx->atoms.gamescopeColorGain = XInternAtom( ctx->dpy, "GAMESCOPE_COLOR_GAIN", false ); + ctx->atoms.gamescopeColorLinearGainBlend = XInternAtom( ctx->dpy, "GAMESCOPE_COLOR_LINEARGAIN_BLEND", false ); ctx->atoms.gamescopeXWaylandModeControl = XInternAtom( ctx->dpy, "GAMESCOPE_XWAYLAND_MODE_CONTROL", false ); ctx->root_width = DisplayWidth(ctx->dpy, ctx->scr); diff --git a/src/xwayland_ctx.hpp b/src/xwayland_ctx.hpp index 35e7301..894c055 100644 --- a/src/xwayland_ctx.hpp +++ b/src/xwayland_ctx.hpp @@ -117,6 +117,8 @@ struct xwayland_ctx_t Atom gamescopeFSRSharpness; Atom gamescopeColorLinearGain; + Atom gamescopeColorGain; + Atom gamescopeColorLinearGainBlend; Atom gamescopeXWaylandModeControl; } atoms;