From 2b909e1729a5913098dcb67c46404a9ab93221e2 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 9 Jun 2017 10:28:50 -0400 Subject: [PATCH] Add error "handling" to gles3 backend --- include/render/gles3.h | 8 +++++ render/CMakeLists.txt | 1 + render/gles3/renderer.c | 66 ++++++++++++++++++++--------------------- render/gles3/surface.c | 17 +++++------ render/gles3/util.c | 38 ++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 43 deletions(-) create mode 100644 render/gles3/util.c diff --git a/include/render/gles3.h b/include/render/gles3.h index 91b738a6..5efb197e 100644 --- a/include/render/gles3.h +++ b/include/render/gles3.h @@ -1,6 +1,8 @@ #ifndef _WLR_RENDER_GLES2_INTERNAL_H #define _WLR_RENDER_GLES2_INTERNAL_H #include +#include +#include #include #include @@ -15,4 +17,10 @@ extern const GLchar vertex_src[]; extern const GLchar fragment_src_RGB[]; extern const GLchar fragment_src_RGBA[]; +bool _gles3_flush_errors(const char *file, int line); +#define gles3_flush_errors(...) \ + _gles3_flush_errors(__FILE__ + strlen(WLR_SRC_DIR) + 1, __LINE__) + +#define GL_CALL(func) func; gles3_flush_errors() + #endif diff --git a/render/CMakeLists.txt b/render/CMakeLists.txt index aabf42d8..7b863d64 100644 --- a/render/CMakeLists.txt +++ b/render/CMakeLists.txt @@ -5,4 +5,5 @@ add_library(wlr-render STATIC gles3/shaders.c gles3/renderer.c gles3/surface.c + gles3/util.c ) diff --git a/render/gles3/renderer.c b/render/gles3/renderer.c index 8f602fcf..74754d1b 100644 --- a/render/gles3/renderer.c +++ b/render/gles3/renderer.c @@ -17,17 +17,17 @@ static struct { static GLuint vao, vbo, ebo; static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) { - *shader = glCreateShader(type); + *shader = GL_CALL(glCreateShader(type)); int len = strlen(src); - glShaderSource(*shader, 1, &src, &len); - glCompileShader(*shader); + GL_CALL(glShaderSource(*shader, 1, &src, &len)); + GL_CALL(glCompileShader(*shader)); GLint success; - glGetShaderiv(*shader, GL_COMPILE_STATUS, &success); + GL_CALL(glGetShaderiv(*shader, GL_COMPILE_STATUS, &success)); if (success == GL_FALSE) { GLint loglen; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen); + GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen)); GLchar msg[loglen]; - glGetShaderInfoLog(*shader, loglen, &loglen, msg); + GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg)); return false; } return true; @@ -43,12 +43,10 @@ static bool compile_program(const GLchar *vert_src, glDeleteProgram(vertex); return false; } - *program = glCreateProgram(); - glAttachShader(*program, vertex); - glAttachShader(*program, fragment); - glLinkProgram(*program); - glDeleteProgram(vertex); - glDeleteProgram(fragment); + *program = GL_CALL(glCreateProgram()); + GL_CALL(glAttachShader(*program, vertex)); + GL_CALL(glAttachShader(*program, fragment)); + GL_CALL(glLinkProgram(*program)); return true; } @@ -79,21 +77,21 @@ static void init_default_quad() { 1, 2, 3, }; - glGenVertexArrays(1, &vao); - glGenBuffers(1, &vbo); + GL_CALL(glGenVertexArrays(1, &vao)); + GL_CALL(glGenBuffers(1, &vbo)); - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); + GL_CALL(glBindVertexArray(vao)); + GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo)); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)0); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat))); - glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW); + GL_CALL(glEnableVertexAttribArray(0)); + GL_CALL(glEnableVertexAttribArray(1)); + GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)0)); + GL_CALL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat)))); + GL_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW)); - glGenBuffers(1, &ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW); + GL_CALL(glGenBuffers(1, &ebo)); + GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)); + GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW)); } static void init_globals() { @@ -104,11 +102,11 @@ static void init_globals() { static void wlr_gles3_begin(struct wlr_renderer_state *state, struct wlr_output *output) { // TODO: let users customize the clear color? - glClearColor(0.25f, 0.25f, 0.25f, 1); - glClear(GL_COLOR_BUFFER_BIT); + GL_CALL(glClearColor(0.25f, 0.25f, 0.25f, 1)); + GL_CALL(glClear(GL_COLOR_BUFFER_BIT)); int32_t width = output->width; int32_t height = output->height; - glViewport(0, 0, width, height); + GL_CALL(glViewport(0, 0, width, height)); // Note: maybe we should save output projection and remove some of the need // for users to sling matricies themselves } @@ -126,20 +124,20 @@ static bool wlr_gles3_render_surface(struct wlr_renderer_state *state, assert(surface && surface->valid); switch (surface->format) { case GL_RGB: - glUseProgram(shaders.rgb); + GL_CALL(glUseProgram(shaders.rgb)); break; case GL_RGBA: - glUseProgram(shaders.rgba); + GL_CALL(glUseProgram(shaders.rgba)); break; default: return false; } - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + GL_CALL(glBindVertexArray(vao)); + GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo)); + GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)); wlr_surface_bind(surface); - glUniformMatrix4fv(0, 1, GL_TRUE, *matrix); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix)); + GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)); return true; } diff --git a/render/gles3/surface.c b/render/gles3/surface.c index 09d78715..c1fef48e 100644 --- a/render/gles3/surface.c +++ b/render/gles3/surface.c @@ -15,11 +15,10 @@ static bool gles3_surface_attach_pixels(struct wlr_surface_state *surface, surface->wlr_surface->width = width; surface->wlr_surface->height = height; surface->wlr_surface->format = format; - // TODO: Error handling - glGenTextures(1, &surface->tex_id); - glBindTexture(GL_TEXTURE_2D, surface->tex_id); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, - format, GL_UNSIGNED_BYTE, pixels); + GL_CALL(glGenTextures(1, &surface->tex_id)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id)); + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, + format, GL_UNSIGNED_BYTE, pixels)); surface->wlr_surface->valid = true; return true; } @@ -37,10 +36,10 @@ static void gles3_surface_get_matrix(struct wlr_surface_state *surface, } static void gles3_surface_bind(struct wlr_surface_state *surface) { - glActiveTexture(GL_TEXTURE0 + 1); - glBindTexture(GL_TEXTURE_2D, surface->tex_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + GL_CALL(glActiveTexture(GL_TEXTURE0 + 1)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); } static void gles3_surface_destroy(struct wlr_surface_state *surface) { diff --git a/render/gles3/util.c b/render/gles3/util.c new file mode 100644 index 00000000..1f216182 --- /dev/null +++ b/render/gles3/util.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include "common/log.h" +#include "render/gles3.h" + +const char *gles3_strerror(GLenum err) { + switch (err) { + case GL_INVALID_ENUM: + return "Invalid enum"; + case GL_INVALID_VALUE: + return "Invalid value"; + case GL_INVALID_OPERATION: + return "Invalid operation"; + case GL_OUT_OF_MEMORY: + return "Out of memory"; + case GL_INVALID_FRAMEBUFFER_OPERATION: + return "Invalid framebuffer operation"; + default: + return "Unknown error"; + } +} + +bool _gles3_flush_errors(const char *file, int line) { + GLenum err; + bool failure = false; + while ((err = glGetError()) != GL_NO_ERROR) { + failure = true; + if (err == GL_OUT_OF_MEMORY) { + // The OpenGL context is now undefined + _wlr_log(L_ERROR, "[%s:%d] Fatal GL error: out of memory", file, line); + exit(1); + } else { + _wlr_log(L_ERROR, "[%s:%d] GL error %d %s", file, line, err, gles3_strerror(err)); + } + } + return failure; +}