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