cedric pushed a commit to branch master.

http://git.enlightenment.org/website/www-content.git/commit/?id=5e0f62e4cd610d40270bf0ddbe9a328559b059d9

commit 5e0f62e4cd610d40270bf0ddbe9a328559b059d9
Author: Clément Bénier <clement.ben...@openwide.fr>
Date:   Tue Jul 7 09:59:43 2015 +0200

    Wiki pages gl_2d_tutorial created: 8 tuto pages + 4 images + code c
    
    Signed-off-by: Clément Bénier <clement.ben...@openwide.fr>
    Signed-off-by: Pierre Le Magourou <pierre.lemagou...@openwide.fr>
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 media/code_c/tutorial/gl2d/gl_2d.c         | 663 +++++++++++++++++++++++++++++
 media/cube.png                             | Bin 0 -> 6543 bytes
 media/cube_matrix.png                      | Bin 0 -> 29895 bytes
 media/gl_cube.png                          | Bin 0 -> 8807 bytes
 media/gl_cube_example.png                  | Bin 0 -> 96729 bytes
 pages/docs.txt                             |   3 +-
 pages/tutorial/gl2d/animating_cube.txt     | 132 ++++++
 pages/tutorial/gl2d/basic_application.txt  |  87 ++++
 pages/tutorial/gl2d/creating_cube.txt      | 128 ++++++
 pages/tutorial/gl2d/drawing_cube.txt       | 403 ++++++++++++++++++
 pages/tutorial/gl2d/effects.txt            |  53 +++
 pages/tutorial/gl2d/rendering_cube.txt     |  55 +++
 pages/tutorial/gl2d/widget_interaction.txt |  74 ++++
 pages/tutorial/gl_2d_tutorial.txt          |  19 +
 14 files changed, 1616 insertions(+), 1 deletion(-)

diff --git a/media/code_c/tutorial/gl2d/gl_2d.c 
b/media/code_c/tutorial/gl2d/gl_2d.c
new file mode 100644
index 0000000..d0a990e
--- /dev/null
+++ b/media/code_c/tutorial/gl2d/gl_2d.c
@@ -0,0 +1,663 @@
+#include <Elementary.h>
+#include <Evas_GL.h>
+
+typedef struct _GLData GLData;
+// GL related data here..
+struct _GLData
+{
+   Evas_GL_API  *glapi;
+   GLuint       program;
+   GLuint       vtx_shader;
+   GLuint       fgmt_shader;
+   GLuint       vbo;
+   GLuint       vertexID;
+   GLuint       colorID;
+   GLuint       mvpLoc;
+   GLuint       positionLoc;
+   GLuint       colorLoc;
+   GLfloat      model[16], mvp[16];
+   GLfloat      view[16];
+   GLfloat      xangle;
+   GLfloat      yangle;
+   GLfloat      zangle;
+   Eina_Bool    mouse_down : 1;
+   Eina_Bool    initialized : 1;
+   Evas_Object  *slx;
+   Evas_Object  *sly;
+   Evas_Object  *slz;
+   float        slx_value;
+   float        sly_value;
+   float        slz_value;
+};
+
+const float unit_matrix[] =
+{
+   1.0f, 0.0f, 0.0f, 0.0f,
+   0.0f, 1.0f, 0.0f, 0.0f,
+   0.0f, 0.0f, 1.0f, 0.0f,
+   0.0f, 0.0f, 0.0f, 1.0f
+};
+
+static const float vertices[] =
+{
+   // Front
+   -0.5f, 0.5f, 0.5f,
+   -0.5f, -0.5f, 0.5f,
+   0.5f, 0.5f, 0.5f,
+   0.5f, 0.5f, 0.5f,
+   -0.5f, -0.5f, 0.5f,
+   0.5f, -0.5f, 0.5f,
+   // Right
+   0.5f, 0.5f, 0.5f,
+   0.5f, -0.5f, 0.5f,
+   0.5f, 0.5f, -0.5f,
+   0.5f, 0.5f, -0.5f,
+   0.5f, -0.5f, 0.5f,
+   0.5f, -0.5f, -0.5f,
+   // Back
+   0.5f, 0.5f, -0.5f,
+   0.5f, -0.5f, -0.5f,
+   -0.5f, 0.5f, -0.5f,
+   -0.5f, 0.5f, -0.5f,
+   0.5f, -0.5f, -0.5f,
+   -0.5f, -0.5f, -0.5f,
+   // Left
+   -0.5f, 0.5f, -0.5f,
+   -0.5f, -0.5f, -0.5f,
+   -0.5f, 0.5f, 0.5f,
+   -0.5f, 0.5f, 0.5f,
+   -0.5f, -0.5f, -0.5f,
+   -0.5f, -0.5f, 0.5f,
+   // Top
+   -0.5f, 0.5f, -0.5f,
+   -0.5f, 0.5f, 0.5f,
+   0.5f, 0.5f, -0.5f,
+   0.5f, 0.5f, -0.5f,
+   -0.5f, 0.5f, 0.5f,
+   0.5f, 0.5f, 0.5f,
+   // Bottom
+   -0.5f, -0.5f, 0.5f,
+   -0.5f, -0.5f, -0.5f,
+   0.5f, -0.5f, 0.5f,
+   0.5f, -0.5f, 0.5f,
+   -0.5f, -0.5f, -0.5f,
+   0.5f, -0.5f, -0.5f
+};
+
+static const float colors[] =
+{
+   // Front
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   // Right
+   0.29296875f, 0.66796875f, 0.82578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.82578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.82578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.82578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.82578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.82578125f, 1.0f,
+   // Back
+   0.52734375f, 0.76171875f, 0.72578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.72578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.72578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.72578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.72578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.72578125f, 1.0f,
+   // Left
+   0.0625f, 0.57421875f, 0.62578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.62578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.62578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.62578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.62578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.62578125f, 1.0f,
+   // Top
+   0.29296875f, 0.66796875f, 0.52578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.52578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.52578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.52578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.52578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.52578125f, 1.0f,
+   // Bottom
+   0.52734375f, 0.76171875f, 0.42578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.42578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.42578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.42578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.42578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.42578125f, 1.0f
+};
+
+static void
+customLoadIdentity(float matrix[16])
+{
+   for (int i = 0; i < 16; i++)
+        matrix[i] = unit_matrix[i];
+}
+
+static void
+customMutlMatrix(float matrix[16], const float matrix0[16], const float 
matrix1[16])
+{
+   int i, row, column;
+   float temp[16];
+   for (column = 0; column < 4; column++)
+     {
+        for (row = 0; row < 4; row++)
+          {
+             temp[column * 4 + row] = 0.0f;
+             for (i = 0; i < 4; i++)
+                  temp[column * 4 + row] += matrix0[i * 4 + row] * 
matrix1[column * 4 + i];
+          }
+     }
+   for (i = 0; i < 16; i++)
+        matrix[i] = temp[i];
+}
+
+static void
+customScale(float matrix[16], const float sx, const float sy, const float sz)
+{
+   matrix[0]  *= sx;
+   matrix[1]  *= sx;
+   matrix[2]  *= sx;
+   matrix[3]  *= sx;
+
+   matrix[4]  *= sy;
+   matrix[5]  *= sy;
+   matrix[6]  *= sy;
+   matrix[7]  *= sy;
+
+   matrix[8]  *= sz;
+   matrix[9]  *= sz;
+   matrix[10] *= sz;
+   matrix[11] *= sz;
+}
+
+static void
+customRotate(float matrix[16], const float anglex, const float angley, const 
float anglez)
+{
+   const float pi = 3.141592f;
+   float temp[16];
+   float rz = 2.0f * pi * anglez / 360.0f;
+   float rx = 2.0f * pi * anglex / 360.0f;
+   float ry = 2.0f * pi * angley / 360.0f;
+   float sy = sinf(ry);
+   float cy = cosf(ry);
+   float sx = sinf(rx);
+   float cx = cosf(rx);
+   float sz = sinf(rz);
+   float cz = cosf(rz);
+
+   customLoadIdentity(temp);
+
+   temp[0] = cy * cz - sx * sy * sz;
+   temp[1] = cz * sx * sy + cy * sz;
+   temp[2] = -cx * sy;
+
+   temp[4] = -cx * sz;
+   temp[5] = cx * cz;
+   temp[6] = sx;
+
+   temp[8] = cz * sy + cy * sx * sz;
+   temp[9] = -cy * cz * sx + sy * sz;
+   temp[10] = cx * cy;
+
+   customMutlMatrix(matrix, matrix, temp);
+}
+
+static int
+customFrustum(float result[16], const float left, const float right, const 
float bottom, const float top, const float near, const float far)
+{
+   if ((right - left) == 0.0f || (top - bottom) == 0.0f || (far - near) == 
0.0f) return 0;
+
+   result[0] = 2.0f / (right - left);
+   result[1] = 0.0f;
+   result[2] = 0.0f;
+   result[3] = 0.0f;
+
+   result[4] = 0.0f;
+   result[5] = 2.0f / (top - bottom);
+   result[6] = 0.0f;
+   result[7] = 0.0f;
+
+   result[8] = 0.0f;
+   result[9] = 0.0f;
+   result[10] = -2.0f / (far - near);
+   result[11] = 0.0f;
+
+   result[12] = -(right + left) / (right - left);
+   result[13] = -(top + bottom) / (top - bottom);
+   result[14] = -(far + near) / (far - near);
+   result[15] = 1.0f;
+
+   return 1;
+}
+
+static int
+init_shaders(GLData *gld)
+{
+   Evas_GL_API *gl = gld->glapi;
+
+   GLbyte vertex_shader[] =
+       "attribute vec4 a_position;\n"
+       "attribute vec4 a_color;\n"
+       "uniform mat4 u_mvp_mat;\n"
+       "varying vec4 v_color;\n"
+       "void main()\n"
+       "{\n"
+       "   gl_Position = u_mvp_mat*a_position;\n"
+       "   v_color = a_color;\n"
+       "}";
+   GLbyte fragment_shader[] =
+       "varying vec4 v_color;\n"
+       "void main()\n"
+       "{\n"
+       "   gl_FragColor = v_color;\n"
+       "}";
+
+   GLint compiled;
+   const char *p = vertex_shader;
+
+   //vertex shader
+   gld->vtx_shader = gl->glCreateShader(GL_VERTEX_SHADER);
+   gl->glShaderSource(gld->vtx_shader, 1, &p, NULL);
+   gl->glCompileShader(gld->vtx_shader);
+   gl->glGetShaderiv(gld->vtx_shader, GL_COMPILE_STATUS, &compiled);
+   if (!compiled)
+     {
+        GLint info_len = 0;
+        gl->glGetShaderiv(gld->vtx_shader, GL_INFO_LOG_LENGTH, &info_len);
+        if (info_len > 1)
+          {
+             char* info_log = malloc(sizeof(char) * info_len);
+             gl->glGetShaderInfoLog(gld->vtx_shader, info_len, NULL, info_log);
+             printf("Error compiling shader:\n%s\n======\n%s\n======\n", 
info_log, p);
+             free(info_log);
+          }
+        gl->glDeleteShader(gld->vtx_shader);
+     }
+
+   //fragment shader
+   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->glGetShaderiv(gld->fgmt_shader, GL_COMPILE_STATUS, &compiled);
+   if (!compiled)
+     {
+        GLint info_len = 0;
+        gl->glGetShaderiv(gld->fgmt_shader, GL_INFO_LOG_LENGTH, &info_len);
+        if (info_len > 1)
+          {
+             char* info_log = malloc(sizeof(char) * info_len);
+             gl->glGetShaderInfoLog(gld->fgmt_shader, info_len, NULL, 
info_log);
+             printf("Error compiling shader:\n%s\n======\n%s\n======\n", 
info_log, p);
+             free(info_log);
+          }
+        gl->glDeleteShader(gld->fgmt_shader);
+     }
+
+   gld->program = gl->glCreateProgram();
+
+   GLint linked;
+   // Load the vertex/fragment shaders
+   gl->glAttachShader(gld->program, gld->vtx_shader);
+   gl->glAttachShader(gld->program, gld->fgmt_shader);
+   gl->glDeleteShader(gld->vtx_shader);
+   gl->glDeleteShader(gld->fgmt_shader);
+
+   gl->glBindAttribLocation(gld->program, 0, "a_position");
+   gl->glLinkProgram(gld->program);
+   gl->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
+   if (!linked)
+     {
+        GLint info_len = 0;
+        gl->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &info_len);
+        if (info_len > 1)
+          {
+             char* info_log = malloc(sizeof(char) * info_len);
+             gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log);
+             printf("Error linking program:\n%s\n", info_log);
+             free(info_log);
+          }
+        gl->glDeleteProgram(gld->program);
+        return 0;
+     }
+   gld->mvpLoc     = gl->glGetUniformLocation(gld->program, "u_mvp_mat");
+   gld->positionLoc = gl->glGetAttribLocation(gld->program, "a_position");
+   gld->colorLoc   = gl->glGetAttribLocation(gld->program, "a_color");
+   return 1;
+}
+
+// Callbacks
+// intialize callback that gets called once for intialization
+static void
+_init_gl(Evas_Object *obj)
+{
+   int w, h;
+   GLData *gld = evas_object_data_get(obj, "gld");
+   Evas_GL_API *gl = gld->glapi;
+
+   elm_glview_size_get(obj, &w, &h);
+
+   if (!gld->initialized)
+     {
+        if (!init_shaders(gld))
+          {
+             printf("Error Initializing Shaders\n");
+             return;
+          }
+
+        gl->glGenBuffers(1, &gld->vertexID);
+        gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vertexID);
+        gl->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, 
GL_STATIC_DRAW);
+
+        gl->glGenBuffers(1, &gld->colorID);
+        gl->glBindBuffer(GL_ARRAY_BUFFER, gld->colorID);
+        gl->glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, 
GL_STATIC_DRAW);
+
+        gld->initialized = EINA_TRUE;
+     }
+}
+
+// draw callback is where all the main GL rendering happens
+static void
+_draw_gl(Evas_Object *obj)
+{
+   Evas_GL_API *gl = elm_glview_gl_api_get(obj);
+   GLData *gld = evas_object_data_get(obj, "gld");
+   if(!gld) return;
+   int w, h;
+   int r, g, b, a;
+   //scale
+   double scalex = elm_slider_value_get(gld->slx);
+   double scaley = elm_slider_value_get(gld->sly);
+   double scalez = elm_slider_value_get(gld->slz);
+
+   r = 255; g = 255; b = 0; a = 0;
+
+   elm_glview_size_get(obj, &w, &h);
+
+   gl->glClearDepthf(1.0f);
+   gl->glClearColor(r / 255.0, g / 255.0, b / 255.0, a / 255.0);
+   gl->glEnable(GL_CULL_FACE);
+
+   gl->glViewport(0, 0, w, h);
+   gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   gl->glUseProgram(gld->program);
+
+   gl->glEnableVertexAttribArray(gld->positionLoc);
+   gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vertexID);
+   gl->glVertexAttribPointer(gld->positionLoc, 3, GL_FLOAT, GL_FALSE, 3 * 
sizeof(float), 0);
+
+   gl->glEnableVertexAttribArray(gld->colorLoc);
+   gl->glBindBuffer(GL_ARRAY_BUFFER, gld->colorID);
+   gl->glVertexAttribPointer(gld->colorLoc, 4, GL_FLOAT, GL_FALSE, 4 * 
sizeof(float), 0);
+
+   customLoadIdentity(gld->model);
+   customRotate(gld->model, gld->xangle, gld->yangle, gld->zangle++);
+   //scale
+   customScale(gld->model, scalex, scaley, scalez);
+   customMutlMatrix(gld->mvp, gld->view, gld->model);
+
+   gl->glUniformMatrix4fv(gld->mvpLoc, 1, GL_FALSE, gld->mvp);
+   gl->glDrawArrays(GL_TRIANGLES, 0, 36);
+   gl->glFlush();
+}
+
+// resize callback gets called every time object is resized
+static void
+_resize_gl(Evas_Object *obj)
+{
+   int w, h;
+   GLData *gld = evas_object_data_get(obj, "gld");
+   Evas_GL_API *gl = gld->glapi;
+   float aspect;
+
+   elm_glview_size_get(obj, &w, &h);
+   customLoadIdentity(gld->view);
+
+   if (w > h)
+     {
+        aspect = (float) w / h;
+        customFrustum(gld->view, -1.0 * aspect, 1.0 * aspect, -1.0, 1.0, -1.0, 
1.0);
+     }
+   else
+     {
+        aspect = (float) h / w;
+        customFrustum(gld->view, -1.0, 1.0, -1.0 * aspect, 1.0 * aspect, -1.0, 
1.0);
+     }
+}
+// delete callback gets called when glview is deleted
+static void
+_del_gl(Evas_Object *obj)
+{
+   GLData *gld = evas_object_data_get(obj, "gld");
+   if (!gld)
+     {
+        printf("Unable to get GLData. \n");
+        return;
+     }
+
+   Evas_GL_API *gl = gld->glapi;
+   gl->glDeleteShader(gld->vtx_shader);
+   gl->glDeleteShader(gld->fgmt_shader);
+   gl->glDeleteProgram(gld->program);
+   evas_object_data_del((Evas_Object*) obj, "..gld");
+}
+
+// just need to notify that glview has changed so it can render
+static Eina_Bool
+_anim(void *data)
+{
+   elm_glview_changed_set(data);
+   return EINA_TRUE;
+}
+static void
+_mouse_down_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
+{
+   GLData *gld = data;
+   gld->mouse_down = EINA_TRUE;
+}
+
+static void
+_mouse_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
+{
+   GLData *gld = data;
+   gld->mouse_down = EINA_FALSE;
+}
+
+static void
+_mouse_move_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
+{
+   Evas_Event_Mouse_Move *ev;
+   ev = (Evas_Event_Mouse_Move *)event_info;
+      GLData *gld = data;
+   float dx = 0, dy = 0;
+
+   if(gld->mouse_down)
+     {
+        dx = ev->cur.canvas.x - ev->prev.canvas.x;
+        dy = ev->cur.canvas.y - ev->prev.canvas.y;
+        gld->xangle += dy;
+        gld->yangle += dx;
+     }
+}
+
+static void
+_on_done(void *data, Evas_Object *obj, void *event_info)
+{
+   evas_object_del((Evas_Object*)data);
+   elm_exit();
+}
+static void
+_del(void *data, Evas *evas, Evas_Object *obj, void *event_info)
+{
+   Ecore_Animator *ani = evas_object_data_get(obj, "ani");
+   ecore_animator_del(ani);
+}
+
+static Eina_Bool
+animate_reset_cb(void *data, double pos)
+{
+   GLData *gld = data;
+   double frame = pos;
+   float x, y, z;
+
+   frame = ecore_animator_pos_map(pos, ECORE_POS_MAP_BOUNCE, 1.8, 7);
+   x = gld->slx_value * (1 - frame) + 0.75 * frame;
+   y = gld->sly_value * (1 - frame) + 0.75 * frame;
+   z = gld->slz_value * (1 - frame) + 0.75 * frame;
+
+   elm_slider_value_set(gld->slx, x);
+   elm_slider_value_set(gld->sly, y);
+   elm_slider_value_set(gld->slz, z);
+
+   return EINA_TRUE;
+}
+
+static void btn_reset_cb(void *data, Evas_Object *obj,  void *event_info)
+{
+   GLData *gld = data;
+   gld->slx_value = elm_slider_value_get(gld->slx);
+   gld->sly_value = elm_slider_value_get(gld->sly);
+   gld->slz_value = elm_slider_value_get(gld->slz);
+   ecore_animator_timeline_add(1, animate_reset_cb, gld);
+}
+
+EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+   Evas_Object *win, *bx, *inner_box, *bt, *gl, *btn_reset;
+   Ecore_Animator *ani;
+   GLData *gld = NULL;
+   if (!(gld = calloc(1, sizeof(GLData)))) return 1;
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+   win = elm_win_util_standard_add("glview simple", "GLView Simple");
+   elm_win_autodel_set(win, EINA_TRUE);
+   bx = elm_box_add(win);
+   evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bx);
+   inner_box = elm_box_add(bx);
+   evas_object_size_hint_weight_set(inner_box, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+   evas_object_show(inner_box);
+
+   //-//-//-// THIS IS WHERE GL INIT STUFF HAPPENS (ALA EGL)
+   //-//
+   // create a new glview object
+   gl = elm_glview_add(win);
+   gld->glapi = elm_glview_gl_api_get(gl);
+   evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   // mode is simply for supporting alpha, depth buffering, and stencil
+   // buffering.
+   elm_glview_mode_set(gl, ELM_GLVIEW_ALPHA | ELM_GLVIEW_DEPTH);
+   // resize policy tells glview what to do with the surface when it
+   // resizes.  ELM_GLVIEW_RESIZE_POLICY_RECREATE will tell it to
+   // destroy the current surface and recreate it to the new size
+   elm_glview_resize_policy_set(gl, ELM_GLVIEW_RESIZE_POLICY_RECREATE);
+   // render policy tells glview how it would like glview to render
+   // gl code. ELM_GLVIEW_RENDER_POLICY_ON_DEMAND will have the gl
+   // calls called in the pixel_get callback, which only gets called
+   // if the object is visible, hence ON_DEMAND.  ALWAYS mode renders
+   // it despite the visibility of the object.
+   elm_glview_render_policy_set(gl, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND);
+   // initialize callback function gets registered here
+   elm_glview_init_func_set(gl, _init_gl);
+   // delete callback function gets registered here
+   elm_glview_del_func_set(gl, _del_gl);
+   elm_glview_resize_func_set(gl, _resize_gl);
+   elm_glview_render_func_set(gl, _draw_gl);
+   //-//
+   //-//-//-// END GL INIT BLOB
+   elm_box_pack_end(bx, gl);
+   evas_object_show(gl);
+   elm_object_focus_set(gl, EINA_TRUE);
+   // animating - just a demo. as long as you trigger an update on the image
+   // object via elm_glview_changed_set() it will be updated.
+   //
+   // NOTE: if you delete gl, this animator will keep running trying to access
+   // gl so you'd better delete this animator with ecore_animator_del().
+   ani = ecore_animator_add(_anim, gl);
+   evas_object_data_set(gl, "ani", ani);
+   evas_object_data_set(gl, "gld", gld);
+   evas_object_event_callback_add(gl, EVAS_CALLBACK_DEL, _del, gl);
+   evas_object_event_callback_add(gl, EVAS_CALLBACK_MOUSE_DOWN, 
_mouse_down_cb, gld);
+   evas_object_event_callback_add(gl, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, 
gld);
+   evas_object_event_callback_add(gl, EVAS_CALLBACK_MOUSE_MOVE, 
_mouse_move_cb, gld);
+   /* Set rotation variables */
+   gld->xangle = 45.0f;
+   gld->yangle = 45.0f;
+   gld->zangle = 0.0f;
+   gld->mouse_down = EINA_FALSE;
+   gld->initialized = EINA_FALSE;
+   // add an 'OK' button to end the program
+   bt = elm_button_add(win);
+   elm_object_text_set(bt, "OK");
+   evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
+   elm_box_pack_end(bx, bt);
+   evas_object_show(bt);
+   evas_object_smart_callback_add(bt, "clicked", _on_done, win);
+
+   // Slider for X-axis scale
+   gld->slx = elm_slider_add(inner_box);
+   evas_object_size_hint_align_set(gld->slx, EVAS_HINT_FILL, 0);
+   elm_slider_horizontal_set(gld->slx, EINA_TRUE);
+   elm_slider_unit_format_set(gld->slx, "%1.2f units");
+   elm_slider_indicator_format_set(gld->slx, "%1.2f units");
+   elm_slider_indicator_show_set(gld->slx, EINA_TRUE);
+   elm_slider_min_max_set(gld->slx, 0, 1.5);
+   elm_slider_value_set(gld->slx, 0.75);
+   evas_object_color_set(gld->slx, 0.0, 0.0, 120, 255);
+   elm_box_pack_end(inner_box, gld->slx);
+   evas_object_show(gld->slx);
+
+   // Slider for Y-axis scale
+   gld->sly = elm_slider_add(inner_box);
+   evas_object_size_hint_align_set(gld->sly, EVAS_HINT_FILL, 0);
+   elm_slider_horizontal_set(gld->sly, EINA_TRUE);
+   elm_slider_unit_format_set(gld->sly, "%1.2f units");
+   elm_slider_indicator_format_set(gld->sly, "%1.2f units");
+   elm_slider_indicator_show_set(gld->sly, EINA_TRUE);
+   elm_slider_min_max_set(gld->sly, 0, 1.5);
+   elm_slider_value_set(gld->sly, 0.75);
+   evas_object_color_set(gld->sly, 0.0, 0.0, 120, 255);
+   elm_box_pack_end(inner_box, gld->sly);
+   evas_object_show(gld->sly);
+
+   // Slider for Z-axis scale
+   gld->slz = elm_slider_add(inner_box);
+   evas_object_size_hint_align_set(gld->slz, EVAS_HINT_FILL, 0);
+   elm_slider_horizontal_set(gld->slz, EINA_TRUE);
+   elm_slider_unit_format_set(gld->slz, "%1.2f units");
+   elm_slider_indicator_format_set(gld->slz, "%1.2f units");
+   elm_slider_indicator_show_set(gld->slz, EINA_TRUE);
+   elm_slider_min_max_set(gld->slz, 0, 1.5);
+   elm_slider_value_set(gld->slz, 0.75);
+   evas_object_color_set(gld->slz, 0.0, 0.0, 120, 255);
+   elm_box_pack_end(inner_box, gld->slz);
+   evas_object_show(gld->slz);
+
+   // Reset button
+   btn_reset = elm_button_add(inner_box);
+   elm_object_text_set(btn_reset, "Reset");
+   evas_object_smart_callback_add(btn_reset, "clicked", btn_reset_cb, gld);
+   evas_object_size_hint_align_set(btn_reset, EVAS_HINT_FILL, 0);
+   elm_box_pack_end(inner_box, btn_reset);
+   evas_object_show(btn_reset);
+
+   evas_object_resize(inner_box, 100, 100);
+   evas_object_move(inner_box, 0, 5);
+   evas_object_resize(bx, 800, 800);
+   evas_object_resize(win, 800, 800);
+   evas_object_show(win);
+   // run the mainloop and process events and callbacks
+   elm_run();
+   free(gld);
+   elm_shutdown();
+   return 0;
+}
+ELM_MAIN()
diff --git a/media/cube.png b/media/cube.png
new file mode 100644
index 0000000..dc53478
Binary files /dev/null and b/media/cube.png differ
diff --git a/media/cube_matrix.png b/media/cube_matrix.png
new file mode 100644
index 0000000..70710dd
Binary files /dev/null and b/media/cube_matrix.png differ
diff --git a/media/gl_cube.png b/media/gl_cube.png
new file mode 100644
index 0000000..7e1cf04
Binary files /dev/null and b/media/gl_cube.png differ
diff --git a/media/gl_cube_example.png b/media/gl_cube_example.png
new file mode 100644
index 0000000..6b15077
Binary files /dev/null and b/media/gl_cube_example.png differ
diff --git a/pages/docs.txt b/pages/docs.txt
index 9126b2e..93ac435 100644
--- a/pages/docs.txt
+++ b/pages/docs.txt
@@ -48,6 +48,7 @@ Go check the current available version of EFL on each 
distro/platform:
   * [[tutorial/menu_tutorial|Menu Tutorial]]
   * [[tutorial/naviframe_tutorial|Naviframe Tutorial]]
   * [[tutorial/popup_tutorial|Popup Tutorial]]
+  * [[tutorial/gl_2d_tutorial|GL 2D Tutorial]]
 
 ----
 
@@ -66,4 +67,4 @@ improving our API references a lot.
 
   * 
[[https://build.enlightenment.org/job/nightly_efl_gcc_x86_64/lastSuccessfulBuild/artifact/doc/html/index.html|EFL]]
   * 
[[https://build.enlightenment.org/job/nightly_elm_gcc_x86_64/lastSuccessfulBuild/artifact/doc/html/index.html|Elementary]]
-  * 
[[https://build.enlightenment.org/job/base_pyefl_build/lastSuccessfulBuild/artifact/build/sphinx/html/index.html|Python
 Bindings]]
\ No newline at end of file
+  * 
[[https://build.enlightenment.org/job/base_pyefl_build/lastSuccessfulBuild/artifact/build/sphinx/html/index.html|Python
 Bindings]]
diff --git a/pages/tutorial/gl2d/animating_cube.txt 
b/pages/tutorial/gl2d/animating_cube.txt
new file mode 100644
index 0000000..d895884
--- /dev/null
+++ b/pages/tutorial/gl2d/animating_cube.txt
@@ -0,0 +1,132 @@
+~~Title: Creating the Cube - GL 2D Tutorial~~
+//**__previous page__: **//[[/tutorial/gl2d/rendering_cube|Rendering the 
Cube]].
+==== Animating the Cube ====
+
+''Ecore_Animator'' is used to create an animation.
+
+<code c>
+// just need to notify that glview has changed so it can render
+static Eina_Bool
+_anim(void *data)
+{
+   elm_glview_changed_set(data);
+   return EINA_TRUE;
+}
+</code>
+
+Next define the global variables which are used as parameters of the rendering
+process. Add parameters to the application data object that are used to
+control the scaling and the rotation of the cube. To make the cube rotate on
+one axis, take z, and allow the user to interact with the mouse to make the
+cube rotate on the two other axes x and y. In order to figure out whether the
+user is holding the mouse down, add a Boolean variable to have this
+information. Operations such as shader initialization or program compilation
+are not required at each tick of the animation loop. For better performance,
+isolate such task from the repetitive rendering loop. For such purpose, add a
+Boolean variable which tells whether the initialization is already done.
+
+<code c>
+struct _GLData
+{
+   GLfloat      xangle;
+   GLfloat      yangle;
+   GLfloat      zangle;
+   Eina_Bool    mouse_down : 1;
+   Eina_Bool    initialized : 1;
+} GLData;
+</code>
+
+Here are the modifications that must be done to the rendering loop for
+animation.
+
+First, lighten the recurrent rendering process by adding an initialization
+step:
+
+<code c>
+if (!gld->initialized)
+  {
+     if (!init_shaders(gld))
+       {
+          printf("Error Initializing Shaders\n");
+          return;
+       }
+
+     //generate the buffers for the vertex positions and colors
+     gl->glGenBuffers(1, &gld->vertexID);
+     gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vertexID);
+     gl->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, 
GL_STATIC_DRAW);
+
+     gl->glGenBuffers(1, &gld->colorID);
+     gl->glBindBuffer(GL_ARRAY_BUFFER, gld->colorID);
+     gl->glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
+
+     gld->initialized = EINA_TRUE;
+  }
+</code>
+
+Before drawing the vertices, the rotation angle for the model-view matrix must
+be incremented for every tick.
+
+<code c>
+customLoadIdentity(gld->model);
+customRotate(gld->model, gld->xangle, gld->yangle, gld->zangle++);
+customMutlMatrix(gld->mvp, gld->view, gld->model);
+</code>
+
+This makes the cube rotate automatically. The next thing is to use the mouse
+to drag the cube around. To do so, add callbacks for mouse events. The first
+callback defines whether the user is holding the mouse down while moving the
+cursor around:
+
+This makes the cube rotate automatically. The next thing is to use the mouse
+to drag the cube around. To do so, add callbacks for mouse events. The first
+callback defines whether the user is holding the mouse down while moving the
+cursor around:
+
+<code c>
+static void
+_mouse_down_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
+{
+   GLData *gld = data;
+   gld->mouse_down = EINA_TRUE;
+}
+
+static void
+_mouse_up_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
+{
+   GLData *gld = data;
+   gld->mouse_down = EINA_FALSE;
+}
+</code>
+
+When the mouse is down, calculate the new rotation angle with the mouse
+movement along the x and y axis:
+
+<code c>
+static void
+_mouse_move_cb(void *data, Evas *e , Evas_Object *obj , void *event_info)
+{
+   Evas_Event_Mouse_Move *ev;
+   ev = (Evas_Event_Mouse_Move *)event_info;
+   GLData *gld = data;
+   float dx = 0, dy = 0;
+
+   if(gld->mouse_down)
+     {
+        dx = ev->cur.canvas.x - ev->prev.canvas.x;
+        dy = ev->cur.canvas.y - ev->prev.canvas.y;
+        gld->xangle += dy;
+        gld->yangle += dx;
+     }
+}
+</code>
+
+Define the mouse events callbacks when creating the image canvas:
+
+<code c>
+evas_object_event_callback_add(gl, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, 
gld);
+evas_object_event_callback_add(gl, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, gld);
+evas_object_event_callback_add(gl, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, 
gld);
+</code>
+\\
+//**__next page__: **//[[/tutorial/gl2d/widget_interaction|Implementing Widget 
Interaction]]
diff --git a/pages/tutorial/gl2d/basic_application.txt 
b/pages/tutorial/gl2d/basic_application.txt
new file mode 100644
index 0000000..693ecdb
--- /dev/null
+++ b/pages/tutorial/gl2d/basic_application.txt
@@ -0,0 +1,87 @@
+~~Title: Basic Application - GL 2D Tutorial~~
+==== Creating the Basic Application ====
+
+This tutorial demonstrates how to create a multicolored 3D rotating cube using
+OpenGL ES 2.0 API provided by GLView library. Several concepts are explained,
+such as the cube geometry, the initialization phase of the model, the
+adjustment of this very model frame by frame, and the way to design the OpenGL
+ES rendering loop.
+
+First create a basic application as explained in the Basic application
+tutorial. This provides a basic UI application skeleton which already makes
+available the window object that contains the GLView canvas. Here an example
+below :
+
+<code c>
+#include <Elementary.h>
+#include <Evas_GL.h>
+#include <stdio.h>
+
+EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+   Evas_Object *win, *box, *gl;
+   Ecore_Animator *ani;
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+   win = elm_win_util_standard_add("glview simple", "GLView Simple");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   evas_object_resize(win, 320, 480);
+   evas_object_show(win);
+   // run the mainloop and process events and callbacks
+   elm_run();
+   elm_shutdown();
+   return 0;
+}
+ELM_MAIN()
+</code>
+
+=== OpenGL ES Canvas ===
+
+To develop a GL application, you have to call
+''elm_config_accel_preference_set()'' before creating a window which makes an
+application to use GPU.
+
+<code c>
+elm_config_accel_preference_set("opengl");
+</code>
+
+To call GL functions, you can get the Evas_GL instance from
+''elm_glview_gl_api_get'' function, then you can call the OpenGL ES function
+with the instance.
+
+<code c>
+gl = elm_glview_add(win);
+Evas_GL_API *glapi = elm_glview_gl_api_get(gl);
+evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+</code>
+
+The next thing to do is to set the GLView mode.
+elm_glview_mode_set(Evas_Object *obj, Elm_GLView_Mode mode) supports alpha,
+depth, stencil, MSAA, and client_side_rotation.
+
+<code c>
+// mode is simply for supporting alpha, depth buffering, and stencil
+// buffering.
+elm_glview_mode_set(gl, ELM_GLVIEW_ALPHA | ELM_GLVIEW_DEPTH);
+</code>
+
+To set up callbacks:
+<code c>
+   // initialize callback function gets registered here
+   elm_glview_init_func_set(gl, _init_gl);
+   // delete callback function gets registered here
+   elm_glview_del_func_set(gl, _del_gl);
+   elm_glview_resize_func_set(gl, _resize_gl);
+   elm_glview_render_func_set(gl, _draw_gl);
+   ani = ecore_animator_add(_anim, gl);
+</code>
+\\
+| Callback for initialisation | ''_init_gl'' | The initialization callback is 
called when the GLView is first created, after a valid OpenGL ES context and 
surface have been created. This is called from the main loop, just as the 3 
other callbacks. |
+| Callback for resizing | ''_resize_gl'' | The resize callback is called 
whenever the GLView widget is resized and depends on policy set. A common 
action to take here is to reset the viewport. \\ 
''elm_glview_resize_policy_set(gl, ELM_GLVIEW_RESIZE_POLICY_RECREATE)'' \\ 
resize policy tells glview what to do with the surface when it resizes. 
ELM_GLVIEW_RESIZE_POLICY_RECREATE will tell it to destroy the current surface 
and recreate it to the new size |
+| Callback for drawing | ''_draw_gl'' | The drawing callback is called 
whenever a new frame has to be drawn. The exact moment when this function is 
called depends on the policy set when calling. \\ 
''elm_glview_render_policy_set(gl, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND)'' \\ 
Another policy is ELM_GLVIEW_POLICY_ALWAYS, which requests render always even 
when it is not visible. So on demand policy is probably what you are looking 
for. The application can now draw anything using GL primitives  [...]
+| Callback for deleting | ''_del_gl'' | The delete callback is triggered when 
the GLView is being destroyed, from the main loop, and no other callback can be 
called on the same object afterwards. |
+| Add an animator | ''_anim_gl'' | The application above is technically 
working but the scene does not get updated unless the object is marked as such. 
Games might want to use an animator to have a regular update of the scene. \\ 
Any other event can be used to refresh the view, for example user input if the 
view needs to be updated. |
+
+//**__next page__: **//[[/tutorial/gl2d/creating_cube|Creating the Cube]]
diff --git a/pages/tutorial/gl2d/creating_cube.txt 
b/pages/tutorial/gl2d/creating_cube.txt
new file mode 100644
index 0000000..f572f5d
--- /dev/null
+++ b/pages/tutorial/gl2d/creating_cube.txt
@@ -0,0 +1,128 @@
+~~Title: Creating the Cube - GL 2D Tutorial~~
+//**__previous page__: **//[[/tutorial/gl2d/basic_application|Creating the
+Basic Application]].
+
+==== Creating the Cube ====
+
+Creating and coloring the cube can be separated into two distinct tasks:
+define the vertices and then add the colors to the faces.
+
+{{ :cube.png }}
+
+Declare an array that stores the vertices of the cube in order to make it
+look as the drawing above.
+
+<code c>
+static const float vertices[] =
+{
+    // Front
+    -0.5f, 0.5f, 0.5f,
+    -0.5f, -0.5f, 0.5f,
+    0.5f, 0.5f, 0.5f,
+    0.5f, 0.5f, 0.5f,
+    -0.5f, -0.5f, 0.5f,
+    0.5f, -0.5f, 0.5f,
+    // Right
+    0.5f, 0.5f, 0.5f,
+    0.5f, -0.5f, 0.5f,
+    0.5f, 0.5f, -0.5f,
+    0.5f, 0.5f, -0.5f,
+    0.5f, -0.5f, 0.5f,
+    0.5f, -0.5f, -0.5f,
+    // Back
+    0.5f, 0.5f, -0.5f,
+    0.5f, -0.5f, -0.5f,
+    -0.5f, 0.5f, -0.5f,
+    -0.5f, 0.5f, -0.5f,
+    0.5f, -0.5f, -0.5f,
+    -0.5f, -0.5f, -0.5f,
+    // Left
+    -0.5f, 0.5f, -0.5f,
+    -0.5f, -0.5f, -0.5f,
+    -0.5f, 0.5f, 0.5f,
+    -0.5f, 0.5f, 0.5f,
+    -0.5f, -0.5f, -0.5f,
+    -0.5f, -0.5f, 0.5f,
+    // Top
+    -0.5f, 0.5f, -0.5f,
+    -0.5f, 0.5f, 0.5f,
+    0.5f, 0.5f, -0.5f,
+    0.5f, 0.5f, -0.5f,
+    -0.5f, 0.5f, 0.5f,
+    0.5f, 0.5f, 0.5f,
+    // Bottom
+    -0.5f, -0.5f, 0.5f,
+    -0.5f, -0.5f, -0.5f,
+    0.5f, -0.5f, 0.5f,
+    0.5f, -0.5f, 0.5f,
+    -0.5f, -0.5f, -0.5f,
+    0.5f, -0.5f, -0.5f
+};
+</code>
+
+{{ :cube_matrix.png }}
+
+Each triangle is defined with three point coordinates, three vertices for each
+triangle, two triangles per face and six faces, so there are 36 vertices is
+total.
+
+The next step is to specify a color for each face of the cube. Each color is
+represented in the RGBA format for the corresponding vertex, where each
+component is ranged from 0 to 1 where 1 is the maximum value. For example, in
+32-byte color space, the RGB color of (16, 147, 237) is translated as (0.0625,
+0.57421875, 0.92578125). The A of RGBA stands for the alpha channel, which
+represents the transparency of the color. All colors defined in this tutorial
+are opaque to make it simpler, so each alpha value is set to 1.0. In this
+example, different variants of blue are used for the faces of the cube.
+
+Specify the colors of the cube into an array dedicated to this vertex:
+
+<code c>
+static const float colors[] =
+{
+   // Front
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   // Right
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   // Back
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   // Left
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   0.0625f, 0.57421875f, 0.92578125f, 1.0f,
+   // Top
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   0.29296875f, 0.66796875f, 0.92578125f, 1.0f,
+   // Bottom
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f,
+   0.52734375f, 0.76171875f, 0.92578125f, 1.0f
+};
+</code>
+
+//**__next page__: **//[[/tutorial/gl2d/drawing_cube|Drawing the Cube with 
GLView]]
diff --git a/pages/tutorial/gl2d/drawing_cube.txt 
b/pages/tutorial/gl2d/drawing_cube.txt
new file mode 100644
index 0000000..cf6f023
--- /dev/null
+++ b/pages/tutorial/gl2d/drawing_cube.txt
@@ -0,0 +1,403 @@
+~~Title: Drawing the Cube - GL 2D Tutorial~~
+//**__previous page__: **//[[/tutorial/gl2d/creating_cube|Creating the Cube]]
+==== Drawing the Cube with GLView ====
+
+=== Mathematical Functions for Matrices ===
+
+After the model is initialized, create functionality to manipulate the scene.
+OpenGL ES 2.0 provided by GLView requires more preliminary work that the
+previous version of the library, but gives more power and flexibility,
+although our example does not take much benefit.
+
+First, declare additional global variables for specific OpenGL ES 2.0 tasks: a
+program object, an identifier for the vertices buffer and
+another for the colors. Add also three variables to ensure the
+connection with the shader language:
+
+    * ''mvpLoc'' is an identifier for model-view-projection matrix.
+    * ''positionLoc'' is an identifier for the vertex position.
+    * ''colorLoc'' is an identifier for the vertex color.
+
+Declare all these variables in the ''GLData'' object:
+
+<code c>
+struct _GLData
+{
+    GLuint       program;
+    GLuint       vtx_shader;
+    GLuint       fgmt_shader;
+    GLuint       vbo;
+    GLuint       vertexID;
+    GLuint       colorID;
+    GLuint       mvpLoc;
+    GLuint       positionLoc;
+    GLuint       colorLoc;
+}
+</code>
+
+Since OpenGL ES 2.0, some functions for matrix transformations have been
+removed. Define three matrix functions to use: projection matrix, model-view
+matrix, and a combination of these allows you to perform any transformations
+on the initial vertices matrix.
+
+== Matrix Multiplication Function (glMultMatrix) ==
+
+First, define a function that is able to return the inner product of two
+matrices. This function reproduces the behavior of ''glMultMatrix()''
+available in OpenGL ES 1.1. This function is very useful since almost every
+matrix transformation can be translated as multiplications of matrices.
+
+The function takes three arguments, one is for the result and the other 2
+matrices are operands:
+
+<code c>
+static void
+customMutlMatrix(float matrix[16], const float matrix0[16], const float 
matrix1[16])
+{
+   int i, row, column;
+   float temp[16];
+   for (column = 0; column < 4; column++)
+     {
+        for (row = 0; row < 4; row++)
+          {
+             temp[column * 4 + row] = 0.0f;
+             for (i = 0; i < 4; i++)
+                 temp[column * 4 + row] += matrix0[i * 4 + row] * 
matrix1[column * 4 + i];
+          }
+     }
+   for (i = 0; i < 16; i++)
+        matrix[i) = temp[i];
+}
+</code>
+
+== Matrix Identity Function (glLoadIdentity) ==
+
+Implement a function equivalent to ''glLoadIdentity()'' that replaces the 
current
+matrix with the identity matrix:
+
+<code c>
+const float unit_matrix[] =
+{
+   1.0f, 0.0f, 0.0f, 0.0f,
+   0.0f, 1.0f, 0.0f, 0.0f,
+   0.0f, 0.0f, 1.0f, 0.0f,
+   0.0f, 0.0f, 0.0f, 1.0f
+};
+
+static void
+customLoadIdentity(float matrix[16])
+{
+   for (int i = 0; i < 16; i++)
+        matrix[i] = unit_matrix[i];
+}
+</code>
+
+== Matrix Projection Function (glFrustum) ==
+
+Since ''glFrustum'' has been depreciated, implement a function that produces
+perspective projection matrices that are used to transform from eye coordinate
+space to clip coordinate space. This matrix projects a portion of the space
+(the "fustum") to your screen. Many caveats apply (normalized device
+coordinates, perspective divide, etc), but that is the idea:
+
+<code c>
+static int
+customFrustum(float result[16], const float left, const float right, const 
float bottom, const float top, const float near, const float far)
+{
+   if ((right - left) == 0.0f || (top - bottom) == 0.0f || (far - near) == 
0.0f) return 0;
+
+   result[0] = 2.0f / (right - left);
+   result[1] = 0.0f;
+   result[2] = 0.0f;
+   result[3] = 0.0f;
+
+   result[4] = 0.0f;
+   result[5] = 2.0f / (top - bottom);
+   result[6] = 0.0f;
+   result[7] = 0.0f;
+
+   result[8] = 0.0f;
+   result[9] = 0.0f;
+   result[10] = -2.0f / (far - near);
+   result[11] = 0.0f;
+
+   result[12] = -(right + left) / (right - left);
+   result[13] = -(top + bottom) / (top - bottom);
+   result[14] = -(far + near) / (far - near);
+   result[15] = 1.0f;
+
+   return 1;
+}
+</code>
+
+== Matrix Scaling Function (glScale) ==
+
+Depreciated ''glScale()'' function represents a non-uniform scaling along the 
x,
+y, and z axes. The three parameters indicate the desired scale factor along
+each of the three axes:
+
+<code c>
+const float scale_matrix[] =
+{
+   x,    0.0f, 0.0f, 0.0f,
+   0.0f, y,    0.0f, 0.0f,
+   0.0f, 0.0f, z,    0.0f,
+   0.0f, 0.0f, 0.0f, 1.0f
+}
+</code>
+
+Here is the implementation of the matrix scaling function:
+
+<code c>
+static void
+customScale(float matrix[16], const float sx, const float sy, const float sz)
+{
+    matrix[0]  *= sx;
+    matrix[1]  *= sx;
+    matrix[2]  *= sx;
+    matrix[3]  *= sx;
+
+    matrix[4]  *= sy;
+    matrix[5]  *= sy;
+    matrix[6]  *= sy;
+    matrix[7]  *= sy;
+
+    matrix[8]  *= sz;
+    matrix[9]  *= sz;
+    matrix[10] *= sz;
+    matrix[11] *= sz;
+}
+</code>
+
+== Matrix Rotation Function (glRotate) ==
+
+Define a function to represent a rotation by the vector (x y z). The current
+matrix is multiplied by a rotation matrix:
+
+<code c>
+static void
+customRotate(float matrix[16], const float anglex, const float angley, const 
float anglez)
+{
+    const float pi = 3.141592f;
+    float temp[16];
+    float rz = 2.0f * pi * anglez / 360.0f;
+    float rx = 2.0f * pi * anglex / 360.0f;
+    float ry = 2.0f * pi * angley / 360.0f;
+    float sy = sinf(ry);
+    float cy = cosf(ry);
+    float sx = sinf(rx);
+    float cx = cosf(rx);
+    float sz = sinf(rz);
+    float cz = cosf(rz);
+
+    customLoadIdentity(temp);
+
+    temp[0] = cy * cz - sx * sy * sz;
+    temp[1] = cz * sx * sy + cy * sz;
+    temp[2] = -cx * sy;
+
+    temp[4] = -cx * sz;
+    temp[5] = cx * cz;
+    temp[6] = sx;
+
+    temp[8] = cz * sy + cy * sx * sz;
+    temp[9] = -cy * cz * sx + sy * sz;
+    temp[10] = cx * cy;
+
+    customMutlMatrix(matrix, matrix, temp);
+}
+</code>
+
+=== Create the Shader ===
+
+Define the source for the shader using a ''GLbyte'' array. First comes out 
vertex
+shader, which is used to a medium precision for float values. Then build a
+uniform matrix with dimensions 4x4 intended to hold the model-view-projection
+matrix. Also create two vector attributes which have 4 components for the
+vertex position and the color. This varying variable v_color can be accessed
+from the fragment shader. In the main function of the shader, initialize the
+position of the current vertex, gl_Position, with the product of the vertex
+position and the model-view-projection matrix, in order to normalize the
+position for the target screen. The pixel color is calculated by the varying
+variable from the vertex shader.
+
+In the fragment shader, declare a varying variable, then set the color of the
+pixel with this interpolated color.
+
+<code c>
+GLbyte vertex_shader[] =
+    "attribute vec4 a_position;\n"
+    "attribute vec4 a_color;\n"
+    "uniform mat4 u_mvp_mat;\n"
+    "varying vec4 v_color;\n"
+    "void main()\n"
+    "{\n"
+    "   gl_Position = u_mvp_mat*a_position;\n"
+    "   v_color = a_color;\n"
+    "}";
+GLbyte fragment_shader[] =
+    "varying vec4 v_color;\n"
+    "void main()\n"
+    "{\n"
+    "   gl_FragColor = v_color;\n"
+    "}";
+</code>
+
+Create the shaders, attach the source code that is just defined and compile
+the program object:
+
+<code c>
+static int
+init_shaders(GLData *gld)
+{
+   Evas_GL_API *gl = gld->glapi;
+
+   GLbyte vertex_shader[] =
+       "attribute vec4 a_position;\n"
+       "attribute vec4 a_color;\n"
+       "uniform mat4 u_mvp_mat;\n"
+       "varying vec4 v_color;\n"
+       "void main()\n"
+       "{\n"
+       "   gl_Position = u_mvp_mat*a_position;\n"
+       "   v_color = a_color;\n"
+       "}";
+   GLbyte fragment_shader[] =
+       "varying vec4 v_color;\n"
+       "void main()\n"
+       "{\n"
+       "   gl_FragColor = v_color;\n"
+       "}";
+
+   GLint compiled;
+   const char *p;
+
+   /*vertex_shader*/
+   p = vertex_shader;
+   gld->vtx_shader = gl->glCreateShader(GL_VERTEX_SHADER);
+   gl->glShaderSource(gld->vtx_shader, 1, &p, NULL); //get vertex_shader source
+   gl->glCompileShader(gld->vtx_shader); //compile
+   //get compile status
+   gl->glGetShaderiv(gld->vtx_shader, GL_COMPILE_STATUS, &compiled);
+   //if NULL: error
+   if (!compiled)
+     {
+        GLint info_len = 0;
+        gl->glGetShaderiv(gld->vtx_shader, GL_INFO_LOG_LENGTH, &info_len);
+        if (info_len > 1)
+          {
+             char* info_log = malloc(sizeof(char) * info_len);
+             gl->glGetShaderInfoLog(gld->vtx_shader, info_len, NULL, info_log);
+             printf("Error compiling shader:\n%s\n======\n%s\n======\n", 
info_log, p);
+             free(info_log);
+          }
+        gl->glDeleteShader(gld->vtx_shader);
+     }
+
+   /*fragment_shader*/
+   p = fragment_shader;
+   gld->fgmt_shader = gl->glCreateShader(GL_FRAGMENT_SHADER);
+   gl->glShaderSource(gld->fgmt_shader, 1, &p, NULL);
+   gl->glCompileShader(gld->fgmt_shader);
+   //get compile status
+   gl->glGetShaderiv(gld->fgmt_shader, GL_COMPILE_STATUS, &compiled);
+   //if NULL: error
+   if (!compiled)
+     {
+        GLint info_len = 0;
+        gl->glGetShaderiv(gld->fgmt_shader, GL_INFO_LOG_LENGTH, &info_len);
+        if (info_len > 1)
+          {
+             char* info_log = malloc(sizeof(char) * info_len);
+             gl->glGetShaderInfoLog(gld->fgmt_shader, info_len, NULL, 
info_log);
+             printf("Error compiling shader:\n%s\n======\n%s\n======\n", 
info_log, p);
+             free(info_log);
+          }
+        gl->glDeleteShader(gld->fgmt_shader);
+     }
+</code>
+
+Once the shaders are ready, instantiate the program object and link the
+shaders. If the linking succeeds, you can destroy the shaders afterwards
+(using ''glDeleteShader''). Since they are inside the program object, so it is
+pointless to keep them in memory.
+
+<code c>
+    gld->program = gl->glCreateProgram();
+
+    GLint linked;
+    // Load the vertex/fragment shaders
+    gl->glAttachShader(gld->program, gld->vtx_shader);
+    gl->glAttachShader(gld->program, gld->fgmt_shader);
+
+    gl->glDeleteShader(gld->vtx_shader);
+    gl->glDeleteShader(gld->fgmt_shader);
+
+    gl->glBindAttribLocation(gld->program, 0, "a_position");
+    gl->glLinkProgram(gld->program);
+    gl->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
+    if (!linked)
+      {
+         GLint info_len = 0;
+         gl->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &info_len);
+         if (info_len > 1)
+           {
+              char* info_log = malloc(sizeof(char) * info_len);
+              gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log);
+              printf("Error linking program:\n%s\n", info_log);
+              free(info_log);
+           }
+         gl->glDeleteProgram(gld->program);
+         return 0;
+      }
+</code>
+
+For shader process, create identifiers for the attribute variables used in the
+shader program. First create an identifier for the model-view-projection
+matrix, another one for the current vertex position, and a last one for the
+vertex color.
+
+<code c>
+    gld->mvpLoc     = gl->glGetUniformLocation(gld->program, "u_mvp_mat");
+    gld->positionLoc = gl->glGetAttribLocation(gld->program, "a_position");
+    gld->colorLoc   = gl->glGetAttribLocation(gld->program, "a_color");
+</code>
+
+Finally, generate the buffers for the vertex positions and colors.
+
+<code c>
+   gl->glGenBuffers(1, &gld->vertexID);
+   gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vertexID);
+   gl->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, 
GL_STATIC_DRAW);
+
+   gl->glGenBuffers(1, &gld->colorID);
+   gl->glBindBuffer(GL_ARRAY_BUFFER, gld->colorID);
+   gl->glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
+
+   gld->initialized = EINA_TRUE;
+</code>
+
+Allocate memory for the matrix and load a unit matrix into it. Then define the
+value that is used in order to build the perspective projection matrix. The
+''customFrustum()'' function is used for it. Multiply this resulting matrix
+with a resizing matrix, so the model is correctly adjusted to the screen.
+
+<code c>
+float aspect;
+
+elm_glview_size_get(obj, &w, &h);
+customLoadIdentity(gld->view);
+
+if (w > h)
+  {
+     aspect = (float) w / h;
+     customFrustum(gld->view, -1.0 * aspect, 1.0 * aspect, -1.0, 1.0, -1.0, 
1.0);
+  }
+else
+  {
+     aspect = (float) h / w;
+     customFrustum(gld->view, -1.0, 1.0, -1.0 * aspect, 1.0 * aspect, -1.0, 
1.0);
+  }
+</code>
+\\
+//**__next page__: **//[[/tutorial/gl2d/rendering_cube|Rendering the Cube]]
diff --git a/pages/tutorial/gl2d/effects.txt b/pages/tutorial/gl2d/effects.txt
new file mode 100644
index 0000000..b678615
--- /dev/null
+++ b/pages/tutorial/gl2d/effects.txt
@@ -0,0 +1,53 @@
+~~Title: Implementing Effects - GL 2D Tutorial~~
+//**__previous page__: **//[[/tutorial/gl2d/widget_interaction|Implementing 
Widget Interaction]]
+==== Implementing Effects ====
+
+Create a button that resets the scene by putting the background color to black
+and makes the cube bounce back to its original scale. Add the button to the
+GUI:
+
+<code c>
+Evas_Object *btn_reset;
+btn_reset = elm_button_add(inner_box);
+elm_object_text_set(btn_reset, "Reset");
+evas_object_smart_callback_add(btn_reset, "clicked", btn_reset_cb, gld);
+evas_object_size_hint_align_set(btn_reset, EVAS_HINT_FILL, 0);
+elm_box_pack_end(inner_box, btn_reset);
+evas_object_show(btn_reset);
+</code>
+
+Declare a callback that resets the variables that have influence on the
+drawing of the cube. In addition, animate the sliders when they get back to
+their original position using ''Ecore_Animator''.
+
+<code c>
+static Eina_Bool
+animate_reset_cb(void *data, double pos)
+{
+    GLData *gld = data;
+    double frame = pos;
+    float x, y, z;
+
+    frame = ecore_animator_pos_map(pos, ECORE_POS_MAP_BOUNCE, 1.8, 7);
+    x = gld->slx_value * (1 - frame) + 0.75 * frame;
+    y = gld->sly_value * (1 - frame) + 0.75 * frame;
+    z = gld->slz_value * (1 - frame) + 0.75 * frame;
+
+    elm_slider_value_set(gld->slx, x);
+    elm_slider_value_set(gld->sly, y);
+    elm_slider_value_set(gld->slz, z);
+
+    return EINA_TRUE;
+}
+
+static void btn_reset_cb(void *data, Evas_Object *obj,  void *event_info)
+{
+    GLData *gld = data;
+    gld->slx_value = elm_slider_value_get(gld->slx);
+    gld->sly_value = elm_slider_value_get(gld->sly);
+    gld->slz_value = elm_slider_value_get(gld->slz);
+    ecore_animator_timeline_add(1, animate_reset_cb, gld);
+}
+</code>
+\\
+//**__The whole code__: **//{{ code_c/tutorial/gl2d/gl_2d.c }}
diff --git a/pages/tutorial/gl2d/rendering_cube.txt 
b/pages/tutorial/gl2d/rendering_cube.txt
new file mode 100644
index 0000000..cdf0e6c
--- /dev/null
+++ b/pages/tutorial/gl2d/rendering_cube.txt
@@ -0,0 +1,55 @@
+~~Title: Rendering the Cube - GL 2D Tutorial~~
+//**__previous page__: **//[[/tutorial/gl2d/drawing_cube|Drawing the Cube with 
GLView]]
+==== Rendering the Cube ====
+
+The viewport is set at 0,0 corresponding to the bottom left edge of the
+window, and the height and width of the GL surface. Clear the depth and the
+color buffers to the values that were selected during initialization. Then
+call the ''glUseProgram()'' function in order to trigger the shader program.
+
+In ''draw_gl'' callback :
+
+<code c>
+gl->glViewport(0, 0, w, h);
+gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+gl->glUseProgram(gld->program);
+</code>
+
+Also bind the position and color identifiers to the buffers defined above.
+
+<code c>
+gl->glEnableVertexAttribArray(gld->positionLoc);
+gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vertexID);
+gl->glVertexAttribPointer(gld->positionLoc, 3, GL_FLOAT, GL_FALSE, 3 * 
sizeof(float), 0);
+
+gl->glEnableVertexAttribArray(gld->colorLoc);
+gl->glBindBuffer(GL_ARRAY_BUFFER, gld->colorID);
+gl->glVertexAttribPointer(gld->colorLoc, 4, GL_FLOAT, GL_FALSE, 4 * 
sizeof(float), 0);
+</code>
+
+After this, initialize and calculate the transformation matrix of the
+model-view matrix by calling the ''customRotate()'' function. This makes the 
cube
+view rotate a little for a better perspective. Once the model-view matrix is
+ready to display, multiply the projection matrix with the model-view matrix.
+
+<code c>
+customLoadIdentity(gld->model);
+customRotate(gld->model, gld->xangle, gld->yangle, gld->zangle);
+customMutlMatrix(gld->mvp, gld->view, gld->model);
+</code>
+
+Then load the model-view-projection matrix into the shader and call
+''glDrawArrays()'' to draw the model.
+
+<code c>
+gl->glUniformMatrix4fv(gld->mvpLoc, 1, GL_FALSE, gld->mvp);
+gl->glDrawArrays(GL_TRIANGLES, 0, 36);
+gl->glFlush();
+</code>
+
+You now are the proud owner of a nice cube!
+
+{{ :gl_cube.png?500 }}
+\\
+//**__next page__: **//[[/tutorial/gl2d/animating_cube|Animating the Cube]]
diff --git a/pages/tutorial/gl2d/widget_interaction.txt 
b/pages/tutorial/gl2d/widget_interaction.txt
new file mode 100644
index 0000000..fddeaa5
--- /dev/null
+++ b/pages/tutorial/gl2d/widget_interaction.txt
@@ -0,0 +1,74 @@
+~~Title: Widget Interaction - GL 2D Tutorial~~
+//**__previous page__: **//[[/tutorial/gl2d/animating_cube|Animating the Cube]]
+==== Implementing Widget Interaction ====
+
+Consider using widget to control some aspects of the rendering. For example,
+use some sliders to control the shape of the cube. Declare 3 sliders to play
+with the scaling coordinates of the cube.
+
+struct _GLData
+{
+    Evas_Object *slx;
+    Evas_Object *sly;
+    Evas_Object *slz;
+}
+
+When rendering the GUI, build and show the sliders. Those accept values in a
+range from 0.0 to 1.5 and control the scaling of each axis of the cube.
+
+<code c>
+// Slider for X-axis scale
+gld->slx = elm_slider_add(inner_box);
+evas_object_size_hint_align_set(gld->slx, EVAS_HINT_FILL, 0);
+elm_slider_horizontal_set(gld->slx, EINA_TRUE);
+elm_slider_unit_format_set(gld->slx, "%1.2f units");
+elm_slider_indicator_format_set(gld->slx, "%1.2f units");
+elm_slider_indicator_show_set(gld->slx, EINA_TRUE);
+elm_slider_min_max_set(gld->slx, 0, 1.5);
+elm_slider_value_set(gld->slx, 0.75);
+evas_object_color_set(gld->slx, 0.0, 0.0, 120, 255);
+elm_box_pack_end(inner_box, gld->slx);
+evas_object_show(gld->slx);
+
+// Slider for Y-axis scale
+gld->sly = elm_slider_add(inner_box);
+evas_object_size_hint_align_set(gld->sly, EVAS_HINT_FILL, 0);
+elm_slider_horizontal_set(gld->sly, EINA_TRUE);
+elm_slider_unit_format_set(gld->sly, "%1.2f units");
+elm_slider_indicator_format_set(gld->sly, "%1.2f units");
+elm_slider_indicator_show_set(gld->sly, EINA_TRUE);
+elm_slider_min_max_set(gld->sly, 0, 1.5);
+elm_slider_value_set(gld->sly, 0.75);
+evas_object_color_set(gld->sly, 0.0, 0.0, 120, 255);
+elm_box_pack_end(inner_box, gld->sly);
+evas_object_show(gld->sly);
+
+// Slider for Z-axis scale
+gld->slz = elm_slider_add(inner_box);
+evas_object_size_hint_align_set(gld->slz, EVAS_HINT_FILL, 0);
+elm_slider_horizontal_set(gld->slz, EINA_TRUE);
+elm_slider_unit_format_set(gld->slz, "%1.2f units");
+elm_slider_indicator_format_set(gld->slz, "%1.2f units");
+elm_slider_indicator_show_set(gld->slz, EINA_TRUE);
+elm_slider_min_max_set(gld->slz, 0, 1.5);
+elm_slider_value_set(gld->slz, 0.75);
+evas_object_color_set(gld->slz, 0.0, 0.0, 120, 255);
+elm_box_pack_end(inner_box, gld->slz);
+evas_object_show(gld->slz);
+</code>
+
+Then use the actual the values of sliders and pass them to the scaling 
function in
+the rendering loop, ''_draw_gl'':
+
+<code c>
+double scalex = elm_slider_value_get(gld->slx);
+double scaley = elm_slider_value_get(gld->sly);
+double scalez = elm_slider_value_get(gld->slz);
+
+customLoadIdentity(gld->model);
+customRotate(gld->model, gld->xangle, gld->yangle, gld->zangle++);
+customScale(gld->model, scalex, scaley, scalez);
+customMutlMatrix(gld->mvp, gld->view, gld->model);
+</code>
+\\
+//**__next page__: **//[[/tutorial/gl2d/effects|Implementing Effects]]
diff --git a/pages/tutorial/gl_2d_tutorial.txt 
b/pages/tutorial/gl_2d_tutorial.txt
new file mode 100644
index 0000000..86ee99c
--- /dev/null
+++ b/pages/tutorial/gl_2d_tutorial.txt
@@ -0,0 +1,19 @@
+~~Title: GL 2D Tutorial~~
+==== GL 2D Tutorial ====
+
+This tutorial demonstrates how you can handle OpenGL ES graphics with the
+GLView widget and EvasGL.
+
+=== Table of Contents ===
+
+  * [[/tutorial/gl2d/basic_application|Creating the Basic Application]]
+  * [[/tutorial/gl2d/creating_cube|Creating the Cube]]
+  * [[/tutorial/gl2d/drawing_cube|Drawing the Cube with GLView]]
+  * [[/tutorial/gl2d/rendering_cube|Rendering the Cube]]
+  * [[/tutorial/gl2d/animating_cube|Animating the Cube]]
+  * [[/tutorial/gl2d/widget_interaction|Implementing Widget Interaction]]
+  * [[/tutorial/gl2d/effects|Implementing Effects]]
+
+Gl 2D example: {{ :gl_cube_example.png?600 }}
+
+//**__The whole code__: **//{{ code_c/tutorial/gl2d/gl_2d.c }}

-- 


Reply via email to