[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;
-static Display *display = NULL;
-static EGLDisplay *egl_display = EGL_NO_DISPLAY;
-static EGLSurface egl_surface = EGL_NO_SURFACE;
+/** 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[] = {
- EGL_BUFFER_SIZE, 0,
- EGL_RED_SIZE, 0,
- EGL_GREEN_SIZE, 0,
- EGL_BLUE_SIZE, 0,
- EGL_LUMINANCE_SIZE, 0,
- EGL_ALPHA_SIZE, 0,
- EGL_CONFIG_CAVEAT, EGL_DONT_CARE,
- EGL_CONFIG_ID, EGL_DONT_CARE,
- EGL_DEPTH_SIZE, 0,
- EGL_LEVEL, 0,
- EGL_NATIVE_RENDERABLE, EGL_DONT_CARE,
- EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE,
- EGL_RENDERABLE_TYPE, 0,
- EGL_SAMPLE_BUFFERS, 0,
- EGL_SAMPLES, 0,
- EGL_STENCIL_SIZE, 0,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_TRANSPARENT_TYPE, EGL_NONE,
- EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE,
- EGL_TRANSPARENT_GREEN_VALUE,EGL_DONT_CARE,
- EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE,
+#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 int attrib_list_size = (sizeof(attrib_list) / sizeof(EGLint)) / 2;
-static const int context_attrib_list_size = (sizeof(context_attrib_list) / sizeof(EGLint)) / 2;
-static SDL_GLES_ContextPriv *cur_context = NULL;
static const char * get_error_string(int error) {
switch (error) {
}
}
-static int set_egl_attrib(EGLenum attrib, EGLint value)
+static inline void set_egl_attrib(attrib_enum attrib, EGLint value)
{
- const EGLint a = attrib;
- int i;
- for (i = 0; i < attrib_list_size; i++) {
- if (attrib_list[i * 2] == a) {
- attrib_list[(i*2)+1] = value;
- return 0;
- }
- }
-
- return -1;
+ const unsigned int i = (unsigned int)attrib + 1;
+ assert(i < countof(attrib_list));
+ attrib_list[i] = value;
}
-static EGLint get_egl_attrib(EGLenum attrib)
+static inline EGLint get_egl_attrib(attrib_enum attrib)
{
- const EGLint a = attrib;
- int i;
- for (i = 0; i < attrib_list_size; i++) {
- if (attrib_list[i * 2] == a) {
- return attrib_list[(i*2)+1];
- }
- }
-
- return -1;
+ const unsigned int i = (unsigned int)attrib + 1;
+ assert(i < countof(attrib_list));
+ return attrib_list[i];
}
-static int set_egl_context_attrib(EGLenum attrib, EGLint value)
+static inline void set_egl_context_attrib(EGLenum attrib, EGLint value)
{
- const EGLint a = attrib;
- int i;
- for (i = 0; i < context_attrib_list_size; i++) {
- if (context_attrib_list[i * 2] == a) {
- context_attrib_list[(i*2)+1] = value;
- return 0;
- }
- }
-
- return -1;
+ /* Only one attribute supported here. */
+ assert(attrib == EGL_CONTEXT_CLIENT_VERSION);
+ context_attrib_list[1] = value;
}
int SDL_GLES_LoadLibrary(const char *path)
/* OpenGL|ES 1.1 */
api_to_bind = EGL_OPENGL_ES_API;
/* filter non ES 1.0 renderable configurations */
- res = set_egl_attrib(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT) == 0;
- assert(res);
+ 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 */
- res = set_egl_attrib(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT) == 0;
- assert(res);
+ set_egl_attrib(A_EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
/* and request GL ES 2.0 contexts */
- res = set_egl_context_attrib(EGL_CONTEXT_CLIENT_VERSION, 2) == 0;
- assert(res);
+ set_egl_context_attrib(EGL_CONTEXT_CLIENT_VERSION, 2);
break;
default:
SDL_SetError("Unsupported API version");
res = SDL_GLES_SetVideoMode();
if (res != 0) return res; /* Surface (re-)creation failed. */
- /* TODO Update attrib_list. Make SDL_GLES_GetAttribute work. */
-
return 0;
}
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;
+ }
+}
+
--- /dev/null
+/* 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)
--- /dev/null
+/* gles1 - a simple SDL_gles OpenGL|ES 1.1 sample
+ *
+ * This file is in the public domain, furnished "as is", without technical
+ * support, and with no warranty, express or implied, as to its usefulness for
+ * any purpose.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include <SDL.h>
+#include <SDL_gles.h>
+
+#include <GLES/gl.h>
+
+static SDL_Surface *screen;
+static SDL_GLES_Context *context;
+
+static bool fullscreen = false;
+
+static const float vertices[] ={-0.6f, -0.6f, -0.5f, /* Square 1 */
+ 0.3f, -0.6f, -0.5f,
+ -0.6f, 0.8f, 0.1f,
+ 0.3f, 0.8f, 0.1f,
+ 0.3f, 0.8f, 0.1f, /* Degenerate vertices */
+ -0.3f, -0.6f, 0.5f,
+ -0.3f, -0.6f, 0.5f, /* Square 2 */
+ 0.6f, -0.6f, 0.5f,
+ -0.3f, 0.8f, -0.1f,
+ 0.6f, 0.8f, -0.1f,
+ };
+static const float colors[] = { 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ };
+
+static void draw()
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
+ SDL_GLES_SwapBuffers();
+}
+
+static void toggle_fullscreen()
+{
+ int res;
+
+ fullscreen = !fullscreen;
+
+ screen = SDL_SetVideoMode(0, 0, 16, SDL_SWSURFACE |
+ (fullscreen ? SDL_FULLSCREEN : 0));
+ assert(screen);
+
+ res = SDL_GLES_SetVideoMode();
+ assert(res == 0);
+
+ draw();
+}
+
+int main()
+{
+ int res, value = 0;
+ res = SDL_Init(SDL_INIT_VIDEO);
+ assert(res == 0);
+
+ res = SDL_GLES_Init(SDL_GLES_VERSION_1_1);
+ assert(res == 0);
+
+ screen = SDL_SetVideoMode(0, 0, 16, SDL_SWSURFACE);
+ assert(screen);
+
+ SDL_WM_SetCaption("SDLgles attrib test", "SDLgles v1 test");
+ SDL_ShowCursor(SDL_DISABLE);
+
+#define ENABLE_DEPTH_BUFFER 1
+
+#ifdef ENABLE_DEPTH_BUFFER
+ /* With a depth buffer, the red square will be partially over the blue sq. */
+ res = SDL_GLES_SetAttribute(SDL_GLES_DEPTH_SIZE, 4);
+ assert(res == 0);
+
+ res = SDL_GLES_GetAttribute(SDL_GLES_DEPTH_SIZE, &value);
+ assert(res == 0);
+ assert(value == 4);
+ printf("Wanted depth buffer size is %d\n", value);
+#else
+ /* Without a depth buffer, the blue square will be over the red square. */
+ printf("Wanted depth buffer size is %d\n", 0);
+#endif
+
+ context = SDL_GLES_CreateContext();
+ assert(context);
+
+ res = SDL_GLES_MakeCurrent(context);
+ assert(res == 0);
+
+ value = 0;
+ res = SDL_GLES_GetAttribute(SDL_GLES_DEPTH_SIZE, &value);
+ assert(res == 0);
+ printf("Depth buffer size is %d\n", value);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glEnable(GL_DEPTH_TEST);
+ glClearColor(0.0f, 0.2f, 0.0f, 0.0f);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, vertices);
+ glColorPointer(4, GL_FLOAT, 0, colors);
+
+ draw();
+
+ SDL_Event event;
+ while (SDL_WaitEvent(&event)) {
+ switch (event.type) {
+ case SDL_QUIT:
+ goto quit;
+ case SDL_MOUSEBUTTONDOWN:
+ toggle_fullscreen();
+ break;
+ }
+ }
+
+quit:
+ SDL_GLES_DeleteContext(context);
+
+ SDL_GLES_Quit();
+ SDL_Quit();
+
+ return 0;
+}
+