summaryrefslogtreecommitdiff
path: root/src/gl.c
diff options
context:
space:
mode:
authorPhil Jones <philj56@gmail.com>2021-10-31 16:47:03 +0000
committerPhil Jones <philj56@gmail.com>2021-10-31 16:54:20 +0000
commit74adfe0cbca300e73774c6e0aa9b3c53a5e5b57b (patch)
tree88d0efbdd9755849eb22ee3478595df5c8e69a34 /src/gl.c
parentc691b8e48c572e2d5f1c7c16c8f42babd7d706d5 (diff)
Add HiDPI support and lots of cleanup.
Diffstat (limited to 'src/gl.c')
-rw-r--r--src/gl.c179
1 files changed, 163 insertions, 16 deletions
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";
+}