1 #include <Elementary.h>
3 #include "elm_widget_glview.h"
5 EAPI const char ELM_GLVIEW_SMART_NAME[] = "elm_glview";
7 static const char SIG_FOCUSED[] = "focused";
8 static const char SIG_UNFOCUSED[] = "unfocused";
9 static const char SIG_LANG_CHANGED[] = "language,changed";
11 /* smart callbacks coming from elm glview objects: */
12 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
15 {SIG_LANG_CHANGED, ""},
19 EVAS_SMART_SUBCLASS_NEW
20 (ELM_GLVIEW_SMART_NAME, _elm_glview, Elm_Glview_Smart_Class,
21 Elm_Widget_Smart_Class, elm_widget_smart_class_get, _smart_callbacks);
24 _elm_glview_smart_translate(Evas_Object *obj)
26 evas_object_smart_callback_call(obj, SIG_LANG_CHANGED, NULL);
31 _elm_glview_smart_on_focus(Evas_Object *obj)
33 ELM_GLVIEW_DATA_GET(obj, sd);
35 if (elm_widget_focus_get(obj))
37 evas_object_focus_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_TRUE);
38 evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
42 evas_object_focus_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_FALSE);
43 evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
50 _glview_update_surface(Evas_Object *obj)
52 ELM_GLVIEW_DATA_GET(obj, sd);
57 evas_object_image_native_surface_set
58 (ELM_WIDGET_DATA(sd)->resize_obj, NULL);
59 evas_gl_surface_destroy(sd->evasgl, sd->surface);
63 evas_object_image_size_set(ELM_WIDGET_DATA(sd)->resize_obj, sd->w, sd->h);
67 Evas_Native_Surface ns;
69 sd->surface = evas_gl_surface_create
70 (sd->evasgl, sd->config, sd->w, sd->h);
71 evas_gl_native_surface_get(sd->evasgl, sd->surface, &ns);
72 evas_object_image_native_surface_set
73 (ELM_WIDGET_DATA(sd)->resize_obj, &ns);
74 elm_glview_changed_set(obj);
79 _elm_glview_smart_resize(Evas_Object *obj,
83 ELM_GLVIEW_DATA_GET(obj, sd);
85 _elm_glview_parent_sc->base.resize(obj, w, h);
87 sd->resized = EINA_TRUE;
89 if (sd->scale_policy == ELM_GLVIEW_RESIZE_POLICY_RECREATE)
91 if ((w == 0) || (h == 0))
97 if ((sd->w == w) && (sd->h == h)) return;
102 _glview_update_surface(obj);
107 _render_cb(void *obj)
109 ELM_GLVIEW_DATA_GET(obj, sd);
112 if (!evas_gl_make_current(sd->evasgl, sd->surface, sd->context))
114 sd->render_idle_enterer = NULL;
115 ERR("Failed doing make current.\n");
119 // Call the init function if it hasn't been called already
120 if (!sd->initialized)
122 if (sd->init_func) sd->init_func(obj);
123 sd->initialized = EINA_TRUE;
128 if (sd->resize_func) sd->resize_func(obj);
129 sd->resized = EINA_FALSE;
132 // Call the render function
133 if (sd->render_func) sd->render_func(obj);
135 // Depending on the policy return true or false
136 if (sd->render_policy == ELM_GLVIEW_RENDER_POLICY_ON_DEMAND)
138 else if (sd->render_policy == ELM_GLVIEW_RENDER_POLICY_ALWAYS)
140 // Return false so it only runs once
141 sd->render_idle_enterer = NULL;
146 ERR("Invalid Render Policy.\n");
147 sd->render_idle_enterer = NULL;
155 _set_render_policy_callback(Evas_Object *obj)
157 ELM_GLVIEW_DATA_GET(obj, sd);
159 switch (sd->render_policy)
161 case ELM_GLVIEW_RENDER_POLICY_ON_DEMAND:
162 // Delete idle_enterer if it for some reason is around
163 if (sd->render_idle_enterer)
165 ecore_idle_enterer_del(sd->render_idle_enterer);
166 sd->render_idle_enterer = NULL;
169 // Set pixel getter callback
170 evas_object_image_pixels_get_callback_set
171 (ELM_WIDGET_DATA(sd)->resize_obj,
172 (Evas_Object_Image_Pixels_Get_Cb)_render_cb,
176 case ELM_GLVIEW_RENDER_POLICY_ALWAYS:
177 // Unset the pixel getter callback if set already
178 evas_object_image_pixels_get_callback_set
179 (ELM_WIDGET_DATA(sd)->resize_obj, NULL, NULL);
184 ERR("Invalid Render Policy.\n");
190 _elm_glview_smart_add(Evas_Object *obj)
192 EVAS_SMART_DATA_ALLOC(obj, Elm_Glview_Smart_Data);
194 // Create image to render Evas_GL Surface
195 ELM_WIDGET_DATA(priv)->resize_obj =
196 evas_object_image_filled_add(evas_object_evas_get(obj));
197 evas_object_image_size_set(ELM_WIDGET_DATA(priv)->resize_obj, 1, 1);
199 _elm_glview_parent_sc->base.add(obj);
202 priv->evasgl = evas_gl_new(evas_object_evas_get(obj));
205 ERR("Failed Creating an Evas GL Object.\n");
210 // Create a default config
211 priv->config = evas_gl_config_new();
214 ERR("Failed Creating a Config Object.\n");
215 evas_object_del(obj);
217 evas_gl_free(priv->evasgl);
221 priv->config->color_format = EVAS_GL_RGB_888;
223 // Initialize variables
225 priv->scale_policy = ELM_GLVIEW_RESIZE_POLICY_RECREATE;
226 priv->render_policy = ELM_GLVIEW_RENDER_POLICY_ON_DEMAND;
227 priv->surface = NULL;
229 // Initialize it to (64,64) (It's an arbitrary value)
233 // Initialize the rest of the values
234 priv->init_func = NULL;
235 priv->del_func = NULL;
236 priv->render_func = NULL;
237 priv->render_idle_enterer = NULL;
238 priv->initialized = EINA_FALSE;
239 priv->resized = EINA_FALSE;
242 priv->context = evas_gl_context_create(priv->evasgl, NULL);
245 ERR("Error Creating an Evas_GL Context.\n");
246 evas_object_del(obj);
248 evas_gl_config_free(priv->config);
249 evas_gl_free(priv->evasgl);
256 _elm_glview_smart_del(Evas_Object *obj)
258 ELM_GLVIEW_DATA_GET(obj, sd);
260 // Call delete func if it's registered
263 evas_gl_make_current(sd->evasgl, sd->surface, sd->context);
267 if (sd->render_idle_enterer)
268 ecore_idle_enterer_del(sd->render_idle_enterer);
270 if (sd->surface) evas_gl_surface_destroy(sd->evasgl, sd->surface);
271 if (sd->context) evas_gl_context_destroy(sd->evasgl, sd->context);
272 if (sd->config) evas_gl_config_free(sd->config);
273 if (sd->evasgl) evas_gl_free(sd->evasgl);
275 _elm_glview_parent_sc->base.del(obj); /* handles freeing sd */
279 _elm_glview_smart_set_user(Elm_Glview_Smart_Class *sc)
281 ELM_WIDGET_CLASS(sc)->base.add = _elm_glview_smart_add;
282 ELM_WIDGET_CLASS(sc)->base.del = _elm_glview_smart_del;
283 ELM_WIDGET_CLASS(sc)->base.resize = _elm_glview_smart_resize;
285 ELM_WIDGET_CLASS(sc)->on_focus = _elm_glview_smart_on_focus;
286 ELM_WIDGET_CLASS(sc)->translate = _elm_glview_smart_translate;
289 EAPI const Elm_Glview_Smart_Class *
290 elm_glview_smart_class_get(void)
292 static Elm_Glview_Smart_Class _sc =
293 ELM_GLVIEW_SMART_CLASS_INIT_NAME_VERSION(ELM_GLVIEW_SMART_NAME);
294 static const Elm_Glview_Smart_Class *class = NULL;
295 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
297 if (class) return class;
299 _elm_glview_smart_set(&_sc);
300 esc->callbacks = _smart_callbacks;
307 elm_glview_add(Evas_Object *parent)
311 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
313 obj = elm_widget_add(_elm_glview_smart_class_new(), parent);
314 if (!obj) return NULL;
316 ELM_GLVIEW_DATA_GET(obj, sd);
321 if (!elm_widget_sub_object_add(parent, obj))
322 ERR("could not add %p as sub object of %p", obj, parent);
328 elm_glview_gl_api_get(const Evas_Object *obj)
330 ELM_GLVIEW_CHECK(obj) NULL;
331 ELM_GLVIEW_DATA_GET(obj, sd);
333 return evas_gl_api_get(sd->evasgl);
337 elm_glview_mode_set(Evas_Object *obj,
338 Elm_GLView_Mode mode)
340 ELM_GLVIEW_CHECK(obj) EINA_FALSE;
341 ELM_GLVIEW_DATA_GET(obj, sd);
344 if (mode & ELM_GLVIEW_ALPHA) sd->config->color_format = EVAS_GL_RGBA_8888;
345 else sd->config->color_format = EVAS_GL_RGB_888;
347 if (mode & ELM_GLVIEW_DEPTH) sd->config->depth_bits = EVAS_GL_DEPTH_BIT_24;
348 else sd->config->depth_bits = EVAS_GL_DEPTH_NONE;
350 if (mode & ELM_GLVIEW_STENCIL)
351 sd->config->stencil_bits = EVAS_GL_STENCIL_BIT_8;
352 else sd->config->stencil_bits = EVAS_GL_STENCIL_NONE;
354 if (mode & ELM_GLVIEW_DIRECT)
355 sd->config->options_bits = EVAS_GL_OPTIONS_DIRECT;
356 else sd->config->options_bits = EVAS_GL_OPTIONS_NONE;
358 // Check for Alpha Channel and enable it
359 if (mode & ELM_GLVIEW_ALPHA)
360 evas_object_image_alpha_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_TRUE);
362 evas_object_image_alpha_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_FALSE);
366 elm_glview_changed_set(obj);
372 elm_glview_resize_policy_set(Evas_Object *obj,
373 Elm_GLView_Resize_Policy policy)
375 ELM_GLVIEW_CHECK(obj) EINA_FALSE;
376 ELM_GLVIEW_DATA_GET(obj, sd);
378 if (policy == sd->scale_policy) return EINA_TRUE;
381 case ELM_GLVIEW_RESIZE_POLICY_RECREATE:
382 case ELM_GLVIEW_RESIZE_POLICY_SCALE:
383 sd->scale_policy = policy;
384 _glview_update_surface(obj);
385 elm_glview_changed_set(obj);
389 ERR("Invalid Scale Policy.\n");
395 elm_glview_render_policy_set(Evas_Object *obj,
396 Elm_GLView_Render_Policy policy)
398 ELM_GLVIEW_CHECK(obj) EINA_FALSE;
399 ELM_GLVIEW_DATA_GET(obj, sd);
401 if ((policy != ELM_GLVIEW_RENDER_POLICY_ON_DEMAND) &&
402 (policy != ELM_GLVIEW_RENDER_POLICY_ALWAYS))
404 ERR("Invalid Render Policy.\n");
408 if (sd->render_policy == policy) return EINA_TRUE;
410 sd->render_policy = policy;
411 _set_render_policy_callback(obj);
412 _glview_update_surface(obj);
418 elm_glview_size_set(Evas_Object *obj,
422 ELM_GLVIEW_CHECK(obj);
423 ELM_GLVIEW_DATA_GET(obj, sd);
425 if ((w == sd->w) && (h == sd->h)) return;
429 _glview_update_surface(obj);
431 elm_glview_changed_set(obj);
435 elm_glview_size_get(const Evas_Object *obj,
439 ELM_GLVIEW_CHECK(obj);
440 ELM_GLVIEW_DATA_GET(obj, sd);
447 elm_glview_init_func_set(Evas_Object *obj,
448 Elm_GLView_Func_Cb func)
450 ELM_GLVIEW_CHECK(obj);
451 ELM_GLVIEW_DATA_GET(obj, sd);
453 sd->initialized = EINA_FALSE;
454 sd->init_func = func;
458 elm_glview_del_func_set(Evas_Object *obj,
459 Elm_GLView_Func_Cb func)
461 ELM_GLVIEW_CHECK(obj);
462 ELM_GLVIEW_DATA_GET(obj, sd);
468 elm_glview_resize_func_set(Evas_Object *obj,
469 Elm_GLView_Func_Cb func)
471 ELM_GLVIEW_CHECK(obj);
472 ELM_GLVIEW_DATA_GET(obj, sd);
474 sd->resize_func = func;
478 elm_glview_render_func_set(Evas_Object *obj,
479 Elm_GLView_Func_Cb func)
481 ELM_GLVIEW_CHECK(obj);
482 ELM_GLVIEW_DATA_GET(obj, sd);
484 sd->render_func = func;
485 _set_render_policy_callback(obj);
489 elm_glview_changed_set(Evas_Object *obj)
491 ELM_GLVIEW_CHECK(obj);
492 ELM_GLVIEW_DATA_GET(obj, sd);
494 evas_object_image_pixels_dirty_set
495 (ELM_WIDGET_DATA(sd)->resize_obj, EINA_TRUE);
496 if (sd->render_policy == ELM_GLVIEW_RENDER_POLICY_ALWAYS &&
497 !sd->render_idle_enterer)
498 sd->render_idle_enterer =
499 ecore_idle_enterer_before_add((Ecore_Task_Cb)_render_cb, obj);