From 74adfe0cbca300e73774c6e0aa9b3c53a5e5b57b Mon Sep 17 00:00:00 2001 From: Phil Jones Date: Sun, 31 Oct 2021 16:47:03 +0000 Subject: Add HiDPI support and lots of cleanup. --- src/gl.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 163 insertions(+), 16 deletions(-) (limited to 'src/gl.c') diff --git a/src/gl.c b/src/gl.c index 94262b4..74e7605 100644 --- a/src/gl.c +++ b/src/gl.c @@ -11,9 +11,26 @@ static void load_shader(GLuint shader, const char *filename); static GLuint create_shader_program(const char *vert, const char *frag); +static void GLAPIENTRY MessageCallback( + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam); +static const char *gl_debug_source_string(GLenum type); +static const char *gl_debug_type_string(GLenum type); +static const char *gl_debug_severity_string(GLenum type); + void gl_initialise(struct gl *gl, struct image *texture) { +#ifdef DEBUG + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback(MessageCallback, 0); +#endif if (texture == NULL) { return; } @@ -37,24 +54,44 @@ void gl_initialise(struct gl *gl, struct image *texture) glGenBuffers(1, &gl->vbo); glBindBuffer(GL_ARRAY_BUFFER, gl->vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glBufferData( + GL_ARRAY_BUFFER, + sizeof(vertices), + vertices, + GL_STATIC_DRAW); - /* Create a vertex array and enable vertex attributes for the shaders. */ + /* + * Create a vertex array and enable vertex attributes for the shaders. + */ glGenVertexArrays(1, &gl->vao); glBindVertexArray(gl->vao); GLint posAttrib = glGetAttribLocation(gl->shader, "position"); - glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0); + glVertexAttribPointer( + posAttrib, + 2, + GL_FLOAT, + GL_FALSE, + 4*sizeof(float), + 0); glEnableVertexAttribArray(posAttrib); GLint texAttrib = glGetAttribLocation(gl->shader, "texcoord"); - glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), (void *)(2*sizeof(float))); + glVertexAttribPointer( + texAttrib, + 2, + GL_FLOAT, + GL_FALSE, + 4*sizeof(float), + (void *)(2*sizeof(float))); glEnableVertexAttribArray(texAttrib); glBindVertexArray(0); - /* Create the element buffer object that will actually be drawn via - * glDrawElements(). */ + /* + * Create the element buffer object that will actually be drawn via + * glDrawElements(). + */ GLuint elements[] = { 0, 1, 2, 2, 3, 0 @@ -62,20 +99,36 @@ void gl_initialise(struct gl *gl, struct image *texture) glGenBuffers(1, &gl->ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl->ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW); + glBufferData( + GL_ELEMENT_ARRAY_BUFFER, + sizeof(elements), + elements, + GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); /* Create the texture we'll draw to */ glGenTextures(1, &gl->texture); glBindTexture(GL_TEXTURE_2D, gl->texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->width, texture->height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, (GLvoid *)texture->buffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA, + texture->width, + texture->height, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + (GLvoid *)texture->buffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + /* + * On little-endian processors, textures from Cairo have to have their + * red and blue channels swapped. + */ if (texture->swizzle) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN); @@ -94,11 +147,26 @@ void gl_clear(struct gl *gl, struct color *color) glClear(GL_COLOR_BUFFER_BIT); } -void gl_draw_texture(struct gl *gl, struct image *texture, int32_t x, int32_t y, int32_t width, int32_t height) +void gl_draw_texture( + struct gl *gl, + struct image *texture, + int32_t x, + int32_t y, + int32_t width, + int32_t height) { if (texture->redraw) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->width, texture->height, GL_RGBA, - GL_UNSIGNED_BYTE, (GLvoid *)texture->buffer); + glTexSubImage2D( + GL_TEXTURE_2D, + 0, + 0, + 0, + texture->width, + texture->height, + GL_RGBA, + GL_UNSIGNED_BYTE, + (GLvoid *)texture->buffer); + glGetError(); texture->redraw = false; } @@ -111,17 +179,20 @@ void load_shader(GLuint shader, const char *filename) errno = 0; FILE *fp = fopen(filename, "rb"); if (!fp) { - log_error("Failed to load shader %s: %s.\n", filename, strerror(errno)); + log_error("Failed to load shader %s: %s.\n", + filename, strerror(errno)); exit(EXIT_FAILURE); } if (fseek(fp, 0, SEEK_END) != 0) { - log_error("Failed to load shader %s: %s.\n", filename, strerror(errno)); + log_error("Failed to load shader %s: %s.\n", + filename, strerror(errno)); fclose(fp); exit(EXIT_FAILURE); } long size = ftell(fp); if (size <= 0) { - log_error("Failed to load shader %s: %s.\n", filename, strerror(errno)); + log_error("Failed to load shader %s: %s.\n", + filename, strerror(errno)); fclose(fp); exit(EXIT_FAILURE); } @@ -129,7 +200,8 @@ void load_shader(GLuint shader, const char *filename) GLchar *source = malloc(usize + 1); rewind(fp); if (fread(source, 1, usize, fp) != usize) { - log_error("Failed to load shader %s: %s.\n", filename, strerror(errno)); + log_error("Failed to load shader %s: %s.\n", + filename, strerror(errno)); fclose(fp); exit(EXIT_FAILURE); } @@ -171,3 +243,78 @@ GLuint create_shader_program(const char *vert, const char *frag) glLinkProgram(shader); return shader; } + +void GLAPIENTRY MessageCallback( + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) +{ + log_debug("Message from OpenGL:\n"); + log_debug("\tSource: %s\n", gl_debug_source_string(source)); + log_debug("\tType: %s\n", gl_debug_type_string(type)); + log_debug("\tSeverity: %s\n", gl_debug_severity_string(severity)); + log_debug("\tMessage: %s\n", message); +} + +const char *gl_debug_source_string(GLenum type) +{ + switch(type) { + case GL_DEBUG_SOURCE_API: + return "API"; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + return "Window system"; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + return "Shader compiler"; + case GL_DEBUG_SOURCE_THIRD_PARTY: + return "Third party"; + case GL_DEBUG_SOURCE_APPLICATION: + return "Application"; + case GL_DEBUG_SOURCE_OTHER: + return "Other"; + } + return "unknown"; +} + +const char *gl_debug_type_string(GLenum type) +{ + switch(type) { + case GL_DEBUG_TYPE_ERROR: + return "Error"; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + return "Deprecated behavior"; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + return "Undefined behavior"; + case GL_DEBUG_TYPE_PORTABILITY: + return "Portability"; + case GL_DEBUG_TYPE_PERFORMANCE: + return "Performance"; + case GL_DEBUG_TYPE_MARKER: + return "Marker"; + case GL_DEBUG_TYPE_PUSH_GROUP: + return "Push group"; + case GL_DEBUG_TYPE_POP_GROUP: + return "Pop group"; + case GL_DEBUG_TYPE_OTHER: + return "Other"; + } + return "Unknown"; +} + +const char *gl_debug_severity_string(GLenum type) +{ + switch(type) { + case GL_DEBUG_SEVERITY_HIGH: + return "High"; + case GL_DEBUG_SEVERITY_MEDIUM: + return "Medium"; + case GL_DEBUG_SEVERITY_LOW: + return "Low"; + case GL_DEBUG_SEVERITY_NOTIFICATION: + return "Notification"; + } + return "Unknown"; +} -- cgit v1.2.3