mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Add error "handling" to gles3 backend
This commit is contained in:
		
							parent
							
								
									63c3faa006
								
							
						
					
					
						commit
						2b909e1729
					
				
					 5 changed files with 87 additions and 43 deletions
				
			
		| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
#ifndef _WLR_RENDER_GLES2_INTERNAL_H
 | 
			
		||||
#define _WLR_RENDER_GLES2_INTERNAL_H
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <GLES3/gl3.h>
 | 
			
		||||
#include <wlr/render.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,4 +5,5 @@ add_library(wlr-render STATIC
 | 
			
		|||
    gles3/shaders.c
 | 
			
		||||
    gles3/renderer.c
 | 
			
		||||
    gles3/surface.c
 | 
			
		||||
    gles3/util.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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										38
									
								
								render/gles3/util.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								render/gles3/util.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
#include <stdlib.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <GLES3/gl3.h>
 | 
			
		||||
#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;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue