X-Git-Url: https://git.ralfj.de/gltest.git/blobdiff_plain/b4dc0596570275aa9def5ff63af951beb8473d58..3e648337c136c8a8715d642857faa9e00a6db180:/glutil_gl2.cpp?ds=sidebyside diff --git a/glutil_gl2.cpp b/glutil_gl2.cpp index ad89138..87d8e0c 100644 --- a/glutil_gl2.cpp +++ b/glutil_gl2.cpp @@ -16,18 +16,120 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "glutil.h" + #include #include +#include +#include -#include "glutil.h" +// extension functions we use +typedef GLuint (*GLCREATESHADERPROC) (GLenum type); +typedef void (*GLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (*GLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (*GLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length); +typedef void (*GLCOMPILESHADERPROC) (GLuint shader); +typedef GLuint (*GLCREATEPROGRAMPROC) (void); +typedef void (*GLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (*GLLINKPROGRAMPROC) (GLuint program); +typedef GLint (*GLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (*GLUSEPROGRAMPROC) (GLuint program); + +typedef void (*GLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (*GLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (*GLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef void (*GLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (*GLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); +typedef void (*GLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); + +#ifdef CON_GL3 +// VAOs are only supported in GL3+, and not needed in earler contexts +typedef void (*GLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (*GLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); +typedef void (*GLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +#endif + +GLGETSHADERIVPROC p_glGetShaderiv = NULL; +GLGETSHADERINFOLOGPROC p_glGetShaderInfoLog = NULL; +GLCREATESHADERPROC p_glCreateShader = NULL; +GLSHADERSOURCEPROC p_glShaderSource = NULL; +GLCOMPILESHADERPROC p_glCompileShader = NULL; +GLCREATEPROGRAMPROC p_glCreateProgram = NULL; +GLATTACHSHADERPROC p_glAttachShader = NULL; +GLLINKPROGRAMPROC p_glLinkProgram = NULL; +GLGETATTRIBLOCATIONPROC p_glGetAttribLocation = NULL; +GLUSEPROGRAMPROC p_glUseProgram = NULL; + +GLVERTEXATTRIBPOINTERPROC p_glVertexAttribPointer = NULL; +GLENABLEVERTEXATTRIBARRAYPROC p_glEnableVertexAttribArray = NULL; +GLGENBUFFERSPROC p_glGenBuffers = NULL; +GLBINDBUFFERPROC p_glBindBuffer = NULL; +GLBUFFERDATAPROC p_glBufferData = NULL; +GLDELETEBUFFERSPROC p_glDeleteBuffers = NULL; + +#ifdef CON_GL3 +GLBINDVERTEXARRAYPROC p_glBindVertexArray = NULL; +GLDELETEVERTEXARRAYSPROC p_glDeleteVertexArrays = NULL; +GLGENVERTEXARRAYSPROC p_glGenVertexArrays = NULL; +#endif + +// resolve function pointers +static T_proc resolveFunctionPointer(T_glGetProcAddress p_glGetProcAddress, const char *name) +{ + T_proc proc = p_glGetProcAddress(name); + if (proc == NULL) { + die("Error resolvung function %s\n", name); + } + return proc; +} + +void resolveFunctionPointers(T_glGetProcAddress p_glGetProcAddress) +{ +#ifdef CON_GL1 + // we need to check if we have GL 2.0 or greater + std::string version = (char*)glGetString(GL_VERSION); + std::stringstream ssv(version); + std::string major; + std::getline(ssv, major, '.'); + std::stringstream ssm(major); + int majorVersion; + ssm >> majorVersion; + if (majorVersion < 2) { + die("Need at least GL 2.0 to function properly, but detected version %d\n", majorVersion); + } +#endif + + // now get the function pointers + p_glGetShaderiv = (GLGETSHADERIVPROC)resolveFunctionPointer(p_glGetProcAddress, "glGetShaderiv"); + p_glGetShaderInfoLog = (GLGETSHADERINFOLOGPROC)resolveFunctionPointer(p_glGetProcAddress, "glGetShaderInfoLog"); + p_glCreateShader = (GLCREATESHADERPROC)resolveFunctionPointer(p_glGetProcAddress, "glCreateShader"); + p_glShaderSource = (GLSHADERSOURCEPROC)resolveFunctionPointer(p_glGetProcAddress, "glShaderSource"); + p_glCompileShader = (GLCOMPILESHADERPROC)resolveFunctionPointer(p_glGetProcAddress, "glCompileShader"); + p_glCreateProgram = (GLCREATEPROGRAMPROC)resolveFunctionPointer(p_glGetProcAddress, "glCreateProgram"); + p_glAttachShader = (GLATTACHSHADERPROC)resolveFunctionPointer(p_glGetProcAddress, "glAttachShader"); + p_glLinkProgram = (GLLINKPROGRAMPROC)resolveFunctionPointer(p_glGetProcAddress, "glLinkProgram"); + p_glGetAttribLocation = (GLGETATTRIBLOCATIONPROC)resolveFunctionPointer(p_glGetProcAddress, "glGetAttribLocation"); -#if defined(CON_GL1) -#error "GL1 contexts do not support GL2 functionality" +#ifdef CON_GL3 + p_glBindVertexArray = (GLBINDVERTEXARRAYPROC)resolveFunctionPointer(p_glGetProcAddress, "glBindVertexArray"); + p_glDeleteVertexArrays = (GLDELETEVERTEXARRAYSPROC)resolveFunctionPointer(p_glGetProcAddress, "glDeleteVertexArrays"); + p_glGenVertexArrays = (GLGENVERTEXARRAYSPROC)resolveFunctionPointer(p_glGetProcAddress, "glGenVertexArrays"); #endif + p_glUseProgram = (GLUSEPROGRAMPROC)resolveFunctionPointer(p_glGetProcAddress, "glUseProgram"); + p_glVertexAttribPointer = (GLVERTEXATTRIBPOINTERPROC)resolveFunctionPointer(p_glGetProcAddress, "glVertexAttribPointer"); + p_glEnableVertexAttribArray = (GLENABLEVERTEXATTRIBARRAYPROC)resolveFunctionPointer(p_glGetProcAddress, "glEnableVertexAttribArray"); + p_glGenBuffers = (GLGENBUFFERSPROC)resolveFunctionPointer(p_glGetProcAddress, "glGenBuffers"); + p_glBindBuffer = (GLBINDBUFFERPROC)resolveFunctionPointer(p_glGetProcAddress, "glBindBuffer"); + p_glBufferData = (GLBUFFERDATAPROC)resolveFunctionPointer(p_glGetProcAddress, "glBufferData"); + p_glDeleteBuffers = (GLDELETEBUFFERSPROC)resolveFunctionPointer(p_glGetProcAddress, "glDeleteBuffers"); +} + // shaders static const char *vertex_shader_source = "#version 100 \n\ +precision mediump float;\n\ +precision mediump int;\n\ attribute vec2 position; \n\ attribute vec3 color; \n\ varying vec3 frag_color; \n\ @@ -38,6 +140,8 @@ void main() \n\ }"; static const char *fragment_shader_source = "#version 100 \n\ +precision mediump float;\n\ +precision mediump int;\n\ varying vec3 frag_color; \n\ void main(void) \n\ { \n\ @@ -56,34 +160,36 @@ static struct { static void show_info_log(GLuint object) { GLint log_length; - glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length); + p_glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length); char *log = new char[log_length]; - glGetShaderInfoLog(object, log_length, NULL, log); + p_glGetShaderInfoLog(object, log_length, NULL, log); fprintf(stderr, "%s", log); delete[] log; } static GLuint compile_shader(GLenum shader_type, const char *source) { - GLuint shader = glCreateShader(shader_type); - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); + GLuint shader = p_glCreateShader(shader_type); + p_glShaderSource(shader, 1, &source, NULL); + p_glCompileShader(shader); GLint shader_ok; - glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_ok); + p_glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_ok); if (!shader_ok) { fprintf(stderr, "Failed to compile shader\n"); show_info_log(shader); exit(1); } + checkGlError("Compiling shader"); return shader; } static GLuint createArrayBuffer(GLsizeiptr size, GLfloat *data) { GLuint buffer; - glGenBuffers(1, &buffer); - glBindBuffer(GL_ARRAY_BUFFER, buffer); - glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + p_glGenBuffers(1, &buffer); + p_glBindBuffer(GL_ARRAY_BUFFER, buffer); + p_glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + checkGlError("Creating array buffer"); return buffer; } @@ -92,18 +198,27 @@ void initialise2dProjection() { GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_source); GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_source); - program = glCreateProgram(); - glAttachShader(program, vertex_shader); - glAttachShader(program, fragment_shader); - glLinkProgram(program); - attributes.position = glGetAttribLocation(program, "position"); - attributes.color = glGetAttribLocation(program, "color"); + program = p_glCreateProgram(); + p_glAttachShader(program, vertex_shader); + p_glAttachShader(program, fragment_shader); + p_glLinkProgram(program); + attributes.position = p_glGetAttribLocation(program, "position"); + attributes.color = p_glGetAttribLocation(program, "color"); } // draw a quad void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) { - glUseProgram(program); + p_glUseProgram(program); + checkGlError("Enabling the shaders"); + +#ifdef CON_GL3 + // create a vertex array obect and use it + GLuint vao; + p_glGenVertexArrays(1, &vao); + p_glBindVertexArray(vao); + checkGlError("Creating a VAO"); +#endif // send vertex data to card with given attribute GLfloat vertex_buffer_data[] = { @@ -113,7 +228,7 @@ void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, x1, y2, }; GLuint vertex_buffer = createArrayBuffer(sizeof(vertex_buffer_data), vertex_buffer_data); - glVertexAttribPointer( + p_glVertexAttribPointer( attributes.position, /* attribute */ 2, /* size */ GL_FLOAT, /* type */ @@ -121,7 +236,9 @@ void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, 0, /* stride */ (void*)0 /* array buffer offset */ ); - glEnableVertexAttribArray(attributes.position); + checkGlError("Preparing vertex data"); + p_glEnableVertexAttribArray(attributes.position); + checkGlError("Sending vertex data"); // same with color data GLfloat color_buffer_data[] = { @@ -131,7 +248,7 @@ void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, red, green, blue, }; GLuint color_buffer = createArrayBuffer(sizeof(color_buffer_data), color_buffer_data); - glVertexAttribPointer( + p_glVertexAttribPointer( attributes.color, /* attribute */ 3, /* size */ GL_FLOAT, /* type */ @@ -139,12 +256,19 @@ void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, 0, /* stride */ (void*)0 /* array buffer offset */ ); - glEnableVertexAttribArray(attributes.color); + checkGlError("Preparing color data"); + p_glEnableVertexAttribArray(attributes.color); + checkGlError("Sending color data"); // draw glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + checkGlError("Drawing"); // cleanup - glDeleteBuffers(1, &vertex_buffer); - glDeleteBuffers(1, &color_buffer); + p_glDeleteBuffers(1, &vertex_buffer); + p_glDeleteBuffers(1, &color_buffer); +#ifdef CON_GL3 + p_glDeleteVertexArrays(1, &vao); +#endif + checkGlError("Doing cleanup"); }