added sdl_gles_get/setattribute calls
authorJavier S. Pedro <javier@javispedro.com>
Wed, 3 Mar 2010 01:57:23 +0000 (02:57 +0100)
committerJavier S. Pedro <javier@javispedro.com>
Wed, 3 Mar 2010 01:57:23 +0000 (02:57 +0100)
sdlgles/src/SDL_gles.c
sdlgles/src/SDL_gles.h
sdlgles/src/attribs.inc [new file with mode: 0644]
sdlgles/test/Makefile
sdlgles/test/attrib.c [new file with mode: 0644]

index 38d92a1..c3d4426 100644 (file)
@@ -43,44 +43,45 @@ static const char * default_libgl[] = {
        [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) {
@@ -119,45 +120,25 @@ static const char * get_error_string(int 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)
@@ -230,19 +211,16 @@ int SDL_GLES_Init(SDL_GLES_Version version)
                        /* 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");
@@ -396,8 +374,6 @@ int SDL_GLES_MakeCurrent(SDL_GLES_Context* c)
        res = SDL_GLES_SetVideoMode();
        if (res != 0) return res; /* Surface (re-)creation failed. */
 
-       /* TODO Update attrib_list. Make SDL_GLES_GetAttribute work. */
-
        return 0;
 }
 
@@ -406,3 +382,47 @@ 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;
+       }
+}
+
index a079601..90d28ce 100644 (file)
@@ -32,6 +32,18 @@ typedef enum SDL_GLES_Version
        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 */
@@ -86,6 +98,21 @@ extern DECLSPEC int SDLCALL SDL_GLES_MakeCurrent(SDL_GLES_Context *context);
   */
 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
 }
diff --git a/sdlgles/src/attribs.inc b/sdlgles/src/attribs.inc
new file mode 100644 (file)
index 0000000..2a4078e
--- /dev/null
@@ -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)
index b2006e0..591f08b 100644 (file)
@@ -6,7 +6,7 @@ TEST_CFLAGS:=$(shell sdl-config --cflags)
 TEST_1_LDLIBS:=-lGLES_CM
 TEST_2_LDLIBS:=-lGLESv2
 
-TESTS_1:=gles1
+TESTS_1:=gles1 attrib
 TESTS_2:=gles2
 TESTS:=$(TESTS_1) $(TESTS_2)
 
diff --git a/sdlgles/test/attrib.c b/sdlgles/test/attrib.c
new file mode 100644 (file)
index 0000000..6e6a8a5
--- /dev/null
@@ -0,0 +1,142 @@
+/* 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;
+}
+