],
[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)
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
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
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"
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}"
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" || \
])
+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
--with-opengl=es \
--disable-rpath \
--disable-ibus \
+ --enable-tbm \
%endif
%if %{with x}
--with-opengl=es \
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 \
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\" \
@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@ \
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@
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
#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
{
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
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
#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;
}
#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 */
#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}
};
#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"))
{
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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
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");
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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());
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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__);
+}
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",
/* store functions for later use */
func = pfunc;
-
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
ORD(info);
return einfo;
}
-static void
+static void
eng_info_free(Evas *eo_evas EINA_UNUSED, void *info)
{
Evas_Engine_Info_Wayland_Shm *einfo;
free(einfo);
}
-static int
+static int
eng_setup(Evas *eo_evas, void *info)
{
Evas_Engine_Info_Wayland_Shm *einfo;
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;
if (!epd->engine.data.context)
{
- epd->engine.data.context =
+ epd->engine.data.context =
epd->engine.func->context_new(epd->engine.data.output);
}
return 0;
}
-static void
+static void
eng_output_free(void *data)
{
Render_Engine *re;
evas_common_shutdown();
}
-static void
+static void
eng_output_resize(void *data, int w, int h)
{
Render_Engine *re;
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);
}
/* EVAS MODULE FUNCTIONS */
-static int
+static int
module_open(Evas_Module *em)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
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)
{
/* copy parent functions */
func = pfunc;
-
/* override engine specific functions */
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
ORD(info);
return 1;
}
-static void
+static void
module_close(Evas_Module *em EINA_UNUSED)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
_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}
};