summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Michael <cpmichael@osg.samsung.com>2016-05-27 11:58:51 -0400
committerChris Michael <cpmichael@osg.samsung.com>2016-05-27 11:58:51 -0400
commit3c50101f73d0f53e6947eea4294f3b03fb2ad919 (patch)
treeaddf704c83a83cb032b4cb0f13fdde9d9ffd70e4
parent072674dbe2118a26d8616b56b4169a6e543805ef (diff)
parent09805d2b15a71a361ec4bf3154f797fe3314775d (diff)
Merge branch 'devs/devilhorns/ecore_drm2'
This new Ecore_Drm2 library is going to replace the existing Ecore_Drm. This will refactor a lot of the code, bring improvements over the existing API, and provide additional support for missing features such as atomic modeset, nuclear pageflip, and hardware planes support. @feature
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac82
-rw-r--r--m4/efl.m43
-rw-r--r--m4/evas_check_engine.m413
-rw-r--r--pc/.gitignore1
-rw-r--r--pc/ecore-drm2.pc.in12
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile_Ecore_Drm2.am28
-rw-r--r--src/Makefile_Ecore_Evas.am14
-rw-r--r--src/Makefile_Evas.am14
-rw-r--r--src/lib/ecore_drm2/Ecore_Drm2.h771
-rw-r--r--src/lib/ecore_drm2/ecore_drm2.c83
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_device.c315
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_fb.c265
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_outputs.c1155
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_private.h185
-rw-r--r--src/lib/elementary/elm_priv.h2
-rw-r--r--src/modules/ecore_evas/engines/drm/ecore_evas_drm.c1258
-rw-r--r--src/modules/evas/engines/drm/Evas_Engine_Drm.h21
-rw-r--r--src/modules/evas/engines/drm/evas_engine.c102
-rw-r--r--src/modules/evas/engines/drm/evas_engine.h56
-rw-r--r--src/modules/evas/engines/drm/evas_outbuf.c501
-rw-r--r--src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h6
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.c70
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.h24
-rw-r--r--src/modules/evas/engines/gl_drm/evas_outbuf.c197
26 files changed, 4118 insertions, 1067 deletions
diff --git a/Makefile.am b/Makefile.am
index 564f332993..1efae6ed10 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -290,6 +290,10 @@ if HAVE_ELPUT
290pkgconfig_DATA += pc/elput.pc 290pkgconfig_DATA += pc/elput.pc
291endif 291endif
292 292
293if HAVE_ECORE_DRM2
294pkgconfig_DATA += pc/ecore-drm2.pc
295endif
296
293# Cmake configs: 297# Cmake configs:
294efl_cmakeconfigdir = $(libdir)/cmake/Efl/ 298efl_cmakeconfigdir = $(libdir)/cmake/Efl/
295efl_cmakeconfig_DATA = \ 299efl_cmakeconfig_DATA = \
diff --git a/configure.ac b/configure.ac
index cae4e39594..ff5c2ad188 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2085,19 +2085,32 @@ if test "x${have_cocoa}" = "xyes"; then
2085fi 2085fi
2086AC_SUBST(cocoa_coreservices_ldflags) 2086AC_SUBST(cocoa_coreservices_ldflags)
2087 2087
2088AC_ARG_ENABLE([elput],
2089 [AS_HELP_STRING([--enable-elput],[enable elput library. @<:@default=disabled@:>@])],
2090 [
2091 if test "x${enableval}" = "xyes" ; then
2092 want_elput="yes"
2093 else
2094 want_elput="no"
2095 fi
2096 ],
2097 [want_elput="no"])
2098
2088# Drm 2099# Drm
2089AC_ARG_ENABLE([drm], 2100AC_ARG_ENABLE([drm],
2090 [AS_HELP_STRING([--enable-drm],[enable drm engine. @<:@default=disabled@:>@])], 2101 [AS_HELP_STRING([--enable-drm],[enable drm engine. @<:@default=disabled@:>@])],
2091 [ 2102 [
2092 if test "x${enableval}" = "xyes" ; then 2103 if test "x${enableval}" = "xyes" ; then
2093 want_drm="yes" 2104 if test "x${want_elput}" != "xyes" ; then
2105 AC_MSG_ERROR([elput is required to build drm support])
2106 fi
2107 want_drm="yes"
2094 else 2108 else
2095 want_drm="no" 2109 want_drm="no"
2096 fi 2110 fi
2097 ], 2111 ],
2098 [want_drm="no"]) 2112 [want_drm="no"])
2099 2113
2100
2101AC_ARG_ENABLE([gl-drm], 2114AC_ARG_ENABLE([gl-drm],
2102 [AC_HELP_STRING([--enable-gl-drm], 2115 [AC_HELP_STRING([--enable-gl-drm],
2103 [enable gl drm engine. @<:@default=disabled@:>@])], 2116 [enable gl drm engine. @<:@default=disabled@:>@])],
@@ -2296,17 +2309,6 @@ AC_ARG_ENABLE([ecore-buffer],
2296 ], 2309 ],
2297 [want_ecore_buffer="no"]) 2310 [want_ecore_buffer="no"])
2298 2311
2299AC_ARG_ENABLE([elput],
2300 [AS_HELP_STRING([--enable-elput],[enable elput library. @<:@default=disabled@:>@])],
2301 [
2302 if test "x${enableval}" = "xyes" ; then
2303 want_elput="yes"
2304 else
2305 want_elput="no"
2306 fi
2307 ],
2308 [want_elput="no"])
2309
2310# Image Loaders 2312# Image Loaders
2311 2313
2312ARG_ENABLE_EVAS_IMAGE_LOADER(BMP, static) 2314ARG_ENABLE_EVAS_IMAGE_LOADER(BMP, static)
@@ -3633,7 +3635,52 @@ EFL_EVAL_PKGS([ELPUT])
3633### Checks for library functions 3635### Checks for library functions
3634 3636
3635EFL_LIB_END_OPTIONAL([Elput]) 3637EFL_LIB_END_OPTIONAL([Elput])
3636#### End of Ecore_Drm 3638#### End of Elput
3639
3640#### Ecore_Drm2
3641have_libinput_new="no"
3642EFL_LIB_START_OPTIONAL([Ecore_Drm2], [test "${want_drm}" = "yes"])
3643
3644### Additional options to configure
3645SUID_CFLAGS=-fPIE
3646SUID_LDFLAGS=-pie
3647AC_SUBST([SUID_CFLAGS])
3648AC_SUBST([SUID_LDFLAGS])
3649
3650### Default values
3651
3652### Checks for programs
3653
3654### Checks for libraries
3655EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [eo])
3656EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [efl])
3657EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [eina])
3658EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [ecore])
3659EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [elput])
3660EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [eeze])
3661
3662EFL_DEPEND_PKG([ECORE_DRM2], [DRM], [libdrm >= 2.4 gbm])
3663
3664EFL_ADD_LIBS([ECORE_DRM2], [-lm])
3665
3666AC_CHECK_LIB(drm, drmModeAtomicCommit, AC_DEFINE(HAVE_ATOMIC_DRM, [], [Atomic modeset supported]))
3667
3668EFL_EVAL_PKGS([ECORE_DRM2])
3669
3670### Checks for header files
3671
3672### Checks for types
3673
3674### Checks for structures
3675
3676### Checks for compiler characteristics
3677
3678### Checks for linker characteristics
3679
3680### Checks for library functions
3681
3682EFL_LIB_END_OPTIONAL([Ecore_Drm2])
3683#### End of Ecore_Drm2
3637 3684
3638 3685
3639#### Ecore_Audio 3686#### Ecore_Audio
@@ -4357,9 +4404,9 @@ ECORE_EVAS_MODULE([extn], [${want_ecore_evas_extn}])
4357ECORE_EVAS_MODULE([ews], [yes]) 4404ECORE_EVAS_MODULE([ews], [yes])
4358ECORE_EVAS_MODULE([fb], [${want_fb}]) 4405ECORE_EVAS_MODULE([fb], [${want_fb}])
4359ECORE_EVAS_MODULE([drm], [${want_drm}], 4406ECORE_EVAS_MODULE([drm], [${want_drm}],
4360 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm])]) 4407 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm2])])
4361ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}], 4408ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}],
4362 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm])]) 4409 [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm2])])
4363ECORE_EVAS_MODULE([psl1ght], [${have_ps3}]) 4410ECORE_EVAS_MODULE([psl1ght], [${have_ps3}])
4364 4411
4365ECORE_EVAS_MODULE([opengl-cocoa], [${want_ecore_evas_gl_cocoa}]) 4412ECORE_EVAS_MODULE([opengl-cocoa], [${want_ecore_evas_gl_cocoa}])
@@ -5260,7 +5307,7 @@ EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${have_ps3}], [ecore_psl1ght])
5260EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_sdl}], [ecore_sdl]) 5307EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_sdl}], [ecore_sdl])
5261EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_ecore_evas_gl_cocoa}], [ecore_cocoa]) 5308EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_ecore_evas_gl_cocoa}], [ecore_cocoa])
5262EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${build_ecore_evas_win32}], [ecore_win32]) 5309EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${build_ecore_evas_win32}], [ecore_win32])
5263EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_drm}], [ecore_drm]) 5310EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_drm}], [ecore_drm2])
5264EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${build_ecore_evas_wayland}], [ecore_wl2]) 5311EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${build_ecore_evas_wayland}], [ecore_wl2])
5265 5312
5266dnl Special case deps for ecore_drm 5313dnl Special case deps for ecore_drm
@@ -5605,6 +5652,7 @@ pc/elua.pc
5605pc/elementary.pc 5652pc/elementary.pc
5606pc/elementary-cxx.pc 5653pc/elementary-cxx.pc
5607pc/elput.pc 5654pc/elput.pc
5655pc/ecore-drm2.pc
5608dbus-services/org.enlightenment.Ethumb.service 5656dbus-services/org.enlightenment.Ethumb.service
5609systemd-services/ethumb.service 5657systemd-services/ethumb.service
5610$po_makefile_in 5658$po_makefile_in
diff --git a/m4/efl.m4 b/m4/efl.m4
index c9e15f3537..f1694c58d5 100644
--- a/m4/efl.m4
+++ b/m4/efl.m4
@@ -174,6 +174,9 @@ case "m4_defn([DOWNOTHER])" in
174 ecore_win32) 174 ecore_win32)
175 depname="ecore-win32" 175 depname="ecore-win32"
176 ;; 176 ;;
177 ecore_drm2)
178 depname="ecore-drm2"
179 ;;
177esac 180esac
178requirements_pc_[]m4_defn([DOWNEFL])="${depname} >= ${PACKAGE_VERSION} ${requirements_pc_[][]m4_defn([DOWNEFL])}" 181requirements_pc_[]m4_defn([DOWNEFL])="${depname} >= ${PACKAGE_VERSION} ${requirements_pc_[][]m4_defn([DOWNEFL])}"
179requirements_cflags_[]m4_defn([DOWNEFL])="-I\$(top_srcdir)/src/lib/${libdirname} -I\$(top_builddir)/src/lib/${libdirname} ${requirements_cflags_[][]m4_defn([DOWNEFL])}" 182requirements_cflags_[]m4_defn([DOWNEFL])="-I\$(top_srcdir)/src/lib/${libdirname} -I\$(top_builddir)/src/lib/${libdirname} ${requirements_cflags_[][]m4_defn([DOWNEFL])}"
diff --git a/m4/evas_check_engine.m4 b/m4/evas_check_engine.m4
index 448a210592..4789d4b9f0 100644
--- a/m4/evas_check_engine.m4
+++ b/m4/evas_check_engine.m4
@@ -597,16 +597,23 @@ AC_DEFUN([EVAS_CHECK_ENGINE_DEP_DRM],
597[ 597[
598 598
599requirement="" 599requirement=""
600have_dep="yes" 600have_dep="no"
601have_hw_dep="no" 601have_hw_dep="no"
602evas_engine_[]$1[]_cflags="" 602evas_engine_[]$1[]_cflags=""
603evas_engine_[]$1[]_libs="" 603evas_engine_[]$1[]_libs=""
604 604
605PKG_CHECK_EXISTS([libdrm],
606 [
607 have_dep="yes"
608 requirement="libdrm"
609 ], [have_dep="no"])
610
605if test "x${have_dep}" = "xyes" ; then 611if test "x${have_dep}" = "xyes" ; then
606 if test "x$3" = "xstatic" ; then 612 if test "x$3" = "xstatic" ; then
607 requirements_pc_evas="${requirement} ${requirements_pc_evas}" 613 requirements_pc_evas="${requirement} ${requirements_pc_evas}"
608 requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}" 614 requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}"
609 else 615 else
616 PKG_CHECK_MODULES([DRM], [${requirement}])
610 evas_engine_[]$1[]_cflags="${DRM_CFLAGS}" 617 evas_engine_[]$1[]_cflags="${DRM_CFLAGS}"
611 evas_engine_[]$1[]_libs="${DRM_LIBS}" 618 evas_engine_[]$1[]_libs="${DRM_LIBS}"
612 fi 619 fi
@@ -636,10 +643,10 @@ else
636 AC_MSG_ERROR([We currently do not support GL DRM without OpenGL ES. Please consider OpenGL ES if you want to use it.]) 643 AC_MSG_ERROR([We currently do not support GL DRM without OpenGL ES. Please consider OpenGL ES if you want to use it.])
637fi 644fi
638 645
639PKG_CHECK_EXISTS([egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION], 646PKG_CHECK_EXISTS([egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION],
640 [ 647 [
641 have_dep="yes" 648 have_dep="yes"
642 requirement="egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION" 649 requirement="egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION"
643 ], 650 ],
644 [have_dep="no"]) 651 [have_dep="no"])
645 652
diff --git a/pc/.gitignore b/pc/.gitignore
index f66395b99d..893e9373c9 100644
--- a/pc/.gitignore
+++ b/pc/.gitignore
@@ -74,3 +74,4 @@
74/efl-js.pc 74/efl-js.pc
75/elementary-cxx.pc 75/elementary-cxx.pc
76/elput.pc 76/elput.pc
77/ecore-drm2.pc
diff --git a/pc/ecore-drm2.pc.in b/pc/ecore-drm2.pc.in
new file mode 100644
index 0000000000..4530eacab4
--- /dev/null
+++ b/pc/ecore-drm2.pc.in
@@ -0,0 +1,12 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: ecore-drm2
7Description: E core library, DRM module
8Requires.private: @requirements_pc_ecore_drm2@
9Version: @VERSION@
10Libs: -L${libdir} -lecore_drm2
11Libs.private: @requirements_libs_ecore_drm2@
12Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/ecore-drm2-@VMAJ@
diff --git a/src/Makefile.am b/src/Makefile.am
index af019a7bc1..523f411037 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -54,7 +54,9 @@ include Makefile_Ecore_IMF.am
54include Makefile_Ecore_IMF_Evas.am 54include Makefile_Ecore_IMF_Evas.am
55include Makefile_Eldbus.am 55include Makefile_Eldbus.am
56include Makefile_Eeze.am 56include Makefile_Eeze.am
57include Makefile_Elput.am
57include Makefile_Ecore_Drm.am 58include Makefile_Ecore_Drm.am
59include Makefile_Ecore_Drm2.am
58include Makefile_Ecore_Evas.am 60include Makefile_Ecore_Evas.am
59include Makefile_Ecore_Audio.am 61include Makefile_Ecore_Audio.am
60include Makefile_Ecore_Avahi.am 62include Makefile_Ecore_Avahi.am
@@ -69,7 +71,6 @@ include Makefile_Ethumb.am
69include Makefile_Ethumb_Client.am 71include Makefile_Ethumb_Client.am
70include Makefile_Elocation.am 72include Makefile_Elocation.am
71include Makefile_Elementary.am 73include Makefile_Elementary.am
72include Makefile_Elput.am
73 74
74include Makefile_Cxx.am 75include Makefile_Cxx.am
75include Makefile_Eolian_Cxx.am 76include Makefile_Eolian_Cxx.am
diff --git a/src/Makefile_Ecore_Drm2.am b/src/Makefile_Ecore_Drm2.am
new file mode 100644
index 0000000000..1c328e33de
--- /dev/null
+++ b/src/Makefile_Ecore_Drm2.am
@@ -0,0 +1,28 @@
1if HAVE_ECORE_DRM2
2
3### Library
4
5lib_LTLIBRARIES += lib/ecore_drm2/libecore_drm2.la
6
7installed_ecoredrm2mainheadersdir = $(includedir)/ecore-drm2-@VMAJ@
8dist_installed_ecoredrm2mainheaders_DATA = \
9 lib/ecore_drm2/Ecore_Drm2.h
10
11lib_ecore_drm2_libecore_drm2_la_SOURCES = \
12lib/ecore_drm2/ecore_drm2_fb.c \
13lib/ecore_drm2/ecore_drm2_outputs.c \
14lib/ecore_drm2/ecore_drm2_device.c \
15lib/ecore_drm2/ecore_drm2.c \
16lib/ecore_drm2/ecore_drm2_private.h
17
18lib_ecore_drm2_libecore_drm2_la_CPPFLAGS = \
19 -I$(top_builddir)/src/lib/efl \
20 @ECORE_DRM2_CFLAGS@ @EFL_CFLAGS@ \
21 -DPACKAGE_LIB_DIR=\"$(libdir)\" \
22 -DMODULE_ARCH=\"$(MODULE_ARCH)\"
23
24lib_ecore_drm2_libecore_drm2_la_LIBADD = @ECORE_DRM2_LIBS@
25lib_ecore_drm2_libecore_drm2_la_DEPENDENCIES = @ECORE_DRM2_INTERNAL_LIBS@
26lib_ecore_drm2_libecore_drm2_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
27
28endif
diff --git a/src/Makefile_Ecore_Evas.am b/src/Makefile_Ecore_Evas.am
index 12efc0b135..747a426b8a 100644
--- a/src/Makefile_Ecore_Evas.am
+++ b/src/Makefile_Ecore_Evas.am
@@ -269,13 +269,15 @@ $(install_ecoreevasenginedrmpkgLTLIBRARIES): install-libLTLIBRARIES
269modules_ecore_evas_engines_drm_module_la_SOURCES = $(DRMSOURCES) 269modules_ecore_evas_engines_drm_module_la_SOURCES = $(DRMSOURCES)
270modules_ecore_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 270modules_ecore_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
271@ECORE_EVAS_CFLAGS@ \ 271@ECORE_EVAS_CFLAGS@ \
272@ECORE_DRM_CFLAGS@ \ 272@ECORE_DRM2_CFLAGS@ \
273-I$(top_srcdir)/src/modules/evas/engines/drm \ 273-I$(top_srcdir)/src/modules/evas/engines/drm \
274-I$(top_srcdir)/src/modules/evas/engines/gl_drm \ 274-I$(top_srcdir)/src/modules/evas/engines/gl_drm
275@ecore_evas_engines_gl_drm_cflags@ 275modules_ecore_evas_engines_drm_module_la_LIBADD = \
276modules_ecore_evas_engines_drm_module_la_LIBADD = @USE_ECORE_EVAS_LIBS@ \ 276@USE_ECORE_EVAS_LIBS@ \
277@ecore_evas_engines_gl_drm_libs@ 277@USE_ECORE_DRM2_LIBS@
278modules_ecore_evas_engines_drm_module_la_DEPENDENCIES = @USE_ECORE_EVAS_INTERNAL_LIBS@ 278modules_ecore_evas_engines_drm_module_la_DEPENDENCIES = \
279@USE_ECORE_EVAS_INTERNAL_LIBS@ \
280@USE_ECORE_DRM2_INTERNAL_LIBS@
279modules_ecore_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ 281modules_ecore_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
280modules_ecore_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static 282modules_ecore_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
281endif 283endif
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index daa11b8a86..19fea04991 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -1276,7 +1276,6 @@ endif
1276endif 1276endif
1277 1277
1278if BUILD_ENGINE_DRM 1278if BUILD_ENGINE_DRM
1279dist_installed_evasmainheaders_DATA += modules/evas/engines/drm/Evas_Engine_Drm.h
1280DRM_SOURCES = \ 1279DRM_SOURCES = \
1281modules/evas/engines/drm/evas_outbuf.c \ 1280modules/evas/engines/drm/evas_outbuf.c \
1282modules/evas/engines/drm/evas_engine.c \ 1281modules/evas/engines/drm/evas_engine.c \
@@ -1301,20 +1300,19 @@ modules_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1301-I$(top_srcdir)/src/lib/evas/cserve2 \ 1300-I$(top_srcdir)/src/lib/evas/cserve2 \
1302-I$(top_srcdir)/src/modules/evas/engines/drm \ 1301-I$(top_srcdir)/src/modules/evas/engines/drm \
1303@EVAS_CFLAGS@ \ 1302@EVAS_CFLAGS@ \
1304@ECORE_DRM_CFLAGS@ \ 1303@ECORE_DRM2_CFLAGS@ \
1305@evas_engine_drm_cflags@ 1304@evas_engine_drm_cflags@
1306modules_evas_engines_drm_module_la_LIBADD = \ 1305modules_evas_engines_drm_module_la_LIBADD = \
1307@USE_EVAS_LIBS@ \ 1306@USE_EVAS_LIBS@ \
1308@USE_ECORE_DRM_LIBS@ \ 1307@USE_ECORE_DRM2_LIBS@ \
1309@evas_engine_drm_libs@ 1308@evas_engine_drm_libs@
1310modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@ 1309modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@
1311modules_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ 1310modules_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
1312modules_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static 1311modules_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
1313endif 1312endif
1314endif 1313endif
1315 1314
1316if BUILD_ENGINE_GL_DRM 1315if BUILD_ENGINE_GL_DRM
1317dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
1318GL_DRM_SOURCES = \ 1316GL_DRM_SOURCES = \
1319modules/evas/engines/gl_drm/evas_outbuf.c \ 1317modules/evas/engines/gl_drm/evas_outbuf.c \
1320modules/evas/engines/gl_drm/evas_engine.c \ 1318modules/evas/engines/gl_drm/evas_engine.c \
@@ -1339,13 +1337,13 @@ modules_evas_engines_gl_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1339-I$(top_srcdir)/src/lib/evas/cserve2 \ 1337-I$(top_srcdir)/src/lib/evas/cserve2 \
1340-I$(top_srcdir)/src/modules/evas/engines/gl_drm \ 1338-I$(top_srcdir)/src/modules/evas/engines/gl_drm \
1341@EVAS_CFLAGS@ \ 1339@EVAS_CFLAGS@ \
1342@ECORE_DRM_CFLAGS@ \ 1340@ECORE_DRM2_CFLAGS@ \
1343@evas_engine_gl_drm_cflags@ 1341@evas_engine_gl_drm_cflags@
1344modules_evas_engines_gl_drm_module_la_LIBADD = \ 1342modules_evas_engines_gl_drm_module_la_LIBADD = \
1345@USE_EVAS_LIBS@ \ 1343@USE_EVAS_LIBS@ \
1346@USE_ECORE_DRM_LIBS@ \ 1344@USE_ECORE_DRM2_LIBS@ \
1347@evas_engine_gl_drm_libs@ 1345@evas_engine_gl_drm_libs@
1348modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@ 1346modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@
1349modules_evas_engines_gl_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ 1347modules_evas_engines_gl_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
1350modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static 1348modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
1351endif 1349endif
diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h
new file mode 100644
index 0000000000..fa2e916c76
--- /dev/null
+++ b/src/lib/ecore_drm2/Ecore_Drm2.h
@@ -0,0 +1,771 @@
1#ifndef _ECORE_DRM2_H
2# define _ECORE_DRM2_H
3
4# include <Ecore.h>
5
6# ifdef EAPI
7# undef EAPI
8# endif
9
10# ifdef _MSC_VER
11# ifdef BUILDING_DLL
12# define EAPI __declspec(dllexport)
13# else // ifdef BUILDING_DLL
14# define EAPI __declspec(dllimport)
15# endif // ifdef BUILDING_DLL
16# else // ifdef _MSC_VER
17# ifdef __GNUC__
18# if __GNUC__ >= 4
19# define EAPI __attribute__ ((visibility("default")))
20# else // if __GNUC__ >= 4
21# define EAPI
22# endif // if __GNUC__ >= 4
23# else // ifdef __GNUC__
24# define EAPI
25# endif // ifdef __GNUC__
26# endif // ifdef _MSC_VER
27
28# ifdef EFL_BETA_API_SUPPORT
29
30/* opaque structure to represent a drm device */
31typedef struct _Ecore_Drm2_Device Ecore_Drm2_Device;
32
33/* opaque structure to represent a framebuffer object */
34typedef struct _Ecore_Drm2_Fb Ecore_Drm2_Fb;
35
36/* opaque structure to represent an output device */
37typedef struct _Ecore_Drm2_Output Ecore_Drm2_Output;
38
39/* opaque structure to represent an output mode */
40typedef struct _Ecore_Drm2_Output_Mode Ecore_Drm2_Output_Mode;
41
42/* structure to represent event for output changes */
43typedef struct _Ecore_Drm2_Event_Output_Changed
44{
45 unsigned int id;
46 int x, y, w, h;
47 int phys_width, phys_height;
48 unsigned int refresh, scale;
49 int subpixel, transform;
50 const char *make, *model, *name;
51 Eina_Bool connected : 1;
52 Eina_Bool enabled : 1;
53} Ecore_Drm2_Event_Output_Changed;
54
55/* structure to represent event for session state changes */
56typedef struct _Ecore_Drm2_Event_Activate
57{
58 Eina_Bool active : 1;
59} Ecore_Drm2_Event_Activate;
60
61EAPI extern int ECORE_DRM2_EVENT_OUTPUT_CHANGED;
62EAPI extern int ECORE_DRM2_EVENT_ACTIVATE;
63
64/**
65 * @file
66 * @brief Ecore functions for dealing with drm, virtual terminals
67 *
68 * @defgroup Ecore_Drm2_Group Ecore_Drm2 - Drm Integration
69 * @ingroup Ecore
70 *
71 * Ecore_Drm2 provides a wrapper and functions for using libdrm
72 *
73 * @li @ref Ecore_Drm2_Init_Group
74 * @li @ref Ecore_Drm2_Device_Group
75 * @li @ref Ecore_Drm2_Output_Group
76 * @li @ref Ecore_Drm2_Fb_Group
77 */
78
79/**
80 * @defgroup Ecore_Drm2_Init_Group Drm library Init and Shutdown functions
81 *
82 * Functions that start and shutdown the Ecore_Drm2 library
83 */
84
85/**
86 * Initialize the Ecore_Drm2 library
87 *
88 * @return The number of times the library has been initialized without
89 * being shut down. 0 is returned if an error occurs.
90 *
91 * @ingroup Ecore_Drm2_Init_Group
92 * @since 1.18
93 */
94EAPI int ecore_drm2_init(void);
95
96/**
97 * Shutdown the Ecore_Drm2 library
98 *
99 * @return The number of times the library has been initialized without
100 * being shutdown. 0 is returned if an error occurs.
101 *
102 * @ingroup Ecore_Drm2_Init_Group
103 * @since 1.18
104 */
105EAPI int ecore_drm2_shutdown(void);
106
107/**
108 * @defgroup Ecore_Drm2_Device_Group Drm device functions
109 *
110 * Functions that deal with finding, opening, closing, or obtaining various
111 * information about a drm device
112 */
113
114/**
115 * Try to find a drm device on a given seat
116 *
117 * @param seat
118 * @param tty
119 * @param sync
120 *
121 * @return A newly allocated Ecore_Drm2_Device on success, NULL otherwise
122 *
123 * @ingroup Ecore_Drm2_Device_Group
124 * @since 1.18
125 */
126EAPI Ecore_Drm2_Device *ecore_drm2_device_find(const char *seat, unsigned int tty);
127
128/**
129 * Try to open a given Ecore_Drm2_Device
130 *
131 * @param device
132 *
133 * @return A valid file descriptor if open succeeds, -1 otherwise.
134 *
135 * @ingroup Ecore_Drm2_Device_Group
136 * @since 1.18
137 */
138EAPI int ecore_drm2_device_open(Ecore_Drm2_Device *device);
139
140/**
141 * Close an open Ecore_Drm2_Device
142 *
143 * @param device
144 *
145 * @ingroup Ecore_Drm2_Device_Group
146 * @since 1.18
147 */
148EAPI void ecore_drm2_device_close(Ecore_Drm2_Device *device);
149
150/**
151 * Free a given Ecore_Drm2_Device
152 *
153 * @param device
154 *
155 * @ingroup Ecore_Drm2_Device_Group
156 * @since 1.18
157 */
158EAPI void ecore_drm2_device_free(Ecore_Drm2_Device *device);
159
160/**
161 * Get the type of clock used by a given Ecore_Drm2_Device
162 *
163 * @param device
164 *
165 * @return The clockid_t used by this drm device
166 *
167 * @ingroup Ecore_Drm2_Device_Group
168 * @since 1.18
169 */
170EAPI int ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device);
171
172/**
173 * Get the size of the cursor supported by a given Ecore_Drm2_Device
174 *
175 * @param device
176 * @param width
177 * @param height
178 *
179 * @ingroup Ecore_Drm2_Device_Group
180 * @since 1.18
181 */
182EAPI void ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height);
183
184/**
185 * Get the current pointer position
186 *
187 * @param device
188 * @param x
189 * @param y
190 *
191 * @ingroup Ecore_Drm2_Device_Group
192 * @since 1.18
193 */
194EAPI void ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, int *y);
195
196/**
197 * Warp the pointer position to given coordinates
198 *
199 * @param dev
200 * @param x
201 * @param y
202 *
203 * @ingroup Ecore_Drm2_Device_Group
204 * @since 1.18
205 */
206EAPI void ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y);
207
208/**
209 * Set a left handed mode for the given device
210 *
211 * @param device
212 * @param left
213 *
214 * @return EINA_TRUE on success, EINA_FALSE otherwise
215 *
216 * @ingroup Ecore_Drm2_Device_Group
217 * @since 1.18
218 */
219EAPI Eina_Bool ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device *device, Eina_Bool left);
220
221/**
222 * Set which window is to be used for input events
223 *
224 * @param device
225 * @param window
226 *
227 * @ingroup Ecore_Drm2_Device_Group
228 * @since 1.18
229 */
230EAPI void ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window);
231
232/**
233 * Set maximium position that pointer device is allowed to move
234 *
235 * @param device
236 * @param w
237 * @param h
238 *
239 * @ingroup Ecore_Drm2_Device_Group
240 * @since 1.18
241 */
242EAPI void ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h);
243
244/**
245 * Set a cached context to be used on keyboards
246 *
247 * @param device
248 * @param context
249 *
250 * @ingroup Ecore_Drm2_Device_Group
251 * @since 1.18
252 */
253EAPI void ecore_drm2_device_keyboard_cached_context_set(Ecore_Drm2_Device *device, void *context);
254
255/**
256 * Set a cached keymap to be used on keyboards
257 *
258 * @param device
259 * @param keymap
260 *
261 * @ingroup Ecore_Drm2_Device_Group
262 * @since 1.18
263 */
264EAPI void ecore_drm2_device_keyboard_cached_keymap_set(Ecore_Drm2_Device *device, void *keymap);
265
266/**
267 * Get the crtcs of a given device
268 *
269 * @param device
270 * @param num
271 *
272 * @return The crtcs of this given device or NULL on failure
273 *
274 * @ingroup Ecore_Drm2_Device_Group
275 * @since 1.18
276 */
277EAPI unsigned int *ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num);
278
279/**
280 * Get the minimum and maximum screen size range
281 *
282 * @param device
283 * @param *minw
284 * @param *minh
285 * @param *maxw
286 * @param *maxh
287 *
288 * @ingroup Ecore_Drm2_Device_Group
289 * @since 1.18
290 */
291EAPI void ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, int *minh, int *maxw, int *maxh);
292
293/**
294 * Calibrate any input devices for given screen size
295 *
296 * @param device
297 * @param w
298 * @param h
299 *
300 * @ingroup Ecore_Drm2_Device_Group
301 * @since 1.18
302 */
303EAPI void ecore_drm2_device_calibrate(Ecore_Drm2_Device *device, int w, int h);
304
305/**
306 * @defgroup Ecore_Drm2_Output_Group Drm output functions
307 *
308 * Functions that deal with setup of outputs
309 */
310
311/**
312 * Iterate drm resources and create outputs
313 *
314 * @param device
315 *
316 * @return EINA_TRUE on success, EINA_FALSE otherwise
317 *
318 * @ingroup Ecore_Drm2_Output_Group
319 * @since 1.18
320 */
321EAPI Eina_Bool ecore_drm2_outputs_create(Ecore_Drm2_Device *device);
322
323/**
324 * Destroy any created outputs
325 *
326 * @param device
327 *
328 * @ingroup Ecore_Drm2_Output_Group
329 * @since 1.18
330 */
331EAPI void ecore_drm2_outputs_destroy(Ecore_Drm2_Device *device);
332
333/**
334 * Get the list of outputs from a drm device
335 *
336 * @param device
337 *
338 * @return
339 *
340 * @ingroup Ecore_Drm2_Output_Group
341 * @since 1.18
342 */
343EAPI const Eina_List *ecore_drm2_outputs_get(Ecore_Drm2_Device *device);
344
345/**
346 * Get the dpms level of a given output
347 *
348 * @param output
349 *
350 * @return Integer value representing the state of DPMS on a given output
351 * or -1 on error
352 *
353 * @ingroup Ecore_Drm2_Output_Group
354 * @since 1.18
355 */
356EAPI int ecore_drm2_output_dpms_get(Ecore_Drm2_Output *output);
357
358/**
359 * Set the dpms level of a given output
360 *
361 * @param output
362 * @param level
363 *
364 * @ingroup Ecore_Drm2_Output_Group
365 * @since 1.18
366 */
367EAPI void ecore_drm2_output_dpms_set(Ecore_Drm2_Output *output, int level);
368
369/**
370 * Get the edid of a given output
371 *
372 * @param output
373 *
374 * @return A string representing the edid
375 *
376 * @ingroup Ecore_Drm2_Output_Group
377 * @since 1.18
378 */
379EAPI char *ecore_drm2_output_edid_get(Ecore_Drm2_Output *output);
380
381/**
382 * Get if a given output has a backlight
383 *
384 * @param output
385 *
386 * @return EINA_TRUE if this output has a backlight, EINA_FALSE otherwise
387 *
388 * @ingroup Ecore_Drm2_Output_Group
389 * @since 1.18
390 */
391EAPI Eina_Bool ecore_drm2_output_backlight_get(Ecore_Drm2_Output *output);
392
393/**
394 * Find an output at the given position
395 *
396 * @param device
397 * @param x
398 * @param y
399 *
400 * @return An Ecore_Drm2_Output which exists at the given coordinates, or NULL on failure
401 *
402 * @ingroup Ecore_Drm2_Output_Group
403 * @since 1.18
404 */
405EAPI Ecore_Drm2_Output *ecore_drm2_output_find(Ecore_Drm2_Device *device, int x, int y);
406
407/**
408 * Get the geometry of a given output
409 *
410 * @param output
411 * @param x
412 * @param y
413 * @param w
414 * @param h
415 *
416 * @ingroup Ecore_Drm2_Output_Group
417 * @since 1.18
418 */
419EAPI void ecore_drm2_output_geometry_get(Ecore_Drm2_Output *output, int *x, int *y, int *w, int *h);
420
421/**
422 * Get the id of the crtc that an output is using
423 *
424 * @param output
425 *
426 * @return A valid crtc id or 0 on failure
427 *
428 * @ingroup Ecore_Drm2_Output_Group
429 * @since 1.18
430 */
431EAPI unsigned int ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output);
432
433/**
434 * Return the next Ecore_Drm2_Fb to be used on a given output
435 *
436 * @param output
437 *
438 * @return The next Ecore_Drm2_Fb which is scheduled to to be flipped, or NULL otherwise
439 *
440 * @ingroup Ecore_Drm2_Output_Group
441 * @since 1.18
442 */
443EAPI Ecore_Drm2_Fb *ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output);
444
445/**
446 * Return the current Ecore_Drm2_Fb used on a given output
447 *
448 * @param output
449 *
450 * @return The current Ecore_Drm2_Fb used on this output, or NULL otherwise
451 *
452 * @ingroup Ecore_Drm2_Output_Group
453 * @since 1.18
454 */
455EAPI Ecore_Drm2_Fb *ecore_drm2_output_current_fb_get(Ecore_Drm2_Output *output);
456
457/**
458 * Set the next Ecore_Drm2_Fb to be used on a given output
459 *
460 * @param output
461 * @param fb
462 *
463 * @ingroup Ecore_Drm2_Output_Group
464 * @since 1.18
465 */
466EAPI void ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb);
467
468/**
469 * Get the size of the crtc for a given output
470 *
471 * @param output
472 * @param *w
473 * @param *h
474 *
475 * @ingroup Ecore_Drm2_Output_Group
476 * @since 1.18
477 */
478EAPI void ecore_drm2_output_crtc_size_get(Ecore_Drm2_Output *output, int *w, int *h);
479
480/**
481 * Get if a given output is marked as the primary output
482 *
483 * @param output
484 *
485 * @return EINA_TRUE if output is primary, EINA_FALSE otherwise
486 *
487 * @ingroup Ecore_Drm2_Output_Group
488 * @since 1.18
489 */
490EAPI Eina_Bool ecore_drm2_output_primary_get(Ecore_Drm2_Output *output);
491
492/**
493 * Set a given output to be primary
494 *
495 * @param output
496 * @param primary
497 *
498 * @ingroup Ecore_Drm2_Output_Group
499 * @since 1.18
500 */
501EAPI void ecore_drm2_output_primary_set(Ecore_Drm2_Output *output, Eina_Bool primary);
502
503/**
504 * Get if a given output is enabled
505 *
506 * @param output
507 *
508 * @return EINA_TRUE if enabled, EINA_FALSE otherwise.
509 *
510 * @ingroup Ecore_Drm2_Output_Group
511 * @since 1.18
512 */
513EAPI Eina_Bool ecore_drm2_output_enabled_get(Ecore_Drm2_Output *output);
514
515/**
516 * Set if a given output is enabled
517 *
518 * @param output
519 * @param enabled
520 *
521 * @ingroup Ecore_Drm2_Output_Group
522 * @since 1.18
523 */
524EAPI void ecore_drm2_output_enabled_set(Ecore_Drm2_Output *output, Eina_Bool enabled);
525
526/**
527 * Get the physical size of a given output
528 *
529 * This function will give the physical size (in mm) of an output
530 *
531 * @param output
532 * @param *w
533 * @param *h
534 *
535 * @ingroup Ecore_Drm2_Output_Group
536 * @since 1.18
537 */
538EAPI void ecore_drm2_output_physical_size_get(Ecore_Drm2_Output *output, int *w, int *h);
539
540/**
541 * Get a list of the modes supported on a given output
542 *
543 * @param output
544 *
545 * @return An Eina_List of the modes supported for this output
546 *
547 * @note The returned list should not be freed
548 *
549 * @ingroup Ecore_Drm2_Output_Group
550 * @since 1.18
551 */
552EAPI const Eina_List *ecore_drm2_output_modes_get(Ecore_Drm2_Output *output);
553
554/**
555 * Get information from an existing output mode
556 *
557 * @param mode
558 * @param w
559 * @param h
560 * @param refresh
561 * @param flags
562 *
563 * @ingroup Ecore_Drm2_Output_Group
564 * @since 1.18
565 */
566EAPI void ecore_drm2_output_mode_info_get(Ecore_Drm2_Output_Mode *mode, int *w, int *h, unsigned int *refresh, unsigned int *flags);
567
568/**
569 * Set a given mode to be used on a given output
570 *
571 * @param output
572 * @param mode
573 * @param x
574 * @param y
575 *
576 * @return EINA_TRUE on success, EINA_FALSE otherwise
577 *
578 * @ingroup Ecore_Drm2_Output_Group
579 * @since 1.18
580 */
581EAPI Eina_Bool ecore_drm2_output_mode_set(Ecore_Drm2_Output *output, Ecore_Drm2_Output_Mode *mode, int x, int y);
582
583/**
584 * Get the name of a given output
585 *
586 * @param output
587 *
588 * @return A string representing the output's name. Caller should free this return.
589 *
590 * @ingroup Ecore_Drm2_Output_Group
591 * @since 1.18
592 */
593EAPI char *ecore_drm2_output_name_get(Ecore_Drm2_Output *output);
594
595/**
596 * Get the model of a given output
597 *
598 * @param output
599 *
600 * @return A string representing the output's model. Caller should free this return.
601 *
602 * @ingroup Ecore_Drm2_Output_Group
603 * @since 1.18
604 */
605EAPI char *ecore_drm2_output_model_get(Ecore_Drm2_Output *output);
606
607/**
608 * Get if a given output is connected
609 *
610 * @param output
611 *
612 * @return EINA_TRUE if connected, EINA_FALSE otherwise
613 *
614 * @ingroup Ecore_Drm2_Output_Group
615 * @since 1.18
616 */
617EAPI Eina_Bool ecore_drm2_output_connected_get(Ecore_Drm2_Output *output);
618
619/**
620 * Get if a given output is cloned
621 *
622 * @param output
623 *
624 * @return EINA_TRUE if cloned, EINA_FALSE otherwise.
625 *
626 * @ingroup Ecore_Drm2_Output_Group
627 * @since 1.18
628 */
629EAPI Eina_Bool ecore_drm2_output_cloned_get(Ecore_Drm2_Output *output);
630
631/**
632 * Get the connector type of a given output
633 *
634 * @param output
635 *
636 * @return An unsigned integer representing the type of connector for this output
637 *
638 * @ingroup Ecore_Drm2_Output_Group
639 * @since 1.18
640 */
641EAPI unsigned int ecore_drm2_output_connector_type_get(Ecore_Drm2_Output *output);
642
643/**
644 * Get the current resolution of a given output
645 *
646 * @param output
647 * @param *w
648 * @param *h
649 * @param *refresh
650 *
651 * @ingroup Ecore_Drm2_Output_Group
652 * @since 1.18
653 */
654EAPI void ecore_drm2_output_resolution_get(Ecore_Drm2_Output *output, int *w, int *h, unsigned int *refresh);
655
656/**
657 * Get if an output can be used on a given crtc
658 *
659 * This function will loop the possible crtcs of an encoder to determine if
660 * a given output can be assigned to a given crtc
661 *
662 * @param output
663 * @param crtc
664 *
665 * @return EINA_TRUE if the output can be assigned to given crtc, EINA_FALSE otherwise
666 *
667 * @ingroup Ecore_Drm2_Output_Group
668 * @since 1.18
669 */
670EAPI Eina_Bool ecore_drm2_output_possible_crtc_get(Ecore_Drm2_Output *output, unsigned int crtc);
671
672/**
673 * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions
674 *
675 * Functions that deal with setup of framebuffers
676 */
677
678/**
679 * Create a new framebuffer object
680 *
681 * @param fd
682 * @param width
683 * @param height
684 * @param depth
685 * @param bpp
686 * @param format
687 *
688 * @return A newly create framebuffer object, or NULL on failure
689 *
690 * @ingroup Ecore_Drm2_Fb_Group
691 * @since 1.18
692 */
693EAPI Ecore_Drm2_Fb *ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format);
694
695EAPI Ecore_Drm2_Fb *ecore_drm2_fb_gbm_create(int fd, int width, int height, int depth, int bpp, unsigned int format, unsigned int handle, unsigned int stride);
696
697/**
698 * Destroy a framebuffer object
699 *
700 * @param fb
701 *
702 * @ingroup Ecore_Drm2_Fb_Group
703 * @since 1.18
704 */
705EAPI void ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb);
706
707/**
708 * Get a framebuffer's mmap'd data
709 *
710 * @param fb
711 *
712 * @return The mmap'd area of the framebuffer or NULL on failure
713 *
714 * @ingroup Ecore_Drm2_Fb_Group
715 * @since 1.18
716 */
717EAPI void *ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb);
718
719/**
720 * Get a framebuffer's size
721 *
722 * @param fb
723 *
724 * @return size of the framebuffers' mmap'd data or 0 on failure
725 *
726 * @ingroup Ecore_Drm2_Fb_Group
727 * @since 1.18
728 */
729EAPI unsigned int ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb);
730
731/**
732 * Get a framebuffer's stride
733 *
734 * @param fb
735 *
736 * @return stride of the framebuffer or 0 on failure
737 *
738 * @ingroup Ecore_Drm2_Fb_Group
739 * @since 1.18
740 */
741EAPI unsigned int ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb);
742
743/**
744 * Mark regions of a framebuffer as dirty
745 *
746 * @param fb
747 * @param rects
748 * @param count
749 *
750 * @ingroup Ecore_Drm2_Fb_Group
751 * @since 1.18
752 */
753EAPI void ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count);
754
755/**
756 * Schedule a pageflip to the given Ecore_Drm2_Fb
757 *
758 * @param fb
759 * @param output
760 * @param data
761 *
762 * @return The result of drmModePageFlip function call
763 *
764 * @ingroup Ecore_Drm2_Fb_Group
765 * @since 1.18
766 */
767EAPI int ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output, void *data);
768
769# endif
770
771#endif
diff --git a/src/lib/ecore_drm2/ecore_drm2.c b/src/lib/ecore_drm2/ecore_drm2.c
new file mode 100644
index 0000000000..339362a9c2
--- /dev/null
+++ b/src/lib/ecore_drm2/ecore_drm2.c
@@ -0,0 +1,83 @@
1#include "ecore_drm2_private.h"
2
3static int _ecore_drm2_init_count = 0;
4
5int _ecore_drm2_log_dom = -1;
6
7EAPI int ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
8EAPI int ECORE_DRM2_EVENT_ACTIVATE = -1;
9
10EAPI int
11ecore_drm2_init(void)
12{
13 if (++_ecore_drm2_init_count != 1) return _ecore_drm2_init_count;
14
15 if (!eina_init()) goto eina_err;
16
17 if (!ecore_init())
18 {
19 EINA_LOG_ERR("Could not initialize Ecore library");
20 goto ecore_err;
21 }
22
23 if (!eeze_init())
24 {
25 EINA_LOG_ERR("Could not initialize Eeze library");
26 goto eeze_err;
27 }
28
29 if (!elput_init())
30 {
31 EINA_LOG_ERR("Could not initialize Elput library");
32 goto elput_err;
33 }
34
35 _ecore_drm2_log_dom =
36 eina_log_domain_register("ecore_drm2", ECORE_DRM2_DEFAULT_LOG_COLOR);
37 if (!_ecore_drm2_log_dom)
38 {
39 EINA_LOG_ERR("Could not create logging domain for Ecore_Drm2");
40 goto log_err;
41 }
42
43 ECORE_DRM2_EVENT_OUTPUT_CHANGED = ecore_event_type_new();
44 ECORE_DRM2_EVENT_ACTIVATE = ecore_event_type_new();
45
46 return _ecore_drm2_init_count;
47
48log_err:
49 elput_shutdown();
50elput_err:
51 eeze_shutdown();
52eeze_err:
53 ecore_shutdown();
54ecore_err:
55 eina_shutdown();
56eina_err:
57 return --_ecore_drm2_init_count;
58}
59
60EAPI int
61ecore_drm2_shutdown(void)
62{
63 if (_ecore_drm2_init_count < 1)
64 {
65 ERR("Ecore_Drm2 shutdown called without init");
66 return 0;
67 }
68
69 if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count;
70
71 ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1;
72 ECORE_DRM2_EVENT_ACTIVATE = -1;
73
74 eina_log_domain_unregister(_ecore_drm2_log_dom);
75 _ecore_drm2_log_dom = -1;
76
77 elput_shutdown();
78 eeze_shutdown();
79 ecore_shutdown();
80 eina_shutdown();
81
82 return _ecore_drm2_init_count;
83}
diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c
new file mode 100644
index 0000000000..95b7315935
--- /dev/null
+++ b/src/lib/ecore_drm2/ecore_drm2_device.c
@@ -0,0 +1,315 @@
1#include "ecore_drm2_private.h"
2
3#ifndef DRM_CAP_CURSOR_WIDTH
4# define DRM_CAP_CURSOR_WIDTH 0x8
5#endif
6
7#ifndef DRM_CAP_CURSOR_HEIGHT
8# define DRM_CAP_CURSOR_HEIGHT 0x9
9#endif
10
11static Eina_Bool
12_cb_session_active(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
13{
14 Elput_Event_Session_Active *ev;
15 Ecore_Drm2_Event_Activate *ea;
16
17 ev = event;
18
19 ea = calloc(1, sizeof(Ecore_Drm2_Event_Activate));
20 if (!ea) return ECORE_CALLBACK_RENEW;
21
22 ea->active = ev->active;
23
24 ecore_event_add(ECORE_DRM2_EVENT_ACTIVATE, ea, NULL, NULL);
25
26 return ECORE_CALLBACK_RENEW;
27}
28
29static const char *
30_drm2_device_find(const char *seat)
31{
32 Eina_List *devs, *l;
33 const char *dev, *ret = NULL;
34 Eina_Bool found = EINA_FALSE;
35 Eina_Bool platform = EINA_FALSE;
36
37 devs = eeze_udev_find_by_subsystem_sysname("drm", "card[0-9]*");
38 if (!devs) return NULL;
39
40 EINA_LIST_FOREACH(devs, l, dev)
41 {
42 const char *dpath, *dseat, *dparent;
43
44 dpath = eeze_udev_syspath_get_devpath(dev);
45 if (!dpath) continue;
46
47 dseat = eeze_udev_syspath_get_property(dev, "ID_SEAT");
48 if (!dseat) dseat = eina_stringshare_add("seat0");
49
50 if ((seat) && (strcmp(seat, dseat)))
51 goto cont;
52 else if (strcmp(dseat, "seat0"))
53 goto cont;
54
55 dparent = eeze_udev_syspath_get_parent_filtered(dev, "pci", NULL);
56 if (!dparent)
57 {
58 dparent =
59 eeze_udev_syspath_get_parent_filtered(dev, "platform", NULL);
60 platform = EINA_TRUE;
61 }
62
63 if (dparent)
64 {
65 if (!platform)
66 {
67 const char *id;
68
69 id = eeze_udev_syspath_get_sysattr(dparent, "boot_vga");
70 if (id)
71 {
72 if (!strcmp(id, "1")) found = EINA_TRUE;
73 eina_stringshare_del(id);
74 }
75 }
76 else
77 found = EINA_TRUE;
78
79 eina_stringshare_del(dparent);
80 }
81
82cont:
83 eina_stringshare_del(dpath);
84 eina_stringshare_del(dseat);
85 if (found) break;
86 }
87
88 if (!found) goto out;
89
90 ret = eeze_udev_syspath_get_devpath(dev);
91
92out:
93 EINA_LIST_FREE(devs, dev)
94 eina_stringshare_del(dev);
95
96 return ret;
97}
98
99EAPI Ecore_Drm2_Device *
100ecore_drm2_device_find(const char *seat, unsigned int tty)
101{
102 Ecore_Drm2_Device *dev;
103
104 dev = calloc(1, sizeof(Ecore_Drm2_Device));
105 if (!dev) return NULL;
106
107 dev->path = _drm2_device_find(seat);
108 if (!dev->path)
109 {
110 ERR("Could not find drm device on seat %s", seat);
111 goto path_err;
112 }
113
114 dev->em = elput_manager_connect(seat, tty);
115 if (!dev->em)
116 {
117 ERR("Could not connect to input manager");
118 goto man_err;
119 }
120
121 return dev;
122
123man_err:
124 eina_stringshare_del(dev->path);
125path_err:
126 free(dev);
127 return NULL;
128}
129
130EAPI int
131ecore_drm2_device_open(Ecore_Drm2_Device *device)
132{
133 EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1);
134
135 device->fd = elput_manager_open(device->em, device->path, -1);
136 if (device->fd < 0) goto open_err;
137
138 if (!elput_input_init(device->em))
139 {
140 ERR("Could not initialize Elput Input");
141 goto input_err;
142 }
143
144 DBG("Device Path: %s", device->path);
145 DBG("Device Fd: %d", device->fd);
146
147 device->active_hdlr =
148 ecore_event_handler_add(ELPUT_EVENT_SESSION_ACTIVE,
149 _cb_session_active, device);
150
151 /* NB: Not going to enable planes if we don't support atomic */
152 /* if (drmSetClientCap(device->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) */
153 /* ERR("Could not set Universal Plane support: %m"); */
154
155 return device->fd;
156
157input_err:
158 elput_manager_close(device->em, device->fd);
159open_err:
160 return -1;
161}
162
163EAPI void
164ecore_drm2_device_close(Ecore_Drm2_Device *device)
165{
166 EINA_SAFETY_ON_NULL_RETURN(device);
167 EINA_SAFETY_ON_TRUE_RETURN(device->fd < 0);
168
169 elput_input_shutdown(device->em);
170 elput_manager_close(device->em, device->fd);
171}
172
173EAPI void
174ecore_drm2_device_free(Ecore_Drm2_Device *device)
175{
176 EINA_SAFETY_ON_NULL_RETURN(device);
177
178 if (device->active_hdlr) ecore_event_handler_del(device->active_hdlr);
179 device->active_hdlr = NULL;
180
181 eina_stringshare_del(device->path);
182 free(device);
183}
184
185EAPI int
186ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device)
187{
188 uint64_t caps;
189 int ret;
190
191 EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1);
192 EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), -1);
193
194 ret = drmGetCap(device->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &caps);
195 if ((ret == 0) && (caps == 1))
196 return CLOCK_MONOTONIC;
197 else
198 return CLOCK_REALTIME;
199}
200
201EAPI void
202ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height)
203{
204 uint64_t caps;
205 int ret;
206
207 EINA_SAFETY_ON_NULL_RETURN(device);
208 EINA_SAFETY_ON_TRUE_RETURN((device->fd < 0));
209
210 if (width)
211 {
212 *width = 64;
213 ret = drmGetCap(device->fd, DRM_CAP_CURSOR_WIDTH, &caps);
214 if (ret == 0) *width = caps;
215 }
216 if (height)
217 {
218 *height = 64;
219 ret = drmGetCap(device->fd, DRM_CAP_CURSOR_HEIGHT, &caps);
220 if (ret == 0) *height = caps;
221 }
222}
223
224EAPI void
225ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, int *y)
226{
227 if (x) *x = 0;
228 if (y) *y = 0;
229
230 EINA_SAFETY_ON_NULL_RETURN(device);
231
232 elput_input_pointer_xy_get(device->em, NULL, x, y);
233}
234
235EAPI void
236ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y)
237{
238 EINA_SAFETY_ON_NULL_RETURN(device);
239
240 elput_input_pointer_xy_set(device->em, NULL, x, y);
241}
242
243EAPI Eina_Bool
244ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device *device, Eina_Bool left)
245{
246 EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
247
248 return elput_input_pointer_left_handed_set(device->em, NULL, left);
249}
250
251EAPI void
252ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window)
253{
254 EINA_SAFETY_ON_NULL_RETURN(device);
255 EINA_SAFETY_ON_NULL_RETURN(device->em);
256 elput_manager_window_set(device->em, window);
257}
258
259EAPI void
260ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h)
261{
262 EINA_SAFETY_ON_NULL_RETURN(device);
263 EINA_SAFETY_ON_NULL_RETURN(device->em);
264
265 elput_input_pointer_max_set(device->em, w, h);
266}
267
268EAPI void
269ecore_drm2_device_keyboard_cached_context_set(Ecore_Drm2_Device *device, void *context)
270{
271 EINA_SAFETY_ON_NULL_RETURN(device);
272
273 elput_input_keyboard_cached_context_set(device->em, context);
274}
275
276EAPI void
277ecore_drm2_device_keyboard_cached_keymap_set(Ecore_Drm2_Device *device, void *keymap)
278{
279 EINA_SAFETY_ON_NULL_RETURN(device);
280
281 elput_input_keyboard_cached_keymap_set(device->em, keymap);
282}
283
284EAPI unsigned int *
285ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num)
286{
287 EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL);
288
289 if (num) *num = device->num_crtcs;
290 return device->crtcs;
291}
292
293EAPI void
294ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, int *minh, int *maxw, int *maxh)
295{
296 if (minw) *minw = 0;
297 if (minh) *minh = 0;
298 if (maxw) *maxw = 0;
299 if (maxh) *maxh = 0;
300
301 EINA_SAFETY_ON_NULL_RETURN(device);
302
303 if (minw) *minw = device->min.width;
304 if (minh) *minh = device->min.height;
305 if (maxw) *maxw = device->max.width;
306 if (maxh) *maxh = device->max.height;
307}
308
309EAPI void
310ecore_drm2_device_calibrate(Ecore_Drm2_Device *device, int w, int h)
311{
312 EINA_SAFETY_ON_NULL_RETURN(device);
313
314 elput_input_devices_calibrate(device->em, w, h);
315}
diff --git a/src/lib/ecore_drm2/ecore_drm2_fb.c b/src/lib/ecore_drm2/ecore_drm2_fb.c
new file mode 100644
index 0000000000..9032c122be
--- /dev/null
+++ b/src/lib/ecore_drm2/ecore_drm2_fb.c
@@ -0,0 +1,265 @@
1#include "ecore_drm2_private.h"
2
3static Eina_Bool
4_fb2_create(Ecore_Drm2_Fb *fb)
5{
6 struct drm_mode_fb_cmd2 cmd;
7 uint32_t hdls[4], pitches[4], offsets[4];
8 uint64_t modifiers[4];
9
10 hdls[0] = fb->hdl;
11 pitches[0] = fb->stride;
12 offsets[0] = 0;
13 modifiers[0] = 0;
14
15 memset(&cmd, 0, sizeof(struct drm_mode_fb_cmd2));
16 cmd.fb_id = 0;
17 cmd.width = fb->w;
18 cmd.height = fb->h;
19 cmd.pixel_format = fb->format;
20 cmd.flags = 0;
21 memcpy(cmd.handles, hdls, 4 * sizeof(hdls[0]));
22 memcpy(cmd.pitches, pitches, 4 * sizeof(pitches[0]));
23 memcpy(cmd.offsets, offsets, 4 * sizeof(offsets[0]));
24 memcpy(cmd.modifier, modifiers, 4 * sizeof(modifiers[0]));
25
26 if (drmIoctl(fb->fd, DRM_IOCTL_MODE_ADDFB2, &cmd))
27 return EINA_FALSE;
28
29 fb->id = cmd.fb_id;
30
31 return EINA_TRUE;
32}
33
34EAPI Ecore_Drm2_Fb *
35ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format)
36{
37 Ecore_Drm2_Fb *fb;
38 struct drm_mode_create_dumb carg;
39 struct drm_mode_destroy_dumb darg;
40 struct drm_mode_map_dumb marg;
41 int ret;
42
43 EINA_SAFETY_ON_TRUE_RETURN_VAL((fd < 0), NULL);
44
45 fb = calloc(1, sizeof(Ecore_Drm2_Fb));
46 if (!fb) return NULL;
47
48 fb->fd = fd;
49 fb->w = width;
50 fb->h = height;
51 fb->bpp = bpp;
52 fb->depth = depth;
53 fb->format = format;
54
55 memset(&carg, 0, sizeof(struct drm_mode_create_dumb));
56 carg.bpp = bpp;
57 carg.width = width;
58 carg.height = height;
59
60 ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg);
61 if (ret) goto err;
62
63 fb->hdl = carg.handle;
64 fb->size = carg.size;
65 fb->stride = carg.pitch;
66
67 if (!_fb2_create(fb))
68 {
69 ret =
70 drmModeAddFB(fd, width, height, depth, bpp,
71 fb->stride, fb->hdl, &fb->id);
72 if (ret)
73 {
74 ERR("Could not add framebuffer: %m");
75 goto add_err;
76 }
77 }
78
79 memset(&marg, 0, sizeof(struct drm_mode_map_dumb));
80 marg.handle = fb->hdl;
81 ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &marg);
82 if (ret)
83 {
84 ERR("Could not map framebuffer: %m");
85 goto map_err;
86 }
87
88 fb->mmap = mmap(NULL, fb->size, PROT_WRITE, MAP_SHARED, fd, marg.offset);
89 if (fb->mmap == MAP_FAILED)
90 {
91 ERR("Could not mmap framebuffer memory: %m");
92 goto map_err;
93 }
94
95 return fb;
96
97map_err:
98 drmModeRmFB(fd, fb->id);
99add_err:
100 memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
101 darg.handle = fb->hdl;
102 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
103err:
104 free(fb);
105 return NULL;
106}
107
108EAPI Ecore_Drm2_Fb *
109ecore_drm2_fb_gbm_create(int fd, int width, int height, int depth, int bpp, unsigned int format, unsigned int handle, unsigned int stride)
110{
111 Ecore_Drm2_Fb *fb;
112
113 EINA_SAFETY_ON_TRUE_RETURN_VAL((fd < 0), NULL);
114
115 fb = calloc(1, sizeof(Ecore_Drm2_Fb));
116 if (!fb) return NULL;
117
118 fb->gbm = EINA_TRUE;
119
120 fb->fd = fd;
121 fb->w = width;
122 fb->h = height;
123 fb->bpp = bpp;
124 fb->depth = depth;
125 fb->format = format;
126 fb->stride = stride;
127 fb->size = fb->stride * fb->h;
128 fb->hdl = handle;
129
130 if (!_fb2_create(fb))
131 {
132 int ret;
133
134 ret =
135 drmModeAddFB(fd, width, height, depth, bpp,
136 fb->stride, fb->hdl, &fb->id);
137 if (ret)
138 {
139 ERR("Could not add framebuffer: %m");
140 goto err;
141 }
142 }
143
144 return fb;
145
146err:
147 free(fb);
148 return NULL;
149}
150
151EAPI void
152ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb)
153{
154 EINA_SAFETY_ON_NULL_RETURN(fb);
155
156 if (fb->id) drmModeRmFB(fb->fd, fb->id);
157
158 if (!fb->gbm)
159 {
160 struct drm_mode_destroy_dumb darg;
161
162 if (fb->mmap) munmap(fb->mmap, fb->size);
163
164 memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb));
165 darg.handle = fb->hdl;
166 drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
167 }
168
169 free(fb);
170}
171
172EAPI void *
173ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb)
174{
175 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL);
176 return fb->mmap;
177}
178
179EAPI unsigned int
180ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb)
181{
182 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
183 return fb->size;
184}
185
186EAPI unsigned int
187ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb)
188{
189 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0);
190 return fb->stride;
191}
192
193EAPI void
194ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count)
195{
196 EINA_SAFETY_ON_NULL_RETURN(fb);
197 EINA_SAFETY_ON_NULL_RETURN(rects);
198
199#ifdef DRM_MODE_FEATURE_DIRTYFB
200 drmModeClip *clip;
201 unsigned int i = 0;
202 int ret;
203
204 clip = alloca(count * sizeof(drmModeClip));
205 for (i = 0; i < count; i++)
206 {
207 clip[i].x1 = rects[i].x;
208 clip[i].y1 = rects[i].y;
209 clip[i].x2 = rects[i].w;
210 clip[i].y2 = rects[i].h;
211 }
212
213 ret = drmModeDirtyFB(fb->fd, fb->id, clip, count);
214 if ((ret) && (ret == -EINVAL))
215 WRN("Could not mark framebuffer as dirty: %m");
216#endif
217}
218
219EAPI int
220ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output, void *data)
221{
222 int ret = 0;
223
224 EINA_SAFETY_ON_NULL_RETURN_VAL(fb, -1);
225 EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1);
226 EINA_SAFETY_ON_NULL_RETURN_VAL(output->current_mode, -1);
227
228 if (output->next)
229 WRN("Fb reused too soon, tearing may be visible");
230
231 if ((!output->current) ||
232 (output->current->stride != fb->stride))
233 {
234 ret =
235 drmModeSetCrtc(fb->fd, output->crtc_id, fb->id,
236 output->x, output->y, &output->conn_id, 1,
237 &output->current_mode->info);
238 if (ret)
239 {
240 ERR("Failed to set Mode %dx%d for Output %s: %m",
241 output->current_mode->width, output->current_mode->height,
242 output->name);
243 return ret;
244 }
245
246 output->current = fb;
247 output->next = NULL;
248
249 return 0;
250 }
251
252 ret =
253 drmModePageFlip(fb->fd, output->crtc_id, fb->id,
254 DRM_MODE_PAGE_FLIP_EVENT, data);
255 if (ret < 0)
256 {
257 DBG("Pageflip Failed for Crtc %u on Connector %u: %m",
258 output->crtc_id, output->conn_id);
259 output->next = fb;
260 return ret;
261 }
262
263 output->current = fb;
264 return 0;
265}
diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c
new file mode 100644
index 0000000000..7596164f73
--- /dev/null
+++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c
@@ -0,0 +1,1155 @@
1#include "ecore_drm2_private.h"
2
3#define INSIDE(x, y, xx, yy, ww, hh) \
4 (((x) < ((xx) + (ww))) && ((y) < ((yy) + (hh))) && \
5 ((x) >= (xx)) && ((y) >= (yy)))
6
7#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe
8#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc
9#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff
10#define EDID_OFFSET_DATA_BLOCKS 0x36
11#define EDID_OFFSET_LAST_BLOCK 0x6c
12#define EDID_OFFSET_PNPID 0x08
13#define EDID_OFFSET_SERIAL 0x0c
14
15static const char *conn_types[] =
16{
17 "None", "VGA", "DVI-I", "DVI-D", "DVI-A",
18 "Composite", "S-Video", "LVDS", "Component", "DIN",
19 "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual", "DSI",
20};
21
22static void
23_output_debug(Ecore_Drm2_Output *output, const drmModeConnector *conn)
24{
25 Eina_List *l;
26 Ecore_Drm2_Output_Mode *omode;
27
28 DBG("Created New Output At %d,%d", output->x, output->y);
29 DBG("\tCrtc Pos: %d %d", output->ocrtc->x, output->ocrtc->y);
30 DBG("\tCrtc: %d", output->crtc_id);
31 DBG("\tConn: %d", output->conn_id);
32 DBG("\tName: %s", output->name);
33 DBG("\tMake: %s", output->make);
34 DBG("\tModel: %s", output->model);
35 DBG("\tSerial: %s", output->serial);
36 DBG("\tCloned: %d", output->cloned);
37 DBG("\tPrimary: %d", output->primary);
38 DBG("\tConnected: %d", output->connected);
39 DBG("\tEnabled: %d", output->enabled);
40
41 if (output->backlight.path)
42 {
43 DBG("\tBacklight");
44 switch (output->backlight.type)
45 {
46 case ECORE_DRM2_BACKLIGHT_RAW:
47 DBG("\t\tType: Raw");
48 break;
49 case ECORE_DRM2_BACKLIGHT_PLATFORM:
50 DBG("\t\tType: Platform");
51 break;
52 case ECORE_DRM2_BACKLIGHT_FIRMWARE:
53 DBG("\t\tType: Firmware");
54 break;
55 }
56 DBG("\t\tPath: %s", output->backlight.path);
57 }
58
59 EINA_LIST_FOREACH(output->modes, l, omode)
60 {
61 DBG("\tAdded Mode: %dx%d@%d%s%s%s",
62 omode->width, omode->height, omode->refresh,
63 (omode->flags & DRM_MODE_TYPE_PREFERRED) ? ", preferred" : "",
64 (omode->flags & DRM_MODE_TYPE_DEFAULT) ? ", current" : "",
65 (conn->count_modes == 0) ? ", built-in" : "");
66 }
67}
68
69static void
70_cb_output_event_free(void *data EINA_UNUSED, void *event)
71{
72 Ecore_Drm2_Event_Output_Changed *ev;
73
74 ev = event;
75 eina_stringshare_del(ev->make);
76 eina_stringshare_del(ev->model);
77 eina_stringshare_del(ev->name);
78 free(ev);
79}
80
81static void
82_output_event_send(Ecore_Drm2_Output *output)
83{
84 Ecore_Drm2_Event_Output_Changed *ev;
85
86 ev = calloc(1, sizeof(Ecore_Drm2_Event_Output_Changed));
87 if (!ev) return;
88
89 ev->id = output->crtc_id;
90
91 ev->x = output->x;
92 ev->y = output->y;
93 if (output->current_mode)
94 {
95 ev->w = output->current_mode->width;
96 ev->h = output->current_mode->height;
97 ev->refresh = output->current_mode->refresh;
98 }
99 else
100 {
101 ev->w = output->ocrtc->width;
102 ev->h = output->ocrtc->height;
103 ev->refresh = 0;
104 }
105
106 ev->phys_width = output->pw;
107 ev->phys_height = output->ph;
108
109 ev->scale = output->scale;
110 ev->subpixel = output->subpixel;
111 ev->transform = output->transform;
112 ev->connected = output->connected;
113 ev->enabled = output->enabled;
114
115 ev->name = eina_stringshare_ref(output->name);
116 ev->make = eina_stringshare_ref(output->make);
117 ev->model = eina_stringshare_ref(output->model);
118
119 ecore_event_add(ECORE_DRM2_EVENT_OUTPUT_CHANGED, ev,
120 _cb_output_event_free, NULL);
121}
122
123static void
124_output_edid_parse_string(const uint8_t *data, char text[])
125{
126 int i = 0, rep = 0;
127
128 strncpy(text, (const char *)data, 12);
129
130 for (; text[i] != '\0'; i++)
131 {
132 if ((text[i] == '\n') || (text[i] == '\r'))
133 {
134 text[i] = '\0';
135 break;
136 }
137 }
138
139 for (i = 0; text[i] != '\0'; i++)
140 {
141 if (!isprint(text[i]))
142 {
143 text[i] = '-';
144 rep++;
145 }
146 }
147
148 if (rep > 4) text[0] = '\0';
149}
150
151static int
152_output_edid_parse(Ecore_Drm2_Output *output, const uint8_t *data, size_t len)
153{
154 int i = 0;
155 uint32_t serial;
156
157 if (len < 128) return -1;
158 if ((data[0] != 0x00) || (data[1] != 0xff)) return -1;
159
160 output->edid.pnp[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
161 output->edid.pnp[1] =
162 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) +
163 ((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
164 output->edid.pnp[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
165 output->edid.pnp[3] = '\0';
166
167 serial = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
168 serial += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
169 serial += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
170 serial += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
171 if (serial > 0)
172 sprintf(output->edid.serial, "%lu", (unsigned long)serial);
173
174 for (i = EDID_OFFSET_DATA_BLOCKS; i <= EDID_OFFSET_LAST_BLOCK; i += 18)
175 {
176 if (data[i] != 0) continue;
177 if (data[i + 2] != 0) continue;
178
179 if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME)
180 _output_edid_parse_string(&data[i + 5], output->edid.monitor);
181 else if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER)
182 _output_edid_parse_string(&data[i + 5], output->edid.serial);
183 else if (data[i + 3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING)
184 _output_edid_parse_string(&data[i + 5], output->edid.eisa);
185 }
186
187 return 0;
188}
189
190static void
191_output_edid_find(Ecore_Drm2_Output *output, const drmModeConnector *conn)
192{
193 drmModePropertyBlobPtr blob = NULL;
194 drmModePropertyPtr prop;
195 int i = 0, ret = 0;
196
197 for (; i < conn->count_props && !blob; i++)
198 {
199 if (!(prop = drmModeGetProperty(output->fd, conn->props[i])))
200 continue;
201 if ((prop->flags & DRM_MODE_PROP_BLOB) &&
202 (!strcmp(prop->name, "EDID")))
203 {
204 blob = drmModeGetPropertyBlob(output->fd, conn->prop_values[i]);
205 }
206 drmModeFreeProperty(prop);
207 if (blob) break;
208 }
209
210 if (!blob) return;
211
212 output->edid.blob = eina_memdup(blob->data, blob->length, 1);
213
214 ret = _output_edid_parse(output, blob->data, blob->length);
215 if (!ret)
216 {
217 if (output->edid.pnp[0] != '\0')
218 eina_stringshare_replace(&output->make, output->edid.pnp);
219 if (output->edid.monitor[0] != '\0')
220 eina_stringshare_replace(&output->model, output->edid.monitor);
221 if (output->edid.serial[0] != '\0')
222 eina_stringshare_replace(&output->serial, output->edid.serial);
223 }
224
225 drmModeFreePropertyBlob(blob);
226}
227
228static int
229_output_crtc_find(const drmModeRes *res, const drmModeConnector *conn, Ecore_Drm2_Device *dev)
230{
231 drmModeEncoder *enc;
232 uint32_t crtc;
233 int i = 0, j = 0;
234
235 for (j = 0; j < conn->count_encoders; j++)
236 {
237 enc = drmModeGetEncoder(dev->fd, conn->encoders[j]);
238 if (!enc) continue;
239
240 crtc = enc->crtc_id;
241 drmModeFreeEncoder(enc);
242
243 for (i = 0; i < res->count_crtcs; i++)
244 if (crtc == res->crtcs[i])
245 return i;
246 }
247
248 return -1;
249}
250
251static char *
252_output_name_get(const drmModeConnector *conn)
253{
254 char name[DRM_CONNECTOR_NAME_LEN];
255 const char *type = NULL;
256
257 if (conn->connector_type < EINA_C_ARRAY_LENGTH(conn_types))
258 type = conn_types[conn->connector_type];
259 else
260 type = "UNKNOWN";
261
262 snprintf(name, sizeof(name), "%s-%d", type, conn->connector_type_id);
263 return strdup(name);
264}
265
266static Ecore_Drm2_Output_Mode *
267_output_mode_add(Ecore_Drm2_Output *output, const drmModeModeInfo *info)
268{
269 Ecore_Drm2_Output_Mode *mode;
270 uint64_t refresh;
271
272 mode = calloc(1, sizeof(Ecore_Drm2_Output_Mode));
273 if (!mode) return NULL;
274
275 mode->flags = 0;
276 mode->width = info->hdisplay;
277 mode->height = info->vdisplay;
278
279 refresh = (info->clock * 1000LL / info->htotal + info->vtotal / 2) /
280 info->vtotal;
281
282 if (info->flags & DRM_MODE_FLAG_INTERLACE)
283 refresh *= 2;
284 if (info->flags & DRM_MODE_FLAG_DBLSCAN)
285 refresh /= 2;
286 if (info->vscan > 1)
287 refresh /= info->vscan;
288
289 mode->refresh = refresh;
290 mode->info = *info;
291
292 if (info->type & DRM_MODE_TYPE_PREFERRED)
293 mode->flags |= DRM_MODE_TYPE_PREFERRED;
294
295 output->modes = eina_list_append(output->modes, mode);
296
297 return mode;
298}
299
300static void
301_output_modes_create(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output, const drmModeConnector *conn)
302{
303 int i = 0;
304 drmModeCrtc *crtc;
305 drmModeEncoder *enc;
306 drmModeModeInfo crtc_mode;
307 Ecore_Drm2_Output_Mode *omode;
308 Ecore_Drm2_Output_Mode *current = NULL, *preferred = NULL, *best = NULL;
309 Eina_List *l = NULL;
310
311 memset(&crtc_mode, 0, sizeof(crtc_mode));
312
313 enc = drmModeGetEncoder(dev->fd, conn->encoder_id);
314 if (enc)
315 {
316 crtc = drmModeGetCrtc(dev->fd, enc->crtc_id);
317 drmModeFreeEncoder(enc);
318 if (!crtc) return;
319 if (crtc->mode_valid) crtc_mode = crtc->mode;
320 drmModeFreeCrtc(crtc);
321 }
322
323 for (i = 0; i < conn->count_modes; i++)
324 {
325 omode = _output_mode_add(output, &conn->modes[i]);
326 if (!omode) continue;
327 }
328
329 EINA_LIST_REVERSE_FOREACH(output->modes, l, omode)
330 {
331 if (!memcmp(&crtc_mode, &omode->info, sizeof(crtc_mode)))
332 current = omode;
333 if (omode->flags & DRM_MODE_TYPE_PREFERRED)
334 preferred = omode;
335 best = omode;
336 }
337
338 if ((!current) && (crtc_mode.clock != 0))
339 {
340 current = _output_mode_add(output, &crtc_mode);
341 if (!current) goto err;
342 }
343
344 if (current) output->current_mode = current;
345 else if (preferred) output->current_mode = preferred;
346 else if (best) output->current_mode = best;
347
348 if (!output->current_mode) goto err;
349
350 output->current_mode->flags |= DRM_MODE_TYPE_DEFAULT;
351
352 return;
353
354err:
355 EINA_LIST_FREE(output->modes, omode)
356 free(omode);
357}
358
359static drmModePropertyPtr
360_output_dpms_property_get(int fd, const drmModeConnector *conn)
361{
362 drmModePropertyPtr prop;
363 int i = 0;
364
365 for (; i < conn->count_props; i++)
366 {
367 prop = drmModeGetProperty(fd, conn->props[i]);
368 if (!prop) continue;
369
370 if (!strcmp(prop->name, "DPMS")) return prop;
371
372 drmModeFreeProperty(prop);
373 }
374
375 return NULL;
376}
377
378static void
379_output_backlight_init(Ecore_Drm2_Output *output, unsigned int conn_type)
380{
381 Eina_List *devs, *l;
382 const char *dev, *t;
383 Eina_Bool found = EINA_FALSE;
384 Ecore_Drm2_Backlight_Type type = 0;
385
386 devs = eeze_udev_find_by_filter("backlight", NULL, NULL);
387
388 EINA_LIST_FOREACH(devs, l, dev)
389 {
390 t = eeze_udev_syspath_get_sysattr(dev, "type");
391 if (!t) continue;
392
393 if (!strcmp(t, "raw"))
394 type = ECORE_DRM2_BACKLIGHT_RAW;
395 else if (!strcmp(t, "platform"))
396 type = ECORE_DRM2_BACKLIGHT_PLATFORM;
397 else if (!strcmp(t, "firmware"))
398 type = ECORE_DRM2_BACKLIGHT_FIRMWARE;
399
400 if ((conn_type == DRM_MODE_CONNECTOR_LVDS) ||
401 (conn_type == DRM_MODE_CONNECTOR_eDP) ||
402 (type == ECORE_DRM2_BACKLIGHT_RAW))
403 found = EINA_TRUE;
404
405 eina_stringshare_del(t);
406 if (found) break;
407 }
408
409 if (found)
410 {
411 output->backlight.type = type;
412 output->backlight.path = eina_stringshare_add(dev);
413 }
414
415 EINA_LIST_FREE(devs, dev)
416 eina_stringshare_del(dev);
417}
418
419static void
420_output_scale_init(Ecore_Drm2_Output *output, Ecore_Drm2_Transform transform, unsigned int scale)
421{
422 output->transform = transform;
423
424 if ((output->enabled) && (output->current_mode))
425 {
426 switch (transform)
427 {
428 case ECORE_DRM2_TRANSFORM_90:
429 case ECORE_DRM2_TRANSFORM_270:
430 case ECORE_DRM2_TRANSFORM_FLIPPED_90:
431 case ECORE_DRM2_TRANSFORM_FLIPPED_270:
432 output->w = output->current_mode->height;
433 output->h = output->current_mode->width;
434 break;
435 case ECORE_DRM2_TRANSFORM_NORMAL:
436 case ECORE_DRM2_TRANSFORM_180:
437 case ECORE_DRM2_TRANSFORM_FLIPPED:
438 case ECORE_DRM2_TRANSFORM_FLIPPED_180:
439 output->w = output->current_mode->width;
440 output->h = output->current_mode->height;
441 break;
442 default:
443 break;
444 }
445 }
446
447 output->scale = scale;
448 output->w /= scale;
449 output->h /= scale;
450}
451
452static void
453_output_matrix_rotate_xy(Eina_Matrix3 *matrix, double x, double y)
454{
455 Eina_Matrix4 tmp, m;
456
457 eina_matrix4_identity(&tmp);
458 eina_matrix4_values_set(&tmp, x, y, 0, 0, -y, x, 0, 0,
459 0, 0, 1, 0, 0, 0, 0, 1);
460
461 eina_matrix3_matrix4_to(&m, matrix);
462 eina_matrix4_multiply(&m, &m, &tmp);
463 eina_matrix4_matrix3_to(matrix, &m);
464}
465
466static void
467_output_matrix_update(Ecore_Drm2_Output *output)
468{
469 Eina_Matrix3 m3;
470
471 eina_matrix4_identity(&output->matrix);
472 eina_matrix4_matrix3_to(&m3, &output->matrix);
473 eina_matrix3_translate(&m3, -output->x, -output->y);
474
475 switch (output->transform)
476 {
477 case ECORE_DRM2_TRANSFORM_FLIPPED:
478 case ECORE_DRM2_TRANSFORM_FLIPPED_90:
479 case ECORE_DRM2_TRANSFORM_FLIPPED_180:
480 case ECORE_DRM2_TRANSFORM_FLIPPED_270:
481 eina_matrix3_translate(&m3, -output->w, 0);
482 break;
483 default:
484 break;
485 }
486
487 switch (output->transform)
488 {
489 case ECORE_DRM2_TRANSFORM_NORMAL:
490 case ECORE_DRM2_TRANSFORM_FLIPPED:
491 default:
492 break;
493 case ECORE_DRM2_TRANSFORM_90:
494 case ECORE_DRM2_TRANSFORM_FLIPPED_90:
495 eina_matrix3_translate(&m3, 0, -output->h);
496 _output_matrix_rotate_xy(&m3, 0, 1);
497 break;
498 case ECORE_DRM2_TRANSFORM_180:
499 case ECORE_DRM2_TRANSFORM_FLIPPED_180:
500 eina_matrix3_translate(&m3, -output->w, -output->h);
501 _output_matrix_rotate_xy(&m3, -1, 0);
502 break;
503 case ECORE_DRM2_TRANSFORM_270:
504 case ECORE_DRM2_TRANSFORM_FLIPPED_270:
505 eina_matrix3_translate(&m3, -output->w, 0);
506 _output_matrix_rotate_xy(&m3, 0, -1);
507 break;
508 }
509
510 if (output->scale != 1)
511 eina_matrix3_scale(&m3, output->scale, output->scale);
512
513 eina_matrix3_matrix4_to(&output->matrix, &m3);
514 eina_matrix4_inverse(&output->inverse, &output->matrix);
515}
516
517static Eina_Bool
518_output_create(Ecore_Drm2_Device *dev, const drmModeRes *res, const drmModeConnector *conn, int x, int y, int *w, Eina_Bool cloned)
519{
520 Ecore_Drm2_Output *output;
521 int i = 0;
522
523 if (w) *w = 0;
524
525 i = _output_crtc_find(res, conn, dev);
526 if (i < 0) return EINA_FALSE;
527
528 output = calloc(1, sizeof(Ecore_Drm2_Output));
529 if (!output) return EINA_FALSE;
530
531 output->fd = dev->fd;
532 output->x = x;
533 output->y = y;
534 output->cloned = cloned;
535 output->pw = conn->mmWidth;
536 output->ph = conn->mmHeight;
537
538 switch (conn->subpixel)
539 {
540 case DRM_MODE_SUBPIXEL_UNKNOWN:
541 output->subpixel = 0; // WL_OUTPUT_SUBPIXEL_UNKNOWN
542 break;
543 case DRM_MODE_SUBPIXEL_NONE:
544 output->subpixel = 1; // WL_OUTPUT_SUBPIXEL_NONE
545 break;
546 case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
547 output->subpixel = 2; // WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB
548 break;
549 case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
550 output->subpixel = 3; // WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR
551 break;
552 case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
553 output->subpixel = 4; // WL_OUTPUT_SUBPIXEL_VERTICAL_RGB
554 break;
555 case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
556 output->subpixel = 5; // WL_OUTPUT_SUBPIXEL_VERTICAL_BGR
557 break;
558 default:
559 output->subpixel = 0;
560 break;
561 }
562
563 output->name = eina_stringshare_add(_output_name_get(conn));
564 output->make = eina_stringshare_add("unknown");
565 output->model = eina_stringshare_add("unknown");
566 output->serial = eina_stringshare_add("unknown");
567
568 output->pipe = i;
569 output->crtc_id = res->crtcs[i];
570 output->conn_id = conn->connector_id;
571 output->conn_type = conn->connector_type;
572
573 output->connected = (conn->connection == DRM_MODE_CONNECTED);
574
575 output->ocrtc = drmModeGetCrtc(dev->fd, output->crtc_id);
576
577 output->dpms = _output_dpms_property_get(dev->fd, conn);
578
579 _output_backlight_init(output, conn->connector_type);
580
581 /* TODO: gamma */
582
583 _output_modes_create(dev, output, conn);
584
585 _output_edid_find(output, conn);
586
587 if (output->connected) output->enabled = EINA_TRUE;
588
589 _output_scale_init(output, ECORE_DRM2_TRANSFORM_NORMAL, 1);
590 _output_matrix_update(output);
591
592 if (!eina_list_count(dev->outputs))
593 output->primary = EINA_TRUE;
594
595 dev->alloc.crtc |= (1 << output->crtc_id);
596 dev->alloc.conn |= (1 << output->conn_id);
597 dev->outputs = eina_list_append(dev->outputs, output);
598
599 _output_debug(output, conn);
600
601 if ((output->enabled) && (output->current_mode))
602 {
603 if (w) *w = output->current_mode->width;
604 }
605
606 return EINA_TRUE;
607}
608
609static void
610_outputs_update(Ecore_Drm2_Device *dev)
611{
612 drmModeRes *res;
613 drmModeConnector *conn;
614 uint32_t connected = 0, disconnected = 0;
615 int i = 0, x = 0, y = 0;
616
617 res = drmModeGetResources(dev->fd);
618 if (!res) return;
619
620 for (i = 0; i < res->count_connectors; i++)
621 {
622 conn = drmModeGetConnector(dev->fd, res->connectors[i]);
623 if (!conn) continue;
624
625 if (conn->connection != DRM_MODE_CONNECTED) goto next;
626
627 connected |= (1 << res->connectors[i]);
628
629 if (!(dev->alloc.conn & (1 << res->connectors[i])))
630 {
631 if (dev->outputs)
632 {
633 Ecore_Drm2_Output *last;
634
635 last = eina_list_last_data_get(dev->outputs);
636 if (last) x = last->x + last->current_mode->width;
637 else x = 0;
638 }
639 else
640 x = 0;
641
642 if (!_output_create(dev, res, conn, x, y, NULL, EINA_TRUE))
643 goto next;
644 }
645
646next:
647 drmModeFreeConnector(conn);
648 }
649
650 drmModeFreeResources(res);
651
652 disconnected = (dev->alloc.conn & ~connected);
653 if (disconnected)
654 {
655 Ecore_Drm2_Output *output;
656 Eina_List *l;
657
658 EINA_LIST_FOREACH(dev->outputs, l, output)
659 {
660 if (disconnected & (1 << output->conn_id))
661 {
662 disconnected &= ~(1 << output->conn_id);
663 output->connected = EINA_FALSE;
664 output->enabled = EINA_FALSE;
665 _output_event_send(output);
666 }
667 }
668 }
669}
670
671static void
672_cb_output_event(const char *device EINA_UNUSED, Eeze_Udev_Event event EINA_UNUSED, void *data, Eeze_Udev_Watch *watch EINA_UNUSED)
673{
674 Ecore_Drm2_Device *dev;
675
676 dev = data;
677 _outputs_update(dev);
678}
679
680static void
681_output_destroy(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output)
682{
683 dev->alloc.crtc &= ~(1 << output->crtc_id);
684 dev->alloc.conn &= ~(1 << output->conn_id);
685
686 eina_stringshare_del(output->backlight.path);
687 eina_stringshare_del(output->name);
688 eina_stringshare_del(output->make);
689 eina_stringshare_del(output->model);
690 eina_stringshare_del(output->serial);
691
692 drmModeFreeProperty(output->dpms);
693 free(output->edid.blob);
694
695 free(output);
696}
697
698EAPI Eina_Bool
699ecore_drm2_outputs_create(Ecore_Drm2_Device *device)
700{
701 drmModeConnector *conn;
702 drmModeRes *res;
703 int i = 0, x = 0, y = 0, w = 0;
704 int events = 0;
705
706 EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE);
707 EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), EINA_FALSE);
708
709 res = drmModeGetResources(device->fd);
710 if (!res) return EINA_FALSE;
711
712 device->crtcs = calloc(res->count_crtcs, sizeof(uint32_t));
713 if (!device->crtcs) goto err;
714
715 device->min.width = res->min_width;
716 device->min.height = res->min_height;
717 device->max.width = res->max_width;
718 device->max.height = res->max_height;
719
720 device->num_crtcs = res->count_crtcs;
721 memcpy(device->crtcs, res->crtcs, sizeof(uint32_t) * res->count_crtcs);
722
723 for (i = 0; i < res->count_connectors; i++)
724 {
725 conn = drmModeGetConnector(device->fd, res->connectors[i]);
726 if (!conn) continue;
727
728 if (!_output_create(device, res, conn, x, y, &w, EINA_FALSE))
729 goto next;
730
731 x += w;
732
733next:
734 drmModeFreeConnector(conn);
735 }
736
737 if (eina_list_count(device->outputs) < 1) goto err;
738
739 drmModeFreeResources(res);
740
741 events = (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE |
742 EEZE_UDEV_EVENT_CHANGE);
743
744 device->watch =
745 eeze_udev_watch_add(EEZE_UDEV_TYPE_DRM, events,
746 _cb_output_event, device);
747
748 return EINA_TRUE;
749
750err:
751 drmModeFreeResources(res);
752 return EINA_FALSE;
753}
754
755EAPI void
756ecore_drm2_outputs_destroy(Ecore_Drm2_Device *device)
757{
758 Ecore_Drm2_Output *output;
759
760 EINA_SAFETY_ON_NULL_RETURN(device);
761
762 EINA_LIST_FREE(device->outputs, output)
763 _output_destroy(device, output);
764}
765
766EAPI const Eina_List *
767ecore_drm2_outputs_get(Ecore_Drm2_Device *device)
768{
769 EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL);
770 return device->outputs;
771}
772
773EAPI int
774ecore_drm2_output_dpms_get(Ecore_Drm2_Output *output)
775{
776 drmModeObjectProperties *props;
777 drmModePropertyRes *prop;
778 int val = -1;
779 unsigned int i;
780
781 EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1);
782
783 props =
784 drmModeObjectGetProperties(output->fd, output->conn_id,
785 DRM_MODE_OBJECT_CONNECTOR);
786 if (!props) return -1;
787
788 for (i = 0; i < props->count_props; i++)
789 {
790 prop = drmModeGetProperty(output->fd, props->props[i]);
791 if (!prop) continue;
792
793 if (!strcmp(prop->name, "DPMS"))
794 val = props->prop_values[i];
795
796 drmModeFreeProperty(prop);
797 }
798
799 drmModeFreeObjectProperties(props);
800
801 return val;
802}
803
804EAPI void
805ecore_drm2_output_dpms_set(Ecore_Drm2_Output *output, int level)
806{
807 EINA_SAFETY_ON_NULL_RETURN(output);
808 EINA_SAFETY_ON_TRUE_RETURN(!output->enabled);
809
810 drmModeConnectorSetProperty(output->fd, output->conn_id,
811 output->dpms->prop_id, level);
812}
813
814EAPI char *
815ecore_drm2_output_edid_get(Ecore_Drm2_Output *output)
816{
817 char *edid_str = NULL;
818 unsigned char *blob;
819
820 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
821 EINA_SAFETY_ON_NULL_RETURN_VAL(output->edid.blob, NULL);
822
823 blob = output->edid.blob;
824
825 edid_str = malloc((128 * 2) + 1);
826 if (edid_str)
827 {
828 unsigned int k, kk;
829 const char *hexch = "0123456789abcdef";
830
831 for (kk = 0, k = 0; k < 128; k++)
832 {
833 edid_str[kk] = hexch[(blob[k] >> 4) & 0xf];
834 edid_str[kk + 1] = hexch[blob[k] & 0xf];
835 kk += 2;
836 }
837 edid_str[kk] = 0;
838 }
839
840 return edid_str;
841}
842
843EAPI Eina_Bool
844ecore_drm2_output_backlight_get(Ecore_Drm2_Output *output)
845{
846 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
847 return (output->backlight.path != NULL);
848}
849
850EAPI Ecore_Drm2_Output *
851ecore_drm2_output_find(Ecore_Drm2_Device *device, int x, int y)
852{
853 Eina_List *l;
854 Ecore_Drm2_Output *output;
855
856 EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL);
857
858 EINA_LIST_FOREACH(device->outputs, l, output)
859 {
860 int ox, oy, ow, oh;
861
862 if (!output->enabled) continue;
863
864 ox = output->x;
865 oy = output->y;
866 ow = output->current_mode->width;
867 oh = output->current_mode->height;
868
869 if (INSIDE(x, y, ox, oy, ow, oh))
870 return output;
871 }
872
873 return NULL;
874}
875
876EAPI void
877ecore_drm2_output_geometry_get(Ecore_Drm2_Output *output, int *x, int *y, int *w, int *h)
878{
879 EINA_SAFETY_ON_NULL_RETURN(output);
880 EINA_SAFETY_ON_TRUE_RETURN(!output->enabled);
881
882 if (x) *x = output->x;
883 if (y) *y = output->y;
884 if (w) *w = output->current_mode->width;
885 if (h) *h = output->current_mode->height;
886}
887
888EAPI unsigned int
889ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output)
890{
891 EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0);
892 return output->crtc_id;
893}
894
895EAPI Ecore_Drm2_Fb *
896ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output)
897{
898 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
899 return output->next;
900}
901
902EAPI void
903ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb)
904{
905 EINA_SAFETY_ON_NULL_RETURN(output);
906 output->next = fb;
907}
908
909EAPI Ecore_Drm2_Fb *
910ecore_drm2_output_current_fb_get(Ecore_Drm2_Output *output)
911{
912 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
913 return output->current;
914}
915
916EAPI void
917ecore_drm2_output_crtc_size_get(Ecore_Drm2_Output *output, int *w, int *h)
918{
919 drmModeCrtcPtr crtc;
920
921 if (w) *w = 0;
922 if (h) *h = 0;
923
924 EINA_SAFETY_ON_NULL_RETURN(output);
925
926 crtc = drmModeGetCrtc(output->fd, output->crtc_id);
927 if (!crtc) return;
928
929 if (w) *w = crtc->width;
930 if (h) *h = crtc->height;
931
932 drmModeFreeCrtc(crtc);
933}
934
935EAPI Eina_Bool
936ecore_drm2_output_primary_get(Ecore_Drm2_Output *output)
937{
938 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
939 return output->primary;
940}
941
942EAPI void
943ecore_drm2_output_primary_set(Ecore_Drm2_Output *output, Eina_Bool primary)
944{
945 EINA_SAFETY_ON_NULL_RETURN(output);
946 output->primary = primary;
947}
948
949EAPI Eina_Bool
950ecore_drm2_output_enabled_get(Ecore_Drm2_Output *output)
951{
952 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
953 return output->enabled;
954}
955
956EAPI void
957ecore_drm2_output_enabled_set(Ecore_Drm2_Output *output, Eina_Bool enabled)
958{
959 EINA_SAFETY_ON_NULL_RETURN(output);
960
961 if (output->enabled == enabled) return;
962 output->enabled = enabled;
963
964 if (output->enabled)
965 ecore_drm2_output_dpms_set(output, DRM_MODE_DPMS_ON);
966 else
967 ecore_drm2_output_dpms_set(output, DRM_MODE_DPMS_OFF);
968
969 _output_event_send(output);
970}
971
972EAPI void
973ecore_drm2_output_physical_size_get(Ecore_Drm2_Output *output, int *w, int *h)
974{
975 if (w) *w = 0;
976 if (h) *h = 0;
977
978 EINA_SAFETY_ON_NULL_RETURN(output);
979
980 if (w) *w = output->pw;
981 if (h) *h = output->ph;
982}
983
984EAPI const Eina_List *
985ecore_drm2_output_modes_get(Ecore_Drm2_Output *output)
986{
987 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
988 return output->modes;
989}
990
991EAPI void
992ecore_drm2_output_mode_info_get(Ecore_Drm2_Output_Mode *mode, int *w, int *h, unsigned int *refresh, unsigned int *flags)
993{
994 if (w) *w = 0;
995 if (h) *h = 0;
996 if (refresh) *refresh = 0;
997 if (flags) *flags = 0;
998
999 EINA_SAFETY_ON_NULL_RETURN(mode);
1000
1001 if (w) *w = mode->width;
1002 if (h) *h = mode->height;
1003 if (refresh) *refresh = mode->refresh;
1004 if (flags) *flags = mode->flags;
1005}
1006
1007EAPI Eina_Bool
1008ecore_drm2_output_mode_set(Ecore_Drm2_Output *output, Ecore_Drm2_Output_Mode *mode, int x, int y)
1009{
1010 Eina_Bool ret = EINA_TRUE;
1011 unsigned int buffer = 0;
1012
1013 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1014 EINA_SAFETY_ON_TRUE_RETURN_VAL((output->fd < 0), EINA_FALSE);
1015
1016 output->x = x;
1017 output->y = y;
1018 output->current_mode = mode;
1019
1020 if (mode)
1021 {
1022 if (output->current)
1023 buffer = output->current->id;
1024 else if (output->next)
1025 buffer = output->next->id;
1026 else
1027 buffer = output->ocrtc->buffer_id;
1028
1029 if (drmModeSetCrtc(output->fd, output->crtc_id, buffer,
1030 x, y, &output->conn_id, 1, &mode->info) < 0)
1031 {
1032 ERR("Failed to set Mode %dx%d for Output %s: %m",
1033 mode->width, mode->height, output->name);
1034 ret = EINA_FALSE;
1035 }
1036 }
1037 else
1038 {
1039 if (drmModeSetCrtc(output->fd, output->crtc_id, 0,
1040 0, 0, 0, 0, NULL) < 0)
1041 {
1042 ERR("Failed to turn off Output %s: %m", output->name);
1043 ret = EINA_FALSE;
1044 }
1045 }
1046
1047 return ret;
1048}
1049
1050EAPI char *
1051ecore_drm2_output_name_get(Ecore_Drm2_Output *output)
1052{
1053 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1054 EINA_SAFETY_ON_NULL_RETURN_VAL(output->name, NULL);
1055 return strdup(output->name);
1056}
1057
1058EAPI char *
1059ecore_drm2_output_model_get(Ecore_Drm2_Output *output)
1060{
1061 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1062 EINA_SAFETY_ON_NULL_RETURN_VAL(output->model, NULL);
1063 return strdup(output->model);
1064}
1065
1066EAPI Eina_Bool
1067ecore_drm2_output_connected_get(Ecore_Drm2_Output *output)
1068{
1069 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1070 return output->connected;
1071}
1072
1073EAPI Eina_Bool
1074ecore_drm2_output_cloned_get(Ecore_Drm2_Output *output)
1075{
1076 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1077 return output->cloned;
1078}
1079
1080EAPI unsigned int
1081ecore_drm2_output_connector_type_get(Ecore_Drm2_Output *output)
1082{
1083 EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0);
1084 return output->conn_type;
1085}
1086
1087EAPI void
1088ecore_drm2_output_resolution_get(Ecore_Drm2_Output *output, int *w, int *h, unsigned int *refresh)
1089{
1090 if (w) *w = 0;
1091 if (h) *h = 0;
1092 if (refresh) *refresh = 0;
1093
1094 EINA_SAFETY_ON_NULL_RETURN(output);
1095 EINA_SAFETY_ON_TRUE_RETURN(!output->current_mode);
1096
1097 if (w) *w = output->current_mode->width;
1098 if (h) *h = output->current_mode->height;
1099 if (refresh) *refresh = output->current_mode->refresh;
1100}
1101
1102EAPI Eina_Bool
1103ecore_drm2_output_possible_crtc_get(Ecore_Drm2_Output *output, unsigned int crtc)
1104{
1105 drmModeRes *res;
1106 drmModeConnector *conn;
1107 drmModeEncoder *enc;
1108 int i = 0, j = 0, k = 0;
1109 unsigned int p = 0;
1110 Eina_Bool ret = EINA_FALSE;
1111
1112 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1113 EINA_SAFETY_ON_TRUE_RETURN_VAL((output->fd < 0), EINA_FALSE);
1114
1115 res = drmModeGetResources(output->fd);
1116 if (!res) return EINA_FALSE;
1117
1118 for (; i < res->count_connectors; i++)
1119 {
1120 conn = drmModeGetConnector(output->fd, res->connectors[i]);
1121 if (!conn) continue;
1122
1123 for (j = 0; j < conn->count_encoders; j++)
1124 {
1125 enc = drmModeGetEncoder(output->fd, conn->encoders[j]);
1126 if (!enc) continue;
1127
1128 if (enc->crtc_id != crtc) goto next;
1129
1130 p = enc->possible_crtcs;
1131
1132 for (k = 0; k < res->count_crtcs; k++)
1133 {
1134 if (res->crtcs[k] != output->crtc_id) continue;
1135
1136 if (p & (1 << k))
1137 {
1138 ret = EINA_TRUE;
1139 break;
1140 }
1141 }
1142
1143next:
1144 drmModeFreeEncoder(enc);
1145 if (ret) break;
1146 }
1147
1148 drmModeFreeConnector(conn);
1149 if (ret) break;
1150 }
1151
1152 drmModeFreeResources(res);
1153
1154 return ret;
1155}
diff --git a/src/lib/ecore_drm2/ecore_drm2_private.h b/src/lib/ecore_drm2/ecore_drm2_private.h
new file mode 100644
index 0000000000..23c9c77016
--- /dev/null
+++ b/src/lib/ecore_drm2/ecore_drm2_private.h
@@ -0,0 +1,185 @@
1#ifndef _ECORE_DRM2_PRIVATE_H
2# define _ECORE_DRM2_PRIVATE_H
3
4# ifdef HAVE_CONFIG_H
5# include "config.h"
6# endif
7
8# include "Ecore.h"
9# include "ecore_private.h"
10# include "Eeze.h"
11# include "Elput.h"
12# include <Ecore_Drm2.h>
13
14# include <unistd.h>
15# include <strings.h>
16# include <sys/mman.h>
17# include <fcntl.h>
18# include <ctype.h>
19
20# include <sys/ioctl.h>
21# include <xf86drm.h>
22# include <xf86drmMode.h>
23# include <drm_mode.h>
24# include <drm_fourcc.h>
25
26extern int _ecore_drm2_log_dom;
27
28# ifdef ECORE_DRM2_DEFAULT_LOG_COLOR
29# undef ECORE_DRM2_DEFAULT_LOG_COLOR
30# endif
31# define ECORE_DRM2_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
32
33# ifdef ERR
34# undef ERR
35# endif
36# define ERR(...) EINA_LOG_DOM_ERR(_ecore_drm2_log_dom, __VA_ARGS__)
37
38# ifdef DBG
39# undef DBG
40# endif
41# define DBG(...) EINA_LOG_DOM_DBG(_ecore_drm2_log_dom, __VA_ARGS__)
42
43# ifdef INF
44# undef INF
45# endif
46# define INF(...) EINA_LOG_DOM_INFO(_ecore_drm2_log_dom, __VA_ARGS__)
47
48# ifdef WRN
49# undef WRN
50# endif
51# define WRN(...) EINA_LOG_DOM_WARN(_ecore_drm2_log_dom, __VA_ARGS__)
52
53# ifdef CRIT
54# undef CRIT
55# endif
56# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm2_log_dom, __VA_ARGS__)
57
58typedef enum _Ecore_Drm2_Backlight_Type
59{
60 ECORE_DRM2_BACKLIGHT_RAW,
61 ECORE_DRM2_BACKLIGHT_PLATFORM,
62 ECORE_DRM2_BACKLIGHT_FIRMWARE
63} Ecore_Drm2_Backlight_Type;
64
65typedef enum _Ecore_Drm2_Transform
66{
67 ECORE_DRM2_TRANSFORM_NORMAL,
68 ECORE_DRM2_TRANSFORM_90,
69 ECORE_DRM2_TRANSFORM_180,
70 ECORE_DRM2_TRANSFORM_270,
71 ECORE_DRM2_TRANSFORM_FLIPPED,
72 ECORE_DRM2_TRANSFORM_FLIPPED_90,
73 ECORE_DRM2_TRANSFORM_FLIPPED_180,
74 ECORE_DRM2_TRANSFORM_FLIPPED_270
75} Ecore_Drm2_Transform;
76
77typedef enum _Ecore_Drm2_Rotation
78{
79 ECORE_DRM2_ROTATION_NORMAL = 1,
80 ECORE_DRM2_ROTATION_90 = 2,
81 ECORE_DRM2_ROTATION_180 = 4,
82 ECORE_DRM2_ROTATION_270 = 8,
83 ECORE_DRM2_ROTATION_REFLECT_X = 16,
84 ECORE_DRM2_ROTATION_REFLECT_Y = 32
85} Ecore_Drm2_Rotation;
86
87struct _Ecore_Drm2_Fb
88{
89 int fd;
90 int w, h;
91 int depth, bpp;
92 uint32_t id, hdl;
93 uint32_t stride, size;
94 uint32_t format;
95
96 Eina_Bool gbm : 1;
97
98 void *mmap;
99};
100
101struct _Ecore_Drm2_Output_Mode
102{
103 uint32_t flags;
104 int32_t width, height;
105 uint32_t refresh;
106 drmModeModeInfo info;
107};
108
109struct _Ecore_Drm2_Output
110{
111 Eina_Stringshare *name;
112 Eina_Stringshare *make, *model, *serial;
113
114 int fd;
115 int pipe;
116 int x, y, w, h, pw, ph;
117
118 uint32_t subpixel;
119 uint32_t crtc_id, conn_id, conn_type;
120 uint32_t scale;
121
122 struct
123 {
124 char eisa[13];
125 char monitor[13];
126 char pnp[5];
127 char serial[13];
128 unsigned char *blob; // unused when doing atomic
129 } edid;
130
131 struct
132 {
133 const char *path;
134 int value, max;
135 Ecore_Drm2_Backlight_Type type;
136 } backlight;
137
138 drmModeCrtcPtr ocrtc;
139
140 Ecore_Drm2_Fb *current, *next;
141
142 Eina_Matrix4 matrix, inverse;
143 Ecore_Drm2_Transform transform;
144
145 /* unused when doing atomic */
146 drmModePropertyPtr dpms;
147
148 Ecore_Drm2_Output_Mode *current_mode;
149 Eina_List *modes;
150
151 Eina_List *planes;
152
153 Eina_Bool connected : 1;
154 Eina_Bool primary : 1;
155 Eina_Bool cloned : 1;
156 Eina_Bool enabled : 1;
157};
158
159struct _Ecore_Drm2_Device
160{
161 Elput_Manager *em;
162
163 int fd;
164 const char *path;
165
166 int num_crtcs;
167 uint32_t *crtcs;
168
169 struct
170 {
171 uint32_t crtc, conn;
172 } alloc;
173
174 struct
175 {
176 uint32_t width, height;
177 } min, max;
178
179 Eeze_Udev_Watch *watch;
180 Ecore_Event_Handler *active_hdlr;
181
182 Eina_List *outputs;
183};
184
185#endif
diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h
index 162915a1ce..4ba5917efc 100644
--- a/src/lib/elementary/elm_priv.h
+++ b/src/lib/elementary/elm_priv.h
@@ -10,7 +10,7 @@
10#include <Ecore_Wl2.h> 10#include <Ecore_Wl2.h>
11#endif 11#endif
12#ifdef HAVE_ELEMENTARY_DRM 12#ifdef HAVE_ELEMENTARY_DRM
13#include <Ecore_Drm.h> 13#include <Ecore_Drm2.h>
14#endif 14#endif
15#ifdef HAVE_ELEMENTARY_COCOA 15#ifdef HAVE_ELEMENTARY_COCOA
16/* Ecore_Cocoa is still in Beta. In Elementary, we know what we are 16/* Ecore_Cocoa is still in Beta. In Elementary, we know what we are
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 8b5e4047cc..e14254b381 100644
--- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
+++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
@@ -2,8 +2,6 @@
2# include <config.h> 2# include <config.h>
3#endif 3#endif
4 4
5#include <stdlib.h>
6#include <string.h>
7#include <Eina.h> 5#include <Eina.h>
8#include <Ecore.h> 6#include <Ecore.h>
9#include "ecore_private.h" 7#include "ecore_private.h"
@@ -12,12 +10,12 @@
12#include <Ecore_Evas.h> 10#include <Ecore_Evas.h>
13#include "ecore_evas_private.h" 11#include "ecore_evas_private.h"
14#include "ecore_evas_drm.h" 12#include "ecore_evas_drm.h"
15#include <Ecore_Drm.h> 13#include <Ecore_Drm2.h>
16#include <Evas_Engine_Drm.h> 14#include <Evas_Engine_Drm.h>
15#include <drm_fourcc.h>
17 16
18#ifdef BUILD_ECORE_EVAS_GL_DRM 17#ifdef BUILD_ECORE_EVAS_GL_DRM
19# include <Evas_Engine_GL_Drm.h> 18# include <Evas_Engine_GL_Drm.h>
20# include <gbm.h>
21# include <dlfcn.h> 19# include <dlfcn.h>
22#endif 20#endif
23 21
@@ -43,662 +41,252 @@
43# endif 41# endif
44#endif /* ! _WIN32 */ 42#endif /* ! _WIN32 */
45 43
46typedef struct _Ecore_Evas_Engine_Drm_Data Ecore_Evas_Engine_Drm_Data; 44typedef struct _Ecore_Evas_Engine_Drm_Data
47
48struct _Ecore_Evas_Engine_Drm_Data
49{
50 int w, h;
51};
52
53/* local function prototypes */
54static int _ecore_evas_drm_init(const char *device);
55static int _ecore_evas_drm_shutdown(void);
56static Ecore_Evas_Interface_Drm *_ecore_evas_drm_interface_new(void);
57static void _ecore_evas_drm_free(Ecore_Evas *ee);
58static void _ecore_evas_drm_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
59static void _ecore_evas_drm_callback_move_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
60static void _ecore_evas_drm_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
61static void _ecore_evas_drm_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
62static void _ecore_evas_drm_callback_mouse_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
63static void _ecore_evas_drm_callback_mouse_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
64static void _ecore_evas_drm_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
65static void _ecore_evas_drm_move(Ecore_Evas *ee, int x, int y);
66static void _ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h);
67static void _ecore_evas_drm_move_resize(Ecore_Evas *ee, int x, int y, int w, int h);
68static void _ecore_evas_drm_rotation_set(Ecore_Evas *ee, int rotation, int resize);
69static void _ecore_evas_drm_show(Ecore_Evas *ee);
70static void _ecore_evas_drm_hide(Ecore_Evas *ee);
71static void _ecore_evas_drm_title_set(Ecore_Evas *ee, const char *title);
72static void _ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c);
73static void _ecore_evas_drm_size_min_set(Ecore_Evas *ee, int w, int h);
74static void _ecore_evas_drm_size_max_set(Ecore_Evas *ee, int w, int h);
75static void _ecore_evas_drm_size_base_set(Ecore_Evas *ee, int w, int h);
76static void _ecore_evas_drm_size_step_set(Ecore_Evas *ee, int w, int h);
77static void _ecore_evas_drm_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y);
78static void _ecore_evas_drm_object_cursor_unset(Ecore_Evas *ee);
79static void _ecore_evas_drm_layer_set(Ecore_Evas *ee, int layer);
80static void _ecore_evas_drm_iconified_set(Ecore_Evas *ee, Eina_Bool on);
81static void _ecore_evas_drm_borderless_set(Ecore_Evas *ee, Eina_Bool on);
82static void _ecore_evas_drm_maximized_set(Ecore_Evas *ee, Eina_Bool on);
83static void _ecore_evas_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on);
84static void _ecore_evas_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on);
85static void _ecore_evas_drm_ignore_events_set(Ecore_Evas *ee, int ignore);
86static void _ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha);
87static void _ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent);
88static void _ecore_evas_drm_aspect_set(Ecore_Evas *ee, double aspect);
89
90static int _ecore_evas_drm_render(Ecore_Evas *ee);
91static void _ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event);
92static int _ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates);
93
94static void _ecore_evas_drm_screen_geometry_get(const Ecore_Evas *ee EINA_UNUSED, int *x, int *y, int *w, int *h);
95static void _ecore_evas_drm_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y);
96Eina_Bool _ecore_evas_drm_pointer_warp(const Ecore_Evas *ee EINA_UNUSED, Evas_Coord x, Evas_Coord y);
97
98/* local variables */
99static int _ecore_evas_init_count = 0;
100static Ecore_Drm_Device *dev = NULL;
101
102static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func =
103{ 45{
104 _ecore_evas_drm_free, 46 int fd;
105 _ecore_evas_drm_callback_resize_set, 47 int cw, ch;
106 _ecore_evas_drm_callback_move_set, 48 int clockid;
107 NULL, //void (*fn_callback_show_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); 49 int x, y, w, h;
108 NULL, //void (*fn_callback_hide_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); 50 int depth, bpp;
109 _ecore_evas_drm_delete_request_set, 51 unsigned int format;
110 NULL, //void (*fn_callback_destroy_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); 52 Ecore_Drm2_Device *dev;
111 _ecore_evas_drm_callback_focus_in_set, 53 Ecore_Drm2_Output *output;
112 _ecore_evas_drm_callback_focus_out_set, 54} Ecore_Evas_Engine_Drm_Data;
113 _ecore_evas_drm_callback_mouse_in_set,
114 _ecore_evas_drm_callback_mouse_out_set,
115 NULL, //void (*fn_callback_sticky_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
116 NULL, //void (*fn_callback_unsticky_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
117 NULL, //void (*fn_callback_pre_render_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
118 NULL, //void (*fn_callback_post_render_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
119 _ecore_evas_drm_move,
120 NULL, //void (*fn_managed_move) (Ecore_Evas *ee, int x, int y);
121 _ecore_evas_drm_resize,
122 _ecore_evas_drm_move_resize,
123 _ecore_evas_drm_rotation_set,
124 NULL, //void (*fn_shaped_set) (Ecore_Evas *ee, int shaped);
125 _ecore_evas_drm_show,
126 _ecore_evas_drm_hide,
127 NULL, //void (*fn_raise) (Ecore_Evas *ee);
128 NULL, //void (*fn_lower) (Ecore_Evas *ee);
129 NULL, //void (*fn_activate) (Ecore_Evas *ee);
130 _ecore_evas_drm_title_set,
131 _ecore_evas_drm_name_class_set,
132 _ecore_evas_drm_size_min_set,
133 _ecore_evas_drm_size_max_set,
134 _ecore_evas_drm_size_base_set,
135 _ecore_evas_drm_size_step_set,
136 _ecore_evas_drm_object_cursor_set,
137 _ecore_evas_drm_object_cursor_unset,
138 _ecore_evas_drm_layer_set,
139 NULL, //void (*fn_focus_set) (Ecore_Evas *ee, Eina_Bool on);
140 _ecore_evas_drm_iconified_set,
141 _ecore_evas_drm_borderless_set,
142 NULL, //void (*fn_override_set) (Ecore_Evas *ee, Eina_Bool on);
143 _ecore_evas_drm_maximized_set,
144 _ecore_evas_drm_fullscreen_set,
145 NULL, //void (*fn_avoid_damage_set) (Ecore_Evas *ee, int on);
146 _ecore_evas_drm_withdrawn_set,
147 NULL, //void (*fn_sticky_set) (Ecore_Evas *ee, Eina_Bool on);
148 _ecore_evas_drm_ignore_events_set,
149 _ecore_evas_drm_alpha_set,
150 _ecore_evas_drm_transparent_set,
151 NULL, //void (*fn_profiles_set) (Ecore_Evas *ee, const char **profiles, int count);
152 NULL, //void (*fn_profile_set) (Ecore_Evas *ee, const char *profile);
153 55
154 NULL, //void (*fn_window_group_set) (Ecore_Evas *ee, const Ecore_Evas *ee_group); 56static int _drm_init_count = 0;
155 _ecore_evas_drm_aspect_set,
156 NULL, //void (*fn_urgent_set) (Ecore_Evas *ee, Eina_Bool on);
157 NULL, //void (*fn_modal_set) (Ecore_Evas *ee, Eina_Bool on);
158 NULL, //void (*fn_demands_attention_set) (Ecore_Evas *ee, Eina_Bool on);
159 NULL, //void (*fn_focus_skip_set) (Ecore_Evas *ee, Eina_Bool on);
160
161 _ecore_evas_drm_render,
162
163 _ecore_evas_drm_screen_geometry_get,
164 NULL, //void (*fn_screen_dpi_get) (const Ecore_Evas *ee, int *xdpi, int *ydpi);
165 NULL, //void (*fn_msg_parent_send) (Ecore_Evas *ee, int maj, int min, void *data, int size);
166 NULL, //void (*fn_msg_send) (Ecore_Evas *ee, int maj, int min, void *data, int size);
167
168 _ecore_evas_drm_pointer_xy_get,
169 _ecore_evas_drm_pointer_warp,
170
171 NULL, // wm_rot_preferred_rotation_set
172 NULL, // wm_rot_available_rotations_set
173 NULL, // wm_rot_manual_rotation_done_set
174 NULL, // wm_rot_manual_rotation_done
175
176 NULL, // aux_hints_set
177 57
178 NULL, // fn_animator_register 58static int
179 NULL // fn_animator_unregister 59_ecore_evas_drm_init(Ecore_Evas_Engine_Drm_Data *edata, const char *device)
180};
181
182EAPI Ecore_Evas *
183ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h)
184{ 60{
185 Ecore_Evas *ee; 61 if (++_drm_init_count != 1) return _drm_init_count;
186 Evas_Engine_Info_Drm *einfo;
187 Ecore_Evas_Interface_Drm *iface;
188 Ecore_Evas_Engine_Drm_Data *edata;
189 int method;
190 62
191 /* try to find the evas drm engine */ 63 if (!ecore_drm2_init())
192 if (!(method = evas_render_method_lookup("drm")))
193 { 64 {
194 ERR("Render method lookup failed for Drm"); 65 ERR("Failed to init Ecore_Drm2 library");
195 return NULL; 66 goto init_err;
196 } 67 }
197 68
198 /* try to init drm */ 69 if (!device) device = "seat0";
199 if (_ecore_evas_drm_init(device) < 1) return NULL;
200 70
201 if (!ecore_drm_device_software_setup(dev)) 71 edata->dev = ecore_drm2_device_find(device, 0);
72 if (!edata->dev)
202 { 73 {
203 ERR("Could not setup device for software"); 74 ERR("Failed to create device");
204 goto soft_err; 75 goto dev_err;
205 } 76 }
206 77
207 /* try to allocate space for new ecore_evas */ 78 edata->fd = ecore_drm2_device_open(edata->dev);
208 if (!(ee = calloc(1, sizeof(Ecore_Evas)))) 79 if (edata->fd < 0)
209 { 80 {
210 ERR("Failed to allocate space for new Ecore_Evas"); 81 ERR("Failed to open device");
211 goto ee_err; 82 goto open_err;
212 } 83 }
213 84
214 if (!(edata = calloc(1, sizeof(Ecore_Evas_Engine_Drm_Data)))) 85 edata->clockid = ecore_drm2_device_clock_id_get(edata->dev);
215 { 86 ecore_drm2_device_cursor_size_get(edata->dev, &edata->cw, &edata->ch);
216 ERR("Failed to allocate space for new Ecore_Evas_Engine_Data");
217 free(ee);
218 goto ee_err;
219 }
220
221 ee->engine.data = edata;
222
223 ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
224
225 ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func;
226 87
227 iface = _ecore_evas_drm_interface_new(); 88 if (!ecore_drm2_outputs_create(edata->dev))
228 ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
229
230 /* set some engine properties */
231 ee->driver = "drm";
232 if (device) ee->name = strdup(device);
233 else
234 ee->name = strdup(ecore_drm_device_name_get(dev));
235
236 if (w < 1) w = 1;
237 if (h < 1) h = 1;
238
239 ee->x = ee->req.x = x;
240 ee->y = ee->req.y = y;
241 ee->w = ee->req.w = w;
242 ee->h = ee->req.h = h;
243
244 ee->prop.max.w = 32767;
245 ee->prop.max.h = 32767;
246 ee->prop.layer = 4;
247 ee->prop.request_pos = 0;
248 ee->prop.sticky = 0;
249 ee->prop.withdrawn = EINA_TRUE;
250 ee->alpha = EINA_FALSE;
251
252 ee->can_async_render = 1;
253 if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER"))
254 ee->can_async_render = 0;
255
256 /* try to initialize evas */
257 ee->evas = evas_new();
258 evas_data_attach_set(ee->evas, ee);
259 evas_output_method_set(ee->evas, method);
260
261 if ((ee->rotation == 90) || (ee->rotation == 270))
262 { 89 {
263 evas_output_size_set(ee->evas, h, w); 90 ERR("Could not create outputs");
264 evas_output_viewport_set(ee->evas, 0, 0, h, w); 91 goto output_err;
265 }
266 else
267 {
268 evas_output_size_set(ee->evas, w, h);
269 evas_output_viewport_set(ee->evas, 0, 0, w, h);
270 }
271
272 if (ee->can_async_render)
273 evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
274 _ecore_evas_drm_render_updates, ee);
275
276 if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas)))
277 {
278 Ecore_Drm_Output *output;
279 char *num;
280
281 einfo->info.depth = 32; // FIXME
282 einfo->info.destination_alpha = ee->alpha;
283 einfo->info.rotation = ee->rotation;
284
285 if ((num = getenv("EVAS_DRM_VSYNC")))
286 {
287 if (!atoi(num))
288 einfo->info.vsync = EINA_FALSE;
289 else
290 einfo->info.vsync = EINA_TRUE;
291 }
292 else
293 einfo->info.vsync = EINA_TRUE;
294
295 einfo->info.use_hw_accel = EINA_FALSE;
296 einfo->info.dev = dev;
297
298 if ((output = ecore_drm_device_output_find(dev, x, y)))
299 {
300 einfo->info.conn_id = ecore_drm_output_connector_id_get(output);
301 einfo->info.crtc_id = ecore_drm_output_crtc_id_get(output);
302 einfo->info.buffer_id = ecore_drm_output_crtc_buffer_get(output);
303 }
304
305 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
306 {
307 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
308 goto eng_err;
309 }
310 }
311 else
312 {
313 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
314 goto eng_err;
315 } 92 }
316 93
317 ee->prop.window = einfo->info.buffer_id; 94 edata->output = ecore_drm2_output_find(edata->dev, edata->x, edata->y);
318 95 if (!edata->output)
319 _ecore_evas_register(ee); 96 WRN("Could not find output at %d %d", edata->x, edata->y);
320 ecore_evas_input_event_register(ee);
321
322 ecore_drm_device_window_set(dev, ee->prop.window);
323 ecore_event_window_register(ee->prop.window, ee, ee->evas,
324 (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
325 (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
326 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
327 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
328
329 /* NB: Send a fake mouse move event so that E-Wl gets an updated
330 * pointer position, else we end up with buggers (ref: T2854) */
331 {
332 Ecore_Event_Mouse_Move *ev;
333 97
334 ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)); 98 ecore_event_evas_init();
335 ev->window = ee->prop.window;
336 ev->event_window = ee->prop.window;
337 ev->root_window = ee->prop.window;
338 ev->same_screen = 1;
339 99
340 ecore_drm_device_pointer_xy_get(dev, &ev->x, &ev->y); 100 return _drm_init_count;
341 101
342 ev->root.x = ev->x; 102output_err:
343 ev->root.y = ev->y; 103 ecore_drm2_device_close(edata->dev);
104open_err:
105 ecore_drm2_device_free(edata->dev);
106dev_err:
107 ecore_drm2_shutdown();
108init_err:
109 return --_drm_init_count;
110}
344 111
345 ecore_event_evas_mouse_move(NULL, ECORE_EVENT_MOUSE_MOVE, ev); 112static int
346 } 113_ecore_evas_drm_shutdown(Ecore_Evas_Engine_Drm_Data *edata)
114{
115 if (--_drm_init_count != 0) return _drm_init_count;
347 116
348 return ee; 117 ecore_drm2_outputs_destroy(edata->dev);
118 ecore_drm2_device_close(edata->dev);
119 ecore_drm2_device_free(edata->dev);
120 ecore_drm2_shutdown();
121 ecore_event_evas_shutdown();
349 122
350eng_err: 123 return _drm_init_count;
351 ecore_evas_free(ee);
352soft_err:
353ee_err:
354 _ecore_evas_drm_shutdown();
355 return NULL;
356} 124}
357 125
358#ifdef BUILD_ECORE_EVAS_GL_DRM 126static void
359EAPI Ecore_Evas * 127_drm_free(Ecore_Evas *ee)
360ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h)
361{ 128{
362 Ecore_Evas *ee;
363 Evas_Engine_Info_GL_Drm *einfo;
364 Ecore_Evas_Interface_Drm *iface;
365 Ecore_Evas_Engine_Drm_Data *edata; 129 Ecore_Evas_Engine_Drm_Data *edata;
366 int method;
367 uint32_t format = GBM_FORMAT_XRGB8888;
368 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
369 char *num;
370
371 /* try to find the evas drm engine */
372 if (!(method = evas_render_method_lookup("gl_drm")))
373 {
374 ERR("Render method lookup failed for GL Drm");
375 return NULL;
376 }
377
378 /* try to init drm */
379 if (_ecore_evas_drm_init(device) < 1) return NULL;
380
381 /* try to load gl libary, gbm libary */
382 /* Typically, gbm loads the dri driver However some versions of Mesa
383 * do not have libglapi symbols linked in the driver. Because of this,
384 * using hardware accel for our drm code Could fail with a
385 * message that the driver could not load. Let's be proactive and
386 * work around this for the user by preloading the glapi library */
387 dlopen("libglapi.so.0", (RTLD_LAZY | RTLD_GLOBAL));
388 if (dlerror())
389 {
390 _ecore_evas_drm_shutdown();
391 return NULL;
392 }
393
394 /* try to allocate space for new ecore_evas */
395 if (!(ee = calloc(1, sizeof(Ecore_Evas))))
396 {
397 ERR("Failed to allocate space for new Ecore_Evas");
398 goto ee_err;
399 }
400
401 if (!(edata = calloc(1, sizeof(Ecore_Evas_Engine_Drm_Data))))
402 {
403 ERR("Failed to allocate space for new Ecore_Evas_Engine_Data");
404 free(ee);
405 goto ee_err;
406 }
407 130
408 ee->engine.data = edata; 131 ecore_evas_input_event_unregister(ee);
409
410 ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
411
412 ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func;
413
414 iface = _ecore_evas_drm_interface_new();
415 ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface);
416
417 /* set some engine properties */
418 ee->driver = "gl_drm";
419 if (device) ee->name = strdup(device);
420 else
421 ee->name = strdup(ecore_drm_device_name_get(dev));
422
423 if (w < 1) w = 1;
424 if (h < 1) h = 1;
425
426 ee->x = ee->req.x = x;
427 ee->y = ee->req.y = y;
428 ee->w = ee->req.w = w;
429 ee->h = ee->req.h = h;
430
431 ee->prop.max.w = 32767;
432 ee->prop.max.h = 32767;
433 ee->prop.layer = 4;
434 ee->prop.request_pos = 0;
435 ee->prop.sticky = 0;
436 ee->prop.withdrawn = EINA_TRUE;
437 ee->alpha = EINA_FALSE;
438 132
439 /* NB: Disable async rendering for egl. Not Applicable as EGL is sync only */ 133 edata = ee->engine.data;
440 ee->can_async_render = 0; 134 _ecore_evas_drm_shutdown(edata);
441 /* if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER")) */ 135 free(edata);
442 /* ee->can_async_render = 0; */ 136}
443 137
444 /* try to initialize evas */ 138static int
445 ee->evas = evas_new(); 139_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates)
446 evas_data_attach_set(ee->evas, ee); 140{
447 evas_output_method_set(ee->evas, method); 141 int rend = 0;
448 142
449 if ((ee->rotation == 90) || (ee->rotation == 270)) 143 if ((ee->visible) && (updates))
450 { 144 {
451 evas_output_size_set(ee->evas, h, w); 145 _ecore_evas_idle_timeout_update(ee);
452 evas_output_viewport_set(ee->evas, 0, 0, h, w); 146 rend = 1;
453 } 147 }
454 else 148 else
455 { 149 evas_norender(ee->evas);
456 evas_output_size_set(ee->evas, w, h);
457 evas_output_viewport_set(ee->evas, 0, 0, w, h);
458 }
459
460 if (ee->can_async_render)
461 evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST,
462 _ecore_evas_drm_render_updates, ee);
463
464 if ((einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(ee->evas)))
465 {
466 Ecore_Drm_Output *output;
467
468 einfo->info.depth = 32;
469 einfo->info.destination_alpha = ee->alpha;
470 einfo->info.rotation = ee->rotation;
471
472 if ((num = getenv("EVAS_DRM_VSYNC")))
473 {
474 if (!atoi(num))
475 einfo->info.vsync = EINA_FALSE;
476 else
477 einfo->info.vsync = EINA_TRUE;
478 }
479 else
480 einfo->info.vsync = EINA_TRUE;
481
482 einfo->info.dev = dev;
483 einfo->info.format = format;
484 einfo->info.flags = flags;
485
486 if ((output = ecore_drm_device_output_find(dev, x, y)))
487 {
488 einfo->info.conn_id = ecore_drm_output_connector_id_get(output);
489 einfo->info.crtc_id = ecore_drm_output_crtc_id_get(output);
490 einfo->info.buffer_id = ecore_drm_output_crtc_buffer_get(output);
491 }
492 150
493 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) 151 if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
494 {
495 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
496 goto eng_err;
497 }
498 }
499 else
500 {
501 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
502 goto eng_err;
503 }
504 152
505 ee->prop.window = einfo->info.buffer_id; 153 return rend;
154}
506 155
507 _ecore_evas_register(ee); 156static void
508 ecore_evas_input_event_register(ee); 157_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event)
158{
159 Evas_Event_Render_Post *ev;
160 Ecore_Evas *ee;
509 161
510 ecore_drm_device_window_set(dev, ee->prop.window); 162 ev = event;
511 ecore_event_window_register(ee->prop.window, ee, ee->evas, 163 if (!ev) return;
512 (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
513 (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
514 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
515 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
516 164
517 return ee; 165 ee = data;
166 if (!ee) return;
518 167
519eng_err: 168 ee->in_async_render = EINA_FALSE;
520 ecore_evas_free(ee); 169 _drm_render_updates_process(ee, ev->updated_area);
521ee_err:
522 _ecore_evas_drm_shutdown();
523 return NULL;
524} 170}
525#endif
526 171
527/* local functions */
528static int 172static int
529_ecore_evas_drm_init(const char *device) 173_drm_render(Ecore_Evas *ee)
530{ 174{
531 if (++_ecore_evas_init_count != 1) return _ecore_evas_init_count; 175 int rend = 0;
176 Eina_List *l;
177 Ecore_Evas *ee2;
532 178
533 /* try to init ecore_drm */ 179 if (ee->in_async_render) return 0;
534 if (!ecore_drm_init())
535 {
536 ERR("Could not initialize Ecore_Drm");
537 return --_ecore_evas_init_count;
538 }
539 180
540 /* try to find the device */ 181 if (!ee->visible)
541 if (!(dev = ecore_drm_device_find(device, NULL)))
542 { 182 {
543 ERR("Could not find drm device with name: %s. Falling back to default device.", device); 183 evas_norender(ee->evas);
544 184 return 0;
545 /* if we already passed in NULL as device name, then no point in
546 * calling the find function below with no name either */
547 if (!device) goto dev_err;
548
549 /* try getting the default drm device */
550 if (!(dev = ecore_drm_device_find(NULL, NULL)))
551 goto dev_err;
552 } 185 }
553 186
554 if (!ecore_drm_launcher_connect(dev)) 187 EINA_LIST_FOREACH(ee->sub_ecore_evas, l, ee2)
555 { 188 {
556 ERR("Could not connect DRM launcher"); 189 if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
557 goto launcher_err; 190 if (ee2->engine.func->fn_render)
191 rend |= ee2->engine.func->fn_render(ee2);
192 if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
558 } 193 }
559 194
560 /* try to open the graphics card */ 195 if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
561 if (!ecore_drm_device_open(dev))
562 {
563 ERR("Could not open drm device");
564 goto dev_open_err;
565 }
566 196
567 /* try to create sprites */ 197 if (!ee->can_async_render)
568 if (!ecore_drm_sprites_create(dev))
569 { 198 {
570 ERR("Could not create sprites"); 199 Eina_List *updates;
571 goto sprite_err;
572 }
573 200
574 /* try to create outputs */ 201 updates = evas_render_updates(ee->evas);
575 if (!ecore_drm_outputs_create(dev))