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