2 * Simple Elementary's <b>GLView widget</b> example, illustrating its
5 * See stdout/stderr for output. Compile with:
8 * gcc -o glview_example_01 glview_example_01.c -g `pkg-config --cflags --libs elementary`
11 #include <Elementary.h>
15 typedef struct _GLData GLData;
17 // GL related data here..
28 static float red = 1.0;
30 //--------------------------------//
31 // a helper function to load shaders from a shader source
33 load_shader( GLData *gld, GLenum type, const char *shader_src )
35 Evas_GL_API *gl = gld->glapi;
39 // Create the shader object
40 shader = gl->glCreateShader(type);
44 // Load/Compile shader source
45 gl->glShaderSource(shader, 1, &shader_src, NULL);
46 gl->glCompileShader(shader);
47 gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
52 gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
55 char* info_log = malloc(sizeof(char) * info_len);
57 gl->glGetShaderInfoLog(shader, info_len, NULL, info_log);
58 printf("Error compiling shader:\n%s\n======\n%s\n======\n", info_log, shader_src );
61 gl->glDeleteShader(shader);
68 // Initialize the shader and program object
70 init_shaders(GLData *gld)
72 Evas_GL_API *gl = gld->glapi;
74 "attribute vec4 vPosition; \n"
77 " gl_Position = vPosition; \n"
82 "precision mediump float; \n"
86 " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
91 // Load the vertex/fragment shaders
92 gld->vtx_shader = load_shader(gld, GL_VERTEX_SHADER, (const char*)vShaderStr);
93 gld->fgmt_shader = load_shader(gld, GL_FRAGMENT_SHADER, (const char*)fShaderStr);
95 // Create the program object
96 gld->program = gl->glCreateProgram( );
100 gl->glAttachShader(gld->program, gld->vtx_shader);
101 gl->glAttachShader(gld->program, gld->fgmt_shader);
103 gl->glBindAttribLocation(gld->program, 0, "vPosition");
104 gl->glLinkProgram(gld->program);
105 gl->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
110 gl->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &info_len);
113 char* info_log = malloc(sizeof(char) * info_len);
115 gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log);
116 printf("Error linking program:\n%s\n", info_log);
119 gl->glDeleteProgram(gld->program);
128 // intialize callback that gets called once for intialization
130 _init_gl(Evas_Object *obj)
132 GLData *gld = evas_object_data_get(obj, "gld");
133 Evas_GL_API *gl = gld->glapi;
134 GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
138 if (!init_shaders(gld))
140 printf("Error Initializing Shaders\n");
144 gl->glGenBuffers(1, &gld->vbo);
145 gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
146 gl->glBufferData(GL_ARRAY_BUFFER, 3 * 3 * 4, vVertices, GL_STATIC_DRAW);
149 // delete callback gets called when glview is deleted
151 _del_gl(Evas_Object *obj)
153 GLData *gld = evas_object_data_get(obj, "gld");
156 printf("Unable to get GLData. \n");
159 Evas_GL_API *gl = gld->glapi;
161 gl->glDeleteShader(gld->vtx_shader);
162 gl->glDeleteShader(gld->fgmt_shader);
163 gl->glDeleteProgram(gld->program);
164 gl->glDeleteBuffers(1, &gld->vbo);
166 evas_object_data_del((Evas_Object*)obj, "..gld");
170 // resize callback gets called every time object is resized
172 _resize_gl(Evas_Object *obj)
175 GLData *gld = evas_object_data_get(obj, "gld");
176 Evas_GL_API *gl = gld->glapi;
178 elm_glview_size_get(obj, &w, &h);
180 // GL Viewport stuff. you can avoid doing this if viewport is all the
181 // same as last frame if you want
182 gl->glViewport(0, 0, w, h);
186 // draw callback is where all the main GL rendering happens
188 _draw_gl(Evas_Object *obj)
190 Evas_GL_API *gl = elm_glview_gl_api_get(obj);
191 GLData *gld = evas_object_data_get(obj, "gld");
195 elm_glview_size_get(obj, &w, &h);
197 gl->glViewport(0, 0, w, h);
198 gl->glClearColor(red,0.8,0.3,1);
199 gl->glClear(GL_COLOR_BUFFER_BIT);
202 gl->glEnable(GL_BLEND);
204 gl->glUseProgram(gld->program);
206 gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
207 gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
209 gl->glEnableVertexAttribArray(0);
211 gl->glDrawArrays(GL_TRIANGLES, 0, 3);
213 // Optional - Flush the GL pipeline
217 if (red < 0.0) red = 1.0;
220 // just need to notify that glview has changed so it can render
224 elm_glview_changed_set(data);
229 _on_done(void *data, Evas_Object *obj, void *event_info)
231 evas_object_del((Evas_Object*)data);
236 _del(void *data, Evas *evas, Evas_Object *obj, void *event_info)
238 Ecore_Animator *ani = evas_object_data_get(obj, "ani");
239 ecore_animator_del(ani);
244 elm_main(int argc, char **argv)
246 Evas_Object *win, *bg, *bx, *bt, *gl;
250 if (!(gld = calloc(1, sizeof(GLData)))) return 1;
252 // set the engine to opengl_x11
253 // if commented out, ELM will choose one
254 elm_config_engine_set("opengl_x11");
256 win = elm_win_add(NULL, "glview simple", ELM_WIN_BASIC);
257 elm_win_title_set(win, "GLView Simple");
258 elm_win_autodel_set(win, EINA_TRUE);
259 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
261 bg = elm_bg_add(win);
262 elm_win_resize_object_add(win, bg);
263 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
264 evas_object_show(bg);
266 bx = elm_box_add(win);
267 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
268 elm_win_resize_object_add(win, bx);
269 evas_object_show(bx);
271 //-//-//-// THIS IS WHERE GL INIT STUFF HAPPENS (ALA EGL)
273 // create a new glview object
274 gl = elm_glview_add(win);
275 gld->glapi = elm_glview_gl_api_get(gl);
276 evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
277 evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
278 // mode is simply for supporting alpha, depth buffering, and stencil
280 elm_glview_mode_set(gl, ELM_GLVIEW_ALPHA | ELM_GLVIEW_DEPTH);
281 // resize policy tells glview what to do with the surface when it
282 // resizes. ELM_GLVIEW_RESIZE_POLICY_RECREATE will tell it to
283 // destroy the current surface and recreate it to the new size
284 elm_glview_resize_policy_set(gl, ELM_GLVIEW_RESIZE_POLICY_RECREATE);
285 // render policy tells glview how it would like glview to render
286 // gl code. ELM_GLVIEW_RENDER_POLICY_ON_DEMAND will have the gl
287 // calls called in the pixel_get callback, which only gets called
288 // if the object is visible, hence ON_DEMAND. ALWAYS mode renders
289 // it despite the visibility of the object.
290 elm_glview_render_policy_set(gl, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND);
291 // initialize callback function gets registered here
292 elm_glview_init_func_set(gl, _init_gl);
293 // delete callback function gets registered here
294 elm_glview_del_func_set(gl, _del_gl);
295 elm_glview_resize_func_set(gl, _resize_gl);
296 elm_glview_render_func_set(gl, _draw_gl);
298 //-//-//-// END GL INIT BLOB
300 elm_box_pack_end(bx, gl);
301 evas_object_show(gl);
303 elm_object_focus_set(gl, EINA_TRUE);
305 // animating - just a demo. as long as you trigger an update on the image
306 // object via elm_glview_changed_set() it will be updated.
308 // NOTE: if you delete gl, this animator will keep running trying to access
309 // gl so you'd better delete this animator with ecore_animator_del().
310 ani = ecore_animator_add(_anim, gl);
312 evas_object_data_set(gl, "ani", ani);
313 evas_object_data_set(gl, "gld", gld);
314 evas_object_event_callback_add(gl, EVAS_CALLBACK_DEL, _del, gl);
316 // add an 'OK' button to end the program
317 bt = elm_button_add(win);
318 elm_object_text_set(bt, "OK");
319 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
320 evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
321 elm_box_pack_end(bx, bt);
322 evas_object_show(bt);
323 evas_object_smart_callback_add(bt, "clicked", _on_done, win);
325 evas_object_resize(win, 320, 480);
326 evas_object_show(win);
328 // run the mainloop and process events and callbacks