zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_shaders_gl.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 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_config.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 
35 typedef struct
36 {
38  GLhandleARB vert_shader;
39  GLhandleARB frag_shader;
40 } GL_ShaderData;
41 
42 struct GL_ShaderContext
43 {
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 /*
66  * NOTE: Always use sampler2D, etc here. We'll #define them to the
67  * texture_rectangle versions if we choose to use that extension.
68  */
69 static const char *shader_source[NUM_SHADERS][2] =
70 {
71  /* SHADER_NONE */
72  { NULL, NULL },
73 
74  /* SHADER_SOLID */
75  {
76  /* vertex shader */
77 "varying vec4 v_color;\n"
78 "\n"
79 "void main()\n"
80 "{\n"
81 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
82 " v_color = gl_Color;\n"
83 "}",
84  /* fragment shader */
85 "varying vec4 v_color;\n"
86 "\n"
87 "void main()\n"
88 "{\n"
89 " gl_FragColor = v_color;\n"
90 "}"
91  },
92 
93  /* SHADER_RGB */
94  {
95  /* vertex shader */
96 "varying vec4 v_color;\n"
97 "varying vec2 v_texCoord;\n"
98 "\n"
99 "void main()\n"
100 "{\n"
101 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
102 " v_color = gl_Color;\n"
103 " v_texCoord = vec2(gl_MultiTexCoord0);\n"
104 "}",
105  /* fragment shader */
106 "varying vec4 v_color;\n"
107 "varying vec2 v_texCoord;\n"
108 "uniform sampler2D tex0;\n"
109 "\n"
110 "void main()\n"
111 "{\n"
112 " gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n"
113 "}"
114  },
115 
116  /* SHADER_YV12 */
117  {
118  /* vertex shader */
119 "varying vec4 v_color;\n"
120 "varying vec2 v_texCoord;\n"
121 "\n"
122 "void main()\n"
123 "{\n"
124 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
125 " v_color = gl_Color;\n"
126 " v_texCoord = vec2(gl_MultiTexCoord0);\n"
127 "}",
128  /* fragment shader */
129 "varying vec4 v_color;\n"
130 "varying vec2 v_texCoord;\n"
131 "uniform sampler2D tex0; // Y \n"
132 "uniform sampler2D tex1; // U \n"
133 "uniform sampler2D tex2; // V \n"
134 "\n"
135 "// YUV offset \n"
136 "const vec3 offset = vec3(-0.0625, -0.5, -0.5);\n"
137 "\n"
138 "// RGB coefficients \n"
139 "const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
140 "const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n"
141 "const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n"
142 "\n"
143 "void main()\n"
144 "{\n"
145 " vec2 tcoord;\n"
146 " vec3 yuv, rgb;\n"
147 "\n"
148 " // Get the Y value \n"
149 " tcoord = v_texCoord;\n"
150 " yuv.x = texture2D(tex0, tcoord).r;\n"
151 "\n"
152 " // Get the U and V values \n"
153 " tcoord *= 0.5;\n"
154 " yuv.y = texture2D(tex1, tcoord).r;\n"
155 " yuv.z = texture2D(tex2, tcoord).r;\n"
156 "\n"
157 " // Do the color transform \n"
158 " yuv += offset;\n"
159 " rgb.r = dot(yuv, Rcoeff);\n"
160 " rgb.g = dot(yuv, Gcoeff);\n"
161 " rgb.b = dot(yuv, Bcoeff);\n"
162 "\n"
163 " // That was easy. :) \n"
164 " gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
165 "}"
166  },
167 };
168 
169 static SDL_bool
170 CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, const char *source)
171 {
172  GLint status;
173  const char *sources[2];
174 
175  sources[0] = defines;
176  sources[1] = source;
177 
178  ctx->glShaderSourceARB(shader, SDL_arraysize(sources), sources, NULL);
179  ctx->glCompileShaderARB(shader);
180  ctx->glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
181  if (status == 0) {
182  GLint length;
183  char *info;
184 
185  ctx->glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
186  info = SDL_stack_alloc(char, length+1);
187  ctx->glGetInfoLogARB(shader, length, NULL, info);
189  "Failed to compile shader:\n%s%s\n%s", defines, source, info);
190 #ifdef DEBUG_SHADERS
191  fprintf(stderr,
192  "Failed to compile shader:\n%s%s\n%s", defines, source, info);
193 #endif
194  SDL_stack_free(info);
195 
196  return SDL_FALSE;
197  } else {
198  return SDL_TRUE;
199  }
200 }
201 
202 static SDL_bool
203 CompileShaderProgram(GL_ShaderContext *ctx, int index, GL_ShaderData *data)
204 {
205  const int num_tmus_bound = 4;
206  const char *vert_defines = "";
207  const char *frag_defines = "";
208  int i;
209  GLint location;
210 
211  if (index == SHADER_NONE) {
212  return SDL_TRUE;
213  }
214 
215  ctx->glGetError();
216 
217  /* Make sure we use the correct sampler type for our texture type */
218  if (ctx->GL_ARB_texture_rectangle_supported) {
219  frag_defines =
220 "#define sampler2D sampler2DRect\n"
221 "#define texture2D texture2DRect\n";
222  }
223 
224  /* Create one program object to rule them all */
225  data->program = ctx->glCreateProgramObjectARB();
226 
227  /* Create the vertex shader */
228  data->vert_shader = ctx->glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
229  if (!CompileShader(ctx, data->vert_shader, vert_defines, shader_source[index][0])) {
230  return SDL_FALSE;
231  }
232 
233  /* Create the fragment shader */
234  data->frag_shader = ctx->glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
235  if (!CompileShader(ctx, data->frag_shader, frag_defines, shader_source[index][1])) {
236  return SDL_FALSE;
237  }
238 
239  /* ... and in the darkness bind them */
240  ctx->glAttachObjectARB(data->program, data->vert_shader);
241  ctx->glAttachObjectARB(data->program, data->frag_shader);
242  ctx->glLinkProgramARB(data->program);
243 
244  /* Set up some uniform variables */
245  ctx->glUseProgramObjectARB(data->program);
246  for (i = 0; i < num_tmus_bound; ++i) {
247  char tex_name[10];
248  SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i);
249  location = ctx->glGetUniformLocationARB(data->program, tex_name);
250  if (location >= 0) {
251  ctx->glUniform1iARB(location, i);
252  }
253  }
254  ctx->glUseProgramObjectARB(0);
255 
256  return (ctx->glGetError() == GL_NO_ERROR);
257 }
258 
259 static void
260 DestroyShaderProgram(GL_ShaderContext *ctx, GL_ShaderData *data)
261 {
262  ctx->glDeleteObjectARB(data->vert_shader);
263  ctx->glDeleteObjectARB(data->frag_shader);
264  ctx->glDeleteObjectARB(data->program);
265 }
266 
269 {
271  SDL_bool shaders_supported;
272  int i;
273 
274  ctx = (GL_ShaderContext *)SDL_calloc(1, sizeof(*ctx));
275  if (!ctx) {
276  return NULL;
277  }
278 
279  if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
280  || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
281  ctx->GL_ARB_texture_rectangle_supported = SDL_TRUE;
282  }
283 
284  /* Check for shader support */
285  shaders_supported = SDL_FALSE;
286  if (SDL_GL_ExtensionSupported("GL_ARB_shader_objects") &&
287  SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") &&
288  SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") &&
289  SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) {
290  ctx->glGetError = (GLenum (*)(void)) SDL_GL_GetProcAddress("glGetError");
291  ctx->glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
292  ctx->glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
293  ctx->glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
294  ctx->glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
295  ctx->glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
296  ctx->glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
297  ctx->glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
298  ctx->glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
299  ctx->glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
300  ctx->glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
301  ctx->glUniform1iARB = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
302  ctx->glUniform1fARB = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB");
303  ctx->glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
304  if (ctx->glGetError &&
305  ctx->glAttachObjectARB &&
306  ctx->glCompileShaderARB &&
307  ctx->glCreateProgramObjectARB &&
308  ctx->glCreateShaderObjectARB &&
309  ctx->glDeleteObjectARB &&
310  ctx->glGetInfoLogARB &&
311  ctx->glGetObjectParameterivARB &&
312  ctx->glGetUniformLocationARB &&
313  ctx->glLinkProgramARB &&
314  ctx->glShaderSourceARB &&
315  ctx->glUniform1iARB &&
316  ctx->glUniform1fARB &&
317  ctx->glUseProgramObjectARB) {
318  shaders_supported = SDL_TRUE;
319  }
320  }
321 
322  if (!shaders_supported) {
323  SDL_free(ctx);
324  return NULL;
325  }
326 
327  /* Compile all the shaders */
328  for (i = 0; i < NUM_SHADERS; ++i) {
329  if (!CompileShaderProgram(ctx, i, &ctx->shaders[i])) {
331  return NULL;
332  }
333  }
334 
335  /* We're done! */
336  return ctx;
337 }
338 
339 void
341 {
342  ctx->glUseProgramObjectARB(ctx->shaders[shader].program);
343 }
344 
345 void
347 {
348  int i;
349 
350  for (i = 0; i < NUM_SHADERS; ++i) {
351  DestroyShaderProgram(ctx, &ctx->shaders[i]);
352  }
353  SDL_free(ctx);
354 }
355 
356 #endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */
357 
358 /* vi: set ts=4 sw=4 expandtab: */
#define GL_OBJECT_INFO_LOG_LENGTH_ARB
Definition: glew.h:5612
#define glGetInfoLogARB
Definition: glew.h:5670
#define glLinkProgramARB
Definition: glew.h:5677
#define glUniform1fARB
Definition: glew.h:5679
unsigned int GLhandleARB
Definition: glew.h:5619
DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc)
Get the address of an OpenGL function.
Definition: SDL_video.c:2340
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
#define glCreateShaderObjectARB
Definition: glew.h:5664
GLsizei GLsizei GLuint * shaders
Definition: glew.h:1813
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
unsigned int GLenum
Definition: gl2.h:23
#define NULL
Definition: ftobjs.h:61
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:227
GLint location
Definition: gl2ext.h:1164
SDL_bool
Definition: SDL_stdinc.h:116
GLsizei GLenum * sources
Definition: glew.h:3769
DECLSPEC void SDLCALL SDL_free(void *mem)
#define glCreateProgramObjectARB
Definition: glew.h:5663
#define GL_OBJECT_COMPILE_STATUS_ARB
Definition: glew.h:5609
#define glUniform1iARB
Definition: glew.h:5681
struct GL_ShaderContext GL_ShaderContext
#define glAttachObjectARB
Definition: glew.h:5661
#define glCompileShaderARB
Definition: glew.h:5662
void GL_DestroyShaderContext(GL_ShaderContext *ctx)
#define glDeleteObjectARB
Definition: glew.h:5665
#define GL_NO_ERROR
Definition: gl2.h:157
GLuint shader
Definition: glew.h:1799
GL_Shader
GLsizei GLsizei * length
Definition: gl2ext.h:792
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
GL_ShaderContext * GL_CreateShaderContext()
#define glGetObjectParameterivARB
Definition: glew.h:5672
#define glUseProgramObjectARB
Definition: glew.h:5698
GLuint index
Definition: glew.h:1800
GLbitfield GLuint program
Definition: gl2ext.h:1203
#define glShaderSourceARB
Definition: glew.h:5678
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
int GLint
Definition: gl2.h:28
#define glGetError
Definition: gl_mangle.h:643
DECLSPEC void SDLCALL SDL_LogError(int category, const char *fmt,...)
Log a message with SDL_LOG_PRIORITY_ERROR.
Definition: SDL_log.c:223
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:226
#define GL_FRAGMENT_SHADER_ARB
Definition: glew.h:4005
#define glGetUniformLocationARB
Definition: glew.h:5674
DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char *extension)
Return true if an OpenGL extension is supported for the current context.
Definition: SDL_video.c:2385
int i
Definition: pngrutil.c:1377
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:994
void GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader)
#define GL_VERTEX_SHADER_ARB
Definition: glew.h:7146
EGLContext ctx
Definition: eglext.h:87