4 * Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
5 * Copyright (c) 2011 University of Tuebingen
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * This provides basic shader objects that are used to draw sprites and
33 #define GL_GLEXT_PROTOTYPES
36 #include <GLES2/gl2.h>
37 #include <GLES2/gl2ext.h>
42 #include "static_gl.h"
44 #define LLOG_SUBSYSTEM "gl_shader"
55 /* Clear the GL error stack. The standard says that the error value is just a
56 * single value and no list/stack. However, multiple error fields may be defined
57 * and glGetError() returns only one of them until all are cleared. Hence, we
58 * loop until no more errors are retrieved. */
65 } while (err != GL_NO_ERROR);
68 const char *gl_err_to_str(GLenum err)
74 return "<INVALID_ENUM>";
75 case GL_INVALID_VALUE:
76 return "<INVALID_VALUE>";
77 case GL_INVALID_OPERATION:
78 return "<INVALID_OPERATION>";
79 #ifdef GL_STACK_OVERFLOW
80 case GL_STACK_OVERFLOW:
81 return "<STACK_OVERFLOW>";
83 #ifdef GL_STACK_UNDERFLOW
84 case GL_STACK_UNDERFLOW:
85 return "<STACK_UNDERFLOW>";
87 case GL_OUT_OF_MEMORY:
88 return "<OUT_OF_MEMORY>";
94 /* return true if there is a pending GL error */
95 bool gl_has_error(struct gl_shader *shader)
100 if (err != GL_NO_ERROR) {
101 llog_error(shader, "GL error %d: %s", err, gl_err_to_str(err));
108 static int compile_shader(struct gl_shader *shader, GLenum type,
115 s = glCreateShader(type);
117 llog_warning(shader, "cannot allocate GL shader");
121 glShaderSource(s, 1, &source, NULL);
124 glGetShaderiv(s, GL_COMPILE_STATUS, &status);
125 if (status == GL_FALSE) {
127 glGetShaderInfoLog(s, sizeof(msg), NULL, msg);
128 llog_warning(shader, "cannot compile shader: %s", msg);
135 int gl_shader_new(struct gl_shader **out, const char *vert, const char *frag,
136 char **attr, size_t attr_count, llog_submit_t llog)
138 struct gl_shader *shader;
143 if (!out || !vert || !frag)
146 shader = malloc(sizeof(*shader));
149 memset(shader, 0, sizeof(*shader));
153 llog_debug(shader, "new shader");
155 shader->vshader = compile_shader(shader, GL_VERTEX_SHADER, vert);
156 if (shader->vshader == GL_NONE) {
161 shader->fshader = compile_shader(shader, GL_FRAGMENT_SHADER, frag);
162 if (shader->fshader == GL_NONE) {
167 shader->program = glCreateProgram();
168 glAttachShader(shader->program, shader->vshader);
169 glAttachShader(shader->program, shader->fshader);
171 for (i = 0; i < attr_count; ++i)
172 glBindAttribLocation(shader->program, i, attr[i]);
174 glLinkProgram(shader->program);
175 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
176 if (status == GL_FALSE) {
178 glGetProgramInfoLog(shader->program, sizeof(msg), NULL, msg);
179 llog_warning(shader, "cannot link shader: %s", msg);
184 if (gl_has_error(shader)) {
185 llog_warning(shader, "shader creation failed");
194 glDeleteProgram(shader->program);
195 glDeleteShader(shader->fshader);
197 glDeleteShader(shader->vshader);
203 void gl_shader_ref(struct gl_shader *shader)
205 if (!shader || !shader->ref)
211 void gl_shader_unref(struct gl_shader *shader)
213 if (!shader || !shader->ref || --shader->ref)
216 llog_debug(shader, "free shader");
218 glDeleteProgram(shader->program);
219 glDeleteShader(shader->fshader);
220 glDeleteShader(shader->vshader);
224 GLuint gl_shader_get_uniform(struct gl_shader *shader, const char *name)
229 return glGetUniformLocation(shader->program, name);
232 void gl_shader_use(struct gl_shader *shader)
237 glUseProgram(shader->program);
240 void gl_tex_new(GLuint *tex, size_t num)
244 glGenTextures(num, tex);
246 for (i = 0; i < num; ++i) {
247 glBindTexture(GL_TEXTURE_2D, tex[i]);
248 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
250 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
252 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
254 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
259 void gl_tex_free(GLuint *tex, size_t num)
261 glDeleteTextures(num, tex);
264 void gl_tex_load(GLuint tex, unsigned int width, unsigned int stride,
265 unsigned int height, uint8_t *buf)
267 if (!buf || !width || !height || !stride)
270 /* With OpenGL instead of OpenGLES2 we must use this on linux:
271 * glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA,
272 * GL_UNSIGNED_BYTE, buf);
274 * TODO: Check what kind of stride we need to support here.
275 * GL_UNPACK_ROW_LENGTH only supports specifying a single row but
276 * doesn't allow pixel strides. cairo currently works fine without
277 * touching it but we should probably fix this properly. */
279 glBindTexture(GL_TEXTURE_2D, tex);
280 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); */
281 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
282 GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf);
283 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); */