GLESv2 sample working
authorJavier S. Pedro <javier@javispedro.com>
Tue, 2 Mar 2010 20:57:19 +0000 (21:57 +0100)
committerJavier S. Pedro <javier@javispedro.com>
Tue, 2 Mar 2010 20:57:19 +0000 (21:57 +0100)
sdlgles/src/SDL_gles.c
sdlgles/test/gles1.c
sdlgles/test/gles2.c [new file with mode: 0644]

index c28dfdf..551c7c5 100644 (file)
@@ -55,6 +55,7 @@ static EGLint attrib_list[] = {
        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,
@@ -62,6 +63,7 @@ static EGLint attrib_list[] = {
        EGL_LEVEL,                                      0,
        EGL_NATIVE_RENDERABLE,          EGL_DONT_CARE,
        EGL_NATIVE_VISUAL_TYPE,         EGL_DONT_CARE,
+       EGL_RENDERABLE_TYPE,            EGL_OPENGL_BIT,
        EGL_SAMPLE_BUFFERS,                     0,
        EGL_SAMPLES,                            0,
        EGL_STENCIL_SIZE,                       0,
@@ -72,6 +74,12 @@ static EGLint attrib_list[] = {
        EGL_TRANSPARENT_BLUE_VALUE,     EGL_DONT_CARE,
        EGL_NONE
 };
+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) {
@@ -111,6 +119,47 @@ static const char * get_error_string(int error) {
     }
 }
 
+static int set_egl_attrib(EGLenum 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;
+}
+
+static EGLint get_egl_attrib(EGLenum 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;
+}
+
+static int 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;
+}
+
 int SDL_GLES_LoadLibrary(const char *path)
 {
        if (!path) {
@@ -171,6 +220,22 @@ int SDL_GLES_Init(SDL_GLES_Version version)
        }
 
        gl_version = version;
+       switch (gl_version) {
+               case SDL_GLES_VERSION_1_1:
+                       /* defaults are OK */
+                       break;
+               case SDL_GLES_VERSION_2_0:
+                       /* by default, set egl renderable type attribute to GL ES 2 */
+                       res = set_egl_attrib(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT) == 0;
+                       assert(res);
+                       /* and request GL ES 2.0 contexts */
+                       res = set_egl_context_attrib(EGL_CONTEXT_CLIENT_VERSION, 2) == 0;
+                       assert(res);
+                       break;
+               default:
+                       break;
+       }
+
        return 0;
 }
 
@@ -253,12 +318,19 @@ SDL_GLES_Context* SDL_GLES_CreateContext(void)
        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, NULL);
+               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;
 }
@@ -292,18 +364,21 @@ int SDL_GLES_MakeCurrent(SDL_GLES_Context* c)
 
        /* TODO Update attrib_list. Make SDL_GLES_GetAttribute work. */
 
-       switch (gl_version) {
-               case SDL_GLES_VERSION_1_1:
-               case SDL_GLES_VERSION_2_0:
-                       res = eglBindAPI(EGL_OPENGL_ES_API);
-                       if (!res) {
-                               SDL_SetError("EGL failed to bind the required API: %s",
-                                       get_error_string(eglGetError()));
-                               return -2;
-                       }
-                       break;
-               default:
-                       break;
+       if (cur_context) {
+               /* If selecting a new context, bind the required API. */
+               switch (gl_version) {
+                       case SDL_GLES_VERSION_1_1:
+                       case SDL_GLES_VERSION_2_0:
+                               res = eglBindAPI(EGL_OPENGL_ES_API);
+                               if (!res) {
+                                       SDL_SetError("EGL failed to bind the required API: %s",
+                                               get_error_string(eglGetError()));
+                                       return -2;
+                               }
+                               break;
+                       default:
+                               break;
+               }
        }
 
        return 0;
index 6d844f0..5425ecd 100644 (file)
@@ -18,7 +18,7 @@
 static SDL_Surface *screen;
 static SDL_GLES_Context *context;
 
-static float box_step = 0.05f;
+static float box_step = 0.025f;
 
 static const float w = 0.28f, h = 0.4f;
 static float x = -0.5f, y = 0.0f;
@@ -76,9 +76,10 @@ int main()
        screen = SDL_SetVideoMode(0, 0, 16, SDL_SWSURFACE);
        assert(screen);
 
+       SDL_WM_SetCaption("SDLgles v1 test");
        SDL_ShowCursor(SDL_DISABLE);
 
-       SDL_TimerID timer = SDL_AddTimer(50, tick, NULL);
+       SDL_TimerID timer = SDL_AddTimer(30, tick, NULL);
        assert(timer != NULL);
 
        context = SDL_GLES_CreateContext();
diff --git a/sdlgles/test/gles2.c b/sdlgles/test/gles2.c
new file mode 100644 (file)
index 0000000..3e35e73
--- /dev/null
@@ -0,0 +1,151 @@
+/* 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 <GLES2/gl2.h>
+
+static SDL_Surface *screen;
+static SDL_GLES_Context *context;
+
+static GLuint program;
+static bool fullscreen = false;
+
+static GLuint compile_shader(GLenum type, const char *src)
+{
+       GLuint shader = glCreateShader(type);
+       GLint compiled;
+
+       assert(shader != 0),
+       glShaderSource(shader, 1, &src, NULL);
+       glCompileShader(shader);
+       glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+       assert(compiled);
+
+       return shader;
+}
+
+static void init()
+{
+       const char vertex_shader_src[] =  
+               "attribute vec4 pos;\n"
+               "void main()\n"
+               "{\n"
+               "       gl_Position = pos;\n"
+               "}\n";
+
+       const char fragment_shader_src[] =  
+               "precision mediump float;\n"
+               "void main()\n"
+               "{\n"
+               "       gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
+               "}\n";
+
+       GLuint vertex_shader = compile_shader(GL_VERTEX_SHADER, vertex_shader_src);
+       GLuint fragment_shader = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_src);
+
+       program = glCreateProgram();
+       assert(program);
+
+       glAttachShader(program, vertex_shader);
+       glAttachShader(program, fragment_shader);
+
+       glBindAttribLocation(program, 0, "pos");
+
+       GLint linked;
+       glLinkProgram(program);
+       glGetProgramiv(program, GL_LINK_STATUS, &linked);
+       assert(linked);
+
+       glClearColor(0.0f, 0.0f, 0.2f, 0.0f);
+}
+
+static void render()
+{
+       GLfloat tri_v[] =       {0.0f,  0.5f, 0.0f,
+                                               -0.5f, -0.5f, 0.0f,
+                                                0.5f, -0.5f, 0.0f};
+
+       glViewport(0, 0, screen->w, screen->h);
+       glClear(GL_COLOR_BUFFER_BIT);
+       glUseProgram(program);
+
+       glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, tri_v);
+       glEnableVertexAttribArray(0);
+
+       glDrawArrays(GL_TRIANGLES, 0, 3);
+
+       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();
+       if (res != 0) puts(SDL_GetError());
+       assert(res == 0);
+
+       render();
+}
+
+int main()
+{
+       int res;
+       res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
+       assert(res == 0);
+
+       res = SDL_GLES_Init(SDL_GLES_VERSION_2_0);
+       assert(res == 0);
+
+       screen = SDL_SetVideoMode(0, 0, 16, SDL_SWSURFACE);
+       assert(screen);
+
+       SDL_WM_SetCaption("SDLgles v2 test");
+       SDL_ShowCursor(SDL_DISABLE);
+
+       context = SDL_GLES_CreateContext();
+       if (!context) puts(SDL_GetError());
+       assert(context);
+
+       res = SDL_GLES_MakeCurrent(context);
+       assert(res == 0);
+
+       init();
+       render();
+
+       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;
+}