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 int (*get_last_ctrl_mode)(const char *id, int *cmd, int *value);
40 Ecore_Evas *(*alloc_canvas)(int w, int h, void *(*a)(void *data, int size), void (*f)(void *data, void *ptr), void *data);
41 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);
42 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);
45 LOAD_TYPE_UNKNOWN = -1,
52 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);
56 int (*send)(widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar);
61 .request_update_by_id = NULL,
62 .trigger_update_monitor = NULL,
63 .update_extra_info = NULL,
64 .add_pre_callback = NULL,
65 .del_pre_callback = NULL,
67 .get_last_ctrl_mode = NULL,
69 .alloc_canvas_with_stride = NULL,
70 .alloc_canvas_with_pixmap = NULL,
71 .type = LOAD_TYPE_UNKNOWN, /* Not initialized */
82 #define FUNC_PREFIX "widget_"
83 #define FUNC_WIDGET_SEND_UPDATED FUNC_PREFIX "send_buffer_updated"
84 #define FUNC_WIDGET_FIND_PKGNAME FUNC_PREFIX "find_pkgname"
85 #define FUNC_WIDGET_REQUEST_UPDATE_BY_ID FUNC_PREFIX "request_update_by_id"
86 #define FUNC_WIDGET_TRIGGER_UPDATE_MONITOR FUNC_PREFIX "trigger_update_monitor"
87 #define FUNC_WIDGET_UPDATE_EXTRA_INFO FUNC_PREFIX "update_extra_info"
89 #define FUNC_WIDGET_PROVIDER_APP_UPDATED FUNC_PREFIX "provider_app_send_buffer_updated_event"
91 #define FUNC_WIDGET_PROVIDER_APP_ADD_PRE_CALLBACK FUNC_PREFIX "provider_app_add_pre_callback"
92 #define FUNC_WIDGET_PROVIDER_APP_DEL_PRE_CALLBACK FUNC_PREFIX "provider_app_del_pre_callback"
93 #define FUNC_WIDGET_PROVIDER_APP_ORIENTATION FUNC_PREFIX "provider_app_get_orientation"
94 #define FUNC_WIDGET_PROVIDER_APP_LAST_CTRL_MODE FUNC_PREFIX "provider_app_get_last_ctrl_mode"
96 static inline void load_ecore_evas_function(void)
98 if (!s_info.alloc_canvas && !s_info.alloc_canvas_with_stride && !s_info.alloc_canvas_with_pixmap) {
99 s_info.alloc_canvas_with_pixmap = dlsym(RTLD_DEFAULT, "ecore_evas_gl_x11_pixmap_allocfunc_new");
100 if (!s_info.alloc_canvas_with_pixmap) {
101 DbgPrint("pixmap_allocfunc_new is not found\n");
104 s_info.alloc_canvas_with_stride = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_with_stride_new");
105 if (!s_info.alloc_canvas_with_stride) {
106 DbgPrint("allocfunc_with_stirde_new is not found\n");
109 s_info.alloc_canvas = dlsym(RTLD_DEFAULT, "ecore_evas_buffer_allocfunc_new");
110 if (!s_info.alloc_canvas) {
111 ErrPrint("allocfunc_new is not found\n");
114 if (!s_info.alloc_canvas_with_stride && !s_info.alloc_canvas && !s_info.alloc_canvas_with_pixmap) {
115 ErrPrint("No way to allocate canvas\n");
120 static inline void load_update_function(void)
122 /* Must to be checked the slave function first. */
123 s_info.binder.slave.send = dlsym(RTLD_DEFAULT, FUNC_WIDGET_SEND_UPDATED);
124 if (s_info.binder.slave.send) {
125 s_info.type = LOAD_TYPE_SLAVE;
126 DbgPrint("Slave detected\n");
128 s_info.binder.app.send = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_UPDATED);
129 if (s_info.binder.app.send) {
130 s_info.type = LOAD_TYPE_APP;
131 DbgPrint("App detected\n");
136 PUBLIC int widget_get_last_ctrl_mode(const char *id, int *cmd, int *value)
138 if (!s_info.get_last_ctrl_mode) {
139 s_info.get_last_ctrl_mode = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_LAST_CTRL_MODE);
140 if (!s_info.get_last_ctrl_mode) {
141 return WIDGET_ERROR_NOT_SUPPORTED;
145 return s_info.get_last_ctrl_mode(id, cmd, value);
148 PUBLIC int widget_get_orientation(const char *id)
150 if (!s_info.orientation) {
151 s_info.orientation = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_ORIENTATION);
152 if (!s_info.orientation) {
153 return WIDGET_ERROR_NOT_SUPPORTED;
157 return s_info.orientation(id);
160 PUBLIC int widget_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
162 if (!s_info.add_pre_callback) {
163 s_info.add_pre_callback = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_ADD_PRE_CALLBACK);
164 if (!s_info.add_pre_callback) {
165 return WIDGET_ERROR_NOT_SUPPORTED;
169 return s_info.add_pre_callback(type, cb, data);
172 PUBLIC int widget_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
174 if (!s_info.del_pre_callback) {
175 s_info.del_pre_callback = dlsym(RTLD_DEFAULT, FUNC_WIDGET_PROVIDER_APP_DEL_PRE_CALLBACK);
176 if (!s_info.del_pre_callback) {
177 return WIDGET_ERROR_NOT_SUPPORTED;
181 return s_info.del_pre_callback(type, cb, data);
184 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)
186 int ret = WIDGET_ERROR_INVALID_PARAMETER;
188 if (s_info.type == LOAD_TYPE_UNKNOWN) {
189 load_update_function();
192 if (s_info.type == LOAD_TYPE_APP) {
193 ret = s_info.binder.app.send(handle, idx, x, y, w, h, gbar);
194 } else if (s_info.type == LOAD_TYPE_SLAVE) {
196 * pkgname, id are used for finding handle of direct connection.
198 ret = s_info.binder.slave.send(pkgname, id, handle, idx, x, y, w, h, gbar, descfile);
200 widget_damage_region_s region = {
206 ret = widget_provider_send_buffer_updated(handle, idx, ®ion, gbar, descfile);
212 PUBLIC int widget_content_is_updated(const char *filename, int is_gbar)
214 if (!s_info.trigger_update_monitor) {
215 s_info.trigger_update_monitor = dlsym(RTLD_DEFAULT, FUNC_WIDGET_TRIGGER_UPDATE_MONITOR);
216 if (!s_info.trigger_update_monitor) {
217 ErrPrint("Trigger update monitor function is not exists\n");
218 return WIDGET_ERROR_FAULT;
222 return s_info.trigger_update_monitor(filename, is_gbar);
225 const char *binder_widget_find_pkgname(const char *uri)
229 if (!s_info.find_pkgname) {
230 s_info.find_pkgname = dlsym(RTLD_DEFAULT, FUNC_WIDGET_FIND_PKGNAME);
231 if (!s_info.find_pkgname) {
232 ErrPrint("Failed to find a \"widget_find_pkgname\"\n");
237 pkgname = s_info.find_pkgname(uri);
239 ErrPrint("Failed to find a package (%s)\n", uri);
246 PUBLIC int widget_request_update(const char *filename)
252 ErrPrint("Invalid argument\n");
253 return WIDGET_ERROR_INVALID_PARAMETER;
256 uri = util_id_to_uri(filename);
258 ErrPrint("Heap: %d\n", errno);
259 return WIDGET_ERROR_OUT_OF_MEMORY;
262 if (!s_info.request_update_by_id) {
263 s_info.request_update_by_id = dlsym(RTLD_DEFAULT, FUNC_WIDGET_REQUEST_UPDATE_BY_ID);
264 if (!s_info.request_update_by_id) {
265 ErrPrint("\"widget_request_update_by_id\" is not exists\n");
267 return WIDGET_ERROR_FAULT;
271 ret = s_info.request_update_by_id(uri);
276 int binder_widget_update_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
278 if (!s_info.update_extra_info) {
279 s_info.update_extra_info = dlsym(RTLD_DEFAULT, FUNC_WIDGET_UPDATE_EXTRA_INFO);
280 if (!s_info.update_extra_info) {
281 ErrPrint("Failed to find a \"widget_update_extra_info\"\n");
282 return WIDGET_ERROR_INVALID_PARAMETER;
286 return s_info.update_extra_info(id, content, title, icon, name);
291 * This callback can be called twice (or more) to get a several pixmaps
292 * Acquired pixmaps are used for double/tripple buffering for canvas
294 static Ecore_X_Pixmap alloc_pixmap_cb(void *data, Ecore_X_Window parent, int w, int h, int depth)
296 vwin_info_t info = data;
297 Ecore_X_Pixmap pixmap;
300 ErrPrint("Invalid handle\n");
306 DbgPrint("Size of ee is updated: %dx%d - %d (info: %p)\n", info->w, info->h, depth, info);
309 if (widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER) == 0u) {
312 * Need to allocate a primary buffer
314 widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, depth);
316 ErrPrint("Failed to get the buffer\n");
320 pixmap = (Ecore_X_Pixmap)widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER);
321 } else if (WIDGET_CONF_EXTRA_BUFFER_COUNT > 0) {
324 if (!info->resource_array) {
325 info->resource_array = calloc(WIDGET_CONF_EXTRA_BUFFER_COUNT, sizeof(*info->resource_array));
326 if (!info->resource_array) {
327 ErrPrint("Out of memory: %d\n", errno);
333 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
334 if (info->resource_array[idx] == 0u) {
339 if (idx == WIDGET_CONF_EXTRA_BUFFER_COUNT) {
340 ErrPrint("Out of index: %d\n", idx);
345 if (widget_viewer_acquire_buffer(info->handle, idx, info->w, info->h, depth) < 0) {
346 ErrPrint("Failed to acquire a buffer for %d\n", idx);
350 info->resource_array[idx] = widget_viewer_get_resource_id(info->handle, idx);
351 if (info->resource_array[idx] == 0u) {
352 ErrPrint("Failed to allocate pixmap\n");
355 DbgPrint("Allocated index: %d/%d - %u\n", idx, WIDGET_CONF_EXTRA_BUFFER_COUNT, info->resource_array[idx]);
356 pixmap = info->resource_array[idx];
358 ErrPrint("Unable to allocate pixmap\n");
363 * Acquire a buffer for canvas.
365 info->type = VWIN_PIXMAP;
366 info->resource_cnt += !!(unsigned int)pixmap;
370 static void free_pixmap_cb(void *data, Ecore_X_Pixmap pixmap)
372 vwin_info_t info = data;
378 if (info->type != VWIN_PIXMAP) {
379 ErrPrint("Impossible\n");
382 if (widget_viewer_get_resource_id(info->handle, WIDGET_PRIMARY_BUFFER) == pixmap) {
383 if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) {
384 DbgPrint("Failed to release buffer\n");
386 info->resource_cnt--;
390 for (idx = 0; idx < WIDGET_CONF_EXTRA_BUFFER_COUNT; idx++) {
393 * Find a index to release it
395 if (info->resource_array[idx] == pixmap) {
396 if (widget_viewer_release_buffer(info->handle, idx) < 0) {
397 DbgPrint("Failed to release buffer\n");
399 info->resource_array[idx] = 0u;
400 info->resource_cnt--;
406 if (info->flags.field.deleted && info->resource_cnt == 0) {
407 DbgPrint("Destroy buffer handle\n");
409 info->state = VWIN_INFO_DESTROYED;
410 widget_destroy_buffer(info->handle);
411 free(info->resource_array);
417 static void *alloc_fb(void *data, int size)
419 vwin_info_t info = data;
423 ecore_evas_geometry_get(info->ee, NULL, NULL, &info->w, &info->h);
424 DbgPrint("Size of ee is updated: %dx%d (info: %p)\n", info->w, info->h, info);
428 ErrPrint("Failed to create a buffer\n");
432 if (widget_viewer_acquire_buffer(info->handle, WIDGET_PRIMARY_BUFFER, info->w, info->h, sizeof(int)) < 0) {
433 ErrPrint("Failed to acquire buffer\n");
438 * If it supports the H/W accelerated buffer,
441 if (widget_support_hw_buffer(info->handle)) {
442 if (widget_create_hw_buffer(info->handle) == 0) {
443 buffer = widget_buffer_hw_buffer(info->handle);
445 DbgPrint("HW Accelerated buffer is created %p, (%dx%d)\n", info, info->w, info->h);
446 info->type = VWIN_GEM;
451 ErrPrint("Failed to allocate HW Accelerated buffer\n");
455 * Or use the buffer of a S/W backend.
457 buffer = widget_ref_buffer(info->handle);
458 DbgPrint("SW buffer is created (%dx%d)\n", info->w, info->h);
459 info->type = VWIN_SW_BUF;
463 static void *alloc_stride_fb(void *data, int size, int *stride, int *bpp)
467 buffer = alloc_fb(data, size);
469 vwin_info_t info = data;
473 _stride = widget_buffer_stride(info->handle);
475 _stride = info->w * *bpp;
480 DbgPrint("bpp: %d, stride: %d\n", *bpp, *stride);
486 static void free_fb(void *data, void *ptr)
488 vwin_info_t info = data;
494 if (info->type == VWIN_GEM) {
495 if (widget_destroy_hw_buffer(info->handle) == 0) {
496 DbgPrint("HW Accelerated buffer is destroyed\n");
498 } else if (info->type == VWIN_SW_BUF) {
499 DbgPrint("SW buffer is destroyed, %p\n", info);
500 widget_unref_buffer(ptr);
501 } else if (info->type == VWIN_PIXMAP) {
502 ErrPrint("Unable to reach to here\n");
505 if (widget_viewer_release_buffer(info->handle, WIDGET_PRIMARY_BUFFER) < 0) {
506 ErrPrint("Failed to release buffer\n");
509 if (info->flags.field.deleted) {
510 info->state = VWIN_INFO_DESTROYED;
511 widget_destroy_buffer(info->handle);
512 free(info->resource_array);
518 static inline int check_gl_engine(const char *engine)
522 * If the "engine" string going to be changed to more complicated formatted string,
523 * We should replace this with sytanx recognizer (parser).
525 return !!strcasestr(engine, GL_ENGINE);
528 Ecore_Evas *binder_ecore_evas_new(vwin_info_t info)
531 Ecore_Evas *ee = NULL;
533 load_ecore_evas_function();
535 engine = elm_config_accel_preference_get();
537 DbgPrint("Preferred engine: %s (%s or %s)\n", engine, GL_ENGINE, GL_ENGINE_X11);
538 if (engine && check_gl_engine(engine)) {
539 if (s_info.alloc_canvas_with_pixmap) {
540 ee = s_info.alloc_canvas_with_pixmap(NULL, 0u, 0, 0, info->w, info->h, alloc_pixmap_cb, free_pixmap_cb, info);
542 ErrPrint("Unable to create a ee for pixmap\n");
548 if (!widget_conf_auto_align() && s_info.alloc_canvas_with_stride) {
549 ee = s_info.alloc_canvas_with_stride(info->w, info->h, alloc_stride_fb, free_fb, info);
550 } else if (s_info.alloc_canvas) {
551 ee = s_info.alloc_canvas(info->w, info->h, alloc_fb, free_fb, info);
558 int binder_widget_auto_align(void)
560 load_ecore_evas_function();
562 return widget_conf_auto_align() || !s_info.alloc_canvas_with_stride;