color_helpers, steamcompmgr: Avoid allocation of LUTs every time we re-setup color mgmt
This commit is contained in:
parent
36c120901a
commit
f9e47a612f
4 changed files with 89 additions and 96 deletions
|
@ -611,7 +611,7 @@ void calcColorTransform( uint16_t * pRgbxData1d, int nLutSize1d,
|
||||||
destColorLinear = glm::mix( destColorLinear, sourceColorLinear, amount );
|
destColorLinear = glm::mix( destColorLinear, sourceColorLinear, amount );
|
||||||
|
|
||||||
// Apply night mode
|
// Apply night mode
|
||||||
destColorLinear = vNightModeMultLinear * destColorLinear * glm::vec3( flGain );
|
destColorLinear = vNightModeMultLinear * destColorLinear * flGain;
|
||||||
|
|
||||||
// Apply dest EOTF
|
// Apply dest EOTF
|
||||||
glm::vec3 destColorEOTFEncoded = calcLinearToEOTF( destColorLinear, destEOTF, tonemapping );
|
glm::vec3 destColorEOTFEncoded = calcLinearToEOTF( destColorLinear, destEOTF, tonemapping );
|
||||||
|
|
|
@ -2590,18 +2590,18 @@ bool drm_update_color_mgmt(struct drm_t *drm)
|
||||||
|
|
||||||
for ( uint32_t i = 0; i < EOTF_Count; i++ )
|
for ( uint32_t i = 0; i < EOTF_Count; i++ )
|
||||||
{
|
{
|
||||||
if ( g_ColorMgmtLuts[i].lut1d.empty() || g_ColorMgmtLuts[i].lut3d.empty() )
|
if ( !g_ColorMgmtLuts[i].HasLuts() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint32_t shaper_blob_id = 0;
|
uint32_t shaper_blob_id = 0;
|
||||||
if (drmModeCreatePropertyBlob(drm->fd, g_ColorMgmtLuts[i].lut1d.data(), sizeof(uint16_t) * g_ColorMgmtLuts[i].lut1d.size(), &shaper_blob_id) != 0) {
|
if (drmModeCreatePropertyBlob(drm->fd, g_ColorMgmtLuts[i].lut1d, sizeof(g_ColorMgmtLuts[i].lut1d), &shaper_blob_id) != 0) {
|
||||||
drm_log.errorf_errno("Unable to create SHAPERLUT property blob");
|
drm_log.errorf_errno("Unable to create SHAPERLUT property blob");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
drm->pending.shaperlut_id[ i ] = shaper_blob_id;
|
drm->pending.shaperlut_id[ i ] = shaper_blob_id;
|
||||||
|
|
||||||
uint32_t lut3d_blob_id = 0;
|
uint32_t lut3d_blob_id = 0;
|
||||||
if (drmModeCreatePropertyBlob(drm->fd, g_ColorMgmtLuts[i].lut3d.data(), sizeof(uint16_t) * g_ColorMgmtLuts[i].lut3d.size(), &lut3d_blob_id) != 0) {
|
if (drmModeCreatePropertyBlob(drm->fd, g_ColorMgmtLuts[i].lut3d, sizeof(g_ColorMgmtLuts[i].lut3d), &lut3d_blob_id) != 0) {
|
||||||
drm_log.errorf_errno("Unable to create LUT3D property blob");
|
drm_log.errorf_errno("Unable to create LUT3D property blob");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,18 +379,28 @@ struct gamescope_color_mgmt_t
|
||||||
bool operator != (const gamescope_color_mgmt_t&) const = default;
|
bool operator != (const gamescope_color_mgmt_t&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr uint32_t nLutEdgeSize3d = 17;
|
||||||
|
static constexpr uint32_t nLutSize1d = 4096;
|
||||||
|
|
||||||
struct gamescope_color_mgmt_luts
|
struct gamescope_color_mgmt_luts
|
||||||
{
|
{
|
||||||
std::vector<uint16_t> lut3d;
|
bool bHasLut3D = false;
|
||||||
std::vector<uint16_t> lut1d;
|
bool bHasLut1D = false;
|
||||||
|
uint16_t lut3d[nLutEdgeSize3d*nLutEdgeSize3d*nLutEdgeSize3d*4];
|
||||||
|
uint16_t lut1d[nLutSize1d*4];
|
||||||
|
|
||||||
std::shared_ptr<CVulkanTexture> vk_lut3d;
|
std::shared_ptr<CVulkanTexture> vk_lut3d;
|
||||||
std::shared_ptr<CVulkanTexture> vk_lut1d;
|
std::shared_ptr<CVulkanTexture> vk_lut1d;
|
||||||
|
|
||||||
|
bool HasLuts() const
|
||||||
|
{
|
||||||
|
return bHasLut3D && bHasLut1D;
|
||||||
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
lut3d.clear();
|
bHasLut1D = false;
|
||||||
lut1d.clear();
|
bHasLut3D = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -164,92 +164,78 @@ update_color_mgmt()
|
||||||
|
|
||||||
for ( uint32_t nInputEOTF = 0; nInputEOTF < EOTF_Count; nInputEOTF++ )
|
for ( uint32_t nInputEOTF = 0; nInputEOTF < EOTF_Count; nInputEOTF++ )
|
||||||
{
|
{
|
||||||
std::vector<uint16_t> lut3d;
|
|
||||||
uint32_t nLutEdgeSize3d = 17;
|
|
||||||
lut3d.resize( nLutEdgeSize3d*nLutEdgeSize3d*nLutEdgeSize3d*4 );
|
|
||||||
|
|
||||||
std::vector<uint16_t> lut1d;
|
|
||||||
uint32_t nLutSize1d = 4096;
|
|
||||||
lut1d.resize( nLutSize1d*4 );
|
|
||||||
|
|
||||||
if (!g_ColorMgmtLuts[nInputEOTF].vk_lut1d)
|
if (!g_ColorMgmtLuts[nInputEOTF].vk_lut1d)
|
||||||
g_ColorMgmtLuts[nInputEOTF].vk_lut1d = vulkan_create_1d_lut(4096);
|
g_ColorMgmtLuts[nInputEOTF].vk_lut1d = vulkan_create_1d_lut(nLutSize1d);
|
||||||
|
|
||||||
if (!g_ColorMgmtLuts[nInputEOTF].vk_lut3d)
|
if (!g_ColorMgmtLuts[nInputEOTF].vk_lut3d)
|
||||||
g_ColorMgmtLuts[nInputEOTF].vk_lut3d = vulkan_create_3d_lut(17, 17, 17);
|
g_ColorMgmtLuts[nInputEOTF].vk_lut3d = vulkan_create_3d_lut(nLutEdgeSize3d, nLutEdgeSize3d, nLutEdgeSize3d);
|
||||||
|
|
||||||
displaycolorimetry_t inputColorimetry{};
|
if ( g_ColorMgmtLutsOverride[nInputEOTF].HasLuts() )
|
||||||
colormapping_t colorMapping{};
|
|
||||||
|
|
||||||
tonemapping_t tonemapping{};
|
|
||||||
tonemapping.bUseShaper = true;
|
|
||||||
|
|
||||||
EOTF inputEOTF = static_cast<EOTF>( nInputEOTF );
|
|
||||||
float flGain = 1.f;
|
|
||||||
lut3d_t * pLook = g_ColorMgmtLooks[nInputEOTF].lutEdgeSize > 0 ? &g_ColorMgmtLooks[nInputEOTF] : nullptr;
|
|
||||||
|
|
||||||
if ( inputEOTF == EOTF_Gamma22 )
|
|
||||||
{
|
{
|
||||||
flGain = g_ColorMgmt.pending.flSDRInputGain;
|
memcpy(g_ColorMgmtLuts[nInputEOTF].lut1d, g_ColorMgmtLutsOverride[nInputEOTF].lut1d, sizeof(g_ColorMgmtLutsOverride[nInputEOTF].lut1d));
|
||||||
if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_Gamma22 )
|
memcpy(g_ColorMgmtLuts[nInputEOTF].lut3d, g_ColorMgmtLutsOverride[nInputEOTF].lut3d, sizeof(g_ColorMgmtLutsOverride[nInputEOTF].lut3d));
|
||||||
{
|
|
||||||
// G22 -> G22. Does not matter what the g22 mult is
|
|
||||||
tonemapping.g22_luminance = 1.f;
|
|
||||||
// xwm_log.infof("G22 -> G22");
|
|
||||||
}
|
|
||||||
else if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_PQ )
|
|
||||||
{
|
|
||||||
// G22 -> PQ. SDR content going on an HDR output
|
|
||||||
tonemapping.g22_luminance = g_ColorMgmt.pending.flSDROnHDRBrightness;
|
|
||||||
// xwm_log.infof("G22 -> PQ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// The final display colorimetry is used to build the output mapping, as we want a gamut-aware handling
|
|
||||||
// for sdrGamutWideness indepdendent of the output encoding (for SDR data), and when mapping SDR -> PQ output
|
|
||||||
// we only want to utilize a portion of the gamut the actual display can reproduce
|
|
||||||
buildSDRColorimetry( &inputColorimetry, &colorMapping, g_ColorMgmt.pending.sdrGamutWideness, displayColorimetry );
|
|
||||||
}
|
|
||||||
else if ( inputEOTF == EOTF_PQ )
|
|
||||||
{
|
|
||||||
flGain = g_ColorMgmt.pending.flHDRInputGain;
|
|
||||||
if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_Gamma22 )
|
|
||||||
{
|
|
||||||
// PQ -> G22 Leverage the display's native brightness
|
|
||||||
tonemapping.g22_luminance = g_ColorMgmt.pending.flInternalDisplayBrightness;
|
|
||||||
// xwm_log.infof("PQ -> 2.2 - tonemapping.g22_luminance %f", tonemapping.g22_luminance );
|
|
||||||
}
|
|
||||||
else if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_PQ )
|
|
||||||
{
|
|
||||||
// PQ -> PQ. Better not matter what the g22 mult is
|
|
||||||
tonemapping.g22_luminance = 1.f;
|
|
||||||
// xwm_log.infof("PQ -> PQ");
|
|
||||||
}
|
|
||||||
|
|
||||||
buildPQColorimetry( &inputColorimetry, &colorMapping, displayColorimetry );
|
|
||||||
}
|
|
||||||
|
|
||||||
calcColorTransform( &lut1d[0], nLutSize1d, &lut3d[0], nLutEdgeSize3d, inputColorimetry, inputEOTF,
|
|
||||||
outputEncodingColorimetry, g_ColorMgmt.pending.outputEncodingEOTF,
|
|
||||||
colorMapping, g_ColorMgmt.pending.nightmode, tonemapping, pLook, flGain );
|
|
||||||
|
|
||||||
|
|
||||||
if ( !g_ColorMgmtLutsOverride[nInputEOTF].lut3d.empty() && !g_ColorMgmtLutsOverride[nInputEOTF].lut1d.empty() )
|
|
||||||
{
|
|
||||||
g_ColorMgmtLuts[nInputEOTF].lut1d = g_ColorMgmtLutsOverride[nInputEOTF].lut1d;
|
|
||||||
g_ColorMgmtLuts[nInputEOTF].lut3d = g_ColorMgmtLutsOverride[nInputEOTF].lut3d;
|
|
||||||
}
|
|
||||||
else if ( !lut3d.empty() && !lut1d.empty() )
|
|
||||||
{
|
|
||||||
g_ColorMgmtLuts[nInputEOTF].lut3d = std::move(lut3d);
|
|
||||||
g_ColorMgmtLuts[nInputEOTF].lut1d = std::move(lut1d);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_ColorMgmtLuts[nInputEOTF].reset();
|
displaycolorimetry_t inputColorimetry{};
|
||||||
|
colormapping_t colorMapping{};
|
||||||
|
|
||||||
|
tonemapping_t tonemapping{};
|
||||||
|
tonemapping.bUseShaper = true;
|
||||||
|
|
||||||
|
EOTF inputEOTF = static_cast<EOTF>( nInputEOTF );
|
||||||
|
float flGain = 1.f;
|
||||||
|
lut3d_t * pLook = g_ColorMgmtLooks[nInputEOTF].lutEdgeSize > 0 ? &g_ColorMgmtLooks[nInputEOTF] : nullptr;
|
||||||
|
|
||||||
|
if ( inputEOTF == EOTF_Gamma22 )
|
||||||
|
{
|
||||||
|
flGain = g_ColorMgmt.pending.flSDRInputGain;
|
||||||
|
if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_Gamma22 )
|
||||||
|
{
|
||||||
|
// G22 -> G22. Does not matter what the g22 mult is
|
||||||
|
tonemapping.g22_luminance = 1.f;
|
||||||
|
// xwm_log.infof("G22 -> G22");
|
||||||
|
}
|
||||||
|
else if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_PQ )
|
||||||
|
{
|
||||||
|
// G22 -> PQ. SDR content going on an HDR output
|
||||||
|
tonemapping.g22_luminance = g_ColorMgmt.pending.flSDROnHDRBrightness;
|
||||||
|
// xwm_log.infof("G22 -> PQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The final display colorimetry is used to build the output mapping, as we want a gamut-aware handling
|
||||||
|
// for sdrGamutWideness indepdendent of the output encoding (for SDR data), and when mapping SDR -> PQ output
|
||||||
|
// we only want to utilize a portion of the gamut the actual display can reproduce
|
||||||
|
buildSDRColorimetry( &inputColorimetry, &colorMapping, g_ColorMgmt.pending.sdrGamutWideness, displayColorimetry );
|
||||||
|
}
|
||||||
|
else if ( inputEOTF == EOTF_PQ )
|
||||||
|
{
|
||||||
|
flGain = g_ColorMgmt.pending.flHDRInputGain;
|
||||||
|
if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_Gamma22 )
|
||||||
|
{
|
||||||
|
// PQ -> G22 Leverage the display's native brightness
|
||||||
|
tonemapping.g22_luminance = g_ColorMgmt.pending.flInternalDisplayBrightness;
|
||||||
|
// xwm_log.infof("PQ -> 2.2 - tonemapping.g22_luminance %f", tonemapping.g22_luminance );
|
||||||
|
}
|
||||||
|
else if ( g_ColorMgmt.pending.outputEncodingEOTF == EOTF_PQ )
|
||||||
|
{
|
||||||
|
// PQ -> PQ. Better not matter what the g22 mult is
|
||||||
|
tonemapping.g22_luminance = 1.f;
|
||||||
|
// xwm_log.infof("PQ -> PQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
buildPQColorimetry( &inputColorimetry, &colorMapping, displayColorimetry );
|
||||||
|
}
|
||||||
|
|
||||||
|
calcColorTransform( g_ColorMgmtLuts[nInputEOTF].lut1d, nLutSize1d, g_ColorMgmtLuts[nInputEOTF].lut3d, nLutEdgeSize3d, inputColorimetry, inputEOTF,
|
||||||
|
outputEncodingColorimetry, g_ColorMgmt.pending.outputEncodingEOTF,
|
||||||
|
colorMapping, g_ColorMgmt.pending.nightmode, tonemapping, pLook, flGain );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_ColorMgmtLuts[nInputEOTF].lut3d.empty() && !g_ColorMgmtLuts[nInputEOTF].lut1d.empty())
|
g_ColorMgmtLuts[nInputEOTF].bHasLut1D = true;
|
||||||
vulkan_update_luts(g_ColorMgmtLuts[nInputEOTF].vk_lut1d, g_ColorMgmtLuts[nInputEOTF].vk_lut3d, g_ColorMgmtLuts[nInputEOTF].lut1d.data(), g_ColorMgmtLuts[nInputEOTF].lut3d.data());
|
g_ColorMgmtLuts[nInputEOTF].bHasLut3D = true;
|
||||||
|
|
||||||
|
vulkan_update_luts(g_ColorMgmtLuts[nInputEOTF].vk_lut1d, g_ColorMgmtLuts[nInputEOTF].vk_lut3d, g_ColorMgmtLuts[nInputEOTF].lut1d, g_ColorMgmtLuts[nInputEOTF].lut3d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -378,8 +364,8 @@ bool set_color_mgmt_enabled( bool bEnabled )
|
||||||
bool set_color_3dlut_override(const char *path)
|
bool set_color_3dlut_override(const char *path)
|
||||||
{
|
{
|
||||||
int nLutIndex = EOTF_Gamma22;
|
int nLutIndex = EOTF_Gamma22;
|
||||||
g_ColorMgmtLutsOverride[nLutIndex].lut3d.clear();
|
|
||||||
g_ColorMgmt.pending.externalDirtyCtr++;
|
g_ColorMgmt.pending.externalDirtyCtr++;
|
||||||
|
g_ColorMgmtLutsOverride[nLutIndex].bHasLut3D = false;
|
||||||
|
|
||||||
FILE *f = fopen(path, "rb");
|
FILE *f = fopen(path, "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -396,10 +382,8 @@ bool set_color_3dlut_override(const char *path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = std::vector<uint16_t>(elems);
|
fread(g_ColorMgmtLutsOverride[nLutIndex].lut3d, elems, sizeof(uint16_t), f);
|
||||||
fread(data.data(), elems, sizeof(uint16_t), f);
|
g_ColorMgmtLutsOverride[nLutIndex].bHasLut3D = true;
|
||||||
|
|
||||||
g_ColorMgmtLutsOverride[nLutIndex].lut3d = std::move(data);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -407,8 +391,8 @@ bool set_color_3dlut_override(const char *path)
|
||||||
bool set_color_shaperlut_override(const char *path)
|
bool set_color_shaperlut_override(const char *path)
|
||||||
{
|
{
|
||||||
int nLutIndex = EOTF_Gamma22;
|
int nLutIndex = EOTF_Gamma22;
|
||||||
g_ColorMgmtLutsOverride[nLutIndex].lut1d.clear();
|
|
||||||
g_ColorMgmt.pending.externalDirtyCtr++;
|
g_ColorMgmt.pending.externalDirtyCtr++;
|
||||||
|
g_ColorMgmtLutsOverride[nLutIndex].bHasLut1D = false;
|
||||||
|
|
||||||
FILE *f = fopen(path, "rb");
|
FILE *f = fopen(path, "rb");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -425,10 +409,8 @@ bool set_color_shaperlut_override(const char *path)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = std::vector<uint16_t>(elems);
|
fread(g_ColorMgmtLutsOverride[nLutIndex].lut1d, elems, sizeof(uint16_t), f);
|
||||||
fread(data.data(), elems, sizeof(uint16_t), f);
|
g_ColorMgmtLutsOverride[nLutIndex].bHasLut1D = true;
|
||||||
|
|
||||||
g_ColorMgmtLutsOverride[nLutIndex].lut1d = std::move(data);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2360,10 +2342,11 @@ paint_all(bool async)
|
||||||
|
|
||||||
for (uint32_t i = 0; i < EOTF_Count; i++)
|
for (uint32_t i = 0; i < EOTF_Count; i++)
|
||||||
{
|
{
|
||||||
if (!g_ColorMgmtLuts[i].lut1d.empty())
|
if (g_ColorMgmtLuts[i].HasLuts())
|
||||||
|
{
|
||||||
frameInfo.shaperLut[i] = g_ColorMgmtLuts[i].vk_lut1d;
|
frameInfo.shaperLut[i] = g_ColorMgmtLuts[i].vk_lut1d;
|
||||||
if (!g_ColorMgmtLuts[i].lut3d.empty())
|
|
||||||
frameInfo.lut3D[i] = g_ColorMgmtLuts[i].vk_lut3d;
|
frameInfo.lut3D[i] = g_ColorMgmtLuts[i].vk_lut3d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !BIsNested() && g_bOutputHDREnabled )
|
if ( !BIsNested() && g_bOutputHDREnabled )
|
||||||
|
|
Loading…
Reference in a new issue