2 * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "PUI_internal.h"
27 #include "PUI_backend.h"
31 static int KEY_WL_BUFFER = 0xabcdbeaf;
32 static int KEY_CLIENT = 0xdcbabeaf;
35 _cb_window_show(void *data, int type EINA_UNUSED, void *event)
37 pui_ani_h handle = (pui_ani_h)data;
38 Ecore_Wl2_Event_Window_Show *ev = (Ecore_Wl2_Event_Window_Show *)event;
46 return ECORE_CALLBACK_PASS_ON;
50 _cb_focus_in(void *data, int type EINA_UNUSED, void *event)
52 pui_ani_h handle = (pui_ani_h)data;
53 Ecore_Wl2_Event_Focus_In *ev = (Ecore_Wl2_Event_Focus_In *)event;
61 return ECORE_CALLBACK_PASS_ON;
65 _cb_focus_out(void *data, int type EINA_UNUSED, void *event)
67 pui_ani_h handle = (pui_ani_h)data;
68 Ecore_Wl2_Event_Focus_Out *ev = (Ecore_Wl2_Event_Focus_Out *)event;
76 return ECORE_CALLBACK_PASS_ON;
80 _cb_visibility_change(void *data, int type EINA_UNUSED, void *event)
82 pui_ani_h ani_h = (pui_ani_h)data;
83 pui_ani_t *ani = ani_h->ani;
84 pui_h ph = ani_h->pui_handle;
86 Ecore_Wl2_Event_Window_Visibility_Change *ev;
87 PUI_Event_Animation_Status *e = NULL;
91 pui_info("Visibility change (window=0x%x, fully_obscured=%d)\n", ev->win, ev->fully_obscured);
93 /* check if this is needed */
94 ph->visibility = !(ev->fully_obscured);
96 if (ev->fully_obscured)
98 if (ani->status == PUI_ANI_STATUS_RUNNING)
100 ani->status = PUI_ANI_STATUS_STOPPED;
102 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
106 pui_err("Failed to allocate memory for PUI Event !\n");
107 return ECORE_CALLBACK_PASS_ON;
111 e->status = PUI_ANI_STATUS_FORCE_STOPPED;
113 ecore_event_add(PUI_EVENT_ANI_STOPPED, e, NULL, ani_h);
118 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
122 pui_err("Failed to allocate memory for PUI Event !\n");
123 return ECORE_CALLBACK_PASS_ON;
127 e->status = ani->status;
129 if (ani->status == PUI_ANI_STATUS_STOPPED)
130 ecore_event_add(PUI_EVENT_ANI_READY_TO_START, e, NULL, ani_h);
131 else if(ani->status == PUI_ANI_STATUS_PAUSED)
132 ecore_event_add(PUI_EVENT_ANI_READY_TO_RESUME, e, NULL, ani_h);
135 return ECORE_CALLBACK_PASS_ON;
139 _pui_ani_cb_frame_done(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, void *data)
141 pui_h handle = (pui_h) data;
143 pui_info("Frame done ! (window=%p)\n", win);
152 _buffer_release(void *data, struct wl_buffer *buffer)
154 tbm_surface_h surface = (tbm_surface_h)data;
157 tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_CLIENT, (void **)&handle);
158 tbm_surface_queue_release(handle->tbm_queue, surface);
160 pui_info("[UPDATE] release wl_buffer:%p, surface:%p\n", buffer, surface);
163 static const struct wl_buffer_listener buffer_listener = {
167 pui_ani_control_buffer *
168 pui_ani_get_buffer(pui_ani_h ani_h)
171 tbm_surface_error_e ret;
172 tbm_surface_h surface;
173 pui_ani_control_buffer *buffer = NULL;
177 pui_err("Invalid pui ani handle !\n");
181 handle = ani_h->pui_handle;
185 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
189 if (handle->current_surface)
191 pui_warn("Current_surface is not used !\n");
194 if (!tbm_surface_queue_can_dequeue(handle->tbm_queue, 0))
196 pui_err("[UPDATE] Cannot dequeue (error : PUI_ERROR_INTERNAL)\n");
200 ret = tbm_surface_queue_dequeue(handle->tbm_queue, &surface);
202 if (ret != TBM_SURFACE_ERROR_NONE)
204 pui_err("[UPDATE] dequeue err:%d\n", ret);
208 tbm_surface_map(surface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &handle->current_sinfo);
210 handle->current_surface = surface;
211 buffer = (pui_ani_control_buffer *)&(handle->current_sinfo.planes[0]);
217 pui_ani_set_buffer(pui_ani_h ani_h, pui_ani_control_buffer *buffer)
223 pui_err("Invalid ani handle !\n");
224 return PUI_INT_ERROR_INVALID_HANDLE;
227 handle = ani_h->pui_handle;
231 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
232 return PUI_INT_ERROR_INVALID_HANDLE;
235 if (!handle->current_surface)
237 pui_err("Current_surface is not valid !\n");
238 return PUI_INT_ERROR_INVALID_SURFACE;
241 if (!buffer || !buffer->ptr || !buffer->size)
242 return PUI_INT_ERROR_INVALID_BUFFER;
244 handle->is_buffer_set = 1;
246 return PUI_INT_ERROR_NONE;
250 pui_ani_update(pui_ani_h ani_h)
252 tbm_surface_h surface;
253 tbm_surface_error_e ret;
254 struct wl_buffer *wl_buffer = NULL;
260 pui_err("Invalid ani handle !\n");
261 return PUI_INT_ERROR_INVALID_HANDLE;
264 handle = ani_h->pui_handle;
268 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
269 return PUI_INT_ERROR_INVALID_HANDLE;
272 if (!handle->current_surface)
273 return PUI_INT_ERROR_INVALID_SURFACE;
275 if (!handle->is_buffer_set)
277 pui_err("Buffer is not set !\n");
278 return PUI_INT_ERROR_INVALID_BUFFER;
281 surface = handle->current_surface;
282 handle->current_surface = NULL;
284 tbm_surface_unmap(surface);
286 ret = tbm_surface_queue_enqueue(handle->tbm_queue, surface);
288 if (ret != TBM_SURFACE_ERROR_NONE)
290 pui_err("[UPDATE] enqueue err:%d\n", ret);
291 return PUI_INT_ERROR_INVALID_SURFACE;
294 ret = tbm_surface_queue_acquire(handle->tbm_queue, &surface);
296 if (ret != TBM_SURFACE_ERROR_NONE)
298 pui_err("[UPDATE] acquire err:%d\n", ret);
299 return PUI_INT_ERROR_INVALID_SURFACE;
302 if (!tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_WL_BUFFER, (void **)&wl_buffer)) {
303 wl_buffer = wayland_tbm_client_create_buffer(handle->wl_tbm_client, surface);
307 pui_err("[UPDATE] failed to create wl_buffer tbm_surface:%p\n", surface);
308 return PUI_INT_ERROR_INVALID_BUFFER;
311 wl_buffer_add_listener(wl_buffer, &buffer_listener, surface);
313 tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_WL_BUFFER, NULL);
314 tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_WL_BUFFER, wl_buffer);
315 tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_CLIENT, NULL);
316 tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_CLIENT, handle);
321 pui_err("[UPDATE] dequeue err:%d\n", ret);
322 return PUI_INT_ERROR_INVALID_BUFFER;
325 ecore_wl2_window_buffer_attach(handle->win, wl_buffer, 0, 0, 0);
326 ecore_wl2_window_damage(handle->win, NULL, 0);
327 ecore_wl2_window_commit(handle->win, EINA_TRUE);
329 pui_info("[UPDATE] commit wl_buffer:%p, surface:%p\n", wl_buffer, surface);
331 handle->is_buffer_set = 0;
333 return PUI_INT_ERROR_NONE;
337 _pui_ani_event_handlers_init(pui_ani_h ani_h)
339 Ecore_Event_Handler *h = NULL;
343 pui_err("Invalid handle !\n");
347 if (!ani_h->ecore_event_hdls)
348 ani_h->ecore_event_hdls = eina_array_new(5);
350 h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_SHOW, _cb_window_show, ani_h);
351 eina_array_push(ani_h->ecore_event_hdls, h);
353 h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_IN, _cb_focus_in, ani_h);
354 eina_array_push(ani_h->ecore_event_hdls, h);
356 h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_OUT, _cb_focus_out, ani_h);
357 eina_array_push(ani_h->ecore_event_hdls, h);
359 h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, ani_h);
360 eina_array_push(ani_h->ecore_event_hdls, h);
365 _pui_ani_event_handlers_shutdown(pui_ani_h ani_h)
369 pui_err("Invalid handle !\n");
373 if (ani_h->ecore_event_hdls)
375 while (eina_array_count(ani_h->ecore_event_hdls))
376 ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
378 eina_array_free(ani_h->ecore_event_hdls);
379 ani_h->ecore_event_hdls = NULL;
384 _pui_ani_frame_cb(void *data)
388 pui_ani_t *ani = (pui_ani_t *)data;
392 pui_err("Invalid pui ani !\n");
393 return ECORE_CALLBACK_CANCEL;
396 if (!ani->backend_frame_cb)
398 pui_err("Invalid backend frame_cb !\n");
399 return ECORE_CALLBACK_CANCEL;
402 if (!ani->frame_cb_timer)
404 pui_err("Invalid frame_cb timer !\n");
405 return ECORE_CALLBACK_CANCEL;
408 pui_info("frame_cb !\n");
410 ret = (Eina_Bool)ani->backend_frame_cb(ani, ++ani->serial);
412 pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
418 pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial), double frame_interval)
420 Ecore_Timer *timer = NULL;
424 pui_err("Invalid put ani !\n");
428 ani->frame_cb = _pui_ani_frame_cb;
429 ani->backend_frame_cb = frame_cb;
430 ani->frame_interval = frame_interval;
431 ani->frame_cb_data = ani;
434 timer = ecore_timer_add(frame_interval, _pui_ani_frame_cb, ani);
438 pui_err("Failed to add ecore timer !\n");
442 ani->frame_cb_timer = timer;
444 /* call frame_cb for starting the first frame */
445 _pui_ani_frame_cb(ani);
451 pui_ani_remove_frame_cb(pui_ani_t *ani)
456 if (ani->frame_cb_timer)
458 ecore_timer_del(ani->frame_cb_timer);
459 ani->frame_cb_timer = NULL;
462 ani->frame_cb = NULL;
463 ani->backend_frame_cb = NULL;
464 ani->frame_interval = 0;
465 ani->frame_cb_data = NULL;
469 pui_ani_get_id(pui_ani_h ani_h)
471 if (!ani_h || !ani_h->ani)
474 return ani_h->ani->id;
478 pui_ani_get_cmd(pui_ani_h ani_h)
480 if (!ani_h || !ani_h->ani)
481 return PUI_ANI_CMD_NONE;
483 return ani_h->ani->cmd;
487 pui_ani_get_repeat(pui_ani_h ani_h)
489 if (!ani_h || !ani_h->ani)
492 return ani_h->ani->repeat;
495 pui_backend_ani_data *
496 pui_ani_get_ani_data(pui_ani_t *ani)
501 return ani->ani_data;
505 pui_ani_status_update(pui_ani_t *ani, pui_ani_status status)
507 //TODO : add PUI EVENT
509 ani->status = status;
513 pui_ani_status_get(pui_ani_t *ani)
515 pui_ani_status status = PUI_ANI_STATUS_UNKNOWN;
519 pui_err("Invalid pui ani !\n");
527 pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
529 pui_ani_t *ani = NULL;
531 pui_backend_ani_func *ani_func = NULL;
534 return PUI_ERROR_INVALID_ANI_HANDLE;
536 if (cmd < PUI_ANI_CMD_START || cmd >= PUI_ANI_CMD_LAST)
538 pui_err("Invalid cmd ! (repeat=%d)\n", repeat);
539 return PUI_ERROR_INVALID_ANI_CMD;
544 pui_err("Invalid repeat count ! (repeat=%d)\n", repeat);
545 return PUI_ERROR_INVALID_ANI_REPEAT;
548 //TODO : check if there is any animation being played already
549 //NOTE : the id of the animation being played can be different from ani_h->id
551 handle = ani_h->pui_handle;
554 if (!ani || !ani->ani_data)
556 pui_err("Invalid ani or ani_data !\n");
557 return PUI_ERROR_INTERNAL;
560 ani_func = ani->ani_data->ani_func;
563 ani->repeat = repeat;
565 if (cmd == PUI_ANI_CMD_START)
567 ani_func->ani_start(ani, repeat);
569 else//cmd == PUI_ANI_CMD_STOP
571 ani_func->ani_stop(ani);
572 return PUI_ERROR_NONE;
575 ani_h->frame_done_cb = ecore_wl2_window_frame_callback_add(handle->win, _pui_ani_cb_frame_done, handle);
577 if (!ani_h->frame_done_cb)
579 pui_err("Failed to add frame callback !");
585 return PUI_ERROR_NONE;
588 return PUI_ERROR_INTERNAL;
592 pui_ani_create(pui_h handle, pui_id id)
594 pui_ani_h ani_h = NULL;
595 pui_ani_t *ani = NULL;
596 pui_backend_ani_data *ani_data = NULL;
598 if (!handle || !handle->backend_module_data)
600 pui_err("Invalid pui handle or backend module data !\n");
604 ani_data = handle->backend_module_data->ani_create(id);
608 pui_err("Invalid ani data from backend module data !\n");
612 ani_h = (pui_ani_h)calloc(1, sizeof(pui_ani));
616 pui_err("Failed to allocate memory for pui ani handle !\n");
620 ani_h->id = strdup(id);
621 ani_h->pui_handle = handle;
622 ani_h->ecore_event_hdls = NULL;
624 _pui_ani_event_handlers_init(ani_h);
626 ani = (pui_ani_t *)calloc(1, sizeof(pui_ani_t));
630 pui_err("Failed to allocate memory for pui ani mgr !\n");
636 ani->cmd = PUI_ANI_CMD_NONE;
638 ani->status = PUI_ANI_STATUS_INITIAL;
639 ani->ani_data = ani_data;
643 handle->ani_handles = eina_list_append(handle->ani_handles, ani_h);
650 handle->backend_module_data->ani_destroy(ani_data);
660 pui_ani_destroy(pui_ani_h ani_h)
663 pui_ani_t *ani = NULL;
664 pui_backend_module_data *backend_module_data = NULL;
666 if (!ani_h || !ani_h->pui_handle)
669 handle = ani_h->pui_handle;
672 /* stop the animation being played already if any */
673 if (ani->status != PUI_ANI_STATUS_STOPPED)
674 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
676 backend_module_data = handle->backend_module_data;
677 backend_module_data->ani_destroy(ani->ani_data);
678 ani->ani_data = NULL;
680 if (ani->frame_cb_timer)
682 ecore_timer_del(ani->frame_cb_timer);
683 ani->frame_cb_timer = NULL;
688 _pui_ani_event_handlers_shutdown(ani_h);
690 if (ani_h->frame_done_cb)
692 ecore_wl2_window_frame_callback_del(ani_h->frame_done_cb);
693 ani_h->frame_done_cb = NULL;
696 handle->ani_handles = eina_list_remove(handle->ani_handles, ani_h);