ecore-buffer: Add intial ecore-buffer library 97/39397/10
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 14 May 2015 10:29:24 +0000 (19:29 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Mon, 18 May 2015 11:22:09 +0000 (04:22 -0700)
Change-Id: Ie1a7bef8f5d31ab45814f4682cb7ee4c1c0efc46

25 files changed:
Makefile.am
configure.ac
packaging/efl.spec
pc/ecore-buffer.pc.in [new file with mode: 0644]
src/Makefile.am
src/Makefile_Ecore_Buffer.am [new file with mode: 0644]
src/examples/ecore/Makefile.am
src/examples/ecore/ecore_buffer_example.c [new file with mode: 0644]
src/lib/ecore_buffer/Ecore_Buffer.h [new file with mode: 0644]
src/lib/ecore_buffer/Ecore_Buffer_Queue.h [new file with mode: 0644]
src/lib/ecore_buffer/bq_mgr_protocol.c [new file with mode: 0644]
src/lib/ecore_buffer/bq_mgr_protocol.h [new file with mode: 0644]
src/lib/ecore_buffer/buffer_queue.c [new file with mode: 0644]
src/lib/ecore_buffer/buffer_queue.h [new file with mode: 0644]
src/lib/ecore_buffer/ecore_buffer.c [new file with mode: 0644]
src/lib/ecore_buffer/ecore_buffer_connection.c [new file with mode: 0644]
src/lib/ecore_buffer/ecore_buffer_connection.h [new file with mode: 0644]
src/lib/ecore_buffer/ecore_buffer_consumer.c [new file with mode: 0644]
src/lib/ecore_buffer/ecore_buffer_private.h [new file with mode: 0644]
src/lib/ecore_buffer/ecore_buffer_provider.c [new file with mode: 0644]
src/lib/ecore_buffer/shared_buffer.c [new file with mode: 0644]
src/lib/ecore_buffer/shared_buffer.h [new file with mode: 0644]
src/modules/ecore_buffer/tbm/ecore_buffer_tbm.c [new file with mode: 0644]
src/modules/ecore_buffer/x11_dri2/ecore_buffer_x11_dri2.c [new file with mode: 0644]
src/modules/ecore_buffer/x11_dri3/ecore_buffer_x11_dri3.c [new file with mode: 0644]

index 2b00391..6bc5b05 100644 (file)
@@ -140,6 +140,7 @@ pc/ecore-imf.pc \
 pc/ecore-imf-evas.pc \
 pc/ecore-evas.pc \
 pc/ecore-avahi.pc \
+pc/ecore-buffer.pc \
 pc/embryo.pc \
 pc/eio.pc \
 pc/eldbus.pc \
index 96ccd7a..7892f2c 100644 (file)
@@ -1556,6 +1556,17 @@ AC_ARG_ENABLE([tile-rotate],
   ],
   [have_tile_rotate="no"])
 
+# Ecore_Buffer
+AC_ARG_ENABLE([ecore-buffer],
+   [AS_HELP_STRING([--enable-ecore-buffer],[Enable ecore-buffer. @<:@default=disabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_ecore_buffer="yes"
+    else
+       want_ecore_buffer="no"
+    fi
+  ],
+  [want_ecore_buffer="no"])
 
 # Image Loaders
 
@@ -4486,6 +4497,77 @@ AC_ARG_ENABLE([i-really-know-what-i-am-doing-and-that-this-will-probably-break-t
    ],
    [ BARF_OK="xno" ])
 
+#### Ecore_Buffer
+build_ecore_buffer_x11_dri2="no"
+build_ecore_buffer_x11_dri3="no"
+build_ecore_buffer_tbm="no"
+EFL_LIB_START_OPTIONAL([Ecore_Buffer], [test "${want_ecore_buffer}" = "yes"])
+### Checks for libraries
+EFL_INTERNAL_DEPEND_PKG([ECORE_BUFFER], [eina])
+EFL_INTERNAL_DEPEND_PKG([ECORE_BUFFER], [ecore])
+EFL_INTERNAL_DEPEND_PKG([ECORE_BUFFER], [eo])
+EFL_INTERNAL_DEPEND_PKG([ECORE_BUFFER], [ecore-x])
+EFL_DEPEND_PKG([ECORE_BUFFER], [WAYLAND],
+               [wayland-client >= 1.5.0])
+EFL_EVAL_PKGS([ECORE_BUFFER])
+
+tbm_version="1.1.0"
+drm_version="2.4.35"
+PKG_CHECK_MODULES([X11_DRI_COMMON],
+   [
+      libtbm >= ${tbm_version},
+      libdrm >= ${drm_version}
+   ],
+   [have_x11_dri_common_pkgs="yes"],
+   [have_x11_dri_common_pkgs="no"]
+)
+
+if test "x$have_x11_dri_common_pkgs" = "xyes" ; then
+   PKG_CHECK_MODULES([X11_DRI2], [libdri2],
+                     [have_x11_dri2_pkgs="yes"],
+                     [have_x11_dri2_pkgs="no"])
+
+   PKG_CHECK_MODULES([X11_DRI3],
+      [
+         xshmfence,
+         xcb,
+         x11-xcb,
+         xcb-sync,
+         xcb-dri3
+      ],
+      [have_x11_dri3_pkgs="yes"],
+      [have_x11_dri3_pkgs="no"])
+fi
+
+PKG_CHECK_MODULES([TBM], [libtbm >= ${tbm_version}],
+                  [have_tbm="yes"],
+                  [have_tbm="no"])
+
+if test "x${have_x11_dri2_pkgs}" = "xyes" ; then
+   build_ecore_buffer_x11_dri2="yes"
+   AC_DEFINE(BUILD_ECORE_BUFFER_X11_DRI2, 1, [Support for X11_DRI2 Backend in Ecore_Buffer])
+fi
+EFL_ADD_FEATURE([ECORE_BUFFER], [x11_dri2], [${build_ecore_buffer_x11_dri2}])
+
+if test "x${have_x11_dri3_pkgs}" = "xyes" ; then
+   build_ecore_buffer_x11_dri3="yes"
+   AC_DEFINE(BUILD_ECORE_BUFFER_X11_DRI3, 1, [Support for X11_DRI3 Backend in Ecore_Buffer])
+fi
+EFL_ADD_FEATURE([ECORE_BUFFER], [x11_dri3], [${build_ecore_buffer_x11_dri3}])
+
+if test "x${have_tbm}" = "xyes" ; then
+   build_ecore_buffer_tbm="yes"
+   AC_DEFINE(BUILD_ECORE_BUFFER_TBM, 1, [Support for TBM Backend in Ecore_Buffer])
+fi
+EFL_ADD_FEATURE([ECORE_BUFFER], [tbm], [${build_ecore_buffer_tbm}])
+
+EFL_LIB_END_OPTIONAL([Ecore_Buffer])
+
+AM_CONDITIONAL([BUILD_ECORE_BUFFER_X11_DRI2], [test "${build_ecore_buffer_x11_dri2}" = "yes"])
+AM_CONDITIONAL([BUILD_ECORE_BUFFER_X11_DRI3], [test "${build_ecore_buffer_x11_dri3}" = "yes"])
+AM_CONDITIONAL([BUILD_ECORE_BUFFER_TBM], [test "${build_ecore_buffer_tbm}" = "yes"])
+
+#### End of Ecore_Buffer
 
 AC_CONFIG_FILES([
 Makefile
@@ -4565,6 +4647,7 @@ pc/ecore-imf-evas.pc
 pc/ecore-audio.pc
 pc/ecore-audio-cxx.pc
 pc/ecore-avahi.pc
+pc/ecore-buffer.pc
 pc/embryo.pc
 pc/eio.pc
 pc/eldbus.pc
@@ -4715,6 +4798,7 @@ echo "Ecore_X.........: ${with_x11} (${features_ecore_x})"
 echo "Ecore_SDL.......: $want_sdl"
 echo "Ecore_Wayland...: $want_wayland"
 echo "IVI-Shell.......: $want_wayland_ivi_shell"
+echo "Ecore_Buffer....: $want_ecore_buffer (${features_ecore_buffer})"
 if test "${have_linux}" = "yes"; then
 echo "Ecore_FB........: $want_fb (${features_ecore_fb})"
 elif test "${have_ps3}" = "yes"; then
index 2fef807..c619fd5 100644 (file)
@@ -83,6 +83,20 @@ BuildRequires:  libudev-devel
 BuildRequires:  libmount-devel
 BuildRequires:  pkgconfig(dlog)
 
+#ecore_buffer
+%if %{with x}
+BuildRequires:  pkgconfig(libdri2)
+BuildRequires:  pkgconfig(xshmfence)
+BuildRequires:  pkgconfig(x11)
+BuildRequires:  pkgconfig(xcb)
+BuildRequires:  pkgconfig(xcb-sync)
+BuildRequires:  pkgconfig(xcb-dri3)
+%endif
+BuildRequires:  pkgconfig(libtbm)
+BuildRequires:  pkgconfig(libdrm)
+BuildRequires:  pkgconfig(wayland-client)
+BuildRequires:  pkgconfig(wayland-server)
+
 ############ efl
 Provides: efl-data
 Obsoletes: efl-data
@@ -596,6 +610,7 @@ CFLAGS+=" -DMESA_EGL_NO_X11_HEADERS "
     --enable-always-build-examples \
     --enable-systemd \
     --enable-lua-old \
+    --enable-ecore-buffer \
     --enable-i-really-know-what-i-am-doing-and-that-this-will-probably-break-things-and-i-will-fix-them-myself-and-send-patches-aba
 
 
@@ -804,6 +819,7 @@ grep --silent ECORE_IMF_MODULE "$f" \
 %{_libdir}/libecore_input_evas.so.*
 %{_libdir}/libecore_ipc.so.*
 %{_libdir}/libecore_fb.so.*
+%{_libdir}/libecore_buffer.so.*
 %if %{with wayland}
 %{_libdir}/libecore_wayland.so.*
 %{_libdir}/libecore_drm.so.*
@@ -815,6 +831,7 @@ grep --silent ECORE_IMF_MODULE "$f" \
 %{_libdir}/ecore_evas/engines/*/*/module.so
 %{_libdir}/ecore_imf/modules/*/*/module.so
 %{_libdir}/ecore/system/systemd/v-*/module.so
+%{_libdir}/ecore_buffer/modules/*/*/module.so
 %{_datadir}/ecore/checkme
 %{_datadir}/ecore_*/checkme
 
@@ -842,6 +859,7 @@ grep --silent ECORE_IMF_MODULE "$f" \
 %{_libdir}/libecore_input_evas.so
 %{_libdir}/libecore_ipc.so
 %{_libdir}/libecore_fb.so
+%{_libdir}/libecore_buffer.so
 %if %{with wayland}
 %{_libdir}/libecore_wayland.so
 %{_libdir}/libecore_drm.so
diff --git a/pc/ecore-buffer.pc.in b/pc/ecore-buffer.pc.in
new file mode 100644 (file)
index 0000000..a23a2a4
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-buffer
+Description: E core library, graphic buffer module
+Requires.private: @requirements_pc_ecore_buffer@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_buffer
+Libs.private: @requirements_libs_ecore_buffer@
+Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/ecore-buffer-@VMAJ@
index b0b4884..ea541b0 100644 (file)
@@ -60,6 +60,7 @@ include Makefile_Ecore_Audio.am
 include Makefile_Ecore_IMF.am
 include Makefile_Ecore_IMF_Evas.am
 include Makefile_Ecore_Evas.am
+include Makefile_Ecore_Buffer.am
 include Makefile_EPhysics.am
 include Makefile_Edje.am
 include Makefile_Emotion.am
diff --git a/src/Makefile_Ecore_Buffer.am b/src/Makefile_Ecore_Buffer.am
new file mode 100644 (file)
index 0000000..d2e95cd
--- /dev/null
@@ -0,0 +1,103 @@
+if HAVE_ECORE_BUFFER
+
+### Library
+
+lib_LTLIBRARIES += lib/ecore_buffer/libecore_buffer.la
+
+installed_ecorebuffermainheadersdir = $(includedir)/ecore-buffer-@VMAJ@
+dist_installed_ecorebuffermainheaders_DATA = \
+lib/ecore_buffer/Ecore_Buffer.h \
+lib/ecore_buffer/Ecore_Buffer_Queue.h
+
+lib_ecore_buffer_libecore_buffer_la_SOURCES = \
+lib/ecore_buffer/bq_mgr_protocol.c \
+lib/ecore_buffer/buffer_queue.c \
+lib/ecore_buffer/shared_buffer.c \
+lib/ecore_buffer/ecore_buffer.c \
+lib/ecore_buffer/ecore_buffer_connection.c \
+lib/ecore_buffer/ecore_buffer_provider.c \
+lib/ecore_buffer/ecore_buffer_consumer.c
+
+lib_ecore_buffer_libecore_buffer_la_CPPFLAGS = \
+-I$(top_builddir)/src/lib/efl \
+-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \
+-DPACKAGE_LIB_DIR=\"$(libdir)\" \
+@ECORE_BUFFER_CFLAGS@
+
+lib_ecore_buffer_libecore_buffer_la_LIBADD = @ECORE_BUFFER_LIBS@
+lib_ecore_buffer_libecore_buffer_la_DEPENDENCIES = @ECORE_BUFFER_INTERNAL_LIBS@
+lib_ecore_buffer_libecore_buffer_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
+
+### Backends
+if BUILD_ECORE_BUFFER_X11_DRI2
+ecorebufferx11dri2dir = $(libdir)/ecore_buffer/modules/x11_dri2/$(MODULE_ARCH)
+ecorebufferx11dri2_LTLIBRARIES = modules/ecore_buffer/x11_dri2/module.la
+
+modules_ecore_buffer_x11_dri2_module_la_SOURCES = \
+   modules/ecore_buffer/x11_dri2/ecore_buffer_x11_dri2.c
+modules_ecore_buffer_x11_dri2_module_la_CPPFLAGS = \
+   -I$(top_builddir)/src/lib/efl \
+   @ECORE_BUFFER_CFLAGS@ \
+   @X11_DRI_COMMON_CFLAGS@ \
+   @X11_DRI2_CFLAGS@ \
+   -I$(top_srcdir)/src/modules/ecore_buffer/x11_dri2
+modules_ecore_buffer_x11_dri2_module_la_LIBADD = \
+   @ECORE_BUFFER_LIBS@ \
+   @USE_ECORE_BUFFER_INTERNAL_LIBS@ \
+   @X11_DRI_COMMON_LIBS@ \
+   @X11_DRI2_LIBS@
+modules_ecore_buffer_x11_dri2_module_la_DEPENDENCIES = \
+   @USE_ECORE_X_INTERNAL_LIBS@ \
+   @USE_ECORE_BUFFER_INTERNAL_LIBS@
+modules_ecore_buffer_x11_dri2_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_ecore_buffer_x11_dri2_module_la_LIBTOOLFLAGS = --tag=disable-static
+endif
+
+if BUILD_ECORE_BUFFER_X11_DRI3
+ecorebufferx11dri3dir = $(libdir)/ecore_buffer/modules/x11_dri3/$(MODULE_ARCH)
+ecorebufferx11dri3_LTLIBRARIES = modules/ecore_buffer/x11_dri3/module.la
+
+modules_ecore_buffer_x11_dri3_module_la_SOURCES = \
+   modules/ecore_buffer/x11_dri3/ecore_buffer_x11_dri3.c
+modules_ecore_buffer_x11_dri3_module_la_CPPFLAGS = \
+   -I$(top_builddir)/src/lib/efl \
+   @ECORE_BUFFER_CFLAGS@ \
+   @X11_DRI_COMMON_CFLAGS@ \
+   @X11_DRI3_CFLAGS@ \
+   -I$(top_srcdir)/src/modules/ecore_buffer/x11_dri3
+modules_ecore_buffer_x11_dri3_module_la_LIBADD = \
+   @ECORE_BUFFER_LIBS@ \
+   @USE_ECORE_BUFFER_INTERNAL_LIBS@ \
+   @X11_DRI_COMMON_LIBS@ \
+   @X11_DRI3_LIBS@
+modules_ecore_buffer_x11_dri3_module_la_DEPENDENCIES = \
+   @USE_ECORE_X_INTERNAL_LIBS@ \
+   @USE_ECORE_BUFFER_INTERNAL_LIBS@
+modules_ecore_buffer_x11_dri3_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_ecore_buffer_x11_dri3_module_la_LIBTOOLFLAGS = --tag=disable-static
+endif
+
+if BUILD_ECORE_BUFFER_TBM
+ecorebuffertbmdir = $(libdir)/ecore_buffer/modules/tbm/$(MODULE_ARCH)
+ecorebuffertbm_LTLIBRARIES = modules/ecore_buffer/tbm/module.la
+
+modules_ecore_buffer_tbm_module_la_SOURCES = \
+   modules/ecore_buffer/tbm/ecore_buffer_tbm.c
+modules_ecore_buffer_tbm_module_la_CPPFLAGS = \
+   -I$(top_builddir)/src/lib/efl \
+   @ECORE_BUFFER_CFLAGS@ \
+   @TBM_CFLAGS@ \
+   -I$(top_srcdir)/src/modules/ecore_buffer/tbm
+modules_ecore_buffer_tbm_module_la_LIBADD = \
+   @ECORE_BUFFER_LIBS@ \
+   @USE_ECORE_BUFFER_INTERNAL_LIBS@ \
+   @TBM_LIBS@
+modules_ecore_buffer_tbm_module_la_DEPENDENCIES = \
+   @USE_ECORE_X_INTERNAL_LIBS@ \
+   @USE_ECORE_BUFFER_INTERNAL_LIBS@
+modules_ecore_buffer_tbm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_ecore_buffer_tbm_module_la_LIBTOOLFLAGS = --tag=disable-static
+endif
+
+endif
+
index b3e0883..dbc06fe 100644 (file)
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
 -I$(top_srcdir)/src/lib/ecore_con \
 -I$(top_srcdir)/src/lib/ecore_evas \
 -I$(top_srcdir)/src/lib/ecore_audio \
+-I$(top_srcdir)/src/lib/ecore_buffer \
 -I$(top_builddir)/src/lib/eina \
 -I$(top_builddir)/src/lib/eo \
 -I$(top_builddir)/src/lib/evas \
@@ -27,6 +28,7 @@ AM_CPPFLAGS = \
 -I$(top_builddir)/src/lib/ecore_evas \
 -I$(top_builddir)/src/lib/ecore_audio \
 -DPACKAGE_EXAMPLES_DIR=\".\" \
+-I$(top_builddir)/src/lib/ecore_buffer \
 @ECORE_CFLAGS@
 
 EXTRA_PROGRAMS = \
@@ -65,7 +67,8 @@ ecore_server_bench \
 ecore_thread_example \
 ecore_time_functions_example \
 ecore_timer_example \
-ecore_getopt_example
+ecore_getopt_example \
+ecore_buffer_example
 
 ECORE_COMMON_LDADD = \
 $(top_builddir)/src/lib/ecore/libecore.la \
@@ -102,6 +105,10 @@ ECORE_CON_COMMON_LDADD = \
 $(top_builddir)/src/lib/ecore_con/libecore_con.la \
 $(ECORE_COMMON_LDADD)
 
+ECORE_BUFFER_COMMON_LDADD = \
+$(top_builddir)/src/lib/ecore_buffer/libecore_buffer.la \
+$(ECORE_COMMON_LDADD)
+
 ecore_animator_example_SOURCES = ecore_animator_example.c
 ecore_animator_example_LDADD = $(ECORE_EVAS_COMMON_LDADD)
 
@@ -234,6 +241,9 @@ ecore_timer_example_LDADD = $(ECORE_COMMON_LDADD)
 ecore_getopt_example_SOURCES = ecore_getopt_example.c
 ecore_getopt_example_LDADD = $(ECORE_COMMON_LDADD)
 
+ecore_buffer_example_SOURCES = ecore_buffer_example.c
+ecore_buffer_example_LDADD = $(ECORE_BUFFER_COMMON_LDADD)
+
 SRCS = \
 ecore_animator_example.c \
 ecore_client_bench.c \
@@ -273,7 +283,8 @@ ecore_server_bench.c \
 ecore_thread_example.c \
 ecore_time_functions_example.c \
 ecore_timer_example.c \
-ecore_getopt_example.c
+ecore_getopt_example.c \
+ecore_buffer_example.c
 
 if HAVE_ECORE_AUDIO
 #SRCS += \
diff --git a/src/examples/ecore/ecore_buffer_example.c b/src/examples/ecore/ecore_buffer_example.c
new file mode 100644 (file)
index 0000000..47075e5
--- /dev/null
@@ -0,0 +1,530 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Buffer.h>
+#include <Ecore_Buffer_Queue.h>
+
+#define EBQ_NAME  "bq-simple-demo-test"
+
+#define DEBUG 1
+
+#if DEBUG
+#define LOGC(f, x...) printf("Consumer (" f ")\n", ##x)
+#define LOGCR(f, x...) printf("Consumer ---> Request(" f ")\n", ##x)
+#define LOGCE(f, x...) printf("Consumer <=== Notify(" f ")\n", ##x)
+#define LOGP(f, x...) printf("Provider (" f ")\n", ##x)
+#define LOGPR(f, x...) printf("Provider ---> Request(" f ")\n", ##x)
+#define LOGPE(f, x...) printf("Provider <=== Notify(" f ")\n", ##x)
+#else
+#define LOGC(f, x...)
+#define LOGCR(f, x...)
+#define LOGCE(f, x...)
+#define LOGP(f, x...)
+#define LOGPR(f, x...)
+#define LOGPE(f, x...)
+#endif
+
+/******* Common *******/
+static int test_count = 0;
+int test_count_limit;
+static int consumer_pid = -1;
+static Ecore_Event_Handler *sig_handler;
+
+static Eina_Bool
+init_all(void)
+{
+   if (!eina_init())
+     goto err_eina;
+
+   if (!ecore_init())
+     goto err_ecore;
+
+   if (!ecore_buffer_init())
+     goto err_buffer;
+
+   if (!ecore_buffer_queue_init())
+     goto err_ebq;
+
+   return EINA_TRUE;
+err_ebq:
+   ecore_buffer_shutdown();
+err_buffer:
+   ecore_shutdown();
+err_ecore:
+   eina_shutdown();
+err_eina:
+   return EINA_FALSE;
+}
+
+static void
+shutdown_all(void)
+{
+   ecore_buffer_queue_shutdown();
+
+   ecore_buffer_shutdown();
+
+   ecore_shutdown();
+   eina_shutdown();
+}
+
+static Eina_Bool
+_simple_demo_cb_signal_exit(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
+{
+   ecore_main_loop_quit();
+
+   return ECORE_CALLBACK_DONE;
+}
+
+/******* Provider *******/
+typedef struct _Provider_Data
+{
+   Ecore_Buffer_Provider *provider;
+   Ecore_Buffer *buffer;
+
+   unsigned int w, h;
+
+   Ecore_Job *render_job;
+   Ecore_Idle_Enterer *post_render;
+} Provider_Data;
+
+static Provider_Data *_simple_demo_provider_new(const char *name);
+static void           _simple_demo_provider_shutdown(Provider_Data *pd);
+static void           _simple_demo_provider_render_queue(Provider_Data *pd);
+static void           _simple_demo_provider_run(Provider_Data *pd);
+Ecore_Buffer         *_simple_demo_provider_buffer_get(Ecore_Buffer_Provider *provider, unsigned int w, unsigned int h, unsigned int format);
+
+static Eina_Bool      _simple_demo_provider_cb_post_render(void *data);
+static void           _simple_demo_provider_cb_render_job(void *data);
+
+static void
+_simple_demo_provider_callback_set(Provider_Data *pd,
+                                   Ecore_Buffer_Provider_Consumer_Add_Cb consumer_add,
+                                   Ecore_Buffer_Provider_Consumer_Del_Cb consumer_del,
+                                   Ecore_Buffer_Provider_Enqueue_Cb buffer_released)
+{
+   ecore_buffer_provider_consumer_add_cb_set(pd->provider, consumer_add, pd);
+   ecore_buffer_provider_consumer_del_cb_set(pd->provider, consumer_del, pd);
+   ecore_buffer_provider_buffer_released_cb_set(pd->provider, buffer_released, pd);
+}
+
+static Provider_Data *
+_simple_demo_provider_new(const char *name)
+{
+   Provider_Data *pd;
+
+   LOGP("Startup");
+
+   if (!init_all())
+     goto err;
+
+   pd = (Provider_Data *)calloc(sizeof(Provider_Data), 1);
+
+   if (!(pd->provider = ecore_buffer_provider_new(name)))
+     {
+        LOGP("ERR");
+        goto err_provider;
+     }
+
+   return pd;
+err_provider:
+   shutdown_all();
+err:
+   return NULL;
+}
+
+static void
+_simple_demo_provider_shutdown(Provider_Data *pd)
+{
+   if (pd->buffer) ecore_buffer_free(pd->buffer);
+   if (pd->provider) ecore_buffer_provider_free(pd->provider);
+   if (pd->render_job) ecore_job_del(pd->render_job);
+   if (pd->post_render) ecore_idle_enterer_del(pd->post_render);
+   free(pd);
+}
+
+static void
+_simple_demo_provider_run(Provider_Data *pd)
+{
+   ecore_main_loop_begin();
+
+   _simple_demo_provider_shutdown(pd);
+   shutdown_all();
+   LOGP("Shutdown");
+   exit(EXIT_SUCCESS);
+}
+
+Eina_Bool
+_simple_demo_provider_cb_post_render(void *data)
+{
+   Provider_Data *pd = (Provider_Data *)data;
+   Ecore_Buffer *next_buffer = NULL;
+
+   LOGP("Startup - Post Render");
+
+   LOGPR("Submit Buffer - buffer: %p", pd->buffer);
+   ecore_buffer_provider_buffer_enqueue(pd->provider, pd->buffer);
+   pd->buffer = NULL;
+
+   next_buffer = _simple_demo_provider_buffer_get(pd->provider, pd->w, pd->h, ECORE_BUFFER_FORMAT_XRGB8888);
+   if (next_buffer)
+     {
+        LOGP("Drawable Buffer is Existed, ADD Render job again - buffer:%p", next_buffer);
+        pd->buffer = next_buffer;
+        _simple_demo_provider_render_queue(pd);
+     }
+
+   ecore_idle_enterer_del(pd->post_render);
+   pd->post_render = NULL;
+
+   LOGP("Done - Post Render");
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_simple_demo_provider_cb_render_job(void *data)
+{
+   Provider_Data *pd = (Provider_Data *)data;
+
+   LOGP("Startup - Render");
+
+   if (!pd->buffer)
+     {
+        pd->buffer = _simple_demo_provider_buffer_get(pd->provider,
+                                                      pd->w, pd->h, ECORE_BUFFER_FORMAT_XRGB8888);
+     }
+
+   if (pd->buffer)
+     {
+        LOGP("Success to get Drawable Buffer, Drawing now... - buffer:%p", pd->buffer);
+        // Drawing...
+
+        if (!pd->post_render)
+          {
+             pd->post_render =
+                ecore_idle_enterer_before_add(_simple_demo_provider_cb_post_render, pd);
+          }
+     }
+
+   ecore_job_del(pd->render_job);
+   pd->render_job = NULL;
+
+   LOGP("Done - Render");
+}
+
+static void
+_simple_demo_provider_render_queue(Provider_Data *pd)
+{
+   if (!pd) return;
+
+   LOGP("Render Queue");
+
+   if (!pd->render_job)
+     pd->render_job = ecore_job_add(_simple_demo_provider_cb_render_job, pd);
+}
+
+Ecore_Buffer *
+_simple_demo_provider_buffer_get(Ecore_Buffer_Provider *provider, unsigned int w, unsigned int h, unsigned int format)
+{
+   Ecore_Buffer *buffer = NULL;
+   Ecore_Buffer_Return ret;
+   unsigned int res_w, res_h, res_format;
+
+   LOGPR("Dequeue");
+   ret = ecore_buffer_provider_buffer_acquire(provider, &buffer);
+
+   if (ret == ECORE_BUFFER_RETURN_NEED_ALLOC)
+     {
+        buffer = ecore_buffer_new(NULL, w, h, format, 0);
+        LOGP("No buffer in Queue, Create Buffer");
+     }
+   else if (ret == ECORE_BUFFER_RETURN_SUCCESS)
+     {
+        ecore_buffer_size_get(buffer, &res_w, &res_h);
+        res_format = ecore_buffer_format_get(buffer);
+
+        if ((res_w != w) || (res_h != h) || (res_format != format))
+          {
+             LOGP("Need to Reallocate Buffer, Free it First: %p", buffer);
+             ecore_buffer_free(buffer);
+
+             buffer = ecore_buffer_new(NULL, w, h, format, 0);
+             LOGP("Create Buffer: %p", buffer);
+          }
+     }
+
+   return buffer;
+}
+
+static void
+_simple_demo_cb_consumer_add(Ecore_Buffer_Provider *provider EINA_UNUSED, int queue_size, int w, int h, void *data)
+{
+   Provider_Data *pd = (Provider_Data *)data;
+
+   LOGPE("Connected with Consumer, Now We can use Ecore_Buffer_Queue - queue_size:%d, geo(%dx%d)",
+       queue_size, w, h);
+
+   pd->w = w;
+   pd->h = h;
+
+   _simple_demo_provider_render_queue(pd);
+}
+
+static void
+_simple_demo_cb_consumer_del(Ecore_Buffer_Provider *provider EINA_UNUSED, void *data)
+{
+   LOGPE("Disconnected with Consumer, End of Ecore_Buffer_Queue");
+
+   (void)provider;
+   (void)data;
+   ecore_main_loop_quit();
+}
+
+static void
+_simple_demo_cb_provider_buffer_released(Ecore_Buffer_Provider *provider EINA_UNUSED, void *data)
+{
+   Provider_Data *pd = (Provider_Data *)data;
+
+   LOGPE("Buffer Enqueued : Count %d\n", test_count);
+
+   test_count++;
+   if (test_count > test_count_limit)
+     {
+        printf("Done Buffer Queue job - count: %d\n", test_count);
+        ecore_main_loop_quit();
+        return;
+     }
+
+   _simple_demo_provider_render_queue(pd);
+}
+
+/******* Consumer *******/
+typedef struct _Consumer_Data
+{
+   Ecore_Buffer_Consumer *consumer;
+   Ecore_Buffer *buffer;
+
+   Ecore_Job *render_job;
+   Ecore_Idle_Enterer *post_render;
+} Consumer_Data;
+
+static Consumer_Data *_simple_demo_consumer_new(const char *name, int32_t queue_size, int32_t w, int32_t h);
+static void           _simple_demo_consumer_shutdown(Consumer_Data *cd);
+static void           _simple_demo_consumer_run(Consumer_Data *cd);
+static void           _simple_demo_consumer_render_queue(Consumer_Data *cd);
+
+static Eina_Bool      _simple_demo_consumer_cb_post_render(void *data);
+static void           _simple_demo_consumer_cb_render_job(void *data);
+static void           _simple_demo_cb_provider_add(Ecore_Buffer_Consumer *consumer, void *data);
+static void           _simple_demo_cb_provider_del(Ecore_Buffer_Consumer *consumer, void *data);
+static void           _simple_demo_cb_consumer_enqueued(Ecore_Buffer_Consumer *consumer, void *data);
+
+static void
+_simple_demo_consumer_callback_set(Consumer_Data *cd,
+                                   Ecore_Buffer_Consumer_Provider_Add_Cb provider_add,
+                                   Ecore_Buffer_Consumer_Provider_Del_Cb provider_del,
+                                   Ecore_Buffer_Consumer_Enqueue_Cb enqueued)
+{
+   ecore_buffer_consumer_provider_add_cb_set(cd->consumer, provider_add, cd);
+   ecore_buffer_consumer_provider_del_cb_set(cd->consumer, provider_del, cd);
+   ecore_buffer_consumer_buffer_enqueued_cb_set(cd->consumer, enqueued, cd);
+}
+
+static Consumer_Data *
+_simple_demo_consumer_new(const char *name, int32_t queue_size, int32_t w, int32_t h)
+{
+   Consumer_Data *cd;
+
+   LOGC("Startup");
+   if (!init_all())
+     {
+        LOGC("Failed to init");
+        goto end;
+     }
+
+   cd = (Consumer_Data *)calloc(sizeof(Consumer_Data), 1);
+
+   if (!(cd->consumer = ecore_buffer_consumer_new(name, queue_size, w, h)))
+     {
+        goto err_consumer;
+        LOGC("Failed to create consumer");
+     }
+
+   return cd;
+err_consumer:
+   shutdown_all();
+end:
+   return NULL;
+}
+
+static void
+_simple_demo_consumer_shutdown(Consumer_Data *cd)
+{
+   if (cd->buffer) ecore_buffer_free(cd->buffer);
+   if (cd->consumer) ecore_buffer_consumer_free(cd->consumer);
+   if (cd->render_job) ecore_job_del(cd->render_job);
+   if (cd->post_render) ecore_idle_enterer_del(cd->post_render);
+   free(cd);
+}
+
+static void
+_simple_demo_consumer_run(Consumer_Data *cd)
+{
+   ecore_main_loop_begin();
+
+   _simple_demo_consumer_shutdown(cd);
+   shutdown_all();
+   LOGC("Shutdown");
+}
+
+static Eina_Bool
+_simple_demo_consumer_cb_post_render(void *data)
+{
+   Consumer_Data *cd = (Consumer_Data *)data;
+   Ecore_Buffer *next_buffer;
+
+   LOGC("Startup - Post Render");
+
+   LOGCR("Release Buffer - buffer: %p", cd->buffer);
+   ecore_buffer_consumer_buffer_release(cd->consumer, cd->buffer);
+   cd->buffer = NULL;
+
+   if ((next_buffer = ecore_buffer_consumer_buffer_dequeue(cd->consumer)))
+     {
+        LOGC("Drawable Buffer is Existed, ADD Render job again - buffer:%p", next_buffer);
+        cd->buffer = next_buffer;
+        _simple_demo_consumer_render_queue(cd);
+     }
+
+   ecore_idle_enterer_del(cd->post_render);
+   cd->post_render = NULL;
+
+   LOGC("Done - Post Render");
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_simple_demo_consumer_cb_render_job(void *data)
+{
+   Consumer_Data *cd = (Consumer_Data *)data;
+   Ecore_Buffer *buffer;
+
+   LOGC("Startup - Render");
+
+   if (!cd->buffer)
+     {
+        if ((buffer = ecore_buffer_consumer_buffer_dequeue(cd->consumer)))
+            cd->buffer = buffer;
+     }
+
+   if (cd->buffer)
+     {
+        LOGC("Success to get Compositable Buffer, "
+             "Drawing it to Consumer's Canvas now... - buffer:%p", cd->buffer);
+        // Drawing...
+
+        if (!cd->post_render)
+          {
+             cd->post_render =
+                ecore_idle_enterer_before_add(_simple_demo_consumer_cb_post_render, cd);
+          }
+     }
+
+   ecore_job_del(cd->render_job);
+   cd->render_job = NULL;
+
+   LOGC("Done - Render");
+}
+
+static void
+_simple_demo_consumer_render_queue(Consumer_Data *cd)
+{
+   if (!cd) return;
+
+   LOGC("Render Queue");
+
+   if (!cd->render_job)
+     cd->render_job = ecore_job_add(_simple_demo_consumer_cb_render_job, cd);
+}
+
+static void
+_simple_demo_cb_provider_add(Ecore_Buffer_Consumer *consumer, void *data)
+{
+   LOGCE("Connected with Provider");
+
+   (void)consumer;
+   (void)data;
+}
+
+static void
+_simple_demo_cb_provider_del(Ecore_Buffer_Consumer *consumer, void *data)
+{
+   LOGCE("Disconnected with Provider");
+
+   (void)consumer;
+   (void)data;
+
+   ecore_main_loop_quit();
+}
+
+static void
+_simple_demo_cb_consumer_enqueued(Ecore_Buffer_Consumer *consumer EINA_UNUSED, void *data)
+{
+   Consumer_Data *cd = (Consumer_Data *)data;
+
+   LOGCE("Buffer Enqueued");
+
+   _simple_demo_consumer_render_queue(cd);
+}
+
+int
+main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
+{
+   Provider_Data *pd;
+   char *str;
+
+   consumer_pid = fork();
+   if (consumer_pid == -1)
+     return -1;
+
+   if (consumer_pid == 0)
+     {
+        Consumer_Data *cd;
+
+        if (!(cd = _simple_demo_consumer_new(EBQ_NAME, 3, 123, 456)))
+          return -1;
+
+        _simple_demo_consumer_callback_set(cd,
+                                           _simple_demo_cb_provider_add,
+                                           _simple_demo_cb_provider_del,
+                                           _simple_demo_cb_consumer_enqueued);
+        _simple_demo_consumer_run(cd);
+     }
+
+   if (!(pd = _simple_demo_provider_new(EBQ_NAME)))
+     return -1;
+
+   str = getenv("TEST_LIMIT");
+   if (!str)
+     test_count_limit = 1000;
+   else
+     test_count_limit = atoi(str);
+
+   sig_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT,
+                                         _simple_demo_cb_signal_exit,
+                                         NULL);
+
+   _simple_demo_provider_callback_set(pd,
+                                      _simple_demo_cb_consumer_add,
+                                      _simple_demo_cb_consumer_del,
+                                      _simple_demo_cb_provider_buffer_released);
+
+   _simple_demo_provider_run(pd);
+
+   return 0;
+}
diff --git a/src/lib/ecore_buffer/Ecore_Buffer.h b/src/lib/ecore_buffer/Ecore_Buffer.h
new file mode 100644 (file)
index 0000000..92203c6
--- /dev/null
@@ -0,0 +1,638 @@
+#ifndef _ECORE_BUFFER_H_
+# define _ECORE_BUFFER_H_
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_BUFFER_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUFFER_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+/**
+ * @defgroup Ecore_Buffer_Group Ecore_Buffer - Graphics buffer functions
+ * @ingroup Ecore
+ *
+ * The Ecore Buffer is an abstraction of graphic buffer. This library allows to
+ * programmer using graphic buffer without having to worry about buffer's back-
+ * ends.
+ *
+ * This library also provides simple mechanisms for sharing graphic buffer bet-
+ * ween processes using wayland socket. Ecore Buffer Queue is for this
+ * function, and it consists of two main object,
+ * The Ecore_Buffer_Consumer and the Ecore_Buffer_Provider.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __ecore_buffer_fourcc_code(a,b,c,d) ((unsigned int)(a) | ((unsigned int)(b) << 8) | \
+                  ((unsigned int)(c) << 16) | ((unsigned int)(d) << 24))
+
+/* color index */
+/**
+ * @brief Definition for the Ecore_Buffer format C8 ([7:0] C little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_C8       __ecore_buffer_fourcc_code('C', '8', ' ', ' ')
+/* 8 bpp RGB */
+/**
+ * @brief Definition for the Ecore_Buffer format RGB332 ([7:0] R:G:B 3:3:2 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGB332   __ecore_buffer_fourcc_code('R', 'G', 'B', '8')
+/**
+ * @brief Definition for the Ecore_Buffer format RGB233 ([7:0] B:G:R 2:3:3 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGR233   __ecore_buffer_fourcc_code('B', 'G', 'R', '8')
+/* 16 bpp RGB */
+/**
+ * @brief Definition for the Ecore_Buffer format XRGB4444 ([15:0] x:R:G:B 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XRGB4444 __ecore_buffer_fourcc_code('X', 'R', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format XBRG4444 ([15:0] x:B:G:R 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XBGR4444 __ecore_buffer_fourcc_code('X', 'B', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBX4444 ([15:0] R:G:B:x 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBX4444 __ecore_buffer_fourcc_code('R', 'X', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRX4444 ([15:0] B:G:R:x 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRX4444 __ecore_buffer_fourcc_code('B', 'X', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format ARGB4444 ([15:0] A:R:G:B 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ARGB4444 __ecore_buffer_fourcc_code('A', 'R', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format ABGR4444 ([15:0] A:B:G:R 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ABGR4444 __ecore_buffer_fourcc_code('A', 'B', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBA4444 ([15:0] R:G:B:A 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBA4444 __ecore_buffer_fourcc_code('R', 'A', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRA4444 ([15:0] B:G:R:A 4:4:4:4 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRA4444 __ecore_buffer_fourcc_code('B', 'A', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format XRGB1555 ([15:0] x:R:G:B 1:5:5:5 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XRGB1555 __ecore_buffer_fourcc_code('X', 'R', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format XBGR1555 ([15:0] x:B:G:R 1:5:5:5 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XBGR1555 __ecore_buffer_fourcc_code('X', 'B', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBX5551 ([15:0] R:G:B:x 5:5:5:1 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBX5551 __ecore_buffer_fourcc_code('R', 'X', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRX5551 ([15:0] B:G:R:x 5:5:5:1 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRX5551 __ecore_buffer_fourcc_code('B', 'X', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format ARGB1555 ([15:0] A:R:G:B 1:5:5:5 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ARGB1555 __ecore_buffer_fourcc_code('A', 'R', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format ABGR1555 ([15:0] A:B:G:R 1:5:5:5 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ABGR1555 __ecore_buffer_fourcc_code('A', 'B', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBA5551 ([15:0] R:G:B:A 5:5:5:1 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBA5551 __ecore_buffer_fourcc_code('R', 'A', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRA5551 ([15:0] B:G:R:A 5:5:5:1 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRA5551 __ecore_buffer_fourcc_code('B', 'A', '1', '5')
+/**
+ * @brief Definition for the Ecore_Buffer format RGB565 ([15:0] R:G:B 5:6:5 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGB565   __ecore_buffer_fourcc_code('R', 'G', '1', '6')
+/**
+ * @brief Definition for the Ecore_Buffer format BGR565 ([15:0] B:G:R 5:6:5 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGR565   __ecore_buffer_fourcc_code('B', 'G', '1', '6')
+/* 24 bpp RGB */
+/**
+ * @brief Definition for the Ecore_Buffer format RGB888 ([23:0] R:G:B little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGB888   __ecore_buffer_fourcc_code('R', 'G', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format BGR888 ([23:0] B:G:R little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGR888   __ecore_buffer_fourcc_code('B', 'G', '2', '4')
+/* 32 bpp RGB */
+/**
+ * @brief Definition for the Ecore_Buffer format XRGB8888 ([31:0] x:R:G:B 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XRGB8888 __ecore_buffer_fourcc_code('X', 'R', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format XBGR8888 ([31:0] x:B:G:R 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XBGR8888 __ecore_buffer_fourcc_code('X', 'B', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBX8888 ([31:0] R:G:B:x 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBX8888 __ecore_buffer_fourcc_code('R', 'X', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRX8888 ([31:0] B:G:R:x 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRX8888 __ecore_buffer_fourcc_code('B', 'X', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format ARGB8888 ([31:0] A:R:G:B 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ARGB8888 __ecore_buffer_fourcc_code('A', 'R', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format ABGR8888 ([31:0] [31:0] A:B:G:R 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ABGR8888 __ecore_buffer_fourcc_code('A', 'B', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBA8888 ([31:0] R:G:B:A 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBA8888 __ecore_buffer_fourcc_code('R', 'A', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRA8888 ([31:0] B:G:R:A 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRA8888 __ecore_buffer_fourcc_code('B', 'A', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format XRGB2101010 ([31:0] x:R:G:B 2:10:10:10 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XRGB2101010  __ecore_buffer_fourcc_code('X', 'R', '3', '0')
+/**
+ * @brief Definition for the Ecore_Buffer format XBGR2101010 ([31:0] x:B:G:R 2:10:10:10 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_XBGR2101010  __ecore_buffer_fourcc_code('X', 'B', '3', '0')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBX1010102 ([31:0] R:G:B:x 10:10:10:2 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBX1010102  __ecore_buffer_fourcc_code('R', 'X', '3', '0')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRX1010102 ([31:0] B:G:R:x 10:10:10:2 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRX1010102  __ecore_buffer_fourcc_code('B', 'X', '3', '0')
+/**
+ * @brief Definition for the Ecore_Buffer format ARGB2101010 ([31:0] A:R:G:B 2:10:10:10 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ARGB2101010  __ecore_buffer_fourcc_code('A', 'R', '3', '0')
+/**
+ * @brief Definition for the Ecore_Buffer format ABGR2101010 ([31:0] A:B:G:R 2:10:10:10 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_ABGR2101010  __ecore_buffer_fourcc_code('A', 'B', '3', '0')
+/**
+ * @brief Definition for the Ecore_Buffer format RGBA1010102 ([31:0] R:G:B:A 10:10:10:2 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_RGBA1010102  __ecore_buffer_fourcc_code('R', 'A', '3', '0')
+/**
+ * @brief Definition for the Ecore_Buffer format BGRA1010102 ([31:0] B:G:R:A 10:10:10:2 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_BGRA1010102  __ecore_buffer_fourcc_code('B', 'A', '3', '0')
+/* packed YCbCr */
+/**
+ * @brief Definition for the Ecore_Buffer format YUYV ([31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YUYV     __ecore_buffer_fourcc_code('Y', 'U', 'Y', 'V')
+/**
+ * @brief Definition for the Ecore_Buffer format YVYU ([31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YVYU     __ecore_buffer_fourcc_code('Y', 'V', 'Y', 'U')
+/**
+ * @brief Definition for the Ecore_Buffer format UYVY ([31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_UYVY     __ecore_buffer_fourcc_code('U', 'Y', 'V', 'Y')
+/**
+ * @brief Definition for the Ecore_Buffer format VYUY ([31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_VYUY     __ecore_buffer_fourcc_code('V', 'Y', 'U', 'Y')
+/**
+ * @brief Definition for the Ecore_Buffer format AYUV ([31:0] A:Y:Cb:Cr 8:8:8:8 little endian).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_AYUV     __ecore_buffer_fourcc_code('A', 'Y', 'U', 'V')
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [7:0] Y
+ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
+ * or
+ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
+ */
+/**
+ * @brief Definition for the Ecore_Buffer format NV12 (2x2 subsampled Cr:Cb plane).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_NV12     __ecore_buffer_fourcc_code('N', 'V', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format NV21 (2x2 subsampled Cb:Cr plane).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_NV21     __ecore_buffer_fourcc_code('N', 'V', '2', '1')
+/**
+ * @brief Definition for the Ecore_Buffer format NV16 (2x1 subsampled Cr:Cb plane).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_NV16     __ecore_buffer_fourcc_code('N', 'V', '1', '6')
+/**
+ * @brief Definition for the Ecore_Buffer format NV61 (2x1 subsampled Cb:Cr plane).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_NV61     __ecore_buffer_fourcc_code('N', 'V', '6', '1')
+/*
+ * 3 plane YCbCr
+ * index 0: Y plane, [7:0] Y
+ * index 1: Cb plane, [7:0] Cb
+ * index 2: Cr plane, [7:0] Cr
+ * or
+ * index 1: Cr plane, [7:0] Cr
+ * index 2: Cb plane, [7:0] Cb
+ */
+/**
+ * @brief Definition for the Ecore_Buffer format YUV410 (4x4 subsampled Cb (1) and Cr (2) planes).
+ */
+#define ECORE_BUFFER_FORMAT_YUV410   __ecore_buffer_fourcc_code('Y', 'U', 'V', '9')
+/**
+ * @brief Definition for the Ecore_Buffer format YVU410 (4x4 subsampled Cr (1) and Cb (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YVU410   __ecore_buffer_fourcc_code('Y', 'V', 'U', '9')
+/**
+ * @brief Definition for the Ecore_Buffer format YUV411 (4x1 subsampled Cb (1) and Cr (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YUV411   __ecore_buffer_fourcc_code('Y', 'U', '1', '1')
+/**
+ * @brief Definition for the Ecore_Buffer format YVU411 (4x1 subsampled Cr (1) and Cb (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YVU411   __ecore_buffer_fourcc_code('Y', 'V', '1', '1')
+/**
+ * @brief Definition for the Ecore_Buffer format YUV420 (2x2 subsampled Cb (1) and Cr (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YUV420   __ecore_buffer_fourcc_code('Y', 'U', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format YVU420 (2x2 subsampled Cr (1) and Cb (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YVU420   __ecore_buffer_fourcc_code('Y', 'V', '1', '2')
+/**
+ * @brief Definition for the Ecore_Buffer format YUV422 (2x1 subsampled Cb (1) and Cr (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YUV422   __ecore_buffer_fourcc_code('Y', 'U', '1', '6')
+/**
+ * @brief Definition for the Ecore_Buffer format YVU422 (2x1 subsampled Cr (1) and Cb (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YVU422   __ecore_buffer_fourcc_code('Y', 'V', '1', '6')
+/**
+ * @brief Definition for the Ecore_Buffer format YUV444 (non-subsampled Cb (1) and Cr (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YUV444   __ecore_buffer_fourcc_code('Y', 'U', '2', '4')
+/**
+ * @brief Definition for the Ecore_Buffer format YVU444 (non-subsampled Cr (1) and Cb (2) planes).
+ * @since_tizen 2.4
+ */
+#define ECORE_BUFFER_FORMAT_YVU444   __ecore_buffer_fourcc_code('Y', 'V', '2', '4')
+
+/**
+ * @defgroup Ecore_Buffer_Lib_Group Ecore Buffer Library Functions
+ * @ingroup Ecore_Buffer_Group
+ *
+ * Utility functions that set up and shut down the Ecore Buffer library.
+ * This group of functions is applied to an Ecore_Buffer object.
+ *
+ * @{
+ */
+
+/**
+ * @typedef Ecore_Buffer
+ * An object representing a graphic buffer.
+ * @since_tizen 2.4
+ */
+typedef struct _Ecore_Buffer Ecore_Buffer;
+/**
+ * @typedef Ecore_Buffer_Backend
+ * The interfaces for backend of buffer.
+ * @since_tizen 2.4
+ */
+typedef struct _Ecore_Buffer_Backend Ecore_Buffer_Backend;
+/**
+ * @typedef Ecore_Export_Type
+ * Types for export buffer.
+ * @since_tizen 2.4
+ */
+typedef enum _Ecore_Export_Type Ecore_Export_Type;
+/**
+ * @typedef Ecore_Buffer_Format
+ * The format of Ecore_Buffer.
+ * @since_tizen 2.4
+ */
+typedef unsigned int Ecore_Buffer_Format;
+/**
+ * @typedef Ecore_Buffer_Pixmap
+ * An Id of Pixmap.
+ * @since_tizen 2.4
+ */
+typedef unsigned long Ecore_Pixmap;
+/**
+ * @typedef Ecore_Buffer_Module_Data
+ * The data of module.
+ * @since_tizen 2.4
+ */
+typedef void *Ecore_Buffer_Module_Data;
+/**
+ * @typedef Ecore_Buffer_Data
+ * The data of Ecore_Buffer.
+ * @since_tizen 2.4
+ */
+typedef void *Ecore_Buffer_Data;
+/**
+ * @typedef Ecore_Buffer_Cb
+ * Called whenever Ecore_Buffer is freed.
+ * @since_tizen 2.4
+ */
+typedef void (*Ecore_Buffer_Cb)(Ecore_Buffer* buf, void* data);
+
+/**
+ * @enum _Ecore_Export_Type
+ * Types for export buffer.
+ * @since_tizen 2.4
+ */
+enum _Ecore_Export_Type
+{
+   EXPORT_TYPE_INVALID,
+   EXPORT_TYPE_ID,
+   EXPORT_TYPE_FD
+};
+
+/**
+ * @struct _Ecore_Buffer_Backend
+ * @brief Structure used when initializing Ecore Buffer Backend. This structure
+ * is mainly used by modules implementing the Ecore Buffer Backend interface.
+ * @since_tizen 2.4
+ */
+struct _Ecore_Buffer_Backend
+{
+   const char *name; /**< The name of backend */
+
+   Ecore_Buffer_Module_Data    (*init)(const char *context, const char *options); /**< Initialize the backend */
+   void                        (*shutdown)(Ecore_Buffer_Module_Data bmPriv); /**< Shut down the backend */
+   Ecore_Buffer_Data           (*buffer_alloc)(Ecore_Buffer_Module_Data bmPriv,
+                                               int width, int height,
+                                               Ecore_Buffer_Format format,
+                                               unsigned int flags); /**< Newly allocate memory for buffer */
+   Ecore_Buffer_Data           (*buffer_alloc_with_tbm_surface)(Ecore_Buffer_Module_Data bmPriv,
+                                                                void *tbm_surface,
+                                                                int *ret_w, int *ret_h,
+                                                                Ecore_Buffer_Format *ret_format,
+                                                                unsigned int flags); /**< Create Ecore_Buffer from existed tbm_surface handle. */
+   void                        (*buffer_free)(Ecore_Buffer_Module_Data bmPriv,
+                                              Ecore_Buffer_Data priv); /**< Free allocated memory */
+   Ecore_Export_Type           (*buffer_export)(Ecore_Buffer_Module_Data bmPriv,
+                                                Ecore_Buffer_Data priv, int *id); /**< Get the id or fd of Ecore_Buffer for exporting it */
+   Ecore_Buffer_Data           (*buffer_import)(Ecore_Buffer_Module_Data bmPriv,
+                                                int w, int h,
+                                                Ecore_Buffer_Format format,
+                                                Ecore_Export_Type type,
+                                                int export_id,
+                                                unsigned int flags); /**< Import and create Ecore_Buffer from id or fd */
+   Ecore_Pixmap                (*pixmap_get)(Ecore_Buffer_Module_Data bmPriv,
+                                             Ecore_Buffer_Data priv); /**< Get the pixmap handle */
+   void                       *(*tbm_surface_get)(Ecore_Buffer_Module_Data bmPriv,
+                                                  Ecore_Buffer_Data priv); /**< Get the tbm_surface_h handle */
+};
+
+/**
+ * @brief Initialize the Ecore_Buffer system.
+ *
+ * @since_tizen 2.4
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ecore_buffer_shutdown()
+ */
+EAPI Eina_Bool     ecore_buffer_init(void);
+/**
+ * @brief Shut down the Ecore_Buffer system.
+ *
+ * @since_tizen 2.4
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ecore_buffer_init()
+ */
+EAPI Eina_Bool     ecore_buffer_shutdown(void);
+/**
+ * @brief Registers the given buffer backend.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] be The backend
+ *
+ * @return @c EINA_TRUE if backend has been correctly registered, @c EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool     ecore_buffer_register(Ecore_Buffer_Backend *be);
+/**
+ * @brief Unregisters the given buffer backend.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] be The backend
+ */
+EAPI void          ecore_buffer_unregister(Ecore_Buffer_Backend *be);
+/**
+ * @brief Creates a new Ecore_Buffer given type
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] engine the name of backend
+ * @param[in] width width for Ecore_Buffer
+ * @param[in] height height for Ecore_Buffer
+ * @param[in] format format for Ecore_Buffer
+ * @param[in] flags flags for Ecore_Buffer
+ *
+ * @return Newly allocated Ecore_Buffer instance, NULL otherwise.
+ */
+EAPI Ecore_Buffer *ecore_buffer_new(const char* engine, unsigned int width, unsigned int height, Ecore_Buffer_Format format, unsigned int flags);
+/**
+ * @brief Creates a new Ecore_Buffer based on given tbm surface.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] engine the name of backend
+ * @param[in] tbm_surface the handle of tbm_surface_h
+ * @param[in] flags the flags for Ecore_Buffer
+ *
+ * @return Newly allocated Ecore_Buffer instance based on tbm surface, NULL otherwise.
+ */
+EAPI Ecore_Buffer *ecore_buffer_new_with_tbm_surface(const char *engine, void *tbm_surface, unsigned int flags);
+/**
+ * @brief Free the given Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer to free
+ */
+EAPI void          ecore_buffer_free(Ecore_Buffer* buf);
+/**
+ * @brief Set a callback for Ecore_Buffer free events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer to set callbacks on
+ * @param[in] func The function to call
+ * @param[in] data A pointer to the user data to store.
+ *
+ * A call to this function will set a callback on an Ecore_Buffer, causing
+ * @p func to be called whenever @p buf is freed.
+ *
+ * @see ecore_buffer_free_callback_remove()
+ */
+EAPI void          ecore_buffer_free_callback_add(Ecore_Buffer* buf, Ecore_Buffer_Cb  func, void* data);
+/**
+ * @brief Remove a callback for Ecore_Buffer free events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer to remove callbacks on
+ * @param[in] func The function to remove
+ * @param[in] data A pointer to the user data to remove
+ *
+ * @see ecore_buffer_free_callback_add()
+ */
+EAPI void          ecore_buffer_free_callback_remove(Ecore_Buffer* buf, Ecore_Buffer_Cb func, void* data);
+/**
+ * @brief Return the Pixmap of given Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer
+ *
+ * @return The Pixmap instance, 0 otherwise.
+ */
+EAPI Ecore_Pixmap  ecore_buffer_pixmap_get(Ecore_Buffer *buf);
+/**
+ * @brief Return the tbm surface handle of given Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer
+ *
+ * @return The tbm surface handle, NULL otherwise.
+ *
+ * The tbm surface handle will be used for the API of libtbm.
+ * The API is described in tbm_surface.h in libtbm.
+ */
+EAPI void         *ecore_buffer_tbm_surface_get(Ecore_Buffer *buf);
+/**
+ * @brief Return size of given Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer
+ * @param[out] width where to return the width value. May be @c NULL.
+ * @param[out] height  where to return the height value. May be @c NULL.
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool     ecore_buffer_size_get(Ecore_Buffer *buf, unsigned int *width, unsigned int *height);
+/**
+ * @brief Return format of given Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer
+ *
+ * @return The format of given Ecore_Buffer.
+ *
+ * return value can be one of those pre-defined value such as ECORE_BUFFER_FORMAT_XRGB8888.
+ */
+EAPI Ecore_Buffer_Format ecore_buffer_format_get(Ecore_Buffer *buf);
+/**
+ * @brief Return flags of given Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] buf The Ecore_Buffer
+ *
+ * @return The flags of given Ecore_Buffer.
+ *
+ * NOTE: Not Defined yet.
+ */
+EAPI unsigned int  ecore_buffer_flags_get(Ecore_Buffer *buf);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_buffer/Ecore_Buffer_Queue.h b/src/lib/ecore_buffer/Ecore_Buffer_Queue.h
new file mode 100644 (file)
index 0000000..3744f9c
--- /dev/null
@@ -0,0 +1,449 @@
+#ifndef _ECORE_BUFFER_QUEUE_H_
+#define _ECORE_BUFFER_QUEUE_H_
+
+#include <Eina.h>
+#include "Ecore_Buffer.h"
+
+#ifdef EAPI
+# undef EAPI
+#endif
+
+#ifdef _WIN32
+# ifdef EFL_ECORE_BUFFER_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif /* ! DLL_EXPORT */
+# else
+#  define EAPI __declspec(dllimport)
+# endif /* ! EFL_ECORE_BUFFER_BUILD */
+#else
+# ifdef __GNUC__
+#  if __GNUC__ >= 4
+#   define EAPI __attribute__ ((visibility("default")))
+#  else
+#   define EAPI
+#  endif
+# else
+#  define EAPI
+# endif
+#endif /* ! _WIN32 */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup Ecore_Buffer_Queue_Group Ecore Buffer Queue functions
+ * @ingroup Ecore_Buffer_Group
+ *
+ * Ecore Buffer Queue is a queue which conntects different processes for sharing
+ * Ecore_Buffer.
+ * one process (related object is Ecore_Buffer_Provider) has rear terminal
+ * position of Ecore_Buffer Queue which can enqueue the Ecore_Buffer,
+ * and the other process (related object is Ecore_Buffer_Consumer) has front
+ * terminal position of Ecore_Buffer_Queue which can dequeue the Ecore_Buffer.
+ */
+
+/**
+ * @defgroup Ecore_Buffer_Provider_Group Ecore Buffer Provider functions
+ * @ingroup Ecore_Buffer_Queue_Group
+ *
+ * This group of functions is applied to an Ecore_Buffer_Provider object.
+ * Ecore_Buffer_Provider provides Ecore_Buffer to Ecore_Buffer_Consumer(usally
+ * different process or thread from Ecore_Buffer_Provider).
+ * Ecore_Buffer_Provider should creates Ecore_Buffer as a provider.
+ */
+
+/**
+ * @defgroup Ecore_Buffer_Consumer_Group Ecore Buffer Consumer functions
+ * @ingroup Ecore_Buffer_Queue_Group
+ *
+ * This group of functions is applied to an Ecore_Buffer_Consumer object.
+ * Ecore_Buffer_Consumer receives Ecore_Buffer enqueued by Ecore_Buffer_Provider.
+ * Consumer must release Ecore_Buffer when it's no longer used.
+ * Thus, the Ecore_Buffer_Provider is now free to re-use or destroy Ecore_Buffer.
+ */
+
+/**
+ * @typedef Ecore_Buffer_Return
+ * @enum _Ecore_Buffer_Return
+ * types for an buffer queue state on provider side.
+ * @ingroup Ecore_Buffer_Provider_Group
+ * @see ecore_buffer_provider_buffer_acquire()
+ * @see ecore_buffer_provider_buffer_acquirable_check()
+ */
+typedef enum _Ecore_Buffer_Return
+{
+   ECORE_BUFFER_RETURN_ERROR,       /**< on error @since_tizen 2.4 */
+   ECORE_BUFFER_RETURN_SUCCESS,     /**< success to dequeue a buffer @since_tizen 2.4 */
+   ECORE_BUFFER_RETURN_EMPTY,       /**< Empty queue @since_tizen 2.4 */
+   ECORE_BUFFER_RETURN_NOT_EMPTY,   /**< Not empty queue @since_tizen 2.4 */
+   ECORE_BUFFER_RETURN_NEED_ALLOC,  /**< need to create Ecore_Buffer @since_tizen 2.4 */
+} Ecore_Buffer_Return;
+/**
+ * @typedef Ecore_Buffer_Consumer
+ * An object representing a consumer of Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @ingroup Ecore_Buffer_Consumer_Group
+ */
+typedef struct _Ecore_Buffer_Consumer Ecore_Buffer_Consumer;
+/**
+ * @typedef Ecore_Buffer_Provider
+ * An object representing a provider of Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @ingroup Ecore_Buffer_Provider_Group
+ */
+typedef struct _Ecore_Buffer_Provider Ecore_Buffer_Provider;
+/**
+ * @typedef Ecore_Buffer_Consumer_Provider_Add_Cb
+ *
+ * @brief Called whenever a Ecore_Buffer_Provider connected.
+ *
+ * @since_tizen 2.4
+ *
+ * @see ecore_buffer_consumer_provider_add_cb_set()
+ * @ingroup Ecore_Buffer_Consumer_Group
+ */
+typedef void (*Ecore_Buffer_Consumer_Provider_Add_Cb) (Ecore_Buffer_Consumer *consumer, void *data);
+/**
+ * @typedef Ecore_Buffer_Consumer_Provider_Del_Cb
+ *
+ * @brief Called whenever a Ecore_Buffer_Provider disonnected.
+ *
+ * @since_tizen 2.4
+ *
+ * @see ecore_buffer_consumer_provider_del_cb_set()
+ * @ingroup Ecore_Buffer_Consumer_Group
+ */
+typedef void (*Ecore_Buffer_Consumer_Provider_Del_Cb) (Ecore_Buffer_Consumer *consumer, void *data);
+/**
+ * @typedef Ecore_Buffer_Consumer_Enqueue_Cb
+ *
+ * @brief Called whenever a Ecore_Buffer enqueued in buffer queue.
+ *
+ * @since_tizen 2.4
+ *
+ * @see ecore_buffer_consumer_buffer_enqueued_cb_set()
+ * @ingroup Ecore_Buffer_Consumer_Group
+ */
+typedef void (*Ecore_Buffer_Consumer_Enqueue_Cb) (Ecore_Buffer_Consumer *consumer, void *data);
+/**
+ * @typedef Ecore_Buffer_Provider_Consumer_Add_Cb
+ *
+ * @brief Called whenever a Ecore_Buffer_Consumer connected.
+ *
+ * @since_tizen 2.4
+ *
+ * @see ecore_buffer_provider_consumer_add_cb_set()
+ * @ingroup Ecore_Buffer_Provider_Group
+ */
+typedef void (*Ecore_Buffer_Provider_Consumer_Add_Cb) (Ecore_Buffer_Provider *provider, int queue_size, int w, int h, void *data);
+/**
+ * @typedef Ecore_Buffer_Provider_Consumer_Del_Cb
+ *
+ * @brief Called whenever a Ecore_Buffer_Consumer disconnected.
+ *
+ * @since_tizen 2.4
+ *
+ * @see ecore_buffer_provider_consumer_del_cb_set()
+ * @ingroup Ecore_Buffer_Provider_Group
+ */
+typedef void (*Ecore_Buffer_Provider_Consumer_Del_Cb) (Ecore_Buffer_Provider *provider, void *data);
+/**
+ * @typedef Ecore_Buffer_Provider_Enqueue_Cb
+ *
+ * @brief Called whenever a Ecore_Buffer is released.
+ *
+ * @since_tizen 2.4
+ *
+ * @see ecore_buffer_provider_buffer_released_cb_set()
+ * @ingroup Ecore_Buffer_Provider_Group
+ */
+typedef void (*Ecore_Buffer_Provider_Enqueue_Cb) (Ecore_Buffer_Provider *provider, void *data);
+
+/**
+ * @addtogroup Ecore_Buffer_Queue_Group
+ * @{
+ */
+
+/**
+ * @brief Init the Ecore_Buffer_Queue system.
+ *
+ * @since_tizen 2.4
+ *
+ * @return How many times the lib has been initialized, 0 indicates failure.
+ *
+ * Set up the connection of Buffer Queue deamon, and Init Ecore_Buffer_Queue libraries.
+ *
+ * @see ecore_buffer_queue_shutdown()
+ */
+EAPI int   ecore_buffer_queue_init(void);
+/**
+ * @brief Shut down the Ecore_Buffer_Queue system.
+ *
+ * @since_tizen 2.4
+ *
+ * this closes the connection of Buffer Queue deamon, and Shut down Ecore_Buffer_Queue libraries.
+ *
+ * @see ecore_buffer_queue_init()
+ */
+EAPI void  ecore_buffer_queue_shutdown(void);
+
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup Ecore_Buffer_Consumer_Group
+ * @{
+ */
+
+/**
+ * @brief Creates a new Buffer Consumer based on name and common parameters.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] name the name of Buffer_Queue, this is needed by Consumer and Provider to connect each other.
+ * @param[in] queue_size size of Queue (If you pass this 0, then default size two(2) is appied)
+ * @param[in] w width of buffer recommeneded to provider.
+ * @param[in] h height of buffer recommended to provider.
+ *
+ * @return Ecore_Buffer_Consumer instance or @c NULL if creation failed.
+ */
+EAPI Ecore_Buffer_Consumer    *ecore_buffer_consumer_new(const char *name, int32_t queue_size, int32_t w, int32_t h);
+/**
+ * @brief Free an Ecore_Buffer_Consumer
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] consumer The Ecore_Buffer_Consumer to free
+ *
+ * This frees up any memory used by the Ecore_Buffer_Consumer.
+ */
+EAPI void                      ecore_buffer_consumer_free(Ecore_Buffer_Consumer *consumer);
+/**
+ * @brief Return the latest Ecore_Buffer submitted by provider.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] consumer The Ecore_Buffer_Consumer to request for buffer
+ *
+ * @return Ecore_Buffer handle or NULL if acquirement failed.
+ *
+ * @see ecore_buffer_consumer_buffer_release()
+ *
+ * Consumer can store Ecore_Buffer submitted by Provider as much as size of queue
+ * which is passed as a argument of ecore_buffer_consumer_new().
+ */
+EAPI Ecore_Buffer             *ecore_buffer_consumer_buffer_dequeue(Ecore_Buffer_Consumer *consumer);
+/**
+ * @brief Release the acquired Ecore_Buffer.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] consumer The Ecore_Buffer_Consumer to request release buffer
+ * @param[in] buffer The Ecore_Buffer to release
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * @see ecore_buffer_consumer_buffer_dequeue()
+ *
+ * Consumer should release the Ecore_Buffer after acquiring and using it.
+ * By doing release, Ecore_Buffer will be used by provider again,
+ * or freed internally if Ecore_Buffer is not necessary anymore.
+ * If not, the resource of Ecore_Buffer is continually owned by consumer until released.
+ */
+EAPI Eina_Bool                 ecore_buffer_consumer_buffer_release(Ecore_Buffer_Consumer *consumer, Ecore_Buffer *buffer);
+/**
+ * @brief Check if Queue of Ecore_Buffer is empty.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] consumer The Ecore_Buffer_Consumer to query
+ *
+ * @return @c EINA_TRUE means queue is empty, @c EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool                 ecore_buffer_consumer_queue_is_empty(Ecore_Buffer_Consumer *consumer);
+/**
+ * @brief Set a callback for provider connection events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] consumer The Ecore_Buffer_Consumer to set callbacks on
+ * @param[in] func The function to call
+ * @param[in] data A pointer to the user data to store.
+ *
+ * A call to this function will set a callback on an Ecore_Buffer_Consumer, causing
+ * @p func to be called whenever @p consumer is connected with provider.
+ */
+EAPI void                      ecore_buffer_consumer_provider_add_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Provider_Add_Cb func, void *data);
+/**
+ * @brief Set a callback for provider disconnection events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] consumer The Ecore_Buffer_Consumer to set callbacks on
+ * @param[in] func The function to call
+ * @param[in] data A pointer to the user data to store.
+ *
+ * A call to this function will set a callback on an Ecore_Buffer_Consumer, causing
+ * @p func to be called whenever @p consumer is disconnected with provider.
+ */
+EAPI void                      ecore_buffer_consumer_provider_del_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Provider_Del_Cb func, void *data);
+/**
+ * @brief Set a callback for enqueued buffer events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] consumer The Ecore_Buffer_Consumer to set callbacks on
+ * @param[in] func The function to call
+ * @param[in] data A pointer to the user data to store.
+ *
+ * A call to this function will set a callback on an Ecore_Buffer_Consumer, causing
+ * @p func to be called whenever @p consumer has received buffer submitted from provider.
+ *
+ * You may success acuiqre Ecore_Buffer after this callback called.
+ */
+EAPI void                      ecore_buffer_consumer_buffer_enqueued_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Enqueue_Cb func, void *data);
+
+/**
+ * @}
+ */
+
+/**
+ * @addtogroup Ecore_Buffer_Provider_Group
+ * @{
+ */
+
+/**
+ * @brief Creates a new Buffer Provider based on name.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] name the name of Buffer_Queue.
+ *
+ * @return Ecore_Buffer_Provider instance or @c NULL if creation failed.
+ */
+EAPI Ecore_Buffer_Provider    *ecore_buffer_provider_new(const char *name);
+/**
+ * @brief Free an Ecore_Buffer_Provider
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] provider The Ecore_Buffer_Provider to free
+ *
+ * This frees up any memory used by the Ecore_Buffer_Provider.
+ */
+EAPI void                      ecore_buffer_provider_free(Ecore_Buffer_Provider *provider);
+/**
+ * @brief Return the Ecore_Buffer released by consumer or State of Queue.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] provider The Ecore_Buffer_Provider to request for buffer
+ * @param[out] ret_buf A Pointer to the Ecore_Buffer
+ *
+ * @return The enumeration of Ecore_Buffer_Return to indicate result of Dequeueing.
+ *
+ * This function gives you drawable buffer and inform you the state of Queue.
+ * Each return value of enumeration has meaning as below.
+ * @li ECORE_BUFFER_RETURN_ERROR, means error occured.
+ * @li ECORE_BUFFER_RETURN_SUCCESS, means success to dequeue, therefore ret_buf is valid.
+ * @li ECORE_BUFFER_RETURN_EMPTY, means queue is empty, not available slot in Queue.
+ *  in other words, there is no free drawable buffer in Queue.
+ * @lib @c ECORE_BUFFER_RETURN_NEED_ALLOC, means that there is available slot, but not allocated.
+ *  so, You may create new Ecore_Buffer, and then just submit the Ecore_Buffer.
+ *
+ * @see ecore_buffer_new(), ecore_buffer_provider_buffer_enqueue()
+ */
+EAPI Ecore_Buffer_Return       ecore_buffer_provider_buffer_acquire(Ecore_Buffer_Provider *provider, Ecore_Buffer **ret_buf);
+/**
+ * @brief Submit the Ecore_Buffer to Consumer to request compositing.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] provider The Ecore_Buffer_Provider connected with consumer.
+ * @param[in] buffer The Ecore_Buffer to submit
+ *
+ * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
+ *
+ * This function allow you to submit the Ecore_Buffer to consumer to request compositing.
+ * And this will be success, in case only you submit dequeued Ecore_Buffer,
+ * and new Ecore_Buffer after received return value of ECORE_BUFFER_RETURN_NEED_ALLOC by ecore_buffer_provider_buffer_acquire().
+ *
+ * @see ecore_buffer_new(), ecore_buffer_provider_buffer_dequeue()
+ */
+EAPI Eina_Bool                 ecore_buffer_provider_buffer_enqueue(Ecore_Buffer_Provider *provider, Ecore_Buffer *buffer);
+/**
+ * @brief Check if state of queue.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] provider The Ecore_Buffer_Provider to query
+ *
+ * @li ECORE_BUFFER_RETURN_NOT_EMPTY, means there is a dequeueable Ecore_Buffer at least one.
+ * @li ECORE_BUFFER_RETURN_EMPTY, means queue is empty, not available slot in Queue.
+ *  in other words, there is no free drawable buffer in Queue.
+ * @li ECORE_BUFFER_RETURN_NEED_ALLOC, means that there is available slot, but not allocated.
+ *  so, You may create new Ecore_Buffer, and then just submit the Ecore_Buffer.
+ *
+ * @return @c EINA_TRUE means queue is empty, @c EINA_FALSE otherwise.
+ */
+EAPI Ecore_Buffer_Return       ecore_buffer_provider_buffer_acquirable_check(Ecore_Buffer_Provider *provider);
+/**
+ * @brief Set a callback for consumer connection events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] provider The Ecore_Buffer_Provider to set callbacks on
+ * @param[in] func The function to call
+ * @param[in] data A pointer to the user data to store.
+ *
+ * A call to this function will set a callback on an Ecore_Buffer_Provider, causing
+ * @p func to be called whenever @p provider is connected with consumer.
+ */
+EAPI void                      ecore_buffer_provider_consumer_add_cb_set(Ecore_Buffer_Provider *provider, Ecore_Buffer_Provider_Consumer_Add_Cb func, void *data);
+/**
+ * @brief Set a callback for consumer disconnection events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] provider The Ecore_Buffer_Provider to set callbacks on
+ * @param[in] func The function to call
+ * @param[in] data A pointer to the user data to store.
+ *
+ * A call to this function will set a callback on an Ecore_Buffer_Provider, causing
+ * @p func to be called whenever @p provider is disconnected with consumer.
+ */
+EAPI void                      ecore_buffer_provider_consumer_del_cb_set(Ecore_Buffer_Provider *provider, Ecore_Buffer_Provider_Consumer_Del_Cb func, void *data);
+/**
+ * @brief Set a callback for released buffer events.
+ *
+ * @since_tizen 2.4
+ *
+ * @param[in] provider The Ecore_Buffer_Provider to set callbacks on
+ * @param[in] func The function to call
+ * @param[in] data A pointer to the user data to store.
+ *
+ * A call to this function will set a callback on an Ecore_Buffer_Provider, causing
+ * @p func to be called whenever @p provider has received Ecore_Buffer released from provider.
+ *
+ * You may success dequeue the Ecore_Buffer after this callback called.
+ */
+EAPI void                      ecore_buffer_provider_buffer_released_cb_set(Ecore_Buffer_Provider *provider, Ecore_Buffer_Provider_Enqueue_Cb func, void *data);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ECORE_BUFFER_QUEUE_H_ */
diff --git a/src/lib/ecore_buffer/bq_mgr_protocol.c b/src/lib/ecore_buffer/bq_mgr_protocol.c
new file mode 100644 (file)
index 0000000..fe8b98c
--- /dev/null
@@ -0,0 +1,131 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include "wayland-util.h"
+
+extern const struct wl_interface bq_buffer_interface;
+extern const struct wl_interface bq_consumer_interface;
+extern const struct wl_interface bq_provider_interface;
+
+static const struct wl_interface *types[] = {
+       NULL,
+       NULL,
+       NULL,
+       &bq_consumer_interface,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &bq_provider_interface,
+       NULL,
+       &bq_buffer_interface,
+       &bq_buffer_interface,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &bq_buffer_interface,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &bq_buffer_interface,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &bq_buffer_interface,
+       &bq_buffer_interface,
+       NULL,
+       &bq_buffer_interface,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &bq_buffer_interface,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &bq_buffer_interface,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       &bq_buffer_interface,
+       &bq_buffer_interface,
+       NULL,
+       &bq_buffer_interface,
+       NULL,
+};
+
+static const struct wl_message bq_mgr_requests[] = {
+       { "create_consumer", "nsiii", types + 3 },
+       { "create_provider", "ns", types + 8 },
+};
+
+WL_EXPORT const struct wl_interface bq_mgr_interface = {
+       "bq_mgr", 1,
+       2, bq_mgr_requests,
+       0, NULL,
+};
+
+static const struct wl_message bq_consumer_requests[] = {
+       { "release_buffer", "o", types + 10 },
+};
+
+static const struct wl_message bq_consumer_events[] = {
+       { "connected", "", types + 0 },
+       { "disconnected", "", types + 0 },
+       { "buffer_attached", "nsiiiu", types + 11 },
+       { "set_buffer_id", "oiiiiiii", types + 17 },
+       { "set_buffer_fd", "ohiiiiii", types + 25 },
+       { "buffer_detached", "o", types + 33 },
+       { "add_buffer", "ou", types + 34 },
+};
+
+WL_EXPORT const struct wl_interface bq_consumer_interface = {
+       "bq_consumer", 1,
+       1, bq_consumer_requests,
+       7, bq_consumer_events,
+};
+
+static const struct wl_message bq_provider_requests[] = {
+       { "attach_buffer", "nsiiiu", types + 36 },
+       { "set_buffer_id", "oiiiiiii", types + 42 },
+       { "set_buffer_fd", "ohiiiiii", types + 50 },
+       { "detach_buffer", "o", types + 58 },
+       { "enqueue_buffer", "ou", types + 59 },
+};
+
+static const struct wl_message bq_provider_events[] = {
+       { "connected", "iii", types + 0 },
+       { "disconnected", "", types + 0 },
+       { "add_buffer", "ou", types + 61 },
+};
+
+WL_EXPORT const struct wl_interface bq_provider_interface = {
+       "bq_provider", 1,
+       5, bq_provider_requests,
+       3, bq_provider_events,
+};
+
+WL_EXPORT const struct wl_interface bq_buffer_interface = {
+       "bq_buffer", 1,
+       0, NULL,
+       0, NULL,
+};
+
diff --git a/src/lib/ecore_buffer/bq_mgr_protocol.h b/src/lib/ecore_buffer/bq_mgr_protocol.h
new file mode 100644 (file)
index 0000000..7cf9ad9
--- /dev/null
@@ -0,0 +1,329 @@
+#ifndef BQ_MGR_CLIENT_PROTOCOL_H
+#define BQ_MGR_CLIENT_PROTOCOL_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+
+struct wl_client;
+struct wl_resource;
+
+struct bq_mgr;
+struct bq_consumer;
+struct bq_provider;
+struct bq_buffer;
+
+extern const struct wl_interface bq_mgr_interface;
+extern const struct wl_interface bq_consumer_interface;
+extern const struct wl_interface bq_provider_interface;
+extern const struct wl_interface bq_buffer_interface;
+
+#ifndef BQ_MGR_ERROR_ENUM
+#define BQ_MGR_ERROR_ENUM
+enum bq_mgr_error {
+       BQ_MGR_ERROR_INVALID_PERMISSION = 0,
+       BQ_MGR_ERROR_INVALID_NAME = 1,
+       BQ_MGR_ERROR_ALREADY_USED = 2,
+};
+#endif /* BQ_MGR_ERROR_ENUM */
+
+#define BQ_MGR_CREATE_CONSUMER 0
+#define BQ_MGR_CREATE_PROVIDER 1
+
+static inline void
+bq_mgr_set_user_data(struct bq_mgr *bq_mgr, void *user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) bq_mgr, user_data);
+}
+
+static inline void *
+bq_mgr_get_user_data(struct bq_mgr *bq_mgr)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) bq_mgr);
+}
+
+static inline void
+bq_mgr_destroy(struct bq_mgr *bq_mgr)
+{
+       wl_proxy_destroy((struct wl_proxy *) bq_mgr);
+}
+
+static inline struct bq_consumer *
+bq_mgr_create_consumer(struct bq_mgr *bq_mgr, const char *name, int32_t queue_size, int32_t width, int32_t height)
+{
+       struct wl_proxy *id;
+
+       id = wl_proxy_marshal_constructor((struct wl_proxy *) bq_mgr,
+                        BQ_MGR_CREATE_CONSUMER, &bq_consumer_interface, NULL, name, queue_size, width, height);
+
+       return (struct bq_consumer *) id;
+}
+
+static inline struct bq_provider *
+bq_mgr_create_provider(struct bq_mgr *bq_mgr, const char *name)
+{
+       struct wl_proxy *id;
+
+       id = wl_proxy_marshal_constructor((struct wl_proxy *) bq_mgr,
+                        BQ_MGR_CREATE_PROVIDER, &bq_provider_interface, NULL, name);
+
+       return (struct bq_provider *) id;
+}
+
+struct bq_consumer_listener {
+       /**
+        * connected - (none)
+        */
+       void (*connected)(void *data,
+                         struct bq_consumer *bq_consumer);
+       /**
+        * disconnected - (none)
+        */
+       void (*disconnected)(void *data,
+                            struct bq_consumer *bq_consumer);
+       /**
+        * buffer_attached - (none)
+        * @buffer: (none)
+        * @engine: (none)
+        * @width: (none)
+        * @height: (none)
+        * @format: (none)
+        * @flags: (none)
+        */
+       void (*buffer_attached)(void *data,
+                               struct bq_consumer *bq_consumer,
+                               struct bq_buffer *buffer,
+                               const char *engine,
+                               int32_t width,
+                               int32_t height,
+                               int32_t format,
+                               uint32_t flags);
+       /**
+        * set_buffer_id - (none)
+        * @buffer: (none)
+        * @id: (none)
+        * @offset0: (none)
+        * @stride0: (none)
+        * @offset1: (none)
+        * @stride1: (none)
+        * @offset2: (none)
+        * @stride2: (none)
+        */
+       void (*set_buffer_id)(void *data,
+                             struct bq_consumer *bq_consumer,
+                             struct bq_buffer *buffer,
+                             int32_t id,
+                             int32_t offset0,
+                             int32_t stride0,
+                             int32_t offset1,
+                             int32_t stride1,
+                             int32_t offset2,
+                             int32_t stride2);
+       /**
+        * set_buffer_fd - (none)
+        * @buffer: (none)
+        * @fd: (none)
+        * @offset0: (none)
+        * @stride0: (none)
+        * @offset1: (none)
+        * @stride1: (none)
+        * @offset2: (none)
+        * @stride2: (none)
+        */
+       void (*set_buffer_fd)(void *data,
+                             struct bq_consumer *bq_consumer,
+                             struct bq_buffer *buffer,
+                             int32_t fd,
+                             int32_t offset0,
+                             int32_t stride0,
+                             int32_t offset1,
+                             int32_t stride1,
+                             int32_t offset2,
+                             int32_t stride2);
+       /**
+        * buffer_detached - (none)
+        * @buffer: (none)
+        */
+       void (*buffer_detached)(void *data,
+                               struct bq_consumer *bq_consumer,
+                               struct bq_buffer *buffer);
+       /**
+        * add_buffer - (none)
+        * @buffer: (none)
+        * @serial: (none)
+        */
+       void (*add_buffer)(void *data,
+                          struct bq_consumer *bq_consumer,
+                          struct bq_buffer *buffer,
+                          uint32_t serial);
+};
+
+static inline int
+bq_consumer_add_listener(struct bq_consumer *bq_consumer,
+                        const struct bq_consumer_listener *listener, void *data)
+{
+       return wl_proxy_add_listener((struct wl_proxy *) bq_consumer,
+                                    (void (**)(void)) listener, data);
+}
+
+#define BQ_CONSUMER_RELEASE_BUFFER     0
+
+static inline void
+bq_consumer_set_user_data(struct bq_consumer *bq_consumer, void *user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) bq_consumer, user_data);
+}
+
+static inline void *
+bq_consumer_get_user_data(struct bq_consumer *bq_consumer)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) bq_consumer);
+}
+
+static inline void
+bq_consumer_destroy(struct bq_consumer *bq_consumer)
+{
+       wl_proxy_destroy((struct wl_proxy *) bq_consumer);
+}
+
+static inline void
+bq_consumer_release_buffer(struct bq_consumer *bq_consumer, struct bq_buffer *buffer)
+{
+       wl_proxy_marshal((struct wl_proxy *) bq_consumer,
+                        BQ_CONSUMER_RELEASE_BUFFER, buffer);
+}
+
+#ifndef BQ_PROVIDER_ERROR_ENUM
+#define BQ_PROVIDER_ERROR_ENUM
+enum bq_provider_error {
+       BQ_PROVIDER_ERROR_OVERFLOW_QUEUE_SIZE = 0,
+       BQ_PROVIDER_ERROR_CONNECTION = 1,
+};
+#endif /* BQ_PROVIDER_ERROR_ENUM */
+
+struct bq_provider_listener {
+       /**
+        * connected - (none)
+        * @queue_size: (none)
+        * @width: (none)
+        * @height: (none)
+        */
+       void (*connected)(void *data,
+                         struct bq_provider *bq_provider,
+                         int32_t queue_size,
+                         int32_t width,
+                         int32_t height);
+       /**
+        * disconnected - (none)
+        */
+       void (*disconnected)(void *data,
+                            struct bq_provider *bq_provider);
+       /**
+        * add_buffer - (none)
+        * @buffer: (none)
+        * @serial: (none)
+        */
+       void (*add_buffer)(void *data,
+                          struct bq_provider *bq_provider,
+                          struct bq_buffer *buffer,
+                          uint32_t serial);
+};
+
+static inline int
+bq_provider_add_listener(struct bq_provider *bq_provider,
+                        const struct bq_provider_listener *listener, void *data)
+{
+       return wl_proxy_add_listener((struct wl_proxy *) bq_provider,
+                                    (void (**)(void)) listener, data);
+}
+
+#define BQ_PROVIDER_ATTACH_BUFFER      0
+#define BQ_PROVIDER_SET_BUFFER_ID      1
+#define BQ_PROVIDER_SET_BUFFER_FD      2
+#define BQ_PROVIDER_DETACH_BUFFER      3
+#define BQ_PROVIDER_ENQUEUE_BUFFER     4
+
+static inline void
+bq_provider_set_user_data(struct bq_provider *bq_provider, void *user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) bq_provider, user_data);
+}
+
+static inline void *
+bq_provider_get_user_data(struct bq_provider *bq_provider)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) bq_provider);
+}
+
+static inline void
+bq_provider_destroy(struct bq_provider *bq_provider)
+{
+       wl_proxy_destroy((struct wl_proxy *) bq_provider);
+}
+
+static inline struct bq_buffer *
+bq_provider_attach_buffer(struct bq_provider *bq_provider, const char *engine, int32_t width, int32_t height, int32_t format, uint32_t flags)
+{
+       struct wl_proxy *buffer;
+
+       buffer = wl_proxy_marshal_constructor((struct wl_proxy *) bq_provider,
+                        BQ_PROVIDER_ATTACH_BUFFER, &bq_buffer_interface, NULL, engine, width, height, format, flags);
+
+       return (struct bq_buffer *) buffer;
+}
+
+static inline void
+bq_provider_set_buffer_id(struct bq_provider *bq_provider, struct bq_buffer *buffer, int32_t id, int32_t offset0, int32_t stride0, int32_t offset1, int32_t stride1, int32_t offset2, int32_t stride2)
+{
+       wl_proxy_marshal((struct wl_proxy *) bq_provider,
+                        BQ_PROVIDER_SET_BUFFER_ID, buffer, id, offset0, stride0, offset1, stride1, offset2, stride2);
+}
+
+static inline void
+bq_provider_set_buffer_fd(struct bq_provider *bq_provider, struct bq_buffer *buffer, int32_t fd, int32_t offset0, int32_t stride0, int32_t offset1, int32_t stride1, int32_t offset2, int32_t stride2)
+{
+       wl_proxy_marshal((struct wl_proxy *) bq_provider,
+                        BQ_PROVIDER_SET_BUFFER_FD, buffer, fd, offset0, stride0, offset1, stride1, offset2, stride2);
+}
+
+static inline void
+bq_provider_detach_buffer(struct bq_provider *bq_provider, struct bq_buffer *buffer)
+{
+       wl_proxy_marshal((struct wl_proxy *) bq_provider,
+                        BQ_PROVIDER_DETACH_BUFFER, buffer);
+}
+
+static inline void
+bq_provider_enqueue_buffer(struct bq_provider *bq_provider, struct bq_buffer *buffer, uint32_t serial)
+{
+       wl_proxy_marshal((struct wl_proxy *) bq_provider,
+                        BQ_PROVIDER_ENQUEUE_BUFFER, buffer, serial);
+}
+
+static inline void
+bq_buffer_set_user_data(struct bq_buffer *bq_buffer, void *user_data)
+{
+       wl_proxy_set_user_data((struct wl_proxy *) bq_buffer, user_data);
+}
+
+static inline void *
+bq_buffer_get_user_data(struct bq_buffer *bq_buffer)
+{
+       return wl_proxy_get_user_data((struct wl_proxy *) bq_buffer);
+}
+
+static inline void
+bq_buffer_destroy(struct bq_buffer *bq_buffer)
+{
+       wl_proxy_destroy((struct wl_proxy *) bq_buffer);
+}
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_buffer/buffer_queue.c b/src/lib/ecore_buffer/buffer_queue.c
new file mode 100644 (file)
index 0000000..ab7160f
--- /dev/null
@@ -0,0 +1,225 @@
+#include "buffer_queue.h"
+
+typedef struct _Queue Queue;
+
+struct _Ecore_Buffer_Queue
+{
+   Eina_Bool connected;
+
+   int w, h;
+   Queue *queue;
+   Eina_List *shared_buffers;
+};
+
+struct _Queue
+{
+   Eina_List *data_list;
+   unsigned int capacity;
+};
+
+static inline Queue       *_queue_new(int capacity);
+static inline void         _queue_free(Queue *queue);
+static inline void         _queue_data_remove(Queue *queue, void *data);
+static inline int          _queue_size_get(Queue *queue);
+static inline Eina_Bool    _queue_is_full(Queue *queue);
+static inline Eina_Bool    _queue_is_empty(Queue *queue);
+static inline Eina_Bool    _queue_dequeue(Queue *queue, void **ret_data);
+static inline Eina_Bool    _queue_enqueue(Queue *queue, void *data);
+
+Ecore_Buffer_Queue *
+_ecore_buffer_queue_new(int w, int h, int queue_size)
+{
+   Ecore_Buffer_Queue *ebq;
+
+   ebq = calloc(sizeof(Ecore_Buffer_Queue), 1);
+   if (!ebq)
+     return NULL;
+
+   ebq->w = w;
+   ebq->h = h;
+   ebq->queue = _queue_new(queue_size);
+
+   return ebq;
+}
+
+void
+_ecore_buffer_queue_free(Ecore_Buffer_Queue *ebq)
+{
+   Shared_Buffer *sb;
+
+   EINA_SAFETY_ON_NULL_RETURN(ebq);
+
+   // FIXME
+   EINA_LIST_FREE(ebq->shared_buffers, sb)
+     {
+        ecore_buffer_free(_shared_buffer_buffer_get(sb));
+        // NOTE: shared buffer will be freed by callback of buffer free.
+     }
+
+   _queue_free(ebq->queue);
+   free(ebq);
+}
+
+void
+_ecore_buffer_queue_enqueue(Ecore_Buffer_Queue *ebq, Shared_Buffer *sb)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ebq);
+
+   if (!eina_list_data_find(ebq->shared_buffers, sb))
+     {
+        WARN("Not added buffer in Queue");
+        return;
+     }
+
+   _queue_enqueue(ebq->queue, (void *)sb);
+}
+
+Eina_Bool
+_ecore_buffer_queue_dequeue(Ecore_Buffer_Queue *ebq, Shared_Buffer **ret_sb)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ebq, EINA_FALSE);
+
+   return _queue_dequeue(ebq->queue, (void **)ret_sb);
+}
+
+Eina_Bool
+_ecore_buffer_queue_is_empty(Ecore_Buffer_Queue *ebq)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ebq, EINA_FALSE);
+
+   return _queue_is_empty(ebq->queue);
+}
+
+void
+_ecore_buffer_queue_shared_buffer_add(Ecore_Buffer_Queue *ebq, Shared_Buffer *sb)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ebq);
+
+   ebq->shared_buffers = eina_list_append(ebq->shared_buffers, sb);
+}
+
+void
+_ecore_buffer_queue_shared_buffer_remove(Ecore_Buffer_Queue *ebq, Shared_Buffer *sb)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ebq);
+
+   _queue_data_remove(ebq->queue, sb);
+   ebq->shared_buffers = eina_list_remove(ebq->shared_buffers, sb);
+}
+
+Eina_List *
+_ecore_buffer_queue_shared_buffer_list_get(Ecore_Buffer_Queue *ebq)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ebq, NULL);
+
+   return ebq->shared_buffers;
+}
+
+void
+_ecore_buffer_queue_connection_state_set(Ecore_Buffer_Queue *ebq, Eina_Bool connect)
+{
+   EINA_SAFETY_ON_NULL_RETURN(ebq);
+
+   ebq->connected = connect;
+}
+
+Eina_Bool
+_ecore_buffer_queue_connection_state_get(Ecore_Buffer_Queue *ebq)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ebq, EINA_FALSE);
+
+   return ebq->connected;
+}
+
+static inline Queue *
+_queue_new(int capacity)
+{
+   Queue *queue;
+
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((capacity > 0), NULL);
+
+   queue = (Queue *)calloc(sizeof(Queue), 1);
+   if (!queue)
+     return NULL;
+
+   queue->capacity = capacity;
+
+   return queue;
+}
+
+static inline void
+_queue_free(Queue *queue)
+{
+   EINA_SAFETY_ON_NULL_RETURN(queue);
+
+   if (queue->data_list)
+     eina_list_free(queue->data_list);
+
+   free(queue);
+}
+
+static inline int
+_queue_size_get(Queue *queue)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue, 0);
+
+   return queue->capacity;
+}
+
+static inline Eina_Bool
+_queue_is_full(Queue *queue)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
+
+   return (eina_list_count(queue->data_list) == queue->capacity);
+}
+
+static inline Eina_Bool
+_queue_is_empty(Queue *queue)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
+
+   return (eina_list_count(queue->data_list) == 0);
+}
+
+static inline Eina_Bool
+_queue_dequeue(Queue *queue, void **ret_data)
+{
+   Eina_List *last;
+   void *data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
+
+   if (_queue_is_empty(queue)) return EINA_FALSE;
+
+   data = eina_list_last_data_get(queue->data_list);
+   last = eina_list_last(queue->data_list);
+   queue->data_list = eina_list_remove_list(queue->data_list, last);
+
+   if (ret_data) *ret_data = data;
+
+   return EINA_TRUE;
+}
+
+static inline Eina_Bool
+_queue_enqueue(Queue *queue, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
+
+   if (_queue_is_full(queue)) return EINA_FALSE;
+
+   queue->data_list = eina_list_prepend(queue->data_list, data);
+
+   return EINA_TRUE;
+}
+
+static inline void
+_queue_data_remove(Queue *queue, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(queue);
+
+   if (_queue_is_empty(queue)) return;
+
+   while (eina_list_data_find(queue->data_list, data) != NULL)
+     queue->data_list = eina_list_remove(queue->data_list, data);
+}
diff --git a/src/lib/ecore_buffer/buffer_queue.h b/src/lib/ecore_buffer/buffer_queue.h
new file mode 100644 (file)
index 0000000..4b9080a
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _BUFFER_QUEUE_H_
+#define _BUFFER_QUEUE_H_
+
+#include <stdio.h>
+#include <Eina.h>
+
+#include "shared_buffer.h"
+
+typedef struct _Ecore_Buffer_Queue Ecore_Buffer_Queue;
+
+Ecore_Buffer_Queue  *_ecore_buffer_queue_new(int w, int h, int queue_size);
+void                 _ecore_buffer_queue_free(Ecore_Buffer_Queue *ebq);
+void                 _ecore_buffer_queue_enqueue(Ecore_Buffer_Queue *ebq, Shared_Buffer *sb);
+Eina_Bool            _ecore_buffer_queue_dequeue(Ecore_Buffer_Queue *ebq, Shared_Buffer **ret_sb);
+Eina_Bool            _ecore_buffer_queue_is_empty(Ecore_Buffer_Queue *ebq);
+void                 _ecore_buffer_queue_shared_buffer_add(Ecore_Buffer_Queue *ebq, Shared_Buffer *sb);
+void                 _ecore_buffer_queue_shared_buffer_remove(Ecore_Buffer_Queue *ebq, Shared_Buffer *sb);
+Eina_List           *_ecore_buffer_queue_shared_buffer_list_get(Ecore_Buffer_Queue *ebq);
+void                 _ecore_buffer_queue_connection_state_set(Ecore_Buffer_Queue *ebq, Eina_Bool connect);
+Eina_Bool            _ecore_buffer_queue_connection_state_get(Ecore_Buffer_Queue *ebq);
+
+#endif
diff --git a/src/lib/ecore_buffer/ecore_buffer.c b/src/lib/ecore_buffer/ecore_buffer.c
new file mode 100644 (file)
index 0000000..54fe4bc
--- /dev/null
@@ -0,0 +1,524 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Eina.h"
+#include "Ecore.h"
+
+#include "Ecore_Buffer.h"
+#include "ecore_buffer_private.h"
+
+typedef struct _Ecore_Buffer_Module Ecore_Buffer_Module;
+typedef struct _Ecore_Buffer_Cb_Data Ecore_Buffer_Cb_Data;
+
+struct _Ecore_Buffer_Module {
+     Ecore_Buffer_Backend *be;
+     Ecore_Buffer_Module_Data data;
+};
+
+struct _Ecore_Buffer
+{
+   unsigned int width;
+   unsigned int height;
+   int format;
+   unsigned int flags;
+
+   Ecore_Buffer_Data buffer_data;
+   Ecore_Buffer_Module* bm;
+
+   Eina_Hash *data;
+   Eina_Inlist *free_callbacks;
+};
+
+struct _Ecore_Buffer_Cb_Data
+{
+   EINA_INLIST;
+   Ecore_Buffer_Cb cb;
+   void* data;
+};
+
+static Eina_Hash *_backends;
+static Eina_Array *_modules;
+static int _ecore_buffer_init_count = 0;
+static int _ecore_buffer_log_dom = -1;
+
+#ifdef ERR
+#undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_ecore_buffer_log_dom, __VA_ARGS__)
+
+#ifdef DBG
+#undef DBG
+#endif
+#define DBG(...) EINA_LOG_DOM_DBG(_ecore_buffer_log_dom, __VA_ARGS__)
+
+#ifndef PACKAGE_LIB_DIR
+#define PACKAGE_LIB_DIR ""
+#endif
+#ifndef MODULE_ARCH
+#define MODULE_ARCH ""
+#endif
+
+static Ecore_Buffer_Module *
+_ecore_buffer_get_backend(const char *name)
+{
+   Ecore_Buffer_Module *bm = NULL;
+   Eina_Iterator *backend_name_itr;
+   const char *backend_name = NULL;
+
+   backend_name = name;
+
+   if (backend_name == NULL)
+     {
+        backend_name = (const char*)getenv("ECORE_BUFFER_ENGINE");
+        if (!backend_name)
+          {
+             backend_name_itr = eina_hash_iterator_data_new(_backends);
+             while((!bm) &&
+                   (eina_iterator_next(backend_name_itr, (void **)&bm)));
+             eina_iterator_free(backend_name_itr);
+          }
+        else
+          bm = eina_hash_find(_backends, backend_name);
+     }
+
+   if ((!bm) || (!bm->be))
+     return NULL;
+
+   if ((!bm->data) && (bm->be->init))
+     bm->data = bm->be->init(NULL, NULL);
+
+   return bm;
+}
+
+static Eina_Bool
+_ecore_buffer_backends_free(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
+{
+   Ecore_Buffer_Module *bm = data;
+
+   if (!bm)
+     return EINA_FALSE;
+
+   if (bm->data)
+     bm->be->shutdown(bm->data);
+
+   return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+ecore_buffer_register(Ecore_Buffer_Backend *be)
+{
+   Ecore_Buffer_Module* bm;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(be, 0);
+
+   bm = calloc(1, sizeof(Ecore_Buffer_Module));
+   if (!bm)
+     return EINA_FALSE;
+
+   bm->be = be;
+   bm->data = NULL;
+
+   return eina_hash_add(_backends, be->name, bm);
+}
+
+EAPI void
+ecore_buffer_unregister(Ecore_Buffer_Backend *be)
+{
+   Ecore_Buffer_Module *bm;
+
+   EINA_SAFETY_ON_NULL_RETURN(be);
+
+   bm = eina_hash_find(_backends, be->name);
+   if (!bm)
+     return;
+
+   eina_hash_del(_backends, be->name, bm);
+   free(bm);
+}
+
+EAPI Eina_Bool
+ecore_buffer_init(void)
+{
+   char *path;
+
+   if (++_ecore_buffer_init_count > 1)
+     return EINA_TRUE;
+
+   _ecore_buffer_log_dom = eina_log_domain_register("ecore_buffer", EINA_COLOR_BLUE);
+   if (_ecore_buffer_log_dom < 0)
+     {
+        EINA_LOG_ERR("Could not register log domain: ecore_buffer");
+        goto err;
+     }
+
+   _backends = eina_hash_string_superfast_new(NULL);
+
+   /* dynamic backends */
+   _modules = eina_module_arch_list_get(NULL,
+                                        PACKAGE_LIB_DIR "/ecore_buffer/modules",
+                                        MODULE_ARCH);
+
+   path = eina_module_symbol_path_get((const void *)ecore_buffer_init,
+                                      "/ecore_buffer/modules");
+
+   _modules = eina_module_arch_list_get(_modules, path, MODULE_ARCH);
+   if (path)
+     free(path);
+
+   /* fallback using module where in build directory */
+   if ((!_modules) ||
+       (eina_array_count(_modules) == 0))
+     {
+        ERR("No available module in library directy: %s",
+            PACKAGE_LIB_DIR "/ecore_buffer/modules");
+        ERR("Fallback to load module where in build directory :%s",
+            PACKAGE_BUILD_DIR "/src/modules/");
+        _modules = eina_module_list_get(NULL,
+                                        PACKAGE_BUILD_DIR "/src/modules/",
+                                        EINA_TRUE, NULL, NULL);
+     }
+
+   if ((!_modules) ||
+       (eina_array_count(_modules) == 0))
+     {
+        ERR("no ecore_buffer modules able to be loaded.");
+        eina_hash_free(_backends);
+        eina_log_domain_unregister(_ecore_buffer_log_dom);
+        _ecore_buffer_log_dom = -1;
+        goto err;
+     }
+
+   // XXX: MODFIX: do not list ALL modules and load them ALL! this is
+   // wrong. load the module we need WHEN we need it (by name etc. etc.
+   // from api).
+   eina_module_list_load(_modules);
+
+   return EINA_TRUE;
+
+err:
+   _ecore_buffer_init_count--;
+   return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+ecore_buffer_shutdown(void)
+{
+   if (_ecore_buffer_init_count < 1)
+     {
+        WARN("Ecore_Buffer shut down called without init");
+        return EINA_FALSE;
+     }
+
+   if (--_ecore_buffer_init_count != 0)
+     return EINA_FALSE;
+
+   /* dynamic backends */
+   eina_hash_foreach(_backends, _ecore_buffer_backends_free, NULL);
+
+   eina_module_list_free(_modules);
+   if (_modules)
+     eina_array_free(_modules);
+
+   if (_backends)
+     eina_hash_free(_backends);
+
+   eina_log_domain_unregister(_ecore_buffer_log_dom);
+   _ecore_buffer_log_dom = -1;
+
+   return EINA_TRUE;
+}
+
+EAPI Ecore_Buffer*
+ecore_buffer_new(const char* engine, unsigned int width, unsigned int height, Ecore_Buffer_Format format, unsigned int flags)
+{
+   Ecore_Buffer_Module* bm;
+   Ecore_Buffer* bo;
+   void *bo_data;
+
+   bm = _ecore_buffer_get_backend(engine);
+   if (!bm)
+     {
+        ERR("Failed to get backend: %s", engine);
+        return NULL;
+     }
+
+   bo_data = bm->be->buffer_alloc(bm->data, width, height, format, flags);
+   if (!bo_data)
+     return NULL;
+
+   bo = calloc(1, sizeof(Ecore_Buffer));
+   if (!bo)
+     return NULL;
+
+   bo->bm = bm;
+   bo->width = width;
+   bo->height = height;
+   bo->format = format;
+   bo->flags = flags;
+   bo->buffer_data = bo_data;
+
+   return bo;
+}
+
+EAPI Ecore_Buffer *
+ecore_buffer_new_with_tbm_surface(const char *engine, void *tbm_surface, unsigned int flags)
+{
+   Ecore_Buffer_Module *bm;
+   Ecore_Buffer *bo;
+   int w = 0, h = 0;
+   Ecore_Buffer_Format format = 0;
+   void *bo_data;
+
+   bm = _ecore_buffer_get_backend(engine);
+   if (!bm)
+     {
+        ERR("Failed to get Backend: %s", engine);
+        return NULL;
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(bm->be, NULL);
+
+   bo_data = bm->be->buffer_alloc_with_tbm_surface(bm->data, tbm_surface,
+                                                   &w, &h, &format, flags);
+   if (!bo_data)
+     return NULL;
+
+   bo = calloc(1, sizeof(Ecore_Buffer));
+   if (!bo)
+     return NULL;
+
+   bo->bm = bm;
+   bo->flags = flags;
+   bo->buffer_data = bo_data;
+   bo->width = w;
+   bo->height = h;
+   bo->format = format;
+
+   return bo;
+}
+
+EAPI void
+ecore_buffer_free(Ecore_Buffer* buf)
+{
+   Ecore_Buffer_Cb_Data* free_cb;
+
+   EINA_SAFETY_ON_NULL_RETURN(buf);
+
+   //Call free_cb
+   while (buf->free_callbacks)
+     {
+        free_cb = EINA_INLIST_CONTAINER_GET(buf->free_callbacks, Ecore_Buffer_Cb_Data);
+        buf->free_callbacks = eina_inlist_remove(buf->free_callbacks, buf->free_callbacks);
+
+        free_cb->cb(buf, free_cb->data);
+        free(free_cb);
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN(buf->bm);
+   EINA_SAFETY_ON_NULL_RETURN(buf->bm->be);
+   EINA_SAFETY_ON_NULL_RETURN(buf->bm->be->buffer_free);
+
+   buf->bm->be->buffer_free(buf->bm->data, buf->buffer_data);
+
+   //Free User Data
+   if (buf->data)
+     eina_hash_free(buf->data);
+
+   free(buf);
+}
+
+EAPI Ecore_Pixmap
+ecore_buffer_pixmap_get(Ecore_Buffer *buf)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm->be, 0);
+
+   if (!buf->bm->be->pixmap_get)
+     return 0;
+
+   return buf->bm->be->pixmap_get(buf->bm->data, buf->buffer_data);
+}
+
+EAPI void *
+ecore_buffer_tbm_surface_get(Ecore_Buffer *buf)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm->be, 0);
+
+   if (!buf->bm->be->tbm_surface_get)
+     {
+        ERR("TBM is not supported\n");
+        return NULL;
+     }
+
+   return buf->bm->be->tbm_surface_get(buf->bm->data, buf->buffer_data);
+}
+
+EAPI Eina_Bool
+ecore_buffer_size_get(Ecore_Buffer *buf, unsigned int *width, unsigned int *height)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, EINA_FALSE);
+
+   if (width) *width = buf->width;
+   if (height) *height = buf->height;
+
+   return EINA_TRUE;
+}
+
+EAPI unsigned int
+ecore_buffer_format_get(Ecore_Buffer *buf)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
+
+   return buf->format;
+}
+
+EAPI unsigned int
+ecore_buffer_flags_get(Ecore_Buffer *buf)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
+
+   return buf->flags;
+}
+
+EAPI void
+ecore_buffer_free_callback_add(Ecore_Buffer* buf, Ecore_Buffer_Cb func, void* data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(buf);
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   Ecore_Buffer_Cb_Data* free_cb;
+
+   free_cb = calloc(sizeof(Ecore_Buffer_Cb_Data), 1);
+   if (!free_cb)
+     return;
+
+   free_cb->cb = func;
+   free_cb->data = data;
+   buf->free_callbacks = eina_inlist_append(buf->free_callbacks, EINA_INLIST_GET(free_cb));
+}
+
+EAPI void
+ecore_buffer_free_callback_remove(Ecore_Buffer* buf, Ecore_Buffer_Cb func, void* data)
+{
+   Ecore_Buffer_Cb_Data* free_cb;
+
+   EINA_SAFETY_ON_NULL_RETURN(buf);
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   if (buf->free_callbacks)
+     {
+        Eina_Inlist *itrn;
+        EINA_INLIST_FOREACH_SAFE(buf->free_callbacks, itrn, free_cb)
+          {
+             if (free_cb->cb == func && free_cb->data == data)
+               {
+                  buf->free_callbacks =
+                     eina_inlist_remove(buf->free_callbacks,
+                                        EINA_INLIST_GET(free_cb));
+                  free(free_cb);
+               }
+          }
+     }
+}
+
+const char *
+_ecore_buffer_engine_name_get(Ecore_Buffer* buf)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm->be, 0);
+
+   return buf->bm->be->name;
+}
+
+Ecore_Export_Type
+_ecore_buffer_export(Ecore_Buffer *buf, int *id)
+{
+   Ecore_Export_Type type = EXPORT_TYPE_INVALID;
+   int ret_id;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf, type);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm, type);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buf->bm->be, type);
+
+   if (!buf->bm->be->buffer_export)
+     return type;
+
+   type = buf->bm->be->buffer_export(buf->bm->data, buf->buffer_data, &ret_id);
+
+   if (id) *id = ret_id;
+
+   return type;
+}
+
+Ecore_Buffer *
+_ecore_buffer_import(const char* engine, int width, int height, Ecore_Buffer_Format format, Ecore_Export_Type type, int export_id, unsigned int flags)
+{
+   Ecore_Buffer_Module* bm;
+   Ecore_Buffer* bo;
+   void *bo_data;
+
+   bm = _ecore_buffer_get_backend(engine);
+   if (!bm)
+     {
+        ERR("Filed to get Backend: %s", engine);
+        return NULL;
+     }
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(bm->be, NULL);
+
+   bo_data = bm->be->buffer_import(bm->data, width, height, format, type, export_id, flags);
+   if (!bo_data)
+     return NULL;
+
+   bo = calloc(1, sizeof(Ecore_Buffer));
+   if (!bo)
+     return NULL;
+
+   bo->bm = bm;
+   bo->width = width;
+   bo->height = height;
+   bo->format = format;
+   bo->flags = flags;
+   bo->buffer_data = bo_data;
+
+   return bo;
+}
+
+void
+_ecore_buffer_user_data_set(Ecore_Buffer *buffer, const void *key, const void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(buffer);
+   EINA_SAFETY_ON_NULL_RETURN(key);
+
+   if (buffer->data)
+     eina_hash_del(buffer->data, key, NULL);
+
+   if (data)
+     {
+        if (!buffer->data)
+          buffer->data = eina_hash_string_superfast_new(NULL);
+
+        eina_hash_add(buffer->data, key, data);
+     }
+}
+
+void *
+_ecore_buffer_user_data_get(Ecore_Buffer *buffer, const void *key)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(key, NULL);
+
+   if (!buffer->data)
+     return NULL;
+
+   return eina_hash_find(buffer->data, key);
+}
diff --git a/src/lib/ecore_buffer/ecore_buffer_connection.c b/src/lib/ecore_buffer/ecore_buffer_connection.c
new file mode 100644 (file)
index 0000000..d73c0a6
--- /dev/null
@@ -0,0 +1,331 @@
+#include "ecore_buffer_connection.h"
+
+struct _Ecore_Buffer_Connection
+{
+   struct wl_display *display;
+   struct wl_registry *registry;
+   struct bq_mgr *bq_mgr;
+
+   int fd;
+   Ecore_Fd_Handler *fd_hdl;
+   Ecore_Idle_Enterer *idle_enterer;
+   Eina_Bool init_done;
+};
+
+int _ecore_buffer_queue_log_dom = -1;
+Ecore_Buffer_Connection *_ecore_buffer_connection = NULL;
+
+static int _ecore_buffer_queue_init_count = 0;
+static Eina_Bool _connection_fatal_error = EINA_FALSE;
+
+static void       _ecore_buffer_connection_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED);
+static void       _ecore_buffer_connection_signal_exit_free(void *data EINA_UNUSED, void *event);
+static void       _ecore_buffer_connection_signal_exit(void);
+static Eina_Bool  _ecore_buffer_connection_cb_fd_handle(void *data, Ecore_Fd_Handler *hdl);
+static Eina_Bool  _ecore_buffer_connection_cb_idle_enterer(void *data);
+static void       _ecore_buffer_connection_cb_registry_global(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version);
+static void       _ecore_buffer_connection_cb_registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name);
+
+static const struct wl_callback_listener _ecore_buffer_connection_init_sync_listener =
+{
+   _ecore_buffer_connection_init_callback
+};
+
+struct wl_registry_listener _ecore_buffer_registry_listener =
+{
+   _ecore_buffer_connection_cb_registry_global,
+   _ecore_buffer_connection_cb_registry_global_remove
+};
+
+EAPI int
+ecore_buffer_queue_init(void)
+{
+   struct wl_callback *callback;
+
+   if (++_ecore_buffer_queue_init_count != 1)
+     return _ecore_buffer_queue_init_count;
+
+   _ecore_buffer_queue_log_dom =
+      eina_log_domain_register("ecore_buffer_queue", EINA_COLOR_GREEN);
+
+   if (_ecore_buffer_queue_log_dom < 0)
+     {
+        EINA_LOG_ERR("Could not register log domain: ecore_buffer_queue");
+        return 0;
+     }
+
+   DBG("Ecore_Buffer_Connection Init");
+
+   _ecore_buffer_connection = calloc(sizeof(Ecore_Buffer_Connection), 1);
+   if (!_ecore_buffer_connection)
+     return --_ecore_buffer_queue_init_count;
+
+   if (!(_ecore_buffer_connection->display = wl_display_connect(NULL)))
+     {
+        ERR("Failed to connect to Queue Server");
+        goto err_connect;
+     }
+
+   _ecore_buffer_connection->fd =
+      wl_display_get_fd(_ecore_buffer_connection->display);
+
+   _ecore_buffer_connection->fd_hdl =
+      ecore_main_fd_handler_add(_ecore_buffer_connection->fd,
+                                ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR,
+                                _ecore_buffer_connection_cb_fd_handle,
+                                _ecore_buffer_connection, NULL, NULL);
+
+   _ecore_buffer_connection->idle_enterer =
+      ecore_idle_enterer_add(_ecore_buffer_connection_cb_idle_enterer,
+                             _ecore_buffer_connection);
+
+   _ecore_buffer_connection->registry =
+      wl_display_get_registry(_ecore_buffer_connection->display);
+   if (!_ecore_buffer_connection->registry)
+     goto err_get_registry;
+
+   wl_registry_add_listener(_ecore_buffer_connection->registry,
+                            &_ecore_buffer_registry_listener,
+                            _ecore_buffer_connection);
+
+   _ecore_buffer_connection->init_done = EINA_FALSE;
+   callback = wl_display_sync(_ecore_buffer_connection->display);
+   wl_callback_add_listener(callback,
+                            &_ecore_buffer_connection_init_sync_listener,
+                            _ecore_buffer_connection);
+
+   return _ecore_buffer_queue_init_count;
+
+err_get_registry:
+   eina_log_domain_unregister(_ecore_buffer_queue_log_dom);
+   wl_display_disconnect(_ecore_buffer_connection->display);
+err_connect:
+   free(_ecore_buffer_connection);
+
+   return --_ecore_buffer_queue_init_count;
+}
+
+EAPI void
+ecore_buffer_queue_shutdown(void)
+{
+   if (_ecore_buffer_queue_init_count < 1)
+     {
+        WARN("Ecore_buffer Disconnect called without Connect");
+        return;
+     }
+
+   DBG("Ecore_Buffer_Connection Shutdown");
+
+   if (!_ecore_buffer_connection)
+     return;
+
+   if (_ecore_buffer_connection->fd_hdl)
+     ecore_main_fd_handler_del(_ecore_buffer_connection->fd_hdl);
+
+   if (_ecore_buffer_connection->idle_enterer)
+     ecore_idle_enterer_del(_ecore_buffer_connection->idle_enterer);
+
+   if (_ecore_buffer_connection->bq_mgr)
+     bq_mgr_destroy(_ecore_buffer_connection->bq_mgr);
+
+   if (_ecore_buffer_connection->display)
+     wl_display_disconnect(_ecore_buffer_connection->display);
+
+   if (_ecore_buffer_queue_log_dom > 0)
+     {
+        eina_log_domain_unregister(_ecore_buffer_queue_log_dom);
+        _ecore_buffer_queue_log_dom = -1;
+     }
+
+   free(_ecore_buffer_connection);
+   _ecore_buffer_connection = NULL;
+}
+
+struct bq_provider *
+_ecore_buffer_connection_provider_create(const char *name)
+{
+   if (!name)
+     return NULL;
+
+   return bq_mgr_create_provider(_ecore_buffer_connection->bq_mgr, name);
+}
+
+struct bq_consumer *
+_ecore_buffer_connection_consumer_create(const char *name, int queue_size, int w, int h)
+{
+   if (!name)
+     return NULL;
+
+   if (queue_size < 1)
+     return NULL;
+
+   if ((w < 1) || (h < 1))
+     return NULL;
+
+   return bq_mgr_create_consumer(_ecore_buffer_connection->bq_mgr,
+                                                  name, queue_size, w, h);
+}
+
+void
+_ecore_buffer_connection_init_wait(void)
+{
+   if (!_ecore_buffer_connection)
+     return;
+
+   if (!_ecore_buffer_connection->display)
+     return;
+
+   while (!_ecore_buffer_connection->init_done)
+     wl_display_dispatch(_ecore_buffer_connection->display);
+}
+
+static void
+_ecore_buffer_connection_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
+{
+   Ecore_Buffer_Connection *conn = data;
+
+   if (!conn)
+     return;
+
+   DBG("Queue Server Connected");
+
+   wl_callback_destroy(callback);
+   conn->init_done = EINA_TRUE;
+}
+
+static void
+_ecore_buffer_connection_signal_exit_free(void *data EINA_UNUSED, void *event)
+{
+   free(event);
+}
+
+static void
+_ecore_buffer_connection_signal_exit(void)
+{
+   Ecore_Event_Signal_Exit *ev;
+
+   ev = calloc(sizeof(Ecore_Event_Signal_Exit), 1);
+   if (!ev)
+     return;
+
+   ev->quit = 1;
+   ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, ev,
+                   _ecore_buffer_connection_signal_exit_free, NULL);
+}
+
+static Eina_Bool
+_ecore_buffer_connection_cb_fd_handle(void *data, Ecore_Fd_Handler *hdl)
+{
+   Ecore_Buffer_Connection *conn = data;
+   int ret = 0;
+
+   if (_connection_fatal_error)
+     return ECORE_CALLBACK_CANCEL;
+
+   if (!conn)
+     return ECORE_CALLBACK_RENEW;
+
+   if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
+     {
+        ERR("Received error on wayland display fd");
+        _connection_fatal_error = EINA_TRUE;
+        _ecore_buffer_connection_signal_exit();
+
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
+     ret = wl_display_dispatch(conn->display);
+   else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
+     {
+        ret = wl_display_flush(conn->display);
+        if (ret == 0)
+          ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
+     }
+
+   if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
+     {
+        _connection_fatal_error = EINA_TRUE;
+
+        /* raise exit signal */
+        _ecore_buffer_connection_signal_exit();
+
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+_ecore_buffer_connection_cb_idle_enterer(void *data)
+{
+   Ecore_Buffer_Connection *conn = data;
+   int ret = 0;
+
+   if (_connection_fatal_error)
+     return ECORE_CALLBACK_CANCEL;
+
+   if (!conn)
+     return ECORE_CALLBACK_RENEW;
+
+   ret = wl_display_get_error(conn->display);
+   if (ret < 0)
+     goto err;
+
+   ret = wl_display_flush(conn->display);
+   if ((ret < 0) && (errno == EAGAIN))
+     ecore_main_fd_handler_active_set(conn->fd_hdl,
+                                      (ECORE_FD_READ | ECORE_FD_WRITE));
+
+   ret = wl_display_dispatch_pending(conn->display);
+   if (ret < 0)
+     goto err;
+
+   return ECORE_CALLBACK_RENEW;
+
+err:
+   if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
+     {
+        _connection_fatal_error = EINA_TRUE;
+
+        /* raise exit signal */
+        _ecore_buffer_connection_signal_exit();
+
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_ecore_buffer_connection_cb_registry_global(void *data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version)
+{
+   Ecore_Buffer_Connection *conn = data;
+
+   if (!conn)
+     return;
+
+   DBG("Added Wl Global Registry - name %d interface %s version %d",
+       id, interface, version);
+
+   if (!strncmp(interface, "bq_mgr", strlen("bq_mgr")))
+     conn->bq_mgr = wl_registry_bind(wl_registry, id, &bq_mgr_interface, 1);
+}
+
+static void
+_ecore_buffer_connection_cb_registry_global_remove(void *data EINA_UNUSED, struct wl_registry *wl_registry EINA_UNUSED, uint32_t name EINA_UNUSED)
+{
+   DBG("Removed Wl Global Registry - name %d", name);
+}
+
+void
+ecore_buffer_queue_sync(void)
+{
+   if (!_ecore_buffer_connection)
+     return;
+
+   if (!_ecore_buffer_connection->display)
+     return;
+
+   wl_display_roundtrip(_ecore_buffer_connection->display);
+}
diff --git a/src/lib/ecore_buffer/ecore_buffer_connection.h b/src/lib/ecore_buffer/ecore_buffer_connection.h
new file mode 100644 (file)
index 0000000..44cec32
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _ECORE_BUFFER_CONNECTION_H_
+#define _ECORE_BUFFER_CONNECTION_H_
+
+#include <stdio.h>
+#include <wayland-client.h>
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_Buffer_Queue.h>
+
+#include "bq_mgr_protocol.h"
+#include "ecore_buffer_private.h"
+
+
+typedef struct _Ecore_Buffer_Connection Ecore_Buffer_Connection;
+
+extern Ecore_Buffer_Connection *_ecore_buffer_connection;
+
+void                  _ecore_buffer_connection_init_wait(void);
+struct bq_provider   *_ecore_buffer_connection_provider_create(const char *name);
+struct bq_consumer   *_ecore_buffer_connection_consumer_create(const char *name, int queue_size, int w, int h);
+
+#endif
diff --git a/src/lib/ecore_buffer/ecore_buffer_consumer.c b/src/lib/ecore_buffer/ecore_buffer_consumer.c
new file mode 100644 (file)
index 0000000..d6d8c79
--- /dev/null
@@ -0,0 +1,410 @@
+#include <stdio.h>
+
+#include <Eina.h>
+#include <Ecore_Buffer.h>
+#include <Ecore_Buffer_Queue.h>
+
+#include "bq_mgr_protocol.h"
+#include "shared_buffer.h"
+#include "buffer_queue.h"
+#include "ecore_buffer_private.h"
+#include "ecore_buffer_connection.h"
+
+struct _Ecore_Buffer_Consumer
+{
+   Ecore_Buffer_Queue *ebq;
+   struct bq_consumer *consumer;
+   struct
+   {
+      void  (*provider_add)      (Ecore_Buffer_Consumer *consumer, void *data);
+      void  (*provider_del)      (Ecore_Buffer_Consumer *consumer, void *data);
+      void  (*enqueue)    (Ecore_Buffer_Consumer *consumer, void *data);
+      void *data;
+   } cb;
+};
+
+static void       _ecore_buffer_consumer_cb_provider_connected(void *data, struct bq_consumer *bq_consumer);
+static void       _ecore_buffer_consumer_cb_provider_disconnected(void *data, struct bq_consumer *bq_consumer);
+static void       _ecore_buffer_consumer_cb_buffer_attached(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *id, const char* engine, int32_t width, int32_t height, int32_t format, uint32_t flags);
+static void       _ecore_buffer_consumer_cb_buffer_id_set(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *buffer, int32_t id, int32_t offset0, int32_t stride0, int32_t offset1, int32_t stride1, int32_t offset2, int32_t stride2);
+static void       _ecore_buffer_consumer_cb_buffer_fd_set(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *buffer, int32_t fd, int32_t offset0, int32_t stride0, int32_t offset1, int32_t stride1, int32_t offset2, int32_t stride2);
+static void       _ecore_buffer_consumer_cb_buffer_detached(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *id);
+static void       _ecore_buffer_consumer_cb_add_buffer(void *data, struct bq_consumer *bq_consumer, struct bq_buffer *buffer, uint32_t serial);
+static void       _ecore_buffer_consumer_cb_buffer_free(Ecore_Buffer* buf, void *data);
+static Eina_Bool  _ecore_buffer_consumer_buffer_import(Ecore_Buffer_Consumer *csmr, Shared_Buffer *sb, int32_t seed, Ecore_Export_Type export_type);
+
+struct bq_consumer_listener _ecore_buffer_consumer_listener =
+{
+   _ecore_buffer_consumer_cb_provider_connected,
+   _ecore_buffer_consumer_cb_provider_disconnected,
+   _ecore_buffer_consumer_cb_buffer_attached,
+   _ecore_buffer_consumer_cb_buffer_id_set,
+   _ecore_buffer_consumer_cb_buffer_fd_set,
+   _ecore_buffer_consumer_cb_buffer_detached,
+   _ecore_buffer_consumer_cb_add_buffer
+};
+
+EAPI Ecore_Buffer_Consumer *
+ecore_buffer_consumer_new(const char *name, int32_t queue_size, int32_t w, int32_t h)
+{
+   Ecore_Buffer_Consumer *csmr;
+   const int default_queue_size = 2;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+
+   if ((w < 1) || (h < 1))
+     return NULL;
+
+   if (queue_size < 2)
+     queue_size = default_queue_size;
+
+   _ecore_buffer_connection_init_wait();
+
+   DBG("Consumer New - name %s, queue size %d, size (%dx%d)",
+       name, queue_size, w, h);
+
+   csmr = calloc(sizeof(Ecore_Buffer_Consumer), 1);
+   if (!csmr)
+     return NULL;
+
+   csmr->ebq = _ecore_buffer_queue_new(w, h, queue_size);
+   if (!csmr->ebq)
+     {
+        free(csmr);
+        return NULL;
+     }
+
+   csmr->consumer =
+      _ecore_buffer_connection_consumer_create(name, queue_size, w, h);
+   if (!csmr->consumer)
+     {
+        _ecore_buffer_queue_free(csmr->ebq);
+        free(csmr);
+        return NULL;
+     }
+
+   bq_consumer_add_listener(csmr->consumer,
+                            &_ecore_buffer_consumer_listener,
+                            csmr);
+
+   return csmr;
+}
+
+EAPI void
+ecore_buffer_consumer_free(Ecore_Buffer_Consumer *csmr)
+{
+   EINA_SAFETY_ON_NULL_RETURN(csmr);
+
+   DBG("Consumer Free");
+
+   if (csmr->ebq)
+     _ecore_buffer_queue_free(csmr->ebq);
+
+   if (csmr->consumer)
+     bq_consumer_destroy(csmr->consumer);
+
+   free(csmr);
+}
+
+EAPI Eina_Bool
+ecore_buffer_consumer_buffer_release(Ecore_Buffer_Consumer *csmr, Ecore_Buffer *buffer)
+{
+   Shared_Buffer *sb = _ecore_buffer_user_data_get(buffer, "shared-buffer");
+   struct bq_buffer *proxy = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(csmr, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, EINA_FALSE);
+
+   if (!sb)
+     {
+        ERR("It doesn't seem to be shared buffer");
+        return EINA_FALSE;
+     }
+
+   DBG("Buffer Release");
+
+   if (!_ecore_buffer_queue_connection_state_get(csmr->ebq))
+     {
+        WARN("Not connected with provider yet");
+        return EINA_FALSE;
+     }
+
+   // already detached buffer, free buffer by deputy.
+   if (_shared_buffer_state_get(sb) == SHARED_BUFFER_STATE_DETACH)
+     {
+        DBG("Free buffer - buffer %p", sb);
+        _ecore_buffer_queue_shared_buffer_remove(csmr->ebq, sb);
+        ecore_buffer_free(buffer);
+     }
+   else
+     {
+        if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_DEQUEUE)
+          {
+             WARN("Failed to Release Buffer -"
+                  "DO NOT Release buffer which is not Dequeued: buffer %p state %s",
+                  sb, _shared_buffer_state_string_get(sb));
+             return EINA_FALSE;
+          }
+
+        if ((proxy = _shared_buffer_proxy_get(sb)))
+          bq_consumer_release_buffer(csmr->consumer, proxy);
+
+        _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_RELEASE);
+     }
+
+   return EINA_TRUE;
+}
+
+EAPI Ecore_Buffer *
+ecore_buffer_consumer_buffer_dequeue(Ecore_Buffer_Consumer *csmr)
+{
+   Shared_Buffer *sb;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(csmr, EINA_FALSE);
+
+   DBG("Buffer Acquire");
+
+   if (!_ecore_buffer_queue_dequeue(csmr->ebq, &sb))
+     {
+        DBG("No Available Buffer in Queue");
+        return NULL;
+     }
+
+   // This should not happen.
+   if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_ENQUEUE)
+     {
+        ERR("Unknown error occured - Not on Enqueued State: buffer %p, state %s",
+            sb, _shared_buffer_state_string_get(sb));
+        return NULL;
+     }
+
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_DEQUEUE);
+
+   return _shared_buffer_buffer_get(sb);
+}
+
+EAPI Eina_Bool
+ecore_buffer_consumer_queue_is_empty(Ecore_Buffer_Consumer *csmr)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(csmr, EINA_FALSE);
+
+   return _ecore_buffer_queue_is_empty(csmr->ebq);
+}
+
+
+EAPI void
+ecore_buffer_consumer_provider_add_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Provider_Add_Cb func, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(consumer);
+
+   consumer->cb.provider_add = func;
+   consumer->cb.data = data;
+}
+
+EAPI void
+ecore_buffer_consumer_provider_del_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Provider_Del_Cb func, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(consumer);
+
+   consumer->cb.provider_del = func;
+   consumer->cb.data = data;
+}
+
+EAPI void
+ecore_buffer_consumer_buffer_enqueued_cb_set(Ecore_Buffer_Consumer *consumer, Ecore_Buffer_Consumer_Enqueue_Cb func, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(consumer);
+
+   consumer->cb.enqueue = func;
+   consumer->cb.data = data;
+}
+
+static void
+_ecore_buffer_consumer_cb_provider_connected(void *data, struct bq_consumer *bq_consumer EINA_UNUSED)
+{
+   Ecore_Buffer_Consumer *csmr = data;
+
+   DBG("Provider Connected");
+
+   if (!csmr)
+     return;
+
+   _ecore_buffer_queue_connection_state_set(csmr->ebq, EINA_TRUE);
+
+   CALLBACK_CALL(csmr, provider_add);
+}
+
+static void
+_ecore_buffer_consumer_cb_provider_disconnected(void *data, struct bq_consumer *bq_consumer EINA_UNUSED)
+{
+   Ecore_Buffer_Consumer *csmr = (Ecore_Buffer_Consumer *)data;
+
+   if (!csmr)
+     return;
+
+   DBG("Provider Disconnected");
+
+   _ecore_buffer_queue_connection_state_set(csmr->ebq, EINA_FALSE);
+
+   CALLBACK_CALL(csmr, provider_del);
+
+   _ecore_buffer_queue_free(csmr->ebq);
+   csmr->ebq = NULL;
+}
+
+static void
+_ecore_buffer_consumer_cb_buffer_attached(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *id, const char* engine, int32_t width, int32_t height, int32_t format, uint32_t flags)
+{
+   Ecore_Buffer_Consumer *csmr = data;
+   Shared_Buffer *sb;
+
+   EINA_SAFETY_ON_NULL_RETURN(csmr);
+
+   if (!csmr->ebq)
+     return;
+
+   DBG("Buffer Attached - engine %s, size (%dx%d), format %d, flags %d",
+       engine, width, height, format, flags);
+
+   sb = _shared_buffer_new(id, width, height, format, flags);
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_ATTACH);
+   _ecore_buffer_queue_shared_buffer_add(csmr->ebq, sb);
+
+   bq_buffer_set_user_data(id, sb);
+}
+
+static void
+_ecore_buffer_consumer_cb_buffer_free(Ecore_Buffer* buf, void *data EINA_UNUSED)
+{
+   Shared_Buffer *sb = _ecore_buffer_user_data_get(buf, "shared-buffer");
+
+   if (!sb) return;
+
+   bq_buffer_destroy(_shared_buffer_proxy_get(sb));
+   _shared_buffer_free(sb);
+}
+
+static void
+_ecore_buffer_consumer_cb_buffer_id_set(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *buffer, int32_t id, int32_t offset0 EINA_UNUSED, int32_t stride0 EINA_UNUSED, int32_t offset1 EINA_UNUSED, int32_t stride1 EINA_UNUSED, int32_t offset2 EINA_UNUSED, int32_t stride2 EINA_UNUSED)
+{
+   Ecore_Buffer_Consumer *csmr = data;
+   Shared_Buffer *sb = bq_buffer_get_user_data(buffer);
+
+   EINA_SAFETY_ON_NULL_RETURN(csmr);
+   EINA_SAFETY_ON_NULL_RETURN(sb);
+
+   if (_ecore_buffer_consumer_buffer_import(csmr, sb, id, EXPORT_TYPE_ID))
+     bq_buffer_set_user_data(buffer, sb);
+}
+
+static void
+_ecore_buffer_consumer_cb_buffer_fd_set(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *buffer, int32_t fd, int32_t offset0 EINA_UNUSED, int32_t stride0 EINA_UNUSED, int32_t offset1 EINA_UNUSED, int32_t stride1 EINA_UNUSED, int32_t offset2 EINA_UNUSED, int32_t stride2 EINA_UNUSED)
+{
+   Ecore_Buffer_Consumer *csmr = data;
+   Shared_Buffer *sb = bq_buffer_get_user_data(buffer);
+
+   EINA_SAFETY_ON_NULL_RETURN(csmr);
+   EINA_SAFETY_ON_NULL_RETURN(sb);
+
+   if (_ecore_buffer_consumer_buffer_import(csmr, sb, fd, EXPORT_TYPE_FD))
+     bq_buffer_set_user_data(buffer, sb);
+}
+
+static void
+_ecore_buffer_consumer_cb_buffer_detached(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *id)
+{
+   Ecore_Buffer_Consumer *csmr = (Ecore_Buffer_Consumer *)data;
+   Shared_Buffer *sb = (Shared_Buffer *)bq_buffer_get_user_data(id);
+
+   EINA_SAFETY_ON_NULL_RETURN(csmr);
+   EINA_SAFETY_ON_NULL_RETURN(sb);
+
+   DBG("Buffer Detached");
+
+   // buffer is not yet belong to consumer. free.
+   // NOTE: do we need to notify this to application ??
+   if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_DEQUEUE)
+     {
+        DBG("Free buffer - buffer %p, state %s",
+            sb, _shared_buffer_state_string_get(sb));
+
+        _ecore_buffer_queue_shared_buffer_remove(csmr->ebq, sb);
+        ecore_buffer_free(_shared_buffer_buffer_get(sb));
+        return;
+     }
+
+   // mark this buffer is detached, and then free on buffer release time.
+   DBG("Just mark this buffer to free it when released - buffer %p, state %s",
+       sb, "SHARED_BUFFER_STATE_ACQUIRE");
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_DETACH);
+}
+
+static void
+_ecore_buffer_consumer_cb_add_buffer(void *data, struct bq_consumer *bq_consumer EINA_UNUSED, struct bq_buffer *buffer, uint32_t serial EINA_UNUSED)
+{
+   Ecore_Buffer_Consumer *csmr = data;
+   Shared_Buffer *sb = bq_buffer_get_user_data(buffer);
+   Shared_Buffer_State state;
+
+   EINA_SAFETY_ON_NULL_RETURN(csmr);
+
+   DBG("Buffer Enqueued");
+
+   if (!sb)
+     {
+        ERR("Unknown Error occured - maybe this buffer is not shared yet");
+        return;
+     }
+
+   state = _shared_buffer_state_get(sb);
+   if ((state != SHARED_BUFFER_STATE_IMPORT) &&
+       (state != SHARED_BUFFER_STATE_RELEASE))
+     {
+        ERR("Unknown Error occured - Could not enqueued this state of buffer: buffer %p, state %s",
+            sb, _shared_buffer_state_string_get(sb));
+        return;
+     }
+
+   _ecore_buffer_queue_enqueue(csmr->ebq, sb);
+
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_ENQUEUE);
+
+   CALLBACK_CALL(csmr, enqueue);
+}
+
+static Eina_Bool
+_ecore_buffer_consumer_buffer_import(Ecore_Buffer_Consumer *csmr, Shared_Buffer *sb, int32_t seed, Ecore_Export_Type export_type)
+{
+   Ecore_Buffer *buffer;
+   int w, h, format;
+   unsigned int flags;
+
+   if ((!sb) ||
+       (!_shared_buffer_info_get(sb, &w, &h, &format, &flags)))
+     {
+        ERR("Failed to Get Shared Buffer");
+        return EINA_FALSE;
+     }
+
+   if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_ATTACH)
+     {
+        ERR("Not Attached Buffer - buffer %p state %s",
+            sb, _shared_buffer_state_string_get(sb));
+        return EINA_FALSE;
+     }
+
+   if (!(buffer = _ecore_buffer_import(NULL, w, h, format, export_type, seed, flags)))
+     {
+        ERR("Failed to Import Buffer - size (%dx%d), foramt %d, seed %d, export_type %d",
+            w, h, format, seed, export_type);
+        return EINA_FALSE;
+     }
+
+   _ecore_buffer_user_data_set(buffer, "shared-buffer", sb);
+   ecore_buffer_free_callback_add(buffer, _ecore_buffer_consumer_cb_buffer_free, csmr);
+
+   _shared_buffer_buffer_set(sb, buffer);
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_IMPORT);
+
+   return EINA_TRUE;
+}
diff --git a/src/lib/ecore_buffer/ecore_buffer_private.h b/src/lib/ecore_buffer/ecore_buffer_private.h
new file mode 100644 (file)
index 0000000..b5df57a
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _ECORE_BUFFER_PRIVATE_H_
+# define _ECORE_BUFFER_PRIVATE_H_
+
+#ifdef ERR
+#undef ERR
+#endif
+#ifdef WARN
+#undef WARN
+#endif
+#ifdef DBG
+#undef DBG
+#endif
+
+#define ERR(...)  EINA_LOG_DOM_ERR(_ecore_buffer_queue_log_dom, __VA_ARGS__)
+#define DBG(...)  EINA_LOG_DOM_DBG(_ecore_buffer_queue_log_dom, __VA_ARGS__)
+#define WARN(...) EINA_LOG_DOM_WARN(_ecore_buffer_queue_log_dom, __VA_ARGS__)
+
+#define NFREE(_func_, _data_)                   \
+do                                              \
+{                                               \
+   if (_data_)                                  \
+     {                                          \
+        _func_(_data_);                         \
+        _data_ = NULL;                          \
+     }                                          \
+} while(0)
+
+#define CALLBACK_CALL(obj, cbname)           \
+do {                                         \
+     if (obj->cb.cbname)                     \
+       obj->cb.cbname(obj, obj->cb.data);    \
+} while(0)
+
+extern int _ecore_buffer_queue_log_dom;
+
+const char        *_ecore_buffer_engine_name_get(Ecore_Buffer* buf);
+Ecore_Export_Type  _ecore_buffer_export(Ecore_Buffer *buf, int *id);
+Ecore_Buffer      *_ecore_buffer_import(const char* engine, int width, int height, Ecore_Buffer_Format format, Ecore_Export_Type type, int export_id, unsigned int flags);
+void               _ecore_buffer_user_data_set(Ecore_Buffer *buf, const void *key, const void *data);
+void              *_ecore_buffer_user_data_get(Ecore_Buffer *buf, const void *key);
+
+#endif /* _ECORE_BUFFER_PRIVATE_H_ */
diff --git a/src/lib/ecore_buffer/ecore_buffer_provider.c b/src/lib/ecore_buffer/ecore_buffer_provider.c
new file mode 100644 (file)
index 0000000..a150e9d
--- /dev/null
@@ -0,0 +1,401 @@
+#include <stdio.h>
+
+#include <Eina.h>
+#include <Ecore_Buffer.h>
+#include <Ecore_Buffer_Queue.h>
+
+#include "bq_mgr_protocol.h"
+#include "shared_buffer.h"
+#include "buffer_queue.h"
+#include "ecore_buffer_private.h"
+#include "ecore_buffer_connection.h"
+
+struct _Ecore_Buffer_Provider
+{
+   struct bq_provider *provider;
+   Ecore_Buffer_Queue *ebq;
+   int free_slot;
+   struct
+   {
+      void  (*consumer_add)      (Ecore_Buffer_Provider *provider, int queue_size, int w, int h, void *data);
+      void  (*consumer_del)      (Ecore_Buffer_Provider *provider, void *data);
+      void  (*enqueue)           (Ecore_Buffer_Provider *provider, void *data);
+      void *data;
+   } cb;
+};
+
+static void           _ecore_buffer_provider_cb_consumer_connected(void *data, struct bq_provider *bq_provider, int32_t queue_size, int32_t width, int32_t height);
+static void           _ecore_buffer_provider_cb_consumer_disconnected(void *data, struct bq_provider *bq_provider);
+static void           _ecore_buffer_provider_cb_add_buffer(void *data, struct bq_provider *bq_provider, struct bq_buffer *buffer, uint32_t serial);
+static Shared_Buffer *_ecore_buffer_provider_shared_buffer_new(Ecore_Buffer_Provider *pvdr, Ecore_Buffer *buffer);
+static void           _ecore_buffer_provider_shared_buffer_free(Ecore_Buffer_Provider *pvdr, Shared_Buffer *sb);
+static void           _ecore_buffer_provider_cb_buffer_free(Ecore_Buffer* buf, void *data);
+
+struct bq_provider_listener _ecore_buffer_provider_listener =
+{
+   _ecore_buffer_provider_cb_consumer_connected,
+   _ecore_buffer_provider_cb_consumer_disconnected,
+   _ecore_buffer_provider_cb_add_buffer
+};
+
+EAPI Ecore_Buffer_Provider *
+ecore_buffer_provider_new(const char *name)
+{
+   Ecore_Buffer_Provider *pvdr;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
+
+   _ecore_buffer_connection_init_wait();
+
+   DBG("Provider New - name %s", name);
+
+   pvdr = calloc(sizeof(Ecore_Buffer_Provider), 1);
+   if (!pvdr)
+     return NULL;
+
+   pvdr->provider = _ecore_buffer_connection_provider_create(name);
+   if (!pvdr->provider)
+     {
+        free(pvdr);
+        return NULL;
+     }
+
+   bq_provider_add_listener(pvdr->provider, &_ecore_buffer_provider_listener, pvdr);
+   bq_provider_set_user_data(pvdr->provider, pvdr);
+
+   return pvdr;
+}
+
+EAPI void
+ecore_buffer_provider_free(Ecore_Buffer_Provider *pvdr)
+{
+   Eina_List *shared_buffers;
+   Shared_Buffer *sb;
+
+   EINA_SAFETY_ON_NULL_RETURN(pvdr);
+
+   DBG("Provider Free");
+
+   if (pvdr->ebq)
+     {
+        shared_buffers = _ecore_buffer_queue_shared_buffer_list_get(pvdr->ebq);
+        EINA_LIST_FREE(shared_buffers, sb)
+           _ecore_buffer_provider_shared_buffer_free(pvdr, sb);
+
+        _ecore_buffer_queue_free(pvdr->ebq);
+        pvdr->ebq = NULL;
+     }
+
+   bq_provider_destroy(pvdr->provider);
+   free(pvdr);
+}
+
+EAPI Ecore_Buffer_Return
+ecore_buffer_provider_buffer_acquire(Ecore_Buffer_Provider *pvdr, Ecore_Buffer **ret_buf)
+{
+   Ecore_Buffer_Queue *ebq;
+   Shared_Buffer *sb;
+   Ecore_Buffer_Return ret_flag = ECORE_BUFFER_RETURN_ERROR;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pvdr, ret_flag);
+
+   if (!(ebq = pvdr->ebq))
+     return ret_flag;
+
+   DBG("Buffer Acquire");
+
+   if (!_ecore_buffer_queue_dequeue(pvdr->ebq, &sb))
+     {
+        // Empty Queue.
+        ret_flag = ECORE_BUFFER_RETURN_EMPTY;
+
+        // Check if exist free slot.
+        if (pvdr->free_slot > 0)
+          ret_flag = ECORE_BUFFER_RETURN_NEED_ALLOC;
+     }
+   else
+     {
+        // This should not happen.
+        if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_RELEASE)
+          {
+             ERR("Unknown error occured - Not on Released State: buffer %p state %s",
+                 sb, _shared_buffer_state_string_get(sb));
+             return ECORE_BUFFER_RETURN_ERROR;
+          }
+
+        _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_ACQUIRE);
+        ret_flag = ECORE_BUFFER_RETURN_SUCCESS;
+
+        if (ret_buf) *ret_buf = _shared_buffer_buffer_get(sb);
+     }
+
+   return ret_flag;
+}
+
+EAPI Eina_Bool
+ecore_buffer_provider_buffer_enqueue(Ecore_Buffer_Provider *pvdr, Ecore_Buffer *buffer)
+{
+   Shared_Buffer *sb = _ecore_buffer_user_data_get(buffer, "shared-buffer");
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pvdr, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(buffer, EINA_FALSE);
+
+   DBG("Buffer Enqueue");
+
+   if (!_ecore_buffer_queue_connection_state_get(pvdr->ebq))
+     {
+        WARN("Not connected with consumer yet");
+        return EINA_FALSE;
+     }
+
+   if (!sb)
+     {
+        // this buffer was never attached before.
+        if (pvdr->free_slot > 0)
+          {
+             sb = _ecore_buffer_provider_shared_buffer_new(pvdr, buffer);
+             if (!sb)
+               {
+                  ERR("Unkown error occured -"
+                      "Failed to attach buffer: buffer %p", buffer);
+                  return EINA_FALSE;
+               }
+
+             pvdr->free_slot--;
+          }
+        else
+          {
+             WARN("No Free slot in Queue."
+                  "Need to ecore_buffer_free of submitted buffer first.");
+             return EINA_FALSE;
+          }
+     }
+
+   if (_shared_buffer_state_get(sb) != SHARED_BUFFER_STATE_ACQUIRE)
+     {
+        ERR("Failed to enqueue buffer - Not on acquired state: buffer %p state %s",
+            sb, _shared_buffer_state_string_get(sb));
+        return EINA_FALSE;
+     }
+
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_ENQUEUE);
+   bq_provider_enqueue_buffer(pvdr->provider, _shared_buffer_proxy_get(sb), 0); // serial?
+
+   return EINA_TRUE;
+}
+
+EAPI Ecore_Buffer_Return
+ecore_buffer_provider_buffer_acquirable_check(Ecore_Buffer_Provider *pvdr)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(pvdr, EINA_FALSE);
+
+   if (_ecore_buffer_queue_is_empty(pvdr->ebq))
+     {
+        if (pvdr->free_slot > 0)
+          return ECORE_BUFFER_RETURN_NEED_ALLOC;
+
+        return ECORE_BUFFER_RETURN_EMPTY;
+     }
+
+   return ECORE_BUFFER_RETURN_NOT_EMPTY;
+}
+
+EAPI void
+ecore_buffer_provider_consumer_add_cb_set(Ecore_Buffer_Provider *provider, Ecore_Buffer_Provider_Consumer_Add_Cb func, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(provider);
+
+   provider->cb.consumer_add = func;
+   provider->cb.data = data;
+}
+
+EAPI void
+ecore_buffer_provider_consumer_del_cb_set(Ecore_Buffer_Provider *provider, Ecore_Buffer_Provider_Consumer_Del_Cb func, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(provider);
+
+   provider->cb.consumer_del = func;
+   provider->cb.data = data;
+}
+
+EAPI void
+ecore_buffer_provider_buffer_released_cb_set(Ecore_Buffer_Provider *provider, Ecore_Buffer_Provider_Enqueue_Cb func, void *data)
+{
+   EINA_SAFETY_ON_NULL_RETURN(provider);
+
+   provider->cb.enqueue = func;
+   provider->cb.data = data;
+}
+
+static void
+_ecore_buffer_provider_cb_consumer_connected(void *data, struct bq_provider *bq_provider EINA_UNUSED, int32_t queue_size, int32_t width, int32_t height)
+{
+   Ecore_Buffer_Provider *pvdr = data;
+
+   EINA_SAFETY_ON_NULL_RETURN(pvdr);
+
+   DBG("Consumer Connected - queue_size %d, size (%dx%d)",
+       queue_size, width, height);
+
+   if (!(pvdr->ebq = _ecore_buffer_queue_new(width, height, queue_size)))
+     {
+        ERR("Failed to create Ecore_Buffer_Queue - queue_size %d, size (%dx%d)",
+            queue_size, width, height);
+        return;
+     }
+
+   _ecore_buffer_queue_connection_state_set(pvdr->ebq, EINA_TRUE);
+
+   // set the number of free slot which means allocatable buffer number.
+   pvdr->free_slot = queue_size;
+
+   // CALLBACK_CALL
+   if (pvdr->cb.consumer_add)
+     pvdr->cb.consumer_add(pvdr, queue_size, width, height, pvdr->cb.data);
+}
+
+static void
+_ecore_buffer_provider_cb_consumer_disconnected(void *data, struct bq_provider *bq_provider EINA_UNUSED)
+{
+   Ecore_Buffer_Provider *pvdr = data;
+
+   if (!pvdr)
+     return;
+
+   DBG("Consumer Disconnected");
+
+   _ecore_buffer_queue_connection_state_set(pvdr->ebq, EINA_FALSE);
+
+   // maybe, we should free buffer queue before callback call.
+   _ecore_buffer_queue_free(pvdr->ebq);
+
+   CALLBACK_CALL(pvdr, consumer_del);
+}
+
+static void
+_ecore_buffer_provider_cb_add_buffer(void *data, struct bq_provider *bq_provider EINA_UNUSED, struct bq_buffer *buffer, uint32_t serial EINA_UNUSED)
+{
+   Ecore_Buffer_Provider *pvdr = data;
+   Shared_Buffer *sb = bq_buffer_get_user_data(buffer);
+
+   if ((!pvdr) || (!sb))
+     return;
+
+   DBG("Buffer Enqueued");
+
+   _ecore_buffer_queue_enqueue(pvdr->ebq, sb);
+
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_RELEASE);
+
+   CALLBACK_CALL(pvdr, enqueue);
+}
+
+static void
+_ecore_buffer_provider_cb_buffer_free(Ecore_Buffer* buf, void *data)
+{
+   Ecore_Buffer_Provider *pvdr = data;
+   Shared_Buffer *sb = _ecore_buffer_user_data_get(buf, "shared-buffer");
+
+   if ((!pvdr) || (!sb))
+     return;
+
+   _ecore_buffer_provider_shared_buffer_free(pvdr, sb);
+   pvdr->free_slot++;
+}
+
+static Shared_Buffer *
+_ecore_buffer_provider_shared_buffer_new(Ecore_Buffer_Provider *pvdr, Ecore_Buffer *buffer)
+{
+   Shared_Buffer *sb = NULL;
+   struct bq_buffer *bq_buffer;
+   unsigned int w = 0, h = 0, format = 0;
+   Ecore_Export_Type export_type;
+   int export_id;
+   const char* engine;
+   unsigned int flags;
+
+   if (!pvdr)
+     return NULL;
+
+   if (!buffer)
+     {
+        ERR("Cannot attach NULL buffer");
+        return NULL;
+     }
+
+   DBG("Buffer Attach");
+
+   if (!_ecore_buffer_queue_connection_state_get(pvdr->ebq))
+     {
+        WARN("Not Connected");
+        return NULL;
+     }
+
+   ecore_buffer_size_get(buffer, &w, &h);
+   format = ecore_buffer_format_get(buffer);
+   export_type = _ecore_buffer_export(buffer, &export_id);
+   engine = _ecore_buffer_engine_name_get(buffer);
+   flags = ecore_buffer_flags_get(buffer);
+
+   bq_buffer = bq_provider_attach_buffer(pvdr->provider, engine, w, h, format, flags);
+   if (!bq_buffer)
+     {
+        ERR("Fail to attach buffer - engine %s, size (%dx%d), format %d, flags %d",
+            engine, w, h, format, flags);
+        return NULL;
+     }
+
+   switch (export_type)
+     {
+      case EXPORT_TYPE_ID:
+         bq_provider_set_buffer_id(pvdr->provider, bq_buffer,
+                                   export_id, 0, 0, 0, 0, 0, 0);
+         break;
+      case EXPORT_TYPE_FD:
+         bq_provider_set_buffer_fd(pvdr->provider, bq_buffer,
+                                   export_id, 0, 0, 0, 0, 0, 0);
+         break;
+      default:
+         break;
+     }
+
+   sb = _shared_buffer_new(bq_buffer, w, h, format, flags);
+   _shared_buffer_buffer_set(sb, buffer);
+   _shared_buffer_state_set(sb, SHARED_BUFFER_STATE_ACQUIRE);
+
+   bq_buffer_set_user_data(bq_buffer, sb);
+   _ecore_buffer_user_data_set(buffer, "shared-buffer", sb);
+
+   _ecore_buffer_queue_shared_buffer_add(pvdr->ebq, sb);
+
+   ecore_buffer_free_callback_add(buffer, _ecore_buffer_provider_cb_buffer_free, pvdr);
+
+   return sb;
+}
+
+static void
+_ecore_buffer_provider_shared_buffer_free(Ecore_Buffer_Provider *pvdr, Shared_Buffer *sb)
+{
+   struct bq_buffer *proxy = _shared_buffer_proxy_get(sb);
+
+   if ((!pvdr) || (!pvdr->ebq))
+     return;
+
+   if ((!sb) || (!proxy))
+     return;
+
+   DBG("Buffer Detach");
+
+   if (!_ecore_buffer_queue_connection_state_get(pvdr->ebq))
+     {
+        WARN("Not connected with consumer yet");
+        return;
+     }
+
+   bq_provider_detach_buffer(pvdr->provider, proxy);
+   bq_buffer_destroy(proxy);
+
+   _ecore_buffer_queue_shared_buffer_remove(pvdr->ebq, sb);
+
+   _shared_buffer_free(sb);
+}
diff --git a/src/lib/ecore_buffer/shared_buffer.c b/src/lib/ecore_buffer/shared_buffer.c
new file mode 100644 (file)
index 0000000..0f68835
--- /dev/null
@@ -0,0 +1,153 @@
+#include "shared_buffer.h"
+
+struct _Shared_Buffer
+{
+   Ecore_Buffer *buffer;
+   Shared_Buffer_State state;
+   struct bq_buffer *proxy;
+   int w, h;
+   int format;
+   unsigned int flags;
+   const char *backend;
+};
+
+Shared_Buffer *
+_shared_buffer_new(struct bq_buffer *proxy, int w, int h, int format, unsigned int flags)
+{
+   Shared_Buffer *sb;
+
+   sb = calloc(sizeof(Shared_Buffer), 1);
+   if (!sb)
+     return NULL;
+
+   sb->proxy = proxy;
+   sb->w = w;
+   sb->h = h;
+   sb->format = format;
+   sb->flags = flags;
+
+   return sb;
+}
+
+void
+_shared_buffer_free(Shared_Buffer *sb)
+{
+   if (!sb)
+     return;
+
+   free(sb);
+}
+
+Eina_Bool
+_shared_buffer_info_get(Shared_Buffer *sb, int *w, int *h, int *format, unsigned int *flags)
+{
+   if (!sb)
+     return EINA_FALSE;
+
+   if (w) *w = sb->w;
+   if (h) *h = sb->h;
+   if (format) *format = sb->format;
+   if (flags) *flags = sb->flags;
+
+   return EINA_TRUE;
+}
+
+Eina_Bool
+_shared_buffer_buffer_set(Shared_Buffer *sb, Ecore_Buffer *buffer)
+{
+   if (!sb)
+     return EINA_FALSE;
+
+   if (sb->buffer)
+     {
+        ERR("Already exist buffer");
+        return EINA_FALSE;
+     }
+
+   sb->buffer = buffer;
+
+   return EINA_TRUE;
+}
+
+Ecore_Buffer *
+_shared_buffer_buffer_get(Shared_Buffer *sb)
+{
+   if (!sb)
+     return NULL;
+
+   return sb->buffer;
+}
+
+Eina_Bool
+_shared_buffer_proxy_set(Shared_Buffer *sb, struct bq_buffer *proxy)
+{
+   if (!sb)
+     return EINA_FALSE;
+
+   if (sb->proxy)
+     {
+        ERR("Already exist proxy");
+        return EINA_FALSE;
+     }
+
+   sb->proxy = proxy;
+
+   return EINA_TRUE;
+}
+
+struct bq_buffer *
+_shared_buffer_proxy_get(Shared_Buffer *sb)
+{
+   if (!sb)
+     return NULL;
+
+   return sb->proxy;
+}
+
+void
+_shared_buffer_state_set(Shared_Buffer *sb, Shared_Buffer_State state)
+{
+   if (!sb)
+     return;
+
+   sb->state = state;
+}
+
+Shared_Buffer_State
+_shared_buffer_state_get(Shared_Buffer *sb)
+{
+   if (!sb)
+     return SHARED_BUFFER_STATE_UNKNOWN;
+
+   return sb->state;
+}
+
+const char *
+_shared_buffer_state_string_get(Shared_Buffer *sb)
+{
+   if (!sb)
+     return "INVALID_OBJECT";
+
+   switch (sb->state)
+     {
+      case SHARED_BUFFER_STATE_ENQUEUE:
+         return "SHARED_BUFFER_STATE_ENQUEUE";
+      case SHARED_BUFFER_STATE_SUBMIT:
+         return "SHARED_BUFFER_STATE_SUBMIT";
+      case SHARED_BUFFER_STATE_DEQUEUE:
+         return "SHARED_BUFFER_STATE_SUBMIT";
+      case SHARED_BUFFER_STATE_ATTACH:
+         return "SHARED_BUFFER_STATE_ATTACH";
+      case SHARED_BUFFER_STATE_IMPORT:
+         return "SHARED_BUFFER_STATE_IMPORT";
+      case SHARED_BUFFER_STATE_DETACH:
+         return "SHARED_BUFFER_STATE_DETACH";
+      case SHARED_BUFFER_STATE_ACQUIRE:
+         return "SHARED_BUFFER_STATE_ACQUIRE";
+      case SHARED_BUFFER_STATE_RELEASE:
+         return "SHARED_BUFFER_STATE_RELEASE";
+      default:
+      case SHARED_BUFFER_STATE_UNKNOWN:
+         return "SHARED_BUFFER_STATE_UNKNOWN";
+     }
+}
diff --git a/src/lib/ecore_buffer/shared_buffer.h b/src/lib/ecore_buffer/shared_buffer.h
new file mode 100644 (file)
index 0000000..266fe58
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _SHARED_BUFFER_H_
+# define _SHARED_BUFFER_H_
+
+#include <stdio.h>
+#include <Eina.h>
+#include <Ecore_Buffer.h>
+
+#include "bq_mgr_protocol.h"
+#include "ecore_buffer_private.h"
+
+typedef struct _Shared_Buffer Shared_Buffer;
+
+typedef enum _Shared_Buffer_State
+{
+   // common
+   SHARED_BUFFER_STATE_UNKNOWN,
+   SHARED_BUFFER_STATE_ENQUEUE,
+   // provider side type
+   SHARED_BUFFER_STATE_SUBMIT,
+   SHARED_BUFFER_STATE_DEQUEUE,
+   // consumer side type
+   SHARED_BUFFER_STATE_ATTACH,
+   SHARED_BUFFER_STATE_IMPORT,
+   SHARED_BUFFER_STATE_DETACH,
+   SHARED_BUFFER_STATE_ACQUIRE,
+   SHARED_BUFFER_STATE_RELEASE,
+} Shared_Buffer_State;
+
+Shared_Buffer        *_shared_buffer_new(struct bq_buffer *proxy, int w, int h, int format, unsigned int flags);
+void                  _shared_buffer_free(Shared_Buffer *sb);
+Eina_Bool             _shared_buffer_info_get(Shared_Buffer *sb, int *w, int *h, int *format, unsigned int *flags);
+Eina_Bool             _shared_buffer_buffer_set(Shared_Buffer *sb, Ecore_Buffer *buffer);
+Ecore_Buffer         *_shared_buffer_buffer_get(Shared_Buffer *sb);
+Eina_Bool             _shared_buffer_proxy_set(Shared_Buffer *sb, struct bq_buffer *proxy);
+struct bq_buffer     *_shared_buffer_proxy_get(Shared_Buffer *sb);
+void                  _shared_buffer_state_set(Shared_Buffer *sb, Shared_Buffer_State state);
+Shared_Buffer_State   _shared_buffer_state_get(Shared_Buffer *sb);
+const char           *_shared_buffer_state_string_get(Shared_Buffer *sb);
+
+#endif /* _SHARED_BUFFER_H_ */
diff --git a/src/modules/ecore_buffer/tbm/ecore_buffer_tbm.c b/src/modules/ecore_buffer/tbm/ecore_buffer_tbm.c
new file mode 100644 (file)
index 0000000..8f8abfb
--- /dev/null
@@ -0,0 +1,293 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Ecore.h>
+
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+
+#include <Ecore_Buffer.h>
+#include "ecore_buffer_private.h"
+
+typedef struct _Ecore_Buffer_Module_Tbm_Data Ecore_Buffer_Module_Tbm_Data;
+typedef struct _Ecore_Buffer_Tbm_Data Ecore_Buffer_Tbm_Data;
+
+struct _Ecore_Buffer_Module_Tbm_Data {
+     tbm_bufmgr tbm_mgr;
+};
+
+struct _Ecore_Buffer_Tbm_Data {
+     void *tbm_surface;
+     int w;
+     int h;
+     int stride;
+     unsigned int flags;
+     Ecore_Buffer_Format format;
+     Eina_Bool is_imported;
+};
+
+static int
+_buf_get_num_planes(Ecore_Buffer_Format format)
+{
+   int num_planes = 0;
+
+   switch (format)
+     {
+      case ECORE_BUFFER_FORMAT_C8:
+      case ECORE_BUFFER_FORMAT_RGB332:
+      case ECORE_BUFFER_FORMAT_BGR233:
+      case ECORE_BUFFER_FORMAT_XRGB4444:
+      case ECORE_BUFFER_FORMAT_XBGR4444:
+      case ECORE_BUFFER_FORMAT_RGBX4444:
+      case ECORE_BUFFER_FORMAT_BGRX4444:
+      case ECORE_BUFFER_FORMAT_ARGB4444:
+      case ECORE_BUFFER_FORMAT_ABGR4444:
+      case ECORE_BUFFER_FORMAT_RGBA4444:
+      case ECORE_BUFFER_FORMAT_BGRA4444:
+      case ECORE_BUFFER_FORMAT_XRGB1555:
+      case ECORE_BUFFER_FORMAT_XBGR1555:
+      case ECORE_BUFFER_FORMAT_RGBX5551:
+      case ECORE_BUFFER_FORMAT_BGRX5551:
+      case ECORE_BUFFER_FORMAT_ARGB1555:
+      case ECORE_BUFFER_FORMAT_ABGR1555:
+      case ECORE_BUFFER_FORMAT_RGBA5551:
+      case ECORE_BUFFER_FORMAT_BGRA5551:
+      case ECORE_BUFFER_FORMAT_RGB565:
+      case ECORE_BUFFER_FORMAT_BGR565:
+      case ECORE_BUFFER_FORMAT_RGB888:
+      case ECORE_BUFFER_FORMAT_BGR888:
+      case ECORE_BUFFER_FORMAT_XRGB8888:
+      case ECORE_BUFFER_FORMAT_XBGR8888:
+      case ECORE_BUFFER_FORMAT_RGBX8888:
+      case ECORE_BUFFER_FORMAT_BGRX8888:
+      case ECORE_BUFFER_FORMAT_ARGB8888:
+      case ECORE_BUFFER_FORMAT_ABGR8888:
+      case ECORE_BUFFER_FORMAT_RGBA8888:
+      case ECORE_BUFFER_FORMAT_BGRA8888:
+      case ECORE_BUFFER_FORMAT_XRGB2101010:
+      case ECORE_BUFFER_FORMAT_XBGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBX1010102:
+      case ECORE_BUFFER_FORMAT_BGRX1010102:
+      case ECORE_BUFFER_FORMAT_ARGB2101010:
+      case ECORE_BUFFER_FORMAT_ABGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBA1010102:
+      case ECORE_BUFFER_FORMAT_BGRA1010102:
+      case ECORE_BUFFER_FORMAT_YUYV:
+      case ECORE_BUFFER_FORMAT_YVYU:
+      case ECORE_BUFFER_FORMAT_UYVY:
+      case ECORE_BUFFER_FORMAT_VYUY:
+      case ECORE_BUFFER_FORMAT_AYUV:
+         num_planes = 1;
+         break;
+      case ECORE_BUFFER_FORMAT_NV12:
+      case ECORE_BUFFER_FORMAT_NV21:
+      case ECORE_BUFFER_FORMAT_NV16:
+      case ECORE_BUFFER_FORMAT_NV61:
+         num_planes = 2;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV410:
+      case ECORE_BUFFER_FORMAT_YVU410:
+      case ECORE_BUFFER_FORMAT_YUV411:
+      case ECORE_BUFFER_FORMAT_YVU411:
+      case ECORE_BUFFER_FORMAT_YUV420:
+      case ECORE_BUFFER_FORMAT_YVU420:
+      case ECORE_BUFFER_FORMAT_YUV422:
+      case ECORE_BUFFER_FORMAT_YVU422:
+      case ECORE_BUFFER_FORMAT_YUV444:
+      case ECORE_BUFFER_FORMAT_YVU444:
+         num_planes = 3;
+         break;
+
+      default:
+         break;
+     }
+
+   return num_planes;
+}
+
+static Ecore_Buffer_Module_Data
+_ecore_buffer_tbm_init(const char *context EINA_UNUSED, const char *options EINA_UNUSED)
+{
+   Ecore_Buffer_Module_Tbm_Data *mdata = NULL;
+
+   mdata = calloc(sizeof(Ecore_Buffer_Module_Tbm_Data), 1);
+
+   mdata->tbm_mgr = tbm_bufmgr_init(-1);
+   if (!mdata->tbm_mgr)
+     {
+        free(mdata);
+        return NULL;
+     }
+
+   return mdata;
+}
+
+static void
+_ecore_buffer_tbm_shutdown(Ecore_Buffer_Module_Data bmdata)
+{
+   Ecore_Buffer_Module_Tbm_Data *bm = bmdata;
+
+   if (!bm) return;
+
+   if (bm->tbm_mgr)
+     tbm_bufmgr_deinit(bm->tbm_mgr);
+
+   free(bm);
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_tbm_buffer_alloc(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, int width, int height, Ecore_Buffer_Format format, unsigned int flags)
+{
+   Ecore_Buffer_Tbm_Data *buf;
+
+   /* invalid size */
+   if ((width < 1) || (height < 1))
+     return NULL;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_Tbm_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = width;
+   buf->h = height;
+   buf->flags = flags;
+   buf->format = format;
+   buf->is_imported = EINA_FALSE;
+   buf->tbm_surface = tbm_surface_create(width, height, (tbm_format)format);
+   if (!buf->tbm_surface)
+     {
+        free(buf);
+        return NULL;
+     }
+
+   return buf;
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_tbm_buffer_alloc_with_tbm_surface(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, void *tbm_surface, int *ret_w, int *ret_h, Ecore_Buffer_Format *ret_format, unsigned int flags)
+{
+   Ecore_Buffer_Tbm_Data *buf;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_Tbm_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = tbm_surface_get_width(tbm_surface);
+   buf->h = tbm_surface_get_height(tbm_surface);
+   buf->format = tbm_surface_get_format(tbm_surface);
+   buf->flags = flags;
+   buf->is_imported = EINA_FALSE;
+   buf->tbm_surface = tbm_surface;
+
+   if (ret_w) *ret_w = buf->w;
+   if (ret_h) *ret_h = buf->h;
+   if (ret_format) *ret_format = buf->format;
+
+   return buf;
+}
+
+static void
+_ecore_buffer_tbm_buffer_free(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
+{
+   Ecore_Buffer_Tbm_Data *buf = bdata;
+
+   if (!buf) return;
+
+   if (buf->tbm_surface)
+     {
+        tbm_surface_destroy(buf->tbm_surface);
+        buf->tbm_surface = NULL;
+     }
+
+   free(buf);
+}
+
+static Ecore_Export_Type
+_ecore_buffer_tbm_buffer_export(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata, int *id)
+{
+   Ecore_Buffer_Tbm_Data *buf = bdata;
+   tbm_bo bo;
+
+   if (!buf) return EXPORT_TYPE_INVALID;
+
+   if (_buf_get_num_planes(buf->format) != 1)
+     return EXPORT_TYPE_INVALID;
+
+   bo = tbm_surface_internal_get_bo(buf->tbm_surface, 0);
+
+   if (id) *id = tbm_bo_export_fd(bo);
+
+   return EXPORT_TYPE_FD;
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_tbm_buffer_import(Ecore_Buffer_Module_Data bmdata, int w, int h, Ecore_Buffer_Format format, Ecore_Export_Type type, int export_id, unsigned int flags)
+{
+   Ecore_Buffer_Module_Tbm_Data *bm = bmdata;
+   Ecore_Buffer_Tbm_Data *buf;
+   tbm_bo bo;
+
+   if (type != EXPORT_TYPE_FD) return NULL;
+   if (export_id < 1) return NULL;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_Tbm_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = w;
+   buf->h = h;
+   buf->format = format;
+   buf->flags = flags;
+   buf->is_imported = EINA_TRUE;
+
+   bo = tbm_bo_import_fd(bm->tbm_mgr, export_id);
+   buf->tbm_surface = tbm_surface_internal_create_with_bos(buf->w, buf->h, format, &bo, 1);
+   tbm_bo_unref(bo);
+
+   if (!buf->tbm_surface)
+     {
+        free(buf);
+        return NULL;
+     }
+
+   return buf;
+}
+
+static void *
+_ecore_buffer_tbm_tbm_bo_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
+{
+   Ecore_Buffer_Tbm_Data *buf = bdata;
+
+   if (!buf) return NULL;
+
+   return buf->tbm_surface;
+}
+
+static Ecore_Buffer_Backend _ecore_buffer_tbm_backend = {
+     "tbm",
+     &_ecore_buffer_tbm_init,
+     &_ecore_buffer_tbm_shutdown,
+     &_ecore_buffer_tbm_buffer_alloc,
+     &_ecore_buffer_tbm_buffer_alloc_with_tbm_surface,
+     &_ecore_buffer_tbm_buffer_free,
+     &_ecore_buffer_tbm_buffer_export,
+     &_ecore_buffer_tbm_buffer_import,
+     NULL,
+     &_ecore_buffer_tbm_tbm_bo_get,
+};
+
+Eina_Bool tbm_init(void)
+{
+   return ecore_buffer_register(&_ecore_buffer_tbm_backend);
+}
+
+void tbm_shutdown(void)
+{
+   ecore_buffer_unregister(&_ecore_buffer_tbm_backend);
+}
+
+EINA_MODULE_INIT(tbm_init);
+EINA_MODULE_SHUTDOWN(tbm_shutdown);
diff --git a/src/modules/ecore_buffer/x11_dri2/ecore_buffer_x11_dri2.c b/src/modules/ecore_buffer/x11_dri2/ecore_buffer_x11_dri2.c
new file mode 100644 (file)
index 0000000..e53a6ee
--- /dev/null
@@ -0,0 +1,566 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_X.h>
+
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+
+#include <xf86drm.h>
+#include <X11/Xmd.h>
+
+#include <dri2/dri2.h>
+
+#include "Ecore_Buffer.h"
+#include "ecore_buffer_private.h"
+
+typedef struct _Ecore_Buffer_Module_X11_Dri2_Data Ecore_Buffer_Module_X11_Dri2_Data;
+typedef struct _Ecore_Buffer_X11_Dri2_Data Ecore_Buffer_X11_Dri2_Data;
+
+struct _Ecore_Buffer_Module_X11_Dri2_Data {
+     tbm_bufmgr tbm_mgr;
+};
+
+struct _Ecore_Buffer_X11_Dri2_Data {
+     Ecore_X_Pixmap pixmap;
+     int w;
+     int h;
+     int stride;
+     Ecore_Buffer_Format format;
+     Eina_Bool is_imported;
+
+     struct
+     {
+        void *surface;
+        Eina_Bool owned;
+     } tbm;
+};
+
+static int
+_buf_get_num_planes(Ecore_Buffer_Format format)
+{
+   int num_planes = 0;
+
+   switch (format)
+     {
+      case ECORE_BUFFER_FORMAT_C8:
+      case ECORE_BUFFER_FORMAT_RGB332:
+      case ECORE_BUFFER_FORMAT_BGR233:
+      case ECORE_BUFFER_FORMAT_XRGB4444:
+      case ECORE_BUFFER_FORMAT_XBGR4444:
+      case ECORE_BUFFER_FORMAT_RGBX4444:
+      case ECORE_BUFFER_FORMAT_BGRX4444:
+      case ECORE_BUFFER_FORMAT_ARGB4444:
+      case ECORE_BUFFER_FORMAT_ABGR4444:
+      case ECORE_BUFFER_FORMAT_RGBA4444:
+      case ECORE_BUFFER_FORMAT_BGRA4444:
+      case ECORE_BUFFER_FORMAT_XRGB1555:
+      case ECORE_BUFFER_FORMAT_XBGR1555:
+      case ECORE_BUFFER_FORMAT_RGBX5551:
+      case ECORE_BUFFER_FORMAT_BGRX5551:
+      case ECORE_BUFFER_FORMAT_ARGB1555:
+      case ECORE_BUFFER_FORMAT_ABGR1555:
+      case ECORE_BUFFER_FORMAT_RGBA5551:
+      case ECORE_BUFFER_FORMAT_BGRA5551:
+      case ECORE_BUFFER_FORMAT_RGB565:
+      case ECORE_BUFFER_FORMAT_BGR565:
+      case ECORE_BUFFER_FORMAT_RGB888:
+      case ECORE_BUFFER_FORMAT_BGR888:
+      case ECORE_BUFFER_FORMAT_XRGB8888:
+      case ECORE_BUFFER_FORMAT_XBGR8888:
+      case ECORE_BUFFER_FORMAT_RGBX8888:
+      case ECORE_BUFFER_FORMAT_BGRX8888:
+      case ECORE_BUFFER_FORMAT_ARGB8888:
+      case ECORE_BUFFER_FORMAT_ABGR8888:
+      case ECORE_BUFFER_FORMAT_RGBA8888:
+      case ECORE_BUFFER_FORMAT_BGRA8888:
+      case ECORE_BUFFER_FORMAT_XRGB2101010:
+      case ECORE_BUFFER_FORMAT_XBGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBX1010102:
+      case ECORE_BUFFER_FORMAT_BGRX1010102:
+      case ECORE_BUFFER_FORMAT_ARGB2101010:
+      case ECORE_BUFFER_FORMAT_ABGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBA1010102:
+      case ECORE_BUFFER_FORMAT_BGRA1010102:
+      case ECORE_BUFFER_FORMAT_YUYV:
+      case ECORE_BUFFER_FORMAT_YVYU:
+      case ECORE_BUFFER_FORMAT_UYVY:
+      case ECORE_BUFFER_FORMAT_VYUY:
+      case ECORE_BUFFER_FORMAT_AYUV:
+         num_planes = 1;
+         break;
+      case ECORE_BUFFER_FORMAT_NV12:
+      case ECORE_BUFFER_FORMAT_NV21:
+      case ECORE_BUFFER_FORMAT_NV16:
+      case ECORE_BUFFER_FORMAT_NV61:
+         num_planes = 2;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV410:
+      case ECORE_BUFFER_FORMAT_YVU410:
+      case ECORE_BUFFER_FORMAT_YUV411:
+      case ECORE_BUFFER_FORMAT_YVU411:
+      case ECORE_BUFFER_FORMAT_YUV420:
+      case ECORE_BUFFER_FORMAT_YVU420:
+      case ECORE_BUFFER_FORMAT_YUV422:
+      case ECORE_BUFFER_FORMAT_YVU422:
+      case ECORE_BUFFER_FORMAT_YUV444:
+      case ECORE_BUFFER_FORMAT_YVU444:
+         num_planes = 3;
+         break;
+
+      default :
+         break;
+     }
+
+   return num_planes;
+}
+
+static int
+_buf_get_bpp(Ecore_Buffer_Format format)
+{
+   int bpp = 0;
+
+   switch (format)
+     {
+      case ECORE_BUFFER_FORMAT_C8:
+      case ECORE_BUFFER_FORMAT_RGB332:
+      case ECORE_BUFFER_FORMAT_BGR233:
+         bpp = 8;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB4444:
+      case ECORE_BUFFER_FORMAT_XBGR4444:
+      case ECORE_BUFFER_FORMAT_RGBX4444:
+      case ECORE_BUFFER_FORMAT_BGRX4444:
+      case ECORE_BUFFER_FORMAT_ARGB4444:
+      case ECORE_BUFFER_FORMAT_ABGR4444:
+      case ECORE_BUFFER_FORMAT_RGBA4444:
+      case ECORE_BUFFER_FORMAT_BGRA4444:
+      case ECORE_BUFFER_FORMAT_XRGB1555:
+      case ECORE_BUFFER_FORMAT_XBGR1555:
+      case ECORE_BUFFER_FORMAT_RGBX5551:
+      case ECORE_BUFFER_FORMAT_BGRX5551:
+      case ECORE_BUFFER_FORMAT_ARGB1555:
+      case ECORE_BUFFER_FORMAT_ABGR1555:
+      case ECORE_BUFFER_FORMAT_RGBA5551:
+      case ECORE_BUFFER_FORMAT_BGRA5551:
+      case ECORE_BUFFER_FORMAT_RGB565:
+      case ECORE_BUFFER_FORMAT_BGR565:
+         bpp = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_RGB888:
+      case ECORE_BUFFER_FORMAT_BGR888:
+         bpp = 24;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB8888:
+      case ECORE_BUFFER_FORMAT_XBGR8888:
+      case ECORE_BUFFER_FORMAT_RGBX8888:
+      case ECORE_BUFFER_FORMAT_BGRX8888:
+      case ECORE_BUFFER_FORMAT_ARGB8888:
+      case ECORE_BUFFER_FORMAT_ABGR8888:
+      case ECORE_BUFFER_FORMAT_RGBA8888:
+      case ECORE_BUFFER_FORMAT_BGRA8888:
+      case ECORE_BUFFER_FORMAT_XRGB2101010:
+      case ECORE_BUFFER_FORMAT_XBGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBX1010102:
+      case ECORE_BUFFER_FORMAT_BGRX1010102:
+      case ECORE_BUFFER_FORMAT_ARGB2101010:
+      case ECORE_BUFFER_FORMAT_ABGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBA1010102:
+      case ECORE_BUFFER_FORMAT_BGRA1010102:
+      case ECORE_BUFFER_FORMAT_YUYV:
+      case ECORE_BUFFER_FORMAT_YVYU:
+      case ECORE_BUFFER_FORMAT_UYVY:
+      case ECORE_BUFFER_FORMAT_VYUY:
+      case ECORE_BUFFER_FORMAT_AYUV:
+         bpp = 32;
+         break;
+      case ECORE_BUFFER_FORMAT_NV12:
+      case ECORE_BUFFER_FORMAT_NV21:
+         bpp = 12;
+         break;
+      case ECORE_BUFFER_FORMAT_NV16:
+      case ECORE_BUFFER_FORMAT_NV61:
+         bpp = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV410:
+      case ECORE_BUFFER_FORMAT_YVU410:
+         bpp = 9;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV411:
+      case ECORE_BUFFER_FORMAT_YVU411:
+      case ECORE_BUFFER_FORMAT_YUV420:
+      case ECORE_BUFFER_FORMAT_YVU420:
+         bpp = 12;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV422:
+      case ECORE_BUFFER_FORMAT_YVU422:
+         bpp = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV444:
+      case ECORE_BUFFER_FORMAT_YVU444:
+         bpp = 24;
+         break;
+      default :
+         break;
+     }
+
+   return bpp;
+}
+
+static Ecore_Buffer_Module_Data
+_ecore_buffer_x11_dri2_init(const char *context EINA_UNUSED, const char *options EINA_UNUSED)
+{
+   Ecore_X_Display *xdpy;
+   Ecore_X_Window root;
+   int eb, ee;
+   int major, minor;
+   char *driver_name;
+   char *device_name;
+   int fd = 0;
+   drm_magic_t magic;
+   Ecore_Buffer_Module_X11_Dri2_Data* mdata = NULL;
+
+   if (!ecore_x_init(NULL))
+     return NULL;
+
+   xdpy = ecore_x_display_get();
+   if (!xdpy)
+     goto on_error;
+
+   root = ecore_x_window_root_first_get();
+   if (!root)
+     goto on_error;
+
+   mdata = calloc(1, sizeof(Ecore_Buffer_Module_X11_Dri2_Data));
+   if (!mdata)
+     goto on_error;
+
+   //Init DRI2 and TBM
+   DRI2QueryExtension(xdpy, &eb, &ee);
+   DRI2QueryVersion(xdpy, &major, &minor);
+   DRI2Connect(xdpy, root, &driver_name, &device_name);
+
+   fd = open (device_name, O_RDWR);
+   if (fd < 0)
+     goto on_error;
+
+   if (!(drmGetMagic(fd, &magic)))
+     goto on_error;
+
+   if (!(DRI2Authenticate(xdpy, root, magic)))
+     goto on_error;
+
+   mdata->tbm_mgr = tbm_bufmgr_init(fd);
+   if (!mdata->tbm_mgr)
+     goto on_error;
+
+   free(driver_name);
+   free(device_name);
+   close(fd);
+
+   return mdata;
+
+on_error:
+   if (fd > 0) close(fd);
+   if (driver_name) free(driver_name);
+   if (device_name) free(device_name);
+   if (mdata) free(mdata);
+   ecore_x_shutdown();
+
+   return NULL;
+}
+
+static void
+_ecore_buffer_x11_dri2_shutdown(Ecore_Buffer_Module_Data bmdata)
+{
+   Ecore_Buffer_Module_X11_Dri2_Data *bm = bmdata;
+
+   if (bm->tbm_mgr)
+     tbm_bufmgr_deinit(bm->tbm_mgr);
+
+   ecore_x_shutdown();
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_x11_dri2_buffer_alloc(Ecore_Buffer_Module_Data bmdata, int width, int height, Ecore_Buffer_Format format, unsigned int flags EINA_UNUSED)
+{
+   Ecore_X_Display* xdpy;
+   Ecore_X_Pixmap pixmap;
+   Ecore_Buffer_X11_Dri2_Data *buf;
+   Ecore_Buffer_Module_X11_Dri2_Data *bm = bmdata;
+   DRI2Buffer* bufs = NULL;
+   tbm_bo bo = NULL;
+   int bpp;
+   int num_plane;
+   int rw, rh, rcount;
+   unsigned int attachment = DRI2BufferFrontLeft;
+   tbm_surface_info_s info;
+   int i;
+
+   bpp = _buf_get_bpp(format);
+   if (bpp != 32)
+     return NULL;
+
+   num_plane = _buf_get_num_planes(format);
+   if (num_plane != 1)
+     return NULL;
+
+   xdpy = ecore_x_display_get();
+   pixmap = ecore_x_pixmap_new(0, width, height, bpp);
+   if (!pixmap)
+     return NULL;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri2_Data));
+   if (!buf)
+     {
+        ecore_x_pixmap_free(pixmap);
+        return NULL;
+     }
+
+   buf->w = width;
+   buf->h = height;
+   buf->format = format;
+   buf->pixmap = pixmap;
+   buf->is_imported = EINA_FALSE;
+
+   //Get DRI2Buffer
+   DRI2CreateDrawable(xdpy, buf->pixmap);
+   bufs = DRI2GetBuffers(xdpy, buf->pixmap, &rw, &rh, &attachment, 1, &rcount);
+   if (!(bufs) || (buf->w != rw) || (buf->h != rh))
+     goto on_error;
+
+   buf->stride = bufs->pitch;
+
+   //Import tbm_surface
+   bo = tbm_bo_import(bm->tbm_mgr, bufs->name);
+   if (!bo)
+     goto on_error;
+
+   info.width = width;
+   info.height =  height;
+   info.format = format;
+   info.bpp = bpp;
+   info.size = width * bufs->pitch;
+   for ( i = 0 ; i < num_plane ; i++)
+   {
+      info.planes[i].size = width * bufs->pitch;
+      info.planes[i].stride = bufs->pitch;
+      info.planes[i].offset = 0;
+   }
+
+   buf->tbm.surface = tbm_surface_internal_create_with_bos(&info, &bo, 1);
+   if (!buf->tbm.surface)
+     goto on_error;
+
+   buf->tbm.owned = EINA_TRUE;
+   tbm_bo_unref(bo);
+   free(bufs);
+
+   return buf;
+
+on_error:
+   if (bo) tbm_bo_unref(bo);
+   if (bufs) free(bufs);
+   ecore_x_pixmap_free(buf->pixmap);
+   DRI2DestroyDrawable(xdpy, buf->pixmap);
+   free(buf);
+
+   return NULL;
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_x11_dri2_buffer_alloc_with_tbm_surface(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, void *tbm_surface, int *ret_w, int *ret_h, Ecore_Buffer_Format *ret_format, unsigned int flags EINA_UNUSED)
+{
+   Ecore_Buffer_X11_Dri2_Data *buf;
+
+   if (!tbm_surface)
+     return NULL;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri2_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = tbm_surface_get_width(tbm_surface);
+   buf->h = tbm_surface_get_height(tbm_surface);
+   buf->format = tbm_surface_get_format(tbm_surface);
+   buf->tbm.surface = tbm_surface;
+   buf->tbm.owned = EINA_FALSE;
+   buf->is_imported = EINA_FALSE;
+
+   if (ret_w) *ret_w = buf->w;
+   if (ret_h) *ret_h = buf->h;
+   if (ret_format) *ret_format = buf->format;
+
+   return buf;
+}
+
+static void
+_ecore_buffer_x11_dri2_buffer_free(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
+{
+   Ecore_Buffer_X11_Dri2_Data *buf = bdata;
+
+   if (buf->pixmap)
+     {
+        DRI2DestroyDrawable(ecore_x_display_get(), buf->pixmap);
+
+        if (!buf->is_imported)
+          ecore_x_pixmap_free(buf->pixmap);
+     }
+
+   if (buf->tbm.surface)
+     tbm_surface_destroy(buf->tbm.surface);
+
+   free(buf);
+
+   return;
+}
+
+static Ecore_Export_Type
+_ecore_buffer_x11_dri2_buffer_export(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata, int *id)
+{
+   Ecore_Buffer_X11_Dri2_Data *buf = bdata;
+
+   if (id) *id = buf->pixmap;
+
+   return EXPORT_TYPE_ID;
+}
+
+static void *
+_ecore_buffer_x11_dri2_buffer_import(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, int w, int h, Ecore_Buffer_Format format, Ecore_Export_Type type, int export_id, unsigned int flags EINA_UNUSED)
+{
+   Ecore_Buffer_Module_X11_Dri2_Data *bm = bmdata;
+   Ecore_X_Display* xdpy;
+   Ecore_X_Pixmap pixmap = (Ecore_X_Pixmap)export_id;
+   Ecore_Buffer_X11_Dri2_Data *buf;
+   int rw, rh, rx, ry;
+   DRI2Buffer* bufs = NULL;
+   tbm_bo bo = NULL;
+   int rcount;
+   unsigned int attachment = DRI2BufferFrontLeft;
+   tbm_surface_info_s info;
+   int num_plane,i;
+
+   if (type != EXPORT_TYPE_ID)
+     return NULL;
+
+   xdpy = ecore_x_display_get();
+
+   //Check valid pixmap
+   ecore_x_pixmap_geometry_get(pixmap, &rx, &ry, &rw, &rh);
+   if ((rw != w) || (rh != h))
+     return NULL;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri2_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = w;
+   buf->h = h;
+   buf->format = format;
+   buf->pixmap = pixmap;
+   buf->is_imported = EINA_TRUE;
+
+   //Get DRI2Buffer
+   DRI2CreateDrawable(xdpy, buf->pixmap);
+   bufs = DRI2GetBuffers(xdpy, buf->pixmap, &rw, &rh, &attachment, 1, &rcount);
+   if ((!bufs) || (buf->w != rw) || (buf->h != rh))
+     goto on_error;
+
+   buf->stride = bufs->pitch;
+
+   //Import tbm_surface
+   bo = tbm_bo_import(bm->tbm_mgr, bufs->name);
+   if (!bo)
+     goto on_error;
+
+   num_plane = _buf_get_num_planes(format);
+   info.width = w;
+   info.height = h;
+   info.format = format;
+   info.bpp = _buf_get_bpp(format);
+   info.size = w * bufs->pitch;
+   for ( i = 0 ; i < num_plane ; i++)
+   {
+      info.planes[i].size = w * bufs->pitch;
+      info.planes[i].stride = bufs->pitch;
+      info.planes[i].offset = 0;
+   }
+
+   buf->tbm.surface = tbm_surface_internal_create_with_bos(&info, &bo, 1);
+   if (!buf->tbm.surface)
+     goto on_error;
+
+   buf->tbm.owned = EINA_TRUE;
+   tbm_bo_unref(bo);
+   free(bufs);
+
+   return buf;
+
+on_error:
+   if (bo) tbm_bo_unref(bo);
+   if (bufs) free(bufs);
+   DRI2DestroyDrawable(xdpy, buf->pixmap);
+   free(buf);
+
+   return NULL;
+}
+
+static Ecore_Pixmap
+_ecore_buffer_x11_dri2_pixmap_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
+{
+   Ecore_Buffer_X11_Dri2_Data *buf = bdata;
+
+   if (!buf)
+     return 0;
+
+   if (!buf->tbm.owned)
+     return 0;
+
+   return buf->pixmap;
+}
+
+static void *
+_ecore_buffer_x11_dri2_tbm_bo_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data bdata)
+{
+   Ecore_Buffer_X11_Dri2_Data *buf = bdata;
+
+   if (!buf)
+     return NULL;
+
+   return buf->tbm.surface;
+}
+
+static Ecore_Buffer_Backend _ecore_buffer_x11_dri2_backend = {
+     "x11_dri2",
+     &_ecore_buffer_x11_dri2_init,
+     &_ecore_buffer_x11_dri2_shutdown,
+     &_ecore_buffer_x11_dri2_buffer_alloc,
+     &_ecore_buffer_x11_dri2_buffer_alloc_with_tbm_surface,
+     &_ecore_buffer_x11_dri2_buffer_free,
+     &_ecore_buffer_x11_dri2_buffer_export,
+     &_ecore_buffer_x11_dri2_buffer_import,
+     &_ecore_buffer_x11_dri2_pixmap_get,
+     &_ecore_buffer_x11_dri2_tbm_bo_get,
+};
+
+Eina_Bool x11_dri2_init(void)
+{
+   return ecore_buffer_register(&_ecore_buffer_x11_dri2_backend);
+}
+
+void x11_dri2_shutdown(void)
+{
+   ecore_buffer_unregister(&_ecore_buffer_x11_dri2_backend);
+}
+
+EINA_MODULE_INIT(x11_dri2_init);
+EINA_MODULE_SHUTDOWN(x11_dri2_shutdown);
diff --git a/src/modules/ecore_buffer/x11_dri3/ecore_buffer_x11_dri3.c b/src/modules/ecore_buffer/x11_dri3/ecore_buffer_x11_dri3.c
new file mode 100644 (file)
index 0000000..3d97454
--- /dev/null
@@ -0,0 +1,625 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+#include <X11/xshmfence.h>
+#include <xcb/xcb.h>
+#include <xcb/dri3.h>
+#include <xcb/sync.h>
+
+#include <Eina.h>
+#include <Ecore.h>
+#include <Ecore_X.h>
+
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+
+#include <Ecore_Buffer.h>
+#include "ecore_buffer_private.h"
+
+typedef struct _Ecore_Buffer_Module_X11_Dri3_Data Ecore_Buffer_Module_X11_Dri3_Data;
+typedef struct _Ecore_Buffer_X11_Dri3_Data Ecore_Buffer_X11_Dri3_Data;
+
+struct _Ecore_Buffer_Module_X11_Dri3_Data {
+     tbm_bufmgr tbm_mgr;
+};
+
+struct _Ecore_Buffer_X11_Dri3_Data {
+     Ecore_X_Pixmap pixmap;
+     void *tbm_surface;
+     int w;
+     int h;
+     int stride;
+     unsigned int flags;
+     Ecore_Buffer_Format format;
+     Eina_Bool is_imported;
+};
+
+static int
+_buf_get_num_planes(Ecore_Buffer_Format format)
+{
+   int num_planes = 0;
+
+   switch (format)
+     {
+      case ECORE_BUFFER_FORMAT_C8:
+      case ECORE_BUFFER_FORMAT_RGB332:
+      case ECORE_BUFFER_FORMAT_BGR233:
+      case ECORE_BUFFER_FORMAT_XRGB4444:
+      case ECORE_BUFFER_FORMAT_XBGR4444:
+      case ECORE_BUFFER_FORMAT_RGBX4444:
+      case ECORE_BUFFER_FORMAT_BGRX4444:
+      case ECORE_BUFFER_FORMAT_ARGB4444:
+      case ECORE_BUFFER_FORMAT_ABGR4444:
+      case ECORE_BUFFER_FORMAT_RGBA4444:
+      case ECORE_BUFFER_FORMAT_BGRA4444:
+      case ECORE_BUFFER_FORMAT_XRGB1555:
+      case ECORE_BUFFER_FORMAT_XBGR1555:
+      case ECORE_BUFFER_FORMAT_RGBX5551:
+      case ECORE_BUFFER_FORMAT_BGRX5551:
+      case ECORE_BUFFER_FORMAT_ARGB1555:
+      case ECORE_BUFFER_FORMAT_ABGR1555:
+      case ECORE_BUFFER_FORMAT_RGBA5551:
+      case ECORE_BUFFER_FORMAT_BGRA5551:
+      case ECORE_BUFFER_FORMAT_RGB565:
+      case ECORE_BUFFER_FORMAT_BGR565:
+      case ECORE_BUFFER_FORMAT_RGB888:
+      case ECORE_BUFFER_FORMAT_BGR888:
+      case ECORE_BUFFER_FORMAT_XRGB8888:
+      case ECORE_BUFFER_FORMAT_XBGR8888:
+      case ECORE_BUFFER_FORMAT_RGBX8888:
+      case ECORE_BUFFER_FORMAT_BGRX8888:
+      case ECORE_BUFFER_FORMAT_ARGB8888:
+      case ECORE_BUFFER_FORMAT_ABGR8888:
+      case ECORE_BUFFER_FORMAT_RGBA8888:
+      case ECORE_BUFFER_FORMAT_BGRA8888:
+      case ECORE_BUFFER_FORMAT_XRGB2101010:
+      case ECORE_BUFFER_FORMAT_XBGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBX1010102:
+      case ECORE_BUFFER_FORMAT_BGRX1010102:
+      case ECORE_BUFFER_FORMAT_ARGB2101010:
+      case ECORE_BUFFER_FORMAT_ABGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBA1010102:
+      case ECORE_BUFFER_FORMAT_BGRA1010102:
+      case ECORE_BUFFER_FORMAT_YUYV:
+      case ECORE_BUFFER_FORMAT_YVYU:
+      case ECORE_BUFFER_FORMAT_UYVY:
+      case ECORE_BUFFER_FORMAT_VYUY:
+      case ECORE_BUFFER_FORMAT_AYUV:
+         num_planes = 1;
+         break;
+      case ECORE_BUFFER_FORMAT_NV12:
+      case ECORE_BUFFER_FORMAT_NV21:
+      case ECORE_BUFFER_FORMAT_NV16:
+      case ECORE_BUFFER_FORMAT_NV61:
+         num_planes = 2;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV410:
+      case ECORE_BUFFER_FORMAT_YVU410:
+      case ECORE_BUFFER_FORMAT_YUV411:
+      case ECORE_BUFFER_FORMAT_YVU411:
+      case ECORE_BUFFER_FORMAT_YUV420:
+      case ECORE_BUFFER_FORMAT_YVU420:
+      case ECORE_BUFFER_FORMAT_YUV422:
+      case ECORE_BUFFER_FORMAT_YVU422:
+      case ECORE_BUFFER_FORMAT_YUV444:
+      case ECORE_BUFFER_FORMAT_YVU444:
+         num_planes = 3;
+         break;
+
+      default :
+         break;
+     }
+
+   return num_planes;
+}
+
+static int
+_buf_get_bpp(Ecore_Buffer_Format format)
+{
+   int bpp = 0;
+
+   switch (format)
+     {
+      case ECORE_BUFFER_FORMAT_C8:
+      case ECORE_BUFFER_FORMAT_RGB332:
+      case ECORE_BUFFER_FORMAT_BGR233:
+         bpp = 8;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB4444:
+      case ECORE_BUFFER_FORMAT_XBGR4444:
+      case ECORE_BUFFER_FORMAT_RGBX4444:
+      case ECORE_BUFFER_FORMAT_BGRX4444:
+      case ECORE_BUFFER_FORMAT_ARGB4444:
+      case ECORE_BUFFER_FORMAT_ABGR4444:
+      case ECORE_BUFFER_FORMAT_RGBA4444:
+      case ECORE_BUFFER_FORMAT_BGRA4444:
+      case ECORE_BUFFER_FORMAT_XRGB1555:
+      case ECORE_BUFFER_FORMAT_XBGR1555:
+      case ECORE_BUFFER_FORMAT_RGBX5551:
+      case ECORE_BUFFER_FORMAT_BGRX5551:
+      case ECORE_BUFFER_FORMAT_ARGB1555:
+      case ECORE_BUFFER_FORMAT_ABGR1555:
+      case ECORE_BUFFER_FORMAT_RGBA5551:
+      case ECORE_BUFFER_FORMAT_BGRA5551:
+      case ECORE_BUFFER_FORMAT_RGB565:
+      case ECORE_BUFFER_FORMAT_BGR565:
+         bpp = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_RGB888:
+      case ECORE_BUFFER_FORMAT_BGR888:
+         bpp = 24;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB8888:
+      case ECORE_BUFFER_FORMAT_XBGR8888:
+      case ECORE_BUFFER_FORMAT_RGBX8888:
+      case ECORE_BUFFER_FORMAT_BGRX8888:
+      case ECORE_BUFFER_FORMAT_ARGB8888:
+      case ECORE_BUFFER_FORMAT_ABGR8888:
+      case ECORE_BUFFER_FORMAT_RGBA8888:
+      case ECORE_BUFFER_FORMAT_BGRA8888:
+      case ECORE_BUFFER_FORMAT_XRGB2101010:
+      case ECORE_BUFFER_FORMAT_XBGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBX1010102:
+      case ECORE_BUFFER_FORMAT_BGRX1010102:
+      case ECORE_BUFFER_FORMAT_ARGB2101010:
+      case ECORE_BUFFER_FORMAT_ABGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBA1010102:
+      case ECORE_BUFFER_FORMAT_BGRA1010102:
+      case ECORE_BUFFER_FORMAT_YUYV:
+      case ECORE_BUFFER_FORMAT_YVYU:
+      case ECORE_BUFFER_FORMAT_UYVY:
+      case ECORE_BUFFER_FORMAT_VYUY:
+      case ECORE_BUFFER_FORMAT_AYUV:
+         bpp = 32;
+         break;
+      case ECORE_BUFFER_FORMAT_NV12:
+      case ECORE_BUFFER_FORMAT_NV21:
+         bpp = 12;
+         break;
+      case ECORE_BUFFER_FORMAT_NV16:
+      case ECORE_BUFFER_FORMAT_NV61:
+         bpp = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV410:
+      case ECORE_BUFFER_FORMAT_YVU410:
+         bpp = 9;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV411:
+      case ECORE_BUFFER_FORMAT_YVU411:
+      case ECORE_BUFFER_FORMAT_YUV420:
+      case ECORE_BUFFER_FORMAT_YVU420:
+         bpp = 12;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV422:
+      case ECORE_BUFFER_FORMAT_YVU422:
+         bpp = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_YUV444:
+      case ECORE_BUFFER_FORMAT_YVU444:
+         bpp = 24;
+         break;
+      default :
+         break;
+     }
+
+   return bpp;
+}
+
+static int
+_buf_get_depth(Ecore_Buffer_Format format)
+{
+   int depth = 0;
+
+   switch (format)
+     {
+      case ECORE_BUFFER_FORMAT_C8:
+      case ECORE_BUFFER_FORMAT_RGB332:
+      case ECORE_BUFFER_FORMAT_BGR233:
+         depth = 8;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB4444:
+      case ECORE_BUFFER_FORMAT_XBGR4444:
+      case ECORE_BUFFER_FORMAT_RGBX4444:
+      case ECORE_BUFFER_FORMAT_BGRX4444:
+         depth = 12;
+         break;
+      case ECORE_BUFFER_FORMAT_ARGB4444:
+      case ECORE_BUFFER_FORMAT_ABGR4444:
+      case ECORE_BUFFER_FORMAT_RGBA4444:
+      case ECORE_BUFFER_FORMAT_BGRA4444:
+         depth = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB1555:
+      case ECORE_BUFFER_FORMAT_XBGR1555:
+      case ECORE_BUFFER_FORMAT_RGBX5551:
+      case ECORE_BUFFER_FORMAT_BGRX5551:
+         depth = 15;
+         break;
+      case ECORE_BUFFER_FORMAT_ARGB1555:
+      case ECORE_BUFFER_FORMAT_ABGR1555:
+      case ECORE_BUFFER_FORMAT_RGBA5551:
+      case ECORE_BUFFER_FORMAT_BGRA5551:
+      case ECORE_BUFFER_FORMAT_RGB565:
+      case ECORE_BUFFER_FORMAT_BGR565:
+         depth = 16;
+         break;
+      case ECORE_BUFFER_FORMAT_RGB888:
+      case ECORE_BUFFER_FORMAT_BGR888:
+         depth = 24;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB8888:
+      case ECORE_BUFFER_FORMAT_XBGR8888:
+      case ECORE_BUFFER_FORMAT_RGBX8888:
+      case ECORE_BUFFER_FORMAT_BGRX8888:
+         depth = 24;
+         break;
+      case ECORE_BUFFER_FORMAT_ARGB8888:
+      case ECORE_BUFFER_FORMAT_ABGR8888:
+      case ECORE_BUFFER_FORMAT_RGBA8888:
+      case ECORE_BUFFER_FORMAT_BGRA8888:
+         depth = 32;
+         break;
+      case ECORE_BUFFER_FORMAT_XRGB2101010:
+      case ECORE_BUFFER_FORMAT_XBGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBX1010102:
+      case ECORE_BUFFER_FORMAT_BGRX1010102:
+         depth = 30;
+         break;
+      case ECORE_BUFFER_FORMAT_ARGB2101010:
+      case ECORE_BUFFER_FORMAT_ABGR2101010:
+      case ECORE_BUFFER_FORMAT_RGBA1010102:
+      case ECORE_BUFFER_FORMAT_BGRA1010102:
+         depth = 32;
+         break;
+      case ECORE_BUFFER_FORMAT_YUYV:
+      case ECORE_BUFFER_FORMAT_YVYU:
+      case ECORE_BUFFER_FORMAT_UYVY:
+      case ECORE_BUFFER_FORMAT_VYUY:
+      case ECORE_BUFFER_FORMAT_AYUV:
+      case ECORE_BUFFER_FORMAT_NV12:
+      case ECORE_BUFFER_FORMAT_NV21:
+      case ECORE_BUFFER_FORMAT_NV16:
+      case ECORE_BUFFER_FORMAT_NV61:
+      case ECORE_BUFFER_FORMAT_YUV410:
+      case ECORE_BUFFER_FORMAT_YVU410:
+      case ECORE_BUFFER_FORMAT_YUV411:
+      case ECORE_BUFFER_FORMAT_YVU411:
+      case ECORE_BUFFER_FORMAT_YUV420:
+      case ECORE_BUFFER_FORMAT_YVU420:
+      case ECORE_BUFFER_FORMAT_YUV422:
+      case ECORE_BUFFER_FORMAT_YVU422:
+      case ECORE_BUFFER_FORMAT_YUV444:
+      case ECORE_BUFFER_FORMAT_YVU444:
+      default :
+         depth = 0; //unknown in X
+         break;
+     }
+
+   return depth;
+}
+
+static int
+_dri3_open(Ecore_X_Display *dpy, Ecore_X_Window root, unsigned provider)
+{
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_dri3_open_cookie_t cookie;
+   xcb_dri3_open_reply_t *reply;
+
+   cookie = xcb_dri3_open(c, root, provider);
+   reply = xcb_dri3_open_reply(c, cookie, NULL);
+   if ((!reply) || (reply->nfd != 1))
+     return -1;
+
+   return xcb_dri3_open_reply_fds(c, reply)[0];
+}
+
+static Ecore_X_Pixmap
+_dri3_pixmap_from_fd(Ecore_X_Display *dpy, Ecore_X_Drawable draw, int width, int height, int depth, int fd, int bpp, int stride, int size)
+{
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   Ecore_X_Pixmap pixmap = xcb_generate_id(c);
+
+   if (!dpy)
+     return 0;
+
+   c = XGetXCBConnection(dpy);
+   if (!c)
+     return 0;
+
+   pixmap = xcb_generate_id(c);
+   if (!pixmap)
+     return 0;
+
+   xcb_dri3_pixmap_from_buffer(c, pixmap, draw, size, width, height, stride, depth, bpp, fd);
+
+   return pixmap;
+}
+
+static Ecore_Buffer_Module_Data
+_ecore_buffer_x11_dri3_init(const char *context EINA_UNUSED, const char *options EINA_UNUSED)
+{
+   Ecore_X_Display *xdpy;
+   Ecore_X_Window root;
+   Ecore_Buffer_Module_X11_Dri3_Data *mdata = NULL;
+   int fd = 0;
+
+   if (!ecore_x_init(NULL))
+     return NULL;
+
+   xdpy = ecore_x_display_get();
+   if (!xdpy)
+     goto on_error;
+
+   root = ecore_x_window_root_first_get();
+   if (!root)
+     goto on_error;
+
+   mdata = calloc(1, sizeof(Ecore_Buffer_Module_X11_Dri3_Data));
+   if (!mdata)
+     goto on_error;
+
+   //Init DRI3 and TBM
+   fd = _dri3_open(xdpy, root, 0);
+   if (fd < 0)
+     goto on_error;
+
+   mdata->tbm_mgr = tbm_bufmgr_init(fd);
+   if (!mdata->tbm_mgr)
+     goto on_error;
+
+   close(fd);
+
+   return mdata;
+
+on_error:
+   if (fd > 0) close(fd);
+   if (mdata) free(mdata);
+   ecore_x_shutdown();
+
+   return NULL;
+}
+
+static void
+_ecore_buffer_x11_dri3_shutdown(Ecore_Buffer_Module_Data bmdata)
+{
+   Ecore_Buffer_Module_X11_Dri3_Data *bm = bmdata;
+
+   if (!bm)
+     return;
+
+   if (bm->tbm_mgr)
+     tbm_bufmgr_deinit(bm->tbm_mgr);
+
+   ecore_x_shutdown();
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_x11_dri3_buffer_alloc(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, int width, int height, Ecore_Buffer_Format format, unsigned int flags)
+{
+   Ecore_Buffer_X11_Dri3_Data *buf;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri3_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = width;
+   buf->h = height;
+   buf->format = format;
+   buf->flags = flags;
+   buf->is_imported = EINA_FALSE;
+   buf->tbm_surface = tbm_surface_create(width,height,(tbm_format)format);
+   if (!buf->tbm_surface)
+     {
+        free(buf);
+        return NULL;
+     }
+
+   return buf;
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_x11_dri3_buffer_alloc_with_tbm_surface(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, void *tbm_surface, int *ret_w, int *ret_h, Ecore_Buffer_Format *ret_format, unsigned int flags)
+{
+   Ecore_Buffer_X11_Dri3_Data *buf;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri3_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = tbm_surface_get_width(tbm_surface);
+   buf->h = tbm_surface_get_height(tbm_surface);
+   buf->format = tbm_surface_get_format(tbm_surface);
+   buf->flags = flags;
+   buf->is_imported = EINA_FALSE;
+   buf->tbm_surface = tbm_surface;
+
+   if (ret_w) *ret_w = buf->w;
+   if (ret_h) *ret_h = buf->h;
+   if (ret_format) *ret_format = buf->format;
+
+   return buf;
+}
+
+
+static void
+_ecore_buffer_x11_dri3_buffer_free(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data data)
+{
+   Ecore_Buffer_X11_Dri3_Data *buf = data;
+
+   if (!buf)
+     return;
+
+   if (buf->pixmap)
+     ecore_x_pixmap_free(buf->pixmap);
+
+   if (buf->tbm_surface)
+     tbm_surface_destroy(buf->tbm_surface);
+
+   free(buf);
+}
+
+static Ecore_Export_Type
+_ecore_buffer_x11_dri3_buffer_export(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data data, int *id)
+{
+   Ecore_Buffer_X11_Dri3_Data *buf = data;
+   tbm_bo bo;
+
+   if (_buf_get_num_planes(buf->format) != 1)
+     return EXPORT_TYPE_INVALID;
+
+   bo = tbm_surface_internal_get_bo(buf->tbm_surface, 0);
+   if (!bo)
+     return EXPORT_TYPE_INVALID;
+
+   if (id) *id = tbm_bo_export_fd(bo);
+
+   return EXPORT_TYPE_FD;
+}
+
+static Ecore_Buffer_Data
+_ecore_buffer_x11_dri3_buffer_import(Ecore_Buffer_Module_Data bmdata, int w, int h, Ecore_Buffer_Format format, Ecore_Export_Type type, int export_id, unsigned int flags)
+{
+   Ecore_Buffer_Module_X11_Dri3_Data *bm = bmdata;
+   Ecore_Buffer_X11_Dri3_Data *buf;
+   tbm_bo bo;
+   tbm_surface_info_s info;
+   int i, num_plane;
+
+   if (!bm)
+     return NULL;
+
+   if (type != EXPORT_TYPE_FD)
+     return NULL;
+
+   if (export_id < 1)
+     return NULL;
+
+   buf = calloc(1, sizeof(Ecore_Buffer_X11_Dri3_Data));
+   if (!buf)
+     return NULL;
+
+   buf->w = w;
+   buf->h = h;
+   buf->format = format;
+   buf->flags = flags;
+   buf->is_imported = EINA_TRUE;
+
+   //Import tbm_surface
+   bo = tbm_bo_import_fd(bm->tbm_mgr, export_id);
+   if (!bo)
+     {
+        free(buf);
+        return NULL;
+     }
+
+   num_plane = _buf_get_num_planes(format);
+   info.width = w;
+   info.height = h;
+   info.format = format;
+   info.bpp = _buf_get_bpp(format);
+   info.size = w * h * info.bpp;
+   for ( i = 0 ; i < num_plane ; i++)
+   {
+      info.planes[i].size = w * h * info.bpp;
+      info.planes[i].stride = w * info.bpp;
+      info.planes[i].offset = 0;
+   }
+
+   buf->tbm_surface = tbm_surface_internal_create_with_bos(&info, &bo, 1);
+   if (!buf->tbm_surface)
+     {
+        tbm_bo_unref(bo);
+        free(buf);
+        return NULL;
+     }
+
+   tbm_bo_unref(bo);
+
+   return buf;
+}
+
+static Ecore_Pixmap
+_ecore_buffer_x11_dri3_pixmap_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data data)
+{
+   Ecore_Buffer_X11_Dri3_Data *buf = data;
+   Ecore_X_Display* xdpy;
+   Ecore_X_Window root;
+   tbm_surface_info_s info;
+   tbm_bo bo;
+   int ret;
+
+   if (!buf)
+     return 0;
+
+   if (buf->pixmap)
+     return buf->pixmap;
+
+   ret = tbm_surface_get_info(buf->tbm_surface, &info);
+   if (ret != 0)
+     return 0;
+
+   if (info.num_planes != 1)
+     return 0;
+
+   bo = tbm_surface_internal_get_bo(buf->tbm_surface, 0);
+   if (!bo)
+     return 0;
+
+   xdpy = ecore_x_display_get();
+   root = ecore_x_window_root_first_get();
+   buf->pixmap = _dri3_pixmap_from_fd(xdpy, root,
+                                      buf->w, buf->h,
+                                      _buf_get_depth(buf->format),
+                                      tbm_bo_export_fd(bo),
+                                      _buf_get_bpp(buf->format),
+                                      info.planes[0].stride,
+                                      info.planes[0].size);
+
+   return buf->pixmap;
+}
+
+static void *
+_ecore_buffer_x11_dri3_tbm_bo_get(Ecore_Buffer_Module_Data bmdata EINA_UNUSED, Ecore_Buffer_Data data)
+{
+   Ecore_Buffer_X11_Dri3_Data *buf = data;
+
+   if (!buf)
+     return NULL;
+
+   return buf->tbm_surface;
+}
+
+static Ecore_Buffer_Backend _ecore_buffer_x11_dri3_backend = {
+     "x11_dri3",
+     &_ecore_buffer_x11_dri3_init,
+     &_ecore_buffer_x11_dri3_shutdown,
+     &_ecore_buffer_x11_dri3_buffer_alloc,
+     &_ecore_buffer_x11_dri3_buffer_alloc_with_tbm_surface,
+     &_ecore_buffer_x11_dri3_buffer_free,
+     &_ecore_buffer_x11_dri3_buffer_export,
+     &_ecore_buffer_x11_dri3_buffer_import,
+     &_ecore_buffer_x11_dri3_pixmap_get,
+     &_ecore_buffer_x11_dri3_tbm_bo_get,
+};
+
+Eina_Bool x11_dri3_init(void)
+{
+   return ecore_buffer_register(&_ecore_buffer_x11_dri3_backend);
+}
+
+void x11_dri3_shutdown(void)
+{
+   ecore_buffer_unregister(&_ecore_buffer_x11_dri3_backend);
+}
+
+EINA_MODULE_INIT(x11_dri3_init);
+EINA_MODULE_SHUTDOWN(x11_dri3_shutdown);