--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_wl2_private.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <wayland-client.h>
+#include <wayland-tbm-client.h>
+#include <tbm_surface_internal.h>
+
+#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; i<num_surface; i++) {
+ tbm_surface_internal_get_user_data(surfaces[i], KEY_SURFACE_INFO, (void **)&tbuf_info);
+ if (tbuf_info) {
+ tbuf_info->age = 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;
+}
+++ /dev/null
-#include "evas_common_private.h"
-#include "evas_private.h"
-#include "evas_engine.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dlfcn.h>
-#include <wayland-client.h>
-
-#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; i<num_surface; i++) {
- sym_tbm_surface_internal_get_user_data(surfaces[i], KEY_SURFACE_INFO, (void **)&tbuf_info);
- if (tbuf_info) {
- tbuf_info->age = 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;
-}