8 #include <Elementary.h>
9 #include <Ecore_Evas.h>
11 #include <widget_errno.h>
12 #include <widget_service.h>
13 #include <widget_service_internal.h>
14 #include <widget_provider.h>
15 #include <widget_provider_buffer.h>
16 #include <widget_conf.h>
21 #include "widget_internal.h"
26 #define PUBLIC __attribute__((visibility("default")))
29 * @brief These functions are defined in the data-provider-slave
32 const char *(*find_pkgname)(const char *filename);
33 int (*request_update_by_id)(const char *uri);
34 int (*trigger_update_monitor)(const char *id, int is_gbar);
35 int (*update_extra_info)(const char *id, const char *content, const char *title, const char *icon, const char *name);
36 int (*add_pre_callback)(widget_pre_callback_e type, widget_pre_callback_t cb, void *data);
37 int (*del_pre_callback)(widget_pre_callback_e type, widget_pre_callback_t cb, void *data);
38 int (*orientation)(const char *id);
39 Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data);
40 Ecore_Evas *(*alloc_canvas_with_stride)(int w, int h, void *(*a)(void *data, int size, int *stride, int *bpp), void (*f)(void *data, void *ptr), void *data);
41 Ecore_Evas *(*alloc_canvas_with_pixmap)(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h, Ecore_X_Pixmap (*alloc_cb)(void *data, Ecore_X_Window parent, int w, int h, int depth), void (*free_cb)(void *data, Ecore_X_Pixmap pixmap), void *data);
44 LOAD_TYPE_UNKNOWN = -1,
51 int (*send)(const char *pkgname, const char *id, widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile);
55 int (*send)(widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar);
60 .request_update_by_id = NULL,
61 .trigger_update_monitor = NULL,
62 .update_extra_info = NULL,
63 .add_pre_callback = NULL,
64 .del_pre_callback = NULL,
67 .alloc_canvas_with_stride = NULL,
68 .alloc_canvas_with_pixmap = NULL,
69 .type = LOAD_TYPE_UNKNOWN, /* Not initialized */
80 #define FUNC_PREFIX "widget_"
81 #define FUNC_WIDGET_SEND_UPDATED FUNC_PREFIX "send_buffer_updated"
82 #define FUNC_WIDGET_FIND_PKGNAME FUNC_PREFIX "find_pkgname"
83 #define FUNC_WIDGET_REQUEST_UPDATE_BY_ID FUNC_PREFIX "request_update_by_id"
84 #define FUNC_WIDGET_TRIGGER_UPDATE_MONITOR FUNC_PREFIX "trigger_update_monitor"
85 #define FUNC_WIDGET_UPDATE_EXTRA_INFO FUNC_PREFIX "update_extra_info"
87 #define FUNC_WIDGET_PROVIDER_APP_UPDATED FUNC_PREFIX "provider_app_send_buffer_updated_event"
89 #define FUNC_WIDGET_PROVIDER_APP_ADD_PRE_CALLBACK FUNC_PREFIX "provider_app_add_pre_callback"
90 #define FUNC_WIDGET_PROVIDER_APP_DEL_PRE_CALLBACK FUNC_PREFIX "provider_app_del_pre_callback"
91 #define FUNC_WIDGET_PROVIDER_APP_ORIENTATION FUNC_PREFIX "provider_app_get_orientation"
93 static inline void load_ecore_evas_function(void)
95 if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) {
96 s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new");
97 if (!s_info.alloc_canvas_with_pixmap) {
98 DbgPrint("pixmap_allocfunc_new is not found\n");
101 s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
102 if (!s_info.alloc_canvas_with_stride) {
103 DbgPrint("allocfunc_with_stirde_new is not found\n");
106 s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
107 if (!s_info.alloc_canvas) {
108 ErrPrint("allocfunc_new is not found\n");
111 if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) {
112 ErrPrint("No way to allocate canvas\n");
117 static inline void load_update_function(void)
119 /* Must to be checked the slave function first. */
120 s_info.binder.slave.send = dlsym(RTLD_DEFAULT, FUNC_WIDGET_SEND_UPDATED);
121 if (s_info.binder.slave.send) {
122 s_info.type = LOAD_TYPE_SLAVE;
123 DbgPrint("Slave detected\n");
125 s_info.binder.app.send = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_UPDATED);
126 if (s_info.binder.app.send) {
127 s_info.type = LOAD_TYPE_APP;
128 DbgPrint("App detected\n");
133 PUBLIC int widget_get_orientation(const char *id)
135 if (!s_info.orientation) {
136 s_info.orientation = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_ORIENTATION);
137 if (!s_info.orientation) {
138 return WIDGET_ERROR_NOT_SUPPORTED;
142 return s_info.orientation(id);
145 PUBLIC int widget_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
147 if (!s_info.add_pre_callback) {
148 s_info.add_pre_callback = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_ADD_PRE_CALLBACK);
149 if (!s_info.add_pre_callback) {
150 return WIDGET_ERROR_NOT_SUPPORTED;
154 return s_info.add_pre_callback(type, cb, data);
157 PUBLIC int widget_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
159 if (!s_info.del_pre_callback) {
160 s_info.del_pre_callback = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_DEL_PRE_CALLBACK);
161 if (!s_info.del_pre_callback) {
162 return WIDGET_ERROR_NOT_SUPPORTED;
166 return s_info.del_pre_callback(type, cb, data);
169 int binder_widget_send_updated(const char *pkgname, const char *id, widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
171 int ret = WIDGET_ERROR_INVALID_PARAMETER;
173 if (s_info.type == LOAD_TYPE_UNKNOWN) {
174 load_update_function();
177 if (s_info.type == LOAD_TYPE_APP) {
178 ret = s_info.binder.app.send(handle, idx, x, y, w, h, gbar);
179 } else if (s_info.type == LOAD_TYPE_SLAVE) {
181 * pkgname, id are used for finding handle of direct connection.
183 ret = s_info.binder.slave.send(pkgname, id, handle, idx, x, y, w, h, gbar, descfile);
185 widget_damage_region_s region = {
191 ret = widget_provider_send_buffer_updated(handle, idx, ®ion, gbar, descfile);
197 PUBLIC int widget_content_is_updated(const char *filename, int is_gbar)
199 if (!s_info.trigger_update_monitor) {
200 s_info.trigger_update_monitor = dlsym(RTLD_DEFAULT, FUNC_WIDGET_TRIGGER_UPDATE_MONITOR);
201 if (!s_info.trigger_update_monitor) {
202 ErrPrint("Trigger update monitor function is not exists\n");
203 return WIDGET_ERROR_FAULT;
207 return s_info.trigger_update_monitor(filename, is_gbar);
210 const char *binder_widget_find_pkgname(const char *uri)
214 if (!s_info.find_pkgname) {
215 s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_WIDGET_FIND_PKGNAME);
216 if (!s_info.find_pkgname) {
217 ErrPrint("Failed to find a \"widget_find_pkgname\"\n");
222 pkgname = s_info.find_pkgname(uri);
224 ErrPrint("Failed to find a package (%s)\n", uri);
231 PUBLIC int widget_request_update(const char *filename)
237 ErrPrint("Invalid argument\n");
238 return WIDGET_ERROR_INVALID_PARAMETER;
241 uri = util_id_to_uri(filename);
243 ErrPrint("Heap: %d\n", errno);
244 return WIDGET_ERROR_OUT_OF_MEMORY;
247 if (!s_info.request_update_by_id) {
248 s_info.request_update_by_id = dlsym(RTLD_DEFAULT, FUNC_WIDGET_REQUEST_UPDATE_BY_ID);
249 if (!s_info.request_update_by_id) {
250 ErrPrint("\"widget_request_update_by_id\" is not exists\n");
252 return WIDGET_ERROR_FAULT;
256 ret = s_info.request_update_by_id(uri);
261 int binder_widget_update_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
263 if (!s_info.update_extra_info) {
264 s_info.update_extra_info = dlsym(RTLD_DEFAULT, FUNC_WIDGET_UPDATE_EXTRA_INFO);
265 if (!s_info.update_extra_info) {
266 ErrPrint("Failed to find a \"widget_update_extra_info\"\n");
267 return WIDGET_ERROR_INVALID_PARAMETER;
271 return s_info.update_extra_info(id, content, title, icon, name);
276 * This callback can be called twice (or more) to get a several pixmaps
277 * Acquired pixmaps are used for double/tripple buffering for canvas
279 static Ecore_X_Pixmap alloc_pixmap_cb(void *data, Ecore_X_Window parent, int w, int h, int depth)
281 vwin_info_t info = data;
282 Ecore_X_Pixmap pixmap;
285 ErrPrint("Invalid handle\n");
291 DbgPrint("Size of ee is updated: %dx%d - %d (info: %p)\n", info->w, info->h, depth, info);
294 if (widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER) == 0u) {
297 * Need to allocate a primary buffer
299 widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, depth);
301 ErrPrint("Failed to get the buffer\n");
305 pixmap = (Ecore_X_Pixmap)widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER);
306 } else if (WIDGET_CONF_EXTRA_BUFFER_COUNT > 0) {
309 if (!info->resource_array) {
310 info->resource_array = calloc(WIDGET_CONF_EXTRA_BUFFER_COUNT, sizeof(*info->resource_array));
311 if (!info->resource_array) {
312 ErrPrint("Out of memory: %d\n", errno);
318 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
319 if (info->resource_array[idx] == 0u) {
324 if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) {
325 ErrPrint("Out of index: %d\n", idx);
330 if (widget_viewer_acquire_buffer(info->handle, idx, info->w, info->h, depth) < 0) {
331 ErrPrint("Failed to acquire a buffer for %d\n", idx);
335 info->resource_array[idx] = widget_viewer_get_resource_id(info->handle, idx);
336 if (info->resource_array[idx] == 0u) {
337 ErrPrint("Failed to allocate pixmap\n");
340 DbgPrint("Allocated index: %d/%d - %u\n", idx, WIDGET_CONF_EXTRA_BUFFER_COUNT, info->resource_array[idx]);
341 pixmap = info->resource_array[idx];
343 ErrPrint("Unable to allocate pixmap\n");
348 * Acquire a buffer for canvas.
350 info->type = VWIN_PIXMAP;
351 info->resource_cnt += !!(unsigned int)pixmap;
355 static void free_pixmap_cb(void *data, Ecore_X_Pixmap pixmap)
357 vwin_info_t info = data;
363 if (info->type != VWIN_PIXMAP) {
364 ErrPrint("Impossible\n");
367 if (widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER) == pixmap) {
368 if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) {
369 DbgPrint("Failed to release buffer\n");
371 info->resource_cnt--;
375 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
378 * Find a index to release it
380 if (info->resource_array[idx] == pixmap) {
381 if (widget_viewer_release_buffer(info->handle, idx) < 0) {
382 DbgPrint("Failed to release buffer\n");
384 info->resource_array[idx] = 0u;
385 info->resource_cnt--;
391 if (info->deleted && info->resource_cnt == 0) {
392 DbgPrint("Destroy buffer handle\n");
394 info->state = VWIN_INFO_DESTROYED;
395 widget_destroy_buffer(info->handle);
396 free(info->resource_array);
402 static void *alloc_fb(void *data, int size)
404 vwin_info_t info = data;
408 ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
409 DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
413 ErrPrint("Failed to create a buffer\n");
417 if (widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) {
418 ErrPrint("Failed to acquire buffer\n");
423 * If it supports the H/W accelerated buffer,
426 if (widget_support_hw_buffer(info->handle)) {
427 if (widget_create_hw_buffer(info->handle) == 0) {
428 buffer = widget_buffer_hw_buffer(info->handle);
430 DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
431 info->type = VWIN_GEM;
436 ErrPrint("Failed to allocate HW Accelerated buffer\n");
440 * Or use the buffer of a S/W backend.
442 buffer = widget_ref_buffer(info->handle);
443 DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h);
444 info->type = VWIN_SW_BUF;
448 static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp)
452 buffer = alloc_fb(data, size);
454 vwin_info_t info = data;
458 _stride = widget_buffer_stride(info->handle);
460 _stride = info->w * *bpp;
465 DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride);
471 static void free_fb(void *data, void *ptr)
473 vwin_info_t info = data;
479 if (info->type == VWIN_GEM) {
480 if (widget_destroy_hw_buffer(info->handle) == 0) {
481 DbgPrint("HW Accelerated buffer is destroyed\n");
483 } else if (info->type == VWIN_SW_BUF) {
484 DbgPrint("SW buffer is destroyed, %p\n", info);
485 widget_unref_buffer(ptr);
486 } else if (info->type == VWIN_PIXMAP) {
487 ErrPrint("Unable to reach to here\n");
490 if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) {
491 ErrPrint("Failed to release buffer\n");
495 info->state = VWIN_INFO_DESTROYED;
496 widget_destroy_buffer(info->handle);
497 free(info->resource_array);
503 static inline int check_gl_engine(const char *engine)
507 * If the "engine" string going to be changed to more complicated formatted string,
508 * We should replace this with sytanx recognizer (parser).
510 return !!strcasestr(engine, GL_ENGINE);
513 Ecore_Evas *binder_ecore_evas_new(vwin_info_t info)
516 Ecore_Evas *ee = NULL;
518 load_ecore_evas_function();
520 engine = elm_config_accel_preference_get();
522 DbgPrint("Preferred engine: %s (%s or %s)\n", engine, GL_ENGINE, GL_ENGINE_X11);
523 if (engine && check_gl_engine(engine)) {
524 if (s_info.alloc_canvas_with_pixmap) {
525 ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info);
527 ErrPrint("Unable to create a ee for pixmap\n");
533 if (!widget_conf_auto_align() && s_info.alloc_canvas_with_stride) {
534 ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info);
535 } else if (s_info.alloc_canvas) {
536 ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info);
543 int binder_widget_auto_align(void)
545 load_ecore_evas_function();
547 return widget_conf_auto_align() || !s_info.alloc_canvas_with_stride;