mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-06-06 07:20:48 +00:00
Generalize SDR white level handling into a color scale
This gives applications better control over how and when light levels are adjusted when working with HDR content and display.
This commit is contained in:
parent
82d89ff4fb
commit
d4caef5b89
34 changed files with 3279 additions and 3234 deletions
|
@ -77,12 +77,20 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
float scRGB_output;
|
||||
float SDR_whitelevel;
|
||||
float HDR_whitelevel;
|
||||
float maxCLL;
|
||||
float color_scale;
|
||||
float unused1;
|
||||
float unused2;
|
||||
float YCbCr_matrix[16];
|
||||
} PixelShaderConstants;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ID3D11Buffer *constants;
|
||||
SDL_bool scRGB_output;
|
||||
float color_scale;
|
||||
const float *shader_params;
|
||||
} PixelShaderState;
|
||||
|
||||
/* Per-vertex data */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -147,7 +155,6 @@ typedef struct
|
|||
size_t vertexBufferSizes[8];
|
||||
ID3D11VertexShader *vertexShader;
|
||||
ID3D11PixelShader *pixelShaders[NUM_SHADERS];
|
||||
ID3D11Buffer *pixelShaderConstants[NUM_SHADERS];
|
||||
int blendModesCount;
|
||||
D3D11_BlendMode *blendModes;
|
||||
ID3D11SamplerState *nearestPixelSampler;
|
||||
|
@ -155,11 +162,6 @@ typedef struct
|
|||
D3D_FEATURE_LEVEL featureLevel;
|
||||
SDL_bool pixelSizeChanged;
|
||||
|
||||
/* HDR state */
|
||||
SDL_bool HDR_enabled;
|
||||
int SDR_whitelevel;
|
||||
int HDR_whitelevel;
|
||||
|
||||
/* Rasterizers */
|
||||
ID3D11RasterizerState *mainRasterizer;
|
||||
ID3D11RasterizerState *clippedRasterizer;
|
||||
|
@ -174,7 +176,7 @@ typedef struct
|
|||
ID3D11RasterizerState *currentRasterizerState;
|
||||
ID3D11BlendState *currentBlendState;
|
||||
D3D11_Shader currentShader;
|
||||
const float *currentShaderParams[NUM_SHADERS];
|
||||
PixelShaderState currentShaderState[NUM_SHADERS];
|
||||
ID3D11ShaderResourceView *currentShaderResource;
|
||||
ID3D11SamplerState *currentSampler;
|
||||
SDL_bool cliprectDirty;
|
||||
|
@ -325,8 +327,8 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer)
|
|||
for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
|
||||
SAFE_RELEASE(data->pixelShaders[i]);
|
||||
}
|
||||
for (i = 0; i < SDL_arraysize(data->pixelShaderConstants); ++i) {
|
||||
SAFE_RELEASE(data->pixelShaderConstants[i]);
|
||||
for (i = 0; i < SDL_arraysize(data->currentShaderState); ++i) {
|
||||
SAFE_RELEASE(data->currentShaderState[i].constants);
|
||||
}
|
||||
SAFE_RELEASE(data->vertexShader);
|
||||
for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) {
|
||||
|
@ -352,7 +354,7 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer)
|
|||
data->currentRasterizerState = NULL;
|
||||
data->currentBlendState = NULL;
|
||||
data->currentShader = SHADER_NONE;
|
||||
SDL_zero(data->currentShaderParams);
|
||||
SDL_zero(data->currentShaderState);
|
||||
data->currentShaderResource = NULL;
|
||||
data->currentSampler = NULL;
|
||||
|
||||
|
@ -380,21 +382,6 @@ static void D3D11_DestroyRenderer(SDL_Renderer *renderer)
|
|||
SDL_free(renderer);
|
||||
}
|
||||
|
||||
static void D3D11_UpdateHDRState(SDL_Renderer *renderer)
|
||||
{
|
||||
D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
|
||||
|
||||
/* Using some placeholder values here... */
|
||||
data->HDR_enabled = SDL_TRUE;
|
||||
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB && data->HDR_enabled) {
|
||||
data->SDR_whitelevel = 200.0f;
|
||||
data->HDR_whitelevel = 400.0f;
|
||||
} else {
|
||||
data->SDR_whitelevel = 80.0f;
|
||||
data->HDR_whitelevel = 80.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_BLEND GetBlendFunc(SDL_BlendFactor factor)
|
||||
{
|
||||
switch (factor) {
|
||||
|
@ -736,8 +723,6 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer)
|
|||
|
||||
SDL_SetProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_D3D11_DEVICE_POINTER, data->d3dDevice);
|
||||
|
||||
D3D11_UpdateHDRState(renderer);
|
||||
|
||||
done:
|
||||
SAFE_RELEASE(d3dDevice);
|
||||
SAFE_RELEASE(d3dContext);
|
||||
|
@ -2139,6 +2124,9 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
const SDL_BlendMode blendMode = cmd->data.draw.blend;
|
||||
ID3D11BlendState *blendState = NULL;
|
||||
SDL_bool updateSubresource = SDL_FALSE;
|
||||
SDL_bool scRGB_output = SDL_RenderingLinearSpace(renderer);
|
||||
float color_scale = cmd->data.draw.color_scale;
|
||||
PixelShaderState *shader_state = &rendererData->currentShaderState[shader];
|
||||
|
||||
if (numShaderResources > 0) {
|
||||
shaderResource = shaderResources[0];
|
||||
|
@ -2212,20 +2200,15 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
rendererData->currentBlendState = blendState;
|
||||
}
|
||||
|
||||
if (!rendererData->pixelShaderConstants[shader] ||
|
||||
shader_params != rendererData->currentShaderParams[shader]) {
|
||||
SAFE_RELEASE(rendererData->pixelShaderConstants[shader]);
|
||||
if (!shader_state->constants ||
|
||||
scRGB_output != shader_state->scRGB_output ||
|
||||
color_scale != shader_state->color_scale ||
|
||||
shader_params != shader_state->shader_params) {
|
||||
SAFE_RELEASE(shader_state->constants);
|
||||
|
||||
PixelShaderConstants constants;
|
||||
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB) {
|
||||
constants.scRGB_output = 1.0f;
|
||||
} else {
|
||||
constants.scRGB_output = 0.0f;
|
||||
}
|
||||
constants.SDR_whitelevel = (float)rendererData->SDR_whitelevel;
|
||||
constants.HDR_whitelevel = (float)rendererData->HDR_whitelevel;
|
||||
constants.maxCLL = 400.0f;
|
||||
|
||||
constants.scRGB_output = (float)scRGB_output;
|
||||
constants.color_scale = color_scale;
|
||||
if (shader_params) {
|
||||
SDL_memcpy(constants.YCbCr_matrix, shader_params, sizeof(constants.YCbCr_matrix));
|
||||
}
|
||||
|
@ -2240,12 +2223,16 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
SDL_zero(data);
|
||||
data.pSysMem = &constants;
|
||||
|
||||
HRESULT result = ID3D11Device_CreateBuffer(rendererData->d3dDevice, &desc, &data, &rendererData->pixelShaderConstants[shader]);
|
||||
HRESULT result = ID3D11Device_CreateBuffer(rendererData->d3dDevice, &desc, &data, &shader_state->constants);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device::CreateBuffer [create shader constants]"), result);
|
||||
return -1;
|
||||
}
|
||||
rendererData->currentShaderParams[shader] = shader_params;
|
||||
shader_state->scRGB_output = scRGB_output;
|
||||
shader_state->color_scale = color_scale;
|
||||
shader_state->shader_params = shader_params;
|
||||
|
||||
/* Force the shader parameters to be re-set */
|
||||
rendererData->currentShader = SHADER_NONE;
|
||||
}
|
||||
if (shader != rendererData->currentShader) {
|
||||
|
@ -2255,8 +2242,8 @@ static int D3D11_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
|||
}
|
||||
}
|
||||
ID3D11DeviceContext_PSSetShader(rendererData->d3dContext, rendererData->pixelShaders[shader], NULL, 0);
|
||||
if (rendererData->pixelShaderConstants[shader]) {
|
||||
ID3D11DeviceContext_PSSetConstantBuffers(rendererData->d3dContext, 0, 1, &rendererData->pixelShaderConstants[shader]);
|
||||
if (rendererData->currentShaderState[shader].constants) {
|
||||
ID3D11DeviceContext_PSSetConstantBuffers(rendererData->d3dContext, 0, 1, &rendererData->currentShaderState[shader].constants);
|
||||
}
|
||||
rendererData->currentShader = shader;
|
||||
}
|
||||
|
@ -2338,8 +2325,7 @@ static void D3D11_InvalidateCachedState(SDL_Renderer *renderer)
|
|||
data->currentRenderTargetView = NULL;
|
||||
data->currentRasterizerState = NULL;
|
||||
data->currentBlendState = NULL;
|
||||
data->currentShader = NUM_SHADERS;
|
||||
SDL_zero(data->currentShaderParams);
|
||||
data->currentShader = SHADER_NONE;
|
||||
data->currentShaderResource = NULL;
|
||||
data->currentSampler = NULL;
|
||||
data->cliprectDirty = SDL_TRUE;
|
||||
|
@ -2401,14 +2387,11 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
|||
SDL_bool convert_color = SDL_RenderingLinearSpace(renderer);
|
||||
SDL_FColor color = cmd->data.color.color;
|
||||
if (convert_color) {
|
||||
float light_scale = (float)rendererData->SDR_whitelevel / 80.0f;
|
||||
|
||||
SDL_ConvertToLinear(&color);
|
||||
|
||||
color.r *= light_scale;
|
||||
color.g *= light_scale;
|
||||
color.b *= light_scale;
|
||||
}
|
||||
color.r *= cmd->data.color.color_scale;
|
||||
color.g *= cmd->data.color.color_scale;
|
||||
color.b *= cmd->data.color.color_scale;
|
||||
ID3D11DeviceContext_ClearRenderTargetView(rendererData->d3dContext, D3D11_GetCurrentRenderTargetView(renderer), &color.r);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue