support for GLES2
authorRalf Jung <post@ralfj.de>
Thu, 11 Apr 2013 21:01:18 +0000 (23:01 +0200)
committerRalf Jung <post@ralfj.de>
Thu, 11 Apr 2013 21:01:18 +0000 (23:01 +0200)
.gitignore
Makefile
eglbackend.cpp
gltest.cpp
glutil.h [new file with mode: 0644]
glutil_gl1.cpp [new file with mode: 0644]
glutil_gl2.cpp [new file with mode: 0644]

index e6c19fec6a0afecd9f27921c86b353bea1f15bee..a1b274b25115ab83770d2f81e7067937f95e4b6b 100644 (file)
@@ -1,3 +1,4 @@
 glxtest
 egltest
 eglinfo
 glxtest
 egltest
 eglinfo
+glestest
index c07c0fc69e65c63a5b44dce415322a878c30bdc0..52a6495d67aa3a1fc1876fc81fb14e0afdb39637 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,18 +1,23 @@
-FLAGS := -Wall
+FLAGS := -Wall -g -O1
 
 COMMON_SRC = gltest.cpp glwindow.cpp
 
 COMMON_SRC = gltest.cpp glwindow.cpp
-COMMON_HDR = glwindow.h
+COMMON_HDR = glwindow.h glutil.h
 
 
-all: glxtest egltest eglinfo
+BINARIES := glxtest egltest glestest eglinfo
 
 
-glxtest: $(COMMON_SRC) $(COMMON_HDR) glxbackend.cpp glxbackend.h
-       g++ $(FLAGS) -DUSE_GLX $(COMMON_SRC) glxbackend.cpp -lGL -lX11 -lboost_program_options -o glxtest
+all: $(BINARIES)
 
 
-egltest: $(COMMON_SRC) $(COMMON_HDR) eglbackend.cpp eglbackend.h
-       g++ $(FLAGS) -DUSE_EGL $(COMMON_SRC) eglbackend.cpp -lEGL -lGL -lX11 -lboost_program_options -o egltest
+glxtest: $(COMMON_SRC) $(COMMON_HDR) glutil_gl1.cpp glxbackend.cpp glxbackend.h
+       g++ $(FLAGS) -DUSE_GLX $(COMMON_SRC) glutil_gl1.cpp glxbackend.cpp -lGL -lX11 -lboost_program_options -o glxtest
+
+egltest: $(COMMON_SRC) $(COMMON_HDR) glutil_gl1.cpp eglbackend.cpp eglbackend.h
+       g++ $(FLAGS) -DUSE_EGL $(COMMON_SRC) glutil_gl1.cpp eglbackend.cpp -lEGL -lGL -lX11 -lboost_program_options -o egltest
+
+glestest: $(COMMON_SRC) $(COMMON_HDR) glutil_gl2.cpp eglbackend.cpp eglbackend.h
+       g++ $(FLAGS) -DUSE_EGL -DUSE_GLES $(COMMON_SRC) glutil_gl2.cpp eglbackend.cpp -lEGL -lGLESv2 -lX11 -lboost_program_options -o glestest
 
 eglinfo: eglinfo.c
        gcc $(FLAGS) eglinfo.c -lEGL -lGL -lX11 -o eglinfo
 
 clean:
 
 eglinfo: eglinfo.c
        gcc $(FLAGS) eglinfo.c -lEGL -lGL -lX11 -o eglinfo
 
 clean:
-       rm -f glxtest egltest eglinfo
+       rm -f $(BINARIES)
index ac7ab38d0f560950b5aabf7945f96660da8a996f..a9e20194003a998d4f1cffe47f2a17b4bdec9378 100644 (file)
@@ -49,7 +49,12 @@ static void exitEglError(const char *what)
        exit(1);
 }
 
        exit(1);
 }
 
-// attributes for a  visual in RGBA format with at least 4 bits per color
+static const EGLint context_attribs[] = {
+#ifdef USE_GLES
+       EGL_CONTEXT_CLIENT_VERSION, 2,
+#endif
+       EGL_NONE
+};
 static const EGLint config_attribs[] = {
        EGL_RED_SIZE,             4,
        EGL_GREEN_SIZE,           4,
 static const EGLint config_attribs[] = {
        EGL_RED_SIZE,             4,
        EGL_GREEN_SIZE,           4,
@@ -69,7 +74,12 @@ VisualID EGLBackend::initialize(Display *xDisplay)
                if (eglInitialize(display, &eglMajor, &eglMinor) == EGL_FALSE)
                        exitEglError("Failed to initialize EGL");
                printf("Using EGL version %d.%d\n", eglMajor, eglMinor);
                if (eglInitialize(display, &eglMajor, &eglMinor) == EGL_FALSE)
                        exitEglError("Failed to initialize EGL");
                printf("Using EGL version %d.%d\n", eglMajor, eglMinor);
-               eglBindAPI(EGL_OPENGL_API);
+#ifdef USE_GLES
+               if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE)
+#else
+               if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE)
+#endif
+                       exitEglError("Failed to bind API");
                // get an appropriate config
                EGLConfig configs[1];
                EGLint count;
                // get an appropriate config
                EGLConfig configs[1];
                EGLint count;
@@ -88,7 +98,7 @@ void EGLBackend::createContext(Window window)
        assert(display != EGL_NO_DISPLAY && context == EGL_NO_CONTEXT);
        surface = eglCreateWindowSurface(display, config, window, NULL);
        // create an EGL context and use it with the surface
        assert(display != EGL_NO_DISPLAY && context == EGL_NO_CONTEXT);
        surface = eglCreateWindowSurface(display, config, window, NULL);
        // create an EGL context and use it with the surface
-       context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
+       context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribs);
        if (context == EGL_NO_CONTEXT)
                exitEglError("Failed to create context");
        if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
        if (context == EGL_NO_CONTEXT)
                exitEglError("Failed to create context");
        if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
index d8768a77dea6d8dd9c9691b790233c26383cf8e0..440e8f5ef5d1564150e2f1d6062b4a15840460fd 100644 (file)
 #include <limits.h>
 #include <unistd.h>
 #include <assert.h>
 #include <limits.h>
 #include <unistd.h>
 #include <assert.h>
-#include <GL/gl.h>
 #include <boost/program_options.hpp>
 
 namespace po = boost::program_options;
 
 #include <boost/program_options.hpp>
 
 namespace po = boost::program_options;
 
-// include proper GL connector
+// my GL utility functions and the GL window class
+#include "glutil.h"
 #include "glwindow.h"
 #include "glwindow.h"
+// include proper GL backend
 #if defined(USE_GLX)
 #include "glxbackend.h"
 static GLBackend *createGLBackend()
 #if defined(USE_GLX)
 #include "glxbackend.h"
 static GLBackend *createGLBackend()
@@ -63,24 +64,29 @@ static double getTime()
        return tp.tv_sec + 1e-9 * tp.tv_nsec;
 }
 
        return tp.tv_sec + 1e-9 * tp.tv_nsec;
 }
 
-static void rectQuad(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
-{
-       glVertex2f(x1, y1);
-       glVertex2f(x2, y1);
-       glVertex2f(x2, y2);
-       glVertex2f(x1, y2);
-}
-
 // the window
 class TearTestWindow : public GLWindow {
 public:
 // the window
 class TearTestWindow : public GLWindow {
 public:
-       TearTestWindow(bool overdraw, bool copy, int sleep_time) : GLWindow(XOpenDisplay(0), createGLBackend()),
-               overdraw(overdraw), copy(copy), sleep_time(sleep_time), boxPos(0), boxDirection(1)
+       TearTestWindow() : GLWindow(XOpenDisplay(0), createGLBackend()),
+               overdraw(false), sleep_time(0), boxPos(0), boxDirection(1)
        {}
 
        {}
 
-       void setSwapInterval(int i) {
-               getBackend()->setSwapInterval(i);
-       }
+       void setOverdraw(bool overdraw) { this->overdraw = overdraw; }
+       void setSleepTime(int sleep_time) { this->sleep_time = sleep_time; }
+
+       void setSwapInterval(int i) { getBackend()->setSwapInterval(i); }
+
+private:
+       bool overdraw;
+       int sleep_time;
+       // animation control
+       double lastFrame;
+       GLfloat boxPos, boxDirection;
+       // FPS, profiler
+       double lastDisplay, lastProfile;                 
+       int framect;
+       ProfilerState curState;
+       double stateTime[NumProfilerStates];
 
 protected:
        virtual void initGL()
 
 protected:
        virtual void initGL()
@@ -99,17 +105,9 @@ protected:
        
        virtual void resizeGL(unsigned int width, unsigned int height)
        {
        
        virtual void resizeGL(unsigned int width, unsigned int height)
        {
-               // prevent divide-by-zero
-               if (height == 0)
-                       height = 1;
                glViewport(0, 0, width, height);
                glViewport(0, 0, width, height);
-               glMatrixMode(GL_PROJECTION);
-               glLoadIdentity();
-               glOrtho (0, 1, 1, 0, 0, 1);
-               glMatrixMode(GL_MODELVIEW);
+               initialise2dProjection();
                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-               glClear(GL_COLOR_BUFFER_BIT);
-               glFlush();
        }
        
        void profilerTick(ProfilerState nextState)
        }
        
        void profilerTick(ProfilerState nextState)
@@ -158,31 +156,18 @@ protected:
                profilerTick(StateClear);
                if (overdraw) {
                        // clear manually
                profilerTick(StateClear);
                if (overdraw) {
                        // clear manually
-                       glBegin(GL_QUADS);
-                       glColor3f(0.0f, 0.0f, 0.0f);
-                       rectQuad(0, 0, 1, 1);
-                       glEnd();
+                       drawQuad(/*color*/0.0f, 0.0f, 0.0f, /*coordinates*/0, 0, 1, 1);
                }
                else {
                        glClear(GL_COLOR_BUFFER_BIT);
                }
                //////////////////////////////////////////////
                profilerTick(StateDraw);
                }
                else {
                        glClear(GL_COLOR_BUFFER_BIT);
                }
                //////////////////////////////////////////////
                profilerTick(StateDraw);
-               glBegin(GL_QUADS);
-               glColor3f(0.8f, 1.0f, 0.75f);
-               rectQuad(boxPos, 0, boxPos+boxWidth, 1);
-               glEnd();
+               drawQuad(/*color*/0.8f, 1.0f, 0.75f, /*coordinates*/boxPos, 0, boxPos+boxWidth, 1);
                usleep(sleep_time*1000);
                //////////////////////////////////////////////
                profilerTick(StatePresent);
                usleep(sleep_time*1000);
                //////////////////////////////////////////////
                profilerTick(StatePresent);
-               if (copy) {
-                       glDrawBuffer(GL_FRONT);
-                       glCopyPixels(0, 0, getWidth(), getHeight(), GL_COLOR);
-                       glDrawBuffer(GL_BACK);
-               }
-               else {
-                       getBackend()->swapBuffers();
-               }
+               getBackend()->swapBuffers();
                //////////////////////////////////////////////
                profilerTick(StatePostRender);
                glFinish();
                //////////////////////////////////////////////
                profilerTick(StatePostRender);
                glFinish();
@@ -199,18 +184,6 @@ protected:
                        default: break;
                }
        }
                        default: break;
                }
        }
-
-private:
-       bool overdraw, copy;
-       int sleep_time;
-       // animation control
-       double lastFrame;
-       GLfloat boxPos, boxDirection;
-       // FPS, profiler
-       double lastDisplay, lastProfile;                 
-       int framect;
-       ProfilerState curState;
-       double stateTime[NumProfilerStates];
 };
 
 int main(int argc, char ** argv)
 };
 
 int main(int argc, char ** argv)
@@ -220,7 +193,6 @@ int main(int argc, char ** argv)
        desc.add_options()
                ("help,h", "produce help message")
                ("swap-interval,i", po::value<int>(), "set swap interval")
        desc.add_options()
                ("help,h", "produce help message")
                ("swap-interval,i", po::value<int>(), "set swap interval")
-               ("copy,c", "copy to front buffer (instead of performing a buffer swap)")
                ("overdraw,o", "overdraw previous image (instead of calling glClear)")
                ("sleep,s", po::value<int>()->default_value(0), "Number of milliseconds to sleap in each frame (in the drawing phase)")
        ;
                ("overdraw,o", "overdraw previous image (instead of calling glClear)")
                ("sleep,s", po::value<int>()->default_value(0), "Number of milliseconds to sleap in each frame (in the drawing phase)")
        ;
@@ -234,7 +206,9 @@ int main(int argc, char ** argv)
        }
 
        // actual program
        }
 
        // actual program
-       TearTestWindow w(vm.count("overdraw"), vm.count("copy"), vm["sleep"].as<int>());
+       TearTestWindow w;
+       w.setOverdraw(vm.count("overdraw"));
+       w.setSleepTime(vm["sleep"].as<int>());
        w.open(800, 600);
        if (vm.count("swap-interval"))
                w.setSwapInterval(vm["swap-interval"].as<int>());
        w.open(800, 600);
        if (vm.count("swap-interval"))
                w.setSwapInterval(vm["swap-interval"].as<int>());
diff --git a/glutil.h b/glutil.h
new file mode 100644 (file)
index 0000000..704d2cb
--- /dev/null
+++ b/glutil.h
@@ -0,0 +1,27 @@
+/* gltest - small OpenGL tearing test program
+ * Copyright (C) 2012-2013 Ralf Jung <post@ralfj.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifdef USE_GLES
+#include  <GLES2/gl2.h>
+#else
+#include <GL/gl.h>
+#endif
+
+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
new file mode 100644 (file)
index 0000000..8e31114
--- /dev/null
@@ -0,0 +1,40 @@
+/* gltest - small OpenGL tearing test program
+ * Copyright (C) 2012-2013 Ralf Jung <post@ralfj.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "glutil.h"
+
+// initialisation
+void initialise2dProjection()
+{
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       glOrtho (0, 1, 1, 0, 0, 1);
+       glMatrixMode(GL_MODELVIEW);
+}
+
+// draw a quad
+void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+       glBegin(GL_QUADS);
+       glColor3f(red, green, blue);
+       glVertex2f(x1, y1);
+       glVertex2f(x2, y1);
+       glVertex2f(x2, y2);
+       glVertex2f(x1, y2);
+       glEnd();
+}
\ No newline at end of file
diff --git a/glutil_gl2.cpp b/glutil_gl2.cpp
new file mode 100644 (file)
index 0000000..c14b3a5
--- /dev/null
@@ -0,0 +1,145 @@
+/* gltest - small OpenGL tearing test program
+ * Copyright (C) 2012-2013 Ralf Jung <post@ralfj.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "glutil.h"
+
+// shaders
+static const char *vertex_shader_source =
+"#version 100 \n\
+attribute vec2 position; \n\
+attribute vec3 color; \n\
+varying vec3 frag_color; \n\
+void main() \n\
+{ \n\
+       frag_color = color; \n\
+       gl_Position = vec4(position * vec2(2) - vec2(1), 0.0, 1.0); \n\
+}";
+static const char *fragment_shader_source =
+"#version 100 \n\
+varying vec3 frag_color; \n\
+void main(void) \n\
+{ \n\
+       gl_FragColor = vec4(frag_color, 1.0); \n\
+}";
+
+
+// OpenGL IDs (yeah, this is a bad hack... do we care?)
+static GLuint program;
+static struct {
+       GLint position;
+       GLint color;
+} attributes;
+
+// some local hlper functions
+static void show_info_log(GLuint object)
+{
+       GLint log_length;
+       glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
+       char *log = new char[log_length];
+       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);
+       GLint shader_ok;
+       glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_ok);
+       if (!shader_ok) {
+               fprintf(stderr, "Failed to compile shader\n");
+               show_info_log(shader);
+               exit(1);
+       }
+       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);
+       return buffer;
+}
+
+// initialisation
+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");
+}
+
+// draw a quad
+void drawQuad(GLfloat red, GLfloat green, GLfloat blue, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+       glUseProgram(program);
+       
+       // send vertex data to card with given attribute
+       GLfloat vertex_buffer_data[] = {
+               x1, y1,
+               x2, y1,
+               x2, y2,
+               x1, y2,
+       };
+       GLuint vertex_buffer = createArrayBuffer(sizeof(vertex_buffer_data), vertex_buffer_data);
+       glVertexAttribPointer(
+               attributes.position,              /* attribute */
+               2,                                /* size */
+               GL_FLOAT,                         /* type */
+               GL_FALSE,                         /* normalized? */
+               0,                                /* stride */
+               (void*)0                          /* array buffer offset */
+       );
+       glEnableVertexAttribArray(attributes.position);
+       
+       // same with color data
+       GLfloat color_buffer_data[] = {
+               red, green, blue,
+               red, green, blue,
+               red, green, blue,
+               red, green, blue,
+       };
+       GLuint color_buffer = createArrayBuffer(sizeof(color_buffer_data), color_buffer_data);
+       glVertexAttribPointer(
+               attributes.color,              /* attribute */
+               3,                             /* size */
+               GL_FLOAT,                      /* type */
+               GL_FALSE,                      /* normalized? */
+               0,                             /* stride */
+               (void*)0                       /* array buffer offset */
+       );
+       glEnableVertexAttribArray(attributes.color);
+       
+       // draw
+       glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+       
+       // cleanup
+       glDeleteBuffers(1, &vertex_buffer);
+       glDeleteBuffers(1, &color_buffer);
+}