summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMun, Gwan-gyeong <kk.moon@samsung.com>2014-08-21 11:22:16 +0200
committerCedric BAIL <cedric@osg.samsung.com>2014-08-21 12:04:53 +0200
commitf5b81093978fbbe411f9fb509617b6f4081f8da8 (patch)
tree7c6ad1c9bea56711ce23467bcd95c2b5168b3af1
parent23892343cce3b561e98dd050821cad0bed1ce887 (diff)
evas: add evas gl-drm engine
Summary: This is the first step to introduce a gl-drm backend. Test Plan: "ecore evas" create with ecore_evas_gl_drm_new(). It creates "ecore evas" with gl_drm evas backend. @feature Reviewers: raster, Hermet, cedric, devilhorns Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D1187 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--configure.ac23
-rw-r--r--m4/evas_check_engine.m439
-rw-r--r--src/Makefile_Ecore_Evas.am4
-rw-r--r--src/Makefile_Evas.am35
-rw-r--r--src/lib/ecore_evas/Ecore_Evas.h5
-rw-r--r--src/lib/ecore_evas/ecore_evas.c36
-rw-r--r--src/modules/ecore_evas/engines/drm/ecore_evas_drm.c266
-rw-r--r--src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h44
-rw-r--r--src/modules/evas/engines/gl_drm/evas_drm.c602
-rw-r--r--src/modules/evas/engines/gl_drm/evas_drm_main.c638
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.c1015
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.h190
12 files changed, 2841 insertions, 56 deletions
diff --git a/configure.ac b/configure.ac
index f85074daff..dbd24ccbc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1335,6 +1335,17 @@ AC_ARG_ENABLE([drm-hw-accel],
1335 [want_drm_hw_accel="no"]) 1335 [want_drm_hw_accel="no"])
1336 1336
1337 1337
1338AC_ARG_ENABLE([gl-drm],
1339 [AC_HELP_STRING([--enable-gl-drm],
1340 [enable gl drm engine. @<:@default=disabled@:>@])],
1341 [
1342 if test "x${enableval}" = "xyes" ; then
1343 want_gl_drm="yes"
1344 else
1345 want_gl_drm="no"
1346 fi
1347 ],
1348 [want_gl_drm="no"])
1338# Fontconfig 1349# Fontconfig
1339AC_ARG_ENABLE([fontconfig], 1350AC_ARG_ENABLE([fontconfig],
1340 [AS_HELP_STRING([--disable-fontconfig],[disable fontconfig for finding fonts. @<:@default=enabled@:>@])], 1351 [AS_HELP_STRING([--disable-fontconfig],[disable fontconfig for finding fonts. @<:@default=enabled@:>@])],
@@ -1622,6 +1633,7 @@ EVAS_CHECK_ENGINE([software-ddraw], [${want_evas_engine_software_ddraw}], [no],
1622EVAS_CHECK_ENGINE([wayland-egl], [${want_evas_engine_wayland_egl}], [no], [Wayland Egl]) 1633EVAS_CHECK_ENGINE([wayland-egl], [${want_evas_engine_wayland_egl}], [no], [Wayland Egl])
1623EVAS_CHECK_ENGINE([wayland-shm], [${want_wayland}], [no], [Wayland Shm]) 1634EVAS_CHECK_ENGINE([wayland-shm], [${want_wayland}], [no], [Wayland Shm])
1624EVAS_CHECK_ENGINE([drm], [${want_drm}], [no], [Drm]) 1635EVAS_CHECK_ENGINE([drm], [${want_drm}], [no], [Drm])
1636EVAS_CHECK_ENGINE([gl-drm], [${want_gl_drm}], [no], [OpenGL Drm])
1625 1637
1626 1638
1627# Software XCB 1639# Software XCB
@@ -1755,6 +1767,7 @@ if test "x$have_evas_engine_gl_xlib" = "xyes" || \
1755 test "x$have_evas_engine_gl_xcb" = "xyes" || \ 1767 test "x$have_evas_engine_gl_xcb" = "xyes" || \
1756 test "x$have_evas_engine_gl_sdl" = "xyes" || \ 1768 test "x$have_evas_engine_gl_sdl" = "xyes" || \
1757 test "x$have_evas_engine_gl_cocoa" = "xyes" || \ 1769 test "x$have_evas_engine_gl_cocoa" = "xyes" || \
1770 test "x$have_evas_engine_gl_drm" = "xyes" || \
1758 test "x$have_evas_engine_wayland_egl" = "xyes"; then 1771 test "x$have_evas_engine_wayland_egl" = "xyes"; then
1759 have_evas_engine_gl_common="yes" 1772 have_evas_engine_gl_common="yes"
1760fi 1773fi
@@ -1762,6 +1775,7 @@ if test "x$have_evas_engine_gl_xlib" = "xstatic" || \
1762 test "x$have_evas_engine_gl_xcb" = "xstatic" || \ 1775 test "x$have_evas_engine_gl_xcb" = "xstatic" || \
1763 test "x$have_evas_engine_gl_sdl" = "xstatic" || \ 1776 test "x$have_evas_engine_gl_sdl" = "xstatic" || \
1764 test "x$have_evas_engine_gl_cocoa" = "xstatic" || \ 1777 test "x$have_evas_engine_gl_cocoa" = "xstatic" || \
1778 test "x$have_evas_engine_gl_drm" = "xstatic" || \
1765 test "x$have_evas_engine_wayland_egl" = "xstatic"; then 1779 test "x$have_evas_engine_wayland_egl" = "xstatic"; then
1766 have_evas_engine_gl_common="yes" 1780 have_evas_engine_gl_common="yes"
1767 have_static_evas_engine_gl_common="yes" 1781 have_static_evas_engine_gl_common="yes"
@@ -2813,7 +2827,7 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [ecore-input])
2813EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eo]) 2827EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eo])
2814EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eina]) 2828EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eina])
2815 2829
2816EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libudev >= 148 libdrm >= 2.4 xkbcommon >= 0.3.0 libsystemd-login >= 192 dbus-1]) 2830EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libudev >= 148 libdrm >= 2.4 xkbcommon >= 0.3.0 libsystemd-login >= 192 dbus-1 gbm])
2817 2831
2818EFL_EVAL_PKGS([ECORE_DRM]) 2832EFL_EVAL_PKGS([ECORE_DRM])
2819 2833
@@ -3623,8 +3637,9 @@ ECORE_EVAS_MODULE([extn], [${want_ecore_evas_extn}])
3623ECORE_EVAS_MODULE([ews], [yes]) 3637ECORE_EVAS_MODULE([ews], [yes])
3624ECORE_EVAS_MODULE([fb], [${want_fb}]) 3638ECORE_EVAS_MODULE([fb], [${want_fb}])
3625ECORE_EVAS_MODULE([drm], [${want_drm}], 3639ECORE_EVAS_MODULE([drm], [${want_drm}],
3626 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm])] 3640 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm],[gbm])])
3627) 3641ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}],
3642 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm],[gbm])])
3628ECORE_EVAS_MODULE([psl1ght], [${have_ps3}]) 3643ECORE_EVAS_MODULE([psl1ght], [${have_ps3}])
3629 3644
3630ECORE_EVAS_MODULE([opengl-cocoa], [${want_ecore_evas_gl_cocoa}]) 3645ECORE_EVAS_MODULE([opengl-cocoa], [${want_ecore_evas_gl_cocoa}])
@@ -3731,6 +3746,8 @@ if test "x$have_ecore_evas_software_x11" = "xyes" || \
3731fi 3746fi
3732AM_CONDITIONAL([BUILD_ECORE_EVAS_X11], [test "${build_ecore_evas_x11}" = "yes"]) 3747AM_CONDITIONAL([BUILD_ECORE_EVAS_X11], [test "${build_ecore_evas_x11}" = "yes"])
3733 3748
3749AC_DEFINE([BUILD_ECORE_EVAS_OPENGL_DRM], [1], [Build support for DRM based OpenGL])
3750
3734EFL_EVAL_PKGS([ECORE_EVAS]) 3751EFL_EVAL_PKGS([ECORE_EVAS])
3735 3752
3736### Checks for header files 3753### Checks for header files
diff --git a/m4/evas_check_engine.m4 b/m4/evas_check_engine.m4
index fd29393096..6b2ca60335 100644
--- a/m4/evas_check_engine.m4
+++ b/m4/evas_check_engine.m4
@@ -641,6 +641,45 @@ AS_IF([test "x${have_dep}" = "xyes"], [$4], [$5])
641 641
642]) 642])
643 643
644dnl use: EVAS_CHECK_ENGINE_DEP_GL_DRM(engine, simple, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
645
646AC_DEFUN([EVAS_CHECK_ENGINE_DEP_GL_DRM],
647[
648
649requirement=""
650have_dep="no"
651have_hw_dep="no"
652evas_engine_[]$1[]_cflags=""
653evas_engine_[]$1[]_libs=""
654
655gl_library="glesv2"
656
657PKG_CHECK_EXISTS([egl >= 7.10 ${gl_library} gbm],
658 [
659 have_dep="yes"
660 requirement="egl >= 7.10 ${gl_library} gbm"
661 ],
662 [have_dep="no"])
663
664if test "x${have_dep}" = "xyes" ; then
665 if test "x$3" = "xstatic" ; then
666 requirements_pc_evas="${requirement} ${requirements_pc_evas}"
667 requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}"
668 else
669 PKG_CHECK_MODULES([GL_DRM], [${requirement}])
670 evas_engine_[]$1[]_cflags="${GL_DRM_CFLAGS}"
671 evas_engine_[]$1[]_libs="${GL_DRM_LIBS}"
672 evas_engine_gl_common_libs="$evas_engine_[]$1[]_libdirs -lGLESv2 -lm -lEGL"
673 fi
674fi
675
676AC_SUBST([evas_engine_$1_cflags])
677AC_SUBST([evas_engine_$1_libs])
678
679AS_IF([test "x${have_dep}" = "xyes"], [$4], [$5])
680
681])
682
644 683
645dnl use: EVAS_ENGINE(name, want_engine, [DEPENDENCY-CHECK-CODE]) 684dnl use: EVAS_ENGINE(name, want_engine, [DEPENDENCY-CHECK-CODE])
646dnl 685dnl
diff --git a/src/Makefile_Ecore_Evas.am b/src/Makefile_Ecore_Evas.am
index 236cae1666..b1c8cd0161 100644
--- a/src/Makefile_Ecore_Evas.am
+++ b/src/Makefile_Ecore_Evas.am
@@ -213,7 +213,9 @@ ecoreevasenginedrmpkg_LTLIBRARIES = modules/ecore_evas/engines/drm/module.la
213modules_ecore_evas_engines_drm_module_la_SOURCES = $(DRMSOURCES) 213modules_ecore_evas_engines_drm_module_la_SOURCES = $(DRMSOURCES)
214modules_ecore_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 214modules_ecore_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
215@ECORE_EVAS_CFLAGS@ \ 215@ECORE_EVAS_CFLAGS@ \
216-I$(top_srcdir)/src/modules/evas/engines/drm 216@ECORE_DRM_CFLAGS@ \
217-I$(top_srcdir)/src/modules/evas/engines/drm \
218-I$(top_srcdir)/src/modules/evas/engines/gl_drm
217modules_ecore_evas_engines_drm_module_la_LIBADD = @USE_ECORE_EVAS_LIBS@ 219modules_ecore_evas_engines_drm_module_la_LIBADD = @USE_ECORE_EVAS_LIBS@
218modules_ecore_evas_engines_drm_module_la_DEPENDENCIES = @USE_ECORE_EVAS_INTERNAL_LIBS@ 220modules_ecore_evas_engines_drm_module_la_DEPENDENCIES = @USE_ECORE_EVAS_INTERNAL_LIBS@
219modules_ecore_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ 221modules_ecore_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index ceb5f6c9d2..f370b74e64 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -886,6 +886,9 @@ endif
886if BUILD_ENGINE_WAYLAND_EGL 886if BUILD_ENGINE_WAYLAND_EGL
887modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_wayland_egl_cflags@ 887modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_wayland_egl_cflags@
888endif 888endif
889if BUILD_ENGINE_GL_DRM
890modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_gl_drm_cflags@
891endif
889modules_evas_engines_gl_common_libevas_engine_gl_common_la_LIBADD = @USE_EVAS_LIBS@ 892modules_evas_engines_gl_common_libevas_engine_gl_common_la_LIBADD = @USE_EVAS_LIBS@
890modules_evas_engines_gl_common_libevas_engine_gl_common_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ 893modules_evas_engines_gl_common_libevas_engine_gl_common_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@
891modules_evas_engines_gl_common_libevas_engine_gl_common_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ 894modules_evas_engines_gl_common_libevas_engine_gl_common_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
@@ -1239,6 +1242,38 @@ modules_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
1239endif 1242endif
1240endif 1243endif
1241 1244
1245if BUILD_ENGINE_GL_DRM
1246dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
1247GL_DRM_SOURCES = \
1248modules/evas/engines/gl_drm/evas_drm.c \
1249modules/evas/engines/gl_drm/evas_drm_main.c \
1250modules/evas/engines/gl_drm/evas_engine.c \
1251modules/evas/engines/gl_drm/evas_engine.h \
1252modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
1253if EVAS_STATIC_BUILD_GL_DRM
1254lib_evas_libevas_la_SOURCES += $(GL_DRM_SOURCES)
1255lib_evas_libevas_la_CPPFLAGS += @evas_engine_gl_drm_cflags@
1256lib_evas_libevas_la_LIBADD += @evas_engine_gl_drm_libs@
1257else
1258enginegl_drmpkgdir = $(libdir)/evas/modules/engines/gl_drm/$(MODULE_ARCH)
1259enginegl_drmpkg_LTLIBRARIES = modules/evas/engines/gl_drm/module.la
1260modules_evas_engines_gl_drm_module_la_SOURCES = $(GL_DRM_SOURCES)
1261modules_evas_engines_gl_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1262-I$(top_srcdir)/src/lib/evas/include \
1263-I$(top_srcdir)/src/lib/evas/cserve2 \
1264-I$(top_srcdir)/src/modules/evas/engines/gl_drm \
1265@EVAS_CFLAGS@ \
1266@ECORE_DRM_CFLAGS@ \
1267@evas_engine_gl_drm_cflags@
1268modules_evas_engines_gl_drm_module_la_LIBADD = \
1269@USE_EVAS_LIBS@ \
1270@USE_ECORE_DRM_LIBS@ \
1271@evas_engine_gl_drm_libs@
1272modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@
1273modules_evas_engines_gl_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
1274modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
1275endif
1276endif
1242 1277
1243### Cserve2 binary 1278### Cserve2 binary
1244 1279
diff --git a/src/lib/ecore_evas/Ecore_Evas.h b/src/lib/ecore_evas/Ecore_Evas.h
index c70dff3d59..4c97211c56 100644
--- a/src/lib/ecore_evas/Ecore_Evas.h
+++ b/src/lib/ecore_evas/Ecore_Evas.h
@@ -103,6 +103,7 @@ extern "C" {
103#define HAVE_ECORE_EVAS_WAYLAND_SHM 1 103#define HAVE_ECORE_EVAS_WAYLAND_SHM 1
104#define HAVE_ECORE_EVAS_WAYLAND_EGL 1 104#define HAVE_ECORE_EVAS_WAYLAND_EGL 1
105#define HAVE_ECORE_EVAS_DRM 1 105#define HAVE_ECORE_EVAS_DRM 1
106#define HAVE_ECORE_EVAS_DRM_GL 1
106 107
107typedef enum _Ecore_Evas_Engine_Type 108typedef enum _Ecore_Evas_Engine_Type
108{ 109{
@@ -129,7 +130,8 @@ typedef enum _Ecore_Evas_Engine_Type
129 ECORE_EVAS_ENGINE_PSL1GHT, 130 ECORE_EVAS_ENGINE_PSL1GHT,
130 ECORE_EVAS_ENGINE_WAYLAND_SHM, 131 ECORE_EVAS_ENGINE_WAYLAND_SHM,
131 ECORE_EVAS_ENGINE_WAYLAND_EGL, 132 ECORE_EVAS_ENGINE_WAYLAND_EGL,
132 ECORE_EVAS_ENGINE_DRM 133 ECORE_EVAS_ENGINE_DRM,
134 ECORE_EVAS_ENGINE_OPENGL_DRM
133} Ecore_Evas_Engine_Type; 135} Ecore_Evas_Engine_Type;
134 136
135typedef enum _Ecore_Evas_Avoid_Damage_Type 137typedef enum _Ecore_Evas_Avoid_Damage_Type
@@ -1190,6 +1192,7 @@ EAPI void ecore_evas_wayland_type_set(Ecore_Evas *ee, int type);
1190EAPI Ecore_Wl_Window *ecore_evas_wayland_window_get(const Ecore_Evas *ee); 1192EAPI Ecore_Wl_Window *ecore_evas_wayland_window_get(const Ecore_Evas *ee);
1191 1193
1192EAPI Ecore_Evas *ecore_evas_drm_new(const char *device, unsigned int parent, int x, int y, int w, int h); 1194EAPI Ecore_Evas *ecore_evas_drm_new(const char *device, unsigned int parent, int x, int y, int w, int h);
1195EAPI Ecore_Evas *ecore_evas_gl_drm_new(const char *device, unsigned int parent, int x, int y, int w, int h);
1193 1196
1194/** 1197/**
1195 * @brief Create a new @c Ecore_Evas canvas bound to the Evas 1198 * @brief Create a new @c Ecore_Evas canvas bound to the Evas
diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c
index c5be4aa9fa..16966f8d57 100644
--- a/src/lib/ecore_evas/ecore_evas.c
+++ b/src/lib/ecore_evas/ecore_evas.c
@@ -327,6 +327,12 @@ ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine)
327#else 327#else
328 return EINA_FALSE; 328 return EINA_FALSE;
329#endif 329#endif
330 case ECORE_EVAS_ENGINE_OPENGL_DRM:
331#ifdef BUILD_ECORE_EVAS_OPENGL_DRM
332 return EINA_TRUE;
333#else
334 return EINA_FALSE;
335#endif
330 336
331 default: 337 default:
332 return EINA_FALSE; 338 return EINA_FALSE;
@@ -696,6 +702,21 @@ _ecore_evas_constructor_drm(int x, int y, int w, int h, const char *extra_option
696} 702}
697 703
698static Ecore_Evas * 704static Ecore_Evas *
705_ecore_evas_constructor_opengl_drm(int x, int y, int w, int h, const char *extra_options)
706{
707 char *device = NULL;
708 unsigned int parent = 0;
709 Ecore_Evas *ee;
710
711 _ecore_evas_parse_extra_options_str(extra_options, "device=", &device);
712 _ecore_evas_parse_extra_options_uint(extra_options, "parent=", &parent);
713 ee = ecore_evas_gl_drm_new(device, parent, x, y, w, h);
714 free(device);
715
716 return ee;
717}
718
719static Ecore_Evas *
699_ecore_evas_constructor_software_gdi(int x, int y, int w, int h, 720_ecore_evas_constructor_software_gdi(int x, int y, int w, int h,
700 const char *extra_options EINA_UNUSED) 721 const char *extra_options EINA_UNUSED)
701{ 722{
@@ -752,6 +773,7 @@ static const struct ecore_evas_engine _engines[] = {
752 {"wayland_shm", _ecore_evas_constructor_wayland_shm}, 773 {"wayland_shm", _ecore_evas_constructor_wayland_shm},
753 {"wayland_egl", _ecore_evas_constructor_wayland_egl}, 774 {"wayland_egl", _ecore_evas_constructor_wayland_egl},
754 {"drm", _ecore_evas_constructor_drm}, 775 {"drm", _ecore_evas_constructor_drm},
776 {"opengl_drm", _ecore_evas_constructor_opengl_drm},
755 {"opengl_sdl", _ecore_evas_constructor_opengl_sdl}, 777 {"opengl_sdl", _ecore_evas_constructor_opengl_sdl},
756 {"sdl", _ecore_evas_constructor_sdl}, 778 {"sdl", _ecore_evas_constructor_sdl},
757 {"buffer", _ecore_evas_constructor_buffer}, 779 {"buffer", _ecore_evas_constructor_buffer},
@@ -4028,6 +4050,20 @@ ecore_evas_drm_new(const char *disp_name, unsigned int parent,
4028} 4050}
4029 4051
4030EAPI Ecore_Evas * 4052EAPI Ecore_Evas *
4053ecore_evas_gl_drm_new(const char *disp_name, unsigned int parent,
4054 int x, int y, int w, int h)
4055{
4056 Ecore_Evas *(*new)(const char *, unsigned int, int, int, int, int);
4057 Eina_Module *m = _ecore_evas_engine_load("drm");
4058 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
4059
4060 new = eina_module_symbol_get(m, "ecore_evas_gl_drm_new_internal");
4061 EINA_SAFETY_ON_NULL_RETURN_VAL(new, NULL);
4062
4063 return new(disp_name, parent, x, y, w, h);
4064}
4065
4066EAPI Ecore_Evas *
4031ecore_evas_software_gdi_new(Ecore_Win32_Window *parent, 4067ecore_evas_software_gdi_new(Ecore_Win32_Window *parent,
4032 int x, 4068 int x,
4033 int y, 4069 int y,
diff --git a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
index 2b601ae27a..cb7fb615a9 100644
--- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
+++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
@@ -4,7 +4,6 @@
4 4
5#include <stdlib.h> 5#include <stdlib.h>
6#include <string.h> 6#include <string.h>
7
8#include <Eina.h> 7#include <Eina.h>
9#include <Ecore.h> 8#include <Ecore.h>
10#include "ecore_private.h" 9#include "ecore_private.h"
@@ -13,11 +12,14 @@
13#include <Ecore_Evas.h> 12#include <Ecore_Evas.h>
14#include "ecore_evas_private.h" 13#include "ecore_evas_private.h"
15#include "ecore_evas_drm.h" 14#include "ecore_evas_drm.h"
15#include <Ecore_Drm.h>
16#include <Evas_Engine_Drm.h>
16 17
17//#ifdef BUILD_ECORE_EVAS_DRM 18#ifdef BUILD_ECORE_EVAS_OPENGL_DRM
18# include <Evas_Engine_Drm.h> 19# include <Evas_Engine_GL_Drm.h>
19# include <Ecore_Drm.h> 20# include <gbm.h>
20//#endif 21# include <dlfcn.h>
22#endif
21 23
22typedef struct _Ecore_Evas_Engine_Drm_Data Ecore_Evas_Engine_Drm_Data; 24typedef struct _Ecore_Evas_Engine_Drm_Data Ecore_Evas_Engine_Drm_Data;
23 25
@@ -30,7 +32,6 @@ struct _Ecore_Evas_Engine_Drm_Data
30static int _ecore_evas_drm_init(const char *device); 32static int _ecore_evas_drm_init(const char *device);
31static int _ecore_evas_drm_shutdown(void); 33static int _ecore_evas_drm_shutdown(void);
32static Ecore_Evas_Interface_Drm *_ecore_evas_drm_interface_new(void); 34static Ecore_Evas_Interface_Drm *_ecore_evas_drm_interface_new(void);
33
34static void _ecore_evas_drm_free(Ecore_Evas *ee); 35static void _ecore_evas_drm_free(Ecore_Evas *ee);
35static void _ecore_evas_drm_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); 36static void _ecore_evas_drm_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
36static void _ecore_evas_drm_callback_move_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); 37static void _ecore_evas_drm_callback_move_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
@@ -62,6 +63,7 @@ static void _ecore_evas_drm_ignore_events_set(Ecore_Evas *ee, int ignore);
62static void _ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha); 63static void _ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha);
63static void _ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent); 64static void _ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent);
64static void _ecore_evas_drm_aspect_set(Ecore_Evas *ee, double aspect); 65static void _ecore_evas_drm_aspect_set(Ecore_Evas *ee, double aspect);
66
65static int _ecore_evas_drm_render(Ecore_Evas *ee); 67static int _ecore_evas_drm_render(Ecore_Evas *ee);
66static void _ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event); 68static void _ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event);
67static int _ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates); 69static int _ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates);
@@ -70,7 +72,7 @@ static int _ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *upd
70static int _ecore_evas_init_count = 0; 72static int _ecore_evas_init_count = 0;
71static Ecore_Drm_Device *dev = NULL; 73static Ecore_Drm_Device *dev = NULL;
72 74
73static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = 75static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func =
74{ 76{
75 _ecore_evas_drm_free, 77 _ecore_evas_drm_free,
76 _ecore_evas_drm_callback_resize_set, 78 _ecore_evas_drm_callback_resize_set,
@@ -120,14 +122,14 @@ static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func =
120 _ecore_evas_drm_transparent_set, 122 _ecore_evas_drm_transparent_set,
121 NULL, //void (*fn_profiles_set) (Ecore_Evas *ee, const char **profiles, int count); 123 NULL, //void (*fn_profiles_set) (Ecore_Evas *ee, const char **profiles, int count);
122 NULL, //void (*fn_profile_set) (Ecore_Evas *ee, const char *profile); 124 NULL, //void (*fn_profile_set) (Ecore_Evas *ee, const char *profile);
123 125
124 NULL, //void (*fn_window_group_set) (Ecore_Evas *ee, const Ecore_Evas *ee_group); 126 NULL, //void (*fn_window_group_set) (Ecore_Evas *ee, const Ecore_Evas *ee_group);
125 _ecore_evas_drm_aspect_set, 127 _ecore_evas_drm_aspect_set,
126 NULL, //void (*fn_urgent_set) (Ecore_Evas *ee, Eina_Bool on); 128 NULL, //void (*fn_urgent_set) (Ecore_Evas *ee, Eina_Bool on);
127 NULL, //void (*fn_modal_set) (Ecore_Evas *ee, Eina_Bool on); 129 NULL, //void (*fn_modal_set) (Ecore_Evas *ee, Eina_Bool on);
128 NULL, //void (*fn_demands_attention_set) (Ecore_Evas *ee, Eina_Bool on); 130 NULL, //void (*fn_demands_attention_set) (Ecore_Evas *ee, Eina_Bool on);
129 NULL, //void (*fn_focus_skip_set) (Ecore_Evas *ee, Eina_Bool on); 131 NULL, //void (*fn_focus_skip_set) (Ecore_Evas *ee, Eina_Bool on);
130 132
131 _ecore_evas_drm_render, 133 _ecore_evas_drm_render,
132 134
133 NULL, //void (*fn_screen_geometry_get) (const Ecore_Evas *ee, int *x, int *y, int *w, int *h); 135 NULL, //void (*fn_screen_geometry_get) (const Ecore_Evas *ee, int *x, int *y, int *w, int *h);
@@ -223,7 +225,7 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED,
223 evas_output_viewport_set(ee->evas, 0, 0, w, h); 225 evas_output_viewport_set(ee->evas, 0, 0, w, h);
224 226
225 if (ee->can_async_render) 227 if (ee->can_async_render)
226 evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST, 228 evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
227 _ecore_evas_drm_render_updates, ee); 229 _ecore_evas_drm_render_updates, ee);
228 230
229 if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas))) 231 if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas)))
@@ -260,9 +262,167 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED,
260 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, 262 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
261 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); 263 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
262 264
263 evas_event_feed_mouse_in(ee->evas, 265 evas_event_feed_mouse_in(ee->evas,
266 (unsigned int)((unsigned long long)
267 (ecore_time_get() * 1000.0) &
268 0xffffffff), NULL);
269
270 return ee;
271
272eng_err:
273 ecore_evas_free(ee);
274ee_err:
275 _ecore_evas_drm_shutdown();
276 return NULL;
277}
278
279#ifdef BUILD_ECORE_EVAS_OPENGL_DRM
280EAPI Ecore_Evas *
281ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h)
282{
283 Ecore_Evas *ee;
284 Evas_Engine_Info_GL_Drm *einfo;
285 Ecore_Evas_Interface_Drm *iface;
286 Ecore_Evas_Engine_Drm_Data *edata;
287 int method;
288 uint32_t format = GBM_FORMAT_ARGB8888;
289 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
290 char *num;
291
292 /* try to find the evas drm engine */
293 if (!(method = evas_render_method_lookup("gl_drm")))
294 {
295 ERR("Render method lookup failed for GL Drm");
296 return NULL;
297 }
298
299 /* try to init drm */
300 if (_ecore_evas_drm_init(device) < 1) return NULL;
301
302 /* try to load gl libary, gbm libary */
303 /* Typically, gbm loads the dri driver However some versions of Mesa
304 * do not have libglapi symbols linked in the driver. Because of this,
305 * using hardware accel for our drm code Could fail with a
306 * message that the driver could not load. Let's be proactive and
307 * work around this for the user by preloading the glapi library */
308 dlopen("libglapi.so.0", (RTLD_LAZY | RTLD_GLOBAL));
309 if (dlerror())
310 {
311 _ecore_evas_drm_shutdown();
312 return NULL;
313 }
314
315 /* try to allocate space for new ecore_evas */
316 if (!(ee = calloc(1, sizeof(Ecore_Evas))))
317 {
318 ERR("Failed to allocate space for new Ecore_Evas");
319 goto ee_err;
320 }
321
322 if (!(edata = calloc(1, sizeof(Ecore_Evas_Engine_Drm_Data))))
323 {
324 ERR("Failed to allocate space for new Ecore_Evas_Engine_Data");
325 free(ee);
326 goto ee_err;
327 }
328
329 ee->engine.data = edata;
330
331 ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
332
333 ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func;
334
335 iface = _ecore_evas_drm_interface_new();
336 ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
337
338 /* set some engine properties */
339 ee->driver = "gl_drm";
340 if (device) ee->name = strdup(device);
341 else
342 ee->name = strdup(ecore_drm_device_name_get(dev));
343
344 if (w < 1) w = 1;
345 if (h < 1) h = 1;
346
347 ee->x = ee->req.x = x;
348 ee->y = ee->req.y = y;
349 ee->w = ee->req.w = w;
350 ee->h = ee->req.h = h;
351
352 ee->prop.max.w = 32767;
353 ee->prop.max.h = 32767;
354 ee->prop.layer = 4;
355 ee->prop.request_pos = 0;
356 ee->prop.sticky = 0;
357 ee->alpha = EINA_FALSE;
358
359 ee->can_async_render = 1;
360 if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER"))
361 ee->can_async_render = 0;
362
363 /* try to initialize evas */
364 ee->evas = evas_new();
365 evas_data_attach_set(ee->evas, ee);
366 evas_output_method_set(ee->evas, method);
367
368 /* FIXME: Support initial rotation ?? */
369 evas_output_size_set(ee->evas, w, h);
370 evas_output_viewport_set(ee->evas, 0, 0, w, h);
371
372 if (ee->can_async_render)
373 evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
374 _ecore_evas_drm_render_updates, ee);
375
376 if ((einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(ee->evas)))
377 {
378 einfo->info.depth = 32;
379 einfo->info.destination_alpha = ee->alpha;
380 einfo->info.rotation = ee->rotation;
381
382 if ((num = getenv("EVAS_DRM_VSYNC")))
383 {
384 if (!atoi(num)) einfo->vsync = EINA_FALSE;
385 else einfo->vsync = EINA_TRUE;
386 }
387 else einfo->vsync = EINA_TRUE;
388
389 einfo->info.fd = ecore_drm_device_fd_get(dev);
390 einfo->info.format = format;
391 einfo->info.flags = flags;
392 if (einfo->info.fd) einfo->info.gbm = gbm_create_device(einfo->info.fd);
393 if (einfo->info.gbm)
394 {
395 einfo->info.surface = gbm_surface_create(einfo->info.gbm, w, h,
396 format, flags);
397 }
398
399 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
400 {
401 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
402 goto eng_err;
403 }
404 }
405 else
406 {
407 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
408 goto eng_err;
409 }
410
411 ee->prop.window = einfo->info.output;
412
413 _ecore_evas_register(ee);
414 ecore_evas_input_event_register(ee);
415
416 ecore_drm_device_window_set(dev, ee->prop.window);
417 ecore_event_window_register(ee->prop.window, ee, ee->evas,
418 (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
419 (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
420 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
421 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
422
423 evas_event_feed_mouse_in(ee->evas,
264 (unsigned int)((unsigned long long) 424 (unsigned int)((unsigned long long)
265 (ecore_time_get() * 1000.0) & 425 (ecore_time_get() * 1000.0) &
266 0xffffffff), NULL); 426 0xffffffff), NULL);
267 427
268 return ee; 428 return ee;
@@ -271,11 +431,13 @@ eng_err:
271 ecore_evas_free(ee); 431 ecore_evas_free(ee);
272ee_err: 432ee_err:
273 _ecore_evas_drm_shutdown(); 433 _ecore_evas_drm_shutdown();
434
274 return NULL; 435 return NULL;
275} 436}
437#endif
276 438
277/* local functions */ 439/* local functions */
278static int 440static int
279_ecore_evas_drm_init(const char *device) 441_ecore_evas_drm_init(const char *device)
280{ 442{
281 if (++_ecore_evas_init_count != 1) return _ecore_evas_init_count; 443 if (++_ecore_evas_init_count != 1) return _ecore_evas_init_count;
@@ -318,7 +480,7 @@ _ecore_evas_drm_init(const char *device)
318 goto sprite_err; 480 goto sprite_err;
319 } 481 }
320 482
321 /* NB: We don't need to create outputs here. Evas will create the 483 /* NB: We don't need to create outputs here. Evas will create the
322 * framebuffers it needs */ 484 * framebuffers it needs */
323 /* try to create outputs */ 485 /* try to create outputs */
324 /* if (!ecore_drm_outputs_create(dev)) */ 486 /* if (!ecore_drm_outputs_create(dev)) */
@@ -351,7 +513,7 @@ dev_err:
351 return --_ecore_evas_init_count; 513 return --_ecore_evas_init_count;
352} 514}
353 515
354static int 516static int
355_ecore_evas_drm_shutdown(void) 517_ecore_evas_drm_shutdown(void)
356{ 518{
357 if (--_ecore_evas_init_count != 0) return _ecore_evas_init_count; 519 if (--_ecore_evas_init_count != 0) return _ecore_evas_init_count;
@@ -369,6 +531,7 @@ _ecore_evas_drm_shutdown(void)
369 return _ecore_evas_init_count; 531 return _ecore_evas_init_count;
370} 532}
371 533
534#ifdef BUILD_ECORE_EVAS_OPENGL_DRM
372static Ecore_Evas_Interface_Drm * 535static Ecore_Evas_Interface_Drm *
373_ecore_evas_drm_interface_new(void) 536_ecore_evas_drm_interface_new(void)
374{ 537{
@@ -386,9 +549,10 @@ _ecore_evas_drm_interface_new(void)
386 549
387 return iface; 550 return iface;
388} 551}
552#endif
389 553
390/* local ecore_evas functions */ 554/* local ecore_evas functions */
391static void 555static void
392_ecore_evas_drm_free(Ecore_Evas *ee) 556_ecore_evas_drm_free(Ecore_Evas *ee)
393{ 557{
394 Ecore_Evas_Engine_Drm_Data *data; 558 Ecore_Evas_Engine_Drm_Data *data;
@@ -399,49 +563,49 @@ _ecore_evas_drm_free(Ecore_Evas *ee)
399 _ecore_evas_drm_shutdown(); 563 _ecore_evas_drm_shutdown();
400} 564}
401 565
402static void 566static void
403_ecore_evas_drm_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) 567_ecore_evas_drm_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
404{ 568{
405 ee->func.fn_resize = func; 569 ee->func.fn_resize = func;
406} 570}
407 571
408static void 572static void
409_ecore_evas_drm_callback_move_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) 573_ecore_evas_drm_callback_move_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
410{ 574{
411 ee->func.fn_move = func; 575 ee->func.fn_move = func;
412} 576}
413 577
414static void 578static void
415_ecore_evas_drm_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) 579_ecore_evas_drm_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
416{ 580{
417 ee->func.fn_focus_in = func; 581 ee->func.fn_focus_in = func;
418} 582}
419 583
420static void 584static void
421_ecore_evas_drm_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) 585_ecore_evas_drm_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
422{ 586{
423 ee->func.fn_focus_out = func; 587 ee->func.fn_focus_out = func;
424} 588}
425 589
426static void 590static void
427_ecore_evas_drm_callback_mouse_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) 591_ecore_evas_drm_callback_mouse_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
428{ 592{
429 ee->func.fn_mouse_in = func; 593 ee->func.fn_mouse_in = func;
430} 594}
431 595
432static void 596static void
433_ecore_evas_drm_callback_mouse_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) 597_ecore_evas_drm_callback_mouse_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
434{ 598{
435 ee->func.fn_mouse_out = func; 599 ee->func.fn_mouse_out = func;
436} 600}
437 601
438static void 602static void
439_ecore_evas_drm_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) 603_ecore_evas_drm_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
440{ 604{
441 ee->func.fn_delete_request = func; 605 ee->func.fn_delete_request = func;
442} 606}
443 607
444static void 608static void
445_ecore_evas_drm_move(Ecore_Evas *ee, int x, int y) 609_ecore_evas_drm_move(Ecore_Evas *ee, int x, int y)
446{ 610{
447 ee->req.x = x; 611 ee->req.x = x;
@@ -452,7 +616,7 @@ _ecore_evas_drm_move(Ecore_Evas *ee, int x, int y)
452 if (ee->func.fn_move) ee->func.fn_move(ee); 616 if (ee->func.fn_move) ee->func.fn_move(ee);
453} 617}
454 618
455static void 619static void
456_ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h) 620_ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h)
457{ 621{
458 ee->req.w = w; 622 ee->req.w = w;
@@ -465,7 +629,7 @@ _ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h)
465 if (ee->func.fn_resize) ee->func.fn_resize(ee); 629 if (ee->func.fn_resize) ee->func.fn_resize(ee);
466} 630}
467 631
468static void 632static void
469_ecore_evas_drm_move_resize(Ecore_Evas *ee, int x, int y, int w, int h) 633_ecore_evas_drm_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
470{ 634{
471 if ((ee->x != x) || (ee->y != y)) 635 if ((ee->x != x) || (ee->y != y))
@@ -474,7 +638,7 @@ _ecore_evas_drm_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
474 _ecore_evas_drm_resize(ee, w, h); 638 _ecore_evas_drm_resize(ee, w, h);
475} 639}
476 640
477static void 641static void
478_ecore_evas_drm_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSED) 642_ecore_evas_drm_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSED)
479{ 643{
480 Evas_Engine_Info_Drm *einfo; 644 Evas_Engine_Info_Drm *einfo;
@@ -487,7 +651,7 @@ _ecore_evas_drm_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSE
487 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver); 651 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
488} 652}
489 653
490static void 654static void
491_ecore_evas_drm_show(Ecore_Evas *ee) 655_ecore_evas_drm_show(Ecore_Evas *ee)
492{ 656{
493 if ((!ee) || (ee->visible)) return; 657 if ((!ee) || (ee->visible)) return;
@@ -496,7 +660,7 @@ _ecore_evas_drm_show(Ecore_Evas *ee)
496 if (ee->func.fn_show) ee->func.fn_show(ee); 660 if (ee->func.fn_show) ee->func.fn_show(ee);
497} 661}
498 662
499static void 663static void
500_ecore_evas_drm_hide(Ecore_Evas *ee) 664_ecore_evas_drm_hide(Ecore_Evas *ee)
501{ 665{
502 if ((!ee) || (!ee->visible)) return; 666 if ((!ee) || (!ee->visible)) return;
@@ -506,7 +670,7 @@ _ecore_evas_drm_hide(Ecore_Evas *ee)
506 if (ee->func.fn_hide) ee->func.fn_hide(ee); 670 if (ee->func.fn_hide) ee->func.fn_hide(ee);
507} 671}
508 672
509static void 673static void
510_ecore_evas_drm_title_set(Ecore_Evas *ee, const char *title) 674_ecore_evas_drm_title_set(Ecore_Evas *ee, const char *title)
511{ 675{
512 if (ee->prop.title) free(ee->prop.title); 676 if (ee->prop.title) free(ee->prop.title);
@@ -514,7 +678,7 @@ _ecore_evas_drm_title_set(Ecore_Evas *ee, const char *title)
514 if (title) ee->prop.title = strdup(title); 678 if (title) ee->prop.title = strdup(title);
515} 679}
516 680
517static void 681static void
518_ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c) 682_ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c)
519{ 683{
520 if (ee->prop.name) free(ee->prop.name); 684 if (ee->prop.name) free(ee->prop.name);
@@ -525,7 +689,7 @@ _ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c)
525 if (c) ee->prop.clas = strdup(c); 689 if (c) ee->prop.clas = strdup(c);
526} 690}
527 691
528static void 692static void
529_ecore_evas_drm_size_min_set(Ecore_Evas *ee, int w, int h) 693_ecore_evas_drm_size_min_set(Ecore_Evas *ee, int w, int h)
530{ 694{
531 if (w < 0) w = 0; 695 if (w < 0) w = 0;
@@ -535,7 +699,7 @@ _ecore_evas_drm_size_min_set(Ecore_Evas *ee, int w, int h)
535 ee->prop.min.h = h; 699 ee->prop.min.h = h;
536} 700}
537 701
538static void 702static void
539_ecore_evas_drm_size_max_set(Ecore_Evas *ee, int w, int h) 703_ecore_evas_drm_size_max_set(Ecore_Evas *ee, int w, int h)
540{ 704{
541 if (w < 0) w = 0; 705 if (w < 0) w = 0;
@@ -545,7 +709,7 @@ _ecore_evas_drm_size_max_set(Ecore_Evas *ee, int w, int h)
545 ee->prop.max.h = h; 709 ee->prop.max.h = h;
546} 710}
547 711
548static void 712static void
549_ecore_evas_drm_size_base_set(Ecore_Evas *ee, int w, int h) 713_ecore_evas_drm_size_base_set(Ecore_Evas *ee, int w, int h)
550{ 714{
551 if (w < 0) w = 0; 715 if (w < 0) w = 0;
@@ -555,7 +719,7 @@ _ecore_evas_drm_size_base_set(Ecore_Evas *ee, int w, int h)
555 ee->prop.base.h = h; 719 ee->prop.base.h = h;
556} 720}
557 721
558static void 722static void
559_ecore_evas_drm_size_step_set(Ecore_Evas *ee, int w, int h) 723_ecore_evas_drm_size_step_set(Ecore_Evas *ee, int w, int h)
560{ 724{
561 if (w < 0) w = 0; 725 if (w < 0) w = 0;
@@ -565,7 +729,7 @@ _ecore_evas_drm_size_step_set(Ecore_Evas *ee, int w, int h)
565 ee->prop.step.h = h; 729 ee->prop.step.h = h;
566} 730}
567 731
568static void 732static void
569_ecore_evas_drm_object_cursor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) 733_ecore_evas_drm_object_cursor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
570{ 734{
571 Ecore_Evas *ee; 735 Ecore_Evas *ee;
@@ -573,8 +737,8 @@ _ecore_evas_drm_object_cursor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *
573 if ((ee = data)) ee->prop.cursor.object = NULL; 737 if ((ee = data)) ee->prop.cursor.object = NULL;
574} 738}
575 739
576static void 740static void
577_ecore_evas_drm_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y) 741_ecore_evas_drm_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
578{ 742{
579 int x, y; 743 int x, y;
580 Evas_Object *old; 744 Evas_Object *old;
@@ -618,7 +782,7 @@ end:
618 } 782 }
619} 783}
620 784
621static void 785static void
622_ecore_evas_drm_layer_set(Ecore_Evas *ee, int layer) 786_ecore_evas_drm_layer_set(Ecore_Evas *ee, int layer)
623{ 787{
624 if (layer < 1) layer = 1; 788 if (layer < 1) layer = 1;
@@ -627,28 +791,28 @@ _ecore_evas_drm_layer_set(Ecore_Evas *ee, int layer)
627 ee->prop.layer = layer; 791 ee->prop.layer = layer;
628} 792}
629 793
630static void 794static void
631_ecore_evas_drm_iconified_set(Ecore_Evas *ee, Eina_Bool on) 795_ecore_evas_drm_iconified_set(Ecore_Evas *ee, Eina_Bool on)
632{ 796{
633 if (ee->prop.iconified == on) return; 797 if (ee->prop.iconified == on) return;
634 ee->prop.iconified = on; 798 ee->prop.iconified = on;
635} 799}
636 800
637static void 801static void
638_ecore_evas_drm_borderless_set(Ecore_Evas *ee, Eina_Bool on) 802_ecore_evas_drm_borderless_set(Ecore_Evas *ee, Eina_Bool on)
639{ 803{
640 if (ee->prop.borderless == on) return; 804 if (ee->prop.borderless == on) return;
641 ee->prop.borderless = on; 805 ee->prop.borderless = on;
642} 806}
643 807
644static void 808static void
645_ecore_evas_drm_maximized_set(Ecore_Evas *ee, Eina_Bool on) 809_ecore_evas_drm_maximized_set(Ecore_Evas *ee, Eina_Bool on)
646{ 810{
647 if (ee->prop.maximized == on) return; 811 if (ee->prop.maximized == on) return;
648 ee->prop.maximized = on; 812 ee->prop.maximized = on;
649} 813}
650 814
651static void 815static void
652_ecore_evas_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) 816_ecore_evas_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on)
653{ 817{
654 Eina_Bool resized = EINA_FALSE; 818 Eina_Bool resized = EINA_FALSE;
@@ -695,7 +859,7 @@ _ecore_evas_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on)
695 } 859 }
696} 860}
697 861
698static void 862static void
699_ecore_evas_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on) 863_ecore_evas_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on)
700{ 864{
701 if (ee->prop.withdrawn == on) return; 865 if (ee->prop.withdrawn == on) return;
@@ -704,14 +868,14 @@ _ecore_evas_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on)
704 else ecore_evas_show(ee); 868 else ecore_evas_show(ee);
705} 869}
706 870
707static void 871static void
708_ecore_evas_drm_ignore_events_set(Ecore_Evas *ee, int ignore) 872_ecore_evas_drm_ignore_events_set(Ecore_Evas *ee, int ignore)
709{ 873{
710 if (ee->ignore_events == ignore) return; 874 if (ee->ignore_events == ignore) return;
711 ee->ignore_events = ignore; 875 ee->ignore_events = ignore;
712} 876}
713 877
714static void 878static void
715_ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha) 879_ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha)
716{ 880{
717 if (ee->in_async_render) 881 if (ee->in_async_render)
@@ -724,7 +888,7 @@ _ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha)
724 /* FIXME: TODO: Finish */ 888 /* FIXME: TODO: Finish */
725} 889}
726 890
727static void 891static void
728_ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent) 892_ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent)
729{ 893{
730 if (ee->in_async_render) 894 if (ee->in_async_render)
@@ -737,14 +901,14 @@ _ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent)
737 /* FIXME: TODO: Finish */ 901 /* FIXME: TODO: Finish */
738} 902}
739 903
740static void 904static void
741_ecore_evas_drm_aspect_set(Ecore_Evas *ee, double aspect) 905_ecore_evas_drm_aspect_set(Ecore_Evas *ee, double aspect)
742{ 906{
743 if (ee->prop.aspect == aspect) return; 907 if (ee->prop.aspect == aspect) return;
744 ee->prop.aspect = aspect; 908 ee->prop.aspect = aspect;
745} 909}
746 910
747static int 911static int
748_ecore_evas_drm_render(Ecore_Evas *ee) 912_ecore_evas_drm_render(Ecore_Evas *ee)
749{ 913{
750 int rend = 0; 914 int rend = 0;
@@ -786,7 +950,7 @@ _ecore_evas_drm_render(Ecore_Evas *ee)
786 return rend; 950 return rend;
787} 951}
788 952
789static void 953static void
790_ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event) 954_ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event)
791{ 955{
792 Evas_Event_Render_Post *ev; 956 Evas_Event_Render_Post *ev;
@@ -802,7 +966,7 @@ _ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event)
802 /* TODO: handle delayed changes */ 966 /* TODO: handle delayed changes */
803} 967}
804 968
805static int 969static int
806_ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates) 970_ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates)
807{ 971{
808 int rend = 0; 972 int rend = 0;
diff --git a/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
new file mode 100644
index 0000000000..3f41beeca9
--- /dev/null
+++ b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
@@ -0,0 +1,44 @@
1#ifndef _EVAS_ENGINE_GL_DRM_H
2# define _EVAS_ENGINE_GL_DRM_H
3
4# include <gbm.h>
5
6typedef struct _Evas_Engine_Info_GL_Drm Evas_Engine_Info_GL_Drm;
7
8struct _Evas_Engine_Info_GL_Drm
9{
10 /* PRIVATE - don't mess with this baby or evas will poke its tongue out
11 * at you and make nasty noises */
12 Evas_Engine_Info magic;
13
14 /* engine specific data & parameters it needs to set up */
15 struct
16 {
17 struct gbm_device *gbm;
18 struct gbm_surface *surface;
19 uint32_t format;
20 uint32_t flags;
21 int depth, screen, rotation;
22 unsigned char destination_alpha : 1;
23 int fd, tty;
24 Eina_Bool own_fd : 1;
25 Eina_Bool own_tty : 1;
26 int output, plane;
27 } info;
28
29 struct
30 {
31 void (*pre_swap) (void *data, Evas *evas);
32 void (*post_swap) (void *data, Evas *evas);
33 void *data;
34 } callback;
35
36 /* non-blocking or blocking mode */
37 Evas_Engine_Render_Mode render_mode;
38
39 unsigned char vsync : 1;
40 unsigned char indirect : 1;
41 unsigned char swap_mode : 4;
42};
43
44#endif
diff --git a/src/modules/evas/engines/gl_drm/evas_drm.c b/src/modules/evas/engines/gl_drm/evas_drm.c
new file mode 100644
index 0000000000..18c77935f4
--- /dev/null
+++ b/src/modules/evas/engines/gl_drm/evas_drm.c
@@ -0,0 +1,602 @@
1#include "evas_engine.h"
2#include <linux/vt.h>
3#include <linux/kd.h>
4#include <sys/mman.h>
5
6static Evas_Engine_Info_GL_Drm *siginfo;
7
8static void
9_evas_drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
10{
11 Buffer *buffer = data;
12 struct gbm_device *gbm = gbm_bo_get_device(bo);
13
14 if (buffer->fb)
15 drmModeRmFB(gbm_device_get_fd(gbm), buffer->fb);
16}
17
18static int
19_evas_drm_tty_open(Evas_Engine_Info_GL_Drm *info)
20{
21 int tty = STDIN_FILENO;
22
23 /* check if the current stdin is a valid tty */
24 if (!isatty(tty))
25 {
26 /* if not, try to open the curren tty */
27 if ((tty = open("/dev/tty", (O_RDWR | O_CLOEXEC))) < 0)
28 {
29 int tty0 = -1, num = -1;
30 char name[16];
31
32 /* if that fails, try tty0 */
33 if ((tty0 = open("/dev/tty0", (O_WRONLY | O_CLOEXEC))) < 0)
34 {
35 CRI("Could not open tty0: %m");
36 return -1;
37 }
38
39 /* try to find a non-opened tty */
40 if ((ioctl(tty0, VT_OPENQRY, &num) < 0) || (num < 0))
41 {
42 CRI("Could not find a non-opened tty");
43 close(tty0);
44 return -1;
45 }
46
47 snprintf(name, sizeof(name), "/dev/tty%d", num);
48
49 /* try to open this tty */
50 if ((tty = open(name, (O_RDWR | O_CLOEXEC))) < 0)
51 {
52 CRI("Could not open tty: %s", name);
53 close(tty0);
54 return -1;
55 }
56
57 /* set flag that evas should close this tty */
58 info->info.own_tty = EINA_TRUE;
59
60 /* close /dev/tty0 */
61 close(tty0);
62 }
63 }
64 else
65 {
66 /* set flag that evas should close this tty */
67 info->info.own_tty = EINA_TRUE;
68 }
69
70 DBG("Opened Tty %d", tty);
71
72 return tty;
73}
74
75static int
76_evas_drm_crtc_find(int fd, drmModeRes *res, drmModeConnector *conn)
77{
78 int crtc = -1;
79 drmModeEncoder *enc = NULL;
80
81 /* if this connector already has an encoder, get it */
82 if (conn->encoder_id) enc = drmModeGetEncoder(fd, conn->encoder_id);
83
84 /* if this encoder already has a crtc, lets try to use that */
85 if ((enc) && (enc->crtc_id)) crtc = enc->crtc_id;
86
87 if (crtc < 0)
88 {
89 int i = 0, c = 0;
90
91 /* if this connector has no encoder, we need to find one */
92 for (; i < conn->count_encoders; ++i)
93 {
94 /* try to get this encoder */
95 if (!(enc = drmModeGetEncoder(fd, conn->encoders[i])))
96 continue;
97
98 /* loop global crtcs */
99 for (; c < res->count_crtcs; ++c)
100 {
101 /* does this crtc work with this encoder ? */
102 if (!(enc->possible_crtcs & (1 << c))) continue;
103
104 /* FIXME: We could be more proactive here and check that
105 * nobody else is using this crtc */
106
107 /* if it works, let's use it */
108 crtc = res->crtcs[c];
109 break;
110 }
111
112 if (crtc >= 0) break;
113 }
114 }
115
116 /* free the encoder */
117 if (enc) drmModeFreeEncoder(enc);
118
119 return crtc;
120}
121
122static unsigned int
123_evas_drm_crtc_buffer_get(int fd, int crtc_id)
124{
125 drmModeCrtc *crtc;
126 unsigned int id;
127
128 if (!(crtc = drmModeGetCrtc(fd, crtc_id))) return 0;
129 id = crtc->buffer_id;
130 drmModeFreeCrtc(crtc);
131 return id;
132}
133
134static void
135_evas_drm_tty_sigusr1(int x EINA_UNUSED, siginfo_t *info EINA_UNUSED, void *data EINA_UNUSED)
136{
137 Evas_Engine_Info_GL_Drm *einfo;
138
139 DBG("Caught SIGUSR1");
140
141 if (!(einfo = siginfo)) return;
142
143 /* TODO: set canvas to not render */
144
145 DBG("\tDrop Master & Release VT");
146
147 /* drop drm master */
148 if (einfo->info.own_fd)
149 {
150 if (drmDropMaster(einfo->info.fd) != 0)
151 WRN("Could not drop drm master: %m");
152 }
153
154 /* release vt */
155 if (einfo->info.own_tty)
156 {
157 if (ioctl(einfo->info.tty, VT_RELDISP, 1) < 0)
158 WRN("Could not release vt: %m");
159 }
160}
161
162static void
163_evas_drm_tty_sigusr2(int x EINA_UNUSED, siginfo_t *info EINA_UNUSED, void *data EINA_UNUSED)
164{
165 Evas_Engine_Info_GL_Drm *einfo;
166
167 DBG("Caught SIGUSR2");
168
169 if (!(einfo = siginfo)) return;
170
171 /* TODO: set canvas to render again */
172
173 DBG("\tAcquire VT & Set Master");
174
175 /* acquire vt */
176 if (einfo->info.own_tty)
177 {
178 if (ioctl(einfo->info.tty, VT_RELDISP, VT_ACKACQ) < 0)
179 WRN("Could not acquire vt: %m");
180 }
181
182 /* set master */
183 if (einfo->info.own_fd)
184 {
185 if (drmSetMaster(einfo->info.fd) != 0)
186 WRN("Could not set drm master: %m");
187 }
188}
189
190static Eina_Bool
191_evas_drm_tty_setup(Evas_Engine_Info_GL_Drm *info)
192{
193 struct vt_mode vtmode = { 0 };
194 struct sigaction sig;
195
196 /* check for valid tty */
197 if (info->info.tty < 0) return EINA_FALSE;
198
199 /* setup tty rel/acq signals */
200 vtmode.mode = VT_PROCESS;
201 vtmode.waitv = 0;
202 vtmode.relsig = SIGUSR1;
203 vtmode.acqsig = SIGUSR2;
204 if (ioctl(info->info.tty, VT_SETMODE, &vtmode) < 0)
205 {
206 CRI("Could not set tty mode: %m");
207 return EINA_FALSE;
208 }
209
210 /* store info struct
211 *
212 * NB: REALLY hate to store this here, but sigaction signal handlers cannot
213 * pass any 'user data' to the signal handlers :(
214 */
215 siginfo = info;
216
217 /* setup signal handlers for above signals */
218 sig.sa_sigaction = _evas_drm_tty_sigusr1;
219 sig.sa_flags = (SA_NODEFER | SA_SIGINFO | SA_RESTART);
220 sigemptyset(&sig.sa_mask);
221 sigaction(SIGUSR1, &sig, NULL);
222
223 sig.sa_sigaction = _evas_drm_tty_sigusr2;
224 sig.sa_flags = (SA_NODEFER | SA_SIGINFO | SA_RESTART);
225 sigemptyset(&sig.sa_mask);
226 sigaction(SIGUSR2, &sig, NULL);
227
228 return EINA_TRUE;
229}
230
231static void
232_evas_drm_outbuf_page_flip(int fd EINA_UNUSED, unsigned int seq EINA_UNUSED, unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED, void *data)
233{
234 Outbuf *ob;
235 Buffer *buff;
236
237 /* get the output buffer from data */
238 if (!(ob = data)) return;
239
240 buff = &(ob->priv.buffer[ob->priv.curr]);
241 gbm_surface_release_buffer(ob->surface, buff->bo);
242
243 ob->priv.pending_flip = EINA_FALSE;
244 ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
245}
246
247static Eina_Bool
248_evas_drm_outbuf_planes_setup(Outbuf *ob, drmModePlaneResPtr pres)
249{
250 drmModePlanePtr dplane;
251 Plane *oplane;
252 unsigned int p = 0;
253 unsigned int f = 0;
254
255 for (p = 0; p < pres->count_planes; p++)
256 {
257 /* try to get this plane */
258 if (!(dplane = drmModeGetPlane(ob->priv.fd, pres->planes[p])))
259 continue;
260
261 /* try to allocate space for our plane */
262 if (!(oplane =
263 malloc(sizeof(Plane) +
264 ((sizeof(unsigned int)) * dplane->count_formats))))
265 {
266 drmModeFreePlane(dplane);
267 continue;
268 }
269
270 oplane->crtcs = dplane->possible_crtcs;
271 oplane->id = dplane->plane_id;
272 oplane->num_formats = dplane->count_formats;
273 memcpy(oplane->formats, dplane->formats,
274 dplane->count_formats * sizeof(dplane->formats[0]));
275
276 DBG("Plane %d, %d %d", p, dplane->x, dplane->y);
277 DBG("\tFB: %d", dplane->fb_id);
278 DBG("\tCrtc: %d, %d %d", dplane->crtc_id,
279 dplane->crtc_x, dplane->crtc_y);
280
281 DBG("\tSupported Formats");
282 for (f = 0; f < dplane->count_formats; f++)
283 {
284 DBG("\t\t%C%C%C%C", (dplane->formats[f] & 0xFF),
285 ((dplane->formats[f] >> 8) & 0xFF),
286 ((dplane->formats[f] >> 16) & 0xFF),
287 ((dplane->formats[f] >> 24) & 0xFF));
288 }
289
290 /* free this plane */
291 drmModeFreePlane(dplane);
292
293 /* append this plane */
294 ob->priv.planes = eina_list_append(ob->priv.planes, oplane);
295 }
296
297 if (eina_list_count(ob->priv.planes) < 1) return EINA_FALSE;
298 return EINA_TRUE;
299}
300
301Eina_Bool
302evas_drm_init(Evas_Engine_Info_GL_Drm *info)
303{
304 /* check for valid engine info */
305 if (!info) return EINA_FALSE;
306
307 setvbuf(stdout, NULL, _IONBF, 0);
308
309 /* check if we already opened the tty */
310 if (info->info.tty < 0)
311 {
312 /* try to open the current tty */
313 if ((info->info.tty = _evas_drm_tty_open(info)) < 0)
314 {
315 /* check if we already opened the card. if so, close it */
316 if ((info->info.fd >= 0) && (info->info.own_fd))
317 {
318 close(info->info.fd);
319 info->info.fd = -1;
320 }
321
322 return EINA_FALSE;
323 }
324 }
325
326 /* with the tty opened, we need to set it up */
327 if (!_evas_drm_tty_setup(info))
328 {
329 /* setup of tty failed, close it */
330 if ((info->info.tty >= 0) && (info->info.own_tty))
331 close(info->info.tty);
332
333 return EINA_FALSE;
334 }
335
336 return EINA_TRUE;
337}
338
339Eina_Bool
340evas_drm_shutdown(Evas_Engine_Info_GL_Drm *info)
341{
342 /* check for valid engine info */
343 if (!info) return EINA_TRUE;
344
345 /* check if we already opened the tty. if so, close it */
346 if ((info->info.tty >= 0) && (info->info.own_tty))
347 {
348 close(info->info.tty);
349 info->info.tty = -1;
350 }
351
352 return EINA_TRUE;
353}
354
355Eina_Bool
356evas_drm_gbm_init(Evas_Engine_Info_GL_Drm *info, int w, int h)
357{
358 if (!info) return EINA_FALSE;
359 if (info->info.fd < 0) return EINA_FALSE;
360
361 if (!(info->info.gbm = gbm_create_device(info->info.fd)))
362 {
363 return EINA_FALSE;
364 }
365
366 if (!(info->info.surface = gbm_surface_create(info->info.gbm, w, h,
367 info->info.format,
368 info->info.flags)))
369 {
370 gbm_device_destroy(info->info.gbm);
371 info->info.gbm = NULL;
372 return EINA_FALSE;
373 }
374
375 return EINA_TRUE;
376}
377
378Eina_Bool
379evas_drm_gbm_shutdown(Evas_Engine_Info_GL_Drm *info)
380{
381 if (!info) return EINA_TRUE;
382
383 if (info->info.surface)
384 {
385 gbm_surface_destroy(info->info.surface);
386 info->info.surface = NULL;
387 }
388 if (info->info.gbm)
389 {
390 gbm_device_destroy(info->info.gbm);
391 info->info.gbm = NULL;
392 }
393
394 return EINA_TRUE;
395}
396
397Eina_Bool
398evas_drm_outbuf_setup(Outbuf *ob)
399{
400 drmModeRes *res;
401 drmModeConnector *conn;
402 drmModePlaneResPtr pres;
403 int i = 0;
404
405 /* check for valid Output buffer */
406 if ((!ob) || (ob->priv.fd < 0)) return EINA_FALSE;
407
408 /* setup drmHandleEvent context */
409 memset(&ob->priv.ctx, 0, sizeof(ob->priv.ctx));
410 ob->priv.ctx.version = DRM_EVENT_CONTEXT_VERSION;
411 ob->priv.ctx.page_flip_handler = _evas_drm_outbuf_page_flip;
412
413 /* try to get drm resources */
414 if (!(res = drmModeGetResources(ob->priv.fd)))
415 {
416 CRI("Could not get drm resources: %m");
417 return EINA_FALSE;
418 }
419
420 /* loop the connectors */
421 for (; i < res->count_connectors; ++i)
422 {
423 int crtc = -1;
424 int m = 0;
425
426 /* try to get this connector */
427 if (!(conn = drmModeGetConnector(ob->priv.fd, res->connectors[i])))
428 {
429 WRN("Could not get drm connector %d: %m", i);
430 continue;
431 }
432
433 /* make sure this connector is actually connected */
434 if (conn->connection != DRM_MODE_CONNECTED)
435 {
436 /* free connector resources */
437 drmModeFreeConnector(conn);
438 continue;
439 }
440
441 /* make sure it has modes */
442 if (conn->count_modes == 0)
443 {
444 /* free connector resources */
445 drmModeFreeConnector(conn);
446 continue;
447 }
448
449 /* try to find a crtc for this connector */
450 if ((crtc = _evas_drm_crtc_find(ob->priv.fd, res, conn)) < 0)
451 {
452 /* free connector resources */
453 drmModeFreeConnector(conn);
454 continue;
455 }
456
457 /* record the connector id */
458 ob->priv.conn = conn->connector_id;
459
460 /* record the crtc id */
461 ob->priv.crtc = crtc;
462
463 /* get the current framebuffer */
464 ob->priv.fb = _evas_drm_crtc_buffer_get(ob->priv.fd, crtc);
465
466 /* record the current mode */
467 memcpy(&ob->priv.mode, &conn->modes[0], sizeof(ob->priv.mode));
468
469 for (m = 0; m < conn->count_modes; m++)
470 {
471 DBG("Output Available Mode: %d: %d %d %d", ob->priv.conn,
472 conn->modes[m].hdisplay, conn->modes[m].vdisplay,
473 conn->modes[m].vrefresh);
474
475 /* try to find a mode which matches the requested size */
476 if ((conn->modes[m].hdisplay == ob->w) &&
477 (conn->modes[m].vdisplay == ob->h) &&
478 (conn->modes[m].vrefresh == 60))
479 {
480 memcpy(&ob->priv.mode, &conn->modes[m],
481 sizeof(ob->priv.mode));
482 }
483 }
484
485 DBG("Output Current Mode: %d: %d %d", ob->priv.conn,
486 ob->priv.mode.hdisplay, ob->priv.mode.vdisplay);
487
488 if ((ob->priv.mode.hdisplay != conn->modes[0].hdisplay) ||
489 (ob->priv.mode.vdisplay != conn->modes[0].vdisplay))
490 {
491 /* set new crtc mode */
492 drmModeSetCrtc(ob->priv.fd, ob->priv.crtc, ob->priv.fb, 0, 0,
493 &ob->priv.conn, 1, &ob->priv.mode);
494 }
495
496 /* free connector resources */
497 drmModeFreeConnector(conn);
498
499 break;
500 }
501
502 /* get any plane resource from the card */
503 pres = drmModeGetPlaneResources(ob->priv.fd);
504
505 /* if we have at least one plane, set it up */
506 if (pres->count_planes > 0)
507 {
508 if (!_evas_drm_outbuf_planes_setup(ob, pres))
509 WRN("Could not setup hardware planes");
510 }
511
512 /* free plane resources */
513 drmModeFreePlaneResources(pres);
514
515 /* free drm resources */
516 drmModeFreeResources(res);
517
518 return EINA_TRUE;
519}
520
521void
522evas_drm_outbuf_framebuffer_set(Outbuf *ob, Buffer *buffer)
523{
524 int ret;
525 uint32_t handles[4], pitches[4], offsets[4];
526 uint32_t width, height;
527 uint32_t format;
528
529 /* validate params */
530 if ((!ob) || (!buffer)) return;
531
532 if (buffer->valid) return;
533
534 width = gbm_bo_get_width(buffer->bo);
535 height = gbm_bo_get_height(buffer->bo);
536 buffer->stride = gbm_bo_get_stride(buffer->bo);
537 buffer->handle = gbm_bo_get_handle(buffer->bo).u32;
538 buffer->size = buffer->stride * height;
539 format = gbm_bo_get_format(buffer->bo);
540
541 handles[0] = buffer->handle;
542 pitches[0] = buffer->stride;
543 offsets[0] = 0;
544
545 ret = drmModeAddFB2(ob->priv.fd, width, height, format, handles,
546 pitches, offsets, &(buffer->fb), 0);
547
548 if (ret)
549 {
550 ret = drmModeAddFB(ob->priv.fd, width, height, 24, 32,
551 buffer->stride, buffer->handle, &(buffer->fb));
552 }
553 if (ret) ERR("Failed to AddFB: %m");
554
555 ret = drmModeSetCrtc(ob->priv.fd, ob->priv.crtc, buffer->fb, 0, 0,
556 &ob->priv.conn, 1, &ob->priv.mode);
557
558 if (ret) ERR("Failed to set crtc: %m");
559
560 gbm_bo_set_user_data(buffer->bo, buffer, _evas_drm_fb_destroy_callback);
561
562 buffer->valid = EINA_TRUE;
563}
564
565Eina_Bool
566evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer)
567{
568 /* check for valid Output buffer */
569 if ((!ob) || (ob->priv.fd < 0)) return EINA_FALSE;
570
571 /* check for valid buffer */
572 if (!buffer) return EINA_FALSE;
573
574 if (ob->vsync)
575 {
576 if (drmModePageFlip(ob->priv.fd, ob->priv.crtc,
577 buffer->fb, DRM_MODE_PAGE_FLIP_EVENT, ob) < 0)
578 {
579 ERR("Cannot flip crtc for connector %u: %m", ob->priv.conn);
580 return EINA_FALSE;
581 }
582
583 ob->priv.pending_flip = EINA_TRUE;
584
585 while (ob->priv.pending_flip)
586 drmHandleEvent(ob->priv.fd, &ob->priv.ctx);
587 }
588 else
589 {
590 /* NB: We don't actually need to do this if we are not vsync
591 * because we are drawing directly to the buffer anyway.
592 * If we enable the sending of buffer to crtc, it causes vsync */
593
594 /* send this buffer to the crtc */
595 /* evas_drm_outbuf_framebuffer_set(ob, buffer); */
596
597 /* increment buffer we are using */
598 ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
599 }
600
601 return EINA_TRUE;
602}
diff --git a/src/modules/evas/engines/gl_drm/evas_drm_main.c b/src/modules/evas/engines/gl_drm/evas_drm_main.c
new file mode 100644
index 0000000000..84a0b54068
--- /dev/null
+++ b/src/modules/evas/engines/gl_drm/evas_drm_main.c
@@ -0,0 +1,638 @@
1#include "evas_engine.h"
2
3/* local variables */
4static Outbuf *_evas_gl_drm_window = NULL;
5static EGLContext context = EGL_NO_CONTEXT;
6static int win_count = 0;
7
8/* local function prototypes */
9static void _outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count);
10static void _outbuf_flush_famebuffer(Outbuf *ob);
11
12/* local functions */
13static void
14_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects EINA_UNUSED, unsigned int count EINA_UNUSED)
15{
16 Buffer *buff;
17
18 buff = &(ob->priv.buffer[ob->priv.curr]);
19
20 buff->bo = gbm_surface_lock_front_buffer(ob->surface);
21
22 /* if this buffer is not valid, we need to set it */
23 if (!buff->valid) evas_drm_outbuf_framebuffer_set(ob, buff);
24
25 /* send this buffer to the crtc */
26 evas_drm_framebuffer_send(ob, buff);
27}
28
29static void
30_outbuf_flush_famebuffer(Outbuf *ob)
31{
32 Eina_Rectangle *rects = NULL;
33 unsigned int n = 0;
34 //TODO: add region flush routine for SwapBuffersWithDamage
35
36 /* force a buffer swap */
37 _outbuf_buffer_swap(ob, rects, n);
38}
39
40Outbuf *eng_window_new(Evas_Engine_Info_GL_Drm *info, Evas *e, struct gbm_device *gbm, struct gbm_surface *surface, int screen, int depth, int w, int h, int indirect EINA_UNUSED, int alpha, int rot, Render_Engine_Swap_Mode swap_mode)
41{
42 Outbuf *gw;
43 int context_attrs[3];
44 int config_attrs[40];
45 int major_version, minor_version;
46 int num_config, n = 0;
47 const GLubyte *vendor, *renderer, *version;
48 Eina_Bool blacklist = EINA_FALSE;
49 char *num;
50
51 /* try to allocate space for outbuf */
52 gw = calloc(1, sizeof(Outbuf));
53 if (!gw) return NULL;
54
55 /* set properties of outbuf */
56 win_count++;
57 gw->gbm = gbm;
58 gw->surface = surface;
59 gw->screen = screen;
60 gw->depth = depth;
61 gw->w = w;
62 gw->h = h;
63 gw->alpha = alpha;
64 gw->rot = rot;
65 gw->swap_mode = swap_mode;
66 gw->info = info;
67 gw->evas = e;
68
69 /* setup drm outbuf */
70 /* set drm card fd */
71 gw->priv.fd = info->info.fd;
72 /* try to setup the drm card for this outbuf */
73 if (!evas_drm_outbuf_setup(gw))
74 {
75 ERR("Could not setup drm outbuf");
76 free(gw);
77 return NULL;
78 }
79
80 if (gw->w < gw->priv.mode.hdisplay) gw->w = gw->priv.mode.hdisplay;
81 if (gw->h < gw->priv.mode.vdisplay) gw->h = gw->priv.mode.vdisplay;
82
83 info->info.output = gw->priv.fb;
84 // TODO: change vsync for drm egl
85 //gw->vsync = info->vsync;
86
87 gw->priv.num = NUM_BUFFERS;
88 /* check for buffer override */
89 // TODO: change for gbm_bo related drm buffer number.
90 if ((num = getenv("EVAS_GL_DRM_BUFFERS")))
91 {
92 gw->priv.num = atoi(num);
93
94 /* cap maximum # of buffers */
95 if (gw->priv.num <= 0) gw->priv.num = 1;
96 else if (gw->priv.num > 3) gw->priv.num = 3;
97 }
98 /* end drm outbuf setup */
99
100 /* setup gbm egl surface */
101 context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
102 context_attrs[1] = 2;
103 context_attrs[2] = EGL_NONE;
104
105 config_attrs[n++] = EGL_SURFACE_TYPE;
106 config_attrs[n++] = EGL_WINDOW_BIT;
107 config_attrs[n++] = EGL_RED_SIZE;
108 config_attrs[n++] = 1;
109 config_attrs[n++] = EGL_GREEN_SIZE;
110 config_attrs[n++] = 1;
111 config_attrs[n++] = EGL_BLUE_SIZE;
112 config_attrs[n++] = 1;
113 config_attrs[n++] = EGL_ALPHA_SIZE;
114 if (gw->alpha) config_attrs[n++] = 1;
115 else config_attrs[n++] = 0;
116 config_attrs[n++] = EGL_RENDERABLE_TYPE;
117 config_attrs[n++] = EGL_OPENGL_ES2_BIT;
118 config_attrs[n++] = EGL_NONE;
119
120 DBG("GBM DEVICE: %x", (unsigned int)gbm);
121 gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)(gw->gbm));
122 if (gw->egl_disp == EGL_NO_DISPLAY)
123 {
124 ERR("eglGetDisplay() fail. code=%#x", eglGetError());
125 eng_window_free(gw);
126 return NULL;
127 }
128 if (!eglInitialize(gw->egl_disp, &major_version, &minor_version))
129 {
130 ERR("eglInitialize() fail. code=%#x", eglGetError());
131 eng_window_free(gw);
132 return NULL;
133 }
134 eglBindAPI(EGL_OPENGL_ES_API);
135 if (eglGetError() != EGL_SUCCESS)
136 {
137 ERR("eglBindAPI() fail. code=%#x", eglGetError());
138 eng_window_free(gw);
139 return NULL;
140 }
141
142 num_config = 0;
143 if (!eglChooseConfig(gw->egl_disp, config_attrs, &gw->egl_config,
144 1, &num_config) || (num_config != 1))
145 {
146 ERR("eglChooseConfig() fail. code=%#x", eglGetError());
147 eng_window_free(gw);
148 return NULL;
149 }
150
151 gw->egl_surface[0] =
152 eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
153 (EGLNativeWindowType)gw->surface, NULL);
154 if (gw->egl_surface[0] == EGL_NO_SURFACE)
155 {
156 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
157 gw->surface, eglGetError());
158 eng_window_free(gw);
159 return NULL;
160 }
161
162 gw->egl_context[0] =
163 eglCreateContext(gw->egl_disp, gw->egl_config, context, context_attrs);
164 if (gw->egl_context[0] == EGL_NO_CONTEXT)
165 {
166 ERR("eglCreateContext() fail. code=%#x", eglGetError());
167 eng_window_free(gw);
168 return NULL;
169 }
170
171 if (context == EGL_NO_CONTEXT) context = gw->egl_context[0];
172
173 if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
174 gw->egl_surface[0], gw->egl_context[0]) == EGL_FALSE)
175 {
176 ERR("eglMakeCurrent() fail. code=%#x", eglGetError());
177 eng_window_free(gw);
178 return NULL;
179 }
180
181 vendor = glGetString(GL_VENDOR);
182 renderer = glGetString(GL_RENDERER);
183 version = glGetString(GL_VERSION);
184 if (!vendor) vendor = (unsigned char *)"-UNKNOWN-";
185 if (!renderer) renderer = (unsigned char *)"-UNKNOWN-";
186 if (!version) version = (unsigned char *)"-UNKNOWN-";
187 if (getenv("EVAS_GL_INFO"))
188 {
189 fprintf(stderr, "vendor: %s\n", vendor);
190 fprintf(stderr, "renderer: %s\n", renderer);
191 fprintf(stderr, "version: %s\n", version);
192 }
193
194 if (strstr((const char *)vendor, "Mesa Project"))
195 {
196 if (strstr((const char *)renderer, "Software Rasterizer"))
197 blacklist = EINA_TRUE;
198 }
199 if (strstr((const char *)renderer, "softpipe"))
200 blacklist = EINA_TRUE;
201 if (strstr((const char *)renderer, "llvmpipe"))
202 blacklist = EINA_TRUE;
203 if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST")))
204 {
205 ERR("OpenGL Driver blacklisted:");
206 ERR("Vendor: %s", (const char *)vendor);
207 ERR("Renderer: %s", (const char *)renderer);
208 ERR("Version: %s", (const char *)version);
209 eng_window_free(gw);
210 return NULL;
211 }
212
213 gw->gl_context = glsym_evas_gl_common_context_new();
214 if (!gw->gl_context)
215 {
216 eng_window_free(gw);
217 return NULL;
218 }
219
220 gw->gl_context->egldisp = gw->egl_disp;
221 gw->gl_context->eglctxt = gw->egl_context[0];
222
223 eng_window_use(gw);
224 glsym_evas_gl_common_context_resize(gw->gl_context, w, h, rot);
225
226 gw->surf = EINA_TRUE;
227
228 return gw;
229}
230
231void
232eng_window_free(Outbuf *gw)
233{
234 int ref = 0;
235
236 win_count--;
237 eng_window_use(gw);
238
239 if (gw == _evas_gl_drm_window) _evas_gl_drm_window = NULL;
240
241 if (gw->gl_context)
242 {
243 ref = gw->gl_context->references - 1;
244 glsym_evas_gl_common_context_free(gw->gl_context);
245 }
246
247 eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
248
249 if (gw->egl_context[0] != context)
250 eglDestroyContext(gw->egl_disp, gw->egl_context[0]);
251
252 if (gw->egl_surface[0] != EGL_NO_SURFACE)
253 eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
254
255//TODO: consider gbm_surface destroy or not.
256#if 0
257 if (gw->surface)
258 {
259 gbm_surface_destroy(gw->surface);
260 gw->info->info.surface = NULL;
261 }
262#endif
263
264 if (ref == 0)
265 {
266 if (context) eglDestroyContext(gw->egl_disp, context);
267 eglTerminate(gw->egl_disp);
268 eglReleaseThread();
269 context = EGL_NO_CONTEXT;
270 }
271 free(gw);
272}
273
274Eina_Bool
275eng_window_make_current(void *data, void *doit)
276{
277 Outbuf *gw;
278
279 if (!(gw = data)) return EINA_FALSE;
280
281 if (doit)
282 {
283 if (!eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
284 gw->egl_surface[0], gw->egl_context[0]))
285 return EINA_FALSE;
286 }
287 else
288 {
289 if (!eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE,
290 EGL_NO_SURFACE, EGL_NO_CONTEXT))
291 return EINA_FALSE;
292 }
293
294 return EINA_TRUE;
295}
296
297void
298eng_window_use(Outbuf *gw)
299{
300 Eina_Bool force = EINA_FALSE;
301
302 glsym_evas_gl_preload_render_lock(eng_window_make_current, gw);
303
304 if (_evas_gl_drm_window)
305 {
306 if (eglGetCurrentContext() != _evas_gl_drm_window->egl_context[0])
307 force = EINA_TRUE;
308 }
309
310 if ((_evas_gl_drm_window != gw) || (force))
311 {
312 if (_evas_gl_drm_window)
313 {
314 glsym_evas_gl_common_context_use(_evas_gl_drm_window->gl_context);
315 glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
316 }
317
318 _evas_gl_drm_window = gw;
319
320 if (gw)
321 {
322 if (gw->egl_surface[0] != EGL_NO_SURFACE)
323 {
324 if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
325 gw->egl_surface[0],
326 gw->egl_context[0]) == EGL_FALSE)
327 ERR("eglMakeCurrent() failed!");
328 }
329 }
330 }
331
332 if (gw) glsym_evas_gl_common_context_use(gw->gl_context);
333}
334
335void
336eng_window_unsurf(Outbuf *gw)
337{
338 if (!gw->surf) return;
339 if (!getenv("EVAS_GL_WIN_RESURF")) return;
340 if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", gw);
341
342 if (_evas_gl_drm_window)
343 glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
344 if (_evas_gl_drm_window == gw)
345 {
346 eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE,
347 EGL_NO_SURFACE, EGL_NO_CONTEXT);
348 if (gw->egl_surface[0] != EGL_NO_SURFACE)
349 eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
350 gw->egl_surface[0] = EGL_NO_SURFACE;
351
352 _evas_gl_drm_window = NULL;
353 }
354
355 gw->surf = EINA_FALSE;
356}
357
358void
359eng_window_resurf(Outbuf *gw)
360{
361 if (gw->surf) return;
362 if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", gw);
363
364 gw->egl_surface[0] =
365 eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
366 (EGLNativeWindowType)gw->surface, NULL);
367
368 if (gw->egl_surface[0] == EGL_NO_SURFACE)
369 {
370 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
371 gw->surface, eglGetError());
372 return;
373 }
374
375 if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0], gw->egl_surface[0],
376 gw->egl_context[0]) == EGL_FALSE)
377 ERR("eglMakeCurrent() failed!");
378
379 gw->surf = EINA_TRUE;
380}
381
382Context_3D *
383eng_gl_context_new(Outbuf *gw)
384{
385 Context_3D *ctx;
386 int context_attrs[3] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
387
388 if (!gw) return NULL;
389
390 ctx = calloc(1, sizeof(Context_3D));
391 if (!ctx) return NULL;
392
393 ctx->context = eglCreateContext(gw->egl_disp, gw->egl_config,
394 gw->egl_context[0], context_attrs);
395
396 if (!ctx->context)
397 {
398 ERR("EGL context creation failed.");
399 goto error;
400 }
401
402 ctx->display = gw->egl_disp;
403 ctx->surface = gw->egl_surface[0];
404
405 return ctx;
406
407error:
408 free(ctx);
409 return NULL;
410}
411
412void
413eng_gl_context_free(Context_3D *ctx)
414{
415 eglDestroyContext(ctx->display, ctx->context);
416 free(ctx);
417}
418
419void
420eng_gl_context_use(Context_3D *ctx)
421{
422 if (eglMakeCurrent(ctx->display, ctx->surface,
423 ctx->surface, ctx->context) == EGL_FALSE)
424 {
425 ERR("eglMakeCurrent() failed.");
426 }
427}
428
429void
430eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth EINA_UNUSED)
431{
432 ob->w = w;
433 ob->h = h;
434 ob->rot = rot;
435 eng_window_use(ob);
436 glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot);
437
438 //TODO: need drm gbm surface destroy & re-create.?
439}
440
441int
442eng_outbuf_get_rot(Outbuf *ob)
443{
444 return ob->rot;
445}
446
447Render_Engine_Swap_Mode
448eng_outbuf_swap_mode(Outbuf *ob)
449{
450 if (ob->swap_mode == MODE_AUTO && extn_have_buffer_age)
451 {
452 Render_Engine_Swap_Mode swap_mode;
453
454 EGLint age = 0;
455
456 if (!eglQuerySurface(ob->egl_disp,
457 ob->egl_surface[0],
458 EGL_BUFFER_AGE_EXT, &age))
459 age = 0;
460
461 if (age == 1) swap_mode = MODE_COPY;
462 else if (age == 2) swap_mode = MODE_DOUBLE;
463 else if (age == 3) swap_mode = MODE_TRIPLE;
464 else if (age == 4) swap_mode = MODE_QUADRUPLE;
465 else swap_mode = MODE_FULL;
466 if ((int)age != ob->prev_age) swap_mode = MODE_FULL;
467 ob->prev_age = age;
468
469 return swap_mode;
470 }
471
472 return ob->swap_mode;
473}
474
475Eina_Bool
476eng_outbuf_region_first_rect(Outbuf *ob)
477{
478 ob->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM;
479
480 glsym_evas_gl_preload_render_lock(eng_preload_make_current, ob);
481 eng_window_use(ob);
482 if (!_re_wincheck(ob)) return EINA_TRUE;
483
484 glsym_evas_gl_common_context_resize(ob->gl_context,
485 ob->w, ob->h,
486 ob->rot);
487
488 glsym_evas_gl_common_context_flush(ob->gl_context);
489 glsym_evas_gl_common_context_newframe(ob->gl_context);
490
491 return EINA_FALSE;
492}
493
494void*
495eng_outbuf_new_region_for_update(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)
496{
497 if (w == ob->w && h == ob->h)
498 {
499 ob->gl_context->master_clip.enabled = EINA_FALSE;
500 }
501 else
502 {
503 ob->gl_context->master_clip.enabled = EINA_TRUE;
504 ob->gl_context->master_clip.x = x;
505 ob->gl_context->master_clip.y = y;
506 ob->gl_context->master_clip.w = w;
507 ob->gl_context->master_clip.h = h;
508 }
509 return ob->gl_context->def_surface;
510}
511
512void
513eng_outbuf_push_updated_region(Outbuf *ob, RGBA_Image *update EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
514{
515 /* Is it really necessary to flush per region ? Shouldn't we be able to
516 still do that for the full canvas when doing partial update */
517 if (!_re_wincheck(ob)) return;
518 ob->draw.drew = EINA_TRUE;
519 glsym_evas_gl_common_context_flush(ob->gl_context);
520}
521
522void
523eng_outbuf_push_free_region_for_update(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
524{
525 /* Nothing to do here as we don't really create an image per area */
526}
527
528void
529eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode)
530{
531 if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
532
533 if (!_re_wincheck(ob)) goto end;
534 if (!ob->draw.drew) goto end;
535
536 ob->draw.drew = EINA_FALSE;
537 eng_window_use(ob);
538 glsym_evas_gl_common_context_done(ob->gl_context);
539
540 if (!ob->vsync)
541 {
542 if (ob->info->vsync) eglSwapInterval(ob->egl_disp, 1);
543 else eglSwapInterval(ob->egl_disp, 0);
544 ob->vsync = 1;
545 }
546 if (ob->info->callback.pre_swap)
547 {
548 ob->info->callback.pre_swap(ob->info->callback.data, ob->evas);
549 }
550// TODO: Check eglSwapBuffersWithDamage for gl_drm and apply
551#if 0
552 if ((glsym_eglSwapBuffersWithDamage) && (ob->swap_mode != MODE_FULL))
553
554 {
555 EGLint num = 0, *result = NULL, i = 0;
556 Tilebuf_Rect *r;
557
558 // if partial swaps can be done use re->rects
559 num = eina_inlist_count(EINA_INLIST_GET(rects));
560 if (num > 0)
561 {
562 result = alloca(sizeof(EGLint) * 4 * num);
563 EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r)
564 {
565 int gw, gh;
566
567 gw = ob->gl_context->w;
568 gh = ob->gl_context->h;
569 switch (ob->rot)
570 {
571 case 0:
572 result[i + 0] = r->x;
573 result[i + 1] = gh - (r->y + r->h);
574 result[i + 2] = r->w;
575 result[i + 3] = r->h;
576 break;
577 case 90:
578 result[i + 0] = r->y;
579 result[i + 1] = r->x;
580 result[i + 2] = r->h;
581 result[i + 3] = r->w;
582 break;
583 case 180:
584 result[i + 0] = gw - (r->x + r->w);
585 result[i + 1] = r->y;
586 result[i + 2] = r->w;
587 result[i + 3] = r->h;
588 break;
589 case 270:
590 result[i + 0] = gh - (r->y + r->h);
591 result[i + 1] = gw - (r->x + r->w);
592 result[i + 2] = r->h;
593 result[i + 3] = r->w;
594 break;
595 default:
596 result[i + 0] = r->x;
597 result[i + 1] = gh - (r->y + r->h);
598 result[i + 2] = r->w;
599 result[i + 3] = r->h;
600 break;
601 }
602 i += 4;
603 }
604 glsym_eglSwapBuffersWithDamage(ob->egl_disp,
605 ob->egl_surface[0],
606 result, num);
607 }
608 }
609 else
610#endif
611 eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]);
612
613 if (ob->info->callback.post_swap)
614 {
615 ob->info->callback.post_swap(ob->info->callback.data, ob->evas);
616 }
617
618 //Flush GL Surface data to Framebuffer
619 _outbuf_flush_famebuffer(ob);
620
621 ob->frame_cnt++;
622
623 end:
624 //TODO: Need render unlock after drm page flip?
625 glsym_evas_gl_preload_render_unlock(eng_preload_make_current, ob);
626}
627
628Evas_Engine_GL_Context *
629eng_outbuf_gl_context_get(Outbuf *ob)
630{
631 return ob->gl_context;
632}
633
634void *
635eng_outbuf_egl_display_get(Outbuf *ob)
636{
637 return ob->egl_disp;
638}
diff --git a/src/modules/evas/engines/gl_drm/evas_engine.c b/src/modules/evas/engines/gl_drm/evas_engine.c
new file mode 100644
index 0000000000..d6ef083c12
--- /dev/null
+++ b/src/modules/evas/engines/gl_drm/evas_engine.c
@@ -0,0 +1,1015 @@
1#include "evas_common_private.h" /* Also includes international specific stuff */
2#include "evas_engine.h"
3#include <Ecore_Drm.h>
4
5#ifdef HAVE_DLSYM
6# include <dlfcn.h> /* dlopen,dlclose,etc */
7#else
8# error gl_drm should not get compiled if dlsym is not found on the system!
9#endif
10
11#ifdef EVAS_CSERVE2
12# include "evas_cs2_private.h"
13#endif
14
15#define EVAS_GL_NO_GL_H_CHECK 1
16#include "Evas_GL.h"
17
18#define EVAS_GL_UPDATE_TILE_SIZE 16
19
20#ifndef EGL_NATIVE_PIXMAP_KHR
21# define EGL_NATIVE_PIXMAP_KHR 0x30b0
22#endif
23
24/* external variables */
25int _evas_engine_gl_drm_log_dom = -1;
26int extn_have_buffer_age = 1;
27
28/* external dynamic loaded Evas_GL function pointers */
29Evas_GL_Common_Image_Call glsym_evas_gl_common_image_ref = NULL;
30Evas_GL_Common_Image_Call glsym_evas_gl_common_image_unref = NULL;
31Evas_GL_Common_Image_Call glsym_evas_gl_common_image_free = NULL;
32Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_disable = NULL;
33Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_enable = NULL;
34Evas_GL_Common_Image_New_From_Data glsym_evas_gl_common_image_new_from_data = NULL;
35Evas_GL_Common_Context_Call glsym_evas_gl_common_image_all_unload = NULL;
36Evas_GL_Preload glsym_evas_gl_preload_init = NULL;
37Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL;
38EVGL_Engine_Call glsym_evgl_engine_shutdown = NULL;
39Evas_Gl_Symbols glsym_evas_gl_symbols = NULL;
40
41Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL;
42Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush = NULL;
43Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free = NULL;
44Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use = NULL;
45Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe = NULL;
46Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done = NULL;
47Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize = NULL;
48Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump = NULL;
49Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL;
50Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL;
51Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL;
52
53/* local structures */
54typedef struct _Render_Engine Render_Engine;
55
56struct _Render_Engine
57{
58 Render_Engine_GL_Generic generic;
59};
60
61/* local function prototype types */
62typedef void (*_eng_fn) (void);
63typedef _eng_fn (*glsym_func_eng_fn) ();
64typedef void (*glsym_func_void) ();
65typedef void *(*glsym_func_void_ptr) ();
66typedef int (*glsym_func_int) ();
67typedef unsigned int (*glsym_func_uint) ();
68typedef const char *(*glsym_func_const_char_ptr) ();
69
70/* dynamic loaded local egl function pointers */
71_eng_fn (*glsym_eglGetProcAddress)(const char *a) = NULL;
72void *(*glsym_eglCreateImage)(EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL;
73void (*glsym_eglDestroyImage)(EGLDisplay a, void *b) = NULL;
74void (*glsym_glEGLImageTargetTexture2DOES)(int a, void *b) = NULL;
75unsigned int (*glsym_eglSwapBuffersWithDamage)(EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL;
76
77/* local function prototypes */
78static void gl_symbols(void);
79static void gl_extn_veto(Render_Engine *re);
80
81static void *evgl_eng_display_get(void *data);
82static void *evgl_eng_evas_surface_get(void *data);
83static int evgl_eng_make_current(void *data, void *surface, void *context, int flush);
84static void *evgl_eng_native_window_create(void *data);
85static int evgl_eng_native_window_destroy(void *data, void *native_window);
86static void *evgl_eng_window_surface_create(void *data, void *native_window);
87static int evgl_eng_window_surface_destroy(void *data, void *surface);
88static void *evgl_eng_context_create(void *data, void *share_ctx);
89static int evgl_eng_context_destroy(void *data, void *context);
90static const char *evgl_eng_string_get(void *data);
91static void *evgl_eng_proc_address_get(const char *name);
92static int evgl_eng_rotation_angle_get(void *data);
93
94static void _re_winfree(Render_Engine *re);
95
96/* local variables */
97static Ecore_Drm_Device *drm_dev = NULL;
98static Eina_Bool initted = EINA_FALSE;
99static int gl_wins = 0;
100
101/* local inline functions */
102static inline Outbuf *
103eng_get_ob(Render_Engine *re)
104{
105 return re->generic.software.ob;
106}
107
108static inline void
109_drm_device_shutdown(Evas_Engine_Info_GL_Drm *info)
110{
111 if (!info) return;
112 /* check if we already opened the card. if so, close it */
113 if ((info->info.fd >= 0) && (info->info.own_fd))
114 {
115 ecore_drm_device_close(drm_dev);
116 info->info.fd = -1;
117 ecore_drm_device_free(drm_dev);
118 }
119}
120
121/* function tables - filled in later (func and parent func) */
122static Evas_Func func, pfunc;
123static const EVGL_Interface evgl_funcs =
124{
125 evgl_eng_display_get,
126 evgl_eng_evas_surface_get,
127 evgl_eng_native_window_create,
128 evgl_eng_native_window_destroy,
129 evgl_eng_window_surface_create,
130 evgl_eng_window_surface_destroy,
131 evgl_eng_context_create,
132 evgl_eng_context_destroy,
133 evgl_eng_make_current,
134 evgl_eng_proc_address_get,
135 evgl_eng_string_get,
136 evgl_eng_rotation_angle_get
137};
138
139/* local functions */
140static void
141gl_symbols(void)
142{
143 static Eina_Bool done = EINA_FALSE;
144
145 if (done) return;
146
147#define LINK2GENERIC(sym) \
148 glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
149
150 // Get function pointer to evas_gl_common that is now provided through the link of GL_Generic.
151 LINK2GENERIC(evas_gl_common_image_all_unload);
152 LINK2GENERIC(evas_gl_common_image_ref);
153 LINK2GENERIC(evas_gl_common_image_unref);
154 LINK2GENERIC(evas_gl_common_image_new_from_data);
155 LINK2GENERIC(evas_gl_common_image_native_disable);
156 LINK2GENERIC(evas_gl_common_image_free);
157 LINK2GENERIC(evas_gl_common_image_native_enable);
158 LINK2GENERIC(evas_gl_common_context_new);
159 LINK2GENERIC(evas_gl_common_context_flush);
160 LINK2GENERIC(evas_gl_common_context_free);
161 LINK2GENERIC(evas_gl_common_context_use);
162 LINK2GENERIC(evas_gl_common_context_newframe);
163 LINK2GENERIC(evas_gl_common_context_done);
164 LINK2GENERIC(evas_gl_common_context_resize);
165 LINK2GENERIC(evas_gl_common_buffer_dump);
166 LINK2GENERIC(evas_gl_preload_render_lock);
167 LINK2GENERIC(evas_gl_preload_render_unlock);
168 LINK2GENERIC(evas_gl_preload_render_relax);
169 LINK2GENERIC(evas_gl_preload_init);
170 LINK2GENERIC(evas_gl_preload_shutdown);
171 LINK2GENERIC(evgl_engine_shutdown);
172 LINK2GENERIC(evas_gl_symbols);
173
174#define FINDSYM(dst, sym, typ) \
175 if (glsym_eglGetProcAddress) { \
176 if (!dst) dst = (typ)glsym_eglGetProcAddress(sym); \
177 } else { \
178 if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym); \
179 }
180
181 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressKHR", glsym_func_eng_fn);
182 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressEXT", glsym_func_eng_fn);
183 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressARB", glsym_func_eng_fn);
184 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddress", glsym_func_eng_fn);
185
186 glsym_evas_gl_symbols((void*)glsym_eglGetProcAddress);
187
188 FINDSYM(glsym_eglCreateImage, "eglCreateImageKHR", glsym_func_void_ptr);
189 FINDSYM(glsym_eglCreateImage, "eglCreateImageEXT", glsym_func_void_ptr);
190 FINDSYM(glsym_eglCreateImage, "eglCreateImageARB", glsym_func_void_ptr);
191 FINDSYM(glsym_eglCreateImage, "eglCreateImage", glsym_func_void_ptr);
192
193 FINDSYM(glsym_eglDestroyImage, "eglDestroyImageKHR", glsym_func_void);
194 FINDSYM(glsym_eglDestroyImage, "eglDestroyImageEXT", glsym_func_void);
195 FINDSYM(glsym_eglDestroyImage, "eglDestroyImageARB", glsym_func_void);
196 FINDSYM(glsym_eglDestroyImage, "eglDestroyImage", glsym_func_void);
197
198 FINDSYM(glsym_glEGLImageTargetTexture2DOES,
199 "glEGLImageTargetTexture2DOES", glsym_func_void);
200
201 FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageEXT",
202 glsym_func_uint);
203 FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageINTEL",
204 glsym_func_uint);
205 FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage",
206 glsym_func_uint);
207
208 done = EINA_TRUE;
209}
210
211static void
212gl_extn_veto(Render_Engine *re)
213{
214 const char *str = NULL;
215 str = eglQueryString(eng_get_ob(re)->egl_disp, EGL_EXTENSIONS);
216 if (str)
217 {
218 if (getenv("EVAS_GL_INFO"))
219 printf("EGL EXTN:\n%s\n", str);
220 if (!strstr(str, "EGL_EXT_buffer_age"))
221 {
222 extn_have_buffer_age = 0;
223 }
224 if (!strstr(str, "EGL_EXT_swap_buffers_with_damage"))
225 {
226 glsym_eglSwapBuffersWithDamage = NULL;
227 }
228 }
229 else
230 {
231 if (getenv("EVAS_GL_INFO"))
232 printf("NO EGL EXTN!\n");
233 extn_have_buffer_age = 0;
234 }
235}
236
237static void *
238evgl_eng_display_get(void *data)
239{
240 Render_Engine *re = (Render_Engine *)data;
241
242 if (!re)
243 {
244 ERR("Invalid Render Engine Data!");
245 return NULL;
246 }
247
248 if (eng_get_ob(re))
249 return (void*)eng_get_ob(re)->egl_disp;
250 else
251 return NULL;
252}
253
254static void *
255evgl_eng_evas_surface_get(void *data)
256{
257 Render_Engine *re = (Render_Engine *)data;
258
259 if (!re)
260 {
261 ERR("Invalid Render Engine Data!");
262 return NULL;
263 }
264
265 if (eng_get_ob(re))
266 return (void*)eng_get_ob(re)->egl_surface[0];
267 else
268 return NULL;
269}
270
271static int
272evgl_eng_make_current(void *data, void *surface, void *context, int flush)
273{
274 Render_Engine *re = (Render_Engine *)data;
275 EGLContext ctx;
276 EGLSurface sfc;
277 EGLDisplay dpy;
278 int ret = 0;
279
280 if (!re)
281 {
282 ERR("Invalid Render Engine Data!");
283 return 0;
284 }
285
286 dpy = eng_get_ob(re)->egl_disp;
287 ctx = (EGLContext)context;
288 sfc = (EGLSurface)surface;
289
290 if ((!context) && (!surface))
291 {
292 ret = eglMakeCurrent(dpy, EGL_NO_SURFACE,
293 EGL_NO_SURFACE, EGL_NO_CONTEXT);
294 if (!ret)
295 {
296 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
297 return 0;
298 }
299 return 1;
300 }
301
302 if ((eglGetCurrentContext() != ctx) ||
303 (eglGetCurrentSurface(EGL_READ) != sfc) ||
304 (eglGetCurrentSurface(EGL_DRAW) != sfc) )
305 {
306 if (flush) eng_window_use(NULL);
307
308 ret = eglMakeCurrent(dpy, sfc, sfc, ctx);
309 if (!ret)
310 {
311 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
312 return 0;
313 }
314 }
315
316 return 1;
317}
318
319static void *
320evgl_eng_native_window_create(void *data)
321{
322 Render_Engine *re = (Render_Engine *)data;
323 struct gbm_surface *surface;
324 Evas_Engine_Info_GL_Drm *info;
325
326 if (!re)
327 {
328 ERR("Invalid Render Engine Data!");
329 return NULL;
330 }
331
332 info = eng_get_ob(re)->info;
333 if (!info)
334 {
335 ERR("Invalid Evas Engine GL_DRM Info!");
336 return NULL;
337 }
338
339 surface = gbm_surface_create(info->info.gbm, 1, 1,
340 info->info.format,
341 info->info.flags);
342 if (!surface)
343 {
344 ERR("Could not create gl drm window: %m");
345 }
346
347 return (void*)surface;
348}
349
350static int
351evgl_eng_native_window_destroy(void *data, void *native_window)
352{
353 Render_Engine *re = (Render_Engine *)data;
354
355 if (!re)
356 {
357 ERR("Invalid Render Engine Data!");
358 return 0;
359 }
360
361 if (!native_window)
362 {
363 ERR("Inavlid native surface.");
364 return 0;
365 }
366
367 gbm_surface_destroy((struct gbm_surface*)native_window);
368 return 1;
369}
370
371static void *
372evgl_eng_window_surface_create(void *data, void *native_window)
373{
374 Render_Engine *re = (Render_Engine *)data;
375 EGLSurface surface = EGL_NO_SURFACE;
376
377 if (!re)
378 {
379 ERR("Invalid Render Engine Data!");
380 return NULL;
381 }
382
383 // Create resource surface for EGL
384 surface = eglCreateWindowSurface(eng_get_ob(re)->egl_disp,
385 eng_get_ob(re)->egl_config,
386 (EGLNativeWindowType)native_window,
387 NULL);
388 if (!surface)
389 {
390 ERR("Creating window surface failed. Error: %#x.", eglGetError());
391 return NULL;
392 }
393
394 return (void*)surface;
395}
396
397static int
398evgl_eng_window_surface_destroy(void *data, void *surface)
399{
400 Render_Engine *re = (Render_Engine *)data;
401 EGLBoolean ret = EGL_FALSE;
402
403 if (!re)
404 {
405 ERR("Invalid Render Engine Data!");
406 return 0;
407 }
408
409 if (!surface)
410 {
411 ERR("Invalid surface.");
412 return 0;
413 }
414
415 ret = eglDestroySurface(eng_get_ob(re)->egl_disp, (EGLSurface)surface);
416
417 if (ret == EGL_TRUE) return 1;
418
419 return 0;
420}
421
422static void *
423evgl_eng_context_create(void *data, void *share_ctx)
424{
425 Render_Engine *re = (Render_Engine *)data;
426 EGLContext context = EGL_NO_CONTEXT;
427 int context_attrs[3];
428
429 if (!re)
430 {
431 ERR("Invalid Render Engine Data!");
432 return NULL;
433 }
434
435 context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
436 context_attrs[1] = 2;
437 context_attrs[2] = EGL_NONE;
438
439 // Share context already assumes that it's sharing with evas' context
440 if (share_ctx)
441 {
442 context = eglCreateContext(eng_get_ob(re)->egl_disp,
443 eng_get_ob(re)->egl_config,
444 (EGLContext)share_ctx,
445 context_attrs);
446 }
447 else
448 {
449 context = eglCreateContext(eng_get_ob(re)->egl_disp,
450 eng_get_ob(re)->egl_config,
451 eng_get_ob(re)->egl_context[0], // Evas' GL Context
452 context_attrs);
453 }
454
455 if (!context)
456 {
457 ERR("Engine Context Creations Failed. Error: %#x.", eglGetError());
458 return NULL;
459 }
460
461 return (void*)context;
462}
463
464static int
465evgl_eng_context_destroy(void *data, void *context)
466{
467 Render_Engine *re = (Render_Engine *)data;
468 EGLBoolean ret = EGL_FALSE;
469
470 if ((!re) || (!context))
471 {
472 ERR("Invalid Render Input Data. Engine: %p, Context: %p", data, context);
473 return 0;
474 }
475
476 ret = eglDestroyContext(eng_get_ob(re)->egl_disp, (EGLContext)context);
477
478 if (ret == EGL_TRUE) return 1;
479
480 return 0;
481}
482
483static const char *
484evgl_eng_string_get(void *data)
485{
486 Render_Engine *re = (Render_Engine *)data;
487
488 if (!re)
489 {
490 ERR("Invalid Render Engine Data!");
491 return NULL;
492 }
493
494 return eglQueryString(eng_get_ob(re)->egl_disp, EGL_EXTENSIONS);
495
496}
497
498static void *
499evgl_eng_proc_address_get(const char *name)
500{
501 if (glsym_eglGetProcAddress) return glsym_eglGetProcAddress(name);
502 return dlsym(RTLD_DEFAULT, name);
503}
504
505static int
506evgl_eng_rotation_angle_get(void *data)
507{
508 Render_Engine *re = (Render_Engine *)data;
509
510 if (!re)
511 {
512 ERR("Invalid Render Engine Data!");
513 return 0;
514 }
515
516 if ((eng_get_ob(re)) && (eng_get_ob(re)->gl_context))
517 return eng_get_ob(re)->gl_context->rot;
518 else
519 {
520 ERR("Unable to retrieve rotation angle.");
521 return 0;
522 }
523}
524
525static void
526_re_winfree(Render_Engine *re)
527{
528 if (!re) return;
529 if (!eng_get_ob(re)->surf) return;
530 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re));
531 eng_window_unsurf(eng_get_ob(re));
532}
533
534/* engine specific override functions */
535static void *
536eng_info(Evas *eo_e EINA_UNUSED)
537{
538 Evas_Engine_Info_GL_Drm *info;
539
540 /* try to allocate space for our engine info */
541 if (!(info = calloc(1, sizeof(Evas_Engine_Info_GL_Drm))))
542 return NULL;
543
544 info->magic.magic = rand();
545 info->render_mode = EVAS_RENDER_MODE_BLOCKING;
546
547 return info;
548}
549
550static void
551eng_info_free(Evas *eo_e EINA_UNUSED, void *in)
552{
553 Evas_Engine_Info_GL_Drm *info;
554
555 if (info = (Evas_Engine_Info_GL_Drm *)in)
556 free(info);
557}
558
559static int
560eng_setup(Evas *eo_e, void *in)
561{
562 Evas_Engine_Info_GL_Drm *info = NULL;
563 Evas_Public_Data *epd = NULL;
564 Render_Engine *re = NULL;
565 Render_Engine_Swap_Mode swap_mode = MODE_FULL;
566 const char *s;
567
568 /* try to cast to our engine info structure */
569 if (!(info = (Evas_Engine_Info_GL_Drm *)in)) return 0;
570
571 /* try to get the evas public data */
572 if (!(epd = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS))) return 0;
573
574 if ((s = getenv("EVAS_GL_SWAP_MODE")))
575 {
576 if ((!strcasecmp(s, "full")) ||
577 (!strcasecmp(s, "f")))
578 swap_mode = MODE_FULL;
579 else if ((!strcasecmp(s, "copy")) ||
580 (!strcasecmp(s, "c")))
581 swap_mode = MODE_COPY;
582 else if ((!strcasecmp(s, "double")) ||
583 (!strcasecmp(s, "d")) ||
584 (!strcasecmp(s, "2")))
585 swap_mode = MODE_DOUBLE;
586 else if ((!strcasecmp(s, "triple")) ||
587 (!strcasecmp(s, "t")) ||
588 (!strcasecmp(s, "3")))
589 swap_mode = MODE_TRIPLE;
590 else if ((!strcasecmp(s, "quadruple")) ||
591 (!strcasecmp(s, "q")) ||
592 (!strcasecmp(s, "4")))
593 swap_mode = MODE_QUADRUPLE;
594 }
595 else
596 {
597 swap_mode = MODE_FULL;
598 }
599
600 /* check for existing engine output */
601 if (!epd->engine.data.output)
602 {
603 Outbuf *ob;
604 Render_Engine_Merge_Mode merge_mode = MERGE_FULL;
605
606 if (!initted)
607 {
608 evas_common_cpu_init();
609 evas_common_blend_init();
610 evas_common_image_init();
611 evas_common_convert_init();
612 evas_common_scale_init();
613 evas_common_rectangle_init();
614 evas_common_polygon_init();
615 evas_common_line_init();
616 evas_common_font_init();
617 evas_common_draw_init();
618 evas_common_tilebuf_init();
619 glsym_evas_gl_preload_init();
620 }
621
622 /* if we have no drm device, get one */
623 if (info->info.fd < 0)
624 {
625 /* try to init drm (this includes openening the card & tty) */
626 if (!ecore_drm_init())
627 return 0;
628
629 /* try getting the default drm device */
630 if (!(drm_dev = ecore_drm_device_find(NULL, NULL)))
631 {
632 _drm_device_shutdown(info);
633 return 0;
634 }
635
636 /* check if we already opened the drm device with ecore_evas */
637 if (info->info.fd < 0)
638 {
639 /* try to open the drm ourselfs (most likely because we get called from expedite) */
640 if (!ecore_drm_device_open(drm_dev))
641 {
642 _drm_device_shutdown(info);
643 return 0;
644 }
645 info->info.own_fd = EINA_TRUE;
646 info->info.fd = ecore_drm_device_fd_get(drm_dev);
647 }
648 /* try to init drm (this includes openening tty) */
649 /* FIXME replace with ecore_drm_tty */
650 if (!evas_drm_init(info))
651 {
652 _drm_device_shutdown(info);
653 return 0;
654 }
655 }
656
657 if (!(info->info.gbm) || !(info->info.surface))
658 {
659 if (!evas_drm_gbm_init(info, epd->output.w, epd->output.h))
660 {
661 evas_drm_shutdown(info);
662 _drm_device_shutdown(info);
663 return 0;
664 }
665 }
666
667 DBG("FD: %d, GBM_DEVICE: 0x%x, GBM_SURFACE: 0x%x",
668 info->info.fd, (unsigned int)info->info.gbm,
669 (unsigned int)info->info.surface);
670
671 re = calloc(1, sizeof(Render_Engine));
672 if (!re) return 0;
673
674 /* try to create new outbuf */
675 ob = eng_window_new(info, eo_e,
676 info->info.gbm,
677 info->info.surface,
678 info->info.screen,
679 info->info.depth,
680 epd->output.w, epd->output.h,
681 info->indirect,
682 info->info.destination_alpha,
683 info->info.rotation,
684 swap_mode);
685 if (!ob)
686 {
687 /* shutdown destroy gbm surface & shutdown gbm device */
688 evas_drm_gbm_shutdown(info);
689 /* shutdown tty */
690 /* FIXME use ecore_drm_tty */
691 evas_drm_shutdown(info);
692 _drm_device_shutdown(info);
693 free(re);
694 return 0;
695 }
696
697
698 if (!evas_render_engine_gl_generic_init(&re->generic, ob,
699 eng_outbuf_swap_mode,
700 eng_outbuf_get_rot,
701 eng_outbuf_reconfigure,
702 eng_outbuf_region_first_rect,
703 eng_outbuf_new_region_for_update,
704 eng_outbuf_push_updated_region,
705 eng_outbuf_push_free_region_for_update,
706 NULL,
707 eng_outbuf_flush,
708 eng_window_free,
709 eng_window_use,
710 eng_outbuf_gl_context_get,
711 eng_outbuf_egl_display_get,
712 eng_gl_context_new,
713 eng_gl_context_use,
714 &evgl_funcs,
715 epd->output.w, epd->output.h))
716 {
717 /* free outbuf */
718 eng_window_free(ob);
719 /* shutdown destroy gbm surface & shutdown gbm device */
720 evas_drm_gbm_shutdown(info);
721 /* shutdown tty */
722 /* FIXME use ecore_drm_tty */
723 evas_drm_shutdown(info);
724 _drm_device_shutdown(info);
725 free(re);
726 return 0;
727 }
728
729 /* tell the engine to use this render_engine for output */
730 epd->engine.data.output = re;
731 gl_wins++;
732
733 if ((s = getenv("EVAS_GL_PARTIAL_MERGE")))
734 {
735 if ((!strcmp(s, "bounding")) ||
736 (!strcmp(s, "b")))
737 merge_mode = MERGE_BOUNDING;
738 else if ((!strcmp(s, "full")) ||
739 (!strcmp(s, "f")))
740 merge_mode = MERGE_FULL;
741 }
742
743 evas_render_engine_software_generic_merge_mode_set(&re->generic.software, merge_mode);
744
745 if (!initted)
746 {
747 gl_extn_veto(re);
748 initted = EINA_TRUE;
749 }
750 }
751 else
752 {
753 re = epd->engine.data.output;
754
755 if (eng_get_ob(re) && _re_wincheck(eng_get_ob(re)))
756 {
757 if ((eng_get_ob(re)->info->info.gbm != eng_get_ob(re)->gbm) ||
758 (eng_get_ob(re)->info->info.surface != eng_get_ob(re)->surface) ||
759 (eng_get_ob(re)->info->info.screen != eng_get_ob(re)->screen) ||
760 (eng_get_ob(re)->info->info.depth != eng_get_ob(re)->depth) ||
761 (eng_get_ob(re)->info->info.destination_alpha != eng_get_ob(re)->alpha))
762 {
763 Outbuf *ob;
764
765 eng_get_ob(re)->gl_context->references++;
766 gl_wins--;
767
768 ob = eng_window_new(info, eo_e,
769 eng_get_ob(re)->info->info.gbm,
770 eng_get_ob(re)->info->info.surface,
771 eng_get_ob(re)->info->info.screen,
772 eng_get_ob(re)->info->info.depth,
773 epd->output.w, epd->output.h,
774 eng_get_ob(re)->info->indirect,
775 eng_get_ob(re)->info->info.destination_alpha,
776 eng_get_ob(re)->info->info.rotation,
777 swap_mode);
778
779 eng_window_free(eng_get_ob(re));
780 re->generic.software.ob = NULL;
781
782 eng_window_use(ob);
783 if (ob)
784 {
785 evas_render_engine_software_generic_update(&re->generic.software, ob,
786 epd->output.w, epd->output.h);
787
788 gl_wins++;
789 eng_get_ob(re)->gl_context->references--;
790 }
791 }
792 else if ((eng_get_ob(re)->w != epd->output.w) ||
793 (eng_get_ob(re)->h != epd->output.h) ||
794 (eng_get_ob(re)->info->info.rotation != eng_get_ob(re)->rot))
795 {
796 Outbuf *ob;
797
798 eng_get_ob(re)->gl_context->references++;
799 gl_wins--;
800
801 eng_window_free(eng_get_ob(re));
802 re->generic.software.ob = NULL;
803 evas_drm_gbm_shutdown(eng_get_ob(re)->info);
804 if (!evas_drm_gbm_init(info, epd->output.w, epd->output.h))
805 return 0;
806
807 DBG("FD: %d, GBM_DEVICE: 0x%x, GBM_SURFACE: 0x%x",
808 info->info.fd, (unsigned int)info->info.gbm,
809 (unsigned int)info->info.surface);
810
811 ob = eng_window_new(info, eo_e,
812 info->info.gbm,
813 info->info.surface,
814 info->info.screen,
815 info->info.depth,
816 epd->output.w, epd->output.h,
817 info->indirect,
818 info->info.destination_alpha,
819 info->info.rotation,
820 swap_mode);
821
822 eng_window_use(ob);
823 if (ob)
824 {
825 evas_render_engine_software_generic_update(&re->generic.software, ob,
826 epd->output.w, epd->output.h);
827
828 gl_wins++;
829 eng_get_ob(re)->gl_context->references--;
830 }
831 }
832 }
833 }
834 if (!eng_get_ob(re))
835 {
836 free(re);
837 return 0;
838 }
839
840 if (!epd->engine.data.output)
841 {
842 if (eng_get_ob(re))
843 {
844 eng_window_free(eng_get_ob(re));
845 gl_wins--;
846 evas_drm_gbm_shutdown(info);
847 /* shutdown tty */
848 /* FIXME use ecore_drm_tty */
849 evas_drm_shutdown(info);
850 _drm_device_shutdown(info);
851 }
852 free(re);
853 return 0;
854 }
855
856 evas_render_engine_software_generic_tile_strict_set(&re->generic.software, EINA_TRUE);
857
858 if (!epd->engine.data.context)
859 {
860 epd->engine.data.context =
861 epd->engine.func->context_new(epd->engine.data.output);
862 }
863 eng_window_use(eng_get_ob(re));
864
865 return 1;
866}
867
868static void
869eng_output_free(void *data)
870{
871 Render_Engine *re;
872
873 re = (Render_Engine *)data;
874
875 if (re)
876 {
877 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re));
878
879 if (gl_wins == 1) glsym_evgl_engine_shutdown(re);
880
881 evas_drm_gbm_shutdown(eng_get_ob(re)->info);
882 /* shutdown tty */
883 /* FIXME use ecore_drm_tty */
884 evas_drm_shutdown(eng_get_ob(re)->info);
885 _drm_device_shutdown(eng_get_ob(re)->info);
886
887 //evas_render_engine_software_generic_clean() frees ob.
888 evas_render_engine_software_generic_clean(&re->generic.software);
889
890 gl_wins--;
891
892 free(re);
893 }
894 if ((initted == EINA_TRUE) && (gl_wins == 0))
895 {
896 glsym_evas_gl_preload_shutdown();
897 evas_common_image_shutdown();
898 evas_common_font_shutdown();
899 initted = EINA_FALSE;
900 }
901}
902
903Eina_Bool
904eng_preload_make_current(void *data, void *doit)
905{
906 Outbuf *ob = data;
907 if (!ob) return EINA_FALSE;
908
909 if (doit)
910 {
911 if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0],
912 ob->egl_surface[0], ob->egl_context[0]))
913 return EINA_FALSE;
914 }
915 else
916 {
917 if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE,
918 EGL_NO_SURFACE, EGL_NO_CONTEXT))
919 return EINA_FALSE;
920 }
921 return EINA_TRUE;
922}
923
924static Eina_Bool
925eng_canvas_alpha_get(void *data, void *info EINA_UNUSED)
926{
927 Render_Engine *re = (Render_Engine *)data;
928 if (!re) return EINA_FALSE;
929
930 return re->generic.software.ob->alpha;
931}
932
933static void
934eng_output_dump(void *data)
935{
936 Render_Engine *re;
937
938 re = (Render_Engine *)data;
939 if (!re) return;
940 evas_common_image_image_all_unload();
941 evas_common_font_font_all_unload();
942 glsym_evas_gl_common_image_all_unload(eng_get_ob(re)->gl_context);
943 _re_winfree(re);
944}
945
946/* module api functions */
947static int
948module_open(Evas_Module *em)
949{
950 /* check for valid evas module */
951 if (!em) return 0;
952
953 /* get whatever engine module we inherit from */
954 if (!_evas_module_engine_inherit(&pfunc, "gl_generic")) return 0;
955
956 /* try to create eina logging domain */
957 if (_evas_engine_gl_drm_log_dom < 0)
958 {
959 _evas_engine_gl_drm_log_dom =
960 eina_log_domain_register("evas-gl-drm", EVAS_DEFAULT_LOG_COLOR);
961 }
962
963 /* if we could not create a logging domain, error out */
964 if (_evas_engine_gl_drm_log_dom < 0)
965 {
966 EINA_LOG_ERR("Can not create a module log domain.");
967 return 0;
968 }
969
970 /* store it for later use */
971 func = pfunc;
972
973 /* now to override methods */
974#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
975 ORD(info);
976 ORD(info_free);
977 ORD(setup);
978 ORD(canvas_alpha_get);
979 ORD(output_free);
980 ORD(output_dump);
981
982 /* Mesa's EGL driver loads wayland egl by default. (called by eglGetProcaddr() )
983 * implicit env set (EGL_PLATFORM=drm) prevent that.
984 */
985 setenv("EGL_PLATFORM", "drm", 1);
986 gl_symbols();
987
988 /* now advertise out own api */
989 em->functions = (void *)(&func);
990 return 1;
991}
992
993static void
994module_close(Evas_Module *em EINA_UNUSED)
995{
996 /* unregister the eina log domain for this engine */
997 eina_log_domain_unregister(_evas_engine_gl_drm_log_dom);
998}
999
1000static Evas_Module_Api evas_modapi =
1001{
1002 EVAS_MODULE_API_VERSION,
1003 "gl_drm",
1004 "none",
1005 {
1006 module_open,
1007 module_close
1008 }
1009};
1010
1011EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, gl_drm);
1012
1013#ifndef EVAS_STATIC_BUILD_DRM
1014EVAS_EINA_MODULE_DEFINE(engine, gl_drm);
1015#endif
diff --git a/src/modules/evas/engines/gl_drm/evas_engine.h b/src/modules/evas/engines/gl_drm/evas_engine.h
new file mode 100644
index 0000000000..8f9aa5a01f
--- /dev/null
+++ b/src/modules/evas/engines/gl_drm/evas_engine.h
@@ -0,0 +1,190 @@
1#ifndef EVAS_ENGINE_H
2# define EVAS_ENGINE_H
3
4#include "config.h"
5#include "evas_common_private.h"
6#include "evas_private.h"
7#include "Evas.h"
8#include "Evas_Engine_GL_Drm.h"
9#include "evas_macros.h"
10
11#define GL_GLEXT_PROTOTYPES
12#include <EGL/egl.h>
13#include <GLES2/gl2.h>
14#include <GLES2/gl2ext.h>
15#include "../gl_generic/Evas_Engine_GL_Generic.h"
16
17#include <xf86drm.h>
18#include <xf86drmMode.h>
19#include <drm_fourcc.h>
20
21#include <signal.h>
22#include <sys/ioctl.h>
23#include <sys/types.h>
24#include <unistd.h>
25#include <fcntl.h>
26
27extern int extn_have_buffer_age;
28extern int _evas_engine_gl_drm_log_dom;
29
30extern Evas_GL_Common_Context_New glsym_evas_gl_common_context_new;
31extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush;
32extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free;
33extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use;
34extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe;
35extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done;
36extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize;
37extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump;
38extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock;
39extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock;
40
41# ifdef ERR
42# undef ERR
43# endif
44# define ERR(...) EINA_LOG_DOM_ERR(_evas_engine_gl_drm_log_dom, __VA_ARGS__)
45
46# ifdef DBG
47# undef DBG
48# endif
49# define DBG(...) EINA_LOG_DOM_DBG(_evas_engine_gl_drm_log_dom, __VA_ARGS__)
50
51# ifdef INF
52# undef INF
53# endif
54# define INF(...) EINA_LOG_DOM_INFO(_evas_engine_gl_drm_log_dom, __VA_ARGS__)
55
56# ifdef WRN
57# undef WRN
58# endif
59# define WRN(...) EINA_LOG_DOM_WARN(_evas_engine_gl_drm_log_dom, __VA_ARGS__)
60
61# ifdef CRI
62# undef CRI
63# endif
64# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_gl_drm_log_dom, __VA_ARGS__)
65
66# define NUM_BUFFERS 2
67
68typedef struct _Buffer Buffer;
69typedef struct _Plane Plane;
70typedef struct _Outbuf Outbuf;
71
72struct _Buffer
73{
74 int stride;
75 int size;
76 int handle;
77 unsigned int fb;
78 struct gbm_bo *bo; //used for hardware framebuffers
79 Eina_Bool valid : 1;
80};
81
82struct _Plane
83{
84 unsigned int id;
85 unsigned int crtcs;
86
87 struct
88 {
89 unsigned int x, y;
90 unsigned int w, h;
91 } src, dst;
92
93 unsigned int num_formats;
94 unsigned int formats[];
95};
96
97struct _Outbuf
98{
99 EGLContext egl_context[1];
100 EGLSurface egl_surface[1];
101 EGLConfig egl_config;
102 EGLDisplay egl_disp;
103 struct gbm_device *gbm;
104 struct gbm_surface *surface;
105 Evas *evas;
106 uint32_t format;
107 uint32_t flags;
108 Evas_Engine_GL_Context *gl_context;
109 Evas_Engine_Info_GL_Drm *info;
110 Render_Engine_Swap_Mode swap_mode;
111 int w, h;
112 int depth, rot, screen, alpha;
113 int prev_age;
114 int frame_cnt;
115 int vsync;
116 Eina_Bool lost_back : 1;
117 Eina_Bool surf : 1;
118
119 struct
120 {
121 Eina_Bool drew : 1;
122 } draw;
123
124 struct
125 {
126 int fd;
127 unsigned int conn, crtc, fb;
128 Buffer buffer[NUM_BUFFERS];
129 int curr, num;
130 drmModeModeInfo mode;
131 drmEventContext ctx;
132 Eina_List *pending_writes;
133 Eina_List *planes;
134 Eina_Bool pending_flip : 1;
135 } priv;
136};
137
138struct _Context_3D
139{
140 EGLDisplay display;
141 EGLContext context;
142 EGLSurface surface;
143};
144
145Outbuf *eng_window_new(Evas_Engine_Info_GL_Drm *info, Evas *e, struct gbm_device *gbm, struct gbm_surface *surface, int screen, int depth, int w, int h, int indirect, int alpha, int rot, Render_Engine_Swap_Mode swap_mode);
146void eng_window_free(Outbuf *gw);
147void eng_window_use(Outbuf *gw);
148void eng_window_unsurf(Outbuf *gw);
149void eng_window_resurf(Outbuf *gw);
150
151void eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
152int eng_outbuf_get_rot(Outbuf *ob);
153Render_Engine_Swap_Mode eng_outbuf_swap_mode(Outbuf *ob);
154Eina_Bool eng_outbuf_region_first_rect(Outbuf *ob);
155void *eng_outbuf_new_region_for_update(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
156void eng_outbuf_push_free_region_for_update(Outbuf *ob, RGBA_Image *update);
157void eng_outbuf_push_updated_region(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
158void eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
159Evas_Engine_GL_Context* eng_outbuf_gl_context_get(Outbuf *ob);
160void *eng_outbuf_egl_display_get(Outbuf *ob);
161
162void eng_gl_context_free(Context_3D *context);
163void eng_gl_context_use(Context_3D *context);
164
165Eina_Bool eng_preload_make_current(void *data, void *doit);
166
167Context_3D *eng_gl_context_new(Outbuf *win);
168
169static inline Eina_Bool
170_re_wincheck(Outbuf *ob)
171{
172 if (ob->surf) return EINA_TRUE;
173 eng_window_resurf(ob);
174 ob->lost_back = 1;
175 if (!ob->surf)
176 {
177 ERR("GL engine can't re-create window surface!");
178 }
179 return EINA_FALSE;
180}
181
182//TODO: Need to split below evas_drm_... apis
183Eina_Bool evas_drm_init(Evas_Engine_Info_GL_Drm *info);
184Eina_Bool evas_drm_shutdown(Evas_Engine_Info_GL_Drm *info);
185Eina_Bool evas_drm_gbm_init(Evas_Engine_Info_GL_Drm *info, int w, int h);
186Eina_Bool evas_drm_gbm_shutdown(Evas_Engine_Info_GL_Drm *info);
187Eina_Bool evas_drm_outbuf_setup(Outbuf *ob);
188void evas_drm_outbuf_framebuffer_set(Outbuf *ob, Buffer *buffer);
189Eina_Bool evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer);
190#endif