4 * Copyright (c) 2011-2013 David Herrmann <dh.herrmann@gmail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * This provides basic shader objects that are used to draw sprites and
32 #define GL_GLEXT_PROTOTYPES
35 #include <GLES2/gl2.h>
36 #include <GLES2/gl2ext.h>
43 #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,
139 struct gl_shader *shader;
144 if (!out || !vert || !frag)
147 shader = malloc(sizeof(*shader));
150 memset(shader, 0, sizeof(*shader));
153 shader->llog_data = llog_data;
155 llog_debug(shader, "new shader");
157 shader->vshader = compile_shader(shader, GL_VERTEX_SHADER, vert);
158 if (shader->vshader == GL_NONE) {
163 shader->fshader = compile_shader(shader, GL_FRAGMENT_SHADER, frag);
164 if (shader->fshader == GL_NONE) {
169 shader->program = glCreateProgram();
170 glAttachShader(shader->program, shader->vshader);
171 glAttachShader(shader->program, shader->fshader);
173 for (i = 0; i < attr_count; ++i)
174 glBindAttribLocation(shader->program, i, attr[i]);
176 glLinkProgram(shader->program);
177 glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
178 if (status == GL_FALSE) {
180 glGetProgramInfoLog(shader->program, sizeof(msg), NULL, msg);
181 llog_warning(shader, "cannot link shader: %s", msg);
186 if (gl_has_error(shader)) {
187 llog_warning(shader, "shader creation failed");
196 glDeleteProgram(shader->program);
197 glDeleteShader(shader->fshader);
199 glDeleteShader(shader->vshader);
205 void gl_shader_ref(struct gl_shader *shader)
207 if (!shader || !shader->ref)
213 void gl_shader_unref(struct gl_shader *shader)
215 if (!shader || !shader->ref || --shader->ref)
218 llog_debug(shader, "free shader");
220 glDeleteProgram(shader->program);
221 glDeleteShader(shader->fshader);
222 glDeleteShader(shader->vshader);
226 GLuint gl_shader_get_uniform(struct gl_shader *shader, const char *name)
231 return glGetUniformLocation(shader->program, name);
234 void gl_shader_use(struct gl_shader *shader)
239 glUseProgram(shader->program);
242 void gl_tex_new(GLuint *tex, size_t num)
246 glGenTextures(num, tex);
248 for (i = 0; i < num; ++i) {
249 glBindTexture(GL_TEXTURE_2D, tex[i]);
250 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
252 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
254 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
256 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
261 void gl_tex_free(GLuint *tex, size_t num)
263 glDeleteTextures(num, tex);
266 void gl_tex_load(GLuint tex, unsigned int width, unsigned int stride,
267 unsigned int height, uint8_t *buf)
269 if (!buf || !width || !height || !stride)
272 /* With OpenGL instead of OpenGLES2 we must use this on linux:
273 * glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA,
274 * GL_UNSIGNED_BYTE, buf);
276 * TODO: Check what kind of stride we need to support here.
277 * GL_UNPACK_ROW_LENGTH only supports specifying a single row but
278 * doesn't allow pixel strides. cairo currently works fine without
279 * touching it but we should probably fix this properly. */
281 glBindTexture(GL_TEXTURE_2D, tex);
282 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); */
283 glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0,
284 GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf);
285 /* glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); */