Skip to content

Instantly share code, notes, and snippets.

@jonvaldes
Last active August 9, 2020 10:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonvaldes/0fa76a84dca4ac7fe8eb to your computer and use it in GitHub Desktop.
Save jonvaldes/0fa76a84dca4ac7fe8eb to your computer and use it in GitHub Desktop.
Simple OpenGL function wrappers by way of metaprogramming
// Parser for C(++) code, aimed at generating
// code instead of using C macros
typedef int i32;
typedef struct {
const char *Code;
i32 CodeLength;
i32 CurrentLine;
} cpp_lexer;
cpp_lexer createLexer(const char *Code, i32 Length) {
cpp_lexer Result;
Result.Code = Code;
Result.CodeLength = Length;
Result.CurrentLine = 1;
return Result;
}
#define TOKENS() TOK(TOKEN_EOF), TOK(TOKEN_ERROR), TOK(TOKEN_IDENTIFIER), TOK(TOKEN_NUMBER), \
TOK(TOKEN_OPEN_PARENS), TOK(TOKEN_CLOSE_PARENS), TOK(TOKEN_OPEN_BRACKETS), TOK(TOKEN_CLOSE_BRACKETS), \
TOK(TOKEN_OPEN_SQUARE_BRACKETS), TOK(TOKEN_CLOSE_SQUARE_BRACKETS), \
TOK(TOKEN_SEMICOLON), TOK(TOKEN_COMMA), TOK(TOKEN_COLON), TOK(TOKEN_DOT), \
TOK(TOKEN_PLUS), TOK(TOKEN_MINUS), TOK(TOKEN_STAR), TOK(TOKEN_SLASH), \
TOK(TOKEN_PLUS_EQUAL), TOK(TOKEN_MINUS_EQUAL), TOK(TOKEN_STAR_EQUAL), TOK(TOKEN_SLASH_EQUAL), \
TOK(TOKEN_COMMENT), TOK(TOKEN_STRING), TOK(TOKEN_CHAR), \
TOK(TOKEN_EQUAL), TOK(TOKEN_EQUALS), \
TOK(TOKEN_LESS_THAN), TOK(TOKEN_LESS_EQUAL), TOK(TOKEN_LEFT_SHIFT), \
TOK(TOKEN_MORE_THAN), TOK(TOKEN_MORE_EQUAL), TOK(TOKEN_RIGHT_SHIFT), \
TOK(TOKEN_DEC), \
TOK(TOKEN_INC), \
TOK(TOKEN_ARROW), \
TOK(TOKEN_NOT_EQUAL), \
TOK(TOKEN_BIN_AND), TOK(TOKEN_BIN_OR), TOK(TOKEN_BIN_XOR), TOK(TOKEN_BIN_NOT), \
TOK(TOKEN_LOGIC_AND), TOK(TOKEN_LOGIC_OR), TOK(TOKEN_LOGIC_XOR), TOK(TOKEN_LOGIC_NOT), \
TOK(TOKEN_AND_EQUALS), TOK(TOKEN_OR_EQUALS), TOK(TOKEN_XOR_EQUALS), \
TOK(TOKEN_DIRECTIVE)
// ----------------
#define TOK(x) x
#define Assert(x) \
if(!(x)) { \
__debugbreak(); \
}
typedef enum {
TOKENS(),
TOKENS_CNT
} token_type;
#undef TOK
#define TOK(x) #x
const char *TokenNames[] = {
TOKENS(),
};
#undef TOK
typedef struct {
token_type Type;
const char *Text;
i32 Length;
} token;
void ignoreSpaceCharacters(cpp_lexer *Lexer) {
for(;;) {
if(Lexer->CodeLength == 0) {
break;
}
char c = *Lexer->Code;
if(!((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n'))) {
break;
}
Lexer->Code++;
Lexer->CodeLength--;
if(c == '\n') {
Lexer->CurrentLine++;
}
}
}
bool getNextChar(cpp_lexer *Lexer, char *C) {
if(Lexer->CodeLength == 0) {
return false;
}
Lexer->CodeLength--;
*C = *Lexer->Code++;
if(*C == '\n') {
Lexer->CurrentLine++;
}
return true;
}
void unreadChar(cpp_lexer *Lexer) {
Lexer->Code--;
Lexer->CodeLength++;
if(*Lexer->Code == '\n') {
Lexer->CurrentLine--;
}
}
bool isNumeric(char C) { return (C >= '0' && C <= '9'); }
bool isAlphaNumeric(char C) {
return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') || (C == '_') || (C >= '0' && C <= '9');
}
token getNextToken(cpp_lexer *Lexer) {
ignoreSpaceCharacters(Lexer);
token Result;
Result.Text = Lexer->Code;
Result.Length = 1;
char StartC;
if(!getNextChar(Lexer, &StartC)) {
Result.Type = TOKEN_EOF;
Result.Length = 0;
return Result;
}
#define ONE_CHAR_TOKEN(c, toktype) \
case c: \
Result.Type = toktype; \
return Result
#define INIT_MULTICHAR_TOK(onechartok) \
do { \
Result.Type = onechartok; \
if(!getNextChar(Lexer, &StartC)) { \
Result.Type = TOKEN_ERROR; \
return Result; \
} \
} while(0, 0)
#define END_MULTICHAR_TOK() \
unreadChar(Lexer); \
return Result
#define CHECK_ADDED_CHAR(chr, toktype) \
do { \
if(StartC == chr) { \
Result.Type = toktype; \
Result.Length++; \
return Result; \
} \
} while(0, 0)
#define ERRTOK() \
Result.Type = TOKEN_ERROR; \
return Result
switch(StartC) {
ONE_CHAR_TOKEN('(', TOKEN_OPEN_PARENS);
ONE_CHAR_TOKEN(')', TOKEN_CLOSE_PARENS);
ONE_CHAR_TOKEN('{', TOKEN_OPEN_BRACKETS);
ONE_CHAR_TOKEN('}', TOKEN_CLOSE_BRACKETS);
ONE_CHAR_TOKEN('[', TOKEN_OPEN_SQUARE_BRACKETS);
ONE_CHAR_TOKEN(']', TOKEN_CLOSE_SQUARE_BRACKETS);
ONE_CHAR_TOKEN(';', TOKEN_SEMICOLON);
ONE_CHAR_TOKEN(',', TOKEN_COMMA);
ONE_CHAR_TOKEN('.', TOKEN_DOT);
ONE_CHAR_TOKEN(':', TOKEN_COLON);
ONE_CHAR_TOKEN('~', TOKEN_BIN_NOT);
case '+': {
INIT_MULTICHAR_TOK(TOKEN_PLUS);
CHECK_ADDED_CHAR('=', TOKEN_PLUS_EQUAL);
CHECK_ADDED_CHAR('+', TOKEN_INC);
END_MULTICHAR_TOK();
}
case '!': {
INIT_MULTICHAR_TOK(TOKEN_LOGIC_NOT);
CHECK_ADDED_CHAR('=', TOKEN_NOT_EQUAL);
END_MULTICHAR_TOK();
}
case '-': {
INIT_MULTICHAR_TOK(TOKEN_MINUS);
CHECK_ADDED_CHAR('=', TOKEN_MINUS_EQUAL);
CHECK_ADDED_CHAR('-', TOKEN_DEC);
CHECK_ADDED_CHAR('>', TOKEN_ARROW);
END_MULTICHAR_TOK();
}
case '*': {
INIT_MULTICHAR_TOK(TOKEN_STAR);
CHECK_ADDED_CHAR('=', TOKEN_STAR_EQUAL);
END_MULTICHAR_TOK();
}
case '&': {
INIT_MULTICHAR_TOK(TOKEN_BIN_AND);
CHECK_ADDED_CHAR('&', TOKEN_LOGIC_AND);
CHECK_ADDED_CHAR('=', TOKEN_AND_EQUALS);
END_MULTICHAR_TOK();
}
case '|': {
INIT_MULTICHAR_TOK(TOKEN_BIN_OR);
CHECK_ADDED_CHAR('|', TOKEN_LOGIC_OR);
CHECK_ADDED_CHAR('=', TOKEN_OR_EQUALS);
END_MULTICHAR_TOK();
}
case '^': {
INIT_MULTICHAR_TOK(TOKEN_BIN_XOR);
CHECK_ADDED_CHAR('=', TOKEN_XOR_EQUALS);
END_MULTICHAR_TOK();
}
case '<': {
INIT_MULTICHAR_TOK(TOKEN_LESS_THAN);
CHECK_ADDED_CHAR('<', TOKEN_LEFT_SHIFT);
CHECK_ADDED_CHAR('=', TOKEN_LESS_EQUAL);
END_MULTICHAR_TOK();
}
case '>': {
INIT_MULTICHAR_TOK(TOKEN_MORE_THAN);
CHECK_ADDED_CHAR('>', TOKEN_RIGHT_SHIFT);
CHECK_ADDED_CHAR('=', TOKEN_MORE_EQUAL);
END_MULTICHAR_TOK();
}
case '=': {
INIT_MULTICHAR_TOK(TOKEN_EQUAL);
CHECK_ADDED_CHAR('=', TOKEN_EQUALS);
END_MULTICHAR_TOK();
}
case '\'': {
Result.Type = TOKEN_CHAR;
Result.Text++;
if(!getNextChar(Lexer, &StartC)) {
ERRTOK();
}
char NextC;
if(!getNextChar(Lexer, &NextC)) {
ERRTOK();
}
if(StartC == '\\') {
if(!getNextChar(Lexer, &NextC) || NextC != '\'') {
ERRTOK();
}
Result.Length = 2;
return Result;
}
if(NextC != '\'') {
ERRTOK();
}
return Result;
}
case '"': {
Result.Type = TOKEN_STRING;
char C = StartC;
Result.Length = -1;
Result.Text = Lexer->Code;
do {
Result.Length++;
StartC = C;
if(!getNextChar(Lexer, &C)) {
ERRTOK();
}
// NOTE: This doesn't handle multiline strings properly
} while(C != '"' || StartC == '\\');
return Result;
}
case '#': {
Result.Text = Lexer->Code;
Result.Length = 0;
Result.Type = TOKEN_DIRECTIVE;
while(getNextChar(Lexer, &StartC) && StartC != '\r' && StartC != '\n') {
Result.Length++;
}
return Result;
}
case '/': {
char NextChar;
if(!getNextChar(Lexer, &NextChar)) {
Result.Type = TOKEN_SLASH;
return Result;
}
if(NextChar == '=') { // a /= 2;
Result.Length = 2;
Result.Type = TOKEN_SLASH_EQUAL;
return Result;
}
if(NextChar == '/') { // C++-style comment
Result.Text = Lexer->Code;
Result.Length = 0;
Result.Type = TOKEN_COMMENT;
while(getNextChar(Lexer, &NextChar) && NextChar != '\r' && NextChar != '\n') {
Result.Length++;
}
return Result;
}
if(NextChar == '*') { // C-style comment
Result.Type = TOKEN_COMMENT;
Result.Text = Lexer->Code;
Result.Length = 0;
if(!getNextChar(Lexer, &StartC)) {
ERRTOK();
}
for(;;) {
if(!getNextChar(Lexer, &NextChar)) {
ERRTOK();
}
if(NextChar == '/' && StartC == '*') {
return Result;
}
Result.Length++;
StartC = NextChar;
}
}
// Roll back one char, it was just a slash
unreadChar(Lexer);
Result.Type = TOKEN_SLASH;
return Result;
}
default: {
if(isNumeric(StartC)) {
Result.Type = TOKEN_NUMBER;
while(Lexer->CodeLength > 0 && isNumeric(*Lexer->Code)) {
Result.Length++;
Lexer->Code++;
Lexer->CodeLength--;
}
return Result;
} else {
Result.Type = TOKEN_IDENTIFIER;
while(Lexer->CodeLength > 0 && isAlphaNumeric(*Lexer->Code)) {
Result.Length++;
Lexer->Code++;
Lexer->CodeLength--;
}
return Result;
}
}
#undef ONE_CHAR_TOKEN
}
}
// Returns next token, skipping over comments
token getNextSignficantToken(cpp_lexer *Lexer) {
token T;
do {
T = getNextToken(Lexer);
} while(T.Type == TOKEN_COMMENT);
return T;
}
i32 StrLen(const char *Str) {
i32 Result = 0;
while(*Str++) {
Result++;
}
return Result;
}
bool findIdentifier(cpp_lexer *Lexer, const char *Name, token *Token) {
i32 NameLen = StrLen(Name);
for(;;) {
token T = getNextToken(Lexer);
if(T.Type == TOKEN_EOF) {
return false;
}
if(T.Type == TOKEN_IDENTIFIER && T.Length == NameLen) {
bool AreEqual = true;
for(int i = 0; i < NameLen; i++) {
if(Name[i] != T.Text[i]) {
AreEqual = false;
break;
}
}
if(AreEqual) {
*Token = T;
return true;
}
}
}
}
#include "cpp_lexer.cpp"
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char u8;
char *readFile(const char *Filename, i32 *FileSize) {
FILE *fd = fopen(Filename, "r");
if(!fd) {
return NULL;
}
fseek(fd, 0, SEEK_END);
int fileSize = ftell(fd);
fseek(fd, 0, SEEK_SET);
char *Data = (char *)malloc(fileSize);
*FileSize = fread(Data, 1, fileSize, fd);
fclose(fd);
return Data;
}
void printLexerErr(cpp_lexer *Lexer) {
printf("ERROR in line %d --", Lexer->CurrentLine);
}
void AssertNextToken(cpp_lexer *Lexer, token_type Type) {
token Token = getNextToken(Lexer);
if(Token.Type == TOKEN_EOF) {
printLexerErr(Lexer);
printf("Reached end of file while expecting a token of type %s\n", TokenNames[Type]);
exit(1);
}
if(Token.Type != Type) {
printLexerErr(Lexer);
printf("Expected token of type %s, but got %s instead\n", TokenNames[Type], TokenNames[Token.Type]);
exit(1);
}
}
void AssertToken(token Token, token_type Type) {
if(Token.Type != Type) {
printf("Expected token of type %s, but got %s instead\n", TokenNames[Type], TokenNames[Token.Type]);
exit(1);
}
}
token getToken(cpp_lexer *Lexer) {
token Token = getNextToken(Lexer);
if(Token.Type == TOKEN_EOF) {
printLexerErr(Lexer);
printf("Unexpected end of file\n");
exit(1);
}
return Token;
}
#define MAX_TOKENS 50
typedef struct {
token Tokens[MAX_TOKENS];
i32 TokenCnt;
} argument;
bool readMacroArguments(cpp_lexer *Lexer, i32 MaxArguments, argument *Arguments, int *ReadArguments) {
for(int Arg = 0; Arg < MaxArguments; Arg++) {
Arguments[Arg].TokenCnt = 0;
for(int i = 0; i < MAX_TOKENS; i++) {
token Token = getToken(Lexer);
if(Token.Type == TOKEN_COMMA) {
break;
}
if(Token.Type == TOKEN_CLOSE_PARENS) {
*ReadArguments = Arg + 1;
return true;
}
int TokenCnt = Arguments[Arg].TokenCnt;
Arguments[Arg].Tokens[TokenCnt] = Token;
Arguments[Arg].TokenCnt++;
}
}
return false;
}
bool argumentIs(argument *Arg, const char *Text) {
// Note: this doesn't support arguments with several tokens yet
if(Arg->TokenCnt != 1) {
return false;
}
if(StrLen(Text) != Arg->Tokens[0].Length) {
return false;
}
for(int i = 0; i < Arg->Tokens[0].Length; i++) {
if(Arg->Tokens[0].Text[i] != Text[i]) {
return false;
}
}
return true;
}
void printTokenContents(FILE *fd, token Tok) {
for(int i = 0; i < Tok.Length; i++) {
fprintf(fd, "%c", Tok.Text[i]);
}
}
void printArgument(FILE *fd, argument *Arg) {
for(int i = 0; i < Arg->TokenCnt; i++) {
if(i != 0) {
fprintf(fd, " ");
}
printTokenContents(fd, Arg->Tokens[i]);
}
}
void print(FILE *fd, const char *S) {
fprintf(fd, "%s", S);
}
void print(FILE *fd, argument *Arg) {
printArgument(fd, Arg);
}
void print(FILE *fd, char c) {
fprintf(fd, "%c", c);
}
template <typename T, typename... params>
void print(FILE *fd, T Arg1, params... ArgsN) {
print(fd, Arg1);
print(fd, ArgsN...);
}
// ---------------------------------------------------------------------------
// Actual metaprogramming functions
// ---------------------------------------------------------------------------
void generateGLFunctionWrappers() {
// Generate function wrappers in glFuncs.cpp
i32 FileSize;
char *FileData = readFile("../src/glFuncs.cpp", &FileSize);
if(!FileData) {
printf("ERROR -- Could not open input file\n");
exit(1);
}
FILE *fd = fopen("../src/generated/glFuncsImpl.cpp", "w");
if(!fd) {
printf("ERROR -- Could not open output file for writing\n");
exit(1);
}
cpp_lexer Lexer = createLexer(FileData, FileSize);
token Token;
while(findIdentifier(&Lexer, "GLFUNC", &Token)) {
AssertNextToken(&Lexer, TOKEN_OPEN_PARENS);
argument Args[20];
i32 ArgsCnt;
if(!readMacroArguments(&Lexer, 20, Args, &ArgsCnt)) {
printLexerErr(&Lexer);
printf("GLFUNC macro has too many arguments, or EOF found in the middle of one\n");
exit(1);
}
argument *ReturnType = &Args[1];
argument *FunctionName = &Args[0];
argument *FunctionArgs = &Args[2];
i32 FunctionArgsCnt = ArgsCnt - 2;
print(fd, "// ------ ", FunctionName, " ------\n");
// Print function type typedef
print(fd, "typedef ", ReturnType, " __stdcall ", FunctionName, "Func(");
for(int i = 0; i < FunctionArgsCnt; i++) {
print(fd, i == 0 ? "" : ", ", &FunctionArgs[i]);
}
print(fd, ");\n");
// Print GL function pointer
print(fd, FunctionName, "Func * _", FunctionName, ";\n\n");
// Print wrapper function
print(fd, ReturnType, " ", FunctionName, "(");
for(int i = 0; i < FunctionArgsCnt; i++) {
print(fd, i == 0 ? "" : ", ", &FunctionArgs[i], " arg", char('0' + i));
}
print(fd, "){\n\t");
if(!argumentIs(ReturnType, "void")) {
print(fd, ReturnType, " Result = ");
}
print(fd, "_", FunctionName, "(");
for(int i = 0; i < FunctionArgsCnt; i++) {
print(fd, i == 0 ? "" : ", ", "arg", char('0' + i));
}
print(fd, ");\n");
if(!(
// glGetError must not call itself!
argumentIs(FunctionName, "glGetError") ||
// Can't call glGetError inside a glBegin/glEnd block
argumentIs(FunctionName, "glBegin") ||
argumentIs(FunctionName, "glVertex2f") ||
argumentIs(FunctionName, "glTexCoord2f") ||
// wglCreateContextAttribsARB gives GL_INVALID_OPERATION until context is made current
argumentIs(FunctionName, "wglCreateContextAttribsARB"))) {
print(fd, "\tGLERR();\n");
}
if(!argumentIs(ReturnType, "void")) {
print(fd, "\treturn Result;\n");
}
print(fd, "}\n\n");
}
fclose(fd);
free(FileData);
}
int main() {
generateGLFunctionWrappers();
}
typedef u32 GLenum;
typedef u32 GLuint;
typedef i32 GLint;
typedef i32 GLsizei;
typedef void GLvoid;
typedef f32 GLfloat;
typedef f32 GLclampf;
typedef u32 GLbitfield;
typedef char GLchar;
typedef ptrdiff_t GLsizeiptr;
typedef u8 GLboolean;
typedef u8 GLubyte;
extern "C" {
#ifdef _WIN32
typedef PROC WINAPI wglGetProcAddressFunc(LPCSTR);
wglGetProcAddressFunc *_wglGetProcAddress;
typedef HGLRC WINAPI wglCreateContextFunc(HDC hdc);
wglCreateContextFunc *_wglCreateContext;
typedef BOOL WINAPI wglDeleteContextFunc(HGLRC hglrc);
wglDeleteContextFunc *_wglDeleteContext;
typedef BOOL WINAPI wglMakeCurrentFunc(HDC hdc, HGLRC hglrc);
wglMakeCurrentFunc *_wglMakeCurrent;
typedef BOOL WINAPI wglSwapLayerBuffersFunc(HDC hdc, UINT fuPlanes);
wglSwapLayerBuffersFunc *_wglSwapLayerBuffers;
}
global_var HMODULE g_OpenglLib;
#endif
// ---------------------------------------------------------------------------
#define GLFUNCS_LIST \
GLFUNC(glGenTextures, void, GLsizei, GLuint *) \
GLFUNC(glBindTexture, void, GLenum, GLuint) \
GLFUNC(glTexImage2D, void, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *) \
GLFUNC(glTexParameteri, void, GLenum, GLenum, GLint) \
GLFUNC(glGetError, GLenum) \
GLFUNC(glEnable, void, GLenum) \
GLFUNC(glDisable, void, GLenum) \
GLFUNC(glBegin, void, GLenum) \
GLFUNC(glEnd, void) \
GLFUNC(glTexCoord2f, void, GLfloat, GLfloat) \
GLFUNC(glVertex2f, void, GLfloat, GLfloat) \
GLFUNC(glEnableClientState, void, GLenum) \
GLFUNC(glDisableClientState, void, GLenum) \
GLFUNC(glVertexPointer, void, GLint, GLenum, GLsizei, const GLvoid *) \
GLFUNC(glTexCoordPointer, void, GLint, GLenum, GLsizei, const GLvoid *) \
GLFUNC(glColorPointer, void, GLint, GLenum, GLsizei, const GLvoid *) \
GLFUNC(glDrawArrays, void, GLenum, GLint, GLsizei) \
GLFUNC(glClearColor, void, GLclampf, GLclampf, GLclampf, GLclampf) \
GLFUNC(glClear, void, GLbitfield) \
GLFUNC(glLinkProgram, void, GLuint) \
GLFUNC(glShaderSource, void, GLuint, GLsizei, const GLchar *const *, const GLint *) \
GLFUNC(glUseProgram, void, GLuint) \
GLFUNC(glCompileShader, void, GLuint) \
GLFUNC(glCreateProgram, GLuint) \
GLFUNC(glCreateShader, GLuint, GLenum) \
GLFUNC(glGetShaderiv, void, GLuint, GLenum, GLint *) \
GLFUNC(glGetShaderInfoLog, void, GLuint, GLsizei, GLsizei *, GLchar *) \
GLFUNC(glAttachShader, void, GLuint, GLuint) \
GLFUNC(glGetProgramiv, void, GLuint, GLenum, GLint *) \
GLFUNC(glGetProgramInfoLog, void, GLuint, GLsizei, GLsizei *, GLchar *) \
GLFUNC(glGetUniformLocation, GLint, GLuint, const GLchar *) \
GLFUNC(glUniform1i, void, GLint, GLint) \
GLFUNC(glGenBuffers, void, GLsizei, GLuint *) \
GLFUNC(glBindBuffer, void, GLenum, GLuint) \
GLFUNC(glBufferData, void, GLenum, GLsizeiptr, const void *, GLenum) \
GLFUNC(glVertexAttribPointer, void, GLuint, GLint, GLenum, GLboolean, GLsizei, const void *) \
GLFUNC(glEnableVertexAttribArray, void, GLuint) \
GLFUNC(glUniformMatrix4fv, void, GLint, GLsizei, GLboolean, const GLfloat *) \
GLFUNC(glDrawElements, void, GLenum, GLsizei, GLenum, const void *) \
GLFUNC(glDisableVertexAttribArray, void, GLuint) \
GLFUNC(glGenFramebuffers, void, GLsizei, GLuint *) \
GLFUNC(glBindFramebuffer, void, GLenum, GLuint) \
GLFUNC(glFramebufferTexture2D, void, GLenum, GLenum, GLenum, GLuint, GLint) \
GLFUNC(glCheckFramebufferStatus, GLenum, GLenum) \
GLFUNC(glDeleteFramebuffers, void, GLsizei, const GLuint *) \
GLFUNC(glDeleteTextures, void, GLsizei, const GLuint *) \
GLFUNC(glDrawBuffer, void, GLenum) \
GLFUNC(glBlendFunc, void, GLenum, GLenum) \
GLFUNC(glScissor, void, GLint, GLint, GLsizei, GLsizei) \
GLFUNC(glViewport, void, GLint, GLint, GLsizei, GLsizei) \
GLFUNC(glGetString, const GLubyte *, GLenum) \
GLFUNC(glPolygonMode, void, GLenum, GLenum) \
GLFUNC(wglChoosePixelFormatARB, BOOL, HDC, const int *, const FLOAT *, UINT, int *, UINT *) \
GLFUNC(wglCreateContextAttribsARB, HGLRC, HDC, HGLRC, const int *) \
GLFUNC(wglSwapIntervalEXT, BOOL, i32)
#define GLERR() checkGLErrFunc(__FILE__, __LINE__)
void checkGLErrFunc(const char *filename, int line);
#include "generated/glFuncsImpl.cpp"
// ---------------------------------------------------------------------------
void loadOpenGL() {
g_OpenglLib = LoadLibrary("opengl32.dll");
Assert(g_OpenglLib);
#define GET_WGLFUNC(name) \
_##name = (name##Func *)GetProcAddress(g_OpenglLib, #name); \
Assert(_##name &&#name);
GET_WGLFUNC(wglGetProcAddress);
GET_WGLFUNC(wglCreateContext);
GET_WGLFUNC(wglDeleteContext);
GET_WGLFUNC(wglMakeCurrent);
GET_WGLFUNC(wglSwapLayerBuffers);
#undef GET_WGLFUNC
}
void initGLFuncs() {
#ifdef _WIN32
#undef GLFUNC
#define GLFUNC(name, ...) \
do { \
_##name = (name##Func *)_wglGetProcAddress(#name); \
if(!_##name) { \
_##name = (name##Func *)GetProcAddress(g_OpenglLib, #name); \
} \
Assert(_##name); \
} while(0, 0);
#else
#error Dynamic library loading not implemented in this OS yet
#endif
GLFUNCS_LIST
#undef GLFUNC
}
// ---------------------------------------------------------------------------
#define GL_INVALID_ENUM 0x0500
#define GL_TEXTURE_2D 0x0DE1
#define GL_RGBA 0x1908
#define GL_UNSIGNED_BYTE 0x1401
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_NEAREST 0x2600
#define GL_LINEAR 0x2601
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_CLAMP_TO_EDGE 0x812F
#define GL_DEPTH_TEST 0x0B71
#define GL_QUADS 0x0007
#define GL_TRIANGLES 0x0004
#define GL_VERTEX_ARRAY 0x8074
#define GL_TEXTURE_COORD_ARRAY 0x8078
#define GL_COLOR_ARRAY 0x8076
#define GL_FLOAT 0x1406
#define GL_SCISSOR_TEST 0x0C11
#define GL_COLOR_BUFFER_BIT 0x00004000
#define GL_DEPTH_BUFFER_BIT 0x00000100
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_COMPILE_STATUS 0x8B81
#define GL_LINK_STATUS 0x8B82
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_ARRAY_BUFFER 0x8892
#define GL_STATIC_DRAW 0x88E4
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_UNSIGNED_INT 0x1405
#define GL_RED 0x1903
#define GL_RG 0x8227
#define GL_RGB 0x1907
#define GL_DEPTH_COMPONENT16 0x81A5
#define GL_DEPTH_COMPONENT 0x1902
#define GL_FRAMEBUFFER 0x8D40
#define GL_COLOR_ATTACHMENT0 0x8CE0
#define GL_DEPTH_ATTACHMENT 0x8D00
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
#define GL_BACK 0x0405
#define GL_NONE 0
#define GL_BLEND 0x0BE2
#define GL_SRC_ALPHA 0x0302
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
#define GL_MULTISAMPLE 0x809D
#define GL_VERSION 0x1F02
#define GL_VENDOR 0x1F00
#define GL_RENDERER 0x1F01
#define GL_FALSE 0
#define GL_TRUE 1
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#define GL_FRONT_AND_BACK 0x0408
#define GL_FILL 0x1B02
#define GL_LINE 0x1B01
#define GL_POLYGON_SMOOTH 0x0B41
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_ALPHA_BITS_ARB 0x201B
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_SAMPLES_ARB 0x2042
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_TYPE_RGBA_ARB 0x202B
#define WGL_PIXEL_TYPE_ARB 0x2013
const char *glErrNames[] = {
"GL_INVALID_ENUM",
"GL_INVALID_VALUE",
"GL_INVALID_OPERATION",
"###",
"####",
"GL_OUT_OF_MEMORY"};
void checkGLErrFunc(const char *filename, int line) {
int e = glGetError();
if(e) {
const char *errName = glErrNames[e - GL_INVALID_ENUM];
printf("Error %s (%d): %s, line %d\n", errName, e, filename, line);
Assert(0);
}
}
// ---------------------------------------------------------------------------
// ------ glGenTextures ------
typedef void __stdcall glGenTexturesFunc(GLsizei, GLuint *);
glGenTexturesFunc * _glGenTextures;
void glGenTextures(GLsizei arg0, GLuint * arg1){
_glGenTextures(arg0, arg1);
GLERR();
}
// ------ glBindTexture ------
typedef void __stdcall glBindTextureFunc(GLenum, GLuint);
glBindTextureFunc * _glBindTexture;
void glBindTexture(GLenum arg0, GLuint arg1){
_glBindTexture(arg0, arg1);
GLERR();
}
// ------ glTexImage2D ------
typedef void __stdcall glTexImage2DFunc(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
glTexImage2DFunc * _glTexImage2D;
void glTexImage2D(GLenum arg0, GLint arg1, GLint arg2, GLsizei arg3, GLsizei arg4, GLint arg5, GLenum arg6, GLenum arg7, const GLvoid * arg8){
_glTexImage2D(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
GLERR();
}
// ------ glTexParameteri ------
typedef void __stdcall glTexParameteriFunc(GLenum, GLenum, GLint);
glTexParameteriFunc * _glTexParameteri;
void glTexParameteri(GLenum arg0, GLenum arg1, GLint arg2){
_glTexParameteri(arg0, arg1, arg2);
GLERR();
}
// ------ glGetError ------
typedef GLenum __stdcall glGetErrorFunc();
glGetErrorFunc * _glGetError;
GLenum glGetError(){
GLenum Result = _glGetError();
return Result;
}
// ------ glEnable ------
typedef void __stdcall glEnableFunc(GLenum);
glEnableFunc * _glEnable;
void glEnable(GLenum arg0){
_glEnable(arg0);
GLERR();
}
// ------ glDisable ------
typedef void __stdcall glDisableFunc(GLenum);
glDisableFunc * _glDisable;
void glDisable(GLenum arg0){
_glDisable(arg0);
GLERR();
}
// ------ glBegin ------
typedef void __stdcall glBeginFunc(GLenum);
glBeginFunc * _glBegin;
void glBegin(GLenum arg0){
_glBegin(arg0);
}
// ------ glEnd ------
typedef void __stdcall glEndFunc();
glEndFunc * _glEnd;
void glEnd(){
_glEnd();
GLERR();
}
// ------ glTexCoord2f ------
typedef void __stdcall glTexCoord2fFunc(GLfloat, GLfloat);
glTexCoord2fFunc * _glTexCoord2f;
void glTexCoord2f(GLfloat arg0, GLfloat arg1){
_glTexCoord2f(arg0, arg1);
}
// ------ glVertex2f ------
typedef void __stdcall glVertex2fFunc(GLfloat, GLfloat);
glVertex2fFunc * _glVertex2f;
void glVertex2f(GLfloat arg0, GLfloat arg1){
_glVertex2f(arg0, arg1);
}
// ------ glEnableClientState ------
typedef void __stdcall glEnableClientStateFunc(GLenum);
glEnableClientStateFunc * _glEnableClientState;
void glEnableClientState(GLenum arg0){
_glEnableClientState(arg0);
GLERR();
}
// ------ glDisableClientState ------
typedef void __stdcall glDisableClientStateFunc(GLenum);
glDisableClientStateFunc * _glDisableClientState;
void glDisableClientState(GLenum arg0){
_glDisableClientState(arg0);
GLERR();
}
// ------ glVertexPointer ------
typedef void __stdcall glVertexPointerFunc(GLint, GLenum, GLsizei, const GLvoid *);
glVertexPointerFunc * _glVertexPointer;
void glVertexPointer(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3){
_glVertexPointer(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glTexCoordPointer ------
typedef void __stdcall glTexCoordPointerFunc(GLint, GLenum, GLsizei, const GLvoid *);
glTexCoordPointerFunc * _glTexCoordPointer;
void glTexCoordPointer(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3){
_glTexCoordPointer(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glColorPointer ------
typedef void __stdcall glColorPointerFunc(GLint, GLenum, GLsizei, const GLvoid *);
glColorPointerFunc * _glColorPointer;
void glColorPointer(GLint arg0, GLenum arg1, GLsizei arg2, const GLvoid * arg3){
_glColorPointer(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glDrawArrays ------
typedef void __stdcall glDrawArraysFunc(GLenum, GLint, GLsizei);
glDrawArraysFunc * _glDrawArrays;
void glDrawArrays(GLenum arg0, GLint arg1, GLsizei arg2){
_glDrawArrays(arg0, arg1, arg2);
GLERR();
}
// ------ glClearColor ------
typedef void __stdcall glClearColorFunc(GLclampf, GLclampf, GLclampf, GLclampf);
glClearColorFunc * _glClearColor;
void glClearColor(GLclampf arg0, GLclampf arg1, GLclampf arg2, GLclampf arg3){
_glClearColor(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glClear ------
typedef void __stdcall glClearFunc(GLbitfield);
glClearFunc * _glClear;
void glClear(GLbitfield arg0){
_glClear(arg0);
GLERR();
}
// ------ glLinkProgram ------
typedef void __stdcall glLinkProgramFunc(GLuint);
glLinkProgramFunc * _glLinkProgram;
void glLinkProgram(GLuint arg0){
_glLinkProgram(arg0);
GLERR();
}
// ------ glShaderSource ------
typedef void __stdcall glShaderSourceFunc(GLuint, GLsizei, const GLchar * const *, const GLint *);
glShaderSourceFunc * _glShaderSource;
void glShaderSource(GLuint arg0, GLsizei arg1, const GLchar * const * arg2, const GLint * arg3){
_glShaderSource(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glUseProgram ------
typedef void __stdcall glUseProgramFunc(GLuint);
glUseProgramFunc * _glUseProgram;
void glUseProgram(GLuint arg0){
_glUseProgram(arg0);
GLERR();
}
// ------ glCompileShader ------
typedef void __stdcall glCompileShaderFunc(GLuint);
glCompileShaderFunc * _glCompileShader;
void glCompileShader(GLuint arg0){
_glCompileShader(arg0);
GLERR();
}
// ------ glCreateProgram ------
typedef GLuint __stdcall glCreateProgramFunc();
glCreateProgramFunc * _glCreateProgram;
GLuint glCreateProgram(){
GLuint Result = _glCreateProgram();
GLERR();
return Result;
}
// ------ glCreateShader ------
typedef GLuint __stdcall glCreateShaderFunc(GLenum);
glCreateShaderFunc * _glCreateShader;
GLuint glCreateShader(GLenum arg0){
GLuint Result = _glCreateShader(arg0);
GLERR();
return Result;
}
// ------ glGetShaderiv ------
typedef void __stdcall glGetShaderivFunc(GLuint, GLenum, GLint *);
glGetShaderivFunc * _glGetShaderiv;
void glGetShaderiv(GLuint arg0, GLenum arg1, GLint * arg2){
_glGetShaderiv(arg0, arg1, arg2);
GLERR();
}
// ------ glGetShaderInfoLog ------
typedef void __stdcall glGetShaderInfoLogFunc(GLuint, GLsizei, GLsizei *, GLchar *);
glGetShaderInfoLogFunc * _glGetShaderInfoLog;
void glGetShaderInfoLog(GLuint arg0, GLsizei arg1, GLsizei * arg2, GLchar * arg3){
_glGetShaderInfoLog(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glAttachShader ------
typedef void __stdcall glAttachShaderFunc(GLuint, GLuint);
glAttachShaderFunc * _glAttachShader;
void glAttachShader(GLuint arg0, GLuint arg1){
_glAttachShader(arg0, arg1);
GLERR();
}
// ------ glGetProgramiv ------
typedef void __stdcall glGetProgramivFunc(GLuint, GLenum, GLint *);
glGetProgramivFunc * _glGetProgramiv;
void glGetProgramiv(GLuint arg0, GLenum arg1, GLint * arg2){
_glGetProgramiv(arg0, arg1, arg2);
GLERR();
}
// ------ glGetProgramInfoLog ------
typedef void __stdcall glGetProgramInfoLogFunc(GLuint, GLsizei, GLsizei *, GLchar *);
glGetProgramInfoLogFunc * _glGetProgramInfoLog;
void glGetProgramInfoLog(GLuint arg0, GLsizei arg1, GLsizei * arg2, GLchar * arg3){
_glGetProgramInfoLog(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glGetUniformLocation ------
typedef GLint __stdcall glGetUniformLocationFunc(GLuint, const GLchar *);
glGetUniformLocationFunc * _glGetUniformLocation;
GLint glGetUniformLocation(GLuint arg0, const GLchar * arg1){
GLint Result = _glGetUniformLocation(arg0, arg1);
GLERR();
return Result;
}
// ------ glUniform1i ------
typedef void __stdcall glUniform1iFunc(GLint, GLint);
glUniform1iFunc * _glUniform1i;
void glUniform1i(GLint arg0, GLint arg1){
_glUniform1i(arg0, arg1);
GLERR();
}
// ------ glGenBuffers ------
typedef void __stdcall glGenBuffersFunc(GLsizei, GLuint *);
glGenBuffersFunc * _glGenBuffers;
void glGenBuffers(GLsizei arg0, GLuint * arg1){
_glGenBuffers(arg0, arg1);
GLERR();
}
// ------ glBindBuffer ------
typedef void __stdcall glBindBufferFunc(GLenum, GLuint);
glBindBufferFunc * _glBindBuffer;
void glBindBuffer(GLenum arg0, GLuint arg1){
_glBindBuffer(arg0, arg1);
GLERR();
}
// ------ glBufferData ------
typedef void __stdcall glBufferDataFunc(GLenum, GLsizeiptr, const void *, GLenum);
glBufferDataFunc * _glBufferData;
void glBufferData(GLenum arg0, GLsizeiptr arg1, const void * arg2, GLenum arg3){
_glBufferData(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glVertexAttribPointer ------
typedef void __stdcall glVertexAttribPointerFunc(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *);
glVertexAttribPointerFunc * _glVertexAttribPointer;
void glVertexAttribPointer(GLuint arg0, GLint arg1, GLenum arg2, GLboolean arg3, GLsizei arg4, const void * arg5){
_glVertexAttribPointer(arg0, arg1, arg2, arg3, arg4, arg5);
GLERR();
}
// ------ glEnableVertexAttribArray ------
typedef void __stdcall glEnableVertexAttribArrayFunc(GLuint);
glEnableVertexAttribArrayFunc * _glEnableVertexAttribArray;
void glEnableVertexAttribArray(GLuint arg0){
_glEnableVertexAttribArray(arg0);
GLERR();
}
// ------ glUniformMatrix4fv ------
typedef void __stdcall glUniformMatrix4fvFunc(GLint, GLsizei, GLboolean, const GLfloat *);
glUniformMatrix4fvFunc * _glUniformMatrix4fv;
void glUniformMatrix4fv(GLint arg0, GLsizei arg1, GLboolean arg2, const GLfloat * arg3){
_glUniformMatrix4fv(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glDrawElements ------
typedef void __stdcall glDrawElementsFunc(GLenum, GLsizei, GLenum, const void *);
glDrawElementsFunc * _glDrawElements;
void glDrawElements(GLenum arg0, GLsizei arg1, GLenum arg2, const void * arg3){
_glDrawElements(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glDisableVertexAttribArray ------
typedef void __stdcall glDisableVertexAttribArrayFunc(GLuint);
glDisableVertexAttribArrayFunc * _glDisableVertexAttribArray;
void glDisableVertexAttribArray(GLuint arg0){
_glDisableVertexAttribArray(arg0);
GLERR();
}
// ------ glGenFramebuffers ------
typedef void __stdcall glGenFramebuffersFunc(GLsizei, GLuint *);
glGenFramebuffersFunc * _glGenFramebuffers;
void glGenFramebuffers(GLsizei arg0, GLuint * arg1){
_glGenFramebuffers(arg0, arg1);
GLERR();
}
// ------ glBindFramebuffer ------
typedef void __stdcall glBindFramebufferFunc(GLenum, GLuint);
glBindFramebufferFunc * _glBindFramebuffer;
void glBindFramebuffer(GLenum arg0, GLuint arg1){
_glBindFramebuffer(arg0, arg1);
GLERR();
}
// ------ glFramebufferTexture2D ------
typedef void __stdcall glFramebufferTexture2DFunc(GLenum, GLenum, GLenum, GLuint, GLint);
glFramebufferTexture2DFunc * _glFramebufferTexture2D;
void glFramebufferTexture2D(GLenum arg0, GLenum arg1, GLenum arg2, GLuint arg3, GLint arg4){
_glFramebufferTexture2D(arg0, arg1, arg2, arg3, arg4);
GLERR();
}
// ------ glCheckFramebufferStatus ------
typedef GLenum __stdcall glCheckFramebufferStatusFunc(GLenum);
glCheckFramebufferStatusFunc * _glCheckFramebufferStatus;
GLenum glCheckFramebufferStatus(GLenum arg0){
GLenum Result = _glCheckFramebufferStatus(arg0);
GLERR();
return Result;
}
// ------ glDeleteFramebuffers ------
typedef void __stdcall glDeleteFramebuffersFunc(GLsizei, const GLuint *);
glDeleteFramebuffersFunc * _glDeleteFramebuffers;
void glDeleteFramebuffers(GLsizei arg0, const GLuint * arg1){
_glDeleteFramebuffers(arg0, arg1);
GLERR();
}
// ------ glDeleteTextures ------
typedef void __stdcall glDeleteTexturesFunc(GLsizei, const GLuint *);
glDeleteTexturesFunc * _glDeleteTextures;
void glDeleteTextures(GLsizei arg0, const GLuint * arg1){
_glDeleteTextures(arg0, arg1);
GLERR();
}
// ------ glDrawBuffer ------
typedef void __stdcall glDrawBufferFunc(GLenum);
glDrawBufferFunc * _glDrawBuffer;
void glDrawBuffer(GLenum arg0){
_glDrawBuffer(arg0);
GLERR();
}
// ------ glBlendFunc ------
typedef void __stdcall glBlendFuncFunc(GLenum, GLenum);
glBlendFuncFunc * _glBlendFunc;
void glBlendFunc(GLenum arg0, GLenum arg1){
_glBlendFunc(arg0, arg1);
GLERR();
}
// ------ glScissor ------
typedef void __stdcall glScissorFunc(GLint, GLint, GLsizei, GLsizei);
glScissorFunc * _glScissor;
void glScissor(GLint arg0, GLint arg1, GLsizei arg2, GLsizei arg3){
_glScissor(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glViewport ------
typedef void __stdcall glViewportFunc(GLint, GLint, GLsizei, GLsizei);
glViewportFunc * _glViewport;
void glViewport(GLint arg0, GLint arg1, GLsizei arg2, GLsizei arg3){
_glViewport(arg0, arg1, arg2, arg3);
GLERR();
}
// ------ glGetString ------
typedef const GLubyte * __stdcall glGetStringFunc(GLenum);
glGetStringFunc * _glGetString;
const GLubyte * glGetString(GLenum arg0){
const GLubyte * Result = _glGetString(arg0);
GLERR();
return Result;
}
// ------ glPolygonMode ------
typedef void __stdcall glPolygonModeFunc(GLenum, GLenum);
glPolygonModeFunc * _glPolygonMode;
void glPolygonMode(GLenum arg0, GLenum arg1){
_glPolygonMode(arg0, arg1);
GLERR();
}
// ------ wglChoosePixelFormatARB ------
typedef BOOL __stdcall wglChoosePixelFormatARBFunc(HDC, const int *, const FLOAT *, UINT, int *, UINT *);
wglChoosePixelFormatARBFunc * _wglChoosePixelFormatARB;
BOOL wglChoosePixelFormatARB(HDC arg0, const int * arg1, const FLOAT * arg2, UINT arg3, int * arg4, UINT * arg5){
BOOL Result = _wglChoosePixelFormatARB(arg0, arg1, arg2, arg3, arg4, arg5);
GLERR();
return Result;
}
// ------ wglCreateContextAttribsARB ------
typedef HGLRC __stdcall wglCreateContextAttribsARBFunc(HDC, HGLRC, const int *);
wglCreateContextAttribsARBFunc * _wglCreateContextAttribsARB;
HGLRC wglCreateContextAttribsARB(HDC arg0, HGLRC arg1, const int * arg2){
HGLRC Result = _wglCreateContextAttribsARB(arg0, arg1, arg2);
return Result;
}
// ------ wglSwapIntervalEXT ------
typedef BOOL __stdcall wglSwapIntervalEXTFunc(i32);
wglSwapIntervalEXTFunc * _wglSwapIntervalEXT;
BOOL wglSwapIntervalEXT(i32 arg0){
BOOL Result = _wglSwapIntervalEXT(arg0);
GLERR();
return Result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment