1af86d3046b03275cfe9793daf015bfaaf89f283
[framework/uifw/elementary.git] / src / lib / elm_glview.h
1 /**
2  * @defgroup GLView GLView
3  *
4 <<<<<<< HEAD
5  * A simple GLView widget that allows GL rendering.
6  *
7  * Signals that you can add callbacks for are:
8  *
9 =======
10  * A GLView widget allows for simple GL rendering in elementary environment.
11  * GLView hides all the complicated evas_gl details so that the user only
12  * has to deal with registering a few callback functions for rendering
13  * to a surface using OpenGL APIs.
14  *
15  * Below is an illustrative example of how to use GLView and and OpenGL
16  * to render in elementary environment.
17  * @code
18 // Simple GLView example
19 #include <Elementary.h>
20 #include <Evas_GL.h>
21 #include <stdio.h>
22
23 typedef struct _GLData GLData;
24
25 // GL related data here..
26 struct _GLData
27 {
28    Evas_GL_API *glapi;
29    GLuint       program;
30    GLuint       vtx_shader;
31    GLuint       fgmt_shader;
32    GLuint       vbo;
33    int          initialized : 1;
34 };
35
36
37 static float red = 1.0;
38
39 //--------------------------------//
40 // a helper function to load shaders from a shader source
41 static GLuint
42 load_shader( GLData *gld, GLenum type, const char *shader_src )
43 {
44    Evas_GL_API *gl = gld->glapi;
45    GLuint shader;
46    GLint compiled;
47
48    // Create the shader object
49    shader = gl->glCreateShader(type);
50    if (shader==0)
51       return 0;
52
53    // Load/Compile shader source
54    gl->glShaderSource(shader, 1, &shader_src, NULL);
55    gl->glCompileShader(shader);
56    gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
57
58    if (!compiled)
59      {
60         GLint info_len = 0;
61         gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
62         if (info_len > 1)
63           {
64              char* info_log = malloc(sizeof(char) * info_len);
65
66              gl->glGetShaderInfoLog(shader, info_len, NULL, info_log);
67              printf("Error compiling shader:\n%s\n======\n%s\n======\n", info_log, shader_src );
68              free(info_log);
69           }
70         gl->glDeleteShader(shader);
71         return 0;
72      }
73
74    return shader;
75 }
76
77 // Initialize the shader and program object
78 static int
79 init_shaders(GLData *gld)
80 {
81    Evas_GL_API *gl = gld->glapi;
82    GLbyte vShaderStr[] =
83       "attribute vec4 vPosition;    \n"
84       "void main()                  \n"
85       "{                            \n"
86       "   gl_Position = vPosition;  \n"
87       "}                            \n";
88
89    GLbyte fShaderStr[] =
90       "#ifdef GL_ES                                 \n"
91       "precision mediump float;                     \n"
92       "#endif                                       \n"
93       "void main()                                  \n"
94       "{                                            \n"
95       "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
96       "}                                            \n";
97
98    GLint linked;
99
100    // Load the vertex/fragment shaders
101    gld->vtx_shader  = load_shader(gld, GL_VERTEX_SHADER, (const char*)vShaderStr);
102    gld->fgmt_shader = load_shader(gld, GL_FRAGMENT_SHADER, (const char*)fShaderStr);
103
104    // Create the program object
105    gld->program = gl->glCreateProgram( );
106    if (gld->program==0)
107       return 0;
108
109    gl->glAttachShader(gld->program, gld->vtx_shader);
110    gl->glAttachShader(gld->program, gld->fgmt_shader);
111
112    gl->glBindAttribLocation(gld->program, 0, "vPosition");
113    gl->glLinkProgram(gld->program);
114    gl->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
115
116    if (!linked)
117      {
118         GLint info_len = 0;
119         gl->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &info_len);
120         if (info_len > 1)
121           {
122              char* info_log = malloc(sizeof(char) * info_len);
123
124              gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log);
125              printf("Error linking program:\n%s\n", info_log);
126              free(info_log);
127           }
128         gl->glDeleteProgram(gld->program);
129         return 0;
130      }
131    return 1;
132 }
133
134
135
136 // Callbacks
137 // intialize callback that gets called once for intialization
138 static void
139 _init_gl(Evas_Object *obj)
140 {
141    GLData *gld = evas_object_data_get(obj, "gld");
142    Evas_GL_API *gl = gld->glapi;
143    GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
144                            -0.5f, -0.5f, 0.0f,
145                             0.5f, -0.5f, 0.0f };
146
147    if (!init_shaders(gld))
148      {
149         printf("Error Initializing Shaders\n");
150         return;
151      }
152
153    gl->glGenBuffers(1, &gld->vbo);
154    gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
155    gl->glBufferData(GL_ARRAY_BUFFER, 3 * 3 * 4, vVertices, GL_STATIC_DRAW);
156 }
157
158 // delete callback gets called when glview is deleted
159 static void
160 _del_gl(Evas_Object *obj)
161 {
162    GLData *gld = evas_object_data_get(obj, "gld");
163    if (!gld)
164      {
165         printf("Unable to get GLData. \n");
166         return;
167      }
168    Evas_GL_API *gl = gld->glapi;
169
170    gl->glDeleteShader(gld->vtx_shader);
171    gl->glDeleteShader(gld->fgmt_shader);
172    gl->glDeleteProgram(gld->program);
173    gl->glDeleteBuffers(1, &gld->vbo);
174
175    evas_object_data_del((Evas_Object*)obj, "..gld");
176    free(gld);
177 }
178
179 // resize callback gets called every time object is resized
180 static void
181 _resize_gl(Evas_Object *obj)
182 {
183    int w, h;
184    GLData *gld = evas_object_data_get(obj, "gld");
185    Evas_GL_API *gl = gld->glapi;
186
187    elm_glview_size_get(obj, &w, &h);
188
189    // GL Viewport stuff. you can avoid doing this if viewport is all the
190    // same as last frame if you want
191    gl->glViewport(0, 0, w, h);
192 }
193
194
195 // draw callback is where all the main GL rendering happens
196 static void
197 _draw_gl(Evas_Object *obj)
198 {
199    Evas_GL_API *gl = elm_glview_gl_api_get(obj);
200    GLData *gld = evas_object_data_get(obj, "gld");
201    if (!gld) return;
202    int w, h;
203
204    elm_glview_size_get(obj, &w, &h);
205
206    gl->glViewport(0, 0, w, h);
207    gl->glClearColor(red,0.8,0.3,1);
208    gl->glClear(GL_COLOR_BUFFER_BIT);
209
210    // Draw a Triangle
211    gl->glEnable(GL_BLEND);
212
213    gl->glUseProgram(gld->program);
214
215    gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
216    gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
217                              0, 0);
218    gl->glEnableVertexAttribArray(0);
219
220    gl->glDrawArrays(GL_TRIANGLES, 0, 3);
221
222    // Optional - Flush the GL pipeline
223    gl->glFinish();
224
225    red -= 0.1;
226    if (red < 0.0) red = 1.0;
227 }
228
229 // just need to notify that glview has changed so it can render
230 static Eina_Bool
231 _anim(void *data)
232 {
233    elm_glview_changed_set(data);
234    return EINA_TRUE;
235 }
236
237 static void
238 _on_done(void *data, Evas_Object *obj, void *event_info)
239 {
240    evas_object_del((Evas_Object*)data);
241    elm_exit();
242 }
243
244 static void
245 _del(void *data, Evas *evas, Evas_Object *obj, void *event_info)
246 {
247    Ecore_Animator *ani = evas_object_data_get(obj, "ani");
248    ecore_animator_del(ani);
249 }
250
251
252 EAPI int
253 elm_main(int argc, char **argv)
254 {
255    Evas_Object *win, *bg, *bx, *bt, *gl;
256    Ecore_Animator *ani;
257    GLData *gld = NULL;
258
259    if (!(gld = calloc(1, sizeof(GLData)))) return 1;
260
261    // set the engine to opengl_x11
262    // if commented out, ELM will choose one
263    elm_engine_set("opengl_x11");
264
265    win = elm_win_add(NULL, "glview simple", ELM_WIN_BASIC);
266    elm_win_title_set(win, "GLView Simple");
267    elm_win_autodel_set(win, EINA_TRUE);
268
269    bg = elm_bg_add(win);
270    elm_win_resize_object_add(win, bg);
271    evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
272    evas_object_show(bg);
273
274    bx = elm_box_add(win);
275    evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
276    elm_win_resize_object_add(win, bx);
277    evas_object_show(bx);
278
279    //-//-//-// THIS IS WHERE GL INIT STUFF HAPPENS (ALA EGL)
280    //-//   
281    // create a new glview object
282    gl = elm_glview_add(win);
283    gld->glapi = elm_glview_gl_api_get(gl);
284    evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
285    evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
286    // mode is simply for supporting alpha, depth buffering, and stencil
287    // buffering.
288    elm_glview_mode_set(gl, ELM_GLVIEW_ALPHA | ELM_GLVIEW_DEPTH);
289    // resize policy tells glview what to do with the surface when it
290    // resizes.  ELM_GLVIEW_RESIZE_POLICY_RECREATE will tell it to 
291    // destroy the current surface and recreate it to the new size
292    elm_glview_resize_policy_set(gl, ELM_GLVIEW_RESIZE_POLICY_RECREATE);
293    // render policy tells glview how it would like glview to render
294    // gl code. ELM_GLVIEW_RENDER_POLICY_ON_DEMAND will have the gl
295    // calls called in the pixel_get callback, which only gets called 
296    // if the object is visible, hence ON_DEMAND.  ALWAYS mode renders
297    // it despite the visibility of the object.
298    elm_glview_render_policy_set(gl, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND);
299    // initialize callback function gets registered here
300    elm_glview_init_func_set(gl, _init_gl);
301    // delete callback function gets registered here
302    elm_glview_del_func_set(gl, _del_gl);
303    elm_glview_resize_func_set(gl, _resize_gggl);
304    elm_glview_render_func_set(gl, _draw_gl);
305    //-//
306    //-//-//-// END GL INIT BLOB  
307    
308    elm_box_pack_end(bx, gl);
309    evas_object_show(gl);
310
311    elm_object_focus_set(gl, EINA_TRUE);
312
313    // animating - just a demo. as long as you trigger an update on the image
314    // object via elm_glview_changed_set() it will be updated.
315    //
316    // NOTE: if you delete gl, this animator will keep running trying to access
317    // gl so you'd better delete this animator with ecore_animator_del().
318    ani = ecore_animator_add(_anim, gl);
319
320    evas_object_data_set(gl, "ani", ani);
321    evas_object_data_set(gl, "gld", gld);
322    evas_object_event_callback_add(gl, EVAS_CALLBACK_DEL, _del, gl);
323
324    // add an 'OK' button to end the program
325    bt = elm_button_add(win);
326    elm_object_text_set(bt, "OK");
327    evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
328    evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
329    elm_box_pack_end(bx, bt);
330    evas_object_show(bt);
331    evas_object_smart_callback_add(bt, "clicked", _on_done, win);
332
333    evas_object_resize(win, 320, 480);
334    evas_object_show(win);
335
336    // run the mainloop and process events and callbacks
337    elm_run();
338    return 0;
339 }
340 ELM_MAIN()
341  * @endcode
342  */
343
344
345
346 /**
347  * @addtogroup GLView
348 >>>>>>> remotes/origin/upstream
349  * @{
350  */
351
352 typedef void (*Elm_GLView_Func_Cb)(Evas_Object *obj);
353
354 typedef enum _Elm_GLView_Mode
355 {
356 <<<<<<< HEAD
357    ELM_GLVIEW_NONE    = 0,
358    ELM_GLVIEW_ALPHA   = (1<<1),
359    ELM_GLVIEW_DEPTH   = (1<<2),
360    ELM_GLVIEW_STENCIL = (1<<3),
361    ELM_GLVIEW_DIRECT  = (1<<4)
362 } Elm_GLView_Mode;
363
364 /**
365  * Defines a policy for the glview resizing.
366 =======
367    ELM_GLVIEW_NONE    = 0,       
368    ELM_GLVIEW_ALPHA   = (1<<1), /**< Alpha channel enabled rendering mode */
369    ELM_GLVIEW_DEPTH   = (1<<2), /**< Depth buffer enabled rendering mode */
370    ELM_GLVIEW_STENCIL = (1<<3), /**< Stencil buffer enabled rendering mode */
371    ELM_GLVIEW_DIRECT  = (1<<4)  /**< Direct rendering optimization hint */
372 } Elm_GLView_Mode;
373
374 /**
375  * Defines a policy for the glview resizing. 
376  *
377  * The resizing policy tells glview what to do with the underlying
378  * surface when resize happens. ELM_GLVIEW_RESIZE_POLICY_RECREATE
379  * will destroy the current surface and recreate the surface to the
380  * new size.  ELM_GLVIEW_RESIZE_POLICY_SCALE will instead keep the
381  * current surface but only display the result at the desired size
382  * scaled.
383 >>>>>>> remotes/origin/upstream
384  *
385  * @note Default is ELM_GLVIEW_RESIZE_POLICY_RECREATE
386  */
387 typedef enum
388 {
389    ELM_GLVIEW_RESIZE_POLICY_RECREATE = 1, /**< Resize the internal surface along with the image */
390 <<<<<<< HEAD
391    ELM_GLVIEW_RESIZE_POLICY_SCALE = 2 /**< Only reize the internal image and not the surface */
392 } Elm_GLView_Resize_Policy;
393
394 typedef enum
395 {
396    ELM_GLVIEW_RENDER_POLICY_ON_DEMAND = 1, /**< Render only when there is a need for redrawing */
397    ELM_GLVIEW_RENDER_POLICY_ALWAYS = 2 /**< Render always even when it is not visible */
398 =======
399    ELM_GLVIEW_RESIZE_POLICY_SCALE    = 2  /**< Only resize the internal image and not the surface */
400 } Elm_GLView_Resize_Policy;
401
402 /**
403  * Defines a policy for gl rendering. 
404  *
405  * The rendering policy tells glview where to run the gl rendering code.
406  * ELM_GLVIEW_RENDER_POLICY_ON_DEMAND tells glview to call the rendering
407  * calls on demand, which means that the rendering code gets called
408  * only when it is visible. 
409  *
410  * @note Default is ELM_GLVIEW_RENDER_POLICY_ON_DEMAND
411  */
412 typedef enum
413 {
414    ELM_GLVIEW_RENDER_POLICY_ON_DEMAND = 1, /**< Render only when there is a need for redrawing */
415    ELM_GLVIEW_RENDER_POLICY_ALWAYS    = 2  /**< Render always even when it is not visible */
416 >>>>>>> remotes/origin/upstream
417 } Elm_GLView_Render_Policy;
418
419 /**
420  * Add a new glview to the parent
421  *
422  * @param parent The parent object
423  * @return The new object or NULL if it cannot be created
424  *
425  * @ingroup GLView
426  */
427 EAPI Evas_Object *elm_glview_add(Evas_Object *parent);
428
429 /**
430  * Sets the size of the glview
431  *
432  * @param obj The glview object
433 <<<<<<< HEAD
434  * @param width width of the glview object
435  * @param height height of the glview object
436  *
437  * @ingroup GLView
438  */
439 EAPI void         elm_glview_size_set(Evas_Object *obj, Evas_Coord width, Evas_Coord height);
440 =======
441  * @param w width of the glview object
442  * @param h height of the glview object
443  *
444  * @ingroup GLView
445  */
446 EAPI void         elm_glview_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
447 >>>>>>> remotes/origin/upstream
448
449 /**
450  * Gets the size of the glview.
451  *
452  * @param obj The glview object
453 <<<<<<< HEAD
454  * @param width width of the glview object
455  * @param height height of the glview object
456 =======
457  * @param w width of the glview object
458  * @param h height of the glview object
459 >>>>>>> remotes/origin/upstream
460  *
461  * Note that this function returns the actual image size of the
462  * glview.  This means that when the scale policy is set to
463  * ELM_GLVIEW_RESIZE_POLICY_SCALE, it'll return the non-scaled
464  * size.
465  *
466  * @ingroup GLView
467  */
468 <<<<<<< HEAD
469 EAPI void         elm_glview_size_get(const Evas_Object *obj, Evas_Coord *width, Evas_Coord *height);
470 =======
471 EAPI void         elm_glview_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
472 >>>>>>> remotes/origin/upstream
473
474 /**
475  * Gets the gl api struct for gl rendering
476  *
477  * @param obj The glview object
478  * @return The api object or NULL if it cannot be created
479  *
480  * @ingroup GLView
481  */
482 EAPI Evas_GL_API *elm_glview_gl_api_get(const Evas_Object *obj);
483
484 /**
485 <<<<<<< HEAD
486  * Set the mode of the GLView. Supports Three simple modes.
487  *
488  * @param obj The glview object
489  * @param mode The mode Options OR'ed enabling Alpha, Depth, Stencil.
490  * @return True if set properly.
491  *
492 =======
493  * Set the mode of the GLView. Supports alpha, depth, stencil.
494  *
495  * @param obj The glview object
496  * @param mode The mode Options OR'ed enabling Alpha, Depth, Stencil, Direct.
497  * @return True if set properly.
498  *
499  * Direct is a hint for the elm_glview to render directly to the window
500  * given that the right conditions are met. Otherwise it falls back
501  * to rendering to an offscreen buffer before it gets composited to the 
502  * window.
503  *
504 >>>>>>> remotes/origin/upstream
505  * @ingroup GLView
506  */
507 EAPI Eina_Bool    elm_glview_mode_set(Evas_Object *obj, Elm_GLView_Mode mode);
508
509 /**
510  * Set the resize policy for the glview object.
511  *
512  * @param obj The glview object.
513  * @param policy The scaling policy.
514  *
515 <<<<<<< HEAD
516  * By default, the resize policy is set to
517  * ELM_GLVIEW_RESIZE_POLICY_RECREATE.  When resize is called it
518  * destroys the previous surface and recreates the newly specified
519  * size. If the policy is set to ELM_GLVIEW_RESIZE_POLICY_SCALE,
520  * however, glview only scales the image object and not the underlying
521  * GL Surface.
522 =======
523  * By default, the resize policy is set to ELM_GLVIEW_RESIZE_POLICY_RECREATE.  
524  * When resize is called it destroys the previous surface and recreates the 
525  * newly specified size. If the policy is set to 
526  * ELM_GLVIEW_RESIZE_POLICY_SCALE, however, glview only scales the image 
527  * object and not the underlying GL Surface.
528 >>>>>>> remotes/origin/upstream
529  *
530  * @ingroup GLView
531  */
532 EAPI Eina_Bool    elm_glview_resize_policy_set(Evas_Object *obj, Elm_GLView_Resize_Policy policy);
533
534 /**
535  * Set the render policy for the glview object.
536  *
537  * @param obj The glview object.
538  * @param policy The render policy.
539  *
540 <<<<<<< HEAD
541  * By default, the render policy is set to
542  * ELM_GLVIEW_RENDER_POLICY_ON_DEMAND.  This policy is set such
543  * that during the render loop, glview is only redrawn if it needs
544  * to be redrawn. (i.e. When it is visible) If the policy is set to
545  * ELM_GLVIEWW_RENDER_POLICY_ALWAYS, it redraws regardless of
546  * whether it is visible/need redrawing or not.
547 =======
548  * By default, the render policy is set to ELM_GLVIEW_RENDER_POLICY_ON_DEMAND.
549  * This policy is set such that during the render loop, glview is only 
550  * redrawn if it needs to be redrawn. (i.e. when it is visible) If the policy
551  * is set to ELM_GLVIEWW_RENDER_POLICY_ALWAYS, it redraws regardless of
552  * whether it is visible or needs redrawing.
553 >>>>>>> remotes/origin/upstream
554  *
555  * @ingroup GLView
556  */
557 EAPI Eina_Bool    elm_glview_render_policy_set(Evas_Object *obj, Elm_GLView_Render_Policy policy);
558
559 /**
560  * Set the init function that runs once in the main loop.
561  *
562  * @param obj The glview object.
563  * @param func The init function to be registered.
564  *
565 <<<<<<< HEAD
566  * The registered init function gets called once during the render loop.
567 =======
568  * The registered init function gets called once during the render loop. 
569  * This function allows glview to hide all the rendering context/surface
570  * details and have the user just call GL calls that they desire
571  * for initialization GL calls.
572 >>>>>>> remotes/origin/upstream
573  *
574  * @ingroup GLView
575  */
576 EAPI void         elm_glview_init_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
577
578 /**
579  * Set the render function that runs in the main loop.
580  *
581  * @param obj The glview object.
582  * @param func The delete function to be registered.
583  *
584  * The registered del function gets called when GLView object is deleted.
585 <<<<<<< HEAD
586 =======
587  * This function allows glview to hide all the rendering context/surface
588  * details and have the user just call GL calls that they desire
589  * when delete happens.
590 >>>>>>> remotes/origin/upstream
591  *
592  * @ingroup GLView
593  */
594 EAPI void         elm_glview_del_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
595
596 /**
597  * Set the resize function that gets called when resize happens.
598  *
599  * @param obj The glview object.
600  * @param func The resize function to be registered.
601  *
602 <<<<<<< HEAD
603 =======
604  * The resize function gets called during the render loop. 
605  * This function allows glview to hide all the rendering context/surface
606  * details and have the user just call GL calls that they desire
607  * when resize happens.
608  *
609 >>>>>>> remotes/origin/upstream
610  * @ingroup GLView
611  */
612 EAPI void         elm_glview_resize_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
613
614 /**
615  * Set the render function that runs in the main loop.
616  *
617 <<<<<<< HEAD
618 =======
619  * The render function gets called in the main loop but whether it runs
620  * depends on the rendering policy and whether elm_glview_changed_set() 
621  * gets called.
622  * 
623 >>>>>>> remotes/origin/upstream
624  * @param obj The glview object.
625  * @param func The render function to be registered.
626  *
627  * @ingroup GLView
628  */
629 EAPI void         elm_glview_render_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
630
631 /**
632  * Notifies that there has been changes in the GLView.
633  *
634  * @param obj The glview object.
635  *
636  * @ingroup GLView
637  */
638 EAPI void         elm_glview_changed_set(Evas_Object *obj);
639
640 /**
641  * @}
642  */