Hi all,

I'm attaching a patch for Evas_GL that fixes a few minor bugs.
For one, I had issues with stencil and depth format on OpenGL ES on a mobile
device using FBO.

Here's a part of the patch as an example...
(By the way, I'm covering 24bit format with 16bits on OpenGL ES for now... )

@@ -2112,7 +2113,12 @@
       case EVAS_GL_DEPTH_BIT_8:
       case EVAS_GL_DEPTH_BIT_16:
       case EVAS_GL_DEPTH_BIT_24:
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+         // 24 bit doesn't work... just cover it with 16 for now..
+         sfc->rb_depth_fmt = GL_DEPTH_COMPONENT16;
+#else
          sfc->rb_depth_fmt = GL_DEPTH_COMPONENT;
+#endif
          break;
       case EVAS_GL_DEPTH_BIT_32:
       default:
@@ -2128,7 +2134,11 @@
       case EVAS_GL_STENCIL_BIT_2:
       case EVAS_GL_STENCIL_BIT_4:
       case EVAS_GL_STENCIL_BIT_8:
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+         sfc->rb_stencil_fmt = GL_STENCIL_INDEX8;
+#else
          sfc->rb_stencil_fmt = GL_STENCIL_INDEX;
+#endif
          break;
       case EVAS_GL_STENCIL_BIT_16:
       default:
@@ -2180,14 +2190,13 @@
 }

Also, I've found a bug where deleting and recreating a surface wouldn't
properly reattach the surface with the FBO in the context.  So that has been
fixed here as well.

The fixes are in the file that I'm attaching: evas_gl_minor_fixes.patch

Also, I'm attaching an evasglgears.c that I've ported from glesgears.
It's still a bit messy but you can play around with it.  "left","right","up",
"down" button works as well. To compile the program, you just need to do

ECORE_PKG = `pkg-config --cflags --libs evas ecore ecore-evas`

evasglgears: evasglgears.c
        gcc -g -Wall -o $@ $< $(ECORE_PKG) -lm

You no longer need to link -lGL if you haven't noticed already.

let me know if the patch seems reasonable.

cheers,
Sung
Index: src/modules/engines/gl_x11/evas_engine.c
===================================================================
--- src/modules/engines/gl_x11/evas_engine.c	(revision 59318)
+++ src/modules/engines/gl_x11/evas_engine.c	(working copy)
@@ -37,6 +37,7 @@
 struct _Render_Engine_GL_Surface
 {
    int     initialized;
+   int     fbo_attached;
    int     w, h;
    int     depth_bits;
    int     stencil_bits;
@@ -2112,7 +2113,12 @@
       case EVAS_GL_DEPTH_BIT_8:
       case EVAS_GL_DEPTH_BIT_16:
       case EVAS_GL_DEPTH_BIT_24:
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+         // 24 bit doesn't work... just cover it with 16 for now..
+         sfc->rb_depth_fmt = GL_DEPTH_COMPONENT16;
+#else
          sfc->rb_depth_fmt = GL_DEPTH_COMPONENT;
+#endif
          break;
       case EVAS_GL_DEPTH_BIT_32:
       default:
@@ -2128,7 +2134,11 @@
       case EVAS_GL_STENCIL_BIT_2:
       case EVAS_GL_STENCIL_BIT_4:
       case EVAS_GL_STENCIL_BIT_8:
+#if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
+         sfc->rb_stencil_fmt = GL_STENCIL_INDEX8;
+#else
          sfc->rb_stencil_fmt = GL_STENCIL_INDEX;
+#endif
          break;
       case EVAS_GL_STENCIL_BIT_16:
       default:
@@ -2180,14 +2190,13 @@
 }
 
 static int
-_create_fbo_surface(Render_Engine *data __UNUSED__, 
+_attach_fbo_surface(Render_Engine *data __UNUSED__, 
                     Render_Engine_GL_Surface *sfc, 
                     Render_Engine_GL_Context *ctx)
 {
    int fb_status;
 
    // FBO
-   glGenFramebuffers(1, &ctx->fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, ctx->fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D, sfc->rt_tex, 0);
@@ -2221,16 +2230,6 @@
    return 1;
 }
 
-/*
-static void
-eng_gl_options_set(void *data, int options __UNUSED__)
-{
-   Render_Engine *re;
-
-   re  = (Render_Engine *)data;
-}
-*/
-
 static void *
 eng_gl_surface_create(void *data, void *config, int w, int h)
 {
@@ -2247,6 +2246,7 @@
    cfg = (Evas_GL_Config *)config;
 
    sfc->initialized  = 0;
+   sfc->fbo_attached = 0;
    sfc->w            = w;
    sfc->h            = h;
    sfc->depth_bits   = cfg->depth_bits;
@@ -2435,6 +2435,8 @@
 #endif
 
    ctx->initialized = 0;
+   ctx->fbo = 0;
+   ctx->current_sfc = NULL;
 
    return ctx;
 }
@@ -2509,6 +2511,7 @@
    sfc = (Render_Engine_GL_Surface*)surface;
    ctx = (Render_Engine_GL_Context*)context;
 
+   // Flush remainder of what's in Evas' pipeline
    if (re->win)
      {
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
@@ -2528,6 +2531,7 @@
 #endif   
      }
 
+   // Unset surface/context
    if ((!sfc) || (!ctx))
      {
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
@@ -2545,11 +2549,18 @@
         return ret;
      }
 
+   // Don't do a make current if it's already current
 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
-   ret = eglMakeCurrent(re->win->egl_disp, re->win->egl_surface[0], 
-                        re->win->egl_surface[0], ctx->context);
+   if ((eglGetCurrentContext() != ctx->context))
+     {
+        ret = eglMakeCurrent(re->win->egl_disp, re->win->egl_surface[0], 
+                             re->win->egl_surface[0], ctx->context);
+     }
 #else
-   ret = glXMakeCurrent(re->info->info.display, re->win->win, ctx->context);
+   if (glXGetCurrentContext() != ctx->context)
+     {
+        ret = glXMakeCurrent(re->info->info.display, re->win->win, ctx->context);
+     }
 #endif
    if (!ret) 
      {
@@ -2557,17 +2568,25 @@
         return 0;
      }
 
-   // Create FBO if not initalized already
+   // Create FBO if not already created
    if (!ctx->initialized) 
      {
-        if (!_create_fbo_surface(re, sfc, ctx)) 
+        glGenFramebuffers(1, &ctx->fbo);
+        ctx->initialized = 1;
+     }
+
+   // Attach FBO if it hasn't been attached or if surface changed
+   if ( (!sfc->fbo_attached) || (ctx != sfc->current_ctx))
+     {
+        if (!_attach_fbo_surface(re, sfc, ctx)) 
           {
-             ERR("_create_fbo_surface() failed.");
+             ERR("_attach_fbo_surface() failed.");
              return 0;
           }
-        ctx->initialized = 1;
+        sfc->fbo_attached = 1;
      }
 
+   // Set the current surface/context 
    ctx->current_sfc = sfc;
    sfc->current_ctx = ctx;
 
/**
 * Simple Evas_GL example
 */
#include <Ecore_Evas.h>
#include <Ecore.h>
#include <Evas_GL.h>
#include <stdio.h>

#ifndef M_PI
#define M_PI 3.14159265
#endif

typedef struct _Gear {
   GLfloat *vertices;
   GLuint vbo;
   int count;
} Gear;

// GL related data here..
typedef struct _GLData
{
   Evas_GL_API *glapi;
   GLuint       program;
   GLuint       vtx_shader;
   GLuint       fgmt_shader;
   int          initialized : 1;

   // Gear Stuff
   GLfloat      view_rotx;
   GLfloat      view_roty;
   GLfloat      view_rotz;

   Gear        *gear1;
   Gear        *gear2;
   Gear        *gear3;

   GLfloat      angle;

   GLuint       proj_location;
   GLuint       light_location;
   GLuint       color_location;


   GLfloat      proj[16];
   GLfloat      light[3];

} GLData;


static Eina_Bool on_animate(void *data);
static void key_down(void *data, Evas *e, Evas_Object *obj, void *event_info);

static void render_gears(GLData *gld);

static void gears_init(GLData *gld);
static void gears_reshape(GLData *gld, int width, int height);

// callbacks we want to handle deletion on the object and updates/draws
static void on_pixels(void *data, Evas_Object *obj);
static void on_del(void *data, Evas *e, Evas_Object *obj, void *event_info);


//--------------------------------//
// Gear Stuff....
static GLfloat *
vert(GLfloat *p, GLfloat x, GLfloat y, GLfloat z, GLfloat *n)
{
   p[0] = x;
   p[1] = y;
   p[2] = z;
   p[3] = n[0];
   p[4] = n[1];
   p[5] = n[2];

   return p + 6;
}

/*  Draw a gear wheel.  You'll probably want to call this function when
 *  building a display list since we do a lot of trig here.
 * 
 *  Input:  inner_radius - radius of hole at center
 *          outer_radius - radius at center of teeth
 *          width - width of gear
 *          teeth - number of teeth
 *          tooth_depth - depth of tooth
 */
static Gear *
make_gear(GLData *gld, GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
     GLint teeth, GLfloat tooth_depth)
{
   GLint i;
   GLfloat r0, r1, r2;
   GLfloat da;
   GLfloat *p, *v;
   Gear *gear;
   double s[5], c[5];
   GLfloat verts[3 * 14], normal[3];
   const int tris_per_tooth = 20;
   Evas_GL_API *gl = gld->glapi;

   gear = (Gear*)malloc(sizeof(Gear));
   if (gear == NULL)
      return NULL;

   r0 = inner_radius;
   r1 = outer_radius - tooth_depth / 2.0;
   r2 = outer_radius + tooth_depth / 2.0;

   da = 2.0 * M_PI / teeth / 4.0;

   gear->vertices = calloc(teeth * tris_per_tooth * 3 * 6,
			   sizeof *gear->vertices);
   s[4] = 0;
   c[4] = 1;
   v = gear->vertices;
   for (i = 0; i < teeth; i++) {
      s[0] = s[4];
      c[0] = c[4];
      sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]);
      sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
      sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
      sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);

      normal[0] = 0.0;
      normal[1] = 0.0;
      normal[2] = 1.0;

      v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);

      v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
      v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal);
      v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
      v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal);
      v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal);
      v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal);
      v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal);

      v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal);
      v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal);
      v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
      v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal);

      normal[0] = 0.0;
      normal[1] = 0.0;
      normal[2] = -1.0;

      v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);

      v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
      v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
      v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal);
      v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal);
      v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal);
      v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal);
      v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal);

      v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);

      v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
      v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal);
      v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
      v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal);
      v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal);
      v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal);
      v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal);
      v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal);
      v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal);
      v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);

      v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
   }

   gear->count = (v - gear->vertices) / 6;

   gl->glGenBuffers(1, &gear->vbo);
   gl->glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
   gl->glBufferData(GL_ARRAY_BUFFER, gear->count * 6 * 4,
		gear->vertices, GL_STATIC_DRAW);

   return gear;
}

static void
multiply(GLfloat *m, const GLfloat *n)
{
   GLfloat tmp[16];
   const GLfloat *row, *column;
   div_t d;
   int i, j;

   for (i = 0; i < 16; i++) {
      tmp[i] = 0;
      d = div(i, 4);
      row = n + d.quot * 4;
      column = m + d.rem;
      for (j = 0; j < 4; j++)
	 tmp[i] += row[j] * column[j * 4];
   }
   memcpy(m, &tmp, sizeof tmp);
}

static void
rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{
   double s, c;

   sincos(angle, &s, &c);
   GLfloat r[16] = {
      x * x * (1 - c) + c,     y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
      x * y * (1 - c) - z * s, y * y * (1 - c) + c,     y * z * (1 - c) + x * s, 0, 
      x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c,     0,
      0, 0, 0, 1
   };

   multiply(m, r);
}

static void
translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
{
   GLfloat t[16] = { 1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  x, y, z, 1 };

   multiply(m, t);
}

	
static void
draw_gear(GLData *gld, Gear *gear, GLfloat *m,
	  GLfloat x, GLfloat y, GLfloat angle, const GLfloat *color)
{
   Evas_GL_API *gl = gld->glapi;
   GLfloat tmp[16];

   memcpy(tmp, m, sizeof tmp);
   translate(tmp, x, y, 0);
   rotate(tmp, 2 * M_PI * angle / 360.0, 0, 0, 1);
   gl->glUniformMatrix4fv(gld->proj_location, 1, GL_FALSE, tmp);
   gl->glUniform3fv(gld->light_location, 1, gld->light);
   gl->glUniform4fv(gld->color_location, 1, color);

   gl->glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);

   gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
			 6 * sizeof(GLfloat), NULL);
   gl->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
			 6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
   gl->glEnableVertexAttribArray(0);
   gl->glEnableVertexAttribArray(1);
   gl->glDrawArrays(GL_TRIANGLE_STRIP, 0, gear->count);
}

static void
gears_draw(GLData *gld)
{
   Evas_GL_API *gl = gld->glapi;

   const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
   const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
   const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
   GLfloat m[16]; 

   gl->glClearColor(0.3, 0.3, 0.3, 0.5);
   gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   memcpy(m, gld->proj, sizeof m);
   rotate(m, 2 * M_PI * gld->view_rotx / 360.0, 1, 0, 0);
   rotate(m, 2 * M_PI * gld->view_roty / 360.0, 0, 1, 0);
   rotate(m, 2 * M_PI * gld->view_rotz / 360.0, 0, 0, 1);

   draw_gear(gld, gld->gear1, m, -3.0, -2.0, gld->angle, red);
   draw_gear(gld, gld->gear2, m, 3.1, -2.0, -2 * gld->angle - 9.0, green);
   draw_gear(gld, gld->gear3, m, -3.1, 4.2, -2 * gld->angle - 25.0, blue);
}

//-------------------------//

static void render_gears(GLData *gld)
{
   gears_draw(gld);

   gld->angle += 2.0;
}

/* new window size or exposure */
static void
gears_reshape(GLData *gld, int width, int height)
{
   Evas_GL_API *gl = gld->glapi;

   GLfloat ar, m[16] = {
      1.0, 0.0, 0.0, 0.0,
      0.0, 1.0, 0.0, 0.0,
      0.0, 0.0, 0.1, 0.0,
      0.0, 0.0, 0.0, 1.0,
   };
      
   if (width < height)
      ar = width;
   else
      ar = height;

   m[0] = 0.1 * ar / width;
   m[5] = 0.1 * ar / height;
   memcpy(gld->proj, m, sizeof gld->proj);
   gl->glViewport(0, 0, (GLint) width, (GLint) height);
}

static const char vertex_shader[] =
   "uniform mat4 proj;\n"
   "attribute vec4 position;\n"
   "attribute vec4 normal;\n"
   "varying vec3 rotated_normal;\n"
   "varying vec3 rotated_position;\n"
   "vec4 tmp;\n"
   "void main()\n"
   "{\n"
   "   gl_Position = proj * position;\n"
   "   rotated_position = gl_Position.xyz;\n"
   "   tmp = proj * normal;\n"
   "   rotated_normal = tmp.xyz;\n"
   "}\n";

 static const char fragment_shader[] =
   //"precision mediump float;\n"
   "uniform vec4 color;\n"
   "uniform vec3 light;\n"
   "varying vec3 rotated_normal;\n"
   "varying vec3 rotated_position;\n"
   "vec3 light_direction;\n"
   "vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n"
   "void main()\n"
   "{\n"
   "   light_direction = normalize(light - rotated_position);\n"
   "   gl_FragColor = color + white * dot(light_direction, rotated_normal);\n"
   "}\n";

static void
gears_init(GLData *gld)
{
   Evas_GL_API *gl = gld->glapi;

   const char *p;
   char msg[512];

   gl->glEnable(GL_CULL_FACE);
   gl->glEnable(GL_DEPTH_TEST);

   p = vertex_shader;
   gld->vtx_shader = gl->glCreateShader(GL_VERTEX_SHADER);
   gl->glShaderSource(gld->vtx_shader, 1, &p, NULL);
   gl->glCompileShader(gld->vtx_shader);
   gl->glGetShaderInfoLog(gld->vtx_shader, sizeof msg, NULL, msg);
   printf("vertex shader info: %s\n", msg);

   p = fragment_shader;
   gld->fgmt_shader = gl->glCreateShader(GL_FRAGMENT_SHADER);
   gl->glShaderSource(gld->fgmt_shader, 1, &p, NULL);
   gl->glCompileShader(gld->fgmt_shader);
   gl->glGetShaderInfoLog(gld->fgmt_shader, sizeof msg, NULL, msg);
   printf("fragment shader info: %s\n", msg);

   gld->program = gl->glCreateProgram();
   gl->glAttachShader(gld->program, gld->vtx_shader);
   gl->glAttachShader(gld->program, gld->fgmt_shader);
   gl->glBindAttribLocation(gld->program, 0, "position");
   gl->glBindAttribLocation(gld->program, 1, "normal");

   gl->glLinkProgram(gld->program);
   gl->glGetProgramInfoLog(gld->program, sizeof msg, NULL, msg);
   printf("info: %s\n", msg);

   gl->glUseProgram(gld->program);
   gld->proj_location  = gl->glGetUniformLocation(gld->program, "proj");
   gld->light_location = gl->glGetUniformLocation(gld->program, "light");
   gld->color_location = gl->glGetUniformLocation(gld->program, "color");

   /* make the gears */
   gld->gear1 = make_gear(gld, 1.0, 4.0, 1.0, 20, 0.7);
   gld->gear2 = make_gear(gld, 0.5, 2.0, 2.0, 10, 0.7);
   gld->gear3 = make_gear(gld, 1.3, 2.0, 0.5, 10, 0.7);
}



static void
gldata_init(GLData *gld)
{
   gld->view_rotx = 20.0;
   gld->view_roty = 30.0;
   gld->view_rotz = 0.0;
   gld->angle = 0.0;

   gld->light[0] = 1.0;  
   gld->light[1] = 1.0;  
   gld->light[2] = -1.0;  
}


void key_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
   GLData *gld = evas_object_data_get(obj, "..gld");
   Evas_Event_Key_Down *ev;
   ev = (Evas_Event_Key_Down *)event_info;

   if (strcmp(ev->keyname, "Left") == 0)
     {
        gld->view_roty += 5.0;
        return;
     }

   if (strcmp(ev->keyname, "Right") == 0)
     {
        gld->view_roty -= 5.0;
        return;
     }

   if (strcmp(ev->keyname, "Up") == 0)
     {
        gld->view_rotx += 5.0;
        return;
     }

   if (strcmp(ev->keyname, "Down") == 0)
     {
        gld->view_rotx -= 5.0;
        return;
     }
   if (strcmp(ev->keyname, "Escape") == 0)
     {
        ecore_main_loop_quit();
     }
}

int main(void)
{
   // config for the surface for evas_gl
   Evas_GL_Config config = 
     {
        EVAS_GL_RGBA_8, 
        EVAS_GL_DEPTH_BIT_8, 
        EVAS_GL_STENCIL_NONE
     };
   // a size by default
   int w = 256, h = 256;
   // some variables we will use
   Ecore_Evas  *ee;
   Evas *canvas;
   Evas_Object *r1;
   Evas_Native_Surface ns;
   Evas_GL *evasgl;
   Evas_GL_Surface *sfc;
   Evas_GL_Context *ctx;
   GLData *gld = NULL;

   // alloc a data struct to hold our relevant gl info in
   if (!(gld = calloc(1, sizeof(GLData)))) return 0;
   gldata_init(gld);

   // regular low-leve EFL (ecore+ecore-evas) init. elm is simpler
   ecore_init();
   ecore_evas_init();
   ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, 512, 512);
   ecore_evas_title_set(ee, "Ecore_Evas Template");
   canvas = ecore_evas_get(ee);

   //-//-//-// THIS IS WHERE GL INIT STUFF HAPPENS (ALA EGL)
   //-//
   // get the evas gl handle for doing gl things
   evasgl = evas_gl_new(canvas);
   gld->glapi = evas_gl_api_get(evasgl);
   // create a surface and context 
   sfc = evas_gl_surface_create(evasgl, &config, w, h);
   ctx = evas_gl_context_create(evasgl, NULL);
   //-//
   //-//-//-// END GL INIT BLOB

   // set up the image object. a filled one by default
   r1 = evas_object_image_filled_add(canvas);
   // attach important data we need to the object using key names. this just
   // avoids some global variables and means we can do nice cleanup. you can
   // avoid this if you are lazy
   evas_object_data_set(r1, "..evasgl", evasgl);
   evas_object_data_set(r1, "..sfc", sfc);
   evas_object_data_set(r1, "..ctx", ctx);
   evas_object_data_set(r1, "..gld", gld);
   // when the object is deleted - call the on_del callback. like the above,
   // this is just being clean
   evas_object_event_callback_add(r1, EVAS_CALLBACK_DEL, on_del, NULL);
   // set up an actual pixel size fot the buffer data. it may be different
   // to the output size. any windowing system has something like this, just
   // evas has 2 sizes, a pixel size and the output object size
   evas_object_image_size_set(r1, w, h);
   // set up the native surface info to use the context and surface created
   // above
   //-//-//-// THIS IS WHERE GL INIT STUFF HAPPENS (ALA EGL)
   //-//
   evas_gl_native_surface_get(evasgl, sfc, &ns);		
   evas_object_image_native_surface_set(r1, &ns);
   evas_object_image_pixels_get_callback_set(r1, on_pixels, r1);
   //-//
   //-//-//-// END GL INIT BLOB

   // move the image object somewhere, resize it and show it. any windowing
   // system would need this kind of thing - place a child "window"
   evas_object_move(r1, 128, 128);
   evas_object_resize(r1, w, h);
   evas_object_show(r1);

   // animating - just a demo. as long as you trigger an update on the image
   // object via evas_object_image_pixels_dirty_set(). any display system,
   // mainloop siztem etc. will have something of this kind unless it's making
   // you spin infinitely yourself and invent your own animation mechanism
   // 
   // NOTE: if you delete r1, this animator will keep runing trying to access
   // r1 so you'd better delete this animator with ecore_animator_del() or
   // structure how you do animation differently. you can also attach it like
   // evasgl, sfc, etc. etc. if this animator is specific to this object
   // only and delete it in the del handler for the obj.
   ecore_animator_add(on_animate, r1);

   evas_object_focus_set(r1, 1);
   evas_object_event_callback_add(r1, EVAS_CALLBACK_KEY_DOWN, key_down, r1);

   // finally show the window for the world to see. windowing system generic
   ecore_evas_show(ee);
   
   // begin the mainloop and tick over the animator, handle events etc.
   // also windowing system generic
   ecore_main_loop_begin();

   // standard EFL shutdown stuff - generic for most systems, EFL or not
   ecore_evas_shutdown();
   ecore_shutdown();
   return 0;
}


static Eina_Bool
on_animate(void *data)
{
   // just a demo - animate here whenever an animation tick happens and then
   // mark the image as "dirty" meaning it needs an update next time evas
   // renders. it will call the pixel get callback then.
   evas_object_image_pixels_dirty_set(data, EINA_TRUE);
   return EINA_TRUE; // keep looping
}

static void
on_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
   // on delete of our object clean up some things that don't get auto
   // celeted for us as they are not intrinsically bound to the image
   // object as such (you could use the same context and surface across
   // multiple image objects and re-use the evasgl handle too multiple times.
   // here we bind them to 1 object only though by doing this.
   Evas_GL *evasgl = evas_object_data_get(obj, "..evasgl");
   Evas_GL_Surface *sfc = evas_object_data_get(obj, "..sfc");
   Evas_GL_Context *ctx = evas_object_data_get(obj, "..ctx");
   GLData *gld = evas_object_data_get(data, "..gld");
   if (!gld) return;
   Evas_GL_API *gl = gld->glapi;

   evas_object_data_del((Evas_Object*)data, "..gld");

   // Do a make_current before deleting all the GL stuff.
   evas_gl_make_current(evasgl, sfc, ctx);
   gl->glDeleteShader(gld->vtx_shader);
   gl->glDeleteShader(gld->fgmt_shader);
   gl->glDeleteProgram(gld->program);

   evas_gl_surface_destroy(evasgl, sfc);
   evas_gl_context_destroy(evasgl, ctx);
   evas_gl_free(evasgl);
   free(gld);
}

static void
on_pixels(void *data, Evas_Object *obj)
{
   // get some variable we need from the object data keys
   Evas_GL *evasgl = evas_object_data_get(obj, "..evasgl");
   Evas_GL_Surface *sfc = evas_object_data_get(obj, "..sfc");
   Evas_GL_Context *ctx = evas_object_data_get(obj, "..ctx");
   GLData *gld = evas_object_data_get(obj, "..gld");
   if (!gld) return;
   Evas_GL_API *gl = gld->glapi;
   int w, h;

   // get the image size in case it changed with evas_object_image_size_set()
   evas_object_image_size_get(obj, &w, &h);
   // set up the context and surface as the current one
   evas_gl_make_current(evasgl, sfc, ctx);

   if (!gld->initialized)
     {
        gears_init(gld);
        gld->initialized = 1;
     }

   gears_reshape(gld, w, h);

   //printf("Image needs its pixels. It was marked as dirty. Provide them.\n");
   // GL Viewport stuff. you can avoid doing this if viewport is all the
   // same as last frame if you want
   // 
   // NOTE: the below GL calls will become something like:
   // 
   // evgl = evas_gl_api_get(evasgl);
   // ...
   // evgl->glViewport(0, 0, w, h);
   // evgl->glMatrixMode(GL_PROJECTION);
   // ...
   // evgl->glClear(GL_COLOR_BUFFER_BIT);
   // evgl->glEnable(GL_BLEND);
   // ... etc.
   gl->glViewport(0, 0, w, h);

   // Clear the buffer
   render_gears(gld);
   gl->glFlush();
}

/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
------------------------------------------------------------------------------
Achieve unprecedented app performance and reliability
What every C/C++ and Fortran developer should know.
Learn how Intel has extended the reach of its next-generation tools
to help boost performance applications - inlcuding clusters.
http://p.sf.net/sfu/intel-dev2devmay
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to