Last active
September 3, 2023 10:19
-
-
Save dyllandry/f5e7a3af3767c06b06f24b8f4099221f to your computer and use it in GitHub Desktop.
Load OpenGL functions pointers with C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "opengl-api.h" | |
#include <dlfcn.h> | |
#include <stdio.h> | |
/* Here we define pointers to each of the opengl functions we use by defining a | |
* function-like macro "GL_FUNC" and applying it to each "GL_FUNC" macro | |
* contained by "GL_FUNC_LIST". This xmacro is defined in our header. */ | |
#define GL_FUNC(returnType, funcName, ...) funcName##Type * funcName; | |
GL_FUNC_LIST | |
#undef GL_FUNC | |
/* Call this function once from whatever function initializes your opengl | |
* functions. */ | |
int openglApiInit() | |
{ | |
void * libGL = dlopen("libGL.so", RTLD_LAZY); | |
if (!libGL) | |
{ | |
printf("ERROR: libGL.so couldn't be loaded\n"); | |
return 0; | |
} | |
/* Here we load each opengl function by again defining a macro GL_FUNC | |
* and applying it to each GL_FUNC macro contained by GL_FUNC_LIST. */ | |
#define GL_FUNC(returnType, funcName, ...) \ | |
funcName = (funcName##Type *) dlsym(libGL, #funcName); \ | |
if (!funcName) \ | |
{ \ | |
printf("Function " #funcName "couldn't be loaded from libGL.so\n");\ | |
return 0; \ | |
} | |
GL_FUNC_LIST | |
#undef GL_FUNC | |
return 1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* opengl-api.h: gets function pointers to gpu driver's opengl api | |
* | |
* To learn the reasons for loading opengl functions yourself, read | |
* <https://apoorvaj.io/loading-opengl-without-glew/> | |
* | |
* Nice introduction to xmacros (heavily used here) | |
* <https://stackoverflow.com/a/9384467/7933478> | |
*/ | |
#ifndef OPENGL_API_H | |
#define OPENGL_API_H | |
#include <GL/gl.h> | |
/* | |
* GL_FUNC_LIST is a macro that whenever used will produce a list of | |
* function-like macro "GL_FUNC" that can be defined, undefined, and redefined | |
* to do different things with the provided arguments. | |
* | |
* For example, GL_FUNC is defined below to create both typedefs for these | |
* opengl functions and declare them as extern. And in opengl-api.c, GL_FUNC is | |
* repeatedly defined, undefined, and redefined to create code that will define | |
* pointers to each of these functions as well as load them dynamically using | |
* libGL.so | |
* | |
* This kind of macro is often called an xmacro, here's a nice explanation | |
* often them <https://stackoverflow.com/a/9384467/7933478> | |
*/ | |
#define GL_FUNC_LIST \ | |
/* params: returnType, funcName, args... */ \ | |
GL_FUNC(GLuint, glCreateShader, GLenum type) \ | |
GL_FUNC(void, glShaderSource, GLuint shader, GLsizei count, const GLchar **string, const GLint *length) \ | |
GL_FUNC(void, glCompileShader, GLuint shader) \ | |
GL_FUNC(void, glGetShaderiv, GLuint shader, GLenum pname, GLint *params) \ | |
GL_FUNC(void, glGetShaderInfoLog, GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog) \ | |
GL_FUNC(GLuint, glCreateProgram) \ | |
GL_FUNC(void, glAttachShader, GLuint program, GLuint shader) \ | |
GL_FUNC(void, glLinkProgram, GLuint program) \ | |
GL_FUNC(void, glGetProgramiv, GLuint program, GLenum pname, GLint *params) \ | |
GL_FUNC(void, glGetProgramInfoLog, GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog) \ | |
GL_FUNC(void, glDeleteShader, GLuint shader) \ | |
GL_FUNC(void, glGenBuffers, GLsizei n, GLuint * buffers) \ | |
GL_FUNC(void, glGenVertexArrays, GLsizei n, GLuint *arrays) \ | |
GL_FUNC(void, glBindVertexArray, GLuint array) \ | |
GL_FUNC(void, glBindBuffer, GLenum target, GLuint buffer) \ | |
GL_FUNC(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage) \ | |
GL_FUNC(void, glVertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) \ | |
GL_FUNC(void, glEnableVertexAttribArray, GLuint index) \ | |
GL_FUNC(void, glUseProgram, GLuint program) \ | |
GL_FUNC(void, glDeleteVertexArrays, GLsizei n, const GLuint *arrays) \ | |
GL_FUNC(void, glDeleteBuffers, GLsizei n, const GLuint * buffers) \ | |
GL_FUNC(void, glDeleteProgram, GLuint program) | |
#define GL_FUNC(returnType, funcName, ...) \ | |
/* Create a typedef for the opengl function so the function pointers are shorter to type. */ \ | |
typedef returnType funcName##Type(__VA_ARGS__); \ | |
/* Declare function pointer as extern so files that include this header can reference it. */ \ | |
extern funcName##Type * funcName; | |
/* So, because we've just defined GL_FUNC, when we next use the GL_FUNC_LIST | |
* macro, our GL_FUNC macro will run for each GL_FUNC in GL_FUNC_LIST. */ | |
GL_FUNC_LIST | |
#undef GL_FUNC | |
int openglApiInit(); | |
#endif // OPENGL_API_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment