From 159b4b8f866841e0bf33ec22be65a5bc56eb1cd3 Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Wed, 3 Mar 2010 02:57:23 +0100 Subject: [PATCH] added sdl_gles_get/setattribute calls --- sdlgles/src/SDL_gles.c | 154 ++++++++++++++++++++++++++--------------------- sdlgles/src/SDL_gles.h | 27 +++++++++ sdlgles/src/attribs.inc | 22 +++++++ sdlgles/test/Makefile | 2 +- sdlgles/test/attrib.c | 142 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 279 insertions(+), 68 deletions(-) create mode 100644 sdlgles/src/attribs.inc create mode 100644 sdlgles/test/attrib.c diff --git a/sdlgles/src/SDL_gles.c b/sdlgles/src/SDL_gles.c index 38d92a1..c3d4426 100644 --- a/sdlgles/src/SDL_gles.c +++ b/sdlgles/src/SDL_gles.c @@ -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; + } +} + diff --git a/sdlgles/src/SDL_gles.h b/sdlgles/src/SDL_gles.h index a079601..90d28ce 100644 --- a/sdlgles/src/SDL_gles.h +++ b/sdlgles/src/SDL_gles.h @@ -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 index 0000000..2a4078e --- /dev/null +++ b/sdlgles/src/attribs.inc @@ -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) diff --git a/sdlgles/test/Makefile b/sdlgles/test/Makefile index b2006e0..591f08b 100644 --- a/sdlgles/test/Makefile +++ b/sdlgles/test/Makefile @@ -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 index 0000000..6e6a8a5 --- /dev/null +++ b/sdlgles/test/attrib.c @@ -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 +#include +#include +#include + +#include +#include + +#include + +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; +} + -- 1.7.9.5