diff --git a/src/color_helpers.cpp b/src/color_helpers.cpp index b4d9676c2..f47d4e391 100644 --- a/src/color_helpers.cpp +++ b/src/color_helpers.cpp @@ -891,3 +891,11 @@ bool approxEqual( const glm::vec3 & a, const glm::vec3 & b, float flTolerance = glm::vec3 v = glm::abs(a - b); return ( v.x < flTolerance && v.y < flTolerance && v.z < flTolerance ); } + +const glm::mat3 k_xyz_from_709 = normalised_primary_matrix( displaycolorimetry_709.primaries, displaycolorimetry_709.white, 1.f ); +const glm::mat3 k_709_from_xyz = glm::inverse( k_xyz_from_709 ); + +const glm::mat3 k_xyz_from_2020 = normalised_primary_matrix( displaycolorimetry_2020.primaries, displaycolorimetry_2020.white, 1.f ); +const glm::mat3 k_2020_from_xyz = glm::inverse( k_xyz_from_2020 ); + +const glm::mat3 k_2020_from_709 = k_2020_from_xyz * k_xyz_from_709; diff --git a/src/color_helpers.h b/src/color_helpers.h index 24b9c2075..51aaedc74 100644 --- a/src/color_helpers.h +++ b/src/color_helpers.h @@ -472,3 +472,12 @@ static constexpr displaycolorimetry_t displaycolorimetry_2020 .primaries = { { 0.708f, 0.292f }, { 0.170f, 0.797f }, { 0.131f, 0.046f } }, .white = { 0.3127f, 0.3290f }, // D65 }; + + +extern const glm::mat3 k_xyz_from_709; +extern const glm::mat3 k_709_from_xyz; + +extern const glm::mat3 k_xyz_from_2020; +extern const glm::mat3 k_2020_from_xyz; + +extern const glm::mat3 k_2020_from_709; diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index ac2dcd645..99193202a 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -130,6 +130,7 @@ extern float g_flHDRItmTargetNits; extern std::atomic g_lastVblank; +static std::shared_ptr s_scRGB709To2020Matrix; std::string clipboard; std::string primarySelection; @@ -1944,6 +1945,7 @@ void MouseCursor::paint(steamcompmgr_win_t *window, steamcompmgr_win_t *fit, str layer->filter = cursor_scale != 1.0f ? GamescopeUpscaleFilter::LINEAR : GamescopeUpscaleFilter::NEAREST; layer->blackBorder = false; + layer->ctm = nullptr; layer->colorspace = GAMESCOPE_APP_TEXTURE_COLORSPACE_SRGB; } @@ -1991,6 +1993,9 @@ paint_cached_base_layer(const std::shared_ptr& commit, const BaseLayer layer->opacity = base.opacity * flOpacityScale; layer->colorspace = commit->colorspace(); + layer->ctm = nullptr; + if (layer->colorspace == GAMESCOPE_APP_TEXTURE_COLORSPACE_SCRGB) + layer->ctm = s_scRGB709To2020Matrix; layer->tex = commit->vulkanTex; layer->fbid = commit->fb_id; @@ -2195,6 +2200,9 @@ paint_window(steamcompmgr_win_t *w, steamcompmgr_win_t *scaleW, struct FrameInfo layer->filter = (w->isOverlay || w->isExternalOverlay) ? GamescopeUpscaleFilter::LINEAR : g_upscaleFilter; layer->colorspace = lastCommit->colorspace(); + layer->ctm = nullptr; + if (layer->colorspace == GAMESCOPE_APP_TEXTURE_COLORSPACE_SCRGB) + layer->ctm = s_scRGB709To2020Matrix; if (layer->filter == GamescopeUpscaleFilter::PIXEL) { @@ -2675,6 +2683,7 @@ paint_all(bool async) baseLayer->applyColorMgmt = false; baseLayer->filter = GamescopeUpscaleFilter::NEAREST; + baseLayer->ctm = nullptr; baseLayer->colorspace = g_bOutputHDREnabled ? GAMESCOPE_APP_TEXTURE_COLORSPACE_HDR10_PQ : GAMESCOPE_APP_TEXTURE_COLORSPACE_SRGB; g_bWasPartialComposite = false; @@ -2702,6 +2711,7 @@ paint_all(bool async) overlayLayer->filter = GamescopeUpscaleFilter::NEAREST; // Partial composition stuff has the same colorspace. // So read that from the composite frame info + overlayLayer->ctm = nullptr; overlayLayer->colorspace = compositeFrameInfo.layers[0].colorspace; } else @@ -7465,6 +7475,11 @@ steamcompmgr_main(int argc, char **argv) update_screenshot_color_mgmt(); + // Transpose to get this 3x3 matrix into the right state for applying as a 3x4 + // on DRM + the Vulkan side. + // ie. color.rgb = color.rgba * u_ctm[offsetLayerIdx]; + s_scRGB709To2020Matrix = drm_create_ctm(&g_DRM, glm::mat3x4(glm::transpose(k_2020_from_709))); + for (;;) { bool vblank = false;