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_visibility_change(void *data, int type EINA_UNUSED, void *event)
37 pui_ani_h ani_h = (pui_ani_h)data;
38 pui_ani_t *ani = ani_h->ani;
39 pui_h ph = ani_h->pui_handle;
41 Ecore_Wl2_Event_Window_Visibility_Change *ev;
42 PUI_Event_Animation_Status *e = NULL;
46 /* check if this is needed */
47 ph->visibility = !(ev->fully_obscured);
49 if (ev->fully_obscured)
51 if (ani->status == PUI_ANI_STATUS_RUNNING)
53 pui_info("animation(%s) will be stopped as it lost its priority !\n", ani->id);
55 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
60 if (ani->status == PUI_ANI_STATUS_STOPPED || ani->status == PUI_ANI_STATUS_PAUSED)
62 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
66 pui_err("Failed to allocate memory for PUI Event !\n");
67 return ECORE_CALLBACK_PASS_ON;
72 e->status = ani->status;
74 if (ani->status == PUI_ANI_STATUS_STOPPED)
76 pui_info("[Event added][ani id:%s] PUI_EVENT_ANI_READY_TO_START event has been added.\n", ani_h->id);
77 ecore_event_add(PUI_EVENT_ANI_READY_TO_START, e, NULL, ani_h);
79 else if(ani->status == PUI_ANI_STATUS_PAUSED)
81 pui_info("[Event added][ani id:%s] PUI_EVENT_ANI_READY_TO_RESUME event has been added.\n", ani_h->id);
82 ecore_event_add(PUI_EVENT_ANI_READY_TO_RESUME, e, NULL, ani_h);
87 return ECORE_CALLBACK_PASS_ON;
91 _pui_ani_cb_frame_done(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, void *data)
93 pui_h handle = (pui_h) data;
95 pui_info("Frame done ! (window=0x%x)\n", ecore_wl2_window_id_get(win));
97 /* TODO : make use of handle */
104 _buffer_release(void *data, struct wl_buffer *buffer)
106 tbm_surface_h surface = (tbm_surface_h)data;
109 tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_CLIENT, (void **)&handle);
110 tbm_surface_queue_release(handle->tbm_queue, surface);
112 pui_info("[UPDATE] release wl_buffer:%p, surface:%p\n", buffer, surface);
115 static const struct wl_buffer_listener buffer_listener = {
119 pui_ani_control_buffer *
120 pui_ani_get_buffer(pui_ani_h ani_h)
123 tbm_surface_error_e ret;
124 tbm_surface_h surface;
125 pui_ani_control_buffer *buffer = NULL;
129 pui_err("Invalid pui ani handle !\n");
133 handle = ani_h->pui_handle;
137 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
141 if (handle->current_surface)
143 pui_warn("Current_surface is not used !\n");
146 if (!tbm_surface_queue_can_dequeue(handle->tbm_queue, 0))
148 pui_err("[UPDATE] Cannot dequeue (error : PUI_ERROR_INTERNAL)\n");
152 ret = tbm_surface_queue_dequeue(handle->tbm_queue, &surface);
154 if (ret != TBM_SURFACE_ERROR_NONE)
156 pui_err("[UPDATE] dequeue err:%d\n", ret);
160 tbm_surface_map(surface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &handle->current_sinfo);
162 handle->current_surface = surface;
163 buffer = (pui_ani_control_buffer *)&(handle->current_sinfo.planes[0]);
169 pui_ani_set_buffer(pui_ani_h ani_h, pui_ani_control_buffer *buffer)
175 pui_err("Invalid ani handle !\n");
176 return PUI_INT_ERROR_INVALID_HANDLE;
179 handle = ani_h->pui_handle;
183 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
184 return PUI_INT_ERROR_INVALID_HANDLE;
187 if (!handle->current_surface)
189 pui_err("Current_surface is not valid !\n");
190 return PUI_INT_ERROR_INVALID_SURFACE;
193 if (!buffer || !buffer->ptr || !buffer->size)
194 return PUI_INT_ERROR_INVALID_BUFFER;
196 handle->is_buffer_set = 1;
198 return PUI_INT_ERROR_NONE;
202 pui_ani_update(pui_ani_h ani_h)
204 tbm_surface_h surface;
205 tbm_surface_error_e ret;
206 struct wl_buffer *wl_buffer = NULL;
212 pui_err("Invalid ani handle !\n");
213 return PUI_INT_ERROR_INVALID_HANDLE;
216 handle = ani_h->pui_handle;
220 pui_err("Error : PUI_INT_ERROR_INVALID_HANDLE\n");
221 return PUI_INT_ERROR_INVALID_HANDLE;
224 if (!handle->current_surface)
225 return PUI_INT_ERROR_INVALID_SURFACE;
227 if (!handle->is_buffer_set)
229 pui_err("Buffer is not set !\n");
230 return PUI_INT_ERROR_INVALID_BUFFER;
233 surface = handle->current_surface;
234 handle->current_surface = NULL;
236 tbm_surface_unmap(surface);
238 ret = tbm_surface_queue_enqueue(handle->tbm_queue, surface);
240 if (ret != TBM_SURFACE_ERROR_NONE)
242 pui_err("[UPDATE] enqueue err:%d\n", ret);
243 return PUI_INT_ERROR_INVALID_SURFACE;
246 ret = tbm_surface_queue_acquire(handle->tbm_queue, &surface);
248 if (ret != TBM_SURFACE_ERROR_NONE)
250 pui_err("[UPDATE] acquire err:%d\n", ret);
251 return PUI_INT_ERROR_INVALID_SURFACE;
254 if (!tbm_surface_internal_get_user_data(surface, (unsigned long)&KEY_WL_BUFFER, (void **)&wl_buffer)) {
255 wl_buffer = wayland_tbm_client_create_buffer(handle->wl_tbm_client, surface);
259 pui_err("[UPDATE] failed to create wl_buffer tbm_surface:%p\n", surface);
260 return PUI_INT_ERROR_INVALID_BUFFER;
263 wl_buffer_add_listener(wl_buffer, &buffer_listener, surface);
265 tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_WL_BUFFER, NULL);
266 tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_WL_BUFFER, wl_buffer);
267 tbm_surface_internal_add_user_data(surface, (unsigned long)&KEY_CLIENT, NULL);
268 tbm_surface_internal_set_user_data(surface, (unsigned long)&KEY_CLIENT, handle);
273 pui_err("[UPDATE] dequeue err:%d\n", ret);
274 return PUI_INT_ERROR_INVALID_BUFFER;
277 ecore_wl2_window_buffer_attach(handle->win, wl_buffer, 0, 0, 0);
278 ecore_wl2_window_damage(handle->win, NULL, 0);
279 ecore_wl2_window_commit(handle->win, EINA_TRUE);
281 pui_info("[UPDATE] commit wl_buffer:%p, surface:%p\n", wl_buffer, surface);
283 handle->is_buffer_set = 0;
285 return PUI_INT_ERROR_NONE;
289 _pui_ani_event_handlers_init(pui_ani_h ani_h)
291 Ecore_Event_Handler *h = NULL;
295 pui_err("Invalid handle !\n");
299 if (!ani_h->ecore_event_hdls)
300 ani_h->ecore_event_hdls = eina_array_new(1);
302 h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, ani_h);
303 eina_array_push(ani_h->ecore_event_hdls, h);
308 _pui_ani_event_handlers_shutdown(pui_ani_h ani_h)
312 pui_err("Invalid handle !\n");
316 if (ani_h->ecore_event_hdls)
318 while (eina_array_count(ani_h->ecore_event_hdls))
319 ecore_event_handler_del(eina_array_pop(ani_h->ecore_event_hdls));
321 eina_array_free(ani_h->ecore_event_hdls);
322 ani_h->ecore_event_hdls = NULL;
327 _pui_ani_frame_cb(void *data)
331 pui_ani_t *ani = (pui_ani_t *)data;
335 pui_err("Invalid pui ani !\n");
336 return ECORE_CALLBACK_CANCEL;
339 if (!ani->backend_frame_cb)
341 pui_err("Invalid backend frame_cb !\n");
342 return ECORE_CALLBACK_CANCEL;
345 if (!ani->frame_cb_timer)
347 pui_err("Invalid frame_cb timer !\n");
348 return ECORE_CALLBACK_CANCEL;
353 ret = (Eina_Bool)ani->backend_frame_cb(ani, ++ani->serial);
357 pui_err("Failed on backend's frame_cb !Frame_cb will be removed forcefuly !\n");
359 pui_ani_remove_frame_cb(ani);
364 if (ret && PUI_ANI_STATUS_STARTED == ani->status)
365 pui_ani_status_update(ani, PUI_ANI_STATUS_RUNNING);
371 pui_ani_add_frame_cb(pui_ani_t *ani, pui_bool (*frame_cb)(void *data, int serial), double frame_interval)
373 Ecore_Timer *timer = NULL;
377 pui_err("Invalid put ani !\n");
381 if (frame_interval <= 0.0f)
383 pui_err("Invalid frame interval (%.2f) ! frame interval must be larger than 0.\n", frame_interval);
387 ani->frame_cb = _pui_ani_frame_cb;
388 ani->backend_frame_cb = frame_cb;
389 ani->frame_interval = frame_interval;
390 ani->frame_cb_data = ani;
393 timer = ecore_timer_add(frame_interval, _pui_ani_frame_cb, ani);
397 pui_err("Failed to add ecore timer !\n");
401 ani->frame_cb_timer = timer;
403 pui_info("[Frame callback added][ani id=%s] frame_interval=%.2f\n", ani->id, frame_interval);
405 /* call frame_cb for starting the first frame */
406 _pui_ani_frame_cb(ani);
412 pui_ani_remove_frame_cb(pui_ani_t *ani)
416 pui_err("Invalid put ani !\n");
420 if (ani->frame_cb_timer)
422 ecore_timer_del(ani->frame_cb_timer);
423 ani->frame_cb_timer = NULL;
426 ani->frame_cb = NULL;
427 ani->backend_frame_cb = NULL;
428 ani->frame_interval = 0;
429 ani->frame_cb_data = NULL;
431 pui_info("[Frame callback removed][ani id=%s]\n", ani->id);
435 pui_ani_get_id(pui_ani_h ani_h)
437 if (!ani_h || !ani_h->ani)
440 return ani_h->ani->id;
444 pui_ani_get_cmd(pui_ani_h ani_h)
446 if (!ani_h || !ani_h->ani)
447 return PUI_ANI_CMD_NONE;
449 return ani_h->ani->cmd;
453 pui_ani_get_repeat(pui_ani_h ani_h)
455 if (!ani_h || !ani_h->ani)
458 return ani_h->ani->repeat;
461 pui_backend_ani_data *
462 pui_ani_get_ani_data(pui_ani_t *ani)
467 return ani->ani_data;
471 pui_ani_status_update(pui_ani_t *ani, pui_ani_status status)
475 PUI_Event_Animation_Status *e = NULL;
479 pui_err("Invalid pui ani !\n");
483 if (ani->status == status)
488 e = (PUI_Event_Animation_Status *)calloc(1, sizeof(PUI_Event_Animation_Status));
492 pui_err("Failed to allocate memory for PUI Event !\n");
496 ani->status = status;
498 e->win = ecore_wl2_window_id_get(ani_h->pui_handle->win);
503 case PUI_ANI_STATUS_STARTED:
504 ev_type = PUI_EVENT_ANI_STARTED;
505 pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STARTED event has been added.\n", ani->id);
508 case PUI_ANI_STATUS_RUNNING:
509 pui_info("[Status update][ani id:%s] PUI_ANI_STATUS_RUNNING !\n", ani->id);
512 case PUI_ANI_STATUS_PAUSED:
513 ev_type = PUI_EVENT_ANI_PAUSED;
514 pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_PAUSED event has been added.\n", ani->id);
517 case PUI_ANI_STATUS_STOPPED:
518 ev_type = PUI_EVENT_ANI_STOPPED;
519 pui_info("[Status update][ani id:%s] PUI_EVENT_ANI_STOPPED event has been added.\n", ani->id);
523 pui_err("Unknown status !(ani status=%d, id=%s) !\n", status, ani->id);
529 ecore_event_add(ev_type, e, NULL, ani_h);
534 pui_ani_status_get(pui_ani_t *ani)
536 pui_ani_status status = PUI_ANI_STATUS_UNKNOWN;
540 pui_err("Invalid pui ani !\n");
548 pui_ani_control(pui_ani_h ani_h, pui_ani_cmd cmd, int repeat)
550 pui_int_error ei = PUI_INT_ERROR_NONE;
551 pui_ani_t *ani = NULL;
553 pui_backend_ani_func *ani_func = NULL;
556 return PUI_ERROR_INVALID_ANI_HANDLE;
558 if (cmd < PUI_ANI_CMD_START || cmd >= PUI_ANI_CMD_LAST)
560 pui_err("Invalid cmd ! (cmd=%d)\n", cmd);
561 return PUI_ERROR_INVALID_ANI_CMD;
566 pui_err("Invalid repeat count ! (repeat=%d)\n", repeat);
567 return PUI_ERROR_INVALID_ANI_REPEAT;
570 handle = ani_h->pui_handle;
573 if (!ani || !ani->ani_data)
575 pui_err("Invalid ani or ani_data !\n");
576 return PUI_ERROR_INTERNAL;
579 ani_func = ani->ani_data->ani_func;
582 ani->repeat = repeat;
584 if (cmd == PUI_ANI_CMD_START)
586 if (handle->current_ani_h && handle->current_ani_h != ani_h)
588 pui_ani_t *current_ani = handle->current_ani_h->ani;
590 if (current_ani->status >= PUI_ANI_STATUS_STARTED &&
591 current_ani->status <= PUI_ANI_STATUS_RUNNING)
593 pui_info("current_ani id=%s, status=%d\n", current_ani->id, current_ani->status);
595 ei = pui_ani_control(handle->current_ani_h, PUI_ANI_CMD_STOP, 0);
597 if (ei != PUI_INT_ERROR_NONE)
598 pui_info("Failed to stop running previous animation ! (id:%s)\n", current_ani->id);
601 handle->current_ani_h = NULL;
605 ei = ani_func->ani_start(ani, repeat);
607 if (ei != PUI_INT_ERROR_NONE)
609 pui_err("Error on starting animation ! (id:%s, repeat:%d, status=%d))\n", ani->id, repeat, ani->status);
611 if (ani->status != PUI_ANI_STATUS_RUNNING)
612 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
614 return PUI_ERROR_INTERNAL;
617 handle->current_ani_h = ani_h;
619 else//cmd == PUI_ANI_CMD_STOP
621 ei = ani_func->ani_stop(ani);
623 if (ei != PUI_INT_ERROR_NONE)
625 pui_err("Failied on stopping animation ! (id:%s)\n", ani->id);
627 if (ani->status != PUI_ANI_STATUS_STOPPED)
628 pui_ani_status_update(ani, PUI_ANI_STATUS_STOPPED);
630 if (ani->frame_cb_timer)
631 pui_ani_remove_frame_cb(ani);
633 return PUI_ERROR_INTERNAL;
636 return PUI_ERROR_NONE;
639 ani_h->frame_done_cb = ecore_wl2_window_frame_callback_add(handle->win, _pui_ani_cb_frame_done, handle);
641 if (!ani_h->frame_done_cb)
643 pui_err("Failed to add frame callback !");
647 return PUI_ERROR_NONE;
650 return PUI_ERROR_INTERNAL;
654 pui_ani_create(pui_h handle, pui_id id)
656 pui_ani_h ani_h = NULL;
657 pui_ani_t *ani = NULL;
658 pui_backend_ani_data *ani_data = NULL;
660 if (!handle || !handle->backend_module_data)
662 pui_err("Invalid pui handle or backend module data !\n");
666 ani_data = handle->backend_module_data->ani_create(id);
670 pui_err("Invalid ani data from backend module data !\n");
674 ani_h = (pui_ani_h)calloc(1, sizeof(pui_ani));
678 pui_err("Failed to allocate memory for pui ani handle !\n");
682 ani_h->id = strdup(id);
683 ani_h->pui_handle = handle;
684 ani_h->ecore_event_hdls = NULL;
686 _pui_ani_event_handlers_init(ani_h);
688 ani = (pui_ani_t *)calloc(1, sizeof(pui_ani_t));
692 pui_err("Failed to allocate memory for pui ani mgr !\n");
698 ani->cmd = PUI_ANI_CMD_NONE;
700 ani->status = PUI_ANI_STATUS_INITIAL;
701 ani->ani_data = ani_data;
705 handle->ani_handles = eina_list_append(handle->ani_handles, ani_h);
712 handle->backend_module_data->ani_destroy(ani_data);
722 pui_ani_destroy(pui_ani_h ani_h)
725 pui_ani_t *ani = NULL;
726 pui_backend_module_data *backend_module_data = NULL;
728 if (!ani_h || !ani_h->pui_handle)
731 handle = ani_h->pui_handle;
734 /* stop the animation being played already if any */
735 if (ani->status == PUI_ANI_STATUS_STARTED || ani->status == PUI_ANI_STATUS_RUNNING)
736 pui_ani_control(ani_h, PUI_ANI_CMD_STOP, 0);
738 backend_module_data = handle->backend_module_data;
739 backend_module_data->ani_destroy(ani->ani_data);
740 ani->ani_data = NULL;
742 if (ani->frame_cb_timer)
744 ecore_timer_del(ani->frame_cb_timer);
745 ani->frame_cb_timer = NULL;
750 _pui_ani_event_handlers_shutdown(ani_h);
752 if (ani_h->frame_done_cb)
754 ecore_wl2_window_frame_callback_del(ani_h->frame_done_cb);
755 ani_h->frame_done_cb = NULL;
758 handle->ani_handles = eina_list_remove(handle->ani_handles, ani_h);