diff options
author | David Walter Seikel | 2012-04-22 09:20:32 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-04-22 09:20:32 +1000 |
commit | 3ad3455551be0d7859ecb02290376206d5e66498 (patch) | |
tree | 497917e12b4d7f458dff9765d9b53f64c4e03fc3 /libraries/elementary/src/lib/elm_glview.c | |
parent | Update EFL to latest beta. (diff) | |
download | SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.zip SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.gz SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.bz2 SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.xz |
And actually include new files, plus elementary libraries.
Diffstat (limited to 'libraries/elementary/src/lib/elm_glview.c')
-rw-r--r-- | libraries/elementary/src/lib/elm_glview.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_glview.c b/libraries/elementary/src/lib/elm_glview.c new file mode 100644 index 0000000..339f23f --- /dev/null +++ b/libraries/elementary/src/lib/elm_glview.c | |||
@@ -0,0 +1,462 @@ | |||
1 | #include <Elementary.h> | ||
2 | #include "elm_priv.h" | ||
3 | |||
4 | typedef struct _Widget_Data Widget_Data; | ||
5 | |||
6 | struct _Widget_Data | ||
7 | { | ||
8 | Evas_Object *glview_image; | ||
9 | |||
10 | Elm_GLView_Mode mode; | ||
11 | Elm_GLView_Resize_Policy scale_policy; | ||
12 | Elm_GLView_Render_Policy render_policy; | ||
13 | |||
14 | Evas_GL *evasgl; | ||
15 | Evas_GL_Config *config; | ||
16 | Evas_GL_Surface *surface; | ||
17 | Evas_GL_Context *context; | ||
18 | |||
19 | Evas_Coord w, h; | ||
20 | |||
21 | Elm_GLView_Func_Cb init_func; | ||
22 | Elm_GLView_Func_Cb del_func; | ||
23 | Elm_GLView_Func_Cb resize_func; | ||
24 | Elm_GLView_Func_Cb render_func; | ||
25 | |||
26 | Ecore_Idle_Enterer *render_idle_enterer; | ||
27 | |||
28 | Eina_Bool initialized; | ||
29 | Eina_Bool resized; | ||
30 | }; | ||
31 | |||
32 | static const char *widtype = NULL; | ||
33 | static void _del_hook(Evas_Object *obj); | ||
34 | static void _on_focus_hook(void *data, Evas_Object *obj); | ||
35 | |||
36 | static const char SIG_FOCUSED[] = "focused"; | ||
37 | static const char SIG_UNFOCUSED[] = "unfocused"; | ||
38 | |||
39 | static void | ||
40 | _del_hook(Evas_Object *obj) | ||
41 | { | ||
42 | Widget_Data *wd = elm_widget_data_get(obj); | ||
43 | if (!wd) return; | ||
44 | |||
45 | // Call delete func if it's registered | ||
46 | if (wd->del_func) | ||
47 | { | ||
48 | evas_gl_make_current(wd->evasgl, wd->surface, wd->context); | ||
49 | wd->del_func(obj); | ||
50 | } | ||
51 | |||
52 | if (wd->render_idle_enterer) ecore_idle_enterer_del(wd->render_idle_enterer); | ||
53 | |||
54 | if (wd->surface) evas_gl_surface_destroy(wd->evasgl, wd->surface); | ||
55 | if (wd->context) evas_gl_context_destroy(wd->evasgl, wd->context); | ||
56 | if (wd->config) evas_gl_config_free(wd->config); | ||
57 | if (wd->evasgl) evas_gl_free(wd->evasgl); | ||
58 | |||
59 | free(wd); | ||
60 | } | ||
61 | |||
62 | static void | ||
63 | _on_focus_hook(void *data __UNUSED__, Evas_Object *obj) | ||
64 | { | ||
65 | Widget_Data *wd = elm_widget_data_get(obj); | ||
66 | if (!wd) return; | ||
67 | |||
68 | if (elm_widget_focus_get(obj)) | ||
69 | { | ||
70 | evas_object_focus_set(wd->glview_image, EINA_TRUE); | ||
71 | evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL); | ||
72 | } | ||
73 | else | ||
74 | { | ||
75 | evas_object_focus_set(wd->glview_image, EINA_FALSE); | ||
76 | evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static void | ||
81 | _glview_update_surface(Evas_Object *obj) | ||
82 | { | ||
83 | Widget_Data *wd = elm_widget_data_get(obj); | ||
84 | if (!wd) return; | ||
85 | |||
86 | if (wd->surface) | ||
87 | { | ||
88 | evas_object_image_native_surface_set(wd->glview_image, NULL); | ||
89 | evas_gl_surface_destroy(wd->evasgl, wd->surface); | ||
90 | wd->surface = NULL; | ||
91 | } | ||
92 | |||
93 | evas_object_image_size_set(wd->glview_image, wd->w, wd->h); | ||
94 | |||
95 | if (!wd->surface) | ||
96 | { | ||
97 | Evas_Native_Surface ns; | ||
98 | |||
99 | wd->surface = evas_gl_surface_create(wd->evasgl, wd->config, | ||
100 | wd->w, wd->h); | ||
101 | evas_gl_native_surface_get(wd->evasgl, wd->surface, &ns); | ||
102 | evas_object_image_native_surface_set(wd->glview_image, &ns); | ||
103 | elm_glview_changed_set(obj); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static void | ||
108 | _glview_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
109 | { | ||
110 | Widget_Data *wd = elm_widget_data_get(data); | ||
111 | Evas_Coord w, h; | ||
112 | |||
113 | if (!wd) return; | ||
114 | |||
115 | wd->resized = EINA_TRUE; | ||
116 | |||
117 | if (wd->scale_policy == ELM_GLVIEW_RESIZE_POLICY_RECREATE) | ||
118 | { | ||
119 | evas_object_geometry_get(wd->glview_image, NULL, NULL, &w, &h); | ||
120 | if ((w == 0) || (h == 0)) | ||
121 | { | ||
122 | w = 64; | ||
123 | h = 64; | ||
124 | } | ||
125 | if ((wd->w == w) && (wd->h == h)) return; | ||
126 | wd->w = w; | ||
127 | wd->h = h; | ||
128 | _glview_update_surface(data); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static Eina_Bool | ||
133 | _render_cb(void *obj) | ||
134 | { | ||
135 | Widget_Data *wd = elm_widget_data_get(obj); | ||
136 | if (!wd) return EINA_FALSE; | ||
137 | |||
138 | // Do a make current | ||
139 | if (!evas_gl_make_current(wd->evasgl, wd->surface, wd->context)) | ||
140 | { | ||
141 | wd->render_idle_enterer = NULL; | ||
142 | ERR("Failed doing make current.\n"); | ||
143 | return EINA_FALSE; | ||
144 | } | ||
145 | |||
146 | // Call the init function if it hasn't been called already | ||
147 | if (!wd->initialized) | ||
148 | { | ||
149 | if (wd->init_func) wd->init_func(obj); | ||
150 | wd->initialized = EINA_TRUE; | ||
151 | } | ||
152 | |||
153 | if (wd->resized) | ||
154 | { | ||
155 | if (wd->resize_func) wd->resize_func(obj); | ||
156 | wd->resized = EINA_FALSE; | ||
157 | } | ||
158 | |||
159 | // Call the render function | ||
160 | if (wd->render_func) wd->render_func(obj); | ||
161 | |||
162 | // Depending on the policy return true or false | ||
163 | if (wd->render_policy == ELM_GLVIEW_RENDER_POLICY_ON_DEMAND) | ||
164 | return EINA_TRUE; | ||
165 | else if (wd->render_policy == ELM_GLVIEW_RENDER_POLICY_ALWAYS) | ||
166 | { | ||
167 | // Return false so it only runs once | ||
168 | wd->render_idle_enterer = NULL; | ||
169 | return EINA_FALSE; | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | ERR("Invalid Render Policy.\n"); | ||
174 | wd->render_idle_enterer = NULL; | ||
175 | return EINA_FALSE; | ||
176 | } | ||
177 | return EINA_TRUE; | ||
178 | } | ||
179 | |||
180 | static void | ||
181 | _set_render_policy_callback(Evas_Object *obj) | ||
182 | { | ||
183 | Widget_Data *wd = elm_widget_data_get(obj); | ||
184 | |||
185 | switch (wd->render_policy) | ||
186 | { | ||
187 | case ELM_GLVIEW_RENDER_POLICY_ON_DEMAND: | ||
188 | // Delete idle_enterer if it for some reason is around | ||
189 | if (wd->render_idle_enterer) | ||
190 | { | ||
191 | ecore_idle_enterer_del(wd->render_idle_enterer); | ||
192 | wd->render_idle_enterer = NULL; | ||
193 | } | ||
194 | |||
195 | // Set pixel getter callback | ||
196 | evas_object_image_pixels_get_callback_set | ||
197 | (wd->glview_image, (Evas_Object_Image_Pixels_Get_Cb)_render_cb, obj); | ||
198 | break; | ||
199 | case ELM_GLVIEW_RENDER_POLICY_ALWAYS: | ||
200 | // Unset the pixel getter callback if set already | ||
201 | evas_object_image_pixels_get_callback_set(wd->glview_image, NULL, NULL); | ||
202 | |||
203 | break; | ||
204 | default: | ||
205 | ERR("Invalid Render Policy.\n"); | ||
206 | return; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | EAPI Evas_Object * | ||
211 | elm_glview_add(Evas_Object *parent) | ||
212 | { | ||
213 | Evas_Object *obj; | ||
214 | Evas *e; | ||
215 | Widget_Data *wd; | ||
216 | |||
217 | ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); | ||
218 | |||
219 | ELM_SET_WIDTYPE(widtype, "glview"); | ||
220 | elm_widget_type_set(obj, "glview"); | ||
221 | elm_widget_sub_object_add(parent, obj); | ||
222 | elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); | ||
223 | elm_widget_data_set(obj, wd); | ||
224 | elm_widget_del_hook_set(obj, _del_hook); | ||
225 | |||
226 | // Evas_GL | ||
227 | wd->evasgl = evas_gl_new(e); | ||
228 | if (!wd->evasgl) | ||
229 | { | ||
230 | ERR("Failed Creating an Evas GL Object.\n"); | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
234 | // Create a default config | ||
235 | wd->config = evas_gl_config_new(); | ||
236 | if (!wd->config) | ||
237 | { | ||
238 | ERR("Failed Creating a Config Object.\n"); | ||
239 | evas_gl_free(wd->evasgl); | ||
240 | return NULL; | ||
241 | } | ||
242 | wd->config->color_format = EVAS_GL_RGB_888; | ||
243 | |||
244 | // Create image to render Evas_GL Surface | ||
245 | wd->glview_image = evas_object_image_filled_add(e); | ||
246 | evas_object_image_size_set(wd->glview_image, 1, 1); | ||
247 | evas_object_event_callback_add(wd->glview_image, EVAS_CALLBACK_RESIZE, | ||
248 | _glview_resize, obj); | ||
249 | elm_widget_resize_object_set(obj, wd->glview_image); | ||
250 | evas_object_show(wd->glview_image); | ||
251 | |||
252 | // Initialize variables | ||
253 | wd->mode = 0; | ||
254 | wd->scale_policy = ELM_GLVIEW_RESIZE_POLICY_RECREATE; | ||
255 | wd->render_policy = ELM_GLVIEW_RENDER_POLICY_ON_DEMAND; | ||
256 | wd->surface = NULL; | ||
257 | |||
258 | // Initialize it to (64,64) (It's an arbitrary value) | ||
259 | wd->w = 64; | ||
260 | wd->h = 64; | ||
261 | |||
262 | // Initialize the rest of the values | ||
263 | wd->init_func = NULL; | ||
264 | wd->del_func = NULL; | ||
265 | wd->render_func = NULL; | ||
266 | wd->render_idle_enterer = NULL; | ||
267 | wd->initialized = EINA_FALSE; | ||
268 | wd->resized = EINA_FALSE; | ||
269 | |||
270 | // Create Context | ||
271 | if (!wd->context) | ||
272 | { | ||
273 | wd->context = evas_gl_context_create(wd->evasgl, NULL); | ||
274 | if (!wd->context) | ||
275 | { | ||
276 | ERR("Error Creating an Evas_GL Context.\n"); | ||
277 | return NULL; | ||
278 | } | ||
279 | } | ||
280 | return obj; | ||
281 | } | ||
282 | |||
283 | EAPI Evas_GL_API * | ||
284 | elm_glview_gl_api_get(const Evas_Object *obj) | ||
285 | { | ||
286 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
287 | Widget_Data *wd = elm_widget_data_get(obj); | ||
288 | if (!wd) return NULL; | ||
289 | |||
290 | return evas_gl_api_get(wd->evasgl); | ||
291 | } | ||
292 | |||
293 | EAPI Eina_Bool | ||
294 | elm_glview_mode_set(Evas_Object *obj, Elm_GLView_Mode mode) | ||
295 | { | ||
296 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
297 | Widget_Data *wd = elm_widget_data_get(obj); | ||
298 | if (!wd) return EINA_FALSE; | ||
299 | |||
300 | // Set the configs | ||
301 | if (mode & ELM_GLVIEW_ALPHA) | ||
302 | wd->config->color_format = EVAS_GL_RGBA_8888; | ||
303 | else | ||
304 | wd->config->color_format = EVAS_GL_RGB_888; | ||
305 | |||
306 | if (mode & ELM_GLVIEW_DEPTH) | ||
307 | wd->config->depth_bits = EVAS_GL_DEPTH_BIT_24; | ||
308 | else | ||
309 | wd->config->depth_bits = EVAS_GL_DEPTH_NONE; | ||
310 | |||
311 | if (mode & ELM_GLVIEW_STENCIL) | ||
312 | wd->config->stencil_bits = EVAS_GL_STENCIL_BIT_8; | ||
313 | else | ||
314 | wd->config->stencil_bits = EVAS_GL_STENCIL_NONE; | ||
315 | |||
316 | if (mode & ELM_GLVIEW_DIRECT) | ||
317 | wd->config->options_bits = EVAS_GL_OPTIONS_DIRECT; | ||
318 | else | ||
319 | wd->config->options_bits = EVAS_GL_OPTIONS_NONE; | ||
320 | |||
321 | // Check for Alpha Channel and enable it | ||
322 | if (mode & ELM_GLVIEW_ALPHA) | ||
323 | evas_object_image_alpha_set(wd->glview_image, EINA_TRUE); | ||
324 | else | ||
325 | evas_object_image_alpha_set(wd->glview_image, EINA_FALSE); | ||
326 | |||
327 | wd->mode = mode; | ||
328 | |||
329 | elm_glview_changed_set(obj); | ||
330 | |||
331 | return EINA_TRUE; | ||
332 | } | ||
333 | |||
334 | EAPI Eina_Bool | ||
335 | elm_glview_resize_policy_set(Evas_Object *obj, Elm_GLView_Resize_Policy policy) | ||
336 | { | ||
337 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
338 | Widget_Data *wd = elm_widget_data_get(obj); | ||
339 | if (!wd) return EINA_FALSE; | ||
340 | |||
341 | if (policy == wd->scale_policy) return EINA_TRUE; | ||
342 | switch (policy) | ||
343 | { | ||
344 | case ELM_GLVIEW_RESIZE_POLICY_RECREATE: | ||
345 | case ELM_GLVIEW_RESIZE_POLICY_SCALE: | ||
346 | wd->scale_policy = policy; | ||
347 | _glview_update_surface(obj); | ||
348 | elm_glview_changed_set(obj); | ||
349 | return EINA_TRUE; | ||
350 | default: | ||
351 | ERR("Invalid Scale Policy.\n"); | ||
352 | return EINA_FALSE; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | EAPI Eina_Bool | ||
357 | elm_glview_render_policy_set(Evas_Object *obj, Elm_GLView_Render_Policy policy) | ||
358 | { | ||
359 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
360 | Widget_Data *wd = elm_widget_data_get(obj); | ||
361 | if (!wd) return EINA_FALSE; | ||
362 | |||
363 | if ((policy != ELM_GLVIEW_RENDER_POLICY_ON_DEMAND) && | ||
364 | (policy != ELM_GLVIEW_RENDER_POLICY_ALWAYS)) | ||
365 | { | ||
366 | ERR("Invalid Render Policy.\n"); | ||
367 | return EINA_FALSE; | ||
368 | } | ||
369 | if (wd->render_policy == policy) return EINA_TRUE; | ||
370 | wd->render_policy = policy; | ||
371 | _set_render_policy_callback(obj); | ||
372 | _glview_update_surface(obj); | ||
373 | return EINA_TRUE; | ||
374 | } | ||
375 | |||
376 | EAPI void | ||
377 | elm_glview_size_set(Evas_Object *obj, int w, int h) | ||
378 | { | ||
379 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
380 | Widget_Data *wd = elm_widget_data_get(obj); | ||
381 | if (!wd) return; | ||
382 | |||
383 | if ((w == wd->w) && (h == wd->h)) return; | ||
384 | wd->w = w; | ||
385 | wd->h = h; | ||
386 | _glview_update_surface(obj); | ||
387 | elm_glview_changed_set(obj); | ||
388 | } | ||
389 | |||
390 | EAPI void | ||
391 | elm_glview_size_get(const Evas_Object *obj, int *w, int *h) | ||
392 | { | ||
393 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
394 | Widget_Data *wd = elm_widget_data_get(obj); | ||
395 | if (!wd) return; | ||
396 | |||
397 | if (w) *w = wd->w; | ||
398 | if (h) *h = wd->h; | ||
399 | } | ||
400 | |||
401 | EAPI void | ||
402 | elm_glview_init_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func) | ||
403 | { | ||
404 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
405 | Widget_Data *wd = elm_widget_data_get(obj); | ||
406 | if (!wd) return; | ||
407 | |||
408 | wd->initialized = EINA_FALSE; | ||
409 | wd->init_func = func; | ||
410 | } | ||
411 | |||
412 | EAPI void | ||
413 | elm_glview_del_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func) | ||
414 | { | ||
415 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
416 | Widget_Data *wd = elm_widget_data_get(obj); | ||
417 | if (!wd) return; | ||
418 | |||
419 | wd->del_func = func; | ||
420 | } | ||
421 | |||
422 | EAPI void | ||
423 | elm_glview_resize_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func) | ||
424 | { | ||
425 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
426 | Widget_Data *wd = elm_widget_data_get(obj); | ||
427 | if (!wd) | ||
428 | { | ||
429 | ERR("Invalid Widget Object.\n"); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | wd->resize_func = func; | ||
434 | } | ||
435 | |||
436 | EAPI void | ||
437 | elm_glview_render_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func) | ||
438 | { | ||
439 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
440 | Widget_Data *wd = elm_widget_data_get(obj); | ||
441 | if (!wd) return; | ||
442 | |||
443 | wd->render_func = func; | ||
444 | _set_render_policy_callback(obj); | ||
445 | } | ||
446 | |||
447 | EAPI void | ||
448 | elm_glview_changed_set(Evas_Object *obj) | ||
449 | { | ||
450 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
451 | Widget_Data *wd = elm_widget_data_get(obj); | ||
452 | if (!wd) return; | ||
453 | |||
454 | evas_object_image_pixels_dirty_set(wd->glview_image, EINA_TRUE); | ||
455 | if (wd->render_policy == ELM_GLVIEW_RENDER_POLICY_ALWAYS) | ||
456 | { | ||
457 | if (!wd->render_idle_enterer) | ||
458 | wd->render_idle_enterer = ecore_idle_enterer_before_add((Ecore_Task_Cb)_render_cb, obj); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/ | ||