elm bin: Use convenient utility function elm_win_util_standard_add()
[framework/uifw/elementary.git] / src / bin / test_glview_simple.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 #include <Elementary.h>
5 #ifndef ELM_LIB_QUICKLAUNCH
6
7 typedef struct _GLData GLData;
8
9 // GL related data here..
10 struct _GLData
11 {
12    Evas_GL_API *glapi;
13    GLuint       program;
14    GLuint       vtx_shader;
15    GLuint       fgmt_shader;
16    GLuint       vbo;
17    int          initialized : 1;
18 };
19
20
21 static float red = 1.0;
22
23 //--------------------------------//
24 static GLuint
25 load_shader( GLData *gld, GLenum type, const char *shader_src )
26 {
27    Evas_GL_API *gl = gld->glapi;
28    GLuint shader;
29    GLint compiled;
30
31    // Create the shader object
32    shader = gl->glCreateShader(type);
33    if (shader==0)
34       return 0;
35
36    // Load/Compile shader source
37    gl->glShaderSource(shader, 1, &shader_src, NULL);
38    gl->glCompileShader(shader);
39    gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
40
41    if (!compiled)
42      {
43         GLint info_len = 0;
44         gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
45         if (info_len > 1)
46           {
47              char* info_log = malloc(sizeof(char) * info_len);
48
49              gl->glGetShaderInfoLog(shader, info_len, NULL, info_log);
50              printf("Error compiling shader:\n%s\n======\n%s\n======\n", info_log, shader_src );
51              free(info_log);
52           }
53         gl->glDeleteShader(shader);
54         return 0;
55      }
56
57    return shader;
58 }
59
60 // Initialize the shader and program object
61 static int
62 init_shaders(GLData *gld)
63 {
64    Evas_GL_API *gl = gld->glapi;
65    GLbyte vShaderStr[] =
66       "attribute vec4 vPosition;    \n"
67       "void main()                  \n"
68       "{                            \n"
69       "   gl_Position = vPosition;  \n"
70       "}                            \n";
71
72    GLbyte fShaderStr[] =
73       "#ifdef GL_ES                                 \n"
74       "precision mediump float;                     \n"
75       "#endif                                       \n"
76       "void main()                                  \n"
77       "{                                            \n"
78       "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
79       "}                                            \n";
80
81    GLint linked;
82
83    // Load the vertex/fragment shaders
84    gld->vtx_shader  = load_shader(gld, GL_VERTEX_SHADER, (const char*)vShaderStr);
85    gld->fgmt_shader = load_shader(gld, GL_FRAGMENT_SHADER, (const char*)fShaderStr);
86
87    // Create the program object
88    gld->program = gl->glCreateProgram( );
89    if (gld->program==0)
90       return 0;
91
92    gl->glAttachShader(gld->program, gld->vtx_shader);
93    gl->glAttachShader(gld->program, gld->fgmt_shader);
94
95    gl->glBindAttribLocation(gld->program, 0, "vPosition");
96    gl->glLinkProgram(gld->program);
97    gl->glGetProgramiv(gld->program, GL_LINK_STATUS, &linked);
98
99    if (!linked)
100      {
101         GLint info_len = 0;
102         gl->glGetProgramiv(gld->program, GL_INFO_LOG_LENGTH, &info_len);
103         if (info_len > 1)
104           {
105              char* info_log = malloc(sizeof(char) * info_len);
106
107              gl->glGetProgramInfoLog(gld->program, info_len, NULL, info_log);
108              printf("Error linking program:\n%s\n", info_log);
109              free(info_log);
110           }
111         gl->glDeleteProgram(gld->program);
112         return 0;
113      }
114    return 1;
115 }
116
117
118
119 // Callbacks
120 static void
121 _init_gl(Evas_Object *obj)
122 {
123    GLData *gld = evas_object_data_get(obj, "gld");
124    Evas_GL_API *gl = gld->glapi;
125    GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
126                            -0.5f, -0.5f, 0.0f,
127                             0.5f, -0.5f, 0.0f };
128
129    if (!init_shaders(gld))
130      {
131         printf("Error Initializing Shaders\n");
132         return;
133      }
134
135    gl->glGenBuffers(1, &gld->vbo);
136    gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
137    gl->glBufferData(GL_ARRAY_BUFFER, 3 * 3 * 4, vVertices, GL_STATIC_DRAW);
138 }
139
140 static void
141 _del_gl(Evas_Object *obj)
142 {
143    GLData *gld = evas_object_data_get(obj, "gld");
144    if (!gld)
145      {
146         printf("Unable to get GLData. \n");
147         return;
148      }
149    Evas_GL_API *gl = gld->glapi;
150
151    gl->glDeleteShader(gld->vtx_shader);
152    gl->glDeleteShader(gld->fgmt_shader);
153    gl->glDeleteProgram(gld->program);
154    gl->glDeleteBuffers(1, &gld->vbo);
155
156    evas_object_data_del((Evas_Object*)obj, "..gld");
157    free(gld);
158 }
159
160
161 static void
162 _resize_gl(Evas_Object *obj)
163 {
164    int w, h;
165    GLData *gld = evas_object_data_get(obj, "gld");
166    Evas_GL_API *gl = gld->glapi;
167
168    elm_glview_size_get(obj, &w, &h);
169
170    // GL Viewport stuff. you can avoid doing this if viewport is all the
171    // same as last frame if you want
172    gl->glViewport(0, 0, w, h);
173 }
174
175
176
177 static void
178 _draw_gl(Evas_Object *obj)
179 {
180    Evas_GL_API *gl = elm_glview_gl_api_get(obj);
181    GLData *gld = evas_object_data_get(obj, "gld");
182    if (!gld) return;
183    int w, h;
184
185    elm_glview_size_get(obj, &w, &h);
186
187    gl->glViewport(0, 0, w, h);
188    gl->glClearColor(red,0.8,0.3,1);
189    gl->glClear(GL_COLOR_BUFFER_BIT);
190
191    // Draw a Triangle
192    gl->glEnable(GL_BLEND);
193
194    gl->glUseProgram(gld->program);
195
196    gl->glBindBuffer(GL_ARRAY_BUFFER, gld->vbo);
197    gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
198                              0, 0);
199    gl->glEnableVertexAttribArray(0);
200
201    gl->glDrawArrays(GL_TRIANGLES, 0, 3);
202
203    // Optional - Flush the GL pipeline
204    gl->glFinish();
205
206    red -= 0.1;
207    if (red < 0.0) red = 1.0;
208 }
209
210 static Eina_Bool
211 _anim(void *data)
212 {
213    elm_glview_changed_set(data);
214    return EINA_TRUE;
215 }
216
217 static void
218 _on_done(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
219 {
220    evas_object_del((Evas_Object*)data);
221 }
222
223
224 static void
225 _del(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
226 {
227    Ecore_Animator *ani = evas_object_data_get(obj, "ani");
228    ecore_animator_del(ani);
229 }
230
231
232 void
233 test_glview_simple(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
234 {
235    Evas_Object *win, *bx, *bt, *gl;
236    Ecore_Animator *ani;
237    GLData *gld = NULL;
238
239    if (!(gld = calloc(1, sizeof(GLData)))) return;
240
241    // Set the engine to opengl_x11
242    elm_config_preferred_engine_set("opengl_x11");
243    win = elm_win_util_standard_add("glview simple", "GLView Simple");
244    // Set preferred engine back to default from config
245    elm_config_preferred_engine_set(NULL);
246
247    elm_win_autodel_set(win, EINA_TRUE);
248
249    bx = elm_box_add(win);
250    evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
251    elm_win_resize_object_add(win, bx);
252    evas_object_show(bx);
253
254    gl = elm_glview_add(win);
255    evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
256    evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
257    elm_glview_mode_set(gl, ELM_GLVIEW_ALPHA | ELM_GLVIEW_DEPTH);
258    elm_glview_resize_policy_set(gl, ELM_GLVIEW_RESIZE_POLICY_RECREATE);
259    elm_glview_render_policy_set(gl, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND);
260    elm_glview_init_func_set(gl, _init_gl);
261    elm_glview_del_func_set(gl, _del_gl);
262    elm_glview_resize_func_set(gl, _resize_gl);
263    elm_glview_render_func_set(gl, _draw_gl);
264    elm_box_pack_end(bx, gl);
265    evas_object_show(gl);
266
267    elm_object_focus_set(gl, EINA_TRUE);
268
269    ani = ecore_animator_add(_anim, gl);
270    gld->glapi = elm_glview_gl_api_get(gl);
271    evas_object_data_set(gl, "ani", ani);
272    evas_object_data_set(gl, "gld", gld);
273    evas_object_event_callback_add(gl, EVAS_CALLBACK_DEL, _del, gl);
274
275    bt = elm_button_add(win);
276    elm_object_text_set(bt, "OK");
277    evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
278    evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
279    elm_box_pack_end(bx, bt);
280    evas_object_show(bt);
281    evas_object_smart_callback_add(bt, "clicked", _on_done, win);
282
283    evas_object_resize(win, 320, 480);
284    evas_object_show(win);
285 }
286 #endif