Added the concept of colorspace to the SDL renderer

This allows color operations to happen in linear space between sRGB input and sRGB output. This is currently supported on the direct3d11, direct3d12 and opengl renderers.

This is a good resource on blending in linear space vs sRGB space:
https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/

Also added testcolorspace to verify colorspace changes
This commit is contained in:
Sam Lantinga 2024-01-29 18:32:27 -08:00
parent 554f0625d3
commit f257eb4481
9 changed files with 648 additions and 40 deletions

View file

@ -49,8 +49,6 @@
http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html
*/
static const float inv255f = 1.0f / 255.0f;
typedef struct GL_FBOList GL_FBOList;
struct GL_FBOList
@ -403,19 +401,27 @@ static SDL_bool GL_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blend
return SDL_TRUE;
}
static SDL_bool convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
static SDL_bool convert_format(Uint32 pixel_format, Uint32 colorspace, SDL_bool colorspace_conversion,
GLint *internalFormat, GLenum *format, GLenum *type)
{
switch (pixel_format) {
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_XRGB8888:
*internalFormat = GL_RGBA8;
if (colorspace_conversion && colorspace == SDL_COLORSPACE_SRGB) {
*internalFormat = GL_SRGB8_ALPHA8;
} else {
*internalFormat = GL_RGBA8;
}
*format = GL_BGRA;
*type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_XBGR8888:
*internalFormat = GL_RGBA8;
if (colorspace_conversion && colorspace == SDL_COLORSPACE_SRGB) {
*internalFormat = GL_SRGB8_ALPHA8;
} else {
*internalFormat = GL_RGBA8;
}
*format = GL_RGBA;
*type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
@ -460,8 +466,8 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr
return SDL_SetError("Render targets not supported by OpenGL");
}
if (!convert_format(renderdata, texture->format, &internalFormat,
&format, &type)) {
if (!convert_format(texture->format, texture->colorspace, renderer->colorspace_conversion,
&internalFormat, &format, &type)) {
return SDL_SetError("Texture format %s not supported by OpenGL",
SDL_GetPixelFormatName(texture->format));
}
@ -1475,7 +1481,8 @@ static int GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
GL_ActivateRenderer(renderer);
if (!convert_format(data, temp_format, &internalFormat, &format, &type)) {
if (!convert_format(temp_format, renderer->input_colorspace, renderer->colorspace_conversion,
&internalFormat, &format, &type)) {
return SDL_SetError("Texture format %s not supported by OpenGL",
SDL_GetPixelFormatName(temp_format));
}
@ -1709,6 +1716,8 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
goto error;
}
SDL_SetupRendererColorspace(renderer, create_props);
renderer->WindowEvent = GL_WindowEvent;
renderer->SupportsBlendMode = GL_SupportsBlendMode;
renderer->CreateTexture = GL_CreateTexture;
@ -1910,6 +1919,9 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
data->glDisable(data->textype);
data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
if (renderer->colorspace_conversion && renderer->output_colorspace == SDL_COLORSPACE_SRGB) {
data->glEnable(GL_FRAMEBUFFER_SRGB);
}
/* This ended up causing video discrepancies between OpenGL and Direct3D */
/* data->glEnable(GL_LINE_SMOOTH); */