[tbm_backend] implement tbm backend (gl_tbm and software_tbm) 25/73625/5 accepted/tizen/common/20160616.151649 accepted/tizen/ivi/20160616.003056 accepted/tizen/mobile/20160616.003037 accepted/tizen/tv/20160616.002934 accepted/tizen/wearable/20160616.003022 submit/tizen/20160615.083837
authorsunghyun kim <scholb.kim@samsung.com>
Wed, 30 Mar 2016 02:46:54 +0000 (11:46 +0900)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Tue, 14 Jun 2016 08:26:24 +0000 (01:26 -0700)
1. dumy engine for Create Tbm backend
2. [Ecore_Evas_TBM] Add ecore_evas_tbm and evas_tbm_backend
3. [tbm_backend] remove bufmgr
  - remove bufmgr in tbm backend
  - redesign ext API
4. [tbm_backend] implement software tbm backend
5. add acquire/release pixel api & delete image fuction
6. [tbm_backend] implement tbm backend (gl_tbm and software_tbm)

Change-Id: If141e2d85e33cd5257a51108338c7afa8f0e3994

21 files changed:
configure.ac [changed mode: 0644->0755]
m4/evas_check_engine.m4 [changed mode: 0644->0755]
packaging/efl.spec [changed mode: 0644->0755]
src/Makefile_Ecore_Evas.am
src/Makefile_Evas.am [changed mode: 0644->0755]
src/lib/ecore_evas/Ecore_Evas.h [changed mode: 0644->0755]
src/lib/ecore_evas/ecore_evas.c [changed mode: 0644->0755]
src/lib/ecore_evas/ecore_evas_module.c [changed mode: 0644->0755]
src/lib/ecore_evas/ecore_evas_tbm.c [new file with mode: 0755]
src/lib/ecore_evas/ecore_evas_tbm.h [new file with mode: 0755]
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c [changed mode: 0644->0755]
src/modules/evas/engines/gl_tbm/Evas_Engine_GL_Tbm.h [new file with mode: 0755]
src/modules/evas/engines/gl_tbm/evas_engine.c [new file with mode: 0755]
src/modules/evas/engines/gl_tbm/evas_engine.h [new file with mode: 0755]
src/modules/evas/engines/gl_tbm/evas_tbm_main.c [new file with mode: 0755]
src/modules/evas/engines/software_tbm/Evas_Engine_Software_Tbm.h [new file with mode: 0755]
src/modules/evas/engines/software_tbm/evas_engine.c [new file with mode: 0755]
src/modules/evas/engines/software_tbm/evas_engine.h [new file with mode: 0755]
src/modules/evas/engines/software_tbm/evas_outbuf.c [new file with mode: 0755]
src/modules/evas/engines/wayland_egl/evas_engine.c
src/modules/evas/engines/wayland_shm/evas_engine.c [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 0e9dd69..6b88da8
@@ -1736,6 +1736,19 @@ AC_ARG_ENABLE([ecore-buffer],
    ],
    [want_ecore_buffer="no"])
 
+
+# Ecore_Tbm
+AC_ARG_ENABLE([tbm],
+   [AS_HELP_STRING([--enable-tbm],[Enable tbm. @<:@default=disabled@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       want_evas_engine_tbm="yes"
+    else
+       want_evas_engine_tbm="no"
+    fi
+   ],
+   [want_evas_engine_tbm="no"])
+
 # Image Loaders
 
 ARG_ENABLE_EVAS_IMAGE_LOADER(BMP, static)
@@ -1871,6 +1884,8 @@ EVAS_CHECK_ENGINE([wayland-egl], [${want_evas_engine_wayland_egl}], [no], [Wayla
 EVAS_CHECK_ENGINE([wayland-shm], [${want_wayland}], [no], [Wayland Shm])
 EVAS_CHECK_ENGINE([drm], [${want_drm}], [no], [Drm])
 EVAS_CHECK_ENGINE([gl-drm], [${want_gl_drm}], [no], [OpenGL Drm])
+EVAS_CHECK_ENGINE([gl-tbm], [${want_evas_engine_tbm}], [no], [OpenGL Tbm])
+EVAS_CHECK_ENGINE([software-tbm], [${want_evas_engine_tbm}], [no], [Software Tbm])
 
 
 # Software XCB
@@ -2027,6 +2042,7 @@ if test "x$have_evas_engine_gl_xlib" = "xyes" || \
    test "x$have_evas_engine_gl_sdl" = "xyes" || \
    test "x$have_evas_engine_gl_cocoa" = "xyes" || \
    test "x$have_evas_engine_gl_drm" = "xyes" || \
+   test "x$have_evas_engine_tbm" = "xyes" || \
    test "x$have_evas_engine_wayland_egl" = "xyes"; then
    have_evas_engine_gl_common="yes"
 fi
@@ -2035,6 +2051,7 @@ if test "x$have_evas_engine_gl_xlib" = "xstatic" || \
    test "x$have_evas_engine_gl_sdl" = "xstatic" || \
    test "x$have_evas_engine_gl_cocoa" = "xstatic" || \
    test "x$have_evas_engine_gl_drm" = "xstatic" || \
+   test "x$have_evas_engine_tbm" = "xstatic" || \
    test "x$have_evas_engine_wayland_egl" = "xstatic"; then
    have_evas_engine_gl_common="yes"
    have_static_evas_engine_gl_common="yes"
@@ -3966,6 +3983,7 @@ want_ecore_evas_software_gdi="${have_evas_engine_software_gdi}"
 want_ecore_evas_software_ddraw="${have_evas_engine_software_ddraw}"
 want_ecore_evas_gl_cocoa="${have_evas_engine_gl_cocoa}"
 want_ecore_evas_wayland_egl="${have_evas_engine_wayland_egl}"
+want_ecore_evas_tbm="${have_evas_engine_tbm}"
 want_ecore_evas_extn="yes"
 want_ecore_evas_drm="${have_evas_engine_drm}"
 
@@ -4017,6 +4035,8 @@ AM_CONDITIONAL([BUILD_ECORE_EVAS_SDL],
 
 ECORE_EVAS_MODULE([wayland-shm], [${want_wayland}])
 ECORE_EVAS_MODULE([wayland-egl], [${want_ecore_evas_wayland_egl}])
+ECORE_EVAS_MODULE([gl-tbm], [${want_ecore_evas_tbm}])
+ECORE_EVAS_MODULE([software-tbm], [${want_ecore_evas_tbm}])
 
 build_ecore_evas_wayland="no"
 if test "x${have_ecore_evas_wayland_shm}" = "xyes" || \
old mode 100644 (file)
new mode 100755 (executable)
index 8f54f2d..fb1f909
@@ -661,6 +661,85 @@ AS_IF([test "x${have_dep}" = "xyes"], [$4], [$5])
 
 ])
 
+dnl use: EVAS_CHECK_ENGINE_DEP_GL_TBM(engine, simple, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+
+AC_DEFUN([EVAS_CHECK_ENGINE_DEP_GL_TBM],
+[
+
+requirement=""
+have_dep="no"
+evas_engine_[]$1[]_cflags=""
+evas_engine_[]$1[]_libs=""
+
+if test "x${with_opengl}" = "xes" ; then
+    gl_library="glesv2"
+else
+    gl_library="gl"
+fi
+
+PKG_CHECK_EXISTS([egl ${gl_library} wayland-client >= 1.3.0 wayland-egl >= 9.2.0],
+   [
+    have_dep="yes"
+    requirement="egl ${gl_library} wayland-client wayland-egl"
+   ],
+   [have_dep="no"])
+
+if test "x${have_dep}" = "xyes" ; then
+   if test "${gl_library}" != "gl" ; then
+      have_egl="yes"
+   fi
+   if test "x$3" = "xstatic" ; then
+      requirements_pc_evas="${requirement} ${requirements_pc_evas}"
+      requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}"
+   else
+      PKG_CHECK_MODULES([GL_TBM], [${requirement}])
+      evas_engine_[]$1[]_cflags="${GL_TBM_CFLAGS}"
+      evas_engine_[]$1[]_libs="${GL_TBM_LIBS}"
+      evas_engine_gl_common_libs="$evas_engine_[]$1[]_libdirs -lGLESv2 -lm -lEGL"
+   fi
+fi
+
+AC_SUBST([evas_engine_$1_cflags])
+AC_SUBST([evas_engine_$1_libs])
+
+AS_IF([test "x${have_dep}" = "xyes"], [$4], [$5])
+
+])
+
+dnl use: EVAS_CHECK_ENGINE_DEP_SOFTWARE_TBM(engine, simple, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+
+AC_DEFUN([EVAS_CHECK_ENGINE_DEP_SOFTWARE_TBM],
+[
+
+requirement=""
+have_dep="no"
+evas_engine_[]$1[]_cflags=""
+evas_engine_[]$1[]_libs=""
+
+PKG_CHECK_EXISTS([wayland-client >= 1.3.0],
+   [
+    have_dep="yes"
+    requirement="wayland-client"
+   ],
+   [have_dep="no"])
+
+if test "x${have_dep}" = "xyes" ; then
+   if test "x$3" = "xstatic" ; then
+      requirements_pc_evas="${requirement} ${requirements_pc_evas}"
+      requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}"
+   else
+      PKG_CHECK_MODULES([SOFTWARE_TBM], [${requirement}])
+      evas_engine_[]$1[]_cflags="${SOFTWARE_TBM_CFLAGS}"
+      evas_engine_[]$1[]_libs="${SOFTWARE_TBM_LIBS}"
+   fi
+fi
+
+AC_SUBST([evas_engine_$1_cflags])
+AC_SUBST([evas_engine_$1_libs])
+
+AS_IF([test "x${have_dep}" = "xyes"], [$4], [$5])
+
+])
 
 dnl use: EVAS_ENGINE(name, want_engine, [DEPENDENCY-CHECK-CODE])
 dnl
old mode 100644 (file)
new mode 100755 (executable)
index cb9cb10..ac42b03
@@ -695,6 +695,7 @@ CFLAGS+=" -DMESA_EGL_NO_X11_HEADERS "
     --with-opengl=es \
     --disable-rpath \
     --disable-ibus \
+    --enable-tbm \
 %endif
 %if %{with x}
     --with-opengl=es \
index b86b661..3d13bea 100755 (executable)
@@ -12,6 +12,8 @@ lib_ecore_evas_libecore_evas_la_SOURCES = \
 lib/ecore_evas/ecore_evas.c \
 lib/ecore_evas/ecore_evas_buffer.c \
 lib/ecore_evas/ecore_evas_buffer.h \
+lib/ecore_evas/ecore_evas_tbm.c \
+lib/ecore_evas/ecore_evas_tbm.h \
 lib/ecore_evas/ecore_evas_deprecated.c \
 lib/ecore_evas/ecore_evas_drm.h \
 lib/ecore_evas/ecore_evas_ews.c \
@@ -26,6 +28,8 @@ lib/ecore_evas/ecore_evas_util.c
 
 lib_ecore_evas_libecore_evas_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/modules/evas/engines/buffer \
+-I$(top_srcdir)/src/modules/evas/engines/gl_tbm \
+-I$(top_srcdir)/src/modules/evas/engines/software_tbm \
 -DPACKAGE_BIN_DIR=\"$(bindir)\" \
 -DPACKAGE_LIB_DIR=\"$(libdir)\" \
 -DPACKAGE_DATA_DIR=\"$(datadir)/ecore_evas\" \
@@ -188,6 +192,7 @@ modules_ecore_evas_engines_wayland_module_la_CPPFLAGS = -I$(top_builddir)/src/li
 @ECORE_WAYLAND_CFLAGS@ \
 -I$(top_srcdir)/src/modules/evas/engines/wayland_shm \
 -I$(top_srcdir)/src/modules/evas/engines/wayland_egl \
+-I$(top_srcdir)/src/modules/evas/engines/gl_tbm \
 @ECORE_WAYLAND_CFLAGS@
 modules_ecore_evas_engines_wayland_module_la_LIBADD = \
 @USE_ECORE_EVAS_LIBS@ \
old mode 100644 (file)
new mode 100755 (executable)
index 807f178..968c391
@@ -800,6 +800,9 @@ endif
 if BUILD_ENGINE_GL_DRM
 modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_gl_drm_cflags@
 endif
+if BUILD_ENGINE_GL_TBM
+modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_gl_tbm_cflags@
+endif
 modules_evas_engines_gl_common_libevas_engine_gl_common_la_LIBADD = @USE_EVAS_LIBS@ @TTRACE_LIBS@
 modules_evas_engines_gl_common_libevas_engine_gl_common_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@
 modules_evas_engines_gl_common_libevas_engine_gl_common_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
@@ -1256,6 +1259,76 @@ modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
 endif
 endif
 
+if BUILD_ENGINE_GL_TBM
+dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_tbm/Evas_Engine_GL_Tbm.h
+GL_TBM_SOURCES = \
+modules/evas/engines/gl_tbm/evas_engine.c \
+modules/evas/engines/gl_tbm/evas_tbm_main.c \
+modules/evas/engines/gl_tbm/evas_engine.h
+if EVAS_STATIC_BUILD_GL_TBM
+lib_evas_libevas_la_SOURCES += $(GL_TBM_SOURCES)
+lib_evas_libevas_la_CPPFLAGS += @evas_engine_gl_tbm_cflags@
+lib_evas_libevas_la_LIBADD += @evas_engine_gl_tbm_libs@
+else
+enginegltbmpkgdir = $(libdir)/evas/modules/engines/gl_tbm/$(MODULE_ARCH)
+enginegltbmpkg_LTLIBRARIES = modules/evas/engines/gl_tbm/module.la
+
+# Workaround for broken parallel install support in automake (relink issue)
+# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7328
+install_enginegltbmpkgLTLIBRARIES = install-enginegltbmpkgLTLIBRARIES
+$(install_enginegltbmpkgLTLIBRARIES): install-libLTLIBRARIES
+
+modules_evas_engines_gl_tbm_module_la_SOURCES = $(GL_TBM_SOURCES)
+modules_evas_engines_gl_tbm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/lib/evas/include \
+-I$(top_srcdir)/src/lib/evas/cserve2 \
+-I$(top_srcdir)/src/modules/evas/engines/gl_tbm \
+@EVAS_CFLAGS@ \
+@evas_engine_gl_tbm_cflags@
+modules_evas_engines_gl_tbm_module_la_LIBADD = \
+@USE_EVAS_LIBS@ \
+@evas_engine_gl_tbm_libs@
+modules_evas_engines_gl_tbm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@
+modules_evas_engines_gl_tbm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_evas_engines_gl_tbm_module_la_LIBTOOLFLAGS = --tag=disable-static
+endif
+endif
+
+if BUILD_ENGINE_SOFTWARE_TBM
+dist_installed_evasmainheaders_DATA += modules/evas/engines/software_tbm/Evas_Engine_Software_Tbm.h
+SOFTWARE_TBM_SOURCES = \
+modules/evas/engines/software_tbm/evas_engine.c \
+modules/evas/engines/software_tbm/evas_outbuf.c \
+modules/evas/engines/software_tbm/evas_engine.h
+if EVAS_STATIC_BUILD_SOFTWARE_TBM
+lib_evas_libevas_la_SOURCES += $(SOFTWARE_TBM_SOURCES)
+lib_evas_libevas_la_CPPFLAGS += @evas_engine_software_tbm_cflags@
+lib_evas_libevas_la_LIBADD += @evas_engine_software_tbm_libs@
+else
+enginesoftwaretbmpkgdir = $(libdir)/evas/modules/engines/software_tbm/$(MODULE_ARCH)
+enginesoftwaretbmpkg_LTLIBRARIES = modules/evas/engines/software_tbm/module.la
+
+# Workaround for broken parallel install support in automake (relink issue)
+# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7328
+install_enginesoftwaretbmpkgLTLIBRARIES = install-enginesoftwaretbmpkgLTLIBRARIES
+$(install_enginesoftwaretbmpkgLTLIBRARIES): install-libLTLIBRARIES
+
+modules_evas_engines_software_tbm_module_la_SOURCES = $(SOFTWARE_TBM_SOURCES)
+modules_evas_engines_software_tbm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-I$(top_srcdir)/src/lib/evas/include \
+-I$(top_srcdir)/src/lib/evas/cserve2 \
+-I$(top_srcdir)/src/modules/evas/engines/software_tbm \
+@EVAS_CFLAGS@ \
+@evas_engine_software_tbm_cflags@
+modules_evas_engines_software_tbm_module_la_LIBADD = \
+@USE_EVAS_LIBS@ \
+@evas_engine_software_tbm_libs@
+modules_evas_engines_software_tbm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@
+modules_evas_engines_software_tbm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
+modules_evas_engines_software_tbm_module_la_LIBTOOLFLAGS = --tag=disable-static
+endif
+endif
+
 ### Cserve2 binary
 
 if EVAS_CSERVE2
old mode 100644 (file)
new mode 100755 (executable)
index adcbd89..f960147
@@ -104,6 +104,8 @@ extern "C" {
 #define HAVE_ECORE_EVAS_WAYLAND_EGL 1
 #define HAVE_ECORE_EVAS_DRM 1
 #define HAVE_ECORE_EVAS_DRM_GL 1
+#define HAVE_ECORE_EVAS_TBM 1
+#define HAVE_ECORE_EVAS_SOFTWARE_TBM 1
 
 typedef enum _Ecore_Evas_Engine_Type
 {
@@ -131,7 +133,9 @@ typedef enum _Ecore_Evas_Engine_Type
    ECORE_EVAS_ENGINE_WAYLAND_SHM,
    ECORE_EVAS_ENGINE_WAYLAND_EGL,
    ECORE_EVAS_ENGINE_DRM,
-   ECORE_EVAS_ENGINE_OPENGL_DRM
+   ECORE_EVAS_ENGINE_OPENGL_DRM,
+   ECORE_EVAS_ENGINE_OPENGL_TBM,
+   ECORE_EVAS_ENGINE_SOFTWARE_TBM,
 } Ecore_Evas_Engine_Type;
 
 typedef enum _Ecore_Evas_Avoid_Damage_Type
@@ -1377,6 +1381,13 @@ EAPI Ecore_Wl_Window *ecore_evas_wayland_window_get(const Ecore_Evas *ee);
 EAPI Ecore_Evas     *ecore_evas_drm_new(const char *device, unsigned int parent, int x, int y, int w, int h);
 EAPI Ecore_Evas     *ecore_evas_gl_drm_new(const char *device, unsigned int parent, int x, int y, int w, int h); /** @since 1.12 */
 
+EAPI Ecore_Evas     *ecore_evas_gl_tbm_new(int w, int h);
+EAPI Ecore_Evas     *ecore_evas_software_tbm_new(int w, int h);
+EAPI Ecore_Evas     *ecore_evas_tbm_allocfunc_new(const char *engine, int w, int h,void *(*alloc_func) (void *data, int w, int h),void (*free_func) (void *data, void *tbm_queue),const void *data);
+EAPI Ecore_Evas     *ecore_evas_tbm_ext_new(const char *engine, const void *tbm_surf_queue, void* data);
+EAPI const void     *ecore_evas_tbm_pixels_acquire(Ecore_Evas *ee);
+EAPI void            ecore_evas_tbm_pixels_release(Ecore_Evas *ee);
+
 /**
  * @brief Create a new @c Ecore_Evas canvas bound to the Evas
  * @b buffer engine
old mode 100644 (file)
new mode 100755 (executable)
index 55911e2..dca937e
@@ -332,6 +332,19 @@ ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine)
 #else
         return EINA_FALSE;
 #endif
+     case ECORE_EVAS_ENGINE_OPENGL_TBM:
+#ifdef BUILD_ECORE_EVAS_GL_TBM
+        return EINA_TRUE;
+#else
+        return EINA_FALSE;
+#endif
+     case ECORE_EVAS_ENGINE_SOFTWARE_TBM:
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_TBM
+        return EINA_TRUE;
+#else
+        return EINA_FALSE;
+#endif
+
 
       default:
         return EINA_FALSE;
@@ -760,6 +773,22 @@ _ecore_evas_constructor_ews(int x, int y, int w, int h, const char *extra_option
 }
 #endif
 
+#ifdef BUILD_ECORE_EVAS_GL_TBM
+static Ecore_Evas *
+_ecore_evas_constructor_gl_tbm(int x EINA_UNUSED, int y EINA_UNUSED, int w, int h, const char *extra_options EINA_UNUSED)
+{
+   return ecore_evas_gl_tbm_new(w, h);
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_TBM
+static Ecore_Evas *
+_ecore_evas_constructor_software_tbm(int x EINA_UNUSED, int y EINA_UNUSED, int w, int h, const char *extra_options EINA_UNUSED)
+{
+   return ecore_evas_software_tbm_new(w, h);
+}
+#endif
+
 /* note: keep sorted by priority, highest first */
 static const struct ecore_evas_engine _engines[] = {
   /* unix */
@@ -789,6 +818,12 @@ static const struct ecore_evas_engine _engines[] = {
 #ifdef BUILD_ECORE_EVAS_EWS
   {"ews", _ecore_evas_constructor_ews},
 #endif
+#ifdef BUILD_ECORE_EVAS_GL_TBM
+  {"gl_tbm", _ecore_evas_constructor_gl_tbm},
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_TBM
+  {"software_tbm", _ecore_evas_constructor_software_tbm},
+#endif
   {NULL, NULL}
 };
 
old mode 100644 (file)
new mode 100755 (executable)
index 59fb601..0bc99ec
@@ -241,6 +241,12 @@ _ecore_evas_available_engines_get(void)
 #ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
                             ADDENG("wayland_egl");
 #endif
+#ifdef BUILD_ECORE_EVAS_TBM
+                           ADDENG("gl_tbm");
+#endif
+#ifdef BUILD_ECORE_EVAS_SOFTWARE_TBM
+                           ADDENG("software_tbm");
+#endif
                          }
                        else if (!strcmp(name, "win32"))
                          {
diff --git a/src/lib/ecore_evas/ecore_evas_tbm.c b/src/lib/ecore_evas/ecore_evas_tbm.c
new file mode 100755 (executable)
index 0000000..e7d33e8
--- /dev/null
@@ -0,0 +1,911 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <Evas_Engine_GL_Tbm.h>
+#include <Evas_Engine_Software_Tbm.h>
+#include <Ecore.h>
+#include "ecore_private.h"
+#include <Ecore_Input.h>
+#include <tbm_bufmgr.h>
+#include <tbm_surface_queue.h>
+
+#include "Ecore_Evas.h"
+#include "ecore_evas_tbm.h"
+#include "ecore_evas_private.h"
+
+
+static void
+_ecore_evas_tbm_free(Ecore_Evas *ee)
+{
+   Ecore_Evas_Engine_Tbm_Data *tbm_data = ee->engine.data;
+
+   if (tbm_data->tbm_queue)
+     tbm_data->free_func(tbm_data->data,tbm_data->tbm_queue);
+   free(tbm_data);
+}
+
+static void
+_ecore_evas_resize(Ecore_Evas *ee, int w, int h)
+{
+   Ecore_Evas_Engine_Tbm_Data *tbm_data = ee->engine.data;
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->req.w = w;
+   ee->req.h = h;
+   if ((w == ee->w) && (h == ee->h)) return;
+   ee->w = w;
+   ee->h = h;
+   evas_output_size_set(ee->evas, ee->w, ee->h);
+   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
+
+   if (tbm_data->tbm_queue)
+     tbm_data->free_func(tbm_data->data,tbm_data->tbm_queue);
+
+   tbm_data->tbm_queue = tbm_data->alloc_func(tbm_data->data, ee->w, ee->h);
+   if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_move_resize(Ecore_Evas *ee, int x EINA_UNUSED, int y EINA_UNUSED, int w, int h)
+{
+   _ecore_evas_resize(ee, w, h);
+}
+
+static void
+_ecore_evas_show(Ecore_Evas *ee)
+{
+   if (ee->prop.focused) return;
+   ee->prop.focused = EINA_TRUE;
+   ee->prop.withdrawn = EINA_FALSE;
+   if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
+   evas_focus_in(ee->evas);
+   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+}
+
+static int
+_ecore_evas_tbm_render(Ecore_Evas *ee)
+{
+   Eina_List *updates = NULL, *ll;
+   Ecore_Evas_Engine_Tbm_Data *tbm_data;
+   Ecore_Evas *ee2;
+   int rend = 0;
+
+   tbm_data = ee->engine.data;
+   EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+     {
+        if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+        if (ee2->engine.func->fn_render)
+           rend |= ee2->engine.func->fn_render(ee2);
+        if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+     }
+   if (tbm_data->tbm_queue)
+     {
+        updates = evas_render_updates(ee->evas);
+     }
+   if (updates)
+     {
+        evas_render_updates_free(updates);
+        _ecore_evas_idle_timeout_update(ee);
+     }
+
+   if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+   return updates ? 1 : rend;
+}
+
+EAPI int
+ecore_evas_tbm_render(Ecore_Evas *ee)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ee, 0);
+   return _ecore_evas_tbm_render(ee);
+}
+
+#if 0
+/* TODO : */
+// NOTE: if you fix this, consider fixing ecore_evas_ews.c as it is similar!
+static void
+_ecore_evas_tbm_coord_translate(Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
+{
+   Ecore_Evas_Engine_Tbm_Data *tbm_data = ee->engine.data;
+   Evas_Coord xx, yy, ww, hh, fx, fy, fw, fh;
+
+   evas_object_geometry_get(tbm_data->image, &xx, &yy, &ww, &hh);
+   evas_object_image_fill_get(tbm_data->image, &fx, &fy, &fw, &fh);
+
+   if (fw < 1) fw = 1;
+   if (fh < 1) fh = 1;
+
+   if (evas_object_map_get(tbm_data->image) &&
+       evas_object_map_enable_get(tbm_data->image))
+     {
+        fx = 0; fy = 0;
+        fw = ee->w; fh = ee->h;
+        ww = ee->w; hh = ee->h;
+     }
+
+   if ((fx == 0) && (fy == 0) && (fw == ww) && (fh == hh))
+     {
+        *x = (ee->w * (*x - xx)) / fw;
+        *y = (ee->h * (*y - yy)) / fh;
+     }
+   else
+     {
+        xx = (*x - xx) - fx;
+        while (xx < 0) xx += fw;
+        while (xx > fw) xx -= fw;
+        *x = (ee->w * xx) / fw;
+
+        yy = (*y - yy) - fy;
+        while (yy < 0) yy += fh;
+        while (yy > fh) yy -= fh;
+        *y = (ee->h * yy) / fh;
+     }
+}
+
+static void
+_ecore_evas_tbm_transfer_modifiers_locks(Evas *e, Evas *e2)
+{
+   const char *mods[] =
+     { "Shift", "Control", "Alt", "Meta", "Hyper", "Super", NULL };
+   const char *locks[] =
+     { "Scroll_Lock", "Num_Lock", "Caps_Lock", NULL };
+   int i;
+
+   for (i = 0; mods[i]; i++)
+     {
+        if (evas_key_modifier_is_set(evas_key_modifier_get(e), mods[i]))
+          evas_key_modifier_on(e2, mods[i]);
+        else
+          evas_key_modifier_off(e2, mods[i]);
+     }
+   for (i = 0; locks[i]; i++)
+     {
+        if (evas_key_lock_is_set(evas_key_lock_get(e), locks[i]))
+          evas_key_lock_on(e2, locks[i]);
+        else
+          evas_key_lock_off(e2, locks[i]);
+     }
+}
+
+static void
+_ecore_evas_tbm_cb_mouse_in(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_In *ev;
+
+   ee = data;
+   ev = event_info;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_mouse_in(ee->evas, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_mouse_out(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Out *ev;
+
+   ee = data;
+   ev = event_info;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_mouse_out(ee->evas, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_mouse_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Down *ev;
+
+   ee = data;
+   ev = event_info;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_mouse_down(ee->evas, ev->button, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_mouse_up(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Up *ev;
+
+   ee = data;
+   ev = event_info;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_mouse_up(ee->evas, ev->button, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_mouse_move(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Move *ev;
+   Evas_Coord x, y;
+
+   ee = data;
+   ev = event_info;
+   x = ev->cur.canvas.x;
+   y = ev->cur.canvas.y;
+   _ecore_evas_tbm_coord_translate(ee, &x, &y);
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   _ecore_evas_mouse_move_process(ee, x, y, ev->timestamp);
+}
+
+static void
+_ecore_evas_tbm_cb_mouse_wheel(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Mouse_Wheel *ev;
+
+   ee = data;
+   ev = event_info;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_mouse_wheel(ee->evas, ev->direction, ev->z, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_multi_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Multi_Down *ev;
+   Evas_Coord x, y, xx, yy;
+   double xf, yf;
+
+   ee = data;
+   ev = event_info;
+   x = ev->canvas.x;
+   y = ev->canvas.y;
+   xx = x;
+   yy = y;
+   _ecore_evas_tbm_coord_translate(ee, &x, &y);
+   xf = (ev->canvas.xsub - (double)xx) + (double)x;
+   yf = (ev->canvas.ysub - (double)yy) + (double)y;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_multi_down(ee->evas, ev->device, x, y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, xf, yf, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_multi_up(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Multi_Up *ev;
+   Evas_Coord x, y, xx, yy;
+   double xf, yf;
+
+   ee = data;
+   ev = event_info;
+   x = ev->canvas.x;
+   y = ev->canvas.y;
+   xx = x;
+   yy = y;
+   _ecore_evas_tbm_coord_translate(ee, &x, &y);
+   xf = (ev->canvas.xsub - (double)xx) + (double)x;
+   yf = (ev->canvas.ysub - (double)yy) + (double)y;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_multi_up(ee->evas, ev->device, x, y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, xf, yf, ev->flags, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_multi_move(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Multi_Move *ev;
+   Evas_Coord x, y, xx, yy;
+   double xf, yf;
+
+   ee = data;
+   ev = event_info;
+   x = ev->cur.canvas.x;
+   y = ev->cur.canvas.y;
+   xx = x;
+   yy = y;
+   _ecore_evas_tbm_coord_translate(ee, &x, &y);
+   xf = (ev->cur.canvas.xsub - (double)xx) + (double)x;
+   yf = (ev->cur.canvas.ysub - (double)yy) + (double)y;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_multi_move(ee->evas, ev->device, x, y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, xf, yf, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_free(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   if (ee->driver) _ecore_evas_free(ee);
+}
+
+static void
+_ecore_evas_tbm_cb_key_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Key_Down *ev;
+
+   ee = data;
+   ev = event_info;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_key_down(ee->evas, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_key_up(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
+{
+   Ecore_Evas *ee;
+   Evas_Event_Key_Up *ev;
+
+   ee = data;
+   ev = event_info;
+   _ecore_evas_tbm_transfer_modifiers_locks(e, ee->evas);
+   evas_event_feed_key_up(ee->evas, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, NULL);
+}
+
+static void
+_ecore_evas_tbm_cb_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->prop.focused = EINA_TRUE;
+   evas_focus_in(ee->evas);
+   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+}
+
+static void
+_ecore_evas_tbm_cb_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->prop.focused = EINA_FALSE;
+   evas_focus_out(ee->evas);
+   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+}
+
+static void
+_ecore_evas_tbm_cb_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->prop.withdrawn = EINA_FALSE;
+   if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
+   ee->visible = 1;
+   if (ee->func.fn_show) ee->func.fn_show(ee);
+}
+
+static void
+_ecore_evas_tbm_cb_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+   Ecore_Evas *ee;
+
+   ee = data;
+   ee->prop.withdrawn = EINA_TRUE;
+   if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
+   ee->visible = 0;
+   if (ee->func.fn_hide) ee->func.fn_hide(ee);
+}
+#endif
+
+static void
+_ecore_evas_tbm_alpha_set(Ecore_Evas *ee, int alpha)
+{
+   if (((ee->alpha) && (alpha)) || ((!ee->alpha) && (!alpha))) return;
+   ee->alpha = alpha;
+}
+
+static void
+_ecore_evas_tbm_profile_set(Ecore_Evas *ee, const char *profile)
+{
+   _ecore_evas_window_profile_free(ee);
+   ee->prop.profile.name = NULL;
+
+   if (profile)
+     {
+        ee->prop.profile.name = (char *)eina_stringshare_add(profile);
+
+        /* just change ee's state.*/
+        if (ee->func.fn_state_change)
+          ee->func.fn_state_change(ee);
+     }
+}
+
+static void
+_ecore_evas_tbm_msg_parent_send(Ecore_Evas *ee, int msg_domain, int msg_id, void *data, int size)
+{
+   Ecore_Evas *parent_ee = NULL;
+   parent_ee = ecore_evas_data_get(ee, "parent");
+
+   if (parent_ee)
+     {
+        if (parent_ee->func.fn_msg_parent_handle)
+          parent_ee ->func.fn_msg_parent_handle(parent_ee, msg_domain, msg_id, data, size);
+     }
+   else
+     {
+        if (ee->func.fn_msg_parent_handle)
+          ee ->func.fn_msg_parent_handle(ee, msg_domain, msg_id, data, size);
+     }
+}
+
+static void
+_ecore_evas_tbm_msg_send(Ecore_Evas *ee, int msg_domain, int msg_id, void *data, int size)
+{
+   Ecore_Evas *child_ee = NULL;
+   child_ee = ecore_evas_data_get(ee, "child");
+
+   if (child_ee)
+     {
+        if (child_ee->func.fn_msg_handle)
+          child_ee->func.fn_msg_handle(child_ee, msg_domain, msg_id, data, size);
+     }
+   else
+     {
+        if (ee->func.fn_msg_handle)
+          ee->func.fn_msg_handle(ee, msg_domain, msg_id, data, size);
+     }
+}
+
+static Ecore_Evas_Engine_Func _ecore_tbm_engine_func =
+{
+     _ecore_evas_tbm_free,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_resize,
+     _ecore_evas_move_resize,
+     NULL,
+     NULL,
+     _ecore_evas_show,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     _ecore_evas_tbm_alpha_set,
+     NULL, //transparent
+     NULL, // profiles_set
+     _ecore_evas_tbm_profile_set,
+
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+     NULL,
+
+     _ecore_evas_tbm_render,
+     NULL, // screen_geometry_get
+     NULL,  // screen_dpi_get
+     _ecore_evas_tbm_msg_parent_send,
+     _ecore_evas_tbm_msg_send,
+
+     NULL, // pointer_xy_get
+     NULL, // pointer_warp
+
+     NULL, // wm_rot_preferred_rotation_set
+     NULL, // wm_rot_available_rotations_set
+     NULL, // wm_rot_manual_rotation_done_set
+     NULL, // wm_rot_manual_rotation_done
+
+     NULL  // aux_hints_set
+};
+
+static tbm_surface_queue_h *
+_ecore_evas_tbm_queue_alloc(void *data EINA_UNUSED, int w, int h)
+{
+   return tbm_surface_queue_create(3, w, h, TBM_FORMAT_ARGB8888, TBM_BO_DEFAULT);
+}
+
+static void
+_ecore_evas_tbm_queue_free(void *data EINA_UNUSED, void *tbm_queue)
+{
+    tbm_surface_queue_destroy(tbm_queue);
+}
+
+EAPI Ecore_Evas *
+ecore_evas_tbm_ext_new(const char *engine, const void *tbm_surf_queue, void* data)
+{
+
+   Ecore_Evas_Engine_Tbm_Data *tbm_data;
+   Ecore_Evas *ee;
+   const char *driver_name;
+   int rmethod;
+   int w, h;
+
+    EINA_SAFETY_ON_NULL_RETURN_VAL(tbm_surf_queue, NULL);
+
+   if (!strcmp(engine, "gl_tbm"))
+      {
+         driver_name = "gl_tbm";
+      }
+   else if (!strcmp(engine, "software_tbm"))
+      {
+         driver_name = "software_tbm";
+      }
+   else
+      {
+         ERR("engine name is NULL!!");
+         return NULL;
+      }
+
+   rmethod = evas_render_method_lookup(driver_name);
+    EINA_SAFETY_ON_TRUE_RETURN_VAL(rmethod == 0, NULL);
+
+
+    ee = calloc(1, sizeof(Ecore_Evas));
+    EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL);
+
+    tbm_data = calloc(1, sizeof(Ecore_Evas_Engine_Tbm_Data));
+    if (!tbm_data)
+      {
+        free(ee);
+        return NULL;
+      }
+
+
+    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_tbm_engine_func;
+    ee->engine.data = tbm_data;
+    tbm_data->alloc_func = NULL;
+    tbm_data->free_func = NULL;
+    tbm_data->data = (void *)data;
+    tbm_data->tbm_queue = tbm_surf_queue;
+    tbm_data->ext_tbm_queue = EINA_TRUE;
+
+   ee->driver = driver_name;
+
+    w = tbm_surface_queue_get_width(tbm_data->tbm_queue);
+    h = tbm_surface_queue_get_height(tbm_data->tbm_queue);
+
+    if (w < 1) w = 1;
+    if (h < 1) h = 1;
+    ee->rotation = 0;
+    ee->visible = 1;
+    ee->w = w;
+    ee->h = h;
+    ee->req.w = ee->w;
+    ee->req.h = ee->h;
+    ee->profile_supported = 1;
+
+    ee->prop.max.w = 0;
+    ee->prop.max.h = 0;
+    ee->prop.layer = 0;
+    ee->prop.focused = EINA_TRUE;
+    ee->prop.borderless = EINA_TRUE;
+    ee->prop.override = EINA_TRUE;
+    ee->prop.maximized = EINA_TRUE;
+    ee->prop.fullscreen = EINA_FALSE;
+    ee->prop.withdrawn = EINA_FALSE;
+    ee->prop.sticky = EINA_FALSE;
+
+    /* init evas here */
+    ee->evas = evas_new();
+    evas_data_attach_set(ee->evas, ee);
+    evas_output_method_set(ee->evas, rmethod);
+    evas_output_size_set(ee->evas, w, h);
+    evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+    if (!strcmp(driver_name, "gl_tbm"))
+      {
+         Evas_Engine_Info_GL_Tbm *einfo = (Evas_Engine_Info_GL_Tbm *)evas_engine_info_get(ee->evas);
+         if (einfo)
+            {
+               einfo->info.tbm_queue = tbm_data->tbm_queue;
+               einfo->info.destination_alpha = EINA_TRUE;
+               einfo->info.ext_tbm_queue = EINA_FALSE;
+               einfo->info.rotation = 0;
+               einfo->info.depth = 32;
+               if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                  {
+                     ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                     ecore_evas_free(ee);
+                     return NULL;
+                  }
+            }
+         else
+            {
+               ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+               ecore_evas_free(ee);
+               return NULL;
+            }
+      }
+   else if (!strcmp(driver_name, "software_tbm"))
+      {
+         Evas_Engine_Info_Software_Tbm *einfo = (Evas_Engine_Info_Software_Tbm *)evas_engine_info_get(ee->evas);
+         if (einfo)
+            {
+               einfo->info.tbm_queue = tbm_data->tbm_queue;
+               einfo->info.destination_alpha = EINA_TRUE;
+               einfo->info.ext_tbm_queue = EINA_FALSE;
+               einfo->info.rotation = 0;
+               einfo->info.depth = 32;
+               if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                  {
+                     ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                     ecore_evas_free(ee);
+                     return NULL;
+                  }
+            }
+         else
+            {
+               ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+               ecore_evas_free(ee);
+               return NULL;
+            }
+      }
+
+    evas_key_modifier_add(ee->evas, "Shift");
+    evas_key_modifier_add(ee->evas, "Control");
+    evas_key_modifier_add(ee->evas, "Alt");
+    evas_key_modifier_add(ee->evas, "Meta");
+    evas_key_modifier_add(ee->evas, "Hyper");
+    evas_key_modifier_add(ee->evas, "Super");
+    evas_key_lock_add(ee->evas, "Caps_Lock");
+    evas_key_lock_add(ee->evas, "Num_Lock");
+    evas_key_lock_add(ee->evas, "Scroll_Lock");
+
+    evas_event_feed_mouse_in(ee->evas, 0, NULL);
+
+    _ecore_evas_register(ee);
+
+    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+
+    return ee;
+}
+
+EAPI Ecore_Evas *
+ecore_evas_tbm_allocfunc_new(const char *engine, int w, int h,
+                             void *(*alloc_func) (void *data, int w, int h),
+                             void (*free_func) (void *data, void *tbm_queue),
+                             const void *data)
+{
+
+   Ecore_Evas_Engine_Tbm_Data *tbm_data;
+   Ecore_Evas *ee;
+   int rmethod;
+   const char *driver_name;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(alloc_func, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(free_func, NULL);
+
+
+   if (!strcmp(engine, "gl_tbm"))
+      {
+         driver_name = "gl_tbm";
+      }
+   else if (!strcmp(engine, "software_tbm"))
+      {
+         driver_name = "software_tbm";
+      }
+   else
+      {
+         ERR("engine name is NULL!!");
+         return NULL;
+      }
+
+   rmethod = evas_render_method_lookup(driver_name);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL(rmethod == 0, NULL);
+
+   ee = calloc(1, sizeof(Ecore_Evas));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL);
+
+   tbm_data = calloc(1, sizeof(Ecore_Evas_Engine_Tbm_Data));
+   if (!tbm_data)
+     {
+       free(ee);
+       return NULL;
+     }
+
+   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_tbm_engine_func;
+   ee->engine.data = tbm_data;
+   tbm_data->alloc_func = alloc_func;
+   tbm_data->free_func = free_func;
+   tbm_data->data = (void *)data;
+   tbm_data->ext_tbm_queue = EINA_FALSE;
+
+   ee->driver = driver_name;
+
+   if (w < 1) w = 1;
+   if (h < 1) h = 1;
+   ee->rotation = 0;
+   ee->visible = 1;
+   ee->w = w;
+   ee->h = h;
+   ee->req.w = ee->w;
+   ee->req.h = ee->h;
+   ee->profile_supported = 1;
+
+   ee->prop.max.w = 0;
+   ee->prop.max.h = 0;
+   ee->prop.layer = 0;
+   ee->prop.focused = EINA_TRUE;
+   ee->prop.borderless = EINA_TRUE;
+   ee->prop.override = EINA_TRUE;
+   ee->prop.maximized = EINA_TRUE;
+   ee->prop.fullscreen = EINA_FALSE;
+   ee->prop.withdrawn = EINA_FALSE;
+   ee->prop.sticky = EINA_FALSE;
+
+   /* init evas here */
+   ee->evas = evas_new();
+   evas_data_attach_set(ee->evas, ee);
+   evas_output_method_set(ee->evas, rmethod);
+   evas_output_size_set(ee->evas, w, h);
+   evas_output_viewport_set(ee->evas, 0, 0, w, h);
+
+   tbm_data->tbm_queue = tbm_data->alloc_func(tbm_data->data, w, h);
+
+   if (!strcmp(driver_name, "gl_tbm"))
+      {
+         Evas_Engine_Info_GL_Tbm *einfo = (Evas_Engine_Info_GL_Tbm *)evas_engine_info_get(ee->evas);
+         if (einfo)
+           {
+              einfo->info.tbm_queue = tbm_data->tbm_queue;
+              einfo->info.destination_alpha = EINA_TRUE;
+              einfo->info.ext_tbm_queue = EINA_FALSE;
+              einfo->info.rotation = 0;
+              einfo->info.depth = 32;
+              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                {
+                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                   ecore_evas_free(ee);
+                   return NULL;
+                }
+           }
+         else
+           {
+              ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+              ecore_evas_free(ee);
+              return NULL;
+           }
+      }
+   else if (!strcmp(driver_name, "software_tbm"))
+      {
+         Evas_Engine_Info_Software_Tbm *einfo = (Evas_Engine_Info_Software_Tbm *)evas_engine_info_get(ee->evas);
+         if (einfo)
+           {
+              einfo->info.tbm_queue = tbm_data->tbm_queue;
+              einfo->info.destination_alpha = EINA_TRUE;
+              einfo->info.ext_tbm_queue = EINA_FALSE;
+              einfo->info.rotation = 0;
+              einfo->info.depth = 32;
+              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+                {
+                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
+                   ecore_evas_free(ee);
+                   return NULL;
+                }
+           }
+         else
+           {
+              ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
+              ecore_evas_free(ee);
+              return NULL;
+           }
+      }
+
+   evas_key_modifier_add(ee->evas, "Shift");
+   evas_key_modifier_add(ee->evas, "Control");
+   evas_key_modifier_add(ee->evas, "Alt");
+   evas_key_modifier_add(ee->evas, "Meta");
+   evas_key_modifier_add(ee->evas, "Hyper");
+   evas_key_modifier_add(ee->evas, "Super");
+   evas_key_lock_add(ee->evas, "Caps_Lock");
+   evas_key_lock_add(ee->evas, "Num_Lock");
+   evas_key_lock_add(ee->evas, "Scroll_Lock");
+
+   evas_event_feed_mouse_in(ee->evas, 0, NULL);
+
+   _ecore_evas_register(ee);
+
+   evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+
+   return ee;
+
+}
+
+EAPI Ecore_Evas *
+ecore_evas_gl_tbm_new(int w, int h)
+{
+    return ecore_evas_tbm_allocfunc_new
+     ("gl_tbm", w, h,_ecore_evas_tbm_queue_alloc, _ecore_evas_tbm_queue_free, NULL);
+}
+
+EAPI Ecore_Evas *
+ecore_evas_software_tbm_new(int w, int h)
+{
+    return ecore_evas_tbm_allocfunc_new
+     ("software_tbm", w, h,_ecore_evas_tbm_queue_alloc, _ecore_evas_tbm_queue_free, NULL);
+}
+
+EAPI Ecore_Evas *
+ecore_evas_tbm_ecore_evas_parent_get(Ecore_Evas *ee)
+{
+   Ecore_Evas_Engine_Tbm_Data *tbm_data;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL);
+
+   tbm_data = ee->engine.data;
+   return evas_object_data_get(tbm_data->image, "Ecore_Evas_Parent");
+}
+
+EAPI const void *
+ecore_evas_tbm_pixels_acquire(Ecore_Evas *ee)
+{
+   Ecore_Evas_Engine_Tbm_Data *tbm_data;
+   tbm_surface_info_s surf_info;
+   void *pixels=NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL);
+
+   tbm_data = ee->engine.data;
+   if (tbm_surface_queue_can_acquire(tbm_data->tbm_queue, 1)) {
+      tbm_surface_queue_acquire(tbm_data->tbm_queue, &(tbm_data->tbm_surf));
+      tbm_surface_get_info(tbm_data->tbm_surf,&surf_info);
+      pixels = surf_info.planes[0].ptr;
+   }
+   ee->engine.data = tbm_data;
+   return pixels;
+}
+
+EAPI void
+ecore_evas_tbm_pixels_release(Ecore_Evas *ee)
+{
+   Ecore_Evas_Engine_Tbm_Data *tbm_data;
+   tbm_surface_info_s surf_info;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL);
+
+   tbm_data = ee->engine.data;
+   if (tbm_data->tbm_surf) {
+      tbm_surface_queue_release(tbm_data->tbm_queue,tbm_data->tbm_surf);
+      tbm_data->tbm_surf= NULL;
+   }
+   tbm_data = ee->engine.data;
+}
+
diff --git a/src/lib/ecore_evas/ecore_evas_tbm.h b/src/lib/ecore_evas/ecore_evas_tbm.h
new file mode 100755 (executable)
index 0000000..7def861
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef ECORE_EVAS_TBM_H
+#define ECORE_EVAS_TBM_H
+
+typedef struct _Ecore_Evas_Engine_Tbm_Data Ecore_Evas_Engine_Tbm_Data;
+
+struct _Ecore_Evas_Engine_Tbm_Data {
+   void* tbm_queue;
+   tbm_surface_h tbm_surf;
+   Eina_Bool ext_tbm_queue;
+   void  (*free_func) (void *data, void *tbm_queue);
+   void *(*alloc_func) (void *data, int w, int h);
+   Evas_Object *image;
+   void *data;
+};
+
+
+#endif // ECORE_EVAS_TBM_H
old mode 100644 (file)
new mode 100755 (executable)
index 7ca60df..338b7d4
@@ -130,7 +130,6 @@ ecore_evas_wayland_egl_options_new_internal(const char *disp_name, unsigned int
    int fx = 0, fy = 0, fw = 0, fh = 0;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
    if (!(method = evas_render_method_lookup("wayland_egl")))
      {
         ERR("Render method lookup failed for Wayland_Egl");
diff --git a/src/modules/evas/engines/gl_tbm/Evas_Engine_GL_Tbm.h b/src/modules/evas/engines/gl_tbm/Evas_Engine_GL_Tbm.h
new file mode 100755 (executable)
index 0000000..34f4f92
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _EVAS_ENGINE_GL_TBM_H
+# define _EVAS_ENGINE_GL_TBM_H
+
+# define EVAS_ENGINE_GL_TBM_SWAP_MODE_EXISTS 1
+
+typedef struct _Evas_Engine_Info_GL_Tbm Evas_Engine_Info_GL_Tbm;
+
+typedef enum _Evas_Engine_Info_GL_Tbm_Swap_Mode
+{
+   EVAS_ENGINE_GL_TBM_SWAP_MODE_AUTO = 0,
+   EVAS_ENGINE_GL_TBM_SWAP_MODE_FULL = 1,
+   EVAS_ENGINE_GL_TBM_SWAP_MODE_COPY = 2,
+   EVAS_ENGINE_GL_TBM_SWAP_MODE_DOUBLE = 3,
+   EVAS_ENGINE_GL_TBM_SWAP_MODE_TRIPLE = 4,
+   EVAS_ENGINE_GL_TBM_SWAP_MODE_QUADRUPLE = 5
+} Evas_Engine_Info_GL_Tbm_Swap_Mode;
+
+struct _Evas_Engine_Info_GL_Tbm
+{
+   /* PRIVATE - don't mess with this baby or evas will poke its tongue out
+    * at you and make nasty noises */
+   Evas_Engine_Info magic;
+
+   /* engine specific data & parameters it needs to set up */
+   struct
+     {
+        int depth, screen, rotation, edges;
+        void *tbm_queue;
+        Eina_Bool ext_tbm_queue;
+        unsigned int destination_alpha : 1;
+     } info;
+
+   struct
+     {
+        void (*pre_swap) (void *data, Evas *evas);
+        void (*post_swap) (void *data, Evas *evas);
+        void *data;
+     } callback;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
+
+   Eina_Bool vsync : 1;
+   Eina_Bool indirect : 1;
+   unsigned char swap_mode : 4;
+
+   /* window surface should be made with these config */
+   int           depth_bits;
+   int           stencil_bits;
+   int           msaa_bits;
+};
+
+#endif
diff --git a/src/modules/evas/engines/gl_tbm/evas_engine.c b/src/modules/evas/engines/gl_tbm/evas_engine.c
new file mode 100755 (executable)
index 0000000..7a2e176
--- /dev/null
@@ -0,0 +1,1837 @@
+#include "evas_common_private.h"
+#include "evas_engine.h"
+#include "../gl_common/evas_gl_define.h"
+#include "../software_generic/evas_native_common.h"
+
+#ifdef HAVE_DLSYM
+# include <dlfcn.h>
+#endif
+
+#ifdef EVAS_CSERVE2
+# include "evas_cs2_private.h"
+#endif
+
+#define EVAS_GL_NO_GL_H_CHECK 1
+#include "Evas_GL.h"
+
+#define EVAS_GL_UPDATE_TILE_SIZE 16
+
+#ifndef EGL_NATIVE_PIXMAP_KHR
+# define EGL_NATIVE_PIXMAP_KHR 0x30b0
+#endif
+
+#ifndef EGL_Y_INVERTED_NOK
+# define EGL_Y_INVERTED_NOK 0x307F
+#endif
+
+/* local structures */
+typedef struct _Render_Engine Render_Engine;
+struct _Render_Engine
+{
+   Render_Engine_GL_Generic generic;
+};
+
+/* local function prototypes */
+typedef void (*_eng_fn) (void);
+typedef _eng_fn (*glsym_func_eng_fn) ();
+typedef void (*glsym_func_void) ();
+typedef void *(*glsym_func_void_ptr) ();
+typedef int (*glsym_func_int) ();
+typedef unsigned int (*glsym_func_uint) ();
+typedef const char *(*glsym_func_const_char_ptr) ();
+
+Evas_GL_Common_Image_Call glsym_evas_gl_common_image_ref = NULL;
+Evas_GL_Common_Image_Call glsym_evas_gl_common_image_unref = NULL;
+Evas_GL_Common_Image_Call glsym_evas_gl_common_image_free = NULL;
+Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_disable = NULL;
+Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_enable = NULL;
+Evas_GL_Common_Image_New_From_Data glsym_evas_gl_common_image_new_from_data = NULL;
+Evas_GL_Common_Context_Call glsym_evas_gl_common_image_all_unload = NULL;
+Evas_GL_Preload glsym_evas_gl_preload_init = NULL;
+Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL;
+EVGL_Engine_Call glsym_evgl_engine_shutdown = NULL;
+EVGL_Native_Surface_Call glsym_evgl_native_surface_buffer_get = NULL;
+EVGL_Native_Surface_Yinvert_Call glsym_evgl_native_surface_yinvert_get = NULL;
+Evas_Gl_Symbols glsym_evas_gl_symbols = NULL;
+
+Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL;
+Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush = NULL;
+Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free = NULL;
+Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use = NULL;
+Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe = NULL;
+Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done = NULL;
+Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize = NULL;
+Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump = NULL;
+Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL;
+Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL;
+Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL;
+
+glsym_func_void     glsym_evas_gl_common_error_set = NULL;
+glsym_func_int      glsym_evas_gl_common_error_get = NULL;
+glsym_func_void_ptr glsym_evas_gl_common_current_context_get = NULL;
+void (*glsym_evas_gl_context_restore_set) (Eina_Bool enable) = NULL;
+
+_eng_fn (*glsym_eglGetProcAddress) (const char *a) = NULL;
+void *(*glsym_eglCreateImage) (EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL;
+void (*glsym_eglDestroyImage) (EGLDisplay a, void *b) = NULL;
+void (*glsym_glEGLImageTargetTexture2DOES) (int a, void *b)  = NULL;
+unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL;
+unsigned int (*glsym_eglSetDamageRegionKHR) (EGLDisplay a, EGLSurface b, EGLint *c, EGLint d) = NULL;
+unsigned int (*glsym_eglQueryWaylandBufferWL)(EGLDisplay a, struct wl_resource *b, EGLint c, EGLint *d) = NULL;
+
+/* local variables */
+static Eina_Bool initted = EINA_FALSE;
+static int gl_wins = 0;
+static Evas_Func func, pfunc;
+
+/* external variables */
+int _evas_engine_gl_tbm_log_dom = -1;
+Eina_Bool extn_have_buffer_age = EINA_TRUE;
+Eina_Bool extn_have_y_inverted = EINA_TRUE;
+
+/* local functions */
+static inline Outbuf *
+eng_get_ob(Render_Engine *re)
+{
+   return re->generic.software.ob;
+}
+
+static void
+gl_symbols(void)
+{
+   static Eina_Bool done = EINA_FALSE;
+
+   if (done) return;
+
+   /* FIXME: Remove this line as soon as eglGetDisplay() autodetection
+    * gets fixed. Currently it is incorrectly detecting wl_display and
+    * returning _EGL_PLATFORM_X11 instead of _EGL_PLATFORM_WAYLAND.
+    *
+    * See ticket #1972 for more info.
+    */
+   //setenv("EGL_PLATFORM", "tbm", 1);
+
+#define LINK2GENERIC(sym) \
+   glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
+
+   // Get function pointer to evas_gl_common now provided through GL_Generic.
+   LINK2GENERIC(evas_gl_common_image_all_unload);
+   LINK2GENERIC(evas_gl_common_image_ref);
+   LINK2GENERIC(evas_gl_common_image_unref);
+   LINK2GENERIC(evas_gl_common_image_new_from_data);
+   LINK2GENERIC(evas_gl_common_image_native_disable);
+   LINK2GENERIC(evas_gl_common_image_free);
+   LINK2GENERIC(evas_gl_common_image_native_enable);
+   LINK2GENERIC(evas_gl_common_context_new);
+   LINK2GENERIC(evas_gl_common_context_flush);
+   LINK2GENERIC(evas_gl_common_context_free);
+   LINK2GENERIC(evas_gl_common_context_use);
+   LINK2GENERIC(evas_gl_common_context_newframe);
+   LINK2GENERIC(evas_gl_common_context_done);
+   LINK2GENERIC(evas_gl_common_context_resize);
+   LINK2GENERIC(evas_gl_common_buffer_dump);
+   LINK2GENERIC(evas_gl_preload_render_lock);
+   LINK2GENERIC(evas_gl_preload_render_unlock);
+   LINK2GENERIC(evas_gl_preload_render_relax);
+   LINK2GENERIC(evas_gl_preload_init);
+   LINK2GENERIC(evas_gl_preload_shutdown);
+   LINK2GENERIC(evgl_native_surface_buffer_get);
+   LINK2GENERIC(evgl_native_surface_yinvert_get);
+   LINK2GENERIC(evgl_engine_shutdown);
+   LINK2GENERIC(evas_gl_symbols);
+   LINK2GENERIC(evas_gl_common_error_get);
+   LINK2GENERIC(evas_gl_common_error_set);
+   LINK2GENERIC(evas_gl_common_current_context_get);
+   LINK2GENERIC(evas_gl_context_restore_set);
+
+#define FINDSYM(dst, sym, typ) \
+   if (glsym_eglGetProcAddress) { \
+      if (!dst) dst = (typ)glsym_eglGetProcAddress(sym); \
+   } else { \
+      if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym); \
+   }
+
+   FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressKHR", glsym_func_eng_fn);
+   FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressEXT", glsym_func_eng_fn);
+   FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressARB", glsym_func_eng_fn);
+   FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddress", glsym_func_eng_fn);
+
+   glsym_evas_gl_symbols((void*)glsym_eglGetProcAddress);
+
+   FINDSYM(glsym_eglCreateImage, "eglCreateImageKHR", glsym_func_void_ptr);
+   FINDSYM(glsym_eglCreateImage, "eglCreateImageEXT", glsym_func_void_ptr);
+   FINDSYM(glsym_eglCreateImage, "eglCreateImageARB", glsym_func_void_ptr);
+   FINDSYM(glsym_eglCreateImage, "eglCreateImage", glsym_func_void_ptr);
+
+   FINDSYM(glsym_eglDestroyImage, "eglDestroyImageKHR", glsym_func_void);
+   FINDSYM(glsym_eglDestroyImage, "eglDestroyImageEXT", glsym_func_void);
+   FINDSYM(glsym_eglDestroyImage, "eglDestroyImageARB", glsym_func_void);
+   FINDSYM(glsym_eglDestroyImage, "eglDestroyImage", glsym_func_void);
+
+   FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES",
+           glsym_func_void);
+
+   FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageEXT",
+           glsym_func_uint);
+   FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageINTEL",
+           glsym_func_uint);
+   FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage",
+           glsym_func_uint);
+   FINDSYM(glsym_eglSetDamageRegionKHR, "eglSetDamageRegionKHR",
+           glsym_func_uint);
+
+   FINDSYM(glsym_eglQueryWaylandBufferWL, "eglQueryWaylandBufferWL",
+           glsym_func_uint);
+
+   done = EINA_TRUE;
+}
+
+static void
+gl_extn_veto(Render_Engine *re)
+{
+   const char *str = NULL;
+
+   str = eglQueryString(eng_get_ob(re)->egl_disp, EGL_EXTENSIONS);
+   if (str)
+     {
+        const char *s;
+        if (getenv("EVAS_GL_INFO"))
+          printf("EGL EXTN:\n%s\n", str);
+        // Disable Partial Rendering
+        if ((s = getenv("EVAS_GL_PARTIAL_DISABLE")) && atoi(s))
+          {
+             extn_have_buffer_age = EINA_FALSE;
+             glsym_eglSwapBuffersWithDamage = NULL;
+             glsym_eglSetDamageRegionKHR = NULL;
+          }
+        if (!strstr(str, "EGL_EXT_buffer_age"))
+          {
+             if (!strstr(str, "EGL_KHR_partial_update"))
+               extn_have_buffer_age = EINA_FALSE;
+          }
+        if (!strstr(str, "EGL_KHR_partial_update"))
+          {
+             glsym_eglSetDamageRegionKHR = NULL;
+          }
+        if (!strstr(str, "EGL_NOK_texture_from_pixmap"))
+          {
+             extn_have_y_inverted = EINA_FALSE;
+          }
+        else
+          {
+             const GLubyte *vendor, *renderer;
+
+             vendor = glGetString(GL_VENDOR);
+             renderer = glGetString(GL_RENDERER);
+             // XXX: workaround mesa bug!
+             // looking for mesa and intel build which is known to
+             // advertise the EGL_NOK_texture_from_pixmap extension
+             // but not set it correctly. guessing vendor/renderer
+             // strings will be like the following:
+             // OpenGL vendor string: Intel Open Source Technology Center
+             // OpenGL renderer string: Mesa DRI Intel(R) Sandybridge Desktop
+             if (((vendor) && (strstr((const char *)vendor, "Intel"))) &&
+                 ((renderer) && (strstr((const char *)renderer, "Mesa"))) &&
+                 ((renderer) && (strstr((const char *)renderer, "Intel")))
+                )
+               extn_have_y_inverted = EINA_FALSE;
+          }
+        if (!strstr(str, "EGL_EXT_swap_buffers_with_damage"))
+          {
+             glsym_eglSwapBuffersWithDamage = NULL;
+          }
+     }
+   else
+     {
+        if (getenv("EVAS_GL_INFO"))
+          printf("NO EGL EXTN!\n");
+        extn_have_buffer_age = EINA_FALSE;
+     }
+}
+
+static void
+_re_winfree(Render_Engine *re)
+{
+   Outbuf *ob;
+
+   if (!(ob = eng_get_ob(re))) return;
+   if (!ob->surf) return;
+   glsym_evas_gl_preload_render_relax(eng_preload_make_current, ob);
+   eng_window_unsurf(ob);
+}
+
+static void *
+evgl_eng_display_get(void *data)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+
+   if (!(re = (Render_Engine *)data)) return NULL;
+   if (!(ob = eng_get_ob(re))) return NULL;
+   return (void *)ob->egl_disp;
+#else
+   return NULL;
+#endif
+}
+
+static void *
+evgl_eng_evas_surface_get(void *data)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+
+   if (!(re = (Render_Engine *)data)) return NULL;
+   if (!(ob = eng_get_ob(re))) return NULL;
+   return (void *)ob->egl_surface[0];
+#else
+   return NULL;
+#endif
+}
+
+static void *
+evgl_eng_native_window_create(void *data)
+{
+#if 0
+   Evgl_wl_Surface* surface;
+   Render_Engine *re;
+   Outbuf *ob;
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return NULL;
+     }
+   if (!(ob = eng_get_ob(re))) return NULL;
+
+   if (!(surface = calloc(1, sizeof(Evgl_wl_Surface))))
+     return NULL;
+   surface->wl_surf = wl_compositor_create_surface(ob->compositor);
+   if (!surface->wl_surf)
+     {
+        ERR("Could not create wl_surface: %m");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_DISPLAY);
+        return NULL;
+     }
+   surface->egl_win = wl_egl_window_create(surface->wl_surf, 1, 1);
+   if (!surface->egl_win)
+     {
+        ERR("Could not create wl_egl window: %m");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_DISPLAY);
+        return NULL;
+     }
+
+   return (void *)surface;
+#else
+   return NULL;
+#endif
+}
+
+static int
+evgl_eng_native_window_destroy(void *data, void *win)
+{
+#if 0
+   Evgl_wl_Surface* surface;
+
+   if (!win)
+     {
+        ERR("Inavlid native window.");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_NATIVE_WINDOW);
+        return 0;
+     }
+
+   surface = (Evgl_wl_Surface*)win;
+   if (surface->egl_win)
+     wl_egl_window_destroy((struct wl_egl_window *)surface->egl_win);
+   if (surface->wl_surf)
+      wl_surface_destroy(surface->wl_surf);
+
+   free(surface);
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+static void *
+evgl_eng_window_surface_create(void *data, void *win)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+   EGLSurface surface = EGL_NO_SURFACE;
+   Evgl_wl_Surface* evgl_surface;
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return NULL;
+     }
+   if (!(ob = eng_get_ob(re))) return NULL;
+   if (!(evgl_surface = (Evgl_wl_Surface *)win)) return NULL;
+   if (!(evgl_surface->egl_win)) return NULL;
+
+   surface = eglCreateWindowSurface(ob->egl_disp, ob->egl_config,
+                                    (EGLNativeWindowType)evgl_surface->egl_win, NULL);
+   if (!surface)
+     {
+        ERR("Could not create egl window surface: %#x", eglGetError());
+        return NULL;
+     }
+
+   return (void *)surface;
+#else
+   return NULL;
+#endif
+}
+
+static int
+evgl_eng_window_surface_destroy(void *data, void *surface)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return 0;
+     }
+   if (!(ob = eng_get_ob(re))) return 0;
+
+   if (!surface)
+     {
+        ERR("Invalid surface.");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_SURFACE);
+        return 0;
+     }
+   eglDestroySurface(ob->egl_disp, (EGLSurface)surface);
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+static void *
+evgl_eng_context_create(void *data, void *ctxt, Evas_GL_Context_Version version)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+   EGLContext context = EGL_NO_CONTEXT;
+   int attrs[3];
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return NULL;
+     }
+
+   if (!(ob = eng_get_ob(re))) return NULL;
+
+   if ((version < EVAS_GL_GLES_1_X) || (version > EVAS_GL_GLES_3_X))
+     {
+        ERR("Invalid context version number %d", version);
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_PARAMETER);
+        return NULL;
+     }
+
+   if ((version == EVAS_GL_GLES_3_X) &&
+       ((!ob->gl_context) || (ob->gl_context->gles_version != EVAS_GL_GLES_3_X)))
+     {
+        EGLint num_config=0;
+        EGLint version_config_attrs[3];
+        version_config_attrs[0] = EGL_RENDERABLE_TYPE;
+        version_config_attrs[1] = EGL_OPENGL_ES3_BIT;
+        version_config_attrs[2] = EGL_NONE;
+
+        if ((!eglChooseConfig(ob->egl_disp, version_config_attrs, NULL, 0, &num_config))
+           || (num_config < 1))
+          {
+             ERR("GLES 3 version not supported!");
+             glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_ATTRIBUTE);
+             return NULL;
+          }
+        else if (ob->gl_context)
+          {
+             ob->gl_context->gles_version = EVAS_GL_GLES_3_X;
+          }
+        else
+          {
+             ERR("Evas GL Context not initialised!");
+             glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+             return NULL;
+          }
+     }
+
+   attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
+   attrs[1] = version;
+   attrs[2] = EGL_NONE;
+
+   if (ctxt)
+     {
+        context =
+          eglCreateContext(ob->egl_disp, ob->egl_config,
+                           (EGLContext)ctxt, attrs);
+     }
+
+   else if (version == EVAS_GL_GLES_1_X || version == EVAS_GL_GLES_3_X)
+     {
+        context =
+          eglCreateContext(ob->egl_disp, ob->egl_config,
+                           NULL, attrs);
+     }
+   else
+     {
+        context =
+          eglCreateContext(ob->egl_disp, ob->egl_config,
+                           ob->egl_context[0], attrs);
+     }
+
+   if (!context)
+     {
+        int err = eglGetError();
+        ERR("Failed to create egl context: %#x", err);
+        glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
+        return NULL;
+     }
+
+   return (void *)context;
+#else
+   return NULL;
+#endif
+}
+
+static int
+evgl_eng_context_destroy(void *data, void *ctxt)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Input Data. Engine: %p", data);
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return 0;
+     }
+   if (!(ob = eng_get_ob(re))) return 0;
+   if (!ctxt)
+     {
+        ERR("Invalid Render Input Data. Context: %p", ctxt);
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_CONTEXT);
+        return 0;
+     }
+
+   eglDestroyContext(ob->egl_disp, (EGLContext)ctxt);
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+static int
+evgl_eng_make_current(void *data, void *surface, void *ctxt, int flush)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+   EGLContext ctx;
+   EGLSurface surf;
+   int ret = 0;
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return 0;
+     }
+   if (!(ob = eng_get_ob(re))) return 0;
+
+   ctx = (EGLContext)ctxt;
+   surf = (EGLSurface)surface;
+
+   if ((!ctxt) && (!surface))
+     {
+        ret =
+          eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE,
+                         EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        if (!ret)
+          {
+             int err = eglGetError();
+             glsym_evas_gl_common_error_set(err - EGL_SUCCESS);
+             ERR("eglMakeCurrent() failed! Error Code=%#x", err);
+             return 0;
+          }
+        return 1;
+     }
+
+   if ((eglGetCurrentContext() != ctx) ||
+       (eglGetCurrentSurface(EGL_READ) != surf) ||
+       (eglGetCurrentSurface(EGL_DRAW) != surf))
+     {
+        if (flush) eng_window_use(NULL);
+
+        ret = eglMakeCurrent(ob->egl_disp, surf, surf, ctx);
+        if (!ret)
+          {
+             int err = eglGetError();
+             glsym_evas_gl_common_error_set(err - EGL_SUCCESS);
+             ERR("eglMakeCurrent() failed! Error Code=%#x", err);
+             return 0;
+          }
+     }
+
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+static void *
+evgl_eng_proc_address_get(const char *name)
+{
+#if 0
+   if (glsym_eglGetProcAddress) return glsym_eglGetProcAddress(name);
+   return dlsym(RTLD_DEFAULT, name);
+#else
+   return NULL;
+#endif
+}
+
+static const char *
+evgl_eng_string_get(void *data)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return NULL;
+     }
+   if (!(ob = eng_get_ob(re))) return NULL;
+
+   return eglQueryString(ob->egl_disp, EGL_EXTENSIONS);
+#else
+   return NULL;
+#endif
+}
+
+static int
+evgl_eng_rotation_angle_get(void *data)
+{
+#if 0
+   Render_Engine *re;
+   Outbuf *ob;
+
+   if (!(re = (Render_Engine *)data))
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_NOT_INITIALIZED);
+        return 0;
+     }
+   if (!(ob = eng_get_ob(re))) return 0;
+
+   if (ob->gl_context)
+     return ob->gl_context->rot;
+   else
+     {
+        ERR("Unable to retrieve rotation angle.");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_CONTEXT);
+        return 0;
+     }
+#else
+   return 0;
+#endif
+}
+
+static void *
+evgl_eng_pbuffer_surface_create(void *data, EVGL_Surface *sfc,
+                                const int *attrib_list)
+{
+#if 0
+   Render_Engine_GL_Generic *re = data;
+
+   // TODO: Add support for surfaceless pbuffers (EGL_NO_TEXTURE)
+   // TODO: Add support for EGL_MIPMAP_TEXTURE??? (GLX doesn't support them)
+
+   if (attrib_list)
+     WRN("This PBuffer implementation does not support extra attributes yet");
+
+#ifdef GL_GLES
+   Evas_Engine_GL_Context *evasglctx;
+   int config_attrs[20];
+   int surface_attrs[20];
+   EGLSurface egl_sfc;
+   EGLConfig egl_cfg;
+   int num_config, i = 0;
+   EGLDisplay disp;
+   EGLContext ctx;
+
+   disp = re->window_egl_display_get(re->software.ob);
+   evasglctx = re->window_gl_context_get(re->software.ob);
+   ctx = evasglctx->eglctxt;
+
+   // It looks like eglMakeCurrent might fail if we use a different config from
+   // the actual display surface. This is weird.
+   i = 0;
+   config_attrs[i++] = EGL_CONFIG_ID;
+   config_attrs[i++] = 0;
+   config_attrs[i++] = EGL_NONE;
+   eglQueryContext(disp, ctx, EGL_CONFIG_ID, &config_attrs[1]);
+
+   if (!eglChooseConfig(disp, config_attrs, &egl_cfg, 1, &num_config)
+       || (num_config < 1))
+     {
+        int err = eglGetError();
+        glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
+        ERR("eglChooseConfig failed with error %x", err);
+        return NULL;
+     }
+
+   // Now, choose the config for the PBuffer
+   i = 0;
+   surface_attrs[i++] = EGL_WIDTH;
+   surface_attrs[i++] = sfc->w;
+   surface_attrs[i++] = EGL_HEIGHT;
+   surface_attrs[i++] = sfc->h;
+
+   surface_attrs[i++] = EGL_NONE;
+
+   egl_sfc = eglCreatePbufferSurface(disp, egl_cfg, surface_attrs);
+   if (!egl_sfc)
+     {
+        int err = eglGetError();
+        glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
+        ERR("eglCreatePbufferSurface failed with error %x", err);
+        return NULL;
+     }
+
+   return egl_sfc;
+#else
+   GLXPbuffer pbuf;
+   GLXFBConfig *cfgs;
+   int config_attrs[20];
+   int surface_attrs[20];
+   int ncfg = 0, i;
+
+   // TODO: Check all required config attributes
+   // TODO: Should be tested when EFL runs with wayland on Desktop
+
+#ifndef GLX_VISUAL_ID
+# define GLX_VISUAL_ID 0x800b
+#endif
+
+   i = 0;
+   if (sfc->pbuffer.color_fmt != EVAS_GL_NO_FBO)
+     {
+        config_attrs[i++] = GLX_BUFFER_SIZE;
+        if (sfc->pbuffer.color_fmt == EVAS_GL_RGBA_8888)
+          {
+             config_attrs[i++] = 32;
+             //config_attrs[i++] = GLX_BIND_TO_TEXTURE_RGBA_EXT;
+             //config_attrs[i++] = 1;
+          }
+        else
+          {
+             config_attrs[i++] = 24;
+             //config_attrs[i++] = GLX_BIND_TO_TEXTURE_RGB_EXT;
+             //config_attrs[i++] = 1;
+          }
+     }
+   if (sfc->depth_fmt)
+     {
+        config_attrs[i++] = GLX_DEPTH_SIZE;
+        config_attrs[i++] = 24; // FIXME: This should depend on the requested bits
+     }
+   if (sfc->stencil_fmt)
+     {
+        config_attrs[i++] = GLX_STENCIL_SIZE;
+        config_attrs[i++] = 8; // FIXME: This should depend on the requested bits
+     }
+   //config_attrs[i++] = GLX_VISUAL_ID;
+   //config_attrs[i++] = XVisualIDFromVisual(vis);
+   config_attrs[i++] = 0;
+
+   cfgs = glXChooseFBConfig(re->software.ob->disp, re->software.ob->screen,
+                            config_attrs, &ncfg);
+   if (!cfgs || !ncfg)
+     {
+        ERR("GLX failed to find a valid config for the pbuffer");
+        if (cfgs) XFree(cfgs);
+        return NULL;
+     }
+
+   i = 0;
+   surface_attrs[i++] = GLX_LARGEST_PBUFFER;
+   surface_attrs[i++] = 0;
+   surface_attrs[i++] = GLX_PBUFFER_WIDTH;
+   surface_attrs[i++] = sfc->w;
+   surface_attrs[i++] = GLX_PBUFFER_HEIGHT;
+   surface_attrs[i++] = sfc->h;
+   surface_attrs[i++] = 0;
+   pbuf = glXCreatePbuffer(re->software.ob->disp, cfgs[0], surface_attrs);
+   if (cfgs) XFree(cfgs);
+
+   if (!pbuf)
+     {
+        ERR("GLX failed to create a pbuffer");
+        return NULL;
+     }
+
+   return (void*)(intptr_t)pbuf;
+#endif
+#else
+   return NULL;
+#endif
+}
+
+static int
+evgl_eng_pbuffer_surface_destroy(void *data, void *surface)
+{
+#if 0
+   /* EVGLINIT(re, 0); */
+   if (!data)
+     {
+        ERR("Invalid Render Engine Data!");
+        glsym_evas_gl_common_error_set(NULL, EVAS_GL_NOT_INITIALIZED);
+        return 0;
+     }
+
+   if (!surface)
+     {
+        ERR("Invalid surface.");
+        glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_SURFACE);
+        return 0;
+     }
+
+#ifdef GL_GLES
+   Render_Engine *re = data;
+
+   eglDestroySurface(eng_get_ob(re)->egl_disp, (EGLSurface)surface);
+#else
+   // TODO: Should be tested when EFL runs with wayland on Desktop
+   Render_Engine_GL_Generic *re = data;
+   GLXPbuffer pbuf = (GLXPbuffer)(intptr_t) surface;
+
+   glXDestroyPbuffer(re->software.ob->disp, pbuf);
+#endif
+
+   return 1;
+#else
+   return 0;
+#endif
+}
+
+static void
+evgl_eng_native_win_surface_config_get(void *data, int *win_depth,
+                                         int *win_stencil, int *win_msaa)
+{
+#if 0
+   Render_Engine *re = data;
+   if (!re) return;
+
+   if (win_depth)
+     *win_depth = eng_get_ob(re)->detected.depth_buffer_size;
+   if (win_stencil)
+     *win_stencil = eng_get_ob(re)->detected.stencil_buffer_size;
+   if (win_msaa)
+     *win_msaa = eng_get_ob(re)->detected.msaa;
+
+   DBG("Window config(depth %d, stencil %d, msaa %d)",
+       eng_get_ob(re)->detected.depth_buffer_size,
+       eng_get_ob(re)->detected.stencil_buffer_size,
+       eng_get_ob(re)->detected.msaa);
+#endif
+}
+
+static const EVGL_Interface evgl_funcs =
+{
+   evgl_eng_display_get,
+   evgl_eng_evas_surface_get,
+   evgl_eng_native_window_create,
+   evgl_eng_native_window_destroy,
+   evgl_eng_window_surface_create,
+   evgl_eng_window_surface_destroy,
+   evgl_eng_context_create,
+   evgl_eng_context_destroy,
+   evgl_eng_make_current,
+   evgl_eng_proc_address_get,
+   evgl_eng_string_get,
+   evgl_eng_rotation_angle_get,
+   evgl_eng_pbuffer_surface_create,
+   evgl_eng_pbuffer_surface_destroy,
+   NULL, // OpenGL-ES 1
+   NULL, // OpenGL-ES 1
+   NULL, // OpenGL-ES 1
+   evgl_eng_native_win_surface_config_get,
+};
+
+/* engine functions */
+static void *
+eng_info(Evas *evas EINA_UNUSED)
+{
+   Evas_Engine_Info_GL_Tbm *info;
+
+   /* try to allocate space for our engine info */
+   if (!(info = calloc(1, sizeof(Evas_Engine_Info_GL_Tbm))))
+     return NULL;
+
+   info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
+
+   return info;
+}
+
+static void
+eng_info_free(Evas *evas EINA_UNUSED, void *info)
+{
+   Evas_Engine_Info_GL_Tbm *inf;
+
+   if ((inf = (Evas_Engine_Info_GL_Tbm *)info))
+     free(inf);
+}
+
+static int
+eng_setup(Evas *evas, void *info)
+{
+   Render_Engine_Swap_Mode swap_mode = MODE_FULL;
+   Evas_Engine_Info_GL_Tbm *inf;
+   Evas_Public_Data *epd;
+   Render_Engine *re;
+   Outbuf *ob;
+   const char *s;
+   inf = (Evas_Engine_Info_GL_Tbm *)info;
+   epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS);
+
+   if ((s = getenv("EVAS_GL_SWAP_MODE")))
+     {
+        if ((!strcasecmp(s, "full")) ||
+            (!strcasecmp(s, "f")))
+          swap_mode = MODE_FULL;
+        else if ((!strcasecmp(s, "copy")) ||
+                 (!strcasecmp(s, "c")))
+          swap_mode = MODE_COPY;
+        else if ((!strcasecmp(s, "double")) ||
+                 (!strcasecmp(s, "d")) ||
+                 (!strcasecmp(s, "2")))
+          swap_mode = MODE_DOUBLE;
+        else if ((!strcasecmp(s, "triple")) ||
+                 (!strcasecmp(s, "t")) ||
+                 (!strcasecmp(s, "3")))
+          swap_mode = MODE_TRIPLE;
+        else if ((!strcasecmp(s, "quadruple")) ||
+                 (!strcasecmp(s, "q")) ||
+                 (!strcasecmp(s, "4")))
+          swap_mode = MODE_QUADRUPLE;
+     }
+   else
+     {
+// in most gl implementations - egl and glx here that we care about the TEND
+// to either swap or copy backbuffer and front buffer, but strictly that is
+// not true. technically backbuffer content is totally undefined after a swap
+// and thus you MUST re-render all of it, thus MODE_FULL
+        swap_mode = MODE_FULL;
+// BUT... reality is that lmost every implementation copies or swaps so
+// triple buffer mode can be used as it is a superset of double buffer and
+// copy (though using those explicitly is more efficient). so let's play with
+// triple buffer mdoe as a default and see.
+//        re->mode = MODE_TRIPLE;
+// XXX: note - the above seems to break on some older intel chipsets and
+// drivers. it seems we CANT depend on backbuffer staying around. bugger!
+        switch (inf->swap_mode)
+          {
+           case EVAS_ENGINE_GL_TBM_SWAP_MODE_FULL:
+             swap_mode = MODE_FULL;
+             break;
+           case EVAS_ENGINE_GL_TBM_SWAP_MODE_COPY:
+             swap_mode = MODE_COPY;
+             break;
+           case EVAS_ENGINE_GL_TBM_SWAP_MODE_DOUBLE:
+             swap_mode = MODE_DOUBLE;
+             break;
+           case EVAS_ENGINE_GL_TBM_SWAP_MODE_TRIPLE:
+             swap_mode = MODE_TRIPLE;
+             break;
+           case EVAS_ENGINE_GL_TBM_SWAP_MODE_QUADRUPLE:
+             swap_mode = MODE_QUADRUPLE;
+             break;
+           default:
+             swap_mode = MODE_AUTO;
+             break;
+          }
+     }
+
+   if (!(re = epd->engine.data.output))
+     {
+        Render_Engine_Merge_Mode merge = MERGE_SMART;
+
+        /* FIXME: Remove this line as soon as eglGetDisplay() autodetection
+         * gets fixed. Currently it is incorrectly detecting wl_display and
+         * returning _EGL_PLATFORM_X11 instead of _EGL_PLATFORM_WAYLAND.
+         *
+         * See ticket #1972 for more info.
+         */
+        setenv("EGL_PLATFORM", "tbm", 1);
+
+        /* try to allocate space for a new render engine */
+        if (!(re = calloc(1, sizeof(Render_Engine))))
+          return 0;
+
+        /* if we have not initialize gl & evas, do it */
+        if (!initted)
+          {
+             evas_common_init();
+             glsym_evas_gl_preload_init();
+          }
+
+        ob = eng_window_new(evas, inf, epd->output.w, epd->output.h, swap_mode,
+                            inf->depth_bits, inf->stencil_bits, inf->msaa_bits);
+        if (!ob) goto ob_err;
+
+        if (!evas_render_engine_gl_generic_init(&re->generic, ob,
+                                                eng_outbuf_swap_mode_get,
+                                                eng_outbuf_rotation_get,
+                                                eng_outbuf_reconfigure,
+                                                eng_outbuf_region_first_rect,
+                                                eng_outbuf_update_region_new,
+                                                eng_outbuf_update_region_push,
+                                                eng_outbuf_update_region_free,
+                                                NULL,
+                                                eng_outbuf_flush,
+                                                eng_window_free,
+                                                eng_window_use,
+                                                eng_outbuf_gl_context_get,
+                                                eng_outbuf_egl_display_get,
+                                                eng_gl_context_new,
+                                                eng_gl_context_use,
+                                                &evgl_funcs,
+                                                epd->output.w, epd->output.h))
+          {
+             eng_window_free(ob);
+             goto ob_err;
+          }
+
+        epd->engine.data.output = re;
+        gl_wins++;
+
+        if ((s = getenv("EVAS_GL_PARTIAL_MERGE")))
+          {
+             if ((!strcmp(s, "bounding")) || (!strcmp(s, "b")))
+               merge = MERGE_BOUNDING;
+             else if ((!strcmp(s, "full")) || (!strcmp(s, "f")))
+               merge = MERGE_FULL;
+             else if ((!strcmp(s, "smart")) || (!strcmp(s, "s")))
+               merge = MERGE_SMART;
+          }
+
+        evas_render_engine_software_generic_merge_mode_set(&re->generic.software, merge);
+
+        if (!initted)
+          {
+             gl_extn_veto(re);
+             initted = EINA_TRUE;
+          }
+     }
+   else
+     {
+        re = epd->engine.data.output;
+        ob = eng_get_ob(re);
+        if ((ob) && (_re_wincheck(ob)))
+          {
+             ob->info = inf;
+             if ((ob->info->info.depth != ob->depth) ||
+                 (ob->info->info.destination_alpha != ob->alpha))
+               {
+                  ob->gl_context->references++;
+                  gl_wins--;
+
+                  ob = eng_window_new(evas, inf, epd->output.w, epd->output.h, swap_mode,
+                                      inf->depth_bits, inf->stencil_bits, inf->msaa_bits);
+                  if (!ob) goto ob_err;
+
+                  eng_window_use(ob);
+
+                  evas_render_engine_software_generic_update(&re->generic.software, ob,
+                                                             epd->output.w, epd->output.h);
+                  gl_wins++;
+                  eng_get_ob(re)->gl_context->references--;
+               }
+             else if ((ob->w != epd->output.w) || (ob->h != epd->output.h) ||
+                      (ob->info->info.rotation != ob->rot))
+               {
+                  eng_outbuf_reconfigure(ob, epd->output.w, epd->output.h,
+                                         ob->info->info.rotation, 0);
+               }
+          }
+     }
+
+   if (!eng_get_ob(re)) goto ob_err;
+
+   if (!epd->engine.data.output)
+     {
+        if (eng_get_ob(re))
+          {
+             eng_window_free(eng_get_ob(re));
+             gl_wins--;
+          }
+        goto ob_err;
+     }
+
+   if (re->generic.software.tb)
+     evas_common_tilebuf_free(re->generic.software.tb);
+   re->generic.software.tb =
+     evas_common_tilebuf_new(epd->output.w, epd->output.h);
+
+   if (re->generic.software.tb)
+     {
+        evas_common_tilebuf_set_tile_size(re->generic.software.tb,
+                                          TILESIZE, TILESIZE);
+        evas_render_engine_software_generic_tile_strict_set
+          (&re->generic.software, EINA_TRUE);
+     }
+
+   if (!epd->engine.data.context)
+     {
+        epd->engine.data.context =
+          epd->engine.func->context_new(epd->engine.data.output);
+     }
+
+   eng_window_use(eng_get_ob(re));
+
+   return 1;
+
+ob_err:
+   free(re);
+   return 0;
+}
+
+static Eina_Bool
+eng_canvas_alpha_get(void *data, void *info EINA_UNUSED)
+{
+   Render_Engine *re;
+
+   if ((re = (Render_Engine *)data))
+     return re->generic.software.ob->alpha;
+
+   return EINA_FALSE;
+}
+
+static void
+eng_output_free(void *data)
+{
+   Render_Engine *re;
+
+   if ((re = (Render_Engine *)data))
+     {
+        glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re));
+
+        if (gl_wins == 1) glsym_evgl_engine_shutdown(re);
+
+        evas_render_engine_software_generic_clean(&re->generic.software);
+
+        gl_wins--;
+
+        free(re);
+     }
+
+   if ((initted == EINA_TRUE) && (gl_wins == 0))
+     {
+        glsym_evas_gl_preload_shutdown();
+        evas_common_shutdown();
+        initted = EINA_FALSE;
+     }
+}
+
+static void
+eng_output_dump(void *data)
+{
+   Render_Engine *re;
+
+   if (!(re = (Render_Engine *)data)) return;
+
+   evas_common_image_image_all_unload();
+   evas_common_font_font_all_unload();
+   glsym_evas_gl_common_image_all_unload(eng_get_ob(re)->gl_context);
+   _re_winfree(re);
+}
+
+static void *
+eng_gl_current_context_get(void *data EINA_UNUSED)
+{
+   EVGL_Context *ctx;
+
+   ctx = glsym_evas_gl_common_current_context_get();
+   if (!ctx)
+     return NULL;
+
+#ifdef GL_GLES
+   if (eglGetCurrentContext() == (ctx->context))
+     return ctx;
+   else
+     return NULL;
+#else
+   if (glXGetCurrentContext() == (ctx->context))
+     return ctx;
+   else
+     return NULL;
+#endif
+}
+
+static int
+eng_gl_error_get(void *data)
+{
+   int err;
+
+   if ((err = glsym_evas_gl_common_error_get(data)) != EVAS_GL_SUCCESS)
+     goto end;
+
+   err = eglGetError() - EGL_SUCCESS;
+
+end:
+   glsym_evas_gl_common_error_set(data, EVAS_GL_SUCCESS);
+   return err;
+}
+
+static void
+_native_cb_bind(void *data EINA_UNUSED, void *image)
+{
+   Evas_GL_Image *img;
+   Native *n;
+
+   if (!(img = image)) return;
+   if (!(n = img->native.data)) return;
+
+   if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
+     {
+        if (n->ns_data.wl_surface.surface)
+          {
+             if (glsym_glEGLImageTargetTexture2DOES)
+               {
+                  glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, n->ns_data.wl_surface.surface);
+                  GLERRV("glsym_glEGLImageTargetTexture2DOES");
+               }
+             else
+               ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
+          }
+     }
+   else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
+     {
+        glBindTexture(GL_TEXTURE_2D, n->ns.data.opengl.texture_id);
+     }
+   else if (n->ns.type == EVAS_NATIVE_SURFACE_EVASGL)
+     {
+        if (n->ns_data.evasgl.surface)
+          {
+             Eina_Bool is_egl_image = EINA_FALSE;
+             void *surface;
+
+             if (glsym_evgl_native_surface_buffer_get)
+               surface = glsym_evgl_native_surface_buffer_get(n->ns_data.evasgl.surface, &is_egl_image);
+
+             if (is_egl_image)
+               {
+                  if (glsym_glEGLImageTargetTexture2DOES)
+                    {
+                       glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, surface);
+                       if (eglGetError() != EGL_SUCCESS)
+                         ERR("glEGLImageTargetTexture2DOES() failed.");
+                    }
+                  else
+                    ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
+               }
+             else
+               {
+                  glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr_t)surface);
+               }
+          }
+    }
+  else if (n->ns.type == EVAS_NATIVE_SURFACE_TBM)
+    {
+#ifdef GL_GLES
+      if (n->ns_data.tbm.surface)
+        {
+           if (glsym_glEGLImageTargetTexture2DOES)
+              {
+                glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, n->ns_data.tbm.surface);
+                if (eglGetError() != EGL_SUCCESS)
+                  ERR("glEGLImageTargetTexture2DOES() failed.");
+              }
+            else
+              ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
+        }
+#endif
+    }
+}
+
+static void
+_native_cb_unbind(void *data EINA_UNUSED, void *image)
+{
+   Evas_GL_Image *img;
+   Native *n;
+
+   if (!(img = image)) return;
+   if (!(n = img->native.data)) return;
+
+   if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
+     {
+        //glBindTexture(GL_TEXTURE_2D, 0); //really need?
+     }
+   else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
+     {
+        glBindTexture(GL_TEXTURE_2D, 0);
+     }
+  else if (n->ns.type == EVAS_NATIVE_SURFACE_EVASGL)
+    {
+      // nothing
+    }
+  else if (n->ns.type == EVAS_NATIVE_SURFACE_TBM)
+    {
+      // nothing
+    }
+}
+
+static void
+_native_cb_free(void *data, void *image)
+{
+   Render_Engine *re;
+   Outbuf *ob;
+   Evas_GL_Image *img;
+   Native *n;
+   uint32_t texid;
+   void *wlid;
+
+   if (!(re = (Render_Engine *)data)) return;
+   if (!(img = image)) return;
+   if (!(n = img->native.data)) return;
+   if (!(ob = eng_get_ob(re))) return;
+
+   if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
+     {
+        wlid = (void*)n->ns_data.wl_surface.wl_buf;
+        eina_hash_del(ob->gl_context->shared->native_wl_hash, &wlid, img);
+        if (n->ns_data.wl_surface.surface)
+          {
+             int err;
+             if (glsym_eglDestroyImage)
+               {
+                  glsym_eglDestroyImage(ob->egl_disp, n->ns_data.wl_surface.surface);
+                  if ((err = eglGetError()) != EGL_SUCCESS)
+                    {
+                       ERR("eglDestroyImage() failed.");
+                       glsym_evas_gl_common_error_set(err - EGL_SUCCESS);
+                    }
+               }
+             else
+               ERR("Try eglDestroyImage on EGL with  no support");
+          }
+     }
+   else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
+     {
+        texid = n->ns.data.opengl.texture_id;
+        eina_hash_del(ob->gl_context->shared->native_tex_hash, &texid, img);
+     }
+  else if (n->ns.type == EVAS_NATIVE_SURFACE_EVASGL)
+    {
+      eina_hash_del(eng_get_ob(re)->gl_context->shared->native_evasgl_hash, &n->ns_data.evasgl.surface, img);
+    }
+  else if (n->ns.type == EVAS_NATIVE_SURFACE_TBM)
+    {
+       eina_hash_del(ob->gl_context->shared->native_tbm_hash, &n->ns_data.tbm.buffer, img);
+#ifdef GL_GLES
+      if (n->ns_data.tbm.surface)
+        {
+           int err;
+           if (glsym_eglDestroyImage)
+             {
+                glsym_eglDestroyImage(ob->egl_disp,
+                                      n->ns_data.tbm.surface);
+                if ((err = eglGetError()) != EGL_SUCCESS)
+                  {
+                     ERR("eglDestroyImage() failed.");
+                  }
+             }
+           else
+              ERR("Try eglDestroyImage on EGL with no support");
+        }
+#endif
+    }
+   img->native.data = NULL;
+   img->native.func.data = NULL;
+   img->native.func.bind = NULL;
+   img->native.func.unbind = NULL;
+   img->native.func.free = NULL;
+
+   free(n);
+}
+
+static int
+_native_cb_yinvert(void *data, void *image)
+{
+   Render_Engine *re = data;
+   Evas_GL_Image *im = image;
+   Native *n = im->native.data;
+   int yinvert = 0, val;
+
+   // Yinvert callback should only be used for EVAS_NATIVE_SURFACE_EVASGL type now,
+   // as yinvert value is not changed for other types.
+   if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
+     {
+     }
+   else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
+     {
+        yinvert = 0;
+     }
+   else if (n->ns.type == EVAS_NATIVE_SURFACE_TBM)
+     {
+        yinvert = 1;
+     }
+   else if (n->ns.type == EVAS_NATIVE_SURFACE_EVASGL)
+     {
+        if (glsym_evgl_native_surface_yinvert_get)
+          yinvert = glsym_evgl_native_surface_yinvert_get(n->ns_data.evasgl.surface);
+     }
+
+   return yinvert;
+}
+
+static void *
+eng_image_native_set(void *data, void *image, void *native)
+{
+   Render_Engine *re;
+   Outbuf *ob;
+   Native *n;
+   Evas_Native_Surface *ns;
+   Evas_GL_Image *img, *img2;
+   unsigned int tex = 0, fbo = 0;
+   uint32_t texid;
+   void *buffer = NULL;
+   void *wlid, *wl_buf = NULL;
+
+   if (!(re = (Render_Engine *)data)) return NULL;
+   if (!(ob = eng_get_ob(re))) return NULL;
+
+   ns = native;
+
+   if (!(img = image))
+     {
+        if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_OPENGL))
+          {
+             img =
+               glsym_evas_gl_common_image_new_from_data(ob->gl_context,
+                                                        ns->data.opengl.w,
+                                                        ns->data.opengl.h,
+                                                        NULL, 1,
+                                                        EVAS_COLORSPACE_ARGB8888);
+          }
+        else
+          return NULL;
+     }
+
+   if (ns)
+     {
+        if (ns->type == EVAS_NATIVE_SURFACE_WL)
+          {
+             wl_buf = ns->data.wl.legacy_buffer;
+             if (img->native.data)
+               {
+                  Evas_Native_Surface *ens;
+
+                  ens = img->native.data;
+                  if (ens->data.wl.legacy_buffer == wl_buf)
+                    return img;
+               }
+          }
+        else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL)
+          {
+             tex = ns->data.opengl.texture_id;
+             fbo = ns->data.opengl.framebuffer_id;
+             if (img->native.data)
+               {
+                  Evas_Native_Surface *ens;
+
+                  ens = img->native.data;
+                  if ((ens->data.opengl.texture_id == tex) &&
+                      (ens->data.opengl.framebuffer_id == fbo))
+                     return img;
+               }
+          }
+        else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
+         {
+            buffer = ns->data.evasgl.surface;
+            if (img->native.data)
+              {
+                 Evas_Native_Surface *ens = img->native.data;
+                 if (ens->data.evasgl.surface == buffer)
+                   return img;
+              }
+         }
+        else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
+         {
+            buffer = ns->data.tbm.buffer;
+            if (img->native.data)
+              {
+                 Evas_Native_Surface *ens = img->native.data;
+                 if (ens->data.tbm.buffer == buffer)
+                   return img;
+              }
+         }
+     }
+
+   if ((!ns) && (!img->native.data)) return img;
+
+   eng_window_use(ob);
+
+   if (img->native.data)
+     {
+        if (img->native.func.free)
+          img->native.func.free(img->native.func.data, img);
+        glsym_evas_gl_common_image_native_disable(img);
+     }
+
+   if (!ns) return img;
+
+   if (ns->type == EVAS_NATIVE_SURFACE_WL)
+     {
+        wlid = wl_buf;
+        img2 = eina_hash_find(ob->gl_context->shared->native_wl_hash, &wlid);
+        if (img2 == img) return img;
+        if (img2)
+          {
+             if((n = img2->native.data))
+               {
+                  glsym_evas_gl_common_image_ref(img2);
+                  glsym_evas_gl_common_image_free(img);
+                  return img2;
+               }
+          }
+     }
+   else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL)
+     {
+        texid = tex;
+        img2 = eina_hash_find(ob->gl_context->shared->native_tex_hash, &texid);
+        if (img2 == img) return img;
+        if (img2)
+          {
+             if ((n = img2->native.data))
+               {
+                  glsym_evas_gl_common_image_ref(img2);
+                  glsym_evas_gl_common_image_free(img);
+                  return img2;
+               }
+          }
+     }
+   else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
+     {
+         img2 = eina_hash_find(eng_get_ob(re)->gl_context->shared->native_evasgl_hash, &buffer);
+        if (img2 == img) return img;
+        if (img2)
+          {
+             n = img2->native.data;
+             if (n)
+              {
+                 glsym_evas_gl_common_image_ref(img2);
+                 glsym_evas_gl_common_image_free(img);
+                 return img2;
+              }
+         }
+     }
+  else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
+    {
+       img2 = eina_hash_find(ob->gl_context->shared->native_tbm_hash, &buffer);
+       if (img2 == img) return img;
+       if (img2)
+         {
+            n = img2->native.data;
+            if (n)
+             {
+                glsym_evas_gl_common_image_ref(img2);
+                glsym_evas_gl_common_image_free(img);
+                return img2;
+             }
+        }
+    }
+
+   img2 = glsym_evas_gl_common_image_new_from_data(ob->gl_context, img->w,
+                                                   img->h, NULL, img->alpha,
+                                                   EVAS_COLORSPACE_ARGB8888);
+   glsym_evas_gl_common_image_free(img);
+
+   if (!(img = img2)) return NULL;
+
+   if (ns->type == EVAS_NATIVE_SURFACE_WL)
+     {
+        if (native)
+          {
+             if ((n = calloc(1, sizeof(Native))))
+               {
+                  EGLint attribs[3];
+                  int format, yinvert = 1;
+
+                  glsym_eglQueryWaylandBufferWL(ob->egl_disp, wl_buf,
+                                                EGL_TEXTURE_FORMAT, &format);
+                  if ((format != EGL_TEXTURE_RGB) &&
+                      (format != EGL_TEXTURE_RGBA))
+                    {
+                       ERR("eglQueryWaylandBufferWL() %d format is not supported ", format);
+                       glsym_evas_gl_common_image_free(img);
+                       free(n);
+                       return NULL;
+                    }
+
+                  attribs[0] = EVAS_GL_WAYLAND_PLANE_WL;
+                  attribs[1] = 0; //if plane is 1 then 0, if plane is 2 then 1
+                  attribs[2] = EGL_NONE;
+
+                  memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
+                  if (glsym_eglQueryWaylandBufferWL(ob->egl_disp, wl_buf,
+                                                    EVAS_GL_WAYLAND_Y_INVERTED_WL,
+                                                    &yinvert) == EGL_FALSE)
+                    yinvert = 1;
+                  eina_hash_add(ob->gl_context->shared->native_wl_hash,
+                                &wlid, img);
+
+                  n->ns_data.wl_surface.wl_buf = wl_buf;
+                  if (glsym_eglCreateImage)
+                    n->ns_data.wl_surface.surface = glsym_eglCreateImage(ob->egl_disp,
+                                                          NULL,
+                                                          EVAS_GL_WAYLAND_BUFFER_WL,
+                                                          wl_buf, attribs);
+                  else
+                    {
+                       ERR("Try eglCreateImage on EGL with no support");
+                       eina_hash_del(ob->gl_context->shared->native_wl_hash,
+                                     &wlid, img);
+                       glsym_evas_gl_common_image_free(img);
+                       free(n);
+                       return NULL;
+                    }
+
+                  if (!n->ns_data.wl_surface.surface)
+                    {
+                       ERR("eglCreatePixmapSurface() for %p failed", wl_buf);
+                       eina_hash_del(ob->gl_context->shared->native_wl_hash,
+                                     &wlid, img);
+                       glsym_evas_gl_common_image_free(img);
+                       free(n);
+                       return NULL;
+                    }
+
+                  //XXX: workaround for mesa-10.2.8
+                  // mesa's eglQueryWaylandBufferWL() with EGL_WAYLAND_Y_INVERTED_WL works incorrect.
+                  //img->native.yinvert = yinvert;
+                  img->native.yinvert = 1;
+                  img->native.loose = 0;
+                  img->native.data = n;
+                  img->native.func.data = re;
+                  img->native.func.bind = _native_cb_bind;
+                  img->native.func.unbind = _native_cb_unbind;
+                  img->native.func.free = _native_cb_free;
+                  img->native.target = GL_TEXTURE_2D;
+                  img->native.mipmap = 0;
+
+                  glsym_evas_gl_common_image_native_enable(img);
+               }
+          }
+     }
+   else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL)
+     {
+        if (native)
+          {
+             if ((n = calloc(1, sizeof(Native))))
+               {
+                  memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
+                  eina_hash_add(ob->gl_context->shared->native_tex_hash, &texid, img);
+
+                  n->ns_data.opengl.surface = 0;
+
+                  img->native.yinvert = 0;
+                  img->native.loose = 0;
+                  img->native.data = n;
+                  img->native.func.data = re;
+                  img->native.func.bind = _native_cb_bind;
+                  img->native.func.unbind = _native_cb_unbind;
+                  img->native.func.free = _native_cb_free;
+                  img->native.func.yinvert = _native_cb_yinvert;
+                  img->native.target = GL_TEXTURE_2D;
+                  img->native.mipmap = 0;
+
+                  glsym_evas_gl_common_image_native_enable(img);
+               }
+          }
+     }
+   else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
+     {
+       if (native)
+         {
+           n = calloc(1, sizeof(Native));
+           if (n)
+             {
+               memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
+
+               eina_hash_add(eng_get_ob(re)->gl_context->shared->native_evasgl_hash, &buffer, img);
+
+               n->ns_data.evasgl.surface = ns->data.evasgl.surface;
+               img->native.yinvert     = 0;
+               img->native.loose       = 0;
+               img->native.data        = n;
+               img->native.func.data   = re;
+               img->native.func.bind   = _native_cb_bind;
+               img->native.func.unbind = _native_cb_unbind;
+               img->native.func.free   = _native_cb_free;
+               img->native.target      = GL_TEXTURE_2D;
+               img->native.mipmap      = 0;
+
+               glsym_evas_gl_common_image_native_enable(img);
+             }
+         }
+     }
+  else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
+    {
+#ifdef GL_GLES
+       if (native)
+         {
+           n = calloc(1, sizeof(Native));
+           if (n)
+             {
+               eina_hash_add(eng_get_ob(re)->gl_context->shared->native_tbm_hash, &buffer, img);
+
+               memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
+               n->ns_data.tbm.buffer = buffer;
+
+               if (glsym_eglCreateImage)
+                 n->ns_data.tbm.surface = glsym_eglCreateImage(eng_get_ob(re)->egl_disp,
+                                                               EGL_NO_CONTEXT,
+                                                               EGL_NATIVE_SURFACE_TIZEN,
+                                                               (void *)buffer,
+                                                               NULL);
+               else
+                 ERR("Try eglCreateImage on EGL with no support");
+               if (!n->ns_data.tbm.surface)
+                 ERR("eglCreateImage() for %p failed", buffer);
+               img->native.yinvert     = 1;
+               img->native.loose       = 0;
+               img->native.data        = n;
+               img->native.func.data   = re;
+               img->native.func.bind   = _native_cb_bind;
+               img->native.func.unbind = _native_cb_unbind;
+               img->native.func.free   = _native_cb_free;
+               img->native.target      = GL_TEXTURE_EXTERNAL_OES;
+               img->native.mipmap      = 0;
+               glsym_evas_gl_common_image_native_enable(img);
+             }
+         }
+#endif
+    }
+
+   return img;
+}
+
+static void *
+eng_image_native_get(void *data EINA_UNUSED, void *image)
+{
+   Evas_GL_Image *im = image;
+   Evas_Native_Surface *n;
+
+   if (!im) return NULL;
+   n = im->native.data;
+   if (!n) return NULL;
+   return n;
+}
+
+Eina_Bool
+eng_preload_make_current(void *data, void *doit)
+{
+   Outbuf *ob;
+
+   if (!(ob = data)) return EINA_FALSE;
+
+   if (doit)
+     {
+        if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0],
+                            ob->egl_surface[0], ob->egl_context[0]))
+          return EINA_FALSE;
+     }
+   else
+     {
+        if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                            EGL_NO_CONTEXT))
+          return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+/* evas module functions */
+static int
+module_open(Evas_Module *em)
+{
+   /* check for valid module */
+   if (!em) return 0;
+
+   /* get whatever engine module we inherit from */
+   if (!_evas_module_engine_inherit(&pfunc, "gl_generic")) return 0;
+
+   /* setup logging domain */
+   if (_evas_engine_gl_tbm_log_dom < 0)
+     {
+         _evas_engine_gl_tbm_log_dom =
+          eina_log_domain_register("evas-gl_tbm", EVAS_DEFAULT_LOG_COLOR);
+     }
+
+   if (_evas_engine_gl_tbm_log_dom < 0)
+     {
+        EINA_LOG_ERR("Can not create a module log domain.");
+        return 0;
+     }
+
+   /* store functions for later use */
+   func = pfunc;
+
+#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
+
+   ORD(info);
+   ORD(info_free);
+   ORD(setup);
+   ORD(canvas_alpha_get);
+
+   ORD(output_free);
+   ORD(output_dump);
+
+   ORD(image_native_set);
+
+   ORD(gl_current_context_get);
+   ORD(gl_error_get);
+
+   gl_symbols();
+
+   /* advertise out which functions we support */
+   em->functions = (void *)(&func);
+
+   return 1;
+}
+
+static void
+module_close(Evas_Module *em EINA_UNUSED)
+{
+   eina_log_domain_unregister(_evas_engine_gl_tbm_log_dom);
+}
+
+static Evas_Module_Api evas_modapi =
+{
+   EVAS_MODULE_API_VERSION, "gl_tbm", "none", {module_open, module_close}
+};
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, gl_tbm);
+
+#ifndef EVAS_STATIC_BUILD_GL_TBM
+EVAS_EINA_MODULE_DEFINE(engine, gl_tbm);
+#endif
diff --git a/src/modules/evas/engines/gl_tbm/evas_engine.h b/src/modules/evas/engines/gl_tbm/evas_engine.h
new file mode 100755 (executable)
index 0000000..cf26567
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef EVAS_ENGINE_H
+# define EVAS_ENGINE_H
+
+# include "config.h"
+# include "evas_common_private.h"
+# include "evas_private.h"
+# include "Evas.h"
+# include "Evas_Engine_GL_Tbm.h"
+
+# define GL_GLEXT_PROTOTYPES
+
+#if !defined(HAVE_ECORE_X_XLIB) && !defined(MESA_EGL_NO_X11_HEADERS)
+# define MESA_EGL_NO_X11_HEADERS
+#endif
+
+# include <EGL/egl.h>
+# include <GLES2/gl2.h>
+# include <GLES2/gl2ext.h>
+
+# include "../gl_generic/Evas_Engine_GL_Generic.h"
+
+extern int _evas_engine_gl_tbm_log_dom;
+
+# ifdef ERR
+#  undef ERR
+# endif
+# define ERR(...) EINA_LOG_DOM_ERR(_evas_engine_gl_tbm_log_dom, __VA_ARGS__)
+
+# ifdef DBG
+#  undef DBG
+# endif
+# define DBG(...) EINA_LOG_DOM_DBG(_evas_engine_gl_tbm_log_dom, __VA_ARGS__)
+
+# ifdef INF
+#  undef INF
+# endif
+# define INF(...) EINA_LOG_DOM_INFO(_evas_engine_gl_tbm_log_dom, __VA_ARGS__)
+
+# ifdef WRN
+#  undef WRN
+# endif
+# define WRN(...) EINA_LOG_DOM_WARN(_evas_engine_gl_tbm_log_dom, __VA_ARGS__)
+
+# ifdef CRI
+#  undef CRI
+# endif
+# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_gl_tbm_log_dom, __VA_ARGS__)
+
+# ifndef EGL_BUFFER_AGE_EXT
+#  define EGL_BUFFER_AGE_EXT 0x313d
+# endif
+
+struct _Outbuf
+{
+   int w, h;
+   int depth, screen, rot, alpha;
+
+   Evas *evas;
+   Evas_Engine_Info_GL_Tbm *info;
+   Evas_Engine_GL_Context *gl_context;
+
+   void *tbm_queue;
+   Eina_Bool ext_tbm_queue;
+
+   Render_Engine_Swap_Mode swap_mode;
+   int prev_age, vsync;
+   int frame_cnt;
+
+   struct
+     {
+        Eina_Bool drew : 1;
+     } draw;
+
+   EGLContext egl_context[1];
+   EGLSurface egl_surface[1];
+   EGLConfig egl_config;
+   EGLDisplay egl_disp;
+
+   Eina_Bool lost_back : 1;
+   Eina_Bool surf : 1;
+
+   struct {
+      unsigned char depth_buffer_size;
+      unsigned char stencil_buffer_size;
+      unsigned char msaa;
+   } detected;
+
+   int depth_bits;
+   int stencil_bits;
+   int msaa_bits;
+};
+
+struct _Context_3D
+{
+   EGLDisplay display;
+   EGLContext context;
+   EGLSurface surface;
+};
+
+extern Eina_Bool extn_have_buffer_age;
+extern Eina_Bool extn_have_y_inverted;
+
+extern Evas_GL_Common_Context_New glsym_evas_gl_common_context_new;
+extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush;
+extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free;
+extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use;
+extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe;
+extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done;
+extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize;
+extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump;
+extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock;
+extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock;
+
+extern unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c);
+extern unsigned int (*glsym_eglSetDamageRegionKHR) (EGLDisplay a, EGLSurface b, EGLint *c, EGLint d);
+
+Outbuf *eng_window_new(Evas *evas, Evas_Engine_Info_GL_Tbm *einfo, int w, int h, Render_Engine_Swap_Mode swap_mode,
+                                  int depth_bits, int stencil_bits, int msaa_bits);
+void eng_window_free(Outbuf *gw);
+void eng_window_use(Outbuf *gw);
+void eng_window_unsurf(Outbuf *gw);
+void eng_window_resurf(Outbuf *gw);
+
+void eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
+int eng_outbuf_rotation_get(Outbuf *ob);
+Render_Engine_Swap_Mode eng_outbuf_swap_mode_get(Outbuf *ob);
+Eina_Bool eng_outbuf_region_first_rect(Outbuf *ob);
+void *eng_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
+void eng_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
+void eng_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
+void eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
+
+Evas_Engine_GL_Context *eng_outbuf_gl_context_get(Outbuf *ob);
+void *eng_outbuf_egl_display_get(Outbuf *ob);
+Eina_Bool eng_preload_make_current(void *data, void *doit);
+
+Context_3D *eng_gl_context_new(Outbuf *win);
+void eng_gl_context_free(Context_3D *context);
+void eng_gl_context_use(Context_3D *context);
+
+static inline int
+_re_wincheck(Outbuf *ob)
+{
+   if (ob->surf) return 1;
+   eng_window_resurf(ob);
+   ob->lost_back = EINA_TRUE;
+   if (!ob->surf)
+     ERR("tbm Engine cannot recreate window surface");
+   return 0;
+}
+
+extern void (*glsym_evas_gl_context_restore_set) (Eina_Bool enable);
+
+#endif
diff --git a/src/modules/evas/engines/gl_tbm/evas_tbm_main.c b/src/modules/evas/engines/gl_tbm/evas_tbm_main.c
new file mode 100755 (executable)
index 0000000..0c20198
--- /dev/null
@@ -0,0 +1,591 @@
+#include "evas_engine.h"
+
+# define SET_RESTORE_CONTEXT() do { if (glsym_evas_gl_context_restore_set) glsym_evas_gl_context_restore_set(EINA_TRUE); } while(0)
+
+/* local function prototypes */
+
+/* local variables */
+static Outbuf *_evas_gl_wl_window = NULL;
+static EGLContext context = EGL_NO_CONTEXT;
+static int win_count = 0;
+
+Outbuf *
+eng_window_new(Evas *evas, Evas_Engine_Info_GL_Tbm *einfo, int w, int h, Render_Engine_Swap_Mode swap_mode,
+                          int depth_bits, int stencil_bits, int msaa_bits)
+{
+   Outbuf *gw;
+   int context_attrs[3];
+   int config_attrs[40];
+   int major_version, minor_version;
+   int num_config, n = 0;
+   const GLubyte *vendor, *renderer, *version;
+   Eina_Bool blacklist = EINA_FALSE;
+   int val = 0;
+
+   /* try to allocate space for our window */
+   if (!(gw = calloc(1, sizeof(Outbuf))))
+     return NULL;
+
+   win_count++;
+   gw->info = einfo;
+   gw->evas = evas;
+   gw->w = w;
+   gw->h = h;
+   gw->swap_mode = swap_mode;
+   gw->tbm_queue = einfo->info.tbm_queue;
+   gw->ext_tbm_queue = einfo->info.ext_tbm_queue;
+   gw->depth = einfo->info.depth;
+   gw->alpha = einfo->info.destination_alpha;
+   gw->rot = einfo->info.rotation;
+   gw->depth_bits = depth_bits;
+   gw->stencil_bits = stencil_bits;
+   gw->msaa_bits = msaa_bits;
+
+   context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
+   context_attrs[1] = 2;
+   context_attrs[2] = EGL_NONE;
+
+   config_attrs[n++] = EGL_SURFACE_TYPE;
+   config_attrs[n++] = EGL_WINDOW_BIT;
+   config_attrs[n++] = EGL_RENDERABLE_TYPE;
+   config_attrs[n++] = EGL_OPENGL_ES2_BIT;
+# if 0
+   /* FIXME: n900 - omap3 sgx libs break here */
+   config_attrs[n++] = EGL_RED_SIZE;
+   config_attrs[n++] = 1;
+   config_attrs[n++] = EGL_GREEN_SIZE;
+   config_attrs[n++] = 1;
+   config_attrs[n++] = EGL_BLUE_SIZE;
+   config_attrs[n++] = 1;
+   /* FIXME: end n900 breakage */
+# endif
+   config_attrs[n++] = EGL_ALPHA_SIZE;
+   config_attrs[n++] = gw->alpha;
+   config_attrs[n++] = EGL_DEPTH_SIZE;
+   config_attrs[n++] = gw->depth_bits;
+   config_attrs[n++] = EGL_STENCIL_SIZE;
+   config_attrs[n++] = gw->stencil_bits;
+   if (msaa_bits > 0)
+     {
+        config_attrs[n++] = EGL_SAMPLE_BUFFERS;
+        config_attrs[n++] = 1;
+        config_attrs[n++] = EGL_SAMPLES;
+        config_attrs[n++] = gw->msaa_bits;
+     }
+   config_attrs[n++] = EGL_NONE;
+
+   /* FIXME: Remove this line as soon as eglGetDisplay() autodetection
+    * gets fixed. Currently it is incorrectly detecting wl_display and
+    * returning _EGL_PLATFORM_X11 instead of _EGL_PLATFORM_WAYLAND.
+    *
+    * See ticket #1972 for more info.
+    */
+
+   setenv("EGL_PLATFORM", "tbm", 1);
+   gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)NULL);
+   if (!gw->egl_disp)
+     {
+        ERR("eglGetDisplay() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+   if (!eglInitialize(gw->egl_disp, &major_version, &minor_version))
+     {
+        ERR("eglInitialize() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+   if (!eglBindAPI(EGL_OPENGL_ES_API))
+     {
+        ERR("eglBindAPI() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   num_config = 0;
+   if (!eglChooseConfig(gw->egl_disp, config_attrs, &gw->egl_config,
+                        1, &num_config) || (num_config != 1))
+     {
+        ERR("eglChooseConfig() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   gw->egl_surface[0] =
+     eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
+                            (EGLNativeWindowType)gw->tbm_queue, NULL);
+   if (gw->egl_surface[0] == EGL_NO_SURFACE)
+     {
+        ERR("eglCreateWindowSurface() fail for %p. code=%#x",
+            gw->tbm_queue, eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   gw->egl_context[0] =
+     eglCreateContext(gw->egl_disp, gw->egl_config, context, context_attrs);
+   if (gw->egl_context[0] == EGL_NO_CONTEXT)
+     {
+        ERR("eglCreateContext() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   if (context == EGL_NO_CONTEXT) context = gw->egl_context[0];
+
+   SET_RESTORE_CONTEXT();
+   if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
+                      gw->egl_surface[0], gw->egl_context[0]) == EGL_FALSE)
+     {
+        ERR("eglMakeCurrent() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   vendor = glGetString(GL_VENDOR);
+   renderer = glGetString(GL_RENDERER);
+   version = glGetString(GL_VERSION);
+   if (!vendor) vendor   = (unsigned char *)"-UNKNOWN-";
+   if (!renderer) renderer = (unsigned char *)"-UNKNOWN-";
+   if (!version) version  = (unsigned char *)"-UNKNOWN-";
+   if (getenv("EVAS_GL_INFO"))
+     {
+        fprintf(stderr, "vendor: %s\n", vendor);
+        fprintf(stderr, "renderer: %s\n", renderer);
+        fprintf(stderr, "version: %s\n", version);
+     }
+
+   if (strstr((const char *)vendor, "Mesa Project"))
+     {
+        if (strstr((const char *)renderer, "Software Rasterizer"))
+          blacklist = EINA_TRUE;
+     }
+   if (strstr((const char *)renderer, "softpipe"))
+     blacklist = EINA_TRUE;
+   if (strstr((const char *)renderer, "llvmpipe"))
+     blacklist = EINA_TRUE;
+   if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST")))
+     {
+        ERR("OpenGL Driver blacklisted:");
+        ERR("Vendor: %s", (const char *)vendor);
+        ERR("Renderer: %s", (const char *)renderer);
+        ERR("Version: %s", (const char *)version);
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   eglGetConfigAttrib(gw->egl_disp, gw->egl_config, EGL_DEPTH_SIZE, &val);
+   gw->detected.depth_buffer_size = val;
+   DBG("Detected depth size %d", val);
+   eglGetConfigAttrib(gw->egl_disp, gw->egl_config, EGL_STENCIL_SIZE, &val);
+   gw->detected.stencil_buffer_size = val;
+   DBG("Detected stencil size %d", val);
+   eglGetConfigAttrib(gw->egl_disp, gw->egl_config, EGL_SAMPLES, &val);
+   gw->detected.msaa = val;
+   DBG("Detected msaa %d", val);
+
+   if (!(gw->gl_context = glsym_evas_gl_common_context_new()))
+     {
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   gw->gl_context->egldisp = gw->egl_disp;
+   gw->gl_context->eglctxt = gw->egl_context[0];
+
+   eng_window_use(gw);
+   glsym_evas_gl_common_context_resize(gw->gl_context, w, h, gw->rot,1);
+
+   gw->surf = EINA_TRUE;
+
+   return gw;
+}
+
+void
+eng_window_free(Outbuf *gw)
+{
+   int ref = 0;
+
+   win_count--;
+   eng_window_use(gw);
+
+   if (gw == _evas_gl_wl_window) _evas_gl_wl_window = NULL;
+
+   if (gw->gl_context)
+     {
+        ref = gw->gl_context->references - 1;
+        glsym_evas_gl_common_context_free(gw->gl_context);
+     }
+
+   SET_RESTORE_CONTEXT();
+   eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE,
+                  EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+   if (gw->egl_context[0] != context)
+     eglDestroyContext(gw->egl_disp, gw->egl_context[0]);
+
+   if (gw->egl_surface[0] != EGL_NO_SURFACE)
+     eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
+
+   if (ref == 0)
+     {
+        if (context) eglDestroyContext(gw->egl_disp, context);
+        eglTerminate(gw->egl_disp);
+        eglReleaseThread();
+        context = EGL_NO_CONTEXT;
+     }
+
+   free(gw);
+}
+
+void
+eng_window_use(Outbuf *gw)
+{
+   Eina_Bool force = EINA_FALSE;
+
+   glsym_evas_gl_preload_render_lock(eng_preload_make_current, gw);
+
+   if (_evas_gl_wl_window)
+     {
+        if (eglGetCurrentContext() != _evas_gl_wl_window->egl_context[0])
+          force = EINA_TRUE;
+     }
+
+   if ((_evas_gl_wl_window != gw) || (force))
+     {
+        if (_evas_gl_wl_window)
+          {
+             glsym_evas_gl_common_context_use(_evas_gl_wl_window->gl_context);
+             glsym_evas_gl_common_context_flush(_evas_gl_wl_window->gl_context);
+          }
+
+        _evas_gl_wl_window = gw;
+
+        if (gw)
+          {
+             if (gw->egl_surface[0] != EGL_NO_SURFACE)
+               {
+                  SET_RESTORE_CONTEXT();
+                  if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
+                                     gw->egl_surface[0],
+                                     gw->egl_context[0]) == EGL_FALSE)
+                    ERR("eglMakeCurrent() failed!");
+               }
+          }
+     }
+
+   if ((gw) && (gw->gl_context))
+     {
+        glsym_evas_gl_common_context_use(gw->gl_context);
+        glsym_evas_gl_common_context_resize(gw->gl_context, gw->w, gw->h, gw->rot,0);
+     }
+}
+
+void
+eng_window_unsurf(Outbuf *gw)
+{
+   if (!gw->surf) return;
+   if (!getenv("EVAS_GL_WIN_RESURF")) return;
+   if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", gw);
+
+   if (_evas_gl_wl_window)
+     glsym_evas_gl_common_context_flush(_evas_gl_wl_window->gl_context);
+
+   if (_evas_gl_wl_window == gw)
+     {
+        SET_RESTORE_CONTEXT();
+        eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE,
+                       EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        if (gw->egl_surface[0] != EGL_NO_SURFACE)
+          eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
+        gw->egl_surface[0] = EGL_NO_SURFACE;
+
+        _evas_gl_wl_window = NULL;
+     }
+
+   gw->surf = EINA_FALSE;
+}
+
+void
+eng_window_resurf(Outbuf *gw)
+{
+   if (gw->surf) return;
+   if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", gw);
+
+   gw->egl_surface[0] =
+     eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
+                            (EGLNativeWindowType)gw->tbm_queue, NULL);
+
+   if (gw->egl_surface[0] == EGL_NO_SURFACE)
+     {
+        ERR("eglCreateWindowSurface() fail code=%#x",
+           eglGetError());
+        return;
+     }
+
+   SET_RESTORE_CONTEXT();
+   if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0], gw->egl_surface[0],
+                      gw->egl_context[0]) == EGL_FALSE)
+     ERR("eglMakeCurrent() failed!");
+
+   gw->surf = EINA_TRUE;
+}
+
+void
+eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth EINA_UNUSED)
+{
+   ob->w = w;
+   ob->h = h;
+   ob->rot = rot;
+   eng_window_use(ob);
+   glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot,1);
+}
+
+int
+eng_outbuf_rotation_get(Outbuf *ob)
+{
+   return ob->rot;
+}
+
+Render_Engine_Swap_Mode
+eng_outbuf_swap_mode_get(Outbuf *ob)
+{
+   if ((ob->swap_mode == MODE_AUTO) && (extn_have_buffer_age))
+     {
+        Render_Engine_Swap_Mode swap_mode;
+        EGLint age = 0;
+
+        if (!eglQuerySurface(ob->egl_disp, ob->egl_surface[0],
+                             EGL_BUFFER_AGE_EXT, &age))
+          age = 0;
+
+        if (age == 1) swap_mode = MODE_COPY;
+        else if (age == 2) swap_mode = MODE_DOUBLE;
+        else if (age == 3) swap_mode = MODE_TRIPLE;
+        else if (age == 4) swap_mode = MODE_QUADRUPLE;
+        else swap_mode = MODE_FULL;
+
+        if ((int)age != ob->prev_age) swap_mode = MODE_FULL;
+        ob->prev_age = age;
+
+        return swap_mode;
+     }
+
+   return ob->swap_mode;
+}
+
+Eina_Bool
+eng_outbuf_region_first_rect(Outbuf *ob)
+{
+   glsym_evas_gl_preload_render_lock(eng_preload_make_current, ob);
+
+   eng_window_use(ob);
+   if (!_re_wincheck(ob)) return EINA_TRUE;
+
+   glsym_evas_gl_common_context_flush(ob->gl_context);
+   glsym_evas_gl_common_context_newframe(ob->gl_context);
+
+   return EINA_FALSE;
+}
+
+static void
+_convert_glcoords(int *result, Outbuf *ob, int x, int y, int w, int h)
+{
+   switch (ob->rot)
+     {
+      case 0:
+        result[0] = x;
+        result[1] = ob->gl_context->h - (y + h);
+        result[2] = w;
+        result[3] = h;
+        break;
+      case 90:
+        result[0] = y;
+        result[1] = x;
+        result[2] = h;
+        result[3] = w;
+        break;
+      case 180:
+        result[0] = ob->gl_context->w - (x + w);
+        result[1] = y;
+        result[2] = w;
+        result[3] = h;
+        break;
+      case 270:
+        result[0] = ob->gl_context->h - (y + h);
+        result[1] = ob->gl_context->w - (x + w);
+        result[2] = h;
+        result[3] = w;
+        break;
+      default:
+        result[0] = x;
+        result[1] = ob->gl_context->h - (y + h);
+        result[2] = w;
+        result[3] = h;
+        break;
+     }
+}
+
+static void
+_damage_rect_set(Outbuf *ob, int x, int y, int w, int h)
+{
+   int rects[4];
+
+   if ((x == 0) && (y == 0) &&
+       (((w == ob->gl_context->w) && (h == ob->gl_context->h)) ||
+           ((h == ob->gl_context->w) && (w == ob->gl_context->h))))
+     return;
+
+   _convert_glcoords(rects, ob, x, y, w, h);
+   glsym_eglSetDamageRegionKHR(ob->egl_disp, ob->egl_surface[0], rects, 1);
+}
+
+void *
+eng_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx EINA_UNUSED, int *cy EINA_UNUSED, int *cw EINA_UNUSED, int *ch EINA_UNUSED)
+{
+   if ((ob->w == w) && (ob->h == h))
+     ob->gl_context->master_clip.enabled = EINA_FALSE;
+   else
+     {
+        ob->gl_context->master_clip.enabled = EINA_TRUE;
+        ob->gl_context->master_clip.x = x;
+        ob->gl_context->master_clip.y = y;
+        ob->gl_context->master_clip.w = w;
+        ob->gl_context->master_clip.h = h;
+
+        if (glsym_eglSetDamageRegionKHR)
+          _damage_rect_set(ob, x, y, w, h);
+     }
+
+   return ob->gl_context->def_surface;
+}
+
+void
+eng_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
+{
+
+}
+
+void
+eng_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
+{
+   if (!_re_wincheck(ob)) return;
+   ob->draw.drew = EINA_TRUE;
+   glsym_evas_gl_common_context_flush(ob->gl_context);
+}
+
+void
+eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode)
+{
+   if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
+
+   if (!_re_wincheck(ob)) goto end;
+   if (!ob->draw.drew) goto end;
+
+   ob->draw.drew = EINA_FALSE;
+   eng_window_use(ob);
+   glsym_evas_gl_common_context_done(ob->gl_context);
+
+   if (!ob->vsync)
+     {
+        if (ob->info->vsync) eglSwapInterval(ob->egl_disp, 1);
+        else eglSwapInterval(ob->egl_disp, 0);
+        ob->vsync = EINA_TRUE;
+     }
+
+   if (ob->info->callback.pre_swap)
+     ob->info->callback.pre_swap(ob->info->callback.data, ob->evas);
+
+   if ((glsym_eglSwapBuffersWithDamage) && (rects) &&
+       (ob->swap_mode != MODE_FULL))
+     {
+        EGLint num = 0, *result = NULL, i = 0;
+        Tilebuf_Rect *r;
+
+        // if partial swaps can be done use re->rects
+        num = eina_inlist_count(EINA_INLIST_GET(rects));
+        if (num > 0)
+          {
+             result = alloca(sizeof(EGLint) * 4 * num);
+             EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
+               {
+                  _convert_glcoords(&result[i], ob, r->x, r->y, r->w, r->h);
+                  i += 4;
+               }
+             glsym_eglSwapBuffersWithDamage(ob->egl_disp, ob->egl_surface[0],
+                                            result, num);
+          }
+     }
+   else
+      eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]);
+
+   if (ob->info->callback.post_swap)
+     ob->info->callback.post_swap(ob->info->callback.data, ob->evas);
+
+   ob->frame_cnt++;
+
+ end:
+   glsym_evas_gl_preload_render_unlock(eng_preload_make_current, ob);
+}
+
+Evas_Engine_GL_Context *
+eng_outbuf_gl_context_get(Outbuf *ob)
+{
+   return ob->gl_context;
+}
+
+void *
+eng_outbuf_egl_display_get(Outbuf *ob)
+{
+   return ob->egl_disp;
+}
+
+Context_3D *
+eng_gl_context_new(Outbuf *ob)
+{
+   Context_3D *ctx;
+   int attrs[3];
+
+   if (!ob) return NULL;
+
+   attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
+   attrs[1] = 2;
+   attrs[2] = EGL_NONE;
+
+   if (!(ctx = calloc(1, sizeof(Context_3D)))) return NULL;
+
+   ctx->context =
+     eglCreateContext(ob->egl_disp, ob->egl_config, ob->egl_context[0], attrs);
+   if (!ctx->context)
+     {
+        ERR("Could not create egl context %#x", eglGetError());
+        goto err;
+     }
+
+   ctx->display = ob->egl_disp;
+   ctx->surface = ob->egl_surface[0];
+
+   return ctx;
+
+err:
+   free(ctx);
+   return NULL;
+}
+
+void
+eng_gl_context_free(Context_3D *ctx)
+{
+   eglDestroyContext(ctx->display, ctx->context);
+   free(ctx);
+}
+
+void
+eng_gl_context_use(Context_3D *ctx)
+{
+   SET_RESTORE_CONTEXT();
+   if (eglMakeCurrent(ctx->display, ctx->surface,
+                      ctx->surface, ctx->context) == EGL_FALSE)
+     {
+        ERR("eglMakeCurrent Failed: %#x", eglGetError());
+     }
+}
diff --git a/src/modules/evas/engines/software_tbm/Evas_Engine_Software_Tbm.h b/src/modules/evas/engines/software_tbm/Evas_Engine_Software_Tbm.h
new file mode 100755 (executable)
index 0000000..01fda78
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _EVAS_ENGINE_SOFTWARE_TBM_H
+# define _EVAS_ENGINE_SOFTWARE_TBM_H
+
+typedef struct _Evas_Engine_Info_Software_Tbm Evas_Engine_Info_Software_Tbm;
+
+struct _Evas_Engine_Info_Software_Tbm
+{
+   /* PRIVATE - don't mess with this baby or evas will poke its tongue out
+    * at you and make nasty noises */
+   Evas_Engine_Info magic;
+
+   /* engine specific data & parameters it needs to set up */
+   struct
+     {
+      int depth, rotation, edges;
+      void *tbm_queue;
+      Eina_Bool ext_tbm_queue;
+      unsigned int destination_alpha : 1;
+     } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
+
+};
+
+#endif
diff --git a/src/modules/evas/engines/software_tbm/evas_engine.c b/src/modules/evas/engines/software_tbm/evas_engine.c
new file mode 100755 (executable)
index 0000000..cdcf89a
--- /dev/null
@@ -0,0 +1,390 @@
+#include "evas_common_private.h"
+#include "evas_private.h"
+#ifdef EVAS_CSERVE2
+# include "evas_cs2_private.h"
+#endif
+
+#include "evas_engine.h"
+#include "../software_generic/evas_native_common.h"
+
+#ifdef HAVE_DLSYM
+# include <dlfcn.h>
+#endif
+
+/* logging domain variable */
+int _evas_engine_software_tbm_log_dom = -1;
+
+/* evas function tables - filled in later (func and parent func) */
+static Evas_Func func, pfunc;
+
+Evas_Native_Tbm_Surface_Image_Set_Call  glsym_evas_native_tbm_surface_image_set = NULL;
+
+/* engine structure data */
+typedef struct _Render_Engine Render_Engine;
+struct _Render_Engine
+{
+   Render_Engine_Software_Generic generic;
+
+   void (*outbuf_reconfigure)(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, Eina_Bool resize);
+};
+
+/* LOCAL FUNCTIONS */
+Render_Engine *
+_render_engine_swapbuf_setup(int w, int h, unsigned int rotation, unsigned int depth, Eina_Bool alpha, void *tbm_queue)
+{
+   Render_Engine *re;
+   Outbuf *ob;
+   Render_Engine_Merge_Mode merge_mode = MERGE_SMART;
+   const char *s;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* try to allocate space for new render engine */
+   if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
+
+   ob = _evas_software_tbm_outbuf_setup(w, h, rotation, depth, alpha, tbm_queue);
+   if (!ob) goto err;
+
+   if (!evas_render_engine_software_generic_init(&re->generic, ob,
+                                                 _evas_software_tbm_outbuf_swap_mode_get,
+                                                 _evas_software_tbm_outbuf_rotation_get,
+                                                 NULL,
+                                                 NULL,
+                                                 _evas_software_tbm_outbuf_update_region_new,
+                                                 _evas_software_tbm_outbuf_update_region_push,
+                                                 _evas_software_tbm_outbuf_update_region_free,
+                                                 _evas_software_tbm_outbuf_idle_flush,
+                                                 _evas_software_tbm_outbuf_flush,
+                                                 _evas_software_tbm_outbuf_free,
+                                                 w, h))
+     goto err;
+
+   re->outbuf_reconfigure = _evas_software_tbm_outbuf_reconfigure;
+
+   s = getenv("EVAS_SOFTWARE_TBM_PARTIAL_MERGE");
+   if (s)
+     {
+        if ((!strcmp(s, "bounding")) || (!strcmp(s, "b")))
+          merge_mode = MERGE_BOUNDING;
+        else if ((!strcmp(s, "full")) || (!strcmp(s, "f")))
+          merge_mode = MERGE_FULL;
+        else if ((!strcmp(s, "smart")) || (!strcmp(s, "s")))
+          merge_mode = MERGE_SMART;
+     }
+
+   evas_render_engine_software_generic_merge_mode_set(&re->generic, merge_mode);
+
+   /* return allocated render engine */
+   return re;
+
+err:
+   if (ob) _evas_software_tbm_outbuf_free(ob);
+   free(re);
+   return NULL;
+}
+
+static void
+_symbols(void)
+{
+   static int done = 0;
+
+   if (done) return;
+
+#define LINK2GENERIC(sym) \
+   glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
+
+   // Get function pointer to native_common that is now provided through the link of SW_Generic.
+   LINK2GENERIC(evas_native_tbm_surface_image_set);
+
+   done = 1;
+}
+
+
+
+/* ENGINE API FUNCTIONS WE PROVIDE */
+static void *
+eng_info(Evas *eo_evas EINA_UNUSED)
+{
+   Evas_Engine_Info_Software_Tbm *einfo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* try to allocate space for new engine info */
+   if (!(einfo = calloc(1, sizeof(Evas_Engine_Info_Software_Tbm))))
+     return NULL;
+
+   /* fill in engine info */
+   einfo->magic.magic = rand();
+   einfo->render_mode = EVAS_RENDER_MODE_BLOCKING;
+
+   /* return allocated engine info */
+   return einfo;
+}
+
+static void
+eng_info_free(Evas *eo_evas EINA_UNUSED, void *info)
+{
+   Evas_Engine_Info_Software_Tbm *einfo;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* try to free previously allocated engine info */
+   if ((einfo = (Evas_Engine_Info_Software_Tbm *)info))
+     free(einfo);
+}
+
+static int
+eng_setup(Evas *eo_evas, void *info)
+{
+   Evas_Engine_Info_Software_Tbm *einfo;
+   Evas_Public_Data *epd;
+   Render_Engine *re = NULL;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+   /* try to cast to our engine info */
+   if (!(einfo = (Evas_Engine_Info_Software_Tbm *)info))
+     return 0;
+
+   /* try to get evas public data */
+   if (!(epd = eo_data_scope_get(eo_evas, EVAS_CANVAS_CLASS)))
+     return 0;
+
+   /* test for valid engine output */
+   if (!(re = epd->engine.data.output))
+     {
+        /* if we have no engine data, assume we have not initialized yet */
+        evas_common_init();
+
+        re = _render_engine_swapbuf_setup(epd->output.w, epd->output.h,
+                                          einfo->info.rotation,
+                                          einfo->info.depth,
+                                          einfo->info.destination_alpha,
+                                          einfo->info.tbm_queue);
+
+        if (re)
+          re->generic.ob->info = einfo;
+        else
+          goto err;
+     }
+   else
+     {
+        Outbuf *ob;
+
+        ob = _evas_software_tbm_outbuf_setup(epd->output.w, epd->output.h,
+                                einfo->info.rotation, einfo->info.depth,
+                                einfo->info.destination_alpha,
+                                einfo->info.tbm_queue);
+        if (ob)
+          {
+             ob->info = einfo;
+             evas_render_engine_software_generic_update(&re->generic, ob,
+                                                        epd->output.w,
+                                                        epd->output.h);
+          }
+     }
+
+   epd->engine.data.output = re;
+   if (!epd->engine.data.output)
+     {
+        ERR("Failed to create Render Engine");
+        goto err;
+     }
+
+   if (!epd->engine.data.context)
+     {
+        epd->engine.data.context =
+          epd->engine.func->context_new(epd->engine.data.output);
+     }
+
+   return 1;
+
+err:
+   evas_common_shutdown();
+   return 0;
+}
+
+static void
+eng_output_free(void *data)
+{
+   Render_Engine *re;
+
+   if ((re = (Render_Engine *)data))
+     {
+        evas_render_engine_software_generic_clean(&re->generic);
+        free(re);
+     }
+
+   evas_common_shutdown();
+}
+
+static void
+eng_output_resize(void *data, int w, int h)
+{
+   Render_Engine *re;
+   Evas_Engine_Info_Software_Tbm *einfo;
+   int dx = 0, dy = 0;
+   Eina_Bool resize = EINA_FALSE;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   if (!(re = (Render_Engine *)data)) return;
+   if (!(einfo = re->generic.ob->info)) return;
+
+   if (einfo->info.edges & 4) // resize from left
+     {
+        if ((einfo->info.rotation == 90) || (einfo->info.rotation == 270))
+          dx = re->generic.ob->h - h;
+        else
+          dx = re->generic.ob->w - w;
+     }
+
+   if (einfo->info.edges & 1) // resize from top
+     {
+        if ((einfo->info.rotation == 90) || (einfo->info.rotation == 270))
+          dy = re->generic.ob->w - w;
+        else
+          dy = re->generic.ob->h - h;
+     }
+
+   if (einfo->info.edges) resize = EINA_TRUE;
+
+   re->outbuf_reconfigure(re->generic.ob, dx, dy, w, h,
+                          einfo->info.rotation, einfo->info.depth,
+                          einfo->info.destination_alpha, resize);
+
+   evas_common_tilebuf_free(re->generic.tb);
+   if ((re->generic.tb = evas_common_tilebuf_new(w, h)))
+     evas_common_tilebuf_set_tile_size(re->generic.tb, TILESIZE, TILESIZE);
+
+   re->generic.w = w;
+   re->generic.h = h;
+}
+
+static void *
+eng_image_native_set(void *data EINA_UNUSED, void *image, void *native)
+{
+   Evas_Native_Surface *ns = native;
+   Image_Entry *ie = image;
+   RGBA_Image *im = image, *im2;
+
+   if (!im || !ns) return im;
+
+   if (ns->type == EVAS_NATIVE_SURFACE_TBM)
+     {
+        if (im->native.data)
+          {
+             //image have native surface already
+             Evas_Native_Surface *ens = im->native.data;
+
+             if ((ens->type == ns->type) &&
+                 (ens->data.tbm.buffer == ns->data.tbm.buffer))
+                return im;
+          }
+      }
+
+   if ((ns->type == EVAS_NATIVE_SURFACE_OPENGL) &&
+       (ns->version == EVAS_NATIVE_SURFACE_VERSION))
+     im2 = evas_cache_image_data(evas_common_image_cache_get(),
+                                 ie->w, ie->h,
+                                 ns->data.x11.visual, 1,
+                                 EVAS_COLORSPACE_ARGB8888);
+   else
+     im2 = evas_cache_image_data(evas_common_image_cache_get(),
+                                 ie->w, ie->h,
+                                 NULL, 1,
+                                 EVAS_COLORSPACE_ARGB8888);
+
+   if (im->native.data)
+      {
+         if (im->native.func.free)
+            im->native.func.free(im->native.func.data, im);
+      }
+
+#ifdef EVAS_CSERVE2
+   if (evas_cserve2_use_get() && evas_cache2_image_cached(ie))
+     evas_cache2_image_close(ie);
+   else
+#endif
+   evas_cache_image_drop(ie);
+   im = im2;
+
+   if (ns->type == EVAS_NATIVE_SURFACE_TBM)
+      return glsym_evas_native_tbm_surface_image_set(NULL, im, ns);
+
+   return im;
+}
+
+static void *
+eng_image_native_get(void *data EINA_UNUSED, void *image)
+{
+   RGBA_Image *im = image;
+   Native *n;
+   if (!im) return NULL;
+   n = im->native.data;
+   if (!n) return NULL;
+   return &(n->ns);
+}
+
+/* EVAS MODULE FUNCTIONS */
+static int
+module_open(Evas_Module *em)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* check for valid evas module */
+   if (!em) return 0;
+
+   /* try to get functions from whatever engine module we inherit from */
+   if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
+
+   /* try to create our logging domain */
+   _evas_engine_software_tbm_log_dom =
+     eina_log_domain_register("evas-software_tbm", EVAS_DEFAULT_LOG_COLOR);
+   if (_evas_engine_software_tbm_log_dom < 0)
+     {
+        EINA_LOG_ERR("Cannot create a module logging domain");
+        return 0;
+     }
+
+   /* copy parent functions */
+   func = pfunc;
+   /* override engine specific functions */
+#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
+   ORD(info);
+   ORD(info_free);
+   ORD(setup);
+   ORD(output_free);
+   ORD(output_resize);
+   ORD(image_native_set);
+   ORD(image_native_get);
+
+   _symbols();
+   /* advertise our own engine functions */
+   em->functions = (void *)(&func);
+
+   return 1;
+}
+
+static void
+module_close(Evas_Module *em EINA_UNUSED)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* unregister logging domain */
+   if (_evas_engine_software_tbm_log_dom > -1)
+     eina_log_domain_unregister(_evas_engine_software_tbm_log_dom);
+
+   /* reset logging domain variable */
+   _evas_engine_software_tbm_log_dom = -1;
+}
+
+static Evas_Module_Api evas_modapi =
+{
+   EVAS_MODULE_API_VERSION, "software_tbm", "none", {module_open, module_close}
+};
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_tbm);
+
+#ifndef EVAS_STATIC_BUILD_SOFTWARE_TBM
+EVAS_EINA_MODULE_DEFINE(engine, software_tbm);
+#endif
diff --git a/src/modules/evas/engines/software_tbm/evas_engine.h b/src/modules/evas/engines/software_tbm/evas_engine.h
new file mode 100755 (executable)
index 0000000..c4d89fb
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef EVAS_ENGINE_H
+# define EVAS_ENGINE_H
+
+# ifdef LOGFNS
+#  include <stdio.h>
+#  define LOGFN(fl, ln, fn) printf("-EVAS-TBM: %25s: %5i - %s\n", fl, ln, fn);
+# else
+#  define LOGFN(fl, ln, fn)
+# endif
+
+extern int _evas_engine_software_tbm_log_dom;
+
+# ifdef ERR
+#  undef ERR
+# endif
+# define ERR(...) EINA_LOG_DOM_ERR(_evas_engine_software_tbm_log_dom, __VA_ARGS__)
+
+# ifdef DBG
+#  undef DBG
+# endif
+# define DBG(...) EINA_LOG_DOM_DBG(_evas_engine_software_tbm_log_dom, __VA_ARGS__)
+
+# ifdef INF
+#  undef INF
+# endif
+# define INF(...) EINA_LOG_DOM_INFO(_evas_engine_software_tbm_log_dom, __VA_ARGS__)
+
+# ifdef WRN
+#  undef WRN
+# endif
+# define WRN(...) EINA_LOG_DOM_WARN(_evas_engine_software_tbm_log_dom, __VA_ARGS__)
+
+# ifdef CRI
+#  undef CRI
+# endif
+# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_software_tbm_log_dom, __VA_ARGS__)
+
+# include <wayland-client.h>
+# include "../software_generic/Evas_Engine_Software_Generic.h"
+# include "Evas_Engine_Software_Tbm.h"
+
+#define TBM_SURF_PLANE_MAX 4 /**< maximum number of the planes  */
+/* option to map the tbm_surface */
+#define TBM_SURF_OPTION_READ      (1 << 0) /**< access option to read  */
+#define TBM_SURF_OPTION_WRITE     (1 << 1) /**< access option to write */
+
+typedef struct _tbm_surface * tbm_surface_h;
+typedef uint32_t tbm_format;
+
+typedef struct _tbm_surface_plane
+{
+    unsigned char *ptr;   /**< Plane pointer */
+    uint32_t size;        /**< Plane size */
+    uint32_t offset;      /**< Plane offset */
+    uint32_t stride;      /**< Plane stride */
+
+    void *reserved1;      /**< Reserved pointer1 */
+    void *reserved2;      /**< Reserved pointer2 */
+    void *reserved3;      /**< Reserved pointer3 */
+} tbm_surface_plane_s;
+
+typedef struct _tbm_surface_info
+{
+    uint32_t width;      /**< TBM surface width */
+    uint32_t height;     /**< TBM surface height */
+    tbm_format format;   /**< TBM surface format*/
+    uint32_t bpp;        /**< TBM surface bbp */
+    uint32_t size;       /**< TBM surface size */
+
+    uint32_t num_planes;                            /**< The number of planes */
+    tbm_surface_plane_s planes[TBM_SURF_PLANE_MAX]; /**< Array of planes */
+
+    void *reserved4;   /**< Reserved pointer4 */
+    void *reserved5;   /**< Reserved pointer5 */
+    void *reserved6;   /**< Reserved pointer6 */
+} tbm_surface_info_s;
+
+/* returns 0 on success */
+
+struct _Outbuf
+{
+   int w, h;
+   int rotation, alpha;
+   Outbuf_Depth depth;
+
+   Evas *evas;
+   Evas_Engine_Info_Software_Tbm *info;
+
+   void *tbm_queue;
+   Eina_Bool ext_tbm_queue;
+
+   tbm_surface_h surface;
+
+   struct
+   {
+      /* one big buffer for updates. flushed on idle_flush */
+      RGBA_Image *onebuf;
+      Eina_Array onebuf_regions;
+
+      /* a list of pending regions to write out */
+      Eina_List *pending_writes;
+
+      /* list of previous frame pending regions to write out */
+      Eina_List *prev_pending_writes;
+
+      /* Eina_Bool redraw : 1; */
+      Eina_Bool destination_alpha : 1;
+   } priv;
+};
+
+
+Outbuf *_evas_software_tbm_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, void *tbm_queue);
+void _evas_software_tbm_outbuf_free(Outbuf *ob);
+void _evas_software_tbm_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
+void _evas_software_tbm_outbuf_idle_flush(Outbuf *ob);
+
+Render_Engine_Swap_Mode _evas_software_tbm_outbuf_swap_mode_get(Outbuf *ob);
+int _evas_software_tbm_outbuf_rotation_get(Outbuf *ob);
+void _evas_software_tbm_outbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, Eina_Bool resize);
+void *_evas_software_tbm_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
+void _evas_software_tbm_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
+void _evas_software_tbm_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
+
+
+
+#endif
diff --git a/src/modules/evas/engines/software_tbm/evas_outbuf.c b/src/modules/evas/engines/software_tbm/evas_outbuf.c
new file mode 100755 (executable)
index 0000000..efaf2aa
--- /dev/null
@@ -0,0 +1,642 @@
+#include "evas_common_private.h"
+#include "evas_private.h"
+#ifdef EVAS_CSERVE2
+# include "evas_cs2_private.h"
+#endif
+#ifdef HAVE_DLSYM
+# include <dlfcn.h>
+#endif
+#include "evas_engine.h"
+
+#define RED_MASK 0xff0000
+#define GREEN_MASK 0x00ff00
+#define BLUE_MASK 0x0000ff
+
+static void *tbm_lib = NULL;
+static int   tbm_ref = 0;
+
+static int (*sym_tbm_surface_map) (tbm_surface_h surface, int opt, tbm_surface_info_s *info) = NULL;
+static int (*sym_tbm_surface_unmap) (tbm_surface_h surface) = NULL;
+static int (*sym_tbm_surface_queue_can_dequeue) (void *tbm_queue, int value) = NULL;
+static int (*sym_tbm_surface_queue_dequeue) (void *tbm_queue, tbm_surface_h *surface) = NULL;
+static int (*sym_tbm_surface_queue_enqueue) (void *tbm_queue, tbm_surface_h surface) = NULL;
+static int (*sym_tbm_surface_get_width) (tbm_surface_h surface) = NULL;
+static int (*sym_tbm_surface_get_height) (tbm_surface_h surface) = NULL;
+
+static Eina_Bool
+tbm_init(void)
+{
+   if (tbm_lib)
+     {
+        tbm_ref++;
+        return EINA_TRUE;
+     }
+
+   const char *tbm_libs[] =
+   {
+      "libtbm.so.1",
+      "libtbm.so.0",
+      NULL,
+   };
+   int i, fail;
+#define SYM(lib, xx)                            \
+  do {                                          \
+       sym_ ## xx = dlsym(lib, #xx);            \
+       if (!(sym_ ## xx)) {                     \
+            ERR("%s", dlerror());               \
+            fail = 1;                           \
+         }                                      \
+    } while (0)
+
+   for (i = 0; tbm_libs[i]; i++)
+     {
+        tbm_lib = dlopen(tbm_libs[i], RTLD_LOCAL | RTLD_LAZY);
+        if (tbm_lib)
+          {
+             fail = 0;
+             SYM(tbm_lib, tbm_surface_map);
+             SYM(tbm_lib, tbm_surface_unmap);
+             SYM(tbm_lib, tbm_surface_queue_can_dequeue);
+             SYM(tbm_lib, tbm_surface_queue_dequeue);
+             SYM(tbm_lib, tbm_surface_queue_enqueue);
+             SYM(tbm_lib, tbm_surface_get_width);
+             SYM(tbm_lib, tbm_surface_get_height);
+             if (fail)
+               {
+                  dlclose(tbm_lib);
+                  tbm_lib = NULL;
+               }
+             else break;
+          }
+     }
+   if (!tbm_lib) return EINA_FALSE;
+
+   tbm_ref++;
+   return EINA_TRUE;
+}
+
+static void
+tbm_shutdown(void)
+{
+   if (tbm_ref > 0)
+     {
+        tbm_ref--;
+
+        if (tbm_ref == 0)
+          {
+             if (tbm_lib)
+               {
+                  dlclose(tbm_lib);
+                  tbm_lib = NULL;
+               }
+          }
+     }
+}
+
+
+Outbuf *
+_evas_software_tbm_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, void *tbm_queue)
+{
+   Outbuf *ob = NULL;
+   char *num;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* try to allocate space for new Outbuf */
+   if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
+
+   if (!tbm_init())
+     {
+        ERR("Could not initialize TBM!");
+        goto setup_err;
+     }
+
+   /* set outbuf properties */
+   ob->w = w;
+   ob->h = h;
+   ob->rotation = rot;
+   ob->depth = depth;
+   ob->priv.destination_alpha = alpha;
+   ob->tbm_queue = tbm_queue;
+   tbm_surface_info_s info;
+
+   eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8);
+
+   return ob;
+
+setup_err:
+   free(ob);
+   return NULL;
+}
+
+void
+_evas_software_tbm_outbuf_free(Outbuf *ob)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   while (ob->priv.pending_writes)
+     {
+        RGBA_Image *img;
+        Eina_Rectangle *rect;
+
+        img = ob->priv.pending_writes->data;
+        ob->priv.pending_writes =
+          eina_list_remove_list(ob->priv.pending_writes, ob->priv.pending_writes);
+
+        rect = img->extended_info;
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          evas_cache2_image_close(&img->cache_entry);
+        else
+#endif
+          evas_cache_image_drop(&img->cache_entry);
+
+        eina_rectangle_free(rect);
+     }
+
+   _evas_software_tbm_outbuf_flush(ob, NULL, EVAS_RENDER_MODE_UNDEF);
+   _evas_software_tbm_outbuf_idle_flush(ob);
+
+   eina_array_flush(&ob->priv.onebuf_regions);
+
+   tbm_shutdown();
+
+   free(ob);
+}
+
+void
+_evas_software_tbm_outbuf_idle_flush(Outbuf *ob)
+{
+   RGBA_Image *img;
+   Eina_Rectangle *rect;
+
+   if (ob->priv.onebuf)
+     {
+        img = ob->priv.onebuf;
+        ob->priv.onebuf = NULL;
+
+        rect = img->extended_info;
+        eina_rectangle_free(rect);
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          evas_cache2_image_close(&img->cache_entry);
+        else
+#endif
+          evas_cache_image_drop(&img->cache_entry);
+     }
+   else
+     {
+        while (ob->priv.prev_pending_writes)
+          {
+             img = ob->priv.prev_pending_writes->data;
+             ob->priv.prev_pending_writes =
+               eina_list_remove_list(ob->priv.prev_pending_writes,
+                                     ob->priv.prev_pending_writes);
+             rect = img->extended_info;
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+
+             eina_rectangle_free(rect);
+          }
+     }
+}
+
+void
+_evas_software_tbm_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
+{
+   Eina_Rectangle *result;
+   RGBA_Image *img;
+   unsigned int n = 0, i = 0;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
+
+   /* check for pending writes */
+   if (!ob->priv.pending_writes)
+     {
+        Eina_Rectangle *rect;
+        Eina_Array_Iterator it;
+
+        /* get number of buffer regions */
+        n = eina_array_count_get(&ob->priv.onebuf_regions);
+        if (n == 0) return;
+
+        /* allocate rectangles */
+        if (!(result = alloca(n * sizeof(Eina_Rectangle)))) return;
+
+        /* loop the buffer regions and assign to result */
+        EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
+          {
+             result[i] = *rect;
+             eina_rectangle_free(rect);
+          }
+
+        sym_tbm_surface_unmap(ob->surface);
+
+        /* clean array */
+        eina_array_clean(&ob->priv.onebuf_regions);
+
+        img = ob->priv.onebuf;
+        ob->priv.onebuf = NULL;
+        if (img)
+          {
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+          }
+     }
+   else
+     {
+        /* get number of pending writes */
+        n = eina_list_count(ob->priv.pending_writes);
+        if (n == 0) return;
+
+        /* allocate rectangles */
+        if (!(result = alloca(n * sizeof(Eina_Rectangle)))) return;
+
+        /* loop the pending writes */
+        EINA_LIST_FREE(ob->priv.pending_writes, img)
+          {
+             Eina_Rectangle *rect;
+             int x = 0, y = 0, w = 0, h = 0;
+
+             if (!(rect = img->extended_info)) continue;
+
+             x = rect->x; y = rect->y; w = rect->w; h = rect->h;
+
+             /* based on rotation, set rectangle position */
+             if (ob->rotation == 0)
+               {
+                  result[i].x = x;
+                  result[i].y = y;
+               }
+             else if (ob->rotation == 90)
+               {
+                  result[i].x = y;
+                  result[i].y = (ob->w - x - w);
+               }
+             else if (ob->rotation == 180)
+               {
+                  result[i].x = (ob->w - x - w);
+                  result[i].y = (ob->h - y - h);
+               }
+             else if (ob->rotation == 270)
+               {
+                  result[i].x = (ob->h - y - h);
+                  result[i].y = x;
+               }
+
+             /* based on rotation, set rectangle size */
+             if ((ob->rotation == 0) || (ob->rotation == 180))
+               {
+                  result[i].w = w;
+                  result[i].h = h;
+               }
+             else if ((ob->rotation == 90) || (ob->rotation == 270))
+               {
+                  result[i].w = h;
+                  result[i].h = w;
+               }
+
+             eina_rectangle_free(rect);
+
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+
+             i++;
+          }
+
+        sym_tbm_surface_unmap(ob->surface);
+     }
+   sym_tbm_surface_queue_enqueue(ob->tbm_queue, ob->surface);
+}
+
+Render_Engine_Swap_Mode
+_evas_software_tbm_outbuf_swap_mode_get(Outbuf *ob)
+{
+   /* TODO: implement if we need buffer age */
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   return MODE_FULL;
+}
+
+int
+_evas_software_tbm_outbuf_rotation_get(Outbuf *ob)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   return ob->rotation;
+}
+
+void
+_evas_software_tbm_outbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, Eina_Bool resize)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   if ((depth == OUTBUF_DEPTH_NONE) ||
+       (depth == OUTBUF_DEPTH_INHERIT))
+     depth = ob->depth;
+
+   if ((ob->w == w) && (ob->h == h) &&
+       (ob->rotation == rot) && (ob->depth == depth) &&
+       (ob->priv.destination_alpha == alpha))
+     return;
+
+   ob->w = w;
+   ob->h = h;
+   ob->rotation = rot;
+   ob->depth = depth;
+   ob->priv.destination_alpha = alpha;
+
+   _evas_software_tbm_outbuf_idle_flush(ob);
+}
+
+void *
+_evas_software_tbm_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
+{
+   RGBA_Image *img;
+   Eina_Rectangle *rect;
+   tbm_surface_info_s info;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h);
+   if ((w <= 0) || (h <= 0)) return NULL;
+
+   if (ob->rotation == 0)
+     {
+        if (!(img = ob->priv.onebuf))
+          {
+             int bw = 0, bh = 0;
+             void *data = NULL;
+
+             if (sym_tbm_surface_queue_can_dequeue(ob->tbm_queue, 1))
+                {
+                   sym_tbm_surface_queue_dequeue(ob->tbm_queue, &ob->surface);
+                   sym_tbm_surface_map(ob->surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
+                   data = info.planes[0].ptr;
+                   if (!data)
+                      {
+                         ERR("Could not get surface data");
+                         return NULL;
+                      }
+                   bw = sym_tbm_surface_get_width(ob->surface);
+                   bh = sym_tbm_surface_get_height(ob->surface);
+                }
+             else {
+                   ERR("sym_tbm_surface_queue_can_dequeue fail");
+                   return NULL;
+             }
+
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               {
+                  img = (RGBA_Image *)
+                    evas_cache2_image_data(evas_common_image_cache2_get(),
+                                           bw, bh, data,
+                                           ob->priv.destination_alpha,
+                                           EVAS_COLORSPACE_ARGB8888);
+               }
+             else
+#endif
+               {
+                  img = (RGBA_Image *)
+                    evas_cache_image_data(evas_common_image_cache_get(),
+                                          bw, bh, data,
+                                          ob->priv.destination_alpha,
+                                          EVAS_COLORSPACE_ARGB8888);
+
+               }
+
+             ob->priv.onebuf = img;
+             if (!img) return NULL;
+          }
+
+        if (!(rect = eina_rectangle_new(x, y, w, h)))
+          return NULL;
+
+        if (!eina_array_push(&ob->priv.onebuf_regions, rect))
+          {
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+
+             eina_rectangle_free(rect);
+             return NULL;
+          }
+
+        if (cx) *cx = x;
+        if (cy) *cy = y;
+        if (cw) *cw = w;
+        if (ch) *ch = h;
+
+        img->extended_info = rect;
+
+        return img;
+     }
+   else
+     {
+        if (!(rect = eina_rectangle_new(x, y, w, h)))
+          return NULL;
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          img = (RGBA_Image *)evas_cache2_image_empty(evas_common_image_cache2_get());
+        else
+#endif
+          img = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
+
+        if (!img)
+          {
+             eina_rectangle_free(rect);
+             return NULL;
+          }
+
+        img->cache_entry.w = w;
+        img->cache_entry.h = h;
+        img->cache_entry.flags.alpha |= ob->priv.destination_alpha ? 1 : 0;
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          evas_cache2_image_surface_alloc(&img->cache_entry, w, h);
+        else
+#endif
+          evas_cache_image_surface_alloc(&img->cache_entry, w, h);
+
+        img->extended_info = rect;
+
+        ob->priv.pending_writes =
+          eina_list_append(ob->priv.pending_writes, img);
+
+        if (cx) *cx = 0;
+        if (cy) *cy = 0;
+        if (cw) *cw = w;
+        if (ch) *ch = h;
+        return img;
+     }
+
+   return NULL;
+}
+
+void
+_evas_software_tbm_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h)
+{
+   Gfx_Func_Convert func = NULL;
+   Eina_Rectangle rect = {0, 0, 0, 0}, pr;
+   DATA32 *src;
+   DATA8 *dst;
+   int depth = 32, bpp = 0, bpl = 0, wid = 0;
+   int ww = 0, hh = 0;
+   int rx = 0, ry = 0;
+   tbm_surface_info_s info;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   /* check for valid output buffer */
+   if (!ob) return;
+
+   /* check for pending writes */
+   if (!ob->priv.pending_writes) return;
+
+   if ((ob->rotation == 0) || (ob->rotation == 180))
+     {
+        func =
+          evas_common_convert_func_get(0, w, h, depth,
+                                       RED_MASK, GREEN_MASK, BLUE_MASK,
+                                       PAL_MODE_NONE, ob->rotation);
+     }
+   else if ((ob->rotation == 90) || (ob->rotation == 270))
+     {
+        func =
+          evas_common_convert_func_get(0, h, w, depth,
+                                       RED_MASK, GREEN_MASK, BLUE_MASK,
+                                       PAL_MODE_NONE, ob->rotation);
+     }
+
+   /* make sure we have a valid convert function */
+   if (!func) return;
+
+   /* based on rotation, set rectangle position */
+   if (ob->rotation == 0)
+     {
+        rect.x = x;
+        rect.y = y;
+     }
+   else if (ob->rotation == 90)
+     {
+        rect.x = y;
+        rect.y = (ob->w - x - w);
+     }
+   else if (ob->rotation == 180)
+     {
+        rect.x = (ob->w - x - w);
+        rect.y = (ob->h - y - h);
+     }
+   else if (ob->rotation == 270)
+     {
+        rect.x = (ob->h - y - h);
+        rect.y = x;
+     }
+
+   /* based on rotation, set rectangle size */
+   if ((ob->rotation == 0) || (ob->rotation == 180))
+     {
+        rect.w = w;
+        rect.h = h;
+     }
+   else if ((ob->rotation == 90) || (ob->rotation == 270))
+     {
+        rect.w = h;
+        rect.h = w;
+     }
+
+   /* check for valid update image data */
+   if (!(src = update->image.data)) return;
+
+   bpp = depth / 8;
+   if (bpp <= 0) return;
+
+   /* check for valid desination data */
+   if (sym_tbm_surface_queue_can_dequeue(ob->tbm_queue, 1))
+      {
+         sym_tbm_surface_queue_dequeue(ob->tbm_queue, &ob->surface);
+         sym_tbm_surface_map(ob->surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
+         dst = info.planes[0].ptr;
+         if (!dst)
+            {
+               ERR("Could not get surface data");
+               return;
+            }
+      }
+   else {
+         ERR("sym_tbm_surface_queue_can_dequeue fail");
+         return;
+   }
+
+
+   bpl = (ww * sizeof(int));
+
+   if (ob->rotation == 0)
+     {
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
+        dst += (bpl * rect.y) + (rect.x * bpp);
+        w -= rx;
+     }
+   else if (ob->rotation == 180)
+     {
+        pr = rect;
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
+        rx = pr.w - rect.w;
+        ry = pr.h - rect.h;
+        src += (update->cache_entry.w * ry) + rx;
+        w -= rx;
+     }
+   else if (ob->rotation == 90)
+     {
+        pr = rect;
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
+        rx = pr.w - rect.w; ry = pr.h - rect.h;
+        src += ry;
+        w -= ry;
+     }
+   else if (ob->rotation == 270)
+     {
+        pr = rect;
+        RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 0, 0, ww, hh);
+        rx = pr.w - rect.w; ry = pr.h - rect.h;
+        src += (update->cache_entry.w * rx);
+        w -= ry;
+     }
+
+   if ((rect.w <= 0) || (rect.h <= 0)) return;
+
+   wid = bpl / bpp;
+
+   dst += (bpl * rect.y) + (rect.x * bpp);
+
+   func(src, dst, (update->cache_entry.w - w), (wid - rect.w),
+        rect.w, rect.h, x + rx, y + ry, NULL);
+}
+
+void
+_evas_software_tbm_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+}
index 5041421..943189a 100755 (executable)
@@ -189,7 +189,7 @@ gl_symbols(void)
            glsym_func_uint);
    FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage",
            glsym_func_uint);
-   FINDSYM(glsym_eglSetDamageRegionKHR, "eglSetDamageRegionKHR", 
+   FINDSYM(glsym_eglSetDamageRegionKHR, "eglSetDamageRegionKHR",
            glsym_func_uint);
 
    FINDSYM(glsym_eglQueryWaylandBufferWL, "eglQueryWaylandBufferWL",
@@ -1761,7 +1761,6 @@ module_open(Evas_Module *em)
 
    /* store functions for later use */
    func = pfunc;
-
 #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
 
    ORD(info);
old mode 100644 (file)
new mode 100755 (executable)
index 7226b1a..27c62ca
@@ -119,7 +119,7 @@ eng_info(Evas *eo_evas EINA_UNUSED)
    return einfo;
 }
 
-static void 
+static void
 eng_info_free(Evas *eo_evas EINA_UNUSED, void *info)
 {
    Evas_Engine_Info_Wayland_Shm *einfo;
@@ -131,7 +131,7 @@ eng_info_free(Evas *eo_evas EINA_UNUSED, void *info)
      free(einfo);
 }
 
-static int 
+static int
 eng_setup(Evas *eo_evas, void *info)
 {
    Evas_Engine_Info_Wayland_Shm *einfo;
@@ -139,7 +139,6 @@ eng_setup(Evas *eo_evas, void *info)
    Render_Engine *re = NULL;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
    /* try to cast to our engine info */
    if (!(einfo = (Evas_Engine_Info_Wayland_Shm *)info))
      return 0;
@@ -194,7 +193,7 @@ eng_setup(Evas *eo_evas, void *info)
 
    if (!epd->engine.data.context)
      {
-        epd->engine.data.context = 
+        epd->engine.data.context =
           epd->engine.func->context_new(epd->engine.data.output);
      }
 
@@ -205,7 +204,7 @@ err:
    return 0;
 }
 
-static void 
+static void
 eng_output_free(void *data)
 {
    Render_Engine *re;
@@ -219,7 +218,7 @@ eng_output_free(void *data)
    evas_common_shutdown();
 }
 
-static void 
+static void
 eng_output_resize(void *data, int w, int h)
 {
    Render_Engine *re;
@@ -250,8 +249,8 @@ eng_output_resize(void *data, int w, int h)
 
    if (einfo->info.edges) resize = EINA_TRUE;
 
-   re->outbuf_reconfigure(re->generic.ob, dx, dy, w, h, 
-                          einfo->info.rotation, einfo->info.depth, 
+   re->outbuf_reconfigure(re->generic.ob, dx, dy, w, h,
+                          einfo->info.rotation, einfo->info.depth,
                           einfo->info.destination_alpha, resize);
 
    evas_common_tilebuf_free(re->generic.tb);
@@ -328,7 +327,7 @@ eng_image_native_get(void *data EINA_UNUSED, void *image)
 }
 
 /* EVAS MODULE FUNCTIONS */
-static int 
+static int
 module_open(Evas_Module *em)
 {
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
@@ -340,7 +339,7 @@ module_open(Evas_Module *em)
    if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
 
    /* try to create our logging domain */
-   _evas_engine_way_shm_log_dom = 
+   _evas_engine_way_shm_log_dom =
      eina_log_domain_register("evas-wayland_shm", EVAS_DEFAULT_LOG_COLOR);
    if (_evas_engine_way_shm_log_dom < 0)
      {
@@ -350,7 +349,6 @@ module_open(Evas_Module *em)
 
    /* copy parent functions */
    func = pfunc;
-
    /* override engine specific functions */
 #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
    ORD(info);
@@ -368,7 +366,7 @@ module_open(Evas_Module *em)
    return 1;
 }
 
-static void 
+static void
 module_close(Evas_Module *em EINA_UNUSED)
 {
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
@@ -381,7 +379,7 @@ module_close(Evas_Module *em EINA_UNUSED)
    _evas_engine_way_shm_log_dom = -1;
 }
 
-static Evas_Module_Api evas_modapi = 
+static Evas_Module_Api evas_modapi =
 {
    EVAS_MODULE_API_VERSION, "wayland_shm", "none", {module_open, module_close}
 };