add {glx,egl}2test using the GL2 API in a classic OpenGL context
authorRalf Jung <post@ralfj.de>
Mon, 9 Sep 2013 14:12:45 +0000 (16:12 +0200)
committerRalf Jung <post@ralfj.de>
Mon, 9 Sep 2013 14:12:45 +0000 (16:12 +0200)
.gitignore
Makefile
eglbackend.cpp
glutil.h
glutil_gl1.cpp
glutil_gl2.cpp
glwindow.cpp
glxbackend.cpp

index a1b274b25115ab83770d2f81e7067937f95e4b6b..a126cd209e6e0d3a5722add436be560be2ca0426 100644 (file)
@@ -1,4 +1,6 @@
 glxtest
+glx2test
 egltest
-eglinfo
+egl2test
 glestest
+eglinfo
index c84863935c3c5c9c53110e88f995a301ecee1205..cfa88c33684df4b978f51f8404e0fdbaaa089fee 100644 (file)
--- 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)
index cbe724cff375cbb5e22329d4f593bfdd437102ca..ef27997391856b882859bb57b4259ba6440123fc 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "eglbackend.h"
+#include "glutil.h"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -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()
index e7a39ad86ddad3652191b6b2b254b21cdb1c8c6b..688ee2995d46311b25c0c15cc69ec9e9fe434109 100644 (file)
--- a/glutil.h
+++ b/glutil.h
 #include <GL/gl.h>
 #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);
index 596704e82e705d2877bbdf60d21efd91ac90315f..1cedfac8e81348d6a7740f4e9487f097087b6f03 100644 (file)
 #error "GLES2 contexts do not support GL1 functionality"
 #endif
 
+void resolveFunctionPointers(T_glGetProcAddress)
+{
+       // nothing to do
+}
+
 // initialisation
 void initialise2dProjection()
 {
index ad89138d14f3748e90a52fd8919c3a4372b9794f..e8cc1904787cab795391912a89e26f276344e329 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string>
+#include <sstream>
 
 #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);
 }
index 64d007575bf2e9dc6310e057c27a0fdecc5849f9..ca6dbb95018d91fa416360a542fe32edc1c0ac33 100644 (file)
@@ -17,7 +17,6 @@
  */
 
 #include "glwindow.h"
-#include "glutil.h"
 
 #include <assert.h>
 #include <X11/Xutil.h>
@@ -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);
 }
index b2383826b66c257090493d5c530f09f27b2aa6c9..3ebc8789116df308498d936260124b3ab8e275b3 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "glxbackend.h"
+#include "glutil.h"
 
 #include <stdio.h>
 #include <assert.h>
@@ -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()