Merge "custom eail widget implementation" into tizen
[platform/core/uifw/eail.git] / tests / eail_glview_tc1.c
1 /*
2  * Tested interface: AtkObject
3  *
4  * Tested AtkObject: EailGlview
5  *
6  * Description: Test AtkObject interface
7  *
8  * Test input: accessible object representing EailGlview
9  *
10  * Expected test result: test should return 0 (success)
11  */
12
13 #include <Elementary.h>
14 #include <atk/atk.h>
15
16 #define DEBUG 1
17
18 #include "eail_test_utils.h"
19
20 INIT_TEST("EailGlview")
21
22 typedef struct _GLData GLData;
23
24 // GL related data here..
25 struct _GLData
26 {
27    Evas_GL_API *glapi;
28    GLuint       program;
29    GLuint       vtx_shader;
30    GLuint       fgmt_shader;
31    GLuint       vbo;
32    int          initialized : 1;
33 };
34
35 static float red = 1.0;
36
37 // a helper function to load shaders from a shader source
38 static GLuint
39 load_shader(GLData *gld, GLenum type, const char *shader_src)
40 {
41    Evas_GL_API *gl = gld->glapi;
42    GLuint shader;
43    GLint compiled;
44
45    // Create the shader object
46    shader = gl->glCreateShader(type);
47    if (0 == shader)
48      return 0;
49
50    // Load/Compile shader source
51    gl->glShaderSource(shader, 1, &shader_src, NULL);
52    gl->glCompileShader(shader);
53    gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
54
55    if (!compiled)
56      {
57         GLint info_len = 0;
58         gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
59         if (1 < info_len)
60           {
61              char* info_log = malloc(sizeof(char) * info_len);
62
63              gl->glGetShaderInfoLog(shader, info_len, NULL, info_log);
64              _printf("Error compiling shader:\n%s\n======\n%s\n======\n", info_log, shader_src);
65              free(info_log);
66              g_assert(FALSE);
67           }
68         gl->glDeleteShader(shader);
69         return 0;
70      }
71
72    return shader;
73 }
74
75 // Initialize the shader and program object
76 static int
77 init_shaders(GLData *gld)
78 {
79    Evas_GL_API *gl = gld->glapi;
80    GLbyte vShaderStr[] =
81       "attribute vec4 vPosition;    \n"
82       "void main()                  \n"
83       "{                            \n"
84       "   gl_Position = vPosition;  \n"
85       "}                            \n";
86
87    GLbyte fShaderStr[] =
88       "#ifdef GL_ES                                 \n"
89       "precision mediump float;                     \n"
90       "#endif                                       \n"
91       "void main()                                  \n"
92       "{                                            \n"
93       "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
94       "}                                            \n";
95
96    GLint linked;
97
98    // Load the vertex/fragment shaders
99    gld->vtx_shader  = load_shader(gld, GL_VERTEX_SHADER, (const char*)vShaderStr);
100    gld->fgmt_shader = load_shader(gld, GL_FRAGMENT_SHADER, (const char*)fShaderStr);
101
102    // Create the program object
103    gld->program = gl->glCreateProgram( );
104    if (0 == gld->program)
105      return 0;
106
107    gl->glAttachShader(gld->program, gld->vtx_shader);
108    gl->glAttachShader(gld->program, gld->fgmt_shader);
109
110    gl->glBindAttribLocation(gld->program, 0, "vPosition");
111    gl->glLinkProgram(gld->program);
112    gl->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
113
114    if (!linked)
115      {
116         GLint info_len = 0;
117         gl->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &info_len);
118         if (1 < info_len)
119           {
120              char* info_log = malloc(sizeof(char) * info_len);
121
122              gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log);
123              _printf("Error linking program:\n%s\n", info_log);
124              free(info_log);
125              g_assert(FALSE);
126           }
127         gl->glDeleteProgram(gld->program);
128         return 0;
129      }
130    return 1;
131 }
132
133 // intialize callback that gets called once for intialization
134 static void
135 _init_gl(Evas_Object *obj)
136 {
137    GLData *gld = evas_object_data_get(obj, "gld");
138    Evas_GL_API *gl = gld->glapi;
139    GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
140                           -0.5f, -0.5f, 0.0f,
141                            0.5f, -0.5f, 0.0f };
142
143    if (!init_shaders(gld))
144      {
145         _printf("Error Initializing Shaders\n");
146         g_assert(FALSE);
147      }
148
149    gl->glGenBuffers(1, &gld->vbo);
150    gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
151    gl->glBufferData(GL_ARRAY_BUFFER, 3 * 3 * 4, vVertices, GL_STATIC_DRAW);
152 }
153
154 // delete callback gets called when glview is deleted
155 static void
156 _del_gl(Evas_Object *obj)
157 {
158    GLData *gld = evas_object_data_get(obj, "gld");
159    if (!gld)
160      {
161         printf("Unable to get GLData. \n");
162         g_assert(FALSE);
163      }
164    Evas_GL_API *gl = gld->glapi;
165
166    gl->glDeleteShader(gld->vtx_shader);
167    gl->glDeleteShader(gld->fgmt_shader);
168    gl->glDeleteProgram(gld->program);
169    gl->glDeleteBuffers(1, &gld->vbo);
170
171    evas_object_data_del((Evas_Object*)obj, "..gld");
172    free(gld);
173 }
174
175 // resize callback gets called every time object is resized
176 static void
177 _resize_gl(Evas_Object *obj)
178 {
179    int w, h;
180    GLData *gld = evas_object_data_get(obj, "gld");
181    Evas_GL_API *gl = gld->glapi;
182
183    elm_glview_size_get(obj, &w, &h);
184
185    // GL Viewport stuff. you can avoid doing this if viewport is all the
186    // same as last frame if you want
187    gl->glViewport(0, 0, w, h);
188 }
189
190
191 // draw callback is where all the main GL rendering happens
192 static void
193 _draw_gl(Evas_Object *obj)
194 {
195    Evas_GL_API *gl = elm_glview_gl_api_get(obj);
196    GLData *gld = evas_object_data_get(obj, "gld");
197
198    if (!gld) return;
199    int w, h;
200
201    elm_glview_size_get(obj, &w, &h);
202
203    gl->glViewport(0, 0, w, h);
204    gl->glClearColor(red, 0.8, 0.3, 1);
205    gl->glClear(GL_COLOR_BUFFER_BIT);
206
207    // Draw a Triangle
208    gl->glEnable(GL_BLEND);
209
210    gl->glUseProgram(gld->program);
211
212    gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
213    gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
214    gl->glEnableVertexAttribArray(0);
215
216    gl->glDrawArrays(GL_TRIANGLES, 0, 3);
217
218    // Optional - Flush the GL pipeline
219    gl->glFinish();
220
221    red -= 0.1;
222    if (0.0 > red) red = 1.0;
223 }
224
225 // just need to notify that glview has changed so it can render
226 static Eina_Bool
227 _anim(void *data)
228 {
229    elm_glview_changed_set(data);
230    return EINA_TRUE;
231 }
232
233 static void
234 _del(void *data, Evas *evas, Evas_Object *obj, void *event_info)
235 {
236    Ecore_Animator *ani = evas_object_data_get(obj, "ani");
237    ecore_animator_del(ani);
238 }
239
240 static void
241 _init_glview(Evas_Object *win, GLData *gld)
242 {
243    Evas_Object *bg, *bx, *bt, *gl;
244    Ecore_Animator *ani;
245
246    bg = elm_bg_add(win);
247    elm_win_resize_object_add(win, bg);
248    evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
249    evas_object_show(bg);
250
251    bx = elm_box_add(win);
252    evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
253    elm_win_resize_object_add(win, bx);
254    evas_object_show(bx);
255
256    //-//-//-// THIS IS WHERE GL INIT STUFF HAPPENS (ALA EGL)
257    //-//
258    // create a new glview object
259    gl = elm_glview_add(win);
260    gld->glapi = elm_glview_gl_api_get(gl);
261    evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
262    evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
263    // mode is simply for supporting alpha, depth buffering, and stencil
264    // buffering.
265    elm_glview_mode_set(gl, ELM_GLVIEW_ALPHA | ELM_GLVIEW_DEPTH);
266    // resize policy tells glview what to do with the surface when it
267    // resizes.  ELM_GLVIEW_RESIZE_POLICY_RECREATE will tell it to
268    // destroy the current surface and recreate it to the new size
269    elm_glview_resize_policy_set(gl, ELM_GLVIEW_RESIZE_POLICY_RECREATE);
270    // render policy tells glview how it would like glview to render
271    // gl code. ELM_GLVIEW_RENDER_POLICY_ON_DEMAND will have the gl
272    // calls called in the pixel_get callback, which only gets called
273    // if the object is visible, hence ON_DEMAND.  ALWAYS mode renders
274    // it despite the visibility of the object.
275    elm_glview_render_policy_set(gl, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND);
276    // initialize callback function gets registered here
277    elm_glview_init_func_set(gl, _init_gl);
278    // delete callback function gets registered here
279    elm_glview_del_func_set(gl, _del_gl);
280    elm_glview_resize_func_set(gl, _resize_gl);
281    elm_glview_render_func_set(gl, _draw_gl);
282    //-//
283    //-//-//-// END GL INIT BLOB
284
285    elm_box_pack_end(bx, gl);
286    evas_object_show(gl);
287
288    elm_object_focus_set(gl, EINA_TRUE);
289
290    // animating - just a demo. as long as you trigger an update on the image
291    // object via elm_glview_changed_set() it will be updated.
292    //
293    // NOTE: if you delete gl, this animator will keep running trying to access
294    // gl so you'd better delete this animator with ecore_animator_del().
295    ani = ecore_animator_add(_anim, gl);
296
297    evas_object_data_set(gl, "ani", ani);
298    evas_object_data_set(gl, "gld", gld);
299    evas_object_event_callback_add(gl, EVAS_CALLBACK_DEL, _del, gl);
300
301    // add an 'OK' button to end the program
302    bt = elm_button_add(win);
303    elm_object_text_set(bt, "OK");
304    evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
305    evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
306    elm_box_pack_end(bx, bt);
307    evas_object_show(bt);
308    evas_object_smart_callback_add(bt, "clicked", _on_done, win);
309
310    evas_object_resize(win, 320, 480);
311 }
312
313 static void
314 _do_test(AtkObject *obj)
315 {
316    g_assert(ATK_IS_OBJECT(obj));
317    g_assert(atk_object_get_role(obj) == ATK_ROLE_ANIMATION);
318    atk_object_set_description(obj, "test");
319    g_assert_cmpstr(atk_object_get_description(obj), ==, "test");
320
321    atk_object_set_name(obj, "test name");
322    g_assert_cmpstr(atk_object_get_name(obj), ==, "test name");
323
324    eailu_test_code_called = 1;
325 }
326
327 EAPI_MAIN int
328 elm_main(int argc, char **argv)
329 {
330    Evas_Object *win = NULL;
331    GLData *gld = calloc(1, sizeof(GLData));
332
333    g_assert(gld);
334
335    // set the preferred engine to opengl_x11. if it isnt' available it
336    // may use another transparently
337    elm_config_preferred_engine_set("opengl_x11");
338
339    win = (Evas_Object *)eailu_create_test_window_with_glib_init(_on_done, _on_focus_in);
340    g_assert(win);
341    _init_glview(win, gld);
342    evas_object_show(win);
343    elm_run();
344    elm_shutdown();
345
346    return 0;
347 }
348 ELM_MAIN()