summaryrefslogtreecommitdiff
path: root/gl.c
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-04-22 14:02:12 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2021-04-22 14:02:12 -0400
commitf6c6f709fed4914a41e3928ad728a076a842bb29 (patch)
treed33be3f8bd3c00c8dd532bfeac4260a3c2358e2d /gl.c
initial commit
Diffstat (limited to 'gl.c')
-rw-r--r--gl.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/gl.c b/gl.c
new file mode 100644
index 0000000..87c4e65
--- /dev/null
+++ b/gl.c
@@ -0,0 +1,203 @@
+#include "lib/glcorearb.h"
+
+// macro trickery to avoid having to write everything twice
+#define gl_for_each_proc(do)\
+ do(DRAWARRAYS, DrawArrays)\
+ do(DRAWELEMENTS, DrawElements)\
+ do(GENTEXTURES, GenTextures)\
+ do(DELETETEXTURES, DeleteTextures)\
+ do(TEXIMAGE2D, TexImage2D)\
+ do(BINDTEXTURE, BindTexture)\
+ do(TEXPARAMETERI, TexParameteri)\
+ do(GETERROR, GetError)\
+ do(GETINTEGERV, GetIntegerv)\
+ do(ENABLE, Enable)\
+ do(DISABLE, Disable)\
+ do(BLENDFUNC, BlendFunc)\
+ do(DEPTHFUNC, DepthFunc)\
+ do(VIEWPORT, Viewport)\
+ do(CLEARCOLOR, ClearColor)\
+ do(CLEAR, Clear)\
+ do(FINISH, Finish)\
+ do(PIXELSTOREI, PixelStorei)\
+ do(CREATESHADER, CreateShader)\
+ do(DELETESHADER, DeleteShader)\
+ do(CREATEPROGRAM, CreateProgram)\
+ do(SHADERSOURCE, ShaderSource)\
+ do(GETSHADERIV, GetShaderiv)\
+ do(GETSHADERINFOLOG, GetShaderInfoLog)\
+ do(COMPILESHADER, CompileShader)\
+ do(CREATEPROGRAM, CreateProgram)\
+ do(DELETEPROGRAM, DeleteProgram)\
+ do(ATTACHSHADER, AttachShader)\
+ do(LINKPROGRAM, LinkProgram)\
+ do(GETPROGRAMIV, GetProgramiv)\
+ do(GETPROGRAMINFOLOG, GetProgramInfoLog)\
+ do(USEPROGRAM, UseProgram)\
+ do(GETATTRIBLOCATION, GetAttribLocation)\
+ do(GETUNIFORMLOCATION, GetUniformLocation)\
+ do(GENBUFFERS, GenBuffers)\
+ do(DELETEBUFFERS, DeleteBuffers)\
+ do(BINDBUFFER, BindBuffer)\
+ do(BUFFERDATA, BufferData)\
+ do(VERTEXATTRIBPOINTER, VertexAttribPointer)\
+ do(VERTEXATTRIBIPOINTER, VertexAttribIPointer)\
+ do(ENABLEVERTEXATTRIBARRAY, EnableVertexAttribArray)\
+ do(DISABLEVERTEXATTRIBARRAY, DisableVertexAttribArray)\
+ do(GENVERTEXARRAYS, GenVertexArrays)\
+ do(DELETEVERTEXARRAYS, DeleteVertexArrays)\
+ do(BINDVERTEXARRAY, BindVertexArray)\
+ do(ACTIVETEXTURE, ActiveTexture)\
+ do(UNIFORM1F, Uniform1f)\
+ do(UNIFORM2F, Uniform2f)\
+ do(UNIFORM3F, Uniform3f)\
+ do(UNIFORM4F, Uniform4f)\
+ do(UNIFORM1I, Uniform1i)\
+ do(UNIFORM2I, Uniform2i)\
+ do(UNIFORM3I, Uniform3i)\
+ do(UNIFORM4I, Uniform4i)\
+ do(UNIFORMMATRIX4FV, UniformMatrix2fv)\
+ do(UNIFORMMATRIX4FV, UniformMatrix3fv)\
+ do(UNIFORMMATRIX4FV, UniformMatrix4fv)\
+ do(DEBUGMESSAGECALLBACK, DebugMessageCallback)\
+ do(DEBUGMESSAGECONTROL, DebugMessageControl)\
+ do(POLYGONMODE, PolygonMode)\
+ do(GENFRAMEBUFFERS, GenFramebuffers)\
+ do(BINDFRAMEBUFFER, BindFramebuffer)\
+ do(FRAMEBUFFERTEXTURE2D, FramebufferTexture2D)\
+ do(DELETEFRAMEBUFFERS, DeleteFramebuffers)\
+ do(BLITFRAMEBUFFER, BlitFramebuffer)\
+ do(DRAWBUFFER, DrawBuffer)\
+ do(TEXIMAGE2DMULTISAMPLE, TexImage2DMultisample)\
+ do(GENRENDERBUFFERS, GenRenderbuffers)\
+ do(DELETERENDERBUFFERS, DeleteRenderbuffers)\
+ do(BINDRENDERBUFFER, BindRenderbuffer)\
+ do(RENDERBUFFERSTORAGE, RenderbufferStorage)\
+ do(RENDERBUFFERSTORAGEMULTISAMPLE, RenderbufferStorageMultisample)\
+ do(FRAMEBUFFERRENDERBUFFER, FramebufferRenderbuffer)\
+ do(CHECKFRAMEBUFFERSTATUS, CheckFramebufferStatus)
+
+#define gl_declare_proc(upper, lower) static PFNGL##upper##PROC gl##lower;
+gl_for_each_proc(gl_declare_proc)
+#undef gl_declare_proc
+
+static void gl_get_procs(void) {
+#if __GNUC__ && !__clang__
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+ #define gl_get_proc(upper, lower) gl##lower = (PFNGL##upper##PROC)SDL_GL_GetProcAddress("gl" #lower);
+ gl_for_each_proc(gl_get_proc)
+ #undef gl_get_proc
+#if __GNUC__ && !__clang__
+ #pragma GCC diagnostic pop
+#endif
+}
+
+#define BUFFER_BATCH_SIZE 8
+#define VARRAY_BATCH_SIZE 8
+static GLuint gl_buffers[BUFFER_BATCH_SIZE], gl_buffers_used = BUFFER_BATCH_SIZE;
+static GLuint gl_varrays[VARRAY_BATCH_SIZE], gl_varrays_used = VARRAY_BATCH_SIZE;
+
+
+static GLuint gl_gen_buffer(void) {
+ if (gl_buffers_used >= BUFFER_BATCH_SIZE) {
+ gl_buffers_used = 0;
+ glGenBuffers(BUFFER_BATCH_SIZE, gl_buffers);
+ }
+ return gl_buffers[gl_buffers_used++];
+}
+
+static GLuint gl_gen_vertex_array(void) {
+ if (gl_varrays_used >= VARRAY_BATCH_SIZE) {
+ gl_varrays_used = 0;
+ glGenVertexArrays(VARRAY_BATCH_SIZE, gl_varrays);
+ }
+ return gl_varrays[gl_varrays_used++];
+}
+
+
+// compile a GLSL shader
+static GLuint gl_compile_shader(char const *code, GLenum shader_type) {
+ GLuint shader = glCreateShader(shader_type);
+ glShaderSource(shader, 1, &code, NULL);
+ glCompileShader(shader);
+ GLint status = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (status == GL_FALSE) {
+ char log[1024] = {0};
+ glGetShaderInfoLog(shader, sizeof log - 1, NULL, log);
+ debug_println("Error compiling shader: %s", log);
+ return 0;
+ }
+ return shader;
+}
+
+// link together GL shaders
+static GLuint gl_link_program(GLuint *shaders, size_t count) {
+ GLuint program = glCreateProgram();
+ if (program) {
+ for (size_t i = 0; i < count; ++i) {
+ if (!shaders[i]) {
+ glDeleteProgram(program);
+ return 0;
+ }
+ glAttachShader(program, shaders[i]);
+ }
+ glLinkProgram(program);
+ GLint status = 0;
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ char log[1024] = {0};
+ glGetProgramInfoLog(program, sizeof log - 1, NULL, log);
+ debug_println("Error linking shaders: %s", log);
+ glDeleteProgram(program);
+ return 0;
+ }
+ }
+ return program;
+}
+
+static GLuint gl_compile_and_link_shaders(char const *vshader_code, char const *fshader_code) {
+ GLuint shaders[2];
+ shaders[0] = gl_compile_shader(vshader_code, GL_VERTEX_SHADER);
+ shaders[1] = gl_compile_shader(fshader_code, GL_FRAGMENT_SHADER);
+ GLuint program = gl_link_program(shaders, 2);
+ if (shaders[0]) glDeleteShader(shaders[0]);
+ if (shaders[1]) glDeleteShader(shaders[1]);
+ if (program) {
+ debug_print("Successfully linked program %u.\n", program);
+ }
+ return program;
+}
+
+static GLuint gl_create_program_from_files(char const *vshader_file, char const *fshader_file) {
+ char *vcode = read_file_contents(vshader_file);
+ char *fcode = read_file_contents(fshader_file);
+ GLuint program = 0;
+ if (vcode && fcode) {
+ program = gl_compile_and_link_shaders(vcode, fcode);
+ } else {
+ debug_print("WARNING: Couldn't read file: %s.\n", vcode ? fshader_file : vshader_file);
+ }
+ free(vcode); free(fcode);
+ return program;
+}
+
+static GLuint gl_attrib_loc(GLuint program, char const *attrib) {
+ GLint loc = glGetAttribLocation(program, attrib);
+ if (loc == -1) {
+ debug_print("Couldn't find vertex attribute %s.\n", attrib);
+ return 0;
+ }
+ return (GLuint)loc;
+}
+
+static GLint gl_uniform_loc(GLuint program, char const *uniform) {
+ GLint loc = glGetUniformLocation(program, uniform);
+ if (loc == -1) {
+ debug_print("Couldn't find uniform: %s.\n", uniform);
+ return -1;
+ }
+ return loc;
+}