Added support for SDL_COLORSPACE_BT709_FULL to the hardware renderers

This commit is contained in:
Sam Lantinga
2024-02-04 00:13:11 -08:00
parent ec322bee1c
commit dab77fe29b
55 changed files with 8405 additions and 9470 deletions

View File

@@ -25,6 +25,7 @@
#include <SDL3/SDL_opengl.h>
#include "../SDL_sysrender.h"
#include "SDL_shaders_gl.h"
#include "../../video/SDL_pixels_c.h"
#include "../../SDL_utils_c.h"
#ifdef SDL_PLATFORM_MACOS
@@ -68,6 +69,7 @@ typedef struct
int drawableh;
SDL_BlendMode blend;
GL_Shader shader;
const float *shader_params;
SDL_bool cliprect_enabled_dirty;
SDL_bool cliprect_enabled;
SDL_bool cliprect_dirty;
@@ -132,6 +134,7 @@ typedef struct
GLenum format;
GLenum formattype;
GL_Shader shader;
const float *shader_params;
void *pixels;
int pitch;
SDL_Rect locked_rect;
@@ -662,46 +665,24 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr
#if SDL_HAVE_YUV
if (data->yuv || data->nv12) {
if (SDL_ISCOLORSPACE_YUV_BT601(texture->colorspace)) {
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
if (data->yuv) {
data->shader = SHADER_YUV_BT601;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
data->shader = SHADER_NV12_RG_BT601;
} else {
data->shader = SHADER_NV12_RA_BT601;
}
} else {
data->shader = SHADER_NV21_BT601;
}
if (data->yuv) {
data->shader = SHADER_YUV;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
data->shader = SHADER_NV12_RG;
} else {
if (data->yuv) {
data->shader = SHADER_YUV_JPEG;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
data->shader = SHADER_NV12_JPEG;
} else {
data->shader = SHADER_NV21_JPEG;
}
}
} else if (SDL_ISCOLORSPACE_YUV_BT709(texture->colorspace)) {
if (SDL_ISCOLORSPACE_LIMITED_RANGE(texture->colorspace)) {
if (data->yuv) {
data->shader = SHADER_YUV_BT709;
} else if (texture->format == SDL_PIXELFORMAT_NV12) {
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
data->shader = SHADER_NV12_RG_BT709;
} else {
data->shader = SHADER_NV12_RA_BT709;
}
} else {
data->shader = SHADER_NV21_BT709;
}
} else {
return SDL_SetError("Unsupported YUV conversion mode");
data->shader = SHADER_NV12_RA;
}
} else {
return SDL_SetError("Unsupported YUV conversion mode");
if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", SDL_FALSE)) {
data->shader = SHADER_NV21_RG;
} else {
data->shader = SHADER_NV21_RA;
}
}
data->shader_params = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace);
if (!data->shader_params) {
return SDL_SetError("Unsupported YUV colorspace");
}
}
#endif /* SDL_HAVE_YUV */
@@ -1049,7 +1030,7 @@ static int GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_
return 0;
}
static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader)
static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const GL_Shader shader, const float *shader_params)
{
const SDL_BlendMode blend = cmd->data.draw.blend;
SDL_bool vertex_array;
@@ -1106,9 +1087,11 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const
data->drawstate.blend = blend;
}
if (data->shaders && (shader != data->drawstate.shader)) {
GL_SelectShader(data->shaders, shader);
if (data->shaders &&
(shader != data->drawstate.shader || shader_params != data->drawstate.shader_params)) {
GL_SelectShader(data->shaders, shader, shader_params);
data->drawstate.shader = shader;
data->drawstate.shader_params = shader_params;
}
if (data->drawstate.texturing_dirty || ((cmd->data.draw.texture != NULL) != data->drawstate.texturing)) {
@@ -1163,7 +1146,7 @@ static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd)
SDL_Texture *texture = cmd->data.draw.texture;
const GL_TextureData *texturedata = (GL_TextureData *)texture->driverdata;
SetDrawState(data, cmd, texturedata->shader);
SetDrawState(data, cmd, texturedata->shader, texturedata->shader_params);
if (texture != data->drawstate.texture) {
const GLenum textype = data->textype;
@@ -1325,7 +1308,7 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
case SDL_RENDERCMD_DRAW_LINES:
{
if (SetDrawState(data, cmd, SHADER_SOLID) == 0) {
if (SetDrawState(data, cmd, SHADER_SOLID, NULL) == 0) {
size_t count = cmd->data.draw.count;
const GLfloat *verts = (GLfloat *)(((Uint8 *)vertices) + cmd->data.draw.first);
@@ -1391,7 +1374,7 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
if (thistexture) {
ret = SetCopyState(data, cmd);
} else {
ret = SetDrawState(data, cmd, SHADER_SOLID);
ret = SetDrawState(data, cmd, SHADER_SOLID, NULL);
}
if (ret == 0) {

View File

@@ -52,11 +52,13 @@ struct GL_ShaderContext
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
PFNGLUNIFORM1IARBPROC glUniform1iARB;
PFNGLUNIFORM1FARBPROC glUniform1fARB;
PFNGLUNIFORM3FARBPROC glUniform3fARB;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
SDL_bool GL_ARB_texture_rectangle_supported;
GL_ShaderData shaders[NUM_SHADERS];
const float *shader_params[NUM_SHADERS];
};
/* *INDENT-OFF* */ /* clang-format off */
@@ -81,39 +83,16 @@ struct GL_ShaderContext
" v_texCoord = vec2(gl_MultiTexCoord0);\n" \
"}" \
#define JPEG_SHADER_CONSTANTS \
"// YUV offset \n" \
"const vec3 offset = vec3(0, -0.501960814, -0.501960814);\n" \
"\n" \
"// RGB coefficients \n" \
"const vec3 Rcoeff = vec3(1, 0.000, 1.402);\n" \
"const vec3 Gcoeff = vec3(1, -0.3441, -0.7141);\n" \
"const vec3 Bcoeff = vec3(1, 1.772, 0.000);\n" \
#define BT601_SHADER_CONSTANTS \
"// YUV offset \n" \
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n" \
"\n" \
"// RGB coefficients \n" \
"const vec3 Rcoeff = vec3(1.1644, 0.000, 1.596);\n" \
"const vec3 Gcoeff = vec3(1.1644, -0.3918, -0.813);\n" \
"const vec3 Bcoeff = vec3(1.1644, 2.0172, 0.000);\n" \
#define BT709_SHADER_CONSTANTS \
"// YUV offset \n" \
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n" \
"\n" \
"// RGB coefficients \n" \
"const vec3 Rcoeff = vec3(1.1644, 0.000, 1.7927);\n" \
"const vec3 Gcoeff = vec3(1.1644, -0.2132, -0.5329);\n" \
"const vec3 Bcoeff = vec3(1.1644, 2.1124, 0.000);\n" \
#define YUV_SHADER_PROLOGUE \
"varying vec4 v_color;\n" \
"varying vec2 v_texCoord;\n" \
"uniform sampler2D tex0; // Y \n" \
"uniform sampler2D tex1; // U \n" \
"uniform sampler2D tex2; // V \n" \
"uniform vec3 Yoffset;\n" \
"uniform vec3 Rcoeff;\n" \
"uniform vec3 Gcoeff;\n" \
"uniform vec3 Bcoeff;\n" \
"\n" \
#define YUV_SHADER_BODY \
@@ -133,7 +112,7 @@ struct GL_ShaderContext
" yuv.z = texture2D(tex2, tcoord).r;\n" \
"\n" \
" // Do the color transform \n" \
" yuv += offset;\n" \
" yuv += Yoffset;\n" \
" rgb.r = dot(yuv, Rcoeff);\n" \
" rgb.g = dot(yuv, Gcoeff);\n" \
" rgb.b = dot(yuv, Bcoeff);\n" \
@@ -147,6 +126,10 @@ struct GL_ShaderContext
"varying vec2 v_texCoord;\n" \
"uniform sampler2D tex0; // Y \n" \
"uniform sampler2D tex1; // U/V \n" \
"uniform vec3 Yoffset;\n" \
"uniform vec3 Rcoeff;\n" \
"uniform vec3 Gcoeff;\n" \
"uniform vec3 Bcoeff;\n" \
"\n" \
#define NV12_RA_SHADER_BODY \
@@ -165,7 +148,7 @@ struct GL_ShaderContext
" yuv.yz = texture2D(tex1, tcoord).ra;\n" \
"\n" \
" // Do the color transform \n" \
" yuv += offset;\n" \
" yuv += Yoffset;\n" \
" rgb.r = dot(yuv, Rcoeff);\n" \
" rgb.g = dot(yuv, Gcoeff);\n" \
" rgb.b = dot(yuv, Bcoeff);\n" \
@@ -190,7 +173,7 @@ struct GL_ShaderContext
" yuv.yz = texture2D(tex1, tcoord).rg;\n" \
"\n" \
" // Do the color transform \n" \
" yuv += offset;\n" \
" yuv += Yoffset;\n" \
" rgb.r = dot(yuv, Rcoeff);\n" \
" rgb.g = dot(yuv, Gcoeff);\n" \
" rgb.b = dot(yuv, Bcoeff);\n" \
@@ -199,14 +182,7 @@ struct GL_ShaderContext
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
"}" \
#define NV21_SHADER_PROLOGUE \
"varying vec4 v_color;\n" \
"varying vec2 v_texCoord;\n" \
"uniform sampler2D tex0; // Y \n" \
"uniform sampler2D tex1; // U/V \n" \
"\n" \
#define NV21_SHADER_BODY \
#define NV21_RA_SHADER_BODY \
"\n" \
"void main()\n" \
"{\n" \
@@ -222,7 +198,32 @@ struct GL_ShaderContext
" yuv.yz = texture2D(tex1, tcoord).ar;\n" \
"\n" \
" // Do the color transform \n" \
" yuv += offset;\n" \
" yuv += Yoffset;\n" \
" rgb.r = dot(yuv, Rcoeff);\n" \
" rgb.g = dot(yuv, Gcoeff);\n" \
" rgb.b = dot(yuv, Bcoeff);\n" \
"\n" \
" // That was easy. :) \n" \
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \
"}" \
#define NV21_RG_SHADER_BODY \
"\n" \
"void main()\n" \
"{\n" \
" vec2 tcoord;\n" \
" vec3 yuv, rgb;\n" \
"\n" \
" // Get the Y value \n" \
" tcoord = v_texCoord;\n" \
" yuv.x = texture2D(tex0, tcoord).r;\n" \
"\n" \
" // Get the U and V values \n" \
" tcoord *= UVCoordScale;\n" \
" yuv.yz = texture2D(tex1, tcoord).gr;\n" \
"\n" \
" // Do the color transform \n" \
" yuv += Yoffset;\n" \
" rgb.r = dot(yuv, Rcoeff);\n" \
" rgb.g = dot(yuv, Gcoeff);\n" \
" rgb.b = dot(yuv, Bcoeff);\n" \
@@ -284,104 +285,45 @@ static const char *shader_source[NUM_SHADERS][2] = {
"}"
},
#if SDL_HAVE_YUV
/* SHADER_YUV_JPEG */
/* SHADER_YUV */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
YUV_SHADER_PROLOGUE
JPEG_SHADER_CONSTANTS
YUV_SHADER_BODY
},
/* SHADER_YUV_BT601 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
YUV_SHADER_PROLOGUE
BT601_SHADER_CONSTANTS
YUV_SHADER_BODY
},
/* SHADER_YUV_BT709 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
YUV_SHADER_PROLOGUE
BT709_SHADER_CONSTANTS
YUV_SHADER_BODY
},
/* SHADER_NV12_JPEG */
/* SHADER_NV12_RA */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
JPEG_SHADER_CONSTANTS
NV12_RA_SHADER_BODY
},
/* SHADER_NV12_RA_BT601 */
/* SHADER_NV12_RG */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT601_SHADER_CONSTANTS
NV12_RA_SHADER_BODY
},
/* SHADER_NV12_RG_BT601 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT601_SHADER_CONSTANTS
NV12_RG_SHADER_BODY
},
/* SHADER_NV12_RA_BT709 */
/* SHADER_NV21_RA */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT709_SHADER_CONSTANTS
NV12_RA_SHADER_BODY
NV21_RA_SHADER_BODY
},
/* SHADER_NV12_RG_BT709 */
/* SHADER_NV21_RG */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV12_SHADER_PROLOGUE
BT709_SHADER_CONSTANTS
NV12_RG_SHADER_BODY
},
/* SHADER_NV21_JPEG */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV21_SHADER_PROLOGUE
JPEG_SHADER_CONSTANTS
NV21_SHADER_BODY
},
/* SHADER_NV21_BT601 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV21_SHADER_PROLOGUE
BT601_SHADER_CONSTANTS
NV21_SHADER_BODY
},
/* SHADER_NV21_BT709 */
{
/* vertex shader */
TEXTURE_VERTEX_SHADER,
/* fragment shader */
NV21_SHADER_PROLOGUE
BT709_SHADER_CONSTANTS
NV21_SHADER_BODY
NV21_RG_SHADER_BODY
},
#endif /* SDL_HAVE_YUV */
};
@@ -524,6 +466,7 @@ GL_ShaderContext *GL_CreateShaderContext(void)
ctx->glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB");
ctx->glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB");
ctx->glUniform1fARB = (PFNGLUNIFORM1FARBPROC)SDL_GL_GetProcAddress("glUniform1fARB");
ctx->glUniform3fARB = (PFNGLUNIFORM3FARBPROC)SDL_GL_GetProcAddress("glUniform3fARB");
ctx->glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB");
if (ctx->glGetError &&
ctx->glAttachObjectARB &&
@@ -538,6 +481,7 @@ GL_ShaderContext *GL_CreateShaderContext(void)
ctx->glShaderSourceARB &&
ctx->glUniform1iARB &&
ctx->glUniform1fARB &&
ctx->glUniform3fARB &&
ctx->glUseProgramObjectARB) {
shaders_supported = SDL_TRUE;
}
@@ -560,9 +504,33 @@ GL_ShaderContext *GL_CreateShaderContext(void)
return ctx;
}
void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader)
void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader, const float *shader_params)
{
ctx->glUseProgramObjectARB(ctx->shaders[shader].program);
GLint location;
GLhandleARB program = ctx->shaders[shader].program;
ctx->glUseProgramObjectARB(program);
if (shader_params && shader_params != ctx->shader_params[shader]) {
/* YUV shader params are Yoffset, 0, Rcoeff, 0, Gcoeff, 0, Bcoeff, 0 */
location = ctx->glGetUniformLocationARB(program, "Yoffset");
if (location >= 0) {
ctx->glUniform3fARB(location, shader_params[0], shader_params[1], shader_params[2]);
}
location = ctx->glGetUniformLocationARB(program, "Rcoeff");
if (location >= 0) {
ctx->glUniform3fARB(location, shader_params[4], shader_params[5], shader_params[6]);
}
location = ctx->glGetUniformLocationARB(program, "Gcoeff");
if (location >= 0) {
ctx->glUniform3fARB(location, shader_params[8], shader_params[9], shader_params[10]);
}
location = ctx->glGetUniformLocationARB(program, "Bcoeff");
if (location >= 0) {
ctx->glUniform3fARB(location, shader_params[12], shader_params[13], shader_params[14]);
}
ctx->shader_params[shader] = shader_params;
}
}
void GL_DestroyShaderContext(GL_ShaderContext *ctx)

View File

@@ -34,17 +34,11 @@ typedef enum
SHADER_RGB,
SHADER_RGBA,
#if SDL_HAVE_YUV
SHADER_YUV_JPEG,
SHADER_YUV_BT601,
SHADER_YUV_BT709,
SHADER_NV12_JPEG,
SHADER_NV12_RA_BT601,
SHADER_NV12_RG_BT601,
SHADER_NV12_RA_BT709,
SHADER_NV12_RG_BT709,
SHADER_NV21_JPEG,
SHADER_NV21_BT601,
SHADER_NV21_BT709,
SHADER_YUV,
SHADER_NV12_RA,
SHADER_NV12_RG,
SHADER_NV21_RA,
SHADER_NV21_RG,
#endif
NUM_SHADERS
} GL_Shader;
@@ -52,7 +46,7 @@ typedef enum
typedef struct GL_ShaderContext GL_ShaderContext;
extern GL_ShaderContext *GL_CreateShaderContext(void);
extern void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader);
extern void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader, const float *shader_params);
extern void GL_DestroyShaderContext(GL_ShaderContext *ctx);
#endif /* SDL_shaders_gl_h_ */