diff mbox

[Branch,~glmark2-dev/glmark2/trunk] Rev 43: Add OpenGL ES 2.0 screen.

Message ID 20110721123633.17019.36098.launchpad@loganberry.canonical.com
State Accepted
Headers show

Commit Message

Alexandros Frantzis July 21, 2011, 12:36 p.m. UTC
------------------------------------------------------------
revno: 43
committer: Alexandros Frantzis <alf82@freemail.gr>
timestamp: Mon 2010-07-12 16:37:04 +0300
message:
  Add OpenGL ES 2.0 screen.
added:
  src/screen-sdl-glesv2.cpp
  src/screen-sdl-glesv2.h
  src/sdlgles/
  src/sdlgles/SDL_gles.c
  src/sdlgles/SDL_gles.h
  src/sdlgles/attribs.inc
modified:
  src/main.cpp
  src/screen-sdl-gl.cpp
  src/wscript_build
  wscript


--
lp:glmark2
https://code.launchpad.net/~glmark2-dev/glmark2/trunk

You are subscribed to branch lp:glmark2.
To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription
diff mbox

Patch

=== modified file 'src/main.cpp'
--- src/main.cpp	2010-07-12 12:15:52 +0000
+++ src/main.cpp	2010-07-12 13:37:04 +0000
@@ -1,7 +1,11 @@ 
 #include "oglsdl.h"
+#include "scene.h"
 
+#if USE_GL
 #include "screen-sdl-gl.h"
-#include "scene.h"
+#elif USE_GLESv2
+#include "screen-sdl-glesv2.h"
+#endif
 
 int main(int argc, char *argv[])
 {
@@ -10,7 +14,11 @@ 
     unsigned current_scene = 0;
 
     // Create the screen
+#if USE_GL
     ScreenSDLGL screen(800, 600, 24, 0);
+#elif USE_GLESv2
+    ScreenSDLGLESv2 screen(800, 600, 24, 0);
+#endif
 
     if (!screen.mInitSuccess) {
         printf("Error: %s: Could not initialize screen\n", __FUNCTION__);

=== modified file 'src/screen-sdl-gl.cpp'
--- src/screen-sdl-gl.cpp	2010-07-12 12:15:52 +0000
+++ src/screen-sdl-gl.cpp	2010-07-12 13:37:04 +0000
@@ -37,4 +37,3 @@ 
     printf("    GL_RENDERER:   %s\n", glGetString(GL_RENDERER));
     printf("    GL_VERSION:    %s\n", glGetString(GL_VERSION));
 }
-

=== added file 'src/screen-sdl-glesv2.cpp'
--- src/screen-sdl-glesv2.cpp	1970-01-01 00:00:00 +0000
+++ src/screen-sdl-glesv2.cpp	2010-07-12 13:37:04 +0000
@@ -0,0 +1,60 @@ 
+#include "screen-sdl-glesv2.h"
+#include "sdlgles/SDL_gles.h"
+
+ScreenSDLGLESv2::ScreenSDLGLESv2(int pWidth, int pHeight, int pBpp, int pFullScreen, int pFlags)
+    : ScreenSDL(pWidth, pHeight, pBpp, pFullScreen, pFlags | SDL_OPENGL)
+{
+    mInitSuccess = 0;
+
+    if (SDL_GLES_Init(SDL_GLES_VERSION_2_0) < 0) {
+	fprintf(stderr, "[ Fail ] - GLES initialization failed: %s\n", SDL_GetError());
+    }
+
+    SDL_GLES_Context *context;
+    context = SDL_GLES_CreateContext();
+    if (context == NULL) {
+	fprintf(stderr, "[ Fail ] - GLES create context: %s\n", SDL_GetError());
+	return;
+    }
+
+    if (SDL_GLES_MakeCurrent(context) != 0) {
+	fprintf(stderr, "[ Fail ] - GLES make context current: %s\n", SDL_GetError());
+	return;
+    }
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LEQUAL);
+    glEnable(GL_CULL_FACE);
+    glCullFace(GL_BACK);
+
+    glViewport(0, 0, mWidth, mHeight);
+
+    clear();
+
+    mInitSuccess = 1;
+}
+
+ScreenSDLGLESv2::~ScreenSDLGLESv2()
+{
+}
+
+
+void ScreenSDLGLESv2::clear()
+{
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void ScreenSDLGLESv2::update()
+{
+	SDL_GLES_SwapBuffers();
+}
+
+void ScreenSDLGLESv2::print_info()
+{
+    printf("    OpenGL Information\n");
+    printf("    GL_VENDOR:     %s\n", glGetString(GL_VENDOR));
+    printf("    GL_RENDERER:   %s\n", glGetString(GL_RENDERER));
+    printf("    GL_VERSION:    %s\n", glGetString(GL_VERSION));
+}
+

=== added file 'src/screen-sdl-glesv2.h'
--- src/screen-sdl-glesv2.h	1970-01-01 00:00:00 +0000
+++ src/screen-sdl-glesv2.h	2010-07-12 13:37:04 +0000
@@ -0,0 +1,17 @@ 
+#ifndef _SCREEN_SDL_GLESv2_H
+#define _SCREEN_SDL_GLESv2_H
+
+#include "screen-sdl.h"
+
+class ScreenSDLGLESv2 : public ScreenSDL
+{
+public:
+    ScreenSDLGLESv2(int pWidth, int pHeight, int pBpp, int pFullscreen, int pFlags = 0);
+    ~ScreenSDLGLESv2();
+
+    virtual void clear();
+    virtual void update();
+    virtual void print_info();
+};
+
+#endif

=== added directory 'src/sdlgles'
=== added file 'src/sdlgles/SDL_gles.c'
--- src/sdlgles/SDL_gles.c	1970-01-01 00:00:00 +0000
+++ src/sdlgles/SDL_gles.c	2010-07-12 13:37:04 +0000
@@ -0,0 +1,428 @@ 
+/* This file is part of SDL_gles - SDL addon for OpenGL|ES
+ * Copyright (C) 2010 Javier S. Pedro
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA or see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <assert.h>
+
+#include <EGL/egl.h>
+
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+#include "SDL_gles.h"
+
+typedef struct SDL_GLES_ContextPriv
+{
+	SDL_GLES_Context p;
+
+	EGLConfig egl_config;
+	EGLContext egl_context;
+} SDL_GLES_ContextPriv;
+
+static const char * default_libgl[] = {
+	[SDL_GLES_VERSION_1_1] = "/usr/lib/libGLES_CM.so",
+	[SDL_GLES_VERSION_2_0] = "/usr/lib/libGLESv2.so"
+};
+
+/** SDL GFX display */
+static Display *display = NULL;
+/** EGLDisplay for the above X11 display */
+static EGLDisplay *egl_display = EGL_NO_DISPLAY;
+/** The current surface. Recreated by SDL_GLES_SetVideoMode(). */
+static EGLSurface egl_surface = EGL_NO_SURFACE;
+/** A pointer to the current active context. */
+static SDL_GLES_ContextPriv *cur_context = NULL;
+
+/** The desired GLES version, as selected by the SDL_GLES_Init() call. */
+static SDL_GLES_Version gl_version = SDL_GLES_VERSION_NONE;
+/** A handle to the dynamically loaded GL library. */
+static void* gl_handle = NULL;
+/** EGL version. */
+static EGLint egl_major, egl_minor;
+
+/** Your average countof() macro. */
+#define countof(a) (sizeof(a)/sizeof(a[0]))
+
+/** List of EGLConfig attributes we care about;
+  * Used for filtering; modified by SDL_GLES_Get/SetAttribute(). */
+static EGLint attrib_list[] = {
+#define A(number, attrib, default_value) \
+	attrib, default_value,
+#include "attribs.inc"
+#undef A
+	EGL_NONE
+};
+/** A enum which maps A_EGL_* attrib constants to attrib_list positions. */
+typedef enum {
+#define A(number, attrib, default_value) \
+	A_ ## attrib = (number * 2),
+#include "attribs.inc"
+#undef A
+} attrib_enum;
+static EGLint context_attrib_list[] = {
+	EGL_CONTEXT_CLIENT_VERSION,	1,
+	EGL_NONE
+};
+
+static const char * get_error_string(int error) {
+	switch (error) {
+		case EGL_SUCCESS:
+			return "EGL_SUCCESS";
+		case EGL_NOT_INITIALIZED:
+			return "EGL_NOT_INITIALIZED";
+		case EGL_BAD_ACCESS:
+			return "EGL_BAD_ACCESS";
+		case EGL_BAD_ALLOC:
+			return "EGL_BAD_ALLOC";
+		case EGL_BAD_ATTRIBUTE:
+			return "EGL_BAD_ATTRIBUTE";
+		case EGL_BAD_CONFIG:
+			return "EGL_BAD_CONFIG";
+		case EGL_BAD_CONTEXT:
+			return "EGL_BAD_CONTEXT";
+		case EGL_BAD_CURRENT_SURFACE:
+			return "EGL_BAD_CURRENT_SURFACE";
+		case EGL_BAD_DISPLAY:
+			return "EGL_BAD_DISPLAY";
+		case EGL_BAD_MATCH:
+			return "EGL_BAD_MATCH";
+		case EGL_BAD_NATIVE_PIXMAP:
+			return "EGL_BAD_NATIVE_PIXMAP";
+		case EGL_BAD_NATIVE_WINDOW:
+			return "EGL_BAD_NATIVE_WINDOW";
+		case EGL_BAD_PARAMETER:
+			return "EGL_BAD_PARAMETER";
+		case EGL_BAD_SURFACE:
+			return "EGL_BAD_SURFACE";
+		case EGL_CONTEXT_LOST:
+			return "EGL_CONTEXT_LOST";
+		default:
+			return "EGL_UNKNOWN_ERROR";
+    }
+}
+
+static inline void set_egl_attrib(attrib_enum attrib, EGLint value)
+{
+	const unsigned int i = (unsigned int)attrib + 1;
+	assert(i < countof(attrib_list));
+	attrib_list[i] = value;
+}
+
+static inline EGLint get_egl_attrib(attrib_enum attrib)
+{
+	const unsigned int i = (unsigned int)attrib + 1;
+	assert(i < countof(attrib_list));
+	return attrib_list[i];
+}
+
+static inline void set_egl_context_attrib(EGLenum attrib, EGLint value)
+{
+	/* Only one attribute supported here. */
+	assert(attrib == EGL_CONTEXT_CLIENT_VERSION);
+	context_attrib_list[1] = value;
+}
+
+int SDL_GLES_LoadLibrary(const char *path)
+{
+	/* If path is NULL, try first to use path from SDL_VIDEO_GL_DRIVER,
+	 * otherwise use a sane default depending on selected GLES version. */
+	if (!path) {
+		path = getenv("SDL_VIDEO_GL_DRIVER");
+		if (!path) {
+			switch (gl_version) {
+				case SDL_GLES_VERSION_1_1:
+				case SDL_GLES_VERSION_2_0:
+					path = default_libgl[gl_version];
+				break;
+				default:
+					SDL_SetError("No GL version specific and SDL_VIDEO_GL_DRIVER set");
+					return -1;
+			}
+		}
+	}
+
+	/* Dynamically load the desired GL library */
+	gl_handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL);
+	if (!gl_handle) {
+		SDL_SetError("Failed to open GL library: %s (%s)", path, dlerror());
+		return -2;
+	}
+
+	return 0;
+}
+
+void* SDL_GLES_GetProcAddress(const char *proc)
+{
+	if (!gl_handle) return NULL;
+	return dlsym(gl_handle, proc);
+}
+
+int SDL_GLES_Init(SDL_GLES_Version version)
+{
+	SDL_SysWMinfo info;
+	EGLBoolean res;
+
+	SDL_VERSION(&info.version);
+	if (SDL_GetWMInfo(&info) != 1) {
+		SDL_SetError("SDL_gles is incompatible with this SDL version");
+		return -1;
+	}
+
+	/* We use the SDL GFX display (we're using the GFX window too after all) */
+	display = info.info.x11.gfxdisplay;
+
+	egl_display = eglGetDisplay((EGLNativeDisplayType)display);
+	if (egl_display == EGL_NO_DISPLAY) {
+		SDL_SetError("EGL found no available displays");
+		return -2;
+	}
+
+	res = eglInitialize(egl_display, &egl_major, &egl_minor);
+	if (!res) {
+		SDL_SetError("EGL failed to initialize: %s",
+			get_error_string(eglGetError()));
+		return -2;
+	}
+
+	/* Configure some context attributes and bind the required API now. */
+	EGLenum api_to_bind = EGL_OPENGL_ES_API;
+	gl_version = version;
+	switch (gl_version) {
+		case SDL_GLES_VERSION_1_1:
+			/* OpenGL|ES 1.1 */
+			api_to_bind = EGL_OPENGL_ES_API;
+			/* filter non ES 1.0 renderable configurations */
+			set_egl_attrib(A_EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
+			/* default egl_context_client_version is OK */
+			break;
+		case SDL_GLES_VERSION_2_0:
+			/* OpenGL|ES 2.0 */
+			api_to_bind = EGL_OPENGL_ES_API; /* Note: no EGL_OPENGL_ES2_API */
+			/* filter non ES 2.0 renderable configurations */
+			set_egl_attrib(A_EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
+			/* and request GL ES 2.0 contexts */
+			set_egl_context_attrib(EGL_CONTEXT_CLIENT_VERSION, 2);
+			break;
+		default:
+			SDL_SetError("Unsupported API version");
+			return -1;
+	}
+
+	res = eglBindAPI(api_to_bind);
+	if (!res) {
+		SDL_SetError("EGL failed to bind the required API");
+		return -2;
+	}
+
+	return 0;
+}
+
+void SDL_GLES_Quit()
+{
+	/* Close the loaded GL library (if any) */
+	if (gl_handle) {
+		dlclose(gl_handle);
+		gl_handle = NULL;
+	}
+	/* Unallocate most stuff we can unallocate. */
+	if (egl_display != EGL_NO_DISPLAY) {
+		eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+			EGL_NO_CONTEXT);
+
+		if (cur_context) {
+			eglDestroyContext(egl_display, cur_context->egl_context);
+			free(cur_context);
+			cur_context = 0;
+		}
+		if (egl_surface != EGL_NO_SURFACE) {
+			eglDestroySurface(egl_display, egl_surface);
+			egl_surface = EGL_NO_SURFACE;
+		}
+
+		eglTerminate(egl_display);
+		egl_display = EGL_NO_DISPLAY;
+	}
+}
+
+int SDL_GLES_SetVideoMode()
+{
+	SDL_SysWMinfo info;
+	EGLBoolean res;
+
+	SDL_VERSION(&info.version);
+	if (SDL_GetWMInfo(&info) != 1) {
+		SDL_SetError("SDL_gles is incompatible with this SDL version");
+		return -1;
+	}
+
+	/* Destroy previous surface, if any. */
+	if (egl_surface != EGL_NO_SURFACE) {
+		/* Ensure the surface is not the current one,
+		 * thus freeing memory earlier. */
+		eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+			 EGL_NO_CONTEXT);
+		eglDestroySurface(egl_display, egl_surface);
+		egl_surface = EGL_NO_SURFACE;
+	}
+
+	/* No current context? Quietly defer surface creation.
+	 * Surface will be created on the call to MakeCurrent. */
+	if (!cur_context) {
+		return 0;
+	}
+
+	/* Create the new window surface. */
+	egl_surface = eglCreateWindowSurface(egl_display, cur_context->egl_config,
+		(EGLNativeWindowType)info.info.x11.window, NULL);
+	if (egl_surface == EGL_NO_SURFACE) {
+		SDL_SetError("EGL failed to create a window surface: %s",
+			get_error_string(eglGetError()));
+		return -2;
+	}
+
+	/* New surface created. Make it active. */
+	assert(cur_context && cur_context->egl_context != EGL_NO_CONTEXT);
+	res = eglMakeCurrent(egl_display, egl_surface, egl_surface,
+		cur_context->egl_context);
+
+	if (!res) {
+		SDL_SetError("EGL failed to change current surface: %s",
+			get_error_string(eglGetError()));
+		cur_context = NULL;
+		return -2;
+	}
+
+	return 0;
+}
+
+SDL_GLES_Context* SDL_GLES_CreateContext(void)
+{
+	SDL_GLES_ContextPriv *context = malloc(sizeof(SDL_GLES_ContextPriv));
+	if (!context) {
+		SDL_Error(SDL_ENOMEM);
+		return NULL;
+	}
+
+	EGLBoolean res;
+	EGLConfig configs[1];
+	EGLint num_config;
+
+	res = eglChooseConfig(egl_display, attrib_list, configs, 1, &num_config);
+	if (!res || num_config < 1) {
+		SDL_SetError("EGL failed to find any valid config with required attributes: %s",
+			get_error_string(eglGetError()));
+		free(context);
+		return NULL;
+	}
+
+	context->egl_config = configs[0];
+	context->egl_context = eglCreateContext(egl_display, configs[0],
+		EGL_NO_CONTEXT, context_attrib_list);
+	if (context->egl_context == EGL_NO_CONTEXT) {
+		SDL_SetError("EGL failed to create context: %s",
+			get_error_string(eglGetError()));
+		free(context);
+		return NULL;
+	}
+
+	return (SDL_GLES_Context*) context;
+}
+
+void SDL_GLES_DeleteContext(SDL_GLES_Context* c)
+{
+	SDL_GLES_ContextPriv *context = (SDL_GLES_ContextPriv*)c;
+	if (!context) return;
+
+	if (cur_context == context) {
+		/* Deleting the active context */
+		SDL_GLES_MakeCurrent(NULL);
+	}
+
+	eglDestroyContext(egl_display, context->egl_context);
+	free(context);
+}
+
+int SDL_GLES_MakeCurrent(SDL_GLES_Context* c)
+{
+	SDL_GLES_ContextPriv *context = (SDL_GLES_ContextPriv*)c;
+	int res;
+
+	cur_context = context;
+
+	/* SDL_GLES_SetVideoMode() will appropiately clear the current context
+	 * (and surface), then create a new surface matching the selected context
+	 * config and make both the surface and the context the active ones. */
+	res = SDL_GLES_SetVideoMode();
+	if (res != 0) return res; /* Surface (re-)creation failed. */
+
+	return 0;
+}
+
+void SDL_GLES_SwapBuffers()
+{
+	eglSwapBuffers(egl_display, egl_surface);
+}
+
+/** A simple map between SDL_GLES_* attributes and EGL ones.
+  * More abstraction layers is always good.
+  */
+static const attrib_enum attrib_map[] = {
+	[SDL_GLES_BUFFER_SIZE]		= A_EGL_BUFFER_SIZE,
+	[SDL_GLES_RED_SIZE]			= A_EGL_RED_SIZE,
+	[SDL_GLES_GREEN_SIZE]		= A_EGL_GREEN_SIZE,
+	[SDL_GLES_BLUE_SIZE]		= A_EGL_BLUE_SIZE,
+	[SDL_GLES_ALPHA_SIZE]		= A_EGL_ALPHA_SIZE,
+	[SDL_GLES_LUMINANCE_SIZE]	= A_EGL_LUMINANCE_SIZE,
+	[SDL_GLES_DEPTH_SIZE]		= A_EGL_DEPTH_SIZE,
+	[SDL_GLES_STENCIL_SIZE]		= A_EGL_STENCIL_SIZE,
+};
+
+int SDL_GLES_SetAttribute(SDL_GLES_Attr attr, int value)
+{
+	if (attr >= countof(attrib_map)) return -1;
+	attrib_enum list_attr = attrib_map[attr];
+	set_egl_attrib(list_attr, value);
+	return 0;
+}
+
+int SDL_GLES_GetAttribute(SDL_GLES_Attr attr, int *value)
+{
+	if (attr >= countof(attrib_map)) return -1;
+	attrib_enum list_attr = attrib_map[attr];
+	if (cur_context) {
+		EGLenum egl_attr = attrib_list[list_attr];
+		EGLint egl_value = 0;
+		EGLBoolean res = eglGetConfigAttrib(egl_display,
+			cur_context->egl_config, egl_attr, &egl_value);
+		if (res) {
+			*value = egl_value;
+			return 0;
+		} else {
+			printf("Failed: %s\n", get_error_string(eglGetError()));
+			return -1;
+		}
+	} else {
+		*value = get_egl_attrib(list_attr);
+		return 0;
+	}
+}
+

=== added file 'src/sdlgles/SDL_gles.h'
--- src/sdlgles/SDL_gles.h	1970-01-01 00:00:00 +0000
+++ src/sdlgles/SDL_gles.h	2010-07-12 13:37:04 +0000
@@ -0,0 +1,121 @@ 
+/* This file is part of SDL_gles - SDL addon for OpenGL|ES
+ * Copyright (C) 2010 Javier S. Pedro
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA or see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SDL_GLES_H
+#define __SDL_GLES_H
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum SDL_GLES_Version
+{
+	SDL_GLES_VERSION_NONE = 0,
+	SDL_GLES_VERSION_1_1 = 1,
+	SDL_GLES_VERSION_2_0 = 2
+} SDL_GLES_Version;
+
+typedef enum SDL_GLES_Attr
+{
+	SDL_GLES_BUFFER_SIZE = 0,
+	SDL_GLES_RED_SIZE,
+	SDL_GLES_GREEN_SIZE,
+	SDL_GLES_BLUE_SIZE,
+	SDL_GLES_ALPHA_SIZE,
+	SDL_GLES_LUMINANCE_SIZE,
+	SDL_GLES_DEPTH_SIZE,
+	SDL_GLES_STENCIL_SIZE
+} SDL_GLES_Attr;
+
+typedef struct SDL_GLES_Context
+{
+	/* Opaque pointer to an EGLContext */
+} SDL_GLES_Context;
+
+/** Invoke after SDL_Init.
+	@return 0 if SDL_gles was initialized correctly.
+  */
+extern DECLSPEC int SDLCALL SDL_GLES_Init(SDL_GLES_Version version);
+
+/** Invoke just before SDL_Quit.
+  */
+extern DECLSPEC void SDLCALL SDL_GLES_Quit();
+
+/** Call before calling GetProcAddress. Dynamically loads a GLES library.
+  * @param path full path to the library to load, or leave as NULL to load
+  *		the default GL ES library (version as specified in SDL_GLES_Init()).
+  * @return 0 if everything went OK.
+  */
+extern DECLSPEC int SDLCALL SDL_GLES_LoadLibrary(const char *path);
+/** Returns the address of a symbol in the loaded GL ES library.
+  * @param name of the symbol to look up.
+  * @return address of the symbol or NULL.
+  */
+extern DECLSPEC void* SDLCALL SDL_GLES_GetProcAddress(const char *proc);
+
+/** Creates a new GL ES rendering context. This is where all your textures,
+  * etc. are stored. You need one for rendering; after creating it, make sure
+  * it is the current one calling SDL_GLES_MakeCurrent().
+  * @return the created context or NULL.
+  */
+extern DECLSPEC SDL_GLES_Context* SDLCALL SDL_GLES_CreateContext(void);
+/** Deletes an existing GL ES rendering context. This can delete the current
+  * context, but after that no context will be current.
+  * @param context context to delete
+  */
+extern DECLSPEC void SDLCALL SDL_GLES_DeleteContext(SDL_GLES_Context *context);
+
+/** Call after calling SDL_SetVideoMode() if you have an active context
+  * to refresh the surface parameters.
+  * @return 0 if everything went OK.
+  */
+extern DECLSPEC int SDLCALL SDL_GLES_SetVideoMode(void);
+/** Makes a context the current one. All GLES calls will use it from now on.
+  * @param context context to use
+  * @return 0 if everything went OK.
+  */
+extern DECLSPEC int SDLCALL SDL_GLES_MakeCurrent(SDL_GLES_Context *context);
+
+/** Equivalent to SDL_Flip(). Call when you're finished issuing GL calls
+  * and want to draw the color buffer contents to the window surface.
+  */
+extern DECLSPEC void SDLCALL SDL_GLES_SwapBuffers(void);
+
+/** Sets a specific context attribute before calling SDL_CreateContext().
+  * @param attr
+  * @param value
+  * @return 0 if the attribute exists, -1 otherwise.
+  */
+extern DECLSPEC int SDLCALL SDL_GLES_SetAttribute(SDL_GLES_Attr attr, int value);
+
+/** Gets a context attribute from the current context, or from the wanted
+  * attribute set if no context is current.
+  * @param attr
+  * @param value pointer where the result will be stored.
+  * @return 0 if the attribute exists, -1 otherwise.
+  */
+extern DECLSPEC int SDLCALL SDL_GLES_GetAttribute(SDL_GLES_Attr attr, int *value);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+
+#endif

=== added file 'src/sdlgles/attribs.inc'
--- src/sdlgles/attribs.inc	1970-01-01 00:00:00 +0000
+++ src/sdlgles/attribs.inc	2010-07-12 13:37:04 +0000
@@ -0,0 +1,22 @@ 
+/* List of EGL attributes we care about */
+A(0,	EGL_BUFFER_SIZE,			0)
+A(1,	EGL_RED_SIZE,				0)
+A(2,	EGL_GREEN_SIZE,				0)
+A(3,	EGL_BLUE_SIZE,				0)
+A(4,	EGL_LUMINANCE_SIZE,			0)
+A(5,	EGL_ALPHA_SIZE,				0)
+A(6,	EGL_CONFIG_CAVEAT,			EGL_DONT_CARE)
+A(7,	EGL_CONFIG_ID,				EGL_DONT_CARE)
+A(8,	EGL_DEPTH_SIZE,				0)
+A(9,	EGL_LEVEL,					0)
+A(10,	EGL_NATIVE_RENDERABLE,		EGL_DONT_CARE)
+A(11,	EGL_NATIVE_VISUAL_TYPE,		EGL_DONT_CARE)
+A(12,	EGL_RENDERABLE_TYPE,		0)
+A(13,	EGL_SAMPLE_BUFFERS,			0)
+A(14,	EGL_SAMPLES,				0)
+A(15,	EGL_STENCIL_SIZE,			0)
+A(16,	EGL_SURFACE_TYPE,			EGL_WINDOW_BIT)
+A(17,	EGL_TRANSPARENT_TYPE,		EGL_NONE)
+A(18,	EGL_TRANSPARENT_RED_VALUE,	EGL_DONT_CARE)
+A(19,	EGL_TRANSPARENT_GREEN_VALUE,EGL_DONT_CARE)
+A(20,	EGL_TRANSPARENT_BLUE_VALUE,	EGL_DONT_CARE)

=== modified file 'src/wscript_build'
--- src/wscript_build	2010-07-12 10:06:29 +0000
+++ src/wscript_build	2010-07-12 13:37:04 +0000
@@ -1,7 +1,32 @@ 
-lib = bld(
+all_sources = bld.path.ant_glob('*.cpp').split();
+common_sources = [f for f in all_sources if f.find('screen-') == -1]
+gl_sources = ['screen-sdl.cpp', 'screen-sdl-gl.cpp']
+glesv2_sources = ['screen-sdl.cpp', 'screen-sdl-glesv2.cpp']
+
+if bld.env.USE_GL:
+	bld(
 		features     = ['cxx', 'cprogram'],
-		source       = bld.path.ant_glob('*.cpp'),
+		source       = common_sources + gl_sources,
 		target       = 'glmark2',
 		uselib       = ['sdl', 'gl'],
 		lib          = ['m'],
+		defines      = ['USE_GL']
+		)
+
+if bld.env.USE_GLESv2:
+	bld(
+		features     = ['cc', 'cstaticlib'],
+		source       = bld.path.ant_glob('sdlgles/*.c'),
+		target       = 'sdlgles',
+		uselib       = ['sdl', 'glesv2', 'egl'],
+		lib          = ['m'],
+		)
+	bld(
+		features     = ['cxx', 'cprogram'],
+		source       = common_sources + glesv2_sources,
+		target       = 'glmark2-es2',
+		uselib       = ['sdl', 'glesv2'],
+		uselib_local = ['sdlgles'],
+		lib          = ['m'],
+		defines      = ['USE_GLESv2']
 		)

=== modified file 'wscript'
--- wscript	2010-07-12 10:06:29 +0000
+++ wscript	2010-07-12 13:37:04 +0000
@@ -13,17 +13,27 @@ 
 # Produce '.tar.gz' with ./waf dist
 Scripting.g_gz = 'gz'
 
+def conf_message(conf, first, second):
+	conf.check_message_1(first)
+	conf.check_message_2(second, color='PINK')
+
 def set_options(opt):
+	opt.tool_options('compiler_cc')
 	opt.tool_options('compiler_cxx')
 
+	opt.add_option('--gl', action='store_true', dest = 'gl', default = False, help='build using OpenGL 2.0')
+	opt.add_option('--glesv2', action='store_true', dest = 'glesv2', default = False, help='build using OpenGL ES 2.0')
 	opt.add_option('--no-debug', action='store_false', dest = 'debug', default = True, help='disable compiler debug information')
 	opt.add_option('--no-opt', action='store_false', dest = 'opt', default = True, help='disable compiler optimizations')
 	opt.add_option('--data-path', action='store', dest = 'data_path', help='the path to install the data to')
 
 def configure(conf):
+	if not Options.options.gl and not Options.options.glesv2:
+		conf.fatal("You must configure using at least one of --gl, --glesv2")
+
+	conf.check_tool('compiler_cc')
 	conf.check_tool('compiler_cxx')
-	conf.check_tool('misc')
-	
+
 	# Check required headers
 	req_headers = ['stdlib.h', 'string.h', 'unistd.h', 'fcntl.h']
 	for header in req_headers:
@@ -40,11 +50,18 @@ 
 		conf.check_cxx(function_name = func, header_name = header, uselib = uselib, mandatory = True)
 		
 	# Check required packages
-	req_pkgs = [('sdl', 'sdl'), ('gl', 'gl')]
+	req_pkgs = [('sdl', 'sdl')]
 	for (pkg, uselib) in req_pkgs:
 		conf.check_cfg(package = pkg, uselib_store = uselib, args = '--cflags --libs',
 				mandatory = True)
 				
+	# Check optional packages
+	opt_pkgs = [('gl', 'gl', Options.options.gl), ('egl', 'egl', Options.options.glesv2),
+			('glesv2', 'glesv2', Options.options.glesv2)]
+	for (pkg, uselib, mandatory) in opt_pkgs:
+		conf.check_cfg(package = pkg, uselib_store = uselib, args = '--cflags --libs',
+				mandatory = mandatory)
+
 	conf.env.append_unique('CXXFLAGS', '-Wall -Wextra -pedantic'.split(' '))
 
 	# Prepend -O# and -g flags so that they can be overriden by the CFLAGS environment variable
@@ -59,8 +76,13 @@ 
 	conf.env.append_unique('GLMARK_DATA_PATH', Options.options.data_path)
 	conf.env.append_unique('CXXDEFINES', 'GLMARK_DATA_PATH="%s"' % Options.options.data_path)
 
-	print("Data path: %s" % Options.options.data_path)
-	print("Prefix   : %s" % conf.env.PREFIX)
+	conf.env.USE_GL = Options.options.gl
+	conf.env.USE_GLESv2 = Options.options.glesv2
+
+	conf_message(conf, "Prefix", conf.env.PREFIX)
+	conf_message(conf, "Data path", Options.options.data_path)
+	conf_message(conf, "Building GL2 version", "Yes" if conf.env.USE_GL else "No")
+	conf_message(conf, "Building GLESv2 version", "Yes" if conf.env.USE_GLESv2 else "No")
 
 def build(bld):
 	bld.recurse('src')