Atlas - SDL_shaders_gl.c

Home / ext / SDL2 / src / render / opengl Lines: 139 | Size: 20528 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED 24 25#include "SDL_stdinc.h" 26#include "SDL_log.h" 27#include "SDL_opengl.h" 28#include "SDL_video.h" 29#include "SDL_shaders_gl.h" 30 31/* OpenGL shader implementation */ 32 33/* #define DEBUG_SHADERS */ 34 35typedef struct 36{ 37 GLhandleARB program; 38 GLhandleARB vert_shader; 39 GLhandleARB frag_shader; 40} GL_ShaderData; 41 42struct GL_ShaderContext 43{ 44 GLenum (*glGetError)(void); 45 46 PFNGLATTACHOBJECTARBPROC glAttachObjectARB; 47 PFNGLCOMPILESHADERARBPROC glCompileShaderARB; 48 PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; 49 PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; 50 PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; 51 PFNGLGETINFOLOGARBPROC glGetInfoLogARB; 52 PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; 53 PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; 54 PFNGLLINKPROGRAMARBPROC glLinkProgramARB; 55 PFNGLSHADERSOURCEARBPROC glShaderSourceARB; 56 PFNGLUNIFORM1IARBPROC glUniform1iARB; 57 PFNGLUNIFORM1FARBPROC glUniform1fARB; 58 PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; 59 60 SDL_bool GL_ARB_texture_rectangle_supported; 61 62 GL_ShaderData shaders[NUM_SHADERS]; 63}; 64 65#define COLOR_VERTEX_SHADER \ 66"varying vec4 v_color;\n" \ 67"\n" \ 68"void main()\n" \ 69"{\n" \ 70" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" \ 71" v_color = gl_Color;\n" \ 72"}" \ 73 74#define TEXTURE_VERTEX_SHADER \ 75"varying vec4 v_color;\n" \ 76"varying vec2 v_texCoord;\n" \ 77"\n" \ 78"void main()\n" \ 79"{\n" \ 80" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" \ 81" v_color = gl_Color;\n" \ 82" v_texCoord = vec2(gl_MultiTexCoord0);\n" \ 83"}" \ 84 85#define JPEG_SHADER_CONSTANTS \ 86"// YUV offset \n" \ 87"const vec3 offset = vec3(0, -0.501960814, -0.501960814);\n" \ 88"\n" \ 89"// RGB coefficients \n" \ 90"const vec3 Rcoeff = vec3(1, 0.000, 1.402);\n" \ 91"const vec3 Gcoeff = vec3(1, -0.3441, -0.7141);\n" \ 92"const vec3 Bcoeff = vec3(1, 1.772, 0.000);\n" \ 93 94#define BT601_SHADER_CONSTANTS \ 95"// YUV offset \n" \ 96"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n" \ 97"\n" \ 98"// RGB coefficients \n" \ 99"const vec3 Rcoeff = vec3(1.1644, 0.000, 1.596);\n" \ 100"const vec3 Gcoeff = vec3(1.1644, -0.3918, -0.813);\n" \ 101"const vec3 Bcoeff = vec3(1.1644, 2.0172, 0.000);\n" \ 102 103#define BT709_SHADER_CONSTANTS \ 104"// YUV offset \n" \ 105"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n" \ 106"\n" \ 107"// RGB coefficients \n" \ 108"const vec3 Rcoeff = vec3(1.1644, 0.000, 1.7927);\n" \ 109"const vec3 Gcoeff = vec3(1.1644, -0.2132, -0.5329);\n" \ 110"const vec3 Bcoeff = vec3(1.1644, 2.1124, 0.000);\n" \ 111 112#define YUV_SHADER_PROLOGUE \ 113"varying vec4 v_color;\n" \ 114"varying vec2 v_texCoord;\n" \ 115"uniform sampler2D tex0; // Y \n" \ 116"uniform sampler2D tex1; // U \n" \ 117"uniform sampler2D tex2; // V \n" \ 118"\n" \ 119 120#define YUV_SHADER_BODY \ 121"\n" \ 122"void main()\n" \ 123"{\n" \ 124" vec2 tcoord;\n" \ 125" vec3 yuv, rgb;\n" \ 126"\n" \ 127" // Get the Y value \n" \ 128" tcoord = v_texCoord;\n" \ 129" yuv.x = texture2D(tex0, tcoord).r;\n" \ 130"\n" \ 131" // Get the U and V values \n" \ 132" tcoord *= UVCoordScale;\n" \ 133" yuv.y = texture2D(tex1, tcoord).r;\n" \ 134" yuv.z = texture2D(tex2, tcoord).r;\n" \ 135"\n" \ 136" // Do the color transform \n" \ 137" yuv += offset;\n" \ 138" rgb.r = dot(yuv, Rcoeff);\n" \ 139" rgb.g = dot(yuv, Gcoeff);\n" \ 140" rgb.b = dot(yuv, Bcoeff);\n" \ 141"\n" \ 142" // That was easy. :) \n" \ 143" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \ 144"}" \ 145 146#define NV12_SHADER_PROLOGUE \ 147"varying vec4 v_color;\n" \ 148"varying vec2 v_texCoord;\n" \ 149"uniform sampler2D tex0; // Y \n" \ 150"uniform sampler2D tex1; // U/V \n" \ 151"\n" \ 152 153#define NV12_SHADER_BODY \ 154"\n" \ 155"void main()\n" \ 156"{\n" \ 157" vec2 tcoord;\n" \ 158" vec3 yuv, rgb;\n" \ 159"\n" \ 160" // Get the Y value \n" \ 161" tcoord = v_texCoord;\n" \ 162" yuv.x = texture2D(tex0, tcoord).r;\n" \ 163"\n" \ 164" // Get the U and V values \n" \ 165" tcoord *= UVCoordScale;\n" \ 166" yuv.yz = texture2D(tex1, tcoord).ra;\n" \ 167"\n" \ 168" // Do the color transform \n" \ 169" yuv += offset;\n" \ 170" rgb.r = dot(yuv, Rcoeff);\n" \ 171" rgb.g = dot(yuv, Gcoeff);\n" \ 172" rgb.b = dot(yuv, Bcoeff);\n" \ 173"\n" \ 174" // That was easy. :) \n" \ 175" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \ 176"}" \ 177 178#define NV21_SHADER_PROLOGUE \ 179"varying vec4 v_color;\n" \ 180"varying vec2 v_texCoord;\n" \ 181"uniform sampler2D tex0; // Y \n" \ 182"uniform sampler2D tex1; // U/V \n" \ 183"\n" \ 184 185#define NV21_SHADER_BODY \ 186"\n" \ 187"void main()\n" \ 188"{\n" \ 189" vec2 tcoord;\n" \ 190" vec3 yuv, rgb;\n" \ 191"\n" \ 192" // Get the Y value \n" \ 193" tcoord = v_texCoord;\n" \ 194" yuv.x = texture2D(tex0, tcoord).r;\n" \ 195"\n" \ 196" // Get the U and V values \n" \ 197" tcoord *= UVCoordScale;\n" \ 198" yuv.yz = texture2D(tex1, tcoord).ar;\n" \ 199"\n" \ 200" // Do the color transform \n" \ 201" yuv += offset;\n" \ 202" rgb.r = dot(yuv, Rcoeff);\n" \ 203" rgb.g = dot(yuv, Gcoeff);\n" \ 204" rgb.b = dot(yuv, Bcoeff);\n" \ 205"\n" \ 206" // That was easy. :) \n" \ 207" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" \ 208"}" \ 209 210/* 211 * NOTE: Always use sampler2D, etc here. We'll #define them to the 212 * texture_rectangle versions if we choose to use that extension. 213 */ 214static const char *shader_source[NUM_SHADERS][2] = 215{ 216 /* SHADER_NONE */ 217 { NULL, NULL }, 218 219 /* SHADER_SOLID */ 220 { 221 /* vertex shader */ 222 COLOR_VERTEX_SHADER, 223 /* fragment shader */ 224"varying vec4 v_color;\n" 225"\n" 226"void main()\n" 227"{\n" 228" gl_FragColor = v_color;\n" 229"}" 230 }, 231 232 /* SHADER_RGB */ 233 { 234 /* vertex shader */ 235 TEXTURE_VERTEX_SHADER, 236 /* fragment shader */ 237"varying vec4 v_color;\n" 238"varying vec2 v_texCoord;\n" 239"uniform sampler2D tex0;\n" 240"\n" 241"void main()\n" 242"{\n" 243" gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n" 244"}" 245 }, 246 247 /* SHADER_YUV_JPEG */ 248 { 249 /* vertex shader */ 250 TEXTURE_VERTEX_SHADER, 251 /* fragment shader */ 252 YUV_SHADER_PROLOGUE 253 JPEG_SHADER_CONSTANTS 254 YUV_SHADER_BODY 255 }, 256 /* SHADER_YUV_BT601 */ 257 { 258 /* vertex shader */ 259 TEXTURE_VERTEX_SHADER, 260 /* fragment shader */ 261 YUV_SHADER_PROLOGUE 262 BT601_SHADER_CONSTANTS 263 YUV_SHADER_BODY 264 }, 265 /* SHADER_YUV_BT709 */ 266 { 267 /* vertex shader */ 268 TEXTURE_VERTEX_SHADER, 269 /* fragment shader */ 270 YUV_SHADER_PROLOGUE 271 BT709_SHADER_CONSTANTS 272 YUV_SHADER_BODY 273 }, 274 /* SHADER_NV12_JPEG */ 275 { 276 /* vertex shader */ 277 TEXTURE_VERTEX_SHADER, 278 /* fragment shader */ 279 NV12_SHADER_PROLOGUE 280 JPEG_SHADER_CONSTANTS 281 NV12_SHADER_BODY 282 }, 283 /* SHADER_NV12_BT601 */ 284 { 285 /* vertex shader */ 286 TEXTURE_VERTEX_SHADER, 287 /* fragment shader */ 288 NV12_SHADER_PROLOGUE 289 BT601_SHADER_CONSTANTS 290 NV12_SHADER_BODY 291 }, 292 /* SHADER_NV12_BT709 */ 293 { 294 /* vertex shader */ 295 TEXTURE_VERTEX_SHADER, 296 /* fragment shader */ 297 NV12_SHADER_PROLOGUE 298 BT709_SHADER_CONSTANTS 299 NV12_SHADER_BODY 300 }, 301 /* SHADER_NV21_JPEG */ 302 { 303 /* vertex shader */ 304 TEXTURE_VERTEX_SHADER, 305 /* fragment shader */ 306 NV21_SHADER_PROLOGUE 307 JPEG_SHADER_CONSTANTS 308 NV21_SHADER_BODY 309 }, 310 /* SHADER_NV21_BT601 */ 311 { 312 /* vertex shader */ 313 TEXTURE_VERTEX_SHADER, 314 /* fragment shader */ 315 NV21_SHADER_PROLOGUE 316 BT601_SHADER_CONSTANTS 317 NV21_SHADER_BODY 318 }, 319 /* SHADER_NV21_BT709 */ 320 { 321 /* vertex shader */ 322 TEXTURE_VERTEX_SHADER, 323 /* fragment shader */ 324 NV21_SHADER_PROLOGUE 325 BT709_SHADER_CONSTANTS 326 NV21_SHADER_BODY 327 }, 328}; 329 330static SDL_bool 331CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, const char *source) 332{ 333 GLint status; 334 const char *sources[2]; 335 336 sources[0] = defines; 337 sources[1] = source; 338 339 ctx->glShaderSourceARB(shader, SDL_arraysize(sources), sources, NULL); 340 ctx->glCompileShaderARB(shader); 341 ctx->glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status); 342 if (status == 0) { 343 GLint length; 344 char *info; 345 346 ctx->glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); 347 info = SDL_stack_alloc(char, length+1); 348 ctx->glGetInfoLogARB(shader, length, NULL, info); 349 SDL_LogError(SDL_LOG_CATEGORY_RENDER, 350 "Failed to compile shader:\n%s%s\n%s", defines, source, info); 351#ifdef DEBUG_SHADERS 352 fprintf(stderr, 353 "Failed to compile shader:\n%s%s\n%s", defines, source, info); 354#endif 355 SDL_stack_free(info); 356 357 return SDL_FALSE; 358 } else { 359 return SDL_TRUE; 360 } 361} 362 363static SDL_bool 364CompileShaderProgram(GL_ShaderContext *ctx, int index, GL_ShaderData *data) 365{ 366 const int num_tmus_bound = 4; 367 const char *vert_defines = ""; 368 const char *frag_defines = ""; 369 int i; 370 GLint location; 371 372 if (index == SHADER_NONE) { 373 return SDL_TRUE; 374 } 375 376 ctx->glGetError(); 377 378 /* Make sure we use the correct sampler type for our texture type */ 379 if (ctx->GL_ARB_texture_rectangle_supported) { 380 frag_defines = 381"#define sampler2D sampler2DRect\n" 382"#define texture2D texture2DRect\n" 383"#define UVCoordScale 0.5\n"; 384 } else { 385 frag_defines = 386"#define UVCoordScale 1.0\n"; 387 } 388 389 /* Create one program object to rule them all */ 390 data->program = ctx->glCreateProgramObjectARB(); 391 392 /* Create the vertex shader */ 393 data->vert_shader = ctx->glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); 394 if (!CompileShader(ctx, data->vert_shader, vert_defines, shader_source[index][0])) { 395 return SDL_FALSE; 396 } 397 398 /* Create the fragment shader */ 399 data->frag_shader = ctx->glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); 400 if (!CompileShader(ctx, data->frag_shader, frag_defines, shader_source[index][1])) { 401 return SDL_FALSE; 402 } 403 404 /* ... and in the darkness bind them */ 405 ctx->glAttachObjectARB(data->program, data->vert_shader); 406 ctx->glAttachObjectARB(data->program, data->frag_shader); 407 ctx->glLinkProgramARB(data->program); 408 409 /* Set up some uniform variables */ 410 ctx->glUseProgramObjectARB(data->program); 411 for (i = 0; i < num_tmus_bound; ++i) { 412 char tex_name[10]; 413 SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i); 414 location = ctx->glGetUniformLocationARB(data->program, tex_name); 415 if (location >= 0) { 416 ctx->glUniform1iARB(location, i); 417 } 418 } 419 ctx->glUseProgramObjectARB(0); 420 421 return (ctx->glGetError() == GL_NO_ERROR); 422} 423 424static void 425DestroyShaderProgram(GL_ShaderContext *ctx, GL_ShaderData *data) 426{ 427 ctx->glDeleteObjectARB(data->vert_shader); 428 ctx->glDeleteObjectARB(data->frag_shader); 429 ctx->glDeleteObjectARB(data->program); 430} 431 432GL_ShaderContext * 433GL_CreateShaderContext(void) 434{ 435 GL_ShaderContext *ctx; 436 SDL_bool shaders_supported; 437 int i; 438 439 ctx = (GL_ShaderContext *)SDL_calloc(1, sizeof(*ctx)); 440 if (!ctx) { 441 return NULL; 442 } 443 444 if (!SDL_GL_ExtensionSupported("GL_ARB_texture_non_power_of_two") && 445 (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") || 446 SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle"))) { 447 ctx->GL_ARB_texture_rectangle_supported = SDL_TRUE; 448 } 449 450 /* Check for shader support */ 451 shaders_supported = SDL_FALSE; 452 if (SDL_GL_ExtensionSupported("GL_ARB_shader_objects") && 453 SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") && 454 SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") && 455 SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) { 456 ctx->glGetError = (GLenum (*)(void)) SDL_GL_GetProcAddress("glGetError"); 457 ctx->glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB"); 458 ctx->glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB"); 459 ctx->glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB"); 460 ctx->glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB"); 461 ctx->glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB"); 462 ctx->glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB"); 463 ctx->glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB"); 464 ctx->glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB"); 465 ctx->glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB"); 466 ctx->glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB"); 467 ctx->glUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB"); 468 ctx->glUniform1fARB = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB"); 469 ctx->glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB"); 470 if (ctx->glGetError && 471 ctx->glAttachObjectARB && 472 ctx->glCompileShaderARB && 473 ctx->glCreateProgramObjectARB && 474 ctx->glCreateShaderObjectARB && 475 ctx->glDeleteObjectARB && 476 ctx->glGetInfoLogARB && 477 ctx->glGetObjectParameterivARB && 478 ctx->glGetUniformLocationARB && 479 ctx->glLinkProgramARB && 480 ctx->glShaderSourceARB && 481 ctx->glUniform1iARB && 482 ctx->glUniform1fARB && 483 ctx->glUseProgramObjectARB) { 484 shaders_supported = SDL_TRUE; 485 } 486 } 487 488 if (!shaders_supported) { 489 SDL_free(ctx); 490 return NULL; 491 } 492 493 /* Compile all the shaders */ 494 for (i = 0; i < NUM_SHADERS; ++i) { 495 if (!CompileShaderProgram(ctx, i, &ctx->shaders[i])) { 496 GL_DestroyShaderContext(ctx); 497 return NULL; 498 } 499 } 500 501 /* We're done! */ 502 return ctx; 503} 504 505void 506GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader) 507{ 508 ctx->glUseProgramObjectARB(ctx->shaders[shader].program); 509} 510 511void 512GL_DestroyShaderContext(GL_ShaderContext *ctx) 513{ 514 int i; 515 516 for (i = 0; i < NUM_SHADERS; ++i) { 517 DestroyShaderProgram(ctx, &ctx->shaders[i]); 518 } 519 SDL_free(ctx); 520} 521 522#endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */ 523 524/* vi: set ts=4 sw=4 expandtab: */ 525
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.