From: Ralf Jung Date: Mon, 9 Sep 2013 14:12:45 +0000 (+0200) Subject: add {glx,egl}2test using the GL2 API in a classic OpenGL context X-Git-Url: https://git.ralfj.de/gltest.git/commitdiff_plain/dac0dad539be501c94cb8646d979e6e7787e1992?ds=inline;hp=a0cb14324fbd2791d62df09e8d10541f280b60ee add {glx,egl}2test using the GL2 API in a classic OpenGL context --- diff --git a/.gitignore b/.gitignore index a1b274b..a126cd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ glxtest +glx2test egltest -eglinfo +egl2test glestest +eglinfo diff --git a/Makefile b/Makefile index c848639..cfa88c3 100644 --- a/Makefile +++ b/Makefile @@ -1,27 +1,35 @@ -FLAGS := -Wall -g -O1 +CFLAGS := -Wall -g -O1 COMMON_SRC = gltest.cpp glwindow.cpp COMMON_HDR = glwindow.h glutil.h +COMMON_LD = -lX11 -lboost_program_options -BINARIES := glxtest egltest glestest eglinfo +BINARIES := glxtest egltest glx2test egl2test glestest eglinfo all: $(BINARIES) # choices (not all combinations are valid) -# windowing system WIN_{GLX,EGL} -# the kind of context CON_{GL1,GLES2} +# windowing system: WIN_{GLX,EGL} +# the kind of context: CON_{GL1,GLES2} +# the API used to draw: compile in glutil_gl1.cpp or glutil_gl2.cpp glxtest: $(COMMON_SRC) $(COMMON_HDR) glutil_gl1.cpp glxbackend.cpp glxbackend.h - g++ $(FLAGS) -DWIN_GLX -DCON_GL1 $(COMMON_SRC) glutil_gl1.cpp glxbackend.cpp -lGL -lX11 -lboost_program_options -o glxtest + g++ $(CFLAGS) -DWIN_GLX -DCON_GL1 $(COMMON_SRC) glutil_gl1.cpp glxbackend.cpp -lGL $(COMMON_LD) -o $@ egltest: $(COMMON_SRC) $(COMMON_HDR) glutil_gl1.cpp eglbackend.cpp eglbackend.h - g++ $(FLAGS) -DWIN_EGL -DCON_GL1 $(COMMON_SRC) glutil_gl1.cpp eglbackend.cpp -lEGL -lGL -lX11 -lboost_program_options -o egltest + g++ $(CFLAGS) -DWIN_EGL -DCON_GL1 $(COMMON_SRC) glutil_gl1.cpp eglbackend.cpp -lEGL -lGL $(COMMON_LD) -o $@ + +glx2test: $(COMMON_SRC) $(COMMON_HDR) glutil_gl2.cpp glxbackend.cpp glxbackend.h + g++ $(CFLAGS) -DWIN_GLX -DCON_GL1 $(COMMON_SRC) glutil_gl2.cpp glxbackend.cpp -lGL $(COMMON_LD) -o $@ + +egl2test: $(COMMON_SRC) $(COMMON_HDR) glutil_gl2.cpp eglbackend.cpp eglbackend.h + g++ $(CFLAGS) -DWIN_EGL -DCON_GL1 $(COMMON_SRC) glutil_gl2.cpp eglbackend.cpp -lEGL -lGL $(COMMON_LD) -o $@ glestest: $(COMMON_SRC) $(COMMON_HDR) glutil_gl2.cpp eglbackend.cpp eglbackend.h - g++ $(FLAGS) -DWIN_EGL -DCON_GLES2 $(COMMON_SRC) glutil_gl2.cpp eglbackend.cpp -lEGL -lGLESv2 -lX11 -lboost_program_options -o glestest + g++ $(CFLAGS) -DWIN_EGL -DCON_GLES2 $(COMMON_SRC) glutil_gl2.cpp eglbackend.cpp -lEGL -lGLESv2 $(COMMON_LD) -o $@ eglinfo: eglinfo.c - gcc $(FLAGS) eglinfo.c -lEGL -lGL -lX11 -o eglinfo + gcc $(CFLAGS) eglinfo.c -lEGL -lGL -lX11 -o $@ clean: rm -f $(BINARIES) diff --git a/eglbackend.cpp b/eglbackend.cpp index cbe724c..ef27997 100644 --- a/eglbackend.cpp +++ b/eglbackend.cpp @@ -17,6 +17,7 @@ */ #include "eglbackend.h" +#include "glutil.h" #include #include @@ -120,6 +121,9 @@ void EGLBackend::createContext(Window window) exitEglError("Failed to create context"); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) exitEglError("Failed to make context current"); + printf("Using GL version: %s\n", glGetString(GL_VERSION)); + // initialise GL utilities + resolveFunctionPointers(eglGetProcAddress); } EGLBackend::~EGLBackend() diff --git a/glutil.h b/glutil.h index e7a39ad..688ee29 100644 --- a/glutil.h +++ b/glutil.h @@ -23,5 +23,11 @@ #include #endif +/* Function name resolving: Call this after initialising the context, but before any utility function is called */ +typedef void (*T_proc)(void); +typedef T_proc (*T_glGetProcAddress)(char const * procname); +void resolveFunctionPointers(T_glGetProcAddress p_glGetProcAddress); + +/* The actual utility functions */ void initialise2dProjection(); void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); diff --git a/glutil_gl1.cpp b/glutil_gl1.cpp index 596704e..1cedfac 100644 --- a/glutil_gl1.cpp +++ b/glutil_gl1.cpp @@ -22,6 +22,11 @@ #error "GLES2 contexts do not support GL1 functionality" #endif +void resolveFunctionPointers(T_glGetProcAddress) +{ + // nothing to do +} + // initialisation void initialise2dProjection() { diff --git a/glutil_gl2.cpp b/glutil_gl2.cpp index ad89138..e8cc190 100644 --- a/glutil_gl2.cpp +++ b/glutil_gl2.cpp @@ -18,12 +18,92 @@ #include #include +#include +#include #include "glutil.h" -#if defined(CON_GL1) -#error "GL1 contexts do not support GL2 functionality" +// 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); + +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; + +// resolve function pointers +static T_proc resolveFunctionPointer(T_glGetProcAddress p_glGetProcAddress, const char *name) +{ + T_proc proc = p_glGetProcAddress(name); + if (proc == NULL) { + fprintf(stderr, "Error resolvung function %s\n", name); + exit(1); + } + 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) { + fprintf(stderr, "Need at least GL 2.0 to function properly, but detected version %d\n", majorVersion); + exit(1); + } #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"); + 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 = @@ -56,20 +136,20 @@ 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); @@ -81,9 +161,9 @@ static GLuint compile_shader(GLenum shader_type, const char *source) 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); return buffer; } @@ -92,18 +172,18 @@ 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); // send vertex data to card with given attribute GLfloat vertex_buffer_data[] = { @@ -113,7 +193,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 +201,7 @@ void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, 0, /* stride */ (void*)0 /* array buffer offset */ ); - glEnableVertexAttribArray(attributes.position); + p_glEnableVertexAttribArray(attributes.position); // same with color data GLfloat color_buffer_data[] = { @@ -131,7 +211,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 +219,12 @@ void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, 0, /* stride */ (void*)0 /* array buffer offset */ ); - glEnableVertexAttribArray(attributes.color); + p_glEnableVertexAttribArray(attributes.color); // draw glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // cleanup - glDeleteBuffers(1, &vertex_buffer); - glDeleteBuffers(1, &color_buffer); + p_glDeleteBuffers(1, &vertex_buffer); + p_glDeleteBuffers(1, &color_buffer); } diff --git a/glwindow.cpp b/glwindow.cpp index 64d0075..ca6dbb9 100644 --- a/glwindow.cpp +++ b/glwindow.cpp @@ -17,7 +17,6 @@ */ #include "glwindow.h" -#include "glutil.h" #include #include @@ -61,7 +60,6 @@ void GLWindow::create(unsigned int width, unsigned int height) this->width = width; this->height = height; backend->createContext(window); - printf("Using GL version: %s\n", glGetString(GL_VERSION)); initGL(); resizeGL(width, height); } diff --git a/glxbackend.cpp b/glxbackend.cpp index b238382..3ebc878 100644 --- a/glxbackend.cpp +++ b/glxbackend.cpp @@ -17,6 +17,7 @@ */ #include "glxbackend.h" +#include "glutil.h" #include #include @@ -76,6 +77,9 @@ void GLXBackend::createContext(Window window) context = glXCreateContext(display, vi, 0, GL_TRUE); glXMakeCurrent(display, window, context); assert(glXIsDirect(display, context)); + printf("Using GL version: %s\n", glGetString(GL_VERSION)); + // initialise GL utilities + resolveFunctionPointers((T_glGetProcAddress)glXGetProcAddress); } GLXBackend::~GLXBackend()