From 150c7dc547d810bc0db6d7c191e64c1dad5f4b8f Mon Sep 17 00:00:00 2001 From: Joogab Yun Date: Thu, 28 Dec 2017 16:06:11 +0900 Subject: [PATCH] [evas_sw_backend] 1. evas sw tbm backend implement 2. wayland_tbm_client_init / deinit in ecore_evas Change-Id: Ia605be8f0cac12b1873d82392d894b89f88543b1 --- src/Makefile_Ecore_Wl2.am | 1 + src/lib/ecore_wl2/ecore_wl2_private.h | 21 + src/lib/ecore_wl2/ecore_wl2_tbmsurface.c | 438 ++++++++++++++ src/modules/evas/engines/wayland_shm/evas_engine.h | 5 + src/modules/evas/engines/wayland_shm/evas_outbuf.c | 28 +- src/modules/evas/engines/wayland_shm/evas_tbmbuf.c | 650 --------------------- 6 files changed, 491 insertions(+), 652 deletions(-) mode change 100644 => 100755 src/Makefile_Ecore_Wl2.am mode change 100644 => 100755 src/lib/ecore_wl2/ecore_wl2_private.h create mode 100755 src/lib/ecore_wl2/ecore_wl2_tbmsurface.c delete mode 100755 src/modules/evas/engines/wayland_shm/evas_tbmbuf.c diff --git a/src/Makefile_Ecore_Wl2.am b/src/Makefile_Ecore_Wl2.am old mode 100644 new mode 100755 index fb1e787..dbe14b2 --- a/src/Makefile_Ecore_Wl2.am +++ b/src/Makefile_Ecore_Wl2.am @@ -20,6 +20,7 @@ lib/ecore_wl2/tizen-policy-ext-protocol.c \ lib/ecore_wl2/ecore_wl2_private.h \ lib/ecore_wl2/ecore_wl2_buffer.c \ lib/ecore_wl2/ecore_wl2_surface.c \ +lib/ecore_wl2/ecore_wl2_tbmsurface.c \ static_libs/libdrm/drm_fourcc.h \ static_libs/libdrm/drm.h \ static_libs/libdrm/drm_mode.h \ diff --git a/src/lib/ecore_wl2/ecore_wl2_private.h b/src/lib/ecore_wl2/ecore_wl2_private.h old mode 100644 new mode 100755 index 866f9bd..3ded1c6 --- a/src/lib/ecore_wl2/ecore_wl2_private.h +++ b/src/lib/ecore_wl2/ecore_wl2_private.h @@ -20,6 +20,12 @@ # include "tizen-policy-ext-client-protocol.h" // +// TIZEN_ONLY(20171226) : evas tbm_buf backend +#include +#include +#include +// + extern int _ecore_wl2_log_dom; extern Eina_Bool no_session_recovery; @@ -700,6 +706,20 @@ typedef struct _Buffer_Handle Buffer_Handle; typedef struct _Ecore_Wl2_Buffer { struct wl_buffer *wl_buffer; + // TIZEN_ONLY(20171226) : evas tbm_buf backend + struct wl_display *wl_display; + struct wl_surface *wl_surface; + struct wl_registry *registry; + struct wayland_tbm_client *tbm_client; + tbm_surface_h tbm_surface; + tbm_surface_info_s tbm_info; + void *tbm_queue; + int wait_release; + Eina_Bool resize : 1; + int compositor_version; + int frame_age; + // TIZEN_ONLY(20171226) : evas tbm_buf backend + int size; int w, h; int age; @@ -732,6 +752,7 @@ typedef struct _Ecore_Wl2_Surface void (*post)(Ecore_Wl2_Surface *surface, Eina_Rectangle *rects, unsigned int count); void (*flush)(Ecore_Wl2_Surface *surface); } funcs; + unsigned int frame_age; // TIZEN_ONLY(20171226) : evas tbm_buf backend } Ecore_Wl2_Surface; Ecore_Wl2_Window *_ecore_wl2_display_window_surface_find(Ecore_Wl2_Display *display, struct wl_surface *wl_surface); diff --git a/src/lib/ecore_wl2/ecore_wl2_tbmsurface.c b/src/lib/ecore_wl2/ecore_wl2_tbmsurface.c new file mode 100755 index 0000000..48a5f8d --- /dev/null +++ b/src/lib/ecore_wl2/ecore_wl2_tbmsurface.c @@ -0,0 +1,438 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "ecore_wl2_private.h" + +#include +#include +#include +#include +#include +#include +#include + +#define KEY_WINDOW (unsigned long)(&key_window) +#define KEY_WL_BUFFER (unsigned long)(&key_wl_buffer) +#define KEY_SURFACE_INFO (unsigned long)(&key_surface_info) + +static int key_window; +static int key_wl_buffer; +static int key_surface_info; + +typedef struct { + unsigned int age; + unsigned int num_surface; +} tbm_buffer_info; + + +static int tbm_queue_ref = 0; +static Eina_Bool need_to_tbm_queue = EINA_TRUE; +static void *tbm_queue; + +typedef enum +{ + MODE_FULL, + MODE_COPY, + MODE_DOUBLE, + MODE_TRIPLE, + MODE_QUADRUPLE, + MODE_AUTO +} Render_Output_Swap_Mode; + + +static void +_evas_tbmbuf_buffer_unmap(Ecore_Wl2_Buffer *surf) +{ + tbm_surface_unmap(surf->tbm_surface); +} + + +static void +_evas_tbmbuf_surface_reconfigure(Ecore_Wl2_Surface *surface, int w, int h, uint32_t flags , Eina_Bool force ) +{ + Ecore_Wl2_Buffer *surf; + + if (!surface) return; + + surf = surface->current; + + if (!surf) return; + + /* TIZEN_ONLY(20171204) : temporary patch */ + if (w < 1) w = 1; + if (h < 1) h = 1; + + if ((w >= surf->w) && (w <= surf->stride / 4) && (h == surf->h)) + { + surf->w = w; + return; + } + surf->resize = EINA_TRUE; + surf->w = w; + surf->h = h; +} + +static void +_wait_free_buffer(Ecore_Wl2_Buffer *surf) +{ + if (!surf) return; + + wl_display_dispatch_pending(surf->wl_display); + if ( tbm_surface_queue_can_dequeue(surf->tbm_queue, 0)) + return; + + DBG("WAIT free buffer"); + + while (! tbm_surface_queue_can_dequeue(surf->tbm_queue, 0)) { + wl_display_dispatch(surf->wl_display); + } +} + +static void +buffer_release(void *data, struct wl_buffer *buffer EINA_UNUSED) +{ + if (!data) return; + void *tbm_queue = NULL; + tbm_surface_h tbm_surface = data; + tbm_surface_internal_get_user_data(tbm_surface, KEY_WINDOW, (void **)&tbm_queue); + tbm_surface_internal_unref(tbm_surface); + if (tbm_queue) + { + ERR("tbm_surface_queue_release"); + tbm_surface_queue_release(tbm_queue, tbm_surface); + } +} + +static void +buffer_destroy(void *data) +{ + if (!data) return; + struct wl_buffer* buffer = data; + wl_buffer_destroy(buffer); +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + + +static int +_evas_tbmbuf_surface_assign(Ecore_Wl2_Surface *surface) +{ + Ecore_Wl2_Buffer *surf; + + Render_Output_Swap_Mode mode = MODE_FULL; + tbm_buffer_info *tbuf_info = NULL; + if (!surface) return 0; + + surf = surface->current; + if (!surf) + { + ERR("surface is NULL"); + return 0; + } + + if (surf->resize) + { + // reset tbm_surface + int width, height, format; + width = surf->w; + height = surf->h; + format = tbm_surface_queue_get_format(surf->tbm_queue); + tbm_surface_queue_reset(surf->tbm_queue, width, height, format); + surf->resize = EINA_FALSE; + } + + surf->tbm_surface = NULL; + tbm_surface_queue_error_e ret = TBM_SURFACE_QUEUE_ERROR_NONE; + struct wl_buffer *buffer; + + _wait_free_buffer(surf); + + // check num of tbm surface + int num_surface, i; + tbm_surface_h surfaces[5]; + tbm_surface_queue_get_surfaces(surf->tbm_queue, surfaces, &num_surface); + + ret = tbm_surface_queue_dequeue(surf->tbm_queue, &surf->tbm_surface); + + if (ret != TBM_SURFACE_QUEUE_ERROR_NONE || + surf->tbm_surface == NULL) { + ERR("dequeue:%p from queue:%p err:%d\n", surf->tbm_surface, surf->tbm_queue, ret); + surf->wait_release = 1; + return 0; + } + + tbm_surface_internal_ref(surf->tbm_surface); + + surf->wait_release = 0; + if(! tbm_surface_internal_get_user_data(surf->tbm_surface, KEY_WL_BUFFER, (void **)&buffer)) { + buffer = wayland_tbm_client_create_buffer(surf->tbm_client, surf->tbm_surface); + if (!buffer) + { + ERR("wayland_tbm_client_create_buffer is NULL"); + tbm_surface_internal_unref(surf->tbm_surface); + tbm_surface_queue_release(surf->tbm_queue, surf->tbm_surface); + return 0; + } + + wl_proxy_set_queue((struct wl_proxy *)buffer, NULL); + + tbm_surface_internal_add_user_data(surf->tbm_surface, KEY_WL_BUFFER, (tbm_data_free)buffer_destroy); + tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_WL_BUFFER, buffer); + + tbm_surface_internal_add_user_data(surf->tbm_surface, KEY_WINDOW, NULL); + tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_WINDOW, surf->tbm_queue); + + wl_buffer_add_listener(buffer, &buffer_listener, surf->tbm_surface); + } + + + tbm_surface_info_s info; + tbm_surface_map(surf->tbm_surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info); + surf->tbm_info = info; + + // check buffer age + if (! tbm_surface_internal_get_user_data(surf->tbm_surface, KEY_SURFACE_INFO, (void**)&tbuf_info)) { + tbuf_info = calloc(1, sizeof(tbm_buffer_info)); + if (tbuf_info) { + tbuf_info->age = 0; + tbuf_info->num_surface = num_surface; + } + tbm_surface_internal_add_user_data(surf->tbm_surface, KEY_SURFACE_INFO, free); + tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_SURFACE_INFO, tbuf_info); + } + + //reset + if (tbuf_info && (unsigned int)num_surface != tbuf_info->num_surface) + { + surface->frame_age = 0; + + for(i=0; iage = 0; + tbuf_info->num_surface = num_surface; + } + } + } + + if (!tbuf_info || !tbuf_info->age) + return MODE_FULL; + + if (tbuf_info && tbuf_info->age < surface->frame_age) + { + unsigned int diff; + diff = surface->frame_age - tbuf_info->age + 1; + if (diff > (unsigned int)num_surface) return MODE_FULL; + switch(diff) + { + case 1: + mode = MODE_COPY; + break; + case 2: + mode = MODE_DOUBLE; + break; + case 3: + mode = MODE_TRIPLE; + break; + default: + mode = MODE_FULL; + } + } + + return mode; +} + + +static void * +_evas_tbmbuf_surface_data_get(Ecore_Wl2_Surface *surface, int *w, int *h) +{ + Ecore_Wl2_Buffer *surf; + void *image; + + surf = surface->current; + if (!surf) + { + ERR("surface is NULL"); + return 0; + } + + image = surf->tbm_info.planes[0].ptr; + + surf->stride = surf->tbm_info.planes[0].stride; + if (w) *w = surf->stride / 4; + if (h) *h = surf->tbm_info.height; + + return image; +} + +void +_evas_surface_damage(struct wl_surface *s, int compositor_version, int w, int h, Eina_Rectangle *rects, unsigned int count) +{ + void (*damage)(struct wl_surface *, int32_t, int32_t, int32_t, int32_t); + unsigned int k; + + if (compositor_version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) + damage = wl_surface_damage_buffer; + else + damage = wl_surface_damage; + + if ((rects) && (count > 0)) + for (k = 0; k < count; k++) + damage(s, rects[k].x, rects[k].y, rects[k].w, rects[k].h); + else + damage(s, 0, 0, w, h); +} + + +static void +_evas_tbmbuf_surface_post(Ecore_Wl2_Surface *surface, Eina_Rectangle *rects, unsigned int count) +{ + Ecore_Wl2_Buffer *surf; + tbm_buffer_info *tbuf_info = NULL; + if (!surface) return; + + surf = surface->current; + if (!surf->wl_surface) return; + + struct wl_buffer *buffer = NULL; + + _evas_tbmbuf_buffer_unmap(surf); + + tbm_surface_internal_get_user_data(surf->tbm_surface, KEY_WL_BUFFER, (void **)&buffer); + if (!buffer) { + ERR("Enqueue:%p from queue:%p", surf->tbm_surface, surf->tbm_queue); + return; + } + + ++surface->frame_age; + tbm_surface_internal_get_user_data(surf->tbm_surface, KEY_SURFACE_INFO, (void **)&tbuf_info); + if (tbuf_info) + tbuf_info->age = surface->frame_age; + + ecore_wl2_window_buffer_attach(surface->wl2_win, buffer, 0, 0, EINA_FALSE); + + _evas_surface_damage(surf->wl_surface, surf->compositor_version, + surf->w, surf->h, rects, count); + + tbm_surface_internal_ref(surf->tbm_surface); + ecore_wl2_window_commit(surface->wl2_win, EINA_TRUE); + + tbm_surface_internal_unref(surf->tbm_surface); + tbm_surface_queue_enqueue(surf->tbm_queue, surf->tbm_surface); + + tbm_surface_queue_acquire(surf->tbm_queue, &surf->tbm_surface); + + return; +} + +static void +_evas_tbmbuf_surface_destroy(Ecore_Wl2_Surface *surface) +{ + Ecore_Wl2_Buffer *surf = NULL; + if (!surface) return; + + surf = surface->current; + if (surf) + { + if (surf->tbm_queue && tbm_queue_ref == 0) + { + if (surf->tbm_surface) + tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_WINDOW, NULL); + tbm_surface_queue_destroy(surf->tbm_queue); + need_to_tbm_queue = EINA_TRUE; + tbm_queue = NULL; + } + if (tbm_queue_ref) + --tbm_queue_ref; + free(surf); + surface->current = NULL; + } +} + +static void +_evas_tbmbuf_surface_flush(Ecore_Wl2_Surface *surface EINA_UNUSED) +{ +} + +EAPI Ecore_Wl2_Surface * +ecore_wl2_tbmbuf_surface_create(Ecore_Wl2_Window *win, Eina_Bool alpha, + struct wayland_tbm_client *tbm_client, int w, int h, int num_buff) +{ + Ecore_Wl2_Buffer *surf = NULL; + + Ecore_Wl2_Surface *out; + out = calloc(1, sizeof(*out)); + if (!out) return NULL; + if (!(surf = calloc(1, sizeof(Ecore_Wl2_Buffer)))) goto err; + + out->wl2_win = win; + out->current = surf; + /* TIZEN_ONLY(20171204) : temporary patch */ + if (w < 1) w = 1; + if (h < 1) h = 1; + + surf->w = w; + surf->h = h; + Ecore_Wl2_Display *wl2_display = ecore_wl2_window_display_get(win); + surf->wl_display = ecore_wl2_display_get(wl2_display); + surf->wl_surface = ecore_wl2_window_surface_get(win); + if (!surf->wl_surface) goto err; + surf->alpha = alpha; + surf->compositor_version = 3; + + /* get tbm_client */ + surf->tbm_client = tbm_client; + if (surf->tbm_client == NULL) { + ERR("No wayland_tbm global"); + goto err; + } + + /* check num_buff, not yet support single buffer */ + if (num_buff == 1) num_buff = 2; + + /* create surface buffers */ + if (need_to_tbm_queue) + { + tbm_queue = wayland_tbm_client_create_surface_queue(surf->tbm_client, + surf->wl_surface, + num_buff, + w, h, + TBM_FORMAT_ARGB8888); + surf->tbm_queue = tbm_queue; + need_to_tbm_queue = EINA_FALSE; + } + else + { + /* reuse tbm_queue */ + surf->tbm_queue = tbm_queue; + tbm_surface_queue_reset(surf->tbm_queue, w, h, TBM_FORMAT_ARGB8888); + + tbm_queue_ref++; + } + if (surf->tbm_queue == NULL) + { + ERR("surf->tbm_queue NULL"); + goto err; + } + surf->tbm_surface = NULL; + + + out->funcs.destroy = _evas_tbmbuf_surface_destroy; + out->funcs.reconfigure = _evas_tbmbuf_surface_reconfigure; + out->funcs.data_get = _evas_tbmbuf_surface_data_get; + out->funcs.assign = _evas_tbmbuf_surface_assign; + out->funcs.post = _evas_tbmbuf_surface_post; + out->funcs.flush = _evas_tbmbuf_surface_flush; + win->wl2_surface = out; + return out; + + err: + if (surf) + { + free(surf); + } + return NULL; +} diff --git a/src/modules/evas/engines/wayland_shm/evas_engine.h b/src/modules/evas/engines/wayland_shm/evas_engine.h index 7291b40..60422a5 100755 --- a/src/modules/evas/engines/wayland_shm/evas_engine.h +++ b/src/modules/evas/engines/wayland_shm/evas_engine.h @@ -115,6 +115,10 @@ void *_evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int void _evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); void _evas_outbuf_redraws_clear(Outbuf *ob); +// TIZEN_ONLY(20171226) : evas tbm_buf backend +Ecore_Wl2_Surface *ecore_wl2_tbmbuf_surface_create(Ecore_Wl2_Window *win, Eina_Bool alpha, + struct wayland_tbm_client *tbm_client, int w, int h, int num_buff); +// Ecore_Wl2_Surface *ecore_wl2_surface_create(Ecore_Wl2_Window *win, Eina_Bool alpha); void ecore_wl2_surface_destroy(Ecore_Wl2_Surface *surface); void ecore_wl2_surface_reconfigure(Ecore_Wl2_Surface *surface, int w, int h, uint32_t flags, Eina_Bool force); @@ -123,4 +127,5 @@ int ecore_wl2_surface_assign(Ecore_Wl2_Surface *surface); void ecore_wl2_surface_post(Ecore_Wl2_Surface *surface, Eina_Rectangle *rects, unsigned int count); + #endif diff --git a/src/modules/evas/engines/wayland_shm/evas_outbuf.c b/src/modules/evas/engines/wayland_shm/evas_outbuf.c index f5d32bb..f4a6a9d 100755 --- a/src/modules/evas/engines/wayland_shm/evas_outbuf.c +++ b/src/modules/evas/engines/wayland_shm/evas_outbuf.c @@ -27,9 +27,33 @@ _evas_outbuf_setup(int w, int h, Evas_Engine_Info_Wayland *info) ob->depth = info->info.depth; ob->priv.destination_alpha = info->info.destination_alpha; ob->ewd = ecore_wl2_window_display_get(info->info.wl2_win); + ob->surface = NULL; + + // TIZEN_ONLY(20171226) : evas tbm_buf backend + if (!getenv("EVAS_WAYLAND_USE_SHMBUF")) + { + int sw = 0; + int sh = 0; + /* try to create the outbuf surface */ + if ((ob->rotation == 0) || (ob->rotation == 180)) + { + sw = w; + sh = h; + } + else if ((ob->rotation == 90) || (ob->rotation == 270)) + { + sw = h; + sh = w; + } + ob->surface = ecore_wl2_tbmbuf_surface_create(info->info.wl2_win, ob->priv.destination_alpha, info->info.tbm_client, sw, sh, 3); + } + // fallback + if (!ob->surface) + { + ob->surface = ecore_wl2_surface_create(info->info.wl2_win, + ob->priv.destination_alpha); + } - ob->surface = ecore_wl2_surface_create(info->info.wl2_win, - ob->priv.destination_alpha); if (!ob->surface) goto surf_err; eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8); diff --git a/src/modules/evas/engines/wayland_shm/evas_tbmbuf.c b/src/modules/evas/engines/wayland_shm/evas_tbmbuf.c deleted file mode 100755 index f26c736..0000000 --- a/src/modules/evas/engines/wayland_shm/evas_tbmbuf.c +++ /dev/null @@ -1,650 +0,0 @@ -#include "evas_common_private.h" -#include "evas_private.h" -#include "evas_engine.h" - -#include -#include -#include -#include -#include - -#define KEY_WINDOW (unsigned long)(&key_window) -#define KEY_WL_BUFFER (unsigned long)(&key_wl_buffer) -#define KEY_SURFACE_INFO (unsigned long)(&key_surface_info) - - -static int key_window; -static int key_wl_buffer; -static int key_surface_info; - - - -#define __tbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ - ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) - -#define TBM_FORMAT_XRGB8888 __tbm_fourcc_code('X', 'R', '2', '4') -#define TBM_FORMAT_ARGB8888 __tbm_fourcc_code('A', 'R', '2', '4') -#define TBM_SURF_PLANE_MAX 4 /**< maximum number of the planes */ -/* option to map the tbm_surface */ -#define TBM_SURF_OPTION_READ (1 << 0) /**< access option to read */ -#define TBM_SURF_OPTION_WRITE (1 << 1) /**< access option to write */ - -typedef struct _tbm_surface * tbm_surface_h; -//typedef struct _tbm_surface_queue *tbm_surface_queue_h; -typedef uint32_t tbm_format; -typedef void (*tbm_data_free) (void *user_data); - -typedef struct _tbm_surface_plane -{ - unsigned char *ptr; /**< Plane pointer */ - uint32_t size; /**< Plane size */ - uint32_t offset; /**< Plane offset */ - uint32_t stride; /**< Plane stride */ - - void *reserved1; /**< Reserved pointer1 */ - void *reserved2; /**< Reserved pointer2 */ - void *reserved3; /**< Reserved pointer3 */ -} tbm_surface_plane_s; - -typedef struct _tbm_surface_info -{ - uint32_t width; /**< TBM surface width */ - uint32_t height; /**< TBM surface height */ - tbm_format format; /**< TBM surface format*/ - uint32_t bpp; /**< TBM surface bbp */ - uint32_t size; /**< TBM surface size */ - - uint32_t num_planes; /**< The number of planes */ - tbm_surface_plane_s planes[TBM_SURF_PLANE_MAX]; /**< Array of planes */ - - void *reserved4; /**< Reserved pointer4 */ - void *reserved5; /**< Reserved pointer5 */ - void *reserved6; /**< Reserved pointer6 */ -} tbm_surface_info_s; - - -typedef enum _queue_node_type { - QUEUE_NODE_TYPE_NONE, - QUEUE_NODE_TYPE_DEQUEUE, - QUEUE_NODE_TYPE_ENQUEUE, - QUEUE_NODE_TYPE_ACQUIRE, - QUEUE_NODE_TYPE_RELEASE -} Queue_Node_Type; - -typedef enum { - TBM_SURFACE_QUEUE_ERROR_NONE = 0, /**< Successful */ - TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE = -1, - TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE = -2, - TBM_SURFACE_QUEUE_ERROR_EMPTY = -3, - TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER = -4, - TBM_SURFACE_QUEUE_ERROR_SURFACE_ALLOC_FAILED = -5, -} tbm_surface_queue_error_e; - -typedef struct _Tbmbuf_Surface Tbmbuf_Surface; - -struct _Tbmbuf_Surface -{ - struct wl_display *wl_display; - struct wl_surface *wl_surface; - struct wl_buffer *wl_buffer; - struct wl_registry *registry; - struct wayland_tbm_client *tbm_client; - tbm_surface_h tbm_surface; - tbm_surface_info_s tbm_info; - void *tbm_queue; - int wait_release; - Eina_Bool resize : 1; - - int compositor_version; - - int w, h; - int dx, dy; - int stride; - int frame_age; - Eina_Bool alpha : 1; - -}; - - -typedef struct { - unsigned int age; - unsigned int num_surface; -} tbm_buffer_info; - - -static void *tbm_lib = NULL; -static void *tbm_client_lib = NULL; -static int tbm_ref = 0; -static int tbm_queue_ref = 0; - -static int (*sym_tbm_surface_map) (tbm_surface_h surface, int opt, tbm_surface_info_s *info) = NULL; -static int (*sym_tbm_surface_unmap) (tbm_surface_h surface) = NULL; -static int (*sym_tbm_surface_queue_can_dequeue) (void *tbm_queue, int value) = NULL; -static int (*sym_tbm_surface_queue_dequeue) (void *tbm_queue, tbm_surface_h *surface) = NULL; -static int (*sym_tbm_surface_queue_enqueue) (void *tbm_queue, tbm_surface_h surface) = NULL; -static tbm_surface_queue_error_e (*sym_tbm_surface_queue_acquire) (void *tbm_queue, tbm_surface_h *surface) = NULL; -static tbm_surface_queue_error_e (*sym_tbm_surface_queue_get_surfaces) (void *surface_queue, - tbm_surface_h *surfaces, int *num) = NULL; -static tbm_surface_queue_error_e (*sym_tbm_surface_queue_release) (void *surface_queue, tbm_surface_h surface) = NULL; -static void (*sym_tbm_surface_queue_destroy) (void *surface_queue) = NULL; -static void (*sym_tbm_surface_internal_unref) (tbm_surface_h surface) = NULL; -static void (*sym_tbm_surface_internal_ref) (tbm_surface_h surface) = NULL; -static int (*sym_tbm_surface_internal_get_user_data) (tbm_surface_h surface, unsigned long key, void **data) = NULL; -static int (*sym_tbm_surface_internal_add_user_data) (tbm_surface_h surface, unsigned long key, tbm_data_free data_free_func) = NULL; -static int (*sym_tbm_surface_internal_set_user_data) (tbm_surface_h surface, unsigned long key, void *data) = NULL; -static int (*sym_tbm_surface_queue_get_format) (void *surface_queue) = NULL; -static tbm_surface_queue_error_e (*sym_tbm_surface_queue_reset) (void *surface_queue, int width, int height, int format) = NULL; - -static struct wl_buffer * (*sym_wayland_tbm_client_create_buffer) (struct wayland_tbm_client *tbm_client, tbm_surface_h surface) = NULL; -static struct wl_tbm * (*sym_wayland_tbm_client_get_wl_tbm) (struct wayland_tbm_client *tbm_client) = NULL; -static void *(*sym_wayland_tbm_client_create_surface_queue) (struct wayland_tbm_client *tbm_client, - struct wl_surface *surface, - int queue_size, - int width, int height, tbm_format format) = NULL; - -static Eina_Bool -tbm_init(void) -{ - if (tbm_lib) - { - tbm_ref++; - return EINA_TRUE; - } - - const char *tbm_libs[] = - { - LIBDIR"/libtbm.so.1", - LIBDIR"/libtbm.so.0", - NULL, - }; - const char *tbm_clients[] = - { - LIBDIR"/libwayland-tbm-client.so.0", - NULL, - }; - int i, fail; -#define SYM(lib, xx) \ - do { \ - sym_ ## xx = dlsym(lib, #xx); \ - if (!(sym_ ## xx)) { \ - ERR("%s", dlerror()); \ - fail = 1; \ - } \ - } while (0) - - for (i = 0; tbm_libs[i]; i++) - { - tbm_lib = dlopen(tbm_libs[i], RTLD_LOCAL | RTLD_LAZY); - if (tbm_lib) - { - fail = 0; - SYM(tbm_lib, tbm_surface_map); - SYM(tbm_lib, tbm_surface_unmap); - SYM(tbm_lib, tbm_surface_queue_can_dequeue); - SYM(tbm_lib, tbm_surface_queue_dequeue); - SYM(tbm_lib, tbm_surface_queue_enqueue); - SYM(tbm_lib, tbm_surface_queue_acquire); - SYM(tbm_lib, tbm_surface_queue_get_surfaces); - SYM(tbm_lib, tbm_surface_queue_release); - SYM(tbm_lib, tbm_surface_queue_destroy); - SYM(tbm_lib, tbm_surface_internal_ref); - SYM(tbm_lib, tbm_surface_internal_unref); - SYM(tbm_lib, tbm_surface_internal_get_user_data); - SYM(tbm_lib, tbm_surface_internal_add_user_data); - SYM(tbm_lib, tbm_surface_internal_set_user_data); - SYM(tbm_lib, tbm_surface_queue_get_format); - SYM(tbm_lib, tbm_surface_queue_reset); - if (fail) - { - dlclose(tbm_lib); - tbm_lib = NULL; - } - else break; - } - } - if (!tbm_lib) return EINA_FALSE; - - for (i = 0; tbm_clients[i]; i++) - { - tbm_client_lib = dlopen(tbm_clients[i], RTLD_LOCAL | RTLD_LAZY); - if (tbm_client_lib) - { - fail = 0; - SYM(tbm_client_lib, wayland_tbm_client_get_wl_tbm); - SYM(tbm_client_lib, wayland_tbm_client_create_buffer); - SYM(tbm_client_lib, wayland_tbm_client_create_surface_queue); - if (fail) - { - dlclose(tbm_client_lib); - tbm_client_lib = NULL; - } - else break; - } - } - if (!tbm_client_lib) return EINA_FALSE; - - tbm_ref++; - return EINA_TRUE; -} - -static void -tbm_shutdown(void) -{ - if (tbm_ref > 0) - { - tbm_ref--; - - if (tbm_ref == 0) - { - if (tbm_lib) - { - dlclose(tbm_lib); - tbm_lib = NULL; - } - if (tbm_client_lib) - { - dlclose(tbm_client_lib); - tbm_client_lib = NULL; - } - } - } -} - - -static void -_evas_tbmbuf_buffer_unmap(Tbmbuf_Surface *surface) -{ - sym_tbm_surface_unmap(surface->tbm_surface); -} - - -static void -_evas_tbmbuf_surface_reconfigure(Surface *s, int w, int h, uint32_t flags, Eina_Bool force) -{ - Tbmbuf_Surface *surface; - - if (!s) return; - - surface = s->surf.tbm; - - if (!surface) return; - - /* TIZEN_ONLY(20171204) : temporary patch */ - if (w < 1) w = 1; - if (h < 1) h = 1; - - if ((w >= surface->w) && (w <= surface->stride / 4) && (h == surface->h)) - { - surface->w = w; - return; - } - surface->resize = EINA_TRUE; - surface->w = w; - surface->h = h; -} - -static void -_wait_free_buffer(Tbmbuf_Surface *surface) -{ - if (!surface) return; - - wl_display_dispatch_pending(surface->wl_display); - if (sym_tbm_surface_queue_can_dequeue(surface->tbm_queue, 0)) - return; - - DBG("WAIT free buffer"); - - while (!sym_tbm_surface_queue_can_dequeue(surface->tbm_queue, 0)) { - wl_display_dispatch(surface->wl_display); - } -} - -static void -buffer_release(void *data, struct wl_buffer *buffer EINA_UNUSED) -{ - if (!data) return; - void *tbm_queue = NULL; - tbm_surface_h tbm_surface = data; - sym_tbm_surface_internal_get_user_data(tbm_surface, KEY_WINDOW, (void **)&tbm_queue); - sym_tbm_surface_internal_unref(tbm_surface); - if (tbm_queue) - sym_tbm_surface_queue_release(tbm_queue, tbm_surface); -} - -static void -buffer_destroy(void *data) -{ - if (!data) return; - struct wl_buffer* buffer = data; - wl_buffer_destroy(buffer); -} - -static const struct wl_buffer_listener buffer_listener = { - buffer_release -}; - - -static int -_evas_tbmbuf_surface_assign(Surface *s) -{ - Tbmbuf_Surface *surface; - Render_Output_Swap_Mode mode = MODE_FULL; - tbm_buffer_info *tbuf_info = NULL; - if (!s) return 0; - - surface = s->surf.tbm; - if (!surface) - { - ERR("surface is NULL"); - return 0; - } - - if (surface->resize) - { - // reset tbm_surface - int width, height, format; - width = surface->w; - height = surface->h; - format = sym_tbm_surface_queue_get_format(surface->tbm_queue); - sym_tbm_surface_queue_reset(surface->tbm_queue, width, height, format); - surface->resize = EINA_FALSE; - } - - surface->tbm_surface = NULL; - tbm_surface_queue_error_e ret = TBM_SURFACE_QUEUE_ERROR_NONE; - struct wl_buffer *buffer; - - _wait_free_buffer(surface); - - // check num of tbm surface - int num_surface, i; - tbm_surface_h surfaces[5]; - sym_tbm_surface_queue_get_surfaces(surface->tbm_queue, surfaces, &num_surface); - - ret = sym_tbm_surface_queue_dequeue(surface->tbm_queue, &surface->tbm_surface); - - if (ret != TBM_SURFACE_QUEUE_ERROR_NONE || - surface->tbm_surface == NULL) { - ERR("dequeue:%p from queue:%p err:%d\n", surface->tbm_surface, surface->tbm_queue, ret); - surface->wait_release = 1; - return 0; - } - - sym_tbm_surface_internal_ref(surface->tbm_surface); - - surface->wait_release = 0; - if(!sym_tbm_surface_internal_get_user_data(surface->tbm_surface, KEY_WL_BUFFER, (void **)&buffer)) { - buffer = sym_wayland_tbm_client_create_buffer(surface->tbm_client, surface->tbm_surface); - if (!buffer) - { - ERR("wayland_tbm_client_create_buffer is NULL"); - sym_tbm_surface_internal_unref(surface->tbm_surface); - sym_tbm_surface_queue_release(surface->tbm_queue, surface->tbm_surface); - return 0; - } - - wl_proxy_set_queue((struct wl_proxy *)buffer, NULL); - - sym_tbm_surface_internal_add_user_data(surface->tbm_surface, KEY_WL_BUFFER, (tbm_data_free)buffer_destroy); - sym_tbm_surface_internal_set_user_data(surface->tbm_surface, KEY_WL_BUFFER, buffer); - - sym_tbm_surface_internal_add_user_data(surface->tbm_surface, KEY_WINDOW, NULL); - sym_tbm_surface_internal_set_user_data(surface->tbm_surface, KEY_WINDOW, surface->tbm_queue); - - wl_buffer_add_listener(buffer, &buffer_listener, surface->tbm_surface); - } - - - tbm_surface_info_s info; - sym_tbm_surface_map(surface->tbm_surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info); - surface->tbm_info = info; - - // check buffer age - if (!sym_tbm_surface_internal_get_user_data(surface->tbm_surface, KEY_SURFACE_INFO, (void**)&tbuf_info)) { - tbuf_info = calloc(1, sizeof(tbm_buffer_info)); - if (tbuf_info) { - tbuf_info->age = 0; - tbuf_info->num_surface = num_surface; - } - sym_tbm_surface_internal_add_user_data(surface->tbm_surface, KEY_SURFACE_INFO, free); - sym_tbm_surface_internal_set_user_data(surface->tbm_surface, KEY_SURFACE_INFO, tbuf_info); - } - - //reset - if (tbuf_info && (unsigned int)num_surface != tbuf_info->num_surface) - { - s->frame_age = 0; - - for(i=0; iage = 0; - tbuf_info->num_surface = num_surface; - } - } - } - - if (!tbuf_info || !tbuf_info->age) - return MODE_FULL; - - if (tbuf_info && tbuf_info->age < s->frame_age) - { - unsigned int diff; - diff = s->frame_age - tbuf_info->age + 1; - if (diff > (unsigned int)num_surface) return MODE_FULL; - switch(diff) - { - case 1: - mode = MODE_COPY; - break; - case 2: - mode = MODE_DOUBLE; - break; - case 3: - mode = MODE_TRIPLE; - break; - default: - mode = MODE_FULL; - } - } - return mode; -} - - -static void * -_evas_tbmbuf_surface_data_get(Surface *s, int *w, int *h) -{ - Tbmbuf_Surface *surface; - void *image; - - surface = s->surf.tbm; - if (!surface) - { - ERR("surface is NULL"); - return 0; - } - - image = surface->tbm_info.planes[0].ptr; - - surface->stride = surface->tbm_info.planes[0].stride; - if (w) *w = surface->stride / 4; - if (h) *h = surface->tbm_info.height; - - return image; -} - - - -static void -__cb_client_frame_callback(void *data EINA_UNUSED, struct wl_callback *callback, - uint32_t time EINA_UNUSED) -{ - wl_callback_destroy(callback); -} - -static const struct wl_callback_listener frame_listener = { - __cb_client_frame_callback -}; - - -static void -_evas_tbmbuf_surface_post(Surface *s, Eina_Rectangle *rects, unsigned int count, Eina_Bool hidden) -{ - Tbmbuf_Surface *surface; - struct wl_callback *frame_callback = NULL; - tbm_buffer_info *tbuf_info = NULL; - if (!s) return; - - surface = s->surf.tbm; - if (!surface->wl_surface) return; - - struct wl_buffer *buffer = NULL; - - _evas_tbmbuf_buffer_unmap(surface); - - sym_tbm_surface_internal_get_user_data(surface->tbm_surface, KEY_WL_BUFFER, (void **)&buffer); - if (!buffer) { - ERR("Enqueue:%p from queue:%p", surface->tbm_surface, surface->tbm_queue); - return; - } - - ++s->frame_age; - sym_tbm_surface_internal_get_user_data(surface->tbm_surface, KEY_SURFACE_INFO, (void **)&tbuf_info); - if (tbuf_info) - tbuf_info->age = s->frame_age; - - if (!hidden) - { - ecore_wl2_window_buffer_attach(s->info->info.wl2_win, buffer, 0, 0, EINA_FALSE); - - _evas_surface_damage(surface->wl_surface, surface->compositor_version, - surface->w, surface->h, rects, count); - } - - frame_callback = wl_surface_frame(surface->wl_surface); - wl_callback_add_listener(frame_callback, &frame_listener, surface->tbm_surface); - - sym_tbm_surface_internal_ref(surface->tbm_surface); - ecore_wl2_window_commit(s->info->info.wl2_win, EINA_TRUE); - - sym_tbm_surface_internal_unref(surface->tbm_surface); - sym_tbm_surface_queue_enqueue(surface->tbm_queue, surface->tbm_surface); - - sym_tbm_surface_queue_acquire(surface->tbm_queue, &surface->tbm_surface); - - return; -} - -static void -_evas_tbmbuf_surface_destroy(Surface *s) -{ - Tbmbuf_Surface *surf = NULL; - if (!s) return; - - surf = s->surf.tbm; - if (surf) - { - if (surf->tbm_queue && tbm_queue_ref == 0) - { - if (surf->tbm_surface) - sym_tbm_surface_internal_set_user_data(surf->tbm_surface, KEY_WINDOW, NULL); - sym_tbm_surface_queue_destroy(surf->tbm_queue); - if (s->info) s->info->info.tbm_queue = NULL; - } - if (tbm_queue_ref) - --tbm_queue_ref; - free(surf); - s->surf.tbm = NULL; - } - tbm_shutdown(); -} - -Eina_Bool -_evas_tbmbuf_surface_surface_set(Surface *s, struct wl_shm *wl_shm EINA_UNUSED, struct zwp_linux_dmabuf_v1 *wl_dmabuf) -{ - return EINA_TRUE; -} - -Eina_Bool -_evas_tbmbuf_surface_create(Surface *s, int w, int h, int num_buff) -{ - Tbmbuf_Surface *surf = NULL; - - if (!tbm_init()) - { - ERR("Could not initialize TBM!"); - goto err; - } - - if (!(s->surf.tbm = calloc(1, sizeof(Tbmbuf_Surface)))) goto err; - surf = s->surf.tbm; - - surf->dx = 0; - surf->dy = 0; - - /* TIZEN_ONLY(20171204) : temporary patch */ - if (w < 1) w = 1; - if (h < 1) h = 1; - - surf->w = w; - surf->h = h; - surf->wl_display = ecore_wl2_display_get(s->info->info.wl2_display); - surf->wl_surface = ecore_wl2_window_surface_get(s->info->info.wl2_win); - if (!surf->wl_surface) goto err; - surf->alpha = s->info->info.destination_alpha; - surf->compositor_version = 3; - - /* get tbm_client */ - surf->tbm_client = s->info->info.tbm_client; - if (surf->tbm_client == NULL) { - ERR("No wayland_tbm global"); - goto err; - } - - /* check num_buff, not yet support single buffer */ - if (num_buff == 1) num_buff = 2; - - /* create surface buffers */ - if (!s->info->info.tbm_queue) - { - s->info->info.tbm_queue = sym_wayland_tbm_client_create_surface_queue(surf->tbm_client, - surf->wl_surface, - num_buff, - w, h, - TBM_FORMAT_ARGB8888); - surf->tbm_queue = s->info->info.tbm_queue; - } - else - { - /* reuse tbm_queue */ - surf->tbm_queue = s->info->info.tbm_queue; - sym_tbm_surface_queue_reset(surf->tbm_queue, w, h, TBM_FORMAT_ARGB8888); - - tbm_queue_ref++; - } - if (surf->tbm_queue == NULL) { - ERR("surf->tbm_queue NULL"); - goto err; - } - surf->tbm_surface = NULL; - - s->type = SURFACE_TBM; - s->funcs.destroy = _evas_tbmbuf_surface_destroy; - s->funcs.reconfigure = _evas_tbmbuf_surface_reconfigure; - s->funcs.data_get = _evas_tbmbuf_surface_data_get; - s->funcs.assign = _evas_tbmbuf_surface_assign; - s->funcs.post = _evas_tbmbuf_surface_post; - s->funcs.surface_set = _evas_tbmbuf_surface_surface_set; - - - - return EINA_TRUE; - -err: - if (surf) - { - free(surf); - s->surf.tbm = NULL; - } - return EINA_FALSE; -} -- 2.7.4