From a0d3b955bfa18e807ef1067aa612a63d99bf7681 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 2 May 2016 10:21:00 -0400 Subject: [PATCH 01/35] ecore-drm2: Add start of Ecore_Drm2 library This new 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. @feature Signed-off-by: Chris Michael --- Makefile.am | 4 ++ configure.ac | 78 ++++++++++++++++++++----- m4/efl.m4 | 3 + pc/.gitignore | 1 + pc/ecore-drm2.pc.in | 12 ++++ src/Makefile.am | 3 +- src/Makefile_Ecore_Drm2.am | 25 ++++++++ src/Makefile_Ecore_Evas.am | 12 ++-- src/lib/ecore_drm2/Ecore_Drm2.h | 74 +++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2.c | 74 +++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_private.h | 58 ++++++++++++++++++ 11 files changed, 323 insertions(+), 21 deletions(-) create mode 100644 pc/ecore-drm2.pc.in create mode 100644 src/Makefile_Ecore_Drm2.am create mode 100644 src/lib/ecore_drm2/Ecore_Drm2.h create mode 100644 src/lib/ecore_drm2/ecore_drm2.c create mode 100644 src/lib/ecore_drm2/ecore_drm2_private.h 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 pkgconfig_DATA += pc/elput.pc endif +if HAVE_ECORE_DRM2 +pkgconfig_DATA += pc/ecore-drm2.pc +endif + # Cmake configs: efl_cmakeconfigdir = $(libdir)/cmake/Efl/ efl_cmakeconfig_DATA = \ diff --git a/configure.ac b/configure.ac index cae4e39594..0912ac2e29 100644 --- a/configure.ac +++ b/configure.ac @@ -2085,19 +2085,32 @@ if test "x${have_cocoa}" = "xyes"; then fi AC_SUBST(cocoa_coreservices_ldflags) +AC_ARG_ENABLE([elput], + [AS_HELP_STRING([--enable-elput],[enable elput library. @<:@default=disabled@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + want_elput="yes" + else + want_elput="no" + fi + ], + [want_elput="no"]) + # Drm AC_ARG_ENABLE([drm], [AS_HELP_STRING([--enable-drm],[enable drm engine. @<:@default=disabled@:>@])], [ if test "x${enableval}" = "xyes" ; then - want_drm="yes" + if test "x${want_elput}" != "xyes" ; then + AC_MSG_ERROR([elput is required to build drm support]) + fi + want_drm="yes" else want_drm="no" fi ], [want_drm="no"]) - AC_ARG_ENABLE([gl-drm], [AC_HELP_STRING([--enable-gl-drm], [enable gl drm engine. @<:@default=disabled@:>@])], @@ -2296,17 +2309,6 @@ AC_ARG_ENABLE([ecore-buffer], ], [want_ecore_buffer="no"]) -AC_ARG_ENABLE([elput], - [AS_HELP_STRING([--enable-elput],[enable elput library. @<:@default=disabled@:>@])], - [ - if test "x${enableval}" = "xyes" ; then - want_elput="yes" - else - want_elput="no" - fi - ], - [want_elput="no"]) - # Image Loaders ARG_ENABLE_EVAS_IMAGE_LOADER(BMP, static) @@ -3633,7 +3635,52 @@ EFL_EVAL_PKGS([ELPUT]) ### Checks for library functions EFL_LIB_END_OPTIONAL([Elput]) -#### End of Ecore_Drm +#### End of Elput + +#### Ecore_Drm2 +have_libinput_new="no" +EFL_LIB_START_OPTIONAL([Ecore_Drm2], [test "${want_drm}" = "yes"]) + +### Additional options to configure +SUID_CFLAGS=-fPIE +SUID_LDFLAGS=-pie +AC_SUBST([SUID_CFLAGS]) +AC_SUBST([SUID_LDFLAGS]) + +### Default values + +### Checks for programs + +### Checks for libraries +EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [eo]) +EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [efl]) +EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [eina]) +EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [ecore]) +EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [elput]) +EFL_INTERNAL_DEPEND_PKG([ECORE_DRM2], [eeze]) + +EFL_DEPEND_PKG([ECORE_DRM2], [DRM], [libdrm >= 2.4 gbm]) + +EFL_ADD_LIBS([ECORE_DRM2], [-lm]) + +AC_CHECK_LIB(drm, drmModeAtomicCommit, AC_DEFINE(HAVE_ATOMIC_DRM, [], [Atomic modeset supported])) + +EFL_EVAL_PKGS([ECORE_DRM2]) + +### Checks for header files + +### Checks for types + +### Checks for structures + +### Checks for compiler characteristics + +### Checks for linker characteristics + +### Checks for library functions + +EFL_LIB_END_OPTIONAL([Ecore_Drm2]) +#### End of Ecore_Drm2 #### Ecore_Audio @@ -5260,7 +5307,7 @@ EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${have_ps3}], [ecore_psl1ght]) EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_sdl}], [ecore_sdl]) EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_ecore_evas_gl_cocoa}], [ecore_cocoa]) EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${build_ecore_evas_win32}], [ecore_win32]) -EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_drm}], [ecore_drm]) +EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${want_drm}], [ecore_drm2]) EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ELEMENTARY], [${build_ecore_evas_wayland}], [ecore_wl2]) dnl Special case deps for ecore_drm @@ -5605,6 +5652,7 @@ pc/elua.pc pc/elementary.pc pc/elementary-cxx.pc pc/elput.pc +pc/ecore-drm2.pc dbus-services/org.enlightenment.Ethumb.service systemd-services/ethumb.service $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 ecore_win32) depname="ecore-win32" ;; + ecore_drm2) + depname="ecore-drm2" + ;; esac requirements_pc_[]m4_defn([DOWNEFL])="${depname} >= ${PACKAGE_VERSION} ${requirements_pc_[][]m4_defn([DOWNEFL])}" requirements_cflags_[]m4_defn([DOWNEFL])="-I\$(top_srcdir)/src/lib/${libdirname} -I\$(top_builddir)/src/lib/${libdirname} ${requirements_cflags_[][]m4_defn([DOWNEFL])}" diff --git a/pc/.gitignore b/pc/.gitignore index f66395b99d..893e9373c9 100644 --- a/pc/.gitignore +++ b/pc/.gitignore @@ -74,3 +74,4 @@ /efl-js.pc /elementary-cxx.pc /elput.pc +/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 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: ecore-drm2 +Description: E core library, DRM module +Requires.private: @requirements_pc_ecore_drm2@ +Version: @VERSION@ +Libs: -L${libdir} -lecore_drm2 +Libs.private: @requirements_libs_ecore_drm2@ +Cflags: -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 include Makefile_Ecore_IMF_Evas.am include Makefile_Eldbus.am include Makefile_Eeze.am +include Makefile_Elput.am include Makefile_Ecore_Drm.am +include Makefile_Ecore_Drm2.am include Makefile_Ecore_Evas.am include Makefile_Ecore_Audio.am include Makefile_Ecore_Avahi.am @@ -69,7 +71,6 @@ include Makefile_Ethumb.am include Makefile_Ethumb_Client.am include Makefile_Elocation.am include Makefile_Elementary.am -include Makefile_Elput.am include Makefile_Cxx.am include Makefile_Eolian_Cxx.am diff --git a/src/Makefile_Ecore_Drm2.am b/src/Makefile_Ecore_Drm2.am new file mode 100644 index 0000000000..2818b0e760 --- /dev/null +++ b/src/Makefile_Ecore_Drm2.am @@ -0,0 +1,25 @@ +if HAVE_ECORE_DRM2 + +### Library + +lib_LTLIBRARIES += lib/ecore_drm2/libecore_drm2.la + +installed_ecoredrm2mainheadersdir = $(includedir)/ecore-drm2-@VMAJ@ +dist_installed_ecoredrm2mainheaders_DATA = \ + lib/ecore_drm2/Ecore_Drm2.h + +lib_ecore_drm2_libecore_drm2_la_SOURCES = \ +lib/ecore_drm2/ecore_drm2.c \ +lib/ecore_drm2/ecore_drm2_private.h + +lib_ecore_drm2_libecore_drm2_la_CPPFLAGS = \ + -I$(top_builddir)/src/lib/efl \ + @ECORE_DRM2_CFLAGS@ @EFL_CFLAGS@ \ + -DPACKAGE_LIB_DIR=\"$(libdir)\" \ + -DMODULE_ARCH=\"$(MODULE_ARCH)\" + +lib_ecore_drm2_libecore_drm2_la_LIBADD = @ECORE_DRM2_LIBS@ +lib_ecore_drm2_libecore_drm2_la_DEPENDENCIES = @ECORE_DRM2_INTERNAL_LIBS@ +lib_ecore_drm2_libecore_drm2_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@ + +endif diff --git a/src/Makefile_Ecore_Evas.am b/src/Makefile_Ecore_Evas.am index 12efc0b135..25af963eb2 100644 --- a/src/Makefile_Ecore_Evas.am +++ b/src/Makefile_Ecore_Evas.am @@ -271,11 +271,13 @@ modules_ecore_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/ef @ECORE_EVAS_CFLAGS@ \ @ECORE_DRM_CFLAGS@ \ -I$(top_srcdir)/src/modules/evas/engines/drm \ --I$(top_srcdir)/src/modules/evas/engines/gl_drm \ -@ecore_evas_engines_gl_drm_cflags@ -modules_ecore_evas_engines_drm_module_la_LIBADD = @USE_ECORE_EVAS_LIBS@ \ -@ecore_evas_engines_gl_drm_libs@ -modules_ecore_evas_engines_drm_module_la_DEPENDENCIES = @USE_ECORE_EVAS_INTERNAL_LIBS@ +-I$(top_srcdir)/src/modules/evas/engines/gl_drm +modules_ecore_evas_engines_drm_module_la_LIBADD = \ +@USE_ECORE_EVAS_LIBS@ \ +@USE_ECORE_DRM2_LIBS@ +modules_ecore_evas_engines_drm_module_la_DEPENDENCIES = \ +@USE_ECORE_EVAS_INTERNAL_LIBS@ \ +@USE_ECORE_DRM2_INTERNAL_LIBS@ modules_ecore_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_ecore_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static endif diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h new file mode 100644 index 0000000000..b2bbd15e02 --- /dev/null +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -0,0 +1,74 @@ +#ifndef _ECORE_DRM2_H +# define _ECORE_DRM2_H + +# include +# include + +# ifdef EAPI +# undef EAPI +# endif + +# ifdef _MSC_VER +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else // ifdef BUILDING_DLL +# define EAPI __declspec(dllimport) +# endif // ifdef BUILDING_DLL +# else // ifdef _MSC_VER +# ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else // if __GNUC__ >= 4 +# define EAPI +# endif // if __GNUC__ >= 4 +# else // ifdef __GNUC__ +# define EAPI +# endif // ifdef __GNUC__ +# endif // ifdef _MSC_VER + +# ifdef EFL_BETA_API_SUPPORT + +/** + * @file + * @brief Ecore functions for dealing with drm, virtual terminals + * + * @defgroup Ecore_Drm2_Group Ecore_Drm2 - Drm Integration + * @ingroup Ecore + * + * Ecore_Drm2 provides a wrapper and functions for using libdrm + * + * @li @ref Ecore_Drm2_Init_Group + * @li @ref Ecore_Drm2_Device_Group + */ + +/** + * @defgroup Ecore_Drm2_Init_Group Drm library Init and Shutdown functions + * + * Functions that start and shutdown the Ecore_Drm2 library + */ + +/** + * Initialize the Ecore_Drm2 library + * + * @return The number of times the library has been initialized without + * being shut down. 0 is returned if an error occurs. + * + * @ingroup Ecore_Drm2_Init_Group + * @since 1.18 + */ +EAPI int ecore_drm2_init(void); + +/** + * Shutdown the Ecore_Drm2 library + * + * @return The number of times the library has been initialized without + * being shutdown. 0 is returned if an error occurs. + * + * @ingroup Ecore_Drm2_Init_Group + * @since 1.18 + */ +EAPI int ecore_drm2_shutdown(void); + +# endif + +#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..32b6781cc7 --- /dev/null +++ b/src/lib/ecore_drm2/ecore_drm2.c @@ -0,0 +1,74 @@ +#include "ecore_drm2_private.h" + +static int _ecore_drm2_init_count = 0; + +int _ecore_drm2_log_dom = -1; + +EAPI int +ecore_drm2_init(void) +{ + if (++_ecore_drm2_init_count != 1) return _ecore_drm2_init_count; + + if (!eina_init()) goto eina_err; + + if (!ecore_init()) + { + EINA_LOG_ERR("Could not initialize Ecore library"); + goto ecore_err; + } + + if (!eeze_init()) + { + EINA_LOG_ERR("Could not initialize Eeze library"); + goto eeze_err; + } + + if (!elput_init()) + { + EINA_LOG_ERR("Could not initialize Elput library"); + goto elput_err; + } + + _ecore_drm2_log_dom = + eina_log_domain_register("ecore_drm2", ECORE_DRM2_DEFAULT_LOG_COLOR); + if (!_ecore_drm2_log_dom) + { + EINA_LOG_ERR("Could not create logging domain for Ecore_Drm2"); + goto log_err; + } + + return _ecore_drm2_init_count; + +log_err: + elput_shutdown(); +elput_err: + eeze_shutdown(); +eeze_err: + ecore_shutdown(); +ecore_err: + eina_shutdown(); +eina_err: + return --_ecore_drm2_init_count; +} + +EAPI int +ecore_drm2_shutdown(void) +{ + if (_ecore_drm2_init_count < 1) + { + ERR("Ecore_Drm2 shutdown called without init"); + return 0; + } + + if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count; + + eina_log_domain_unregister(_ecore_drm2_log_dom); + _ecore_drm2_log_dom = -1; + + elput_shutdown(); + eeze_shutdown(); + ecore_shutdown(); + eina_shutdown(); + + return _ecore_drm2_init_count; +} 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..6177e8e436 --- /dev/null +++ b/src/lib/ecore_drm2/ecore_drm2_private.h @@ -0,0 +1,58 @@ +#ifndef _ECORE_DRM2_PRIVATE_H +# define _ECORE_DRM2_PRIVATE_H + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +# include "Ecore.h" +# include "ecore_private.h" +# include "Eeze.h" +# include "Elput.h" +# include + +# include +# include +# include +# include +# include + +# include +# include +# include +# include +# include + +extern int _ecore_drm2_log_dom; + +# ifdef ECORE_DRM2_DEFAULT_LOG_COLOR +# undef ECORE_DRM2_DEFAULT_LOG_COLOR +# endif +# define ECORE_DRM2_DEFAULT_LOG_COLOR EINA_COLOR_BLUE + +# ifdef ERR +# undef ERR +# endif +# define ERR(...) EINA_LOG_DOM_ERR(_ecore_drm2_log_dom, __VA_ARGS__) + +# ifdef DBG +# undef DBG +# endif +# define DBG(...) EINA_LOG_DOM_DBG(_ecore_drm2_log_dom, __VA_ARGS__) + +# ifdef INF +# undef INF +# endif +# define INF(...) EINA_LOG_DOM_INFO(_ecore_drm2_log_dom, __VA_ARGS__) + +# ifdef WRN +# undef WRN +# endif +# define WRN(...) EINA_LOG_DOM_WARN(_ecore_drm2_log_dom, __VA_ARGS__) + +# ifdef CRIT +# undef CRIT +# endif +# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm2_log_dom, __VA_ARGS__) + +#endif From 9c7b6572875d5245ae69300936d1cb942bfd0498 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 2 May 2016 10:40:47 -0400 Subject: [PATCH 02/35] ecore-drm2: Add API functions to work with a drm device This commit adds new API functions to find, open, and close a drm device, along with API functions to retrieve clock_id and cursor size. Signed-off-by: Chris Michael --- src/Makefile_Ecore_Drm2.am | 1 + src/lib/ecore_drm2/Ecore_Drm2.h | 80 +++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 184 ++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_private.h | 25 ++++ 4 files changed, 290 insertions(+) create mode 100644 src/lib/ecore_drm2/ecore_drm2_device.c diff --git a/src/Makefile_Ecore_Drm2.am b/src/Makefile_Ecore_Drm2.am index 2818b0e760..59e9865aa3 100644 --- a/src/Makefile_Ecore_Drm2.am +++ b/src/Makefile_Ecore_Drm2.am @@ -9,6 +9,7 @@ dist_installed_ecoredrm2mainheaders_DATA = \ lib/ecore_drm2/Ecore_Drm2.h lib_ecore_drm2_libecore_drm2_la_SOURCES = \ +lib/ecore_drm2/ecore_drm2_device.c \ lib/ecore_drm2/ecore_drm2.c \ lib/ecore_drm2/ecore_drm2_private.h diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index b2bbd15e02..bf08be22c5 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -28,6 +28,9 @@ # ifdef EFL_BETA_API_SUPPORT +/* opaque structure to represent a drm device */ +typedef struct _Ecore_Drm2_Device Ecore_Drm2_Device; + /** * @file * @brief Ecore functions for dealing with drm, virtual terminals @@ -69,6 +72,83 @@ EAPI int ecore_drm2_init(void); */ EAPI int ecore_drm2_shutdown(void); +/** + * @defgroup Ecore_Drm2_Device_Group Drm device functions + * + * Functions that deal with finding, opening, closing, or obtaining various + * information about a drm device + */ + +/** + * Try to find a drm device on a given seat + * + * @param seat + * @param tty + * @param sync + * + * @return A newly allocated Ecore_Drm2_Device on success, NULL otherwise + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI Ecore_Drm2_Device *ecore_drm2_device_find(const char *seat, unsigned int tty, Eina_Bool sync); + +/** + * Try to open a given Ecore_Drm2_Device + * + * @param device + * + * @return A valid file descriptor if open succeeds, -1 otherwise. + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI int ecore_drm2_device_open(Ecore_Drm2_Device *device); + +/** + * Close an open Ecore_Drm2_Device + * + * @param device + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_close(Ecore_Drm2_Device *device); + +/** + * Free a given Ecore_Drm2_Device + * + * @param device + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_free(Ecore_Drm2_Device *device); + +/** + * Get the type of clock used by a given Ecore_Drm2_Device + * + * @param device + * + * @return The clockid_t used by this drm device + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI int ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device); + +/** + * Get the size of the cursor supported by a given Ecore_Drm2_Device + * + * @param device + * @param width + * @param height + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height); + # endif #endif 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..b47028bdf4 --- /dev/null +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -0,0 +1,184 @@ +#include "ecore_drm2_private.h" + +#ifndef DRM_CAP_CURSOR_WIDTH +# define DRM_CAP_CURSOR_WIDTH 0x8 +#endif + +#ifndef DRM_CAP_CURSOR_HEIGHT +# define DRM_CAP_CURSOR_HEIGHT 0x9 +#endif + +static const char * +_drm2_device_find(const char *seat) +{ + Eina_List *devs, *l; + const char *dev, *ret = NULL; + Eina_Bool found = EINA_FALSE; + Eina_Bool platform = EINA_FALSE; + + devs = eeze_udev_find_by_subsystem_sysname("drm", "card[0-9]*"); + if (!devs) return NULL; + + EINA_LIST_FOREACH(devs, l, dev) + { + const char *dpath, *dseat, *dparent; + + dpath = eeze_udev_syspath_get_devpath(dev); + if (!dpath) continue; + + dseat = eeze_udev_syspath_get_property(dev, "ID_SEAT"); + if (!dseat) dseat = eina_stringshare_add("seat0"); + + if ((seat) && (strcmp(seat, dseat))) + goto cont; + else if (strcmp(dseat, "seat0")) + goto cont; + + dparent = eeze_udev_syspath_get_parent_filtered(dev, "pci", NULL); + if (!dparent) + { + dparent = + eeze_udev_syspath_get_parent_filtered(dev, "platform", NULL); + platform = EINA_TRUE; + } + + if (dparent) + { + if (!platform) + { + const char *id; + + id = eeze_udev_syspath_get_sysattr(dparent, "boot_vga"); + if (id) + { + if (!strcmp(id, "1")) found = EINA_TRUE; + eina_stringshare_del(id); + } + } + else + found = EINA_TRUE; + + eina_stringshare_del(dparent); + } + +cont: + eina_stringshare_del(dpath); + eina_stringshare_del(dseat); + if (found) break; + } + + if (!found) goto out; + + ret = eeze_udev_syspath_get_devpath(dev); + +out: + EINA_LIST_FREE(devs, dev) + eina_stringshare_del(dev); + + return ret; +} + +EAPI Ecore_Drm2_Device * +ecore_drm2_device_find(const char *seat, unsigned int tty, Eina_Bool sync) +{ + Ecore_Drm2_Device *dev; + + dev = calloc(1, sizeof(Ecore_Drm2_Device)); + if (!dev) return NULL; + + dev->em = elput_manager_connect(seat, tty, sync); + if (!dev->em) + { + ERR("Could not connect to input manager"); + goto man_err; + } + + dev->path = _drm2_device_find(seat); + if (!dev->path) + { + ERR("Could not find drm device on seat %s", seat); + goto path_err; + } + + return dev; + +path_err: + elput_manager_disconnect(dev->em); +man_err: + free(dev); + return NULL; +} + +EAPI int +ecore_drm2_device_open(Ecore_Drm2_Device *device) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1); + + device->fd = elput_manager_open(device->em, device->path, -1); + + DBG("Device Path: %s", device->path); + DBG("Device Fd: %d", device->fd); + + /* NB: Not going to enable planes if we don't support atomic */ + /* if (drmSetClientCap(device->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) */ + /* ERR("Could not set Universal Plane support: %m"); */ + + return device->fd; +} + +EAPI void +ecore_drm2_device_close(Ecore_Drm2_Device *device) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + EINA_SAFETY_ON_TRUE_RETURN(device->fd < 0); + + elput_manager_close(device->em, device->fd); +} + +EAPI void +ecore_drm2_device_free(Ecore_Drm2_Device *device) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + + eina_stringshare_del(device->path); + free(device); +} + +EAPI int +ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device) +{ + uint64_t caps; + int ret; + + EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1); + EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), -1); + + ret = drmGetCap(device->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &caps); + if ((ret == 0) && (caps == 1)) + return CLOCK_MONOTONIC; + else + return CLOCK_REALTIME; +} + +EAPI void +ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height) +{ + uint64_t caps; + int ret; + + EINA_SAFETY_ON_NULL_RETURN(device); + EINA_SAFETY_ON_TRUE_RETURN((device->fd < 0)); + + if (width) + { + *width = 64; + ret = drmGetCap(device->fd, DRM_CAP_CURSOR_WIDTH, &caps); + if (ret == 0) *width = caps; + } + if (height) + { + *height = 64; + ret = drmGetCap(device->fd, DRM_CAP_CURSOR_HEIGHT, &caps); + if (ret == 0) *height = caps; + } +} diff --git a/src/lib/ecore_drm2/ecore_drm2_private.h b/src/lib/ecore_drm2/ecore_drm2_private.h index 6177e8e436..6b4b90f0e5 100644 --- a/src/lib/ecore_drm2/ecore_drm2_private.h +++ b/src/lib/ecore_drm2/ecore_drm2_private.h @@ -55,4 +55,29 @@ extern int _ecore_drm2_log_dom; # endif # define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm2_log_dom, __VA_ARGS__) +struct _Ecore_Drm2_Device +{ + Elput_Manager *em; + + int fd; + const char *path; + + int num_crtcs; + uint32_t *crtcs; + + struct + { + uint32_t crtc, conn; + } alloc; + + struct + { + uint32_t width, height; + } min, max; + + Eeze_Udev_Watch *watch; + + Eina_List *outputs; +}; + #endif From 4e38aabdc09df1ef4ad630caa7fe754433a35d7d Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 2 May 2016 11:26:44 -0400 Subject: [PATCH 03/35] ecore-drm2: Add API functions to work with outputs This patch adds support for creating, destroying, and otherwise working with outputs via exposed API functions. Signed-off-by: Chris Michael --- src/Makefile_Ecore_Drm2.am | 1 + src/lib/ecore_drm2/Ecore_Drm2.h | 153 ++++ src/lib/ecore_drm2/ecore_drm2.c | 6 + src/lib/ecore_drm2/ecore_drm2_outputs.c | 886 ++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_private.h | 101 +++ 5 files changed, 1147 insertions(+) create mode 100644 src/lib/ecore_drm2/ecore_drm2_outputs.c diff --git a/src/Makefile_Ecore_Drm2.am b/src/Makefile_Ecore_Drm2.am index 59e9865aa3..ab401c625f 100644 --- a/src/Makefile_Ecore_Drm2.am +++ b/src/Makefile_Ecore_Drm2.am @@ -9,6 +9,7 @@ dist_installed_ecoredrm2mainheaders_DATA = \ lib/ecore_drm2/Ecore_Drm2.h lib_ecore_drm2_libecore_drm2_la_SOURCES = \ +lib/ecore_drm2/ecore_drm2_outputs.c \ lib/ecore_drm2/ecore_drm2_device.c \ lib/ecore_drm2/ecore_drm2.c \ lib/ecore_drm2/ecore_drm2_private.h diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index bf08be22c5..0bed771489 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -31,6 +31,30 @@ /* opaque structure to represent a drm device */ typedef struct _Ecore_Drm2_Device Ecore_Drm2_Device; +/* opaque structure to represent a framebuffer object */ +typedef struct _Ecore_Drm2_Fb Ecore_Drm2_Fb; + +/* opaque structure to represent an output device */ +typedef struct _Ecore_Drm2_Output Ecore_Drm2_Output; + +/* opaque structure to represent an output mode */ +typedef struct _Ecore_Drm2_Output_Mode Ecore_Drm2_Output_Mode; + +/* structure to represent event for output changes */ +typedef struct _Ecore_Drm2_Event_Output_Changed +{ + unsigned int id; + int x, y, w, h; + int phys_width, phys_height; + unsigned int refresh, scale; + int subpixel, transform; + const char *make, *model, *name; + Eina_Bool connected : 1; + Eina_Bool enabled : 1; +} Ecore_Drm2_Event_Output_Changed; + +EAPI extern int ECORE_DRM2_EVENT_OUTPUT_CHANGED; + /** * @file * @brief Ecore functions for dealing with drm, virtual terminals @@ -42,6 +66,7 @@ typedef struct _Ecore_Drm2_Device Ecore_Drm2_Device; * * @li @ref Ecore_Drm2_Init_Group * @li @ref Ecore_Drm2_Device_Group + * @li @ref Ecore_Drm2_Output_Group */ /** @@ -149,6 +174,134 @@ EAPI int ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device); */ EAPI void ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height); +/** + * @defgroup Ecore_Drm2_Output_Group Drm output functions + * + * Functions that deal with setup of outputs + */ + +/** + * Iterate drm resources and create outputs + * + * @param device + * + * @return EINA_TRUE on success, EINA_FALSE otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_outputs_create(Ecore_Drm2_Device *device); + +/** + * Destroy any created outputs + * + * @param device + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_outputs_destroy(Ecore_Drm2_Device *device); + +/** + * Get the list of outputs from a drm device + * + * @param device + * + * @return + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI const Eina_List *ecore_drm2_outputs_get(Ecore_Drm2_Device *device); + +/** + * Get the dpms level of a given output + * + * @param output + * + * @return Integer value representing the state of DPMS on a given output + * or -1 on error + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI int ecore_drm2_output_dpms_get(Ecore_Drm2_Output *output); + +/** + * Set the dpms level of a given output + * + * @param output + * @param level + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_dpms_set(Ecore_Drm2_Output *output, int level); + +/** + * Get the edid of a given output + * + * @param output + * + * @return A string representing the edid + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI char *ecore_drm2_output_edid_get(Ecore_Drm2_Output *output); + +/** + * Get if a given output has a backlight + * + * @param output + * + * @return EINA_TRUE if this output has a backlight, EINA_FALSE otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_output_backlight_get(Ecore_Drm2_Output *output); + +/** + * Find an output at the given position + * + * @param device + * @param x + * @param y + * + * @return An Ecore_Drm2_Output which exists at the given coordinates, or NULL on failure + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Ecore_Drm2_Output *ecore_drm2_output_find(Ecore_Drm2_Device *device, int x, int y); + +/** + * Get the geometry of a given output + * + * @param output + * @param x + * @param y + * @param w + * @param h + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_geometry_get(Ecore_Drm2_Output *output, int *x, int *y, int *w, int *h); + +/** + * Get the id of the crtc that an output is using + * + * @param output + * + * @return A valid crtc id or 0 on failure + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI unsigned int ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output); + # endif #endif diff --git a/src/lib/ecore_drm2/ecore_drm2.c b/src/lib/ecore_drm2/ecore_drm2.c index 32b6781cc7..a4096f2fa5 100644 --- a/src/lib/ecore_drm2/ecore_drm2.c +++ b/src/lib/ecore_drm2/ecore_drm2.c @@ -4,6 +4,8 @@ static int _ecore_drm2_init_count = 0; int _ecore_drm2_log_dom = -1; +EAPI int ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1; + EAPI int ecore_drm2_init(void) { @@ -37,6 +39,8 @@ ecore_drm2_init(void) goto log_err; } + ECORE_DRM2_EVENT_OUTPUT_CHANGED = ecore_event_type_new(); + return _ecore_drm2_init_count; log_err: @@ -62,6 +66,8 @@ ecore_drm2_shutdown(void) if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count; + ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1; + eina_log_domain_unregister(_ecore_drm2_log_dom); _ecore_drm2_log_dom = -1; 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..d7f1c39f03 --- /dev/null +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -0,0 +1,886 @@ +#include "ecore_drm2_private.h" + +#define INSIDE(x, y, xx, yy, ww, hh) \ + (((x) < ((xx) + (ww))) && ((y) < ((yy) + (hh))) && \ + ((x) >= (xx)) && ((y) >= (yy))) + +#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe +#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc +#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff +#define EDID_OFFSET_DATA_BLOCKS 0x36 +#define EDID_OFFSET_LAST_BLOCK 0x6c +#define EDID_OFFSET_PNPID 0x08 +#define EDID_OFFSET_SERIAL 0x0c + +static const char *conn_types[] = +{ + "None", "VGA", "DVI-I", "DVI-D", "DVI-A", + "Composite", "S-Video", "LVDS", "Component", "DIN", + "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual", "DSI", +}; + +static void +_output_debug(Ecore_Drm2_Output *output, const drmModeConnector *conn) +{ + Eina_List *l; + Ecore_Drm2_Output_Mode *omode; + + DBG("Created New Output At %d,%d", output->x, output->y); + DBG("\tCrtc Pos: %d %d", output->ocrtc->x, output->ocrtc->y); + DBG("\tCrtc: %d", output->crtc_id); + DBG("\tConn: %d", output->conn_id); + DBG("\tName: %s", output->name); + DBG("\tMake: %s", output->make); + DBG("\tModel: %s", output->model); + DBG("\tSerial: %s", output->serial); + DBG("\tCloned: %d", output->cloned); + DBG("\tPrimary: %d", output->primary); + DBG("\tConnected: %d", output->connected); + DBG("\tEnabled: %d", output->enabled); + + if (output->backlight.path) + { + DBG("\tBacklight"); + switch (output->backlight.type) + { + case ECORE_DRM2_BACKLIGHT_RAW: + DBG("\t\tType: Raw"); + break; + case ECORE_DRM2_BACKLIGHT_PLATFORM: + DBG("\t\tType: Platform"); + break; + case ECORE_DRM2_BACKLIGHT_FIRMWARE: + DBG("\t\tType: Firmware"); + break; + } + DBG("\t\tPath: %s", output->backlight.path); + } + + EINA_LIST_FOREACH(output->modes, l, omode) + { + DBG("\tAdded Mode: %dx%d@%.1f%s%s%s", + omode->width, omode->height, (omode->refresh / 1000.0), + (omode->flags & DRM_MODE_TYPE_PREFERRED) ? ", preferred" : "", + (omode->flags & DRM_MODE_TYPE_DEFAULT) ? ", current" : "", + (conn->count_modes == 0) ? ", built-in" : ""); + } +} + +static void +_cb_output_event_free(void *data EINA_UNUSED, void *event) +{ + Ecore_Drm2_Event_Output_Changed *ev; + + ev = event; + eina_stringshare_del(ev->make); + eina_stringshare_del(ev->model); + eina_stringshare_del(ev->name); + free(ev); +} + +static void +_output_event_send(Ecore_Drm2_Output *output) +{ + Ecore_Drm2_Event_Output_Changed *ev; + + ev = calloc(1, sizeof(Ecore_Drm2_Event_Output_Changed)); + if (!ev) return; + + ev->id = output->crtc_id; + + ev->x = output->x; + ev->y = output->y; + ev->w = output->current_mode->width; + ev->h = output->current_mode->height; + ev->phys_width = output->pw; + ev->phys_height = output->ph; + ev->refresh = output->current_mode->refresh; + + ev->scale = output->scale; + ev->subpixel = output->subpixel; + ev->transform = output->transform; + ev->connected = output->connected; + ev->enabled = output->enabled; + + ev->name = eina_stringshare_ref(output->name); + ev->make = eina_stringshare_ref(output->make); + ev->model = eina_stringshare_ref(output->model); + + ecore_event_add(ECORE_DRM2_EVENT_OUTPUT_CHANGED, ev, + _cb_output_event_free, NULL); +} + +static void +_output_edid_parse_string(const uint8_t *data, char text[]) +{ + int i = 0, rep = 0; + + strncpy(text, (const char *)data, 12); + + for (; text[i] != '\0'; i++) + { + if ((text[i] == '\n') || (text[i] == '\r')) + { + text[i] = '\0'; + break; + } + } + + for (i = 0; text[i] != '\0'; i++) + { + if (!isprint(text[i])) + { + text[i] = '-'; + rep++; + } + } + + if (rep > 4) text[0] = '\0'; +} + +static int +_output_edid_parse(Ecore_Drm2_Output *output, const uint8_t *data, size_t len) +{ + int i = 0; + uint32_t serial; + + if (len < 128) return -1; + if ((data[0] != 0x00) || (data[1] != 0xff)) return -1; + + output->edid.pnp[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1; + output->edid.pnp[1] = + 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) + + ((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1; + output->edid.pnp[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1; + output->edid.pnp[3] = '\0'; + + serial = (uint32_t) data[EDID_OFFSET_SERIAL + 0]; + serial += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100; + serial += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000; + serial += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000; + if (serial > 0) + sprintf(output->edid.serial, "%lu", (unsigned long)serial); + + for (i = EDID_OFFSET_DATA_BLOCKS; i <= EDID_OFFSET_LAST_BLOCK; i += 18) + { + if (data[i] != 0) continue; + if (data[i + 2] != 0) continue; + + if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME) + _output_edid_parse_string(&data[i + 5], output->edid.monitor); + else if (data[i + 3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) + _output_edid_parse_string(&data[i + 5], output->edid.serial); + else if (data[i + 3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) + _output_edid_parse_string(&data[i + 5], output->edid.eisa); + } + + return 0; +} + +static void +_output_edid_find(Ecore_Drm2_Output *output, const drmModeConnector *conn) +{ + drmModePropertyBlobPtr blob = NULL; + drmModePropertyPtr prop; + int i = 0, ret = 0; + + for (; i < conn->count_props && !blob; i++) + { + if (!(prop = drmModeGetProperty(output->fd, conn->props[i]))) + continue; + if ((prop->flags & DRM_MODE_PROP_BLOB) && + (!strcmp(prop->name, "EDID"))) + { + blob = drmModeGetPropertyBlob(output->fd, conn->prop_values[i]); + } + drmModeFreeProperty(prop); + if (blob) break; + } + + if (!blob) return; + + output->edid.blob = eina_memdup(blob->data, blob->length, 1); + + ret = _output_edid_parse(output, blob->data, blob->length); + if (!ret) + { + if (output->edid.pnp[0] != '\0') + eina_stringshare_replace(&output->make, output->edid.pnp); + if (output->edid.monitor[0] != '\0') + eina_stringshare_replace(&output->model, output->edid.monitor); + if (output->edid.serial[0] != '\0') + eina_stringshare_replace(&output->serial, output->edid.serial); + } + + drmModeFreePropertyBlob(blob); +} + +static int +_output_crtc_find(const drmModeRes *res, const drmModeConnector *conn, Ecore_Drm2_Device *dev) +{ + drmModeEncoder *enc; + uint32_t pcrtcs; + int i = 0, j = 0; + + for (j = 0; j < conn->count_encoders; j++) + { + enc = drmModeGetEncoder(dev->fd, conn->encoders[j]); + if (!enc) continue; + + pcrtcs = enc->possible_crtcs; + drmModeFreeEncoder(enc); + + for (i = 0; i < res->count_crtcs; i++) + { + if ((pcrtcs & (1 << i)) && + (!(dev->alloc.crtc & (1 << res->crtcs[i])))) + return i; + } + } + + return -1; +} + +static char * +_output_name_get(const drmModeConnector *conn) +{ + char name[DRM_CONNECTOR_NAME_LEN]; + const char *type = NULL; + + if (conn->connector_type < EINA_C_ARRAY_LENGTH(conn_types)) + type = conn_types[conn->connector_type]; + else + type = "UNKNOWN"; + + snprintf(name, sizeof(name), "%s-%d", type, conn->connector_type_id); + return strdup(name); +} + +static Ecore_Drm2_Output_Mode * +_output_mode_add(Ecore_Drm2_Output *output, const drmModeModeInfo *info) +{ + Ecore_Drm2_Output_Mode *mode; + uint64_t refresh; + + mode = calloc(1, sizeof(Ecore_Drm2_Output_Mode)); + if (!mode) return NULL; + + mode->flags = 0; + mode->width = info->hdisplay; + mode->height = info->vdisplay; + + refresh = (info->clock * 1000LL / info->htotal + info->vtotal / 2) / + info->vtotal; + + if (info->flags & DRM_MODE_FLAG_INTERLACE) + refresh *= 2; + if (info->flags & DRM_MODE_FLAG_DBLSCAN) + refresh /= 2; + if (info->vscan > 1) + refresh /= info->vscan; + + mode->refresh = refresh; + mode->info = *info; + + if (info->type & DRM_MODE_TYPE_PREFERRED) + mode->flags |= DRM_MODE_TYPE_PREFERRED; + + output->modes = eina_list_append(output->modes, mode); + + return mode; +} + +static void +_output_modes_create(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output, const drmModeConnector *conn) +{ + int i = 0; + drmModeCrtc *crtc; + drmModeEncoder *enc; + drmModeModeInfo crtc_mode; + Ecore_Drm2_Output_Mode *omode; + Ecore_Drm2_Output_Mode *current = NULL, *preferred = NULL, *best = NULL; + Eina_List *l = NULL; + + memset(&crtc_mode, 0, sizeof(crtc_mode)); + + enc = drmModeGetEncoder(dev->fd, conn->encoder_id); + if (enc) + { + crtc = drmModeGetCrtc(dev->fd, enc->crtc_id); + drmModeFreeEncoder(enc); + if (!crtc) return; + if (crtc->mode_valid) crtc_mode = crtc->mode; + drmModeFreeCrtc(crtc); + } + + for (i = 0; i < conn->count_modes; i++) + { + omode = _output_mode_add(output, &conn->modes[i]); + if (!omode) continue; + } + + EINA_LIST_REVERSE_FOREACH(output->modes, l, omode) + { + if (!memcmp(&crtc_mode, &omode->info, sizeof(crtc_mode))) + current = omode; + if (omode->flags & DRM_MODE_TYPE_PREFERRED) + preferred = omode; + best = omode; + } + + if ((!current) && (crtc_mode.clock != 0)) + { + current = _output_mode_add(output, &crtc_mode); + if (!current) goto err; + } + + if (current) output->current_mode = current; + else if (preferred) output->current_mode = preferred; + else if (best) output->current_mode = best; + + if (!output->current_mode) goto err; + + output->current_mode->flags |= DRM_MODE_TYPE_DEFAULT; + + return; + +err: + EINA_LIST_FREE(output->modes, omode) + free(omode); +} + +static drmModePropertyPtr +_output_dpms_property_get(int fd, const drmModeConnector *conn) +{ + drmModePropertyPtr prop; + int i = 0; + + for (; i < conn->count_props; i++) + { + prop = drmModeGetProperty(fd, conn->props[i]); + if (!prop) continue; + + if (!strcmp(prop->name, "DPMS")) return prop; + + drmModeFreeProperty(prop); + } + + return NULL; +} + +static void +_output_backlight_init(Ecore_Drm2_Output *output, unsigned int conn_type) +{ + Eina_List *devs, *l; + const char *dev, *t; + Eina_Bool found = EINA_FALSE; + Ecore_Drm2_Backlight_Type type = 0; + + devs = eeze_udev_find_by_filter("backlight", NULL, NULL); + + EINA_LIST_FOREACH(devs, l, dev) + { + t = eeze_udev_syspath_get_sysattr(dev, "type"); + if (!t) continue; + + if (!strcmp(t, "raw")) + type = ECORE_DRM2_BACKLIGHT_RAW; + else if (!strcmp(t, "platform")) + type = ECORE_DRM2_BACKLIGHT_PLATFORM; + else if (!strcmp(t, "firmware")) + type = ECORE_DRM2_BACKLIGHT_FIRMWARE; + + if ((conn_type == DRM_MODE_CONNECTOR_LVDS) || + (conn_type == DRM_MODE_CONNECTOR_eDP) || + (type == ECORE_DRM2_BACKLIGHT_RAW)) + found = EINA_TRUE; + + eina_stringshare_del(t); + if (found) break; + } + + if (found) + { + output->backlight.type = type; + output->backlight.path = eina_stringshare_add(dev); + } + + EINA_LIST_FREE(devs, dev) + eina_stringshare_del(dev); +} + +static void +_output_scale_init(Ecore_Drm2_Output *output, Ecore_Drm2_Transform transform, unsigned int scale) +{ + output->transform = transform; + + if ((output->enabled) && (output->current_mode)) + { + switch (transform) + { + case ECORE_DRM2_TRANSFORM_90: + case ECORE_DRM2_TRANSFORM_270: + case ECORE_DRM2_TRANSFORM_FLIPPED_90: + case ECORE_DRM2_TRANSFORM_FLIPPED_270: + output->w = output->current_mode->height; + output->h = output->current_mode->width; + break; + case ECORE_DRM2_TRANSFORM_NORMAL: + case ECORE_DRM2_TRANSFORM_180: + case ECORE_DRM2_TRANSFORM_FLIPPED: + case ECORE_DRM2_TRANSFORM_FLIPPED_180: + output->w = output->current_mode->width; + output->h = output->current_mode->height; + break; + default: + break; + } + } + + output->scale = scale; + output->w /= scale; + output->h /= scale; +} + +static void +_output_matrix_rotate_xy(Eina_Matrix3 *matrix, double x, double y) +{ + Eina_Matrix4 tmp, m; + + eina_matrix4_identity(&tmp); + eina_matrix4_values_set(&tmp, x, y, 0, 0, -y, x, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 1); + + eina_matrix3_matrix4_to(&m, matrix); + eina_matrix4_multiply(&m, &m, &tmp); + eina_matrix4_matrix3_to(matrix, &m); +} + +static void +_output_matrix_update(Ecore_Drm2_Output *output) +{ + Eina_Matrix3 m3; + + eina_matrix4_identity(&output->matrix); + eina_matrix4_matrix3_to(&m3, &output->matrix); + eina_matrix3_translate(&m3, -output->x, -output->y); + + switch (output->transform) + { + case ECORE_DRM2_TRANSFORM_FLIPPED: + case ECORE_DRM2_TRANSFORM_FLIPPED_90: + case ECORE_DRM2_TRANSFORM_FLIPPED_180: + case ECORE_DRM2_TRANSFORM_FLIPPED_270: + eina_matrix3_translate(&m3, -output->w, 0); + break; + default: + break; + } + + switch (output->transform) + { + case ECORE_DRM2_TRANSFORM_NORMAL: + case ECORE_DRM2_TRANSFORM_FLIPPED: + default: + break; + case ECORE_DRM2_TRANSFORM_90: + case ECORE_DRM2_TRANSFORM_FLIPPED_90: + eina_matrix3_translate(&m3, 0, -output->h); + _output_matrix_rotate_xy(&m3, 0, 1); + break; + case ECORE_DRM2_TRANSFORM_180: + case ECORE_DRM2_TRANSFORM_FLIPPED_180: + eina_matrix3_translate(&m3, -output->w, -output->h); + _output_matrix_rotate_xy(&m3, -1, 0); + break; + case ECORE_DRM2_TRANSFORM_270: + case ECORE_DRM2_TRANSFORM_FLIPPED_270: + eina_matrix3_translate(&m3, -output->w, 0); + _output_matrix_rotate_xy(&m3, 0, -1); + break; + } + + if (output->scale != 1) + eina_matrix3_scale(&m3, output->scale, output->scale); + + eina_matrix3_matrix4_to(&output->matrix, &m3); + eina_matrix4_inverse(&output->inverse, &output->matrix); +} + +static Eina_Bool +_output_create(Ecore_Drm2_Device *dev, const drmModeRes *res, const drmModeConnector *conn, int x, int y, int *w, Eina_Bool cloned) +{ + Ecore_Drm2_Output *output; + int i = 0; + + if (w) *w = 0; + + i = _output_crtc_find(res, conn, dev); + if (i < 0) return EINA_FALSE; + + output = calloc(1, sizeof(Ecore_Drm2_Output)); + if (!output) return EINA_FALSE; + + output->fd = dev->fd; + output->x = x; + output->y = y; + output->cloned = cloned; + output->pw = conn->mmWidth; + output->ph = conn->mmHeight; + + switch (conn->subpixel) + { + case DRM_MODE_SUBPIXEL_UNKNOWN: + output->subpixel = 0; // WL_OUTPUT_SUBPIXEL_UNKNOWN + break; + case DRM_MODE_SUBPIXEL_NONE: + output->subpixel = 1; // WL_OUTPUT_SUBPIXEL_NONE + break; + case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: + output->subpixel = 2; // WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB + break; + case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: + output->subpixel = 3; // WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR + break; + case DRM_MODE_SUBPIXEL_VERTICAL_RGB: + output->subpixel = 4; // WL_OUTPUT_SUBPIXEL_VERTICAL_RGB + break; + case DRM_MODE_SUBPIXEL_VERTICAL_BGR: + output->subpixel = 5; // WL_OUTPUT_SUBPIXEL_VERTICAL_BGR + break; + default: + output->subpixel = 0; + break; + } + + output->name = eina_stringshare_add(_output_name_get(conn)); + output->make = eina_stringshare_add("unknown"); + output->model = eina_stringshare_add("unknown"); + output->serial = eina_stringshare_add("unknown"); + + output->pipe = i; + output->crtc_id = res->crtcs[i]; + output->conn_id = conn->connector_id; + output->conn_type = conn->connector_type; + + output->connected = (conn->connection == DRM_MODE_CONNECTED); + + output->ocrtc = drmModeGetCrtc(dev->fd, output->crtc_id); + + output->dpms = _output_dpms_property_get(dev->fd, conn); + + _output_backlight_init(output, conn->connector_type); + + /* TODO: gamma */ + + _output_modes_create(dev, output, conn); + + _output_edid_find(output, conn); + + if (output->connected) output->enabled = EINA_TRUE; + + _output_scale_init(output, ECORE_DRM2_TRANSFORM_NORMAL, 1); + _output_matrix_update(output); + + if (!eina_list_count(dev->outputs)) + output->primary = EINA_TRUE; + + dev->alloc.crtc |= (1 << output->crtc_id); + dev->alloc.conn |= (1 << output->conn_id); + dev->outputs = eina_list_append(dev->outputs, output); + + _output_debug(output, conn); + + if ((output->enabled) && (output->current_mode)) + { + if (w) *w = output->current_mode->width; + } + + return EINA_TRUE; +} + +static void +_outputs_update(Ecore_Drm2_Device *dev) +{ + drmModeRes *res; + drmModeConnector *conn; + uint32_t connected = 0, disconnected = 0; + int i = 0, x = 0, y = 0; + + res = drmModeGetResources(dev->fd); + if (!res) return; + + for (i = 0; i < res->count_connectors; i++) + { + conn = drmModeGetConnector(dev->fd, res->connectors[i]); + if (!conn) continue; + + if (conn->connection != DRM_MODE_CONNECTED) goto next; + + connected |= (1 << res->connectors[i]); + + if (!(dev->alloc.conn & (1 << res->connectors[i]))) + { + if (dev->outputs) + { + Ecore_Drm2_Output *last; + + last = eina_list_last_data_get(dev->outputs); + if (last) x = last->x + last->current_mode->width; + else x = 0; + } + else + x = 0; + + if (!_output_create(dev, res, conn, x, y, NULL, EINA_TRUE)) + goto next; + } + +next: + drmModeFreeConnector(conn); + } + + drmModeFreeResources(res); + + disconnected = (dev->alloc.conn & ~connected); + if (disconnected) + { + Ecore_Drm2_Output *output; + Eina_List *l; + + EINA_LIST_FOREACH(dev->outputs, l, output) + { + if (disconnected & (1 << output->conn_id)) + { + disconnected &= ~(1 << output->conn_id); + output->connected = EINA_FALSE; + output->enabled = EINA_FALSE; + _output_event_send(output); + } + } + } +} + +static void +_cb_output_event(const char *device EINA_UNUSED, Eeze_Udev_Event event EINA_UNUSED, void *data, Eeze_Udev_Watch *watch EINA_UNUSED) +{ + Ecore_Drm2_Device *dev; + + dev = data; + _outputs_update(dev); +} + +static void +_output_destroy(Ecore_Drm2_Device *dev, Ecore_Drm2_Output *output) +{ + dev->alloc.crtc &= ~(1 << output->crtc_id); + dev->alloc.conn &= ~(1 << output->conn_id); + + eina_stringshare_del(output->backlight.path); + eina_stringshare_del(output->name); + eina_stringshare_del(output->make); + eina_stringshare_del(output->model); + eina_stringshare_del(output->serial); + + drmModeFreeProperty(output->dpms); + free(output->edid.blob); + + free(output); +} + +EAPI Eina_Bool +ecore_drm2_outputs_create(Ecore_Drm2_Device *device) +{ + drmModeConnector *conn; + drmModeRes *res; + int i = 0, x = 0, y = 0, w = 0; + int events = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), EINA_FALSE); + + res = drmModeGetResources(device->fd); + if (!res) return EINA_FALSE; + + device->crtcs = calloc(res->count_crtcs, sizeof(uint32_t)); + if (!device->crtcs) goto err; + + device->min.width = res->min_width; + device->min.height = res->min_height; + device->max.width = res->max_width; + device->max.height = res->max_height; + + device->num_crtcs = res->count_crtcs; + memcpy(device->crtcs, res->crtcs, sizeof(uint32_t) * res->count_crtcs); + + for (i = 0; i < res->count_connectors; i++) + { + conn = drmModeGetConnector(device->fd, res->connectors[i]); + if (!conn) continue; + + if (!_output_create(device, res, conn, x, y, &w, EINA_FALSE)) + goto next; + + x += w; + +next: + drmModeFreeConnector(conn); + } + + if (eina_list_count(device->outputs) < 1) goto err; + + drmModeFreeResources(res); + + events = (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE | + EEZE_UDEV_EVENT_CHANGE); + + device->watch = + eeze_udev_watch_add(EEZE_UDEV_TYPE_DRM, events, + _cb_output_event, device); + + return EINA_TRUE; + +err: + drmModeFreeResources(res); + return EINA_FALSE; +} + +EAPI void +ecore_drm2_outputs_destroy(Ecore_Drm2_Device *device) +{ + Ecore_Drm2_Output *output; + + EINA_SAFETY_ON_NULL_RETURN(device); + + EINA_LIST_FREE(device->outputs, output) + _output_destroy(device, output); +} + +EAPI const Eina_List * +ecore_drm2_outputs_get(Ecore_Drm2_Device *device) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL); + return device->outputs; +} + +EAPI int +ecore_drm2_output_dpms_get(Ecore_Drm2_Output *output) +{ + drmModeObjectProperties *props; + drmModePropertyRes *prop; + int val = -1; + unsigned int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1); + + props = + drmModeObjectGetProperties(output->fd, output->conn_id, + DRM_MODE_OBJECT_CONNECTOR); + if (!props) return -1; + + for (i = 0; i < props->count_props; i++) + { + prop = drmModeGetProperty(output->fd, props->props[i]); + if (!prop) continue; + + if (!strcmp(prop->name, "DPMS")) + val = props->prop_values[i]; + + drmModeFreeProperty(prop); + } + + drmModeFreeObjectProperties(props); + + return val; +} + +EAPI void +ecore_drm2_output_dpms_set(Ecore_Drm2_Output *output, int level) +{ + EINA_SAFETY_ON_NULL_RETURN(output); + EINA_SAFETY_ON_TRUE_RETURN(!output->enabled); + + drmModeConnectorSetProperty(output->fd, output->conn_id, + output->dpms->prop_id, level); +} + +EAPI char * +ecore_drm2_output_edid_get(Ecore_Drm2_Output *output) +{ + char *edid_str = NULL; + unsigned char *blob; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->edid.blob, NULL); + + blob = output->edid.blob; + + edid_str = malloc((128 * 2) + 1); + if (edid_str) + { + unsigned int k, kk; + const char *hexch = "0123456789abcdef"; + + for (kk = 0, k = 0; k < 128; k++) + { + edid_str[kk] = hexch[(blob[k] >> 4) & 0xf]; + edid_str[kk + 1] = hexch[blob[k] & 0xf]; + kk += 2; + } + edid_str[kk] = 0; + } + + return edid_str; +} + +EAPI Eina_Bool +ecore_drm2_output_backlight_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + return (output->backlight.path != NULL); +} + +EAPI Ecore_Drm2_Output * +ecore_drm2_output_find(Ecore_Drm2_Device *device, int x, int y) +{ + Eina_List *l; + Ecore_Drm2_Output *output; + + EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL); + + EINA_LIST_FOREACH(device->outputs, l, output) + { + int ox, oy, ow, oh; + + if (!output->enabled) continue; + + ox = output->x; + oy = output->y; + ow = output->current_mode->width; + oh = output->current_mode->height; + + if (INSIDE(x, y, ox, oy, ow, oh)) + return output; + } + + return NULL; +} + +EAPI void +ecore_drm2_output_geometry_get(Ecore_Drm2_Output *output, int *x, int *y, int *w, int *h) +{ + EINA_SAFETY_ON_NULL_RETURN(output); + EINA_SAFETY_ON_TRUE_RETURN(!output->enabled); + + if (x) *x = output->x; + if (y) *y = output->y; + if (w) *w = output->current_mode->width; + if (h) *h = output->current_mode->height; +} + +EAPI unsigned int +ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0); + return output->crtc_id; +} diff --git a/src/lib/ecore_drm2/ecore_drm2_private.h b/src/lib/ecore_drm2/ecore_drm2_private.h index 6b4b90f0e5..2042e4388e 100644 --- a/src/lib/ecore_drm2/ecore_drm2_private.h +++ b/src/lib/ecore_drm2/ecore_drm2_private.h @@ -55,6 +55,107 @@ extern int _ecore_drm2_log_dom; # endif # define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_drm2_log_dom, __VA_ARGS__) +typedef enum _Ecore_Drm2_Backlight_Type +{ + ECORE_DRM2_BACKLIGHT_RAW, + ECORE_DRM2_BACKLIGHT_PLATFORM, + ECORE_DRM2_BACKLIGHT_FIRMWARE +} Ecore_Drm2_Backlight_Type; + +typedef enum _Ecore_Drm2_Transform +{ + ECORE_DRM2_TRANSFORM_NORMAL, + ECORE_DRM2_TRANSFORM_90, + ECORE_DRM2_TRANSFORM_180, + ECORE_DRM2_TRANSFORM_270, + ECORE_DRM2_TRANSFORM_FLIPPED, + ECORE_DRM2_TRANSFORM_FLIPPED_90, + ECORE_DRM2_TRANSFORM_FLIPPED_180, + ECORE_DRM2_TRANSFORM_FLIPPED_270 +} Ecore_Drm2_Transform; + +typedef enum _Ecore_Drm2_Rotation +{ + ECORE_DRM2_ROTATION_NORMAL = 1, + ECORE_DRM2_ROTATION_90 = 2, + ECORE_DRM2_ROTATION_180 = 4, + ECORE_DRM2_ROTATION_270 = 8, + ECORE_DRM2_ROTATION_REFLECT_X = 16, + ECORE_DRM2_ROTATION_REFLECT_Y = 32 +} Ecore_Drm2_Rotation; + +struct _Ecore_Drm2_Fb +{ + int fd; + int w, h; + int depth, bpp; + uint32_t id, hdl; + uint32_t stride, size; + uint32_t format; + + Eina_Bool gbm : 1; + + void *mmap; +}; + +struct _Ecore_Drm2_Output_Mode +{ + uint32_t flags; + int32_t width, height; + uint32_t refresh; + drmModeModeInfo info; +}; + +struct _Ecore_Drm2_Output +{ + Eina_Stringshare *name; + Eina_Stringshare *make, *model, *serial; + + int fd; + int pipe; + int x, y, w, h, pw, ph; + + uint32_t subpixel; + uint32_t crtc_id, conn_id, conn_type; + uint32_t scale; + + struct + { + char eisa[13]; + char monitor[13]; + char pnp[5]; + char serial[13]; + unsigned char *blob; // unused when doing atomic + } edid; + + struct + { + const char *path; + int value, max; + Ecore_Drm2_Backlight_Type type; + } backlight; + + drmModeCrtcPtr ocrtc; + + Ecore_Drm2_Fb *current, *next; + + Eina_Matrix4 matrix, inverse; + Ecore_Drm2_Transform transform; + + /* unused when doing atomic */ + drmModePropertyPtr dpms; + + Ecore_Drm2_Output_Mode *current_mode; + Eina_List *modes; + + Eina_List *planes; + + Eina_Bool connected : 1; + Eina_Bool primary : 1; + Eina_Bool cloned : 1; + Eina_Bool enabled : 1; +}; + struct _Ecore_Drm2_Device { Elput_Manager *em; From d2b4176592c6f0e6bd2a78c7a620f29142b65575 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 2 May 2016 11:45:39 -0400 Subject: [PATCH 04/35] ecore-drm2: Add API functions to work with framebuffer objects This patch adds support for creating, deleting, and manipulating framebuffer objects via exposed API. Signed-off-by: Chris Michael --- src/Makefile_Ecore_Drm2.am | 1 + src/lib/ecore_drm2/Ecore_Drm2.h | 122 ++++++++++- src/lib/ecore_drm2/ecore_drm2_fb.c | 265 ++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 14 ++ 4 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 src/lib/ecore_drm2/ecore_drm2_fb.c diff --git a/src/Makefile_Ecore_Drm2.am b/src/Makefile_Ecore_Drm2.am index ab401c625f..1c328e33de 100644 --- a/src/Makefile_Ecore_Drm2.am +++ b/src/Makefile_Ecore_Drm2.am @@ -9,6 +9,7 @@ dist_installed_ecoredrm2mainheaders_DATA = \ lib/ecore_drm2/Ecore_Drm2.h lib_ecore_drm2_libecore_drm2_la_SOURCES = \ +lib/ecore_drm2/ecore_drm2_fb.c \ lib/ecore_drm2/ecore_drm2_outputs.c \ lib/ecore_drm2/ecore_drm2_device.c \ lib/ecore_drm2/ecore_drm2.c \ diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 0bed771489..f1ce291651 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -2,7 +2,6 @@ # define _ECORE_DRM2_H # include -# include # ifdef EAPI # undef EAPI @@ -67,6 +66,7 @@ EAPI extern int ECORE_DRM2_EVENT_OUTPUT_CHANGED; * @li @ref Ecore_Drm2_Init_Group * @li @ref Ecore_Drm2_Device_Group * @li @ref Ecore_Drm2_Output_Group + * @li @ref Ecore_Drm2_Fb_Group */ /** @@ -302,6 +302,126 @@ EAPI void ecore_drm2_output_geometry_get(Ecore_Drm2_Output *output, int *x, int */ EAPI unsigned int ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output); +/** + * Return the next Ecore_Drm2_Fb to be used on a given output + * + * @param output + * + * @return The next Ecore_Drm2_Fb which is scheduled to to be flipped, or NULL otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Ecore_Drm2_Fb *ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output); + +/** + * Set the next Ecore_Drm2_Fb to be used on a given output + * + * @param output + * @param fb + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb); + +/** + * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions + * + * Functions that deal with setup of framebuffers + */ + +/** + * Create a new framebuffer object + * + * @param fd + * @param width + * @param height + * @param depth + * @param bpp + * @param format + * + * @return A newly create framebuffer object, or NULL on failure + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.18 + */ +EAPI Ecore_Drm2_Fb *ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format); + +EAPI 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); + +/** + * Destroy a framebuffer object + * + * @param fb + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.18 + */ +EAPI void ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb); + +/** + * Get a framebuffer's mmap'd data + * + * @param fb + * + * @return The mmap'd area of the framebuffer or NULL on failure + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.18 + */ +EAPI void *ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb); + +/** + * Get a framebuffer's size + * + * @param fb + * + * @return size of the framebuffers' mmap'd data or 0 on failure + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.18 + */ +EAPI unsigned int ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb); + +/** + * Get a framebuffer's stride + * + * @param fb + * + * @return stride of the framebuffer or 0 on failure + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.18 + */ +EAPI unsigned int ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb); + +/** + * Mark regions of a framebuffer as dirty + * + * @param fb + * @param rects + * @param count + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.18 + */ +EAPI void ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count); + +/** + * Schedule a pageflip to the given Ecore_Drm2_Fb + * + * @param fb + * @param output + * @param data + * + * @return The result of drmModePageFlip function call + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.18 + */ +EAPI int ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output, void *data); + # endif #endif 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 @@ +#include "ecore_drm2_private.h" + +static Eina_Bool +_fb2_create(Ecore_Drm2_Fb *fb) +{ + struct drm_mode_fb_cmd2 cmd; + uint32_t hdls[4], pitches[4], offsets[4]; + uint64_t modifiers[4]; + + hdls[0] = fb->hdl; + pitches[0] = fb->stride; + offsets[0] = 0; + modifiers[0] = 0; + + memset(&cmd, 0, sizeof(struct drm_mode_fb_cmd2)); + cmd.fb_id = 0; + cmd.width = fb->w; + cmd.height = fb->h; + cmd.pixel_format = fb->format; + cmd.flags = 0; + memcpy(cmd.handles, hdls, 4 * sizeof(hdls[0])); + memcpy(cmd.pitches, pitches, 4 * sizeof(pitches[0])); + memcpy(cmd.offsets, offsets, 4 * sizeof(offsets[0])); + memcpy(cmd.modifier, modifiers, 4 * sizeof(modifiers[0])); + + if (drmIoctl(fb->fd, DRM_IOCTL_MODE_ADDFB2, &cmd)) + return EINA_FALSE; + + fb->id = cmd.fb_id; + + return EINA_TRUE; +} + +EAPI Ecore_Drm2_Fb * +ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format) +{ + Ecore_Drm2_Fb *fb; + struct drm_mode_create_dumb carg; + struct drm_mode_destroy_dumb darg; + struct drm_mode_map_dumb marg; + int ret; + + EINA_SAFETY_ON_TRUE_RETURN_VAL((fd < 0), NULL); + + fb = calloc(1, sizeof(Ecore_Drm2_Fb)); + if (!fb) return NULL; + + fb->fd = fd; + fb->w = width; + fb->h = height; + fb->bpp = bpp; + fb->depth = depth; + fb->format = format; + + memset(&carg, 0, sizeof(struct drm_mode_create_dumb)); + carg.bpp = bpp; + carg.width = width; + carg.height = height; + + ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg); + if (ret) goto err; + + fb->hdl = carg.handle; + fb->size = carg.size; + fb->stride = carg.pitch; + + if (!_fb2_create(fb)) + { + ret = + drmModeAddFB(fd, width, height, depth, bpp, + fb->stride, fb->hdl, &fb->id); + if (ret) + { + ERR("Could not add framebuffer: %m"); + goto add_err; + } + } + + memset(&marg, 0, sizeof(struct drm_mode_map_dumb)); + marg.handle = fb->hdl; + ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &marg); + if (ret) + { + ERR("Could not map framebuffer: %m"); + goto map_err; + } + + fb->mmap = mmap(NULL, fb->size, PROT_WRITE, MAP_SHARED, fd, marg.offset); + if (fb->mmap == MAP_FAILED) + { + ERR("Could not mmap framebuffer memory: %m"); + goto map_err; + } + + return fb; + +map_err: + drmModeRmFB(fd, fb->id); +add_err: + memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb)); + darg.handle = fb->hdl; + drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg); +err: + free(fb); + return NULL; +} + +EAPI 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) +{ + Ecore_Drm2_Fb *fb; + + EINA_SAFETY_ON_TRUE_RETURN_VAL((fd < 0), NULL); + + fb = calloc(1, sizeof(Ecore_Drm2_Fb)); + if (!fb) return NULL; + + fb->gbm = EINA_TRUE; + + fb->fd = fd; + fb->w = width; + fb->h = height; + fb->bpp = bpp; + fb->depth = depth; + fb->format = format; + fb->stride = stride; + fb->size = fb->stride * fb->h; + fb->hdl = handle; + + if (!_fb2_create(fb)) + { + int ret; + + ret = + drmModeAddFB(fd, width, height, depth, bpp, + fb->stride, fb->hdl, &fb->id); + if (ret) + { + ERR("Could not add framebuffer: %m"); + goto err; + } + } + + return fb; + +err: + free(fb); + return NULL; +} + +EAPI void +ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb) +{ + EINA_SAFETY_ON_NULL_RETURN(fb); + + if (fb->id) drmModeRmFB(fb->fd, fb->id); + + if (!fb->gbm) + { + struct drm_mode_destroy_dumb darg; + + if (fb->mmap) munmap(fb->mmap, fb->size); + + memset(&darg, 0, sizeof(struct drm_mode_destroy_dumb)); + darg.handle = fb->hdl; + drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg); + } + + free(fb); +} + +EAPI void * +ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(fb, NULL); + return fb->mmap; +} + +EAPI unsigned int +ecore_drm2_fb_size_get(Ecore_Drm2_Fb *fb) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0); + return fb->size; +} + +EAPI unsigned int +ecore_drm2_fb_stride_get(Ecore_Drm2_Fb *fb) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(fb, 0); + return fb->stride; +} + +EAPI void +ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count) +{ + EINA_SAFETY_ON_NULL_RETURN(fb); + EINA_SAFETY_ON_NULL_RETURN(rects); + +#ifdef DRM_MODE_FEATURE_DIRTYFB + drmModeClip *clip; + unsigned int i = 0; + int ret; + + clip = alloca(count * sizeof(drmModeClip)); + for (i = 0; i < count; i++) + { + clip[i].x1 = rects[i].x; + clip[i].y1 = rects[i].y; + clip[i].x2 = rects[i].w; + clip[i].y2 = rects[i].h; + } + + ret = drmModeDirtyFB(fb->fd, fb->id, clip, count); + if ((ret) && (ret == -EINVAL)) + WRN("Could not mark framebuffer as dirty: %m"); +#endif +} + +EAPI int +ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output, void *data) +{ + int ret = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(fb, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(output, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->current_mode, -1); + + if (output->next) + WRN("Fb reused too soon, tearing may be visible"); + + if ((!output->current) || + (output->current->stride != fb->stride)) + { + ret = + drmModeSetCrtc(fb->fd, output->crtc_id, fb->id, + output->x, output->y, &output->conn_id, 1, + &output->current_mode->info); + if (ret) + { + ERR("Failed to set Mode %dx%d for Output %s: %m", + output->current_mode->width, output->current_mode->height, + output->name); + return ret; + } + + output->current = fb; + output->next = NULL; + + return 0; + } + + ret = + drmModePageFlip(fb->fd, output->crtc_id, fb->id, + DRM_MODE_PAGE_FLIP_EVENT, data); + if (ret < 0) + { + DBG("Pageflip Failed for Crtc %u on Connector %u: %m", + output->crtc_id, output->conn_id); + output->next = fb; + return ret; + } + + output->current = fb; + return 0; +} diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index d7f1c39f03..6443ecaf1a 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -884,3 +884,17 @@ ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output) EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0); return output->crtc_id; } + +EAPI Ecore_Drm2_Fb * +ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); + return output->next; +} + +EAPI void +ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb) +{ + EINA_SAFETY_ON_NULL_RETURN(output); + output->next = fb; +} From 296d233f64327d87d318093b2504b58834c5bc85 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 4 May 2016 11:03:15 -0400 Subject: [PATCH 05/35] ecore-drm2: Add API functions to get and set pointer position Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 24 ++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index f1ce291651..f4bbad2d08 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -174,6 +174,30 @@ EAPI int ecore_drm2_device_clock_id_get(Ecore_Drm2_Device *device); */ EAPI void ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *height); +/** + * Get the current pointer position + * + * @param device + * @param x + * @param y + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, int *y); + +/** + * Warp the pointer position to given coordinates + * + * @param dev + * @param x + * @param y + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y); + /** * @defgroup Ecore_Drm2_Output_Group Drm output functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index b47028bdf4..f352b30795 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -182,3 +182,22 @@ ecore_drm2_device_cursor_size_get(Ecore_Drm2_Device *device, int *width, int *he if (ret == 0) *height = caps; } } + +EAPI void +ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, int *y) +{ + if (x) *x = 0; + if (y) *y = 0; + + EINA_SAFETY_ON_NULL_RETURN(device); + + elput_input_pointer_xy_get(device->em, NULL, x, y); +} + +EAPI void +ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + + elput_input_pointer_xy_set(device->em, NULL, x, y); +} From 3c332e1f88881b918abb1c2d042ca8d391f8d588 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 9 May 2016 12:47:02 -0400 Subject: [PATCH 06/35] ecore-drm2: Add drm2 event for session activation This patch adds a new Ecore_Drm2_Event_Activate that can be raised to inform Enlightenment that a session has been activated or suspended so that rendering can be paused/resumed Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 7 +++++++ src/lib/ecore_drm2/ecore_drm2.c | 3 +++ src/lib/ecore_drm2/ecore_drm2_device.c | 25 +++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_private.h | 1 + 4 files changed, 36 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index f4bbad2d08..af69c8d60c 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -52,7 +52,14 @@ typedef struct _Ecore_Drm2_Event_Output_Changed Eina_Bool enabled : 1; } Ecore_Drm2_Event_Output_Changed; +/* structure to represent event for session state changes */ +typedef struct _Ecore_Drm2_Event_Activate +{ + Eina_Bool active : 1; +} Ecore_Drm2_Event_Activate; + EAPI extern int ECORE_DRM2_EVENT_OUTPUT_CHANGED; +EAPI extern int ECORE_DRM2_EVENT_ACTIVATE; /** * @file diff --git a/src/lib/ecore_drm2/ecore_drm2.c b/src/lib/ecore_drm2/ecore_drm2.c index a4096f2fa5..339362a9c2 100644 --- a/src/lib/ecore_drm2/ecore_drm2.c +++ b/src/lib/ecore_drm2/ecore_drm2.c @@ -5,6 +5,7 @@ static int _ecore_drm2_init_count = 0; int _ecore_drm2_log_dom = -1; EAPI int ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1; +EAPI int ECORE_DRM2_EVENT_ACTIVATE = -1; EAPI int ecore_drm2_init(void) @@ -40,6 +41,7 @@ ecore_drm2_init(void) } ECORE_DRM2_EVENT_OUTPUT_CHANGED = ecore_event_type_new(); + ECORE_DRM2_EVENT_ACTIVATE = ecore_event_type_new(); return _ecore_drm2_init_count; @@ -67,6 +69,7 @@ ecore_drm2_shutdown(void) if (--_ecore_drm2_init_count != 0) return _ecore_drm2_init_count; ECORE_DRM2_EVENT_OUTPUT_CHANGED = -1; + ECORE_DRM2_EVENT_ACTIVATE = -1; eina_log_domain_unregister(_ecore_drm2_log_dom); _ecore_drm2_log_dom = -1; diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index f352b30795..9e7d7a6063 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -8,6 +8,24 @@ # define DRM_CAP_CURSOR_HEIGHT 0x9 #endif +static Eina_Bool +_cb_session_active(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +{ + Elput_Event_Session_Active *ev; + Ecore_Drm2_Event_Activate *ea; + + ev = event; + + ea = calloc(1, sizeof(Ecore_Drm2_Event_Activate)); + if (!ea) return ECORE_CALLBACK_RENEW; + + ea->active = ev->active; + + ecore_event_add(ECORE_DRM2_EVENT_ACTIVATE, ea, NULL, NULL); + + return ECORE_CALLBACK_RENEW; +} + static const char * _drm2_device_find(const char *seat) { @@ -119,6 +137,10 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device) DBG("Device Path: %s", device->path); DBG("Device Fd: %d", device->fd); + device->active_hdlr = + ecore_event_handler_add(ELPUT_EVENT_SESSION_ACTIVE, + _cb_session_active, device); + /* NB: Not going to enable planes if we don't support atomic */ /* if (drmSetClientCap(device->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) */ /* ERR("Could not set Universal Plane support: %m"); */ @@ -140,6 +162,9 @@ ecore_drm2_device_free(Ecore_Drm2_Device *device) { EINA_SAFETY_ON_NULL_RETURN(device); + if (device->active_hdlr) ecore_event_handler_del(device->active_hdlr); + device->active_hdlr = NULL; + eina_stringshare_del(device->path); free(device); } diff --git a/src/lib/ecore_drm2/ecore_drm2_private.h b/src/lib/ecore_drm2/ecore_drm2_private.h index 2042e4388e..23c9c77016 100644 --- a/src/lib/ecore_drm2/ecore_drm2_private.h +++ b/src/lib/ecore_drm2/ecore_drm2_private.h @@ -177,6 +177,7 @@ struct _Ecore_Drm2_Device } min, max; Eeze_Udev_Watch *watch; + Ecore_Event_Handler *active_hdlr; Eina_List *outputs; }; From 13337c2583d089909dd2c872fcfa9cab11e9eb70 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:07:48 -0400 Subject: [PATCH 07/35] ecore-drm2: Add API functions needed to port Ecore_Evas drm This patch adds 2 new API functions which are required by Ecore_Evas in order for it to function with drm. These API functions allow for restricting pointer movement, and for setting the window id which will be used when sending input events Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 35 +++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 33 +++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 19 ++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index af69c8d60c..480b373617 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -205,6 +205,29 @@ EAPI void ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, in */ EAPI void ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y); +/** + * Set which window is to be used for input events + * + * @param device + * @param window + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window); + +/** + * Set maximium position that pointer device is allowed to move + * + * @param device + * @param w + * @param h + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h); + /** * @defgroup Ecore_Drm2_Output_Group Drm output functions * @@ -356,6 +379,18 @@ EAPI Ecore_Drm2_Fb *ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output); */ EAPI void ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb); +/** + * Get the size of the crtc for a given output + * + * @param output + * @param *w + * @param *h + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_crtc_size_get(Ecore_Drm2_Output *output, int *w, int *h); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index 9e7d7a6063..4b3afea2b1 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -226,3 +226,36 @@ ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y) elput_input_pointer_xy_set(device->em, NULL, x, y); } + +EAPI void +ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window) +{ + const Eina_List *seats, *l; + const Eina_List *devs, *ll; + Elput_Seat *seat; + Elput_Device *dev; + + EINA_SAFETY_ON_NULL_RETURN(device); + EINA_SAFETY_ON_NULL_RETURN(device->em); + + seats = elput_manager_seats_get(device->em); + if (!seats) return; + + EINA_LIST_FOREACH(seats, l, seat) + { + devs = elput_input_devices_get(seat); + if (!devs) continue; + + EINA_LIST_FOREACH(devs, ll, dev) + elput_device_window_set(dev, window); + } +} + +EAPI void +ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + EINA_SAFETY_ON_NULL_RETURN(device->em); + + elput_input_pointer_max_set(device->em, w, h); +} diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 6443ecaf1a..9922cd7f82 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -898,3 +898,22 @@ ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb) EINA_SAFETY_ON_NULL_RETURN(output); output->next = fb; } + +EAPI void +ecore_drm2_output_crtc_size_get(Ecore_Drm2_Output *output, int *w, int *h) +{ + drmModeCrtcPtr crtc; + + if (w) *w = 0; + if (h) *h = 0; + + EINA_SAFETY_ON_NULL_RETURN(output); + + crtc = drmModeGetCrtc(output->fd, output->crtc_id); + if (!crtc) return; + + if (w) *w = crtc->width; + if (h) *h = crtc->height; + + drmModeFreeCrtc(crtc); +} From ccb573ec7b460326e5d45ce2a3f9ac7a7470e335 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Tue, 3 May 2016 12:02:20 -0400 Subject: [PATCH 08/35] evas-engines: Port evas drm engines to use Ecore_Drm2 library This patch ports the evas drm and gl_drm engines to use the new Ecore_Drm2 library Signed-off-by: Chris Michael --- m4/evas_check_engine.m4 | 13 +- src/Makefile_Evas.am | 14 +- .../evas/engines/drm/Evas_Engine_Drm.h | 21 +- src/modules/evas/engines/drm/evas_engine.c | 102 ++-- src/modules/evas/engines/drm/evas_engine.h | 56 +- src/modules/evas/engines/drm/evas_outbuf.c | 512 +++++++++++++----- .../evas/engines/gl_drm/Evas_Engine_GL_Drm.h | 6 +- src/modules/evas/engines/gl_drm/evas_engine.c | 70 ++- src/modules/evas/engines/gl_drm/evas_engine.h | 24 +- src/modules/evas/engines/gl_drm/evas_outbuf.c | 195 +++++-- 10 files changed, 710 insertions(+), 303 deletions(-) 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], [ requirement="" -have_dep="yes" +have_dep="no" have_hw_dep="no" evas_engine_[]$1[]_cflags="" evas_engine_[]$1[]_libs="" +PKG_CHECK_EXISTS([libdrm], + [ + have_dep="yes" + requirement="libdrm" + ], [have_dep="no"]) + if test "x${have_dep}" = "xyes" ; then if test "x$3" = "xstatic" ; then requirements_pc_evas="${requirement} ${requirements_pc_evas}" requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}" else + PKG_CHECK_MODULES([DRM], [${requirement}]) evas_engine_[]$1[]_cflags="${DRM_CFLAGS}" evas_engine_[]$1[]_libs="${DRM_LIBS}" fi @@ -636,10 +643,10 @@ else AC_MSG_ERROR([We currently do not support GL DRM without OpenGL ES. Please consider OpenGL ES if you want to use it.]) fi -PKG_CHECK_EXISTS([egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION], +PKG_CHECK_EXISTS([egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION], [ have_dep="yes" - requirement="egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION" + requirement="egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION" ], [have_dep="no"]) 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 endif if BUILD_ENGINE_DRM -dist_installed_evasmainheaders_DATA += modules/evas/engines/drm/Evas_Engine_Drm.h DRM_SOURCES = \ modules/evas/engines/drm/evas_outbuf.c \ modules/evas/engines/drm/evas_engine.c \ @@ -1301,20 +1300,19 @@ modules_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_srcdir)/src/lib/evas/cserve2 \ -I$(top_srcdir)/src/modules/evas/engines/drm \ @EVAS_CFLAGS@ \ -@ECORE_DRM_CFLAGS@ \ +@ECORE_DRM2_CFLAGS@ \ @evas_engine_drm_cflags@ modules_evas_engines_drm_module_la_LIBADD = \ @USE_EVAS_LIBS@ \ -@USE_ECORE_DRM_LIBS@ \ +@USE_ECORE_DRM2_LIBS@ \ @evas_engine_drm_libs@ -modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@ +modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@ modules_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static endif endif if BUILD_ENGINE_GL_DRM -dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h GL_DRM_SOURCES = \ modules/evas/engines/gl_drm/evas_outbuf.c \ modules/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 \ -I$(top_srcdir)/src/lib/evas/cserve2 \ -I$(top_srcdir)/src/modules/evas/engines/gl_drm \ @EVAS_CFLAGS@ \ -@ECORE_DRM_CFLAGS@ \ +@ECORE_DRM2_CFLAGS@ \ @evas_engine_gl_drm_cflags@ modules_evas_engines_gl_drm_module_la_LIBADD = \ @USE_EVAS_LIBS@ \ -@USE_ECORE_DRM_LIBS@ \ +@USE_ECORE_DRM2_LIBS@ \ @evas_engine_gl_drm_libs@ -modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@ +modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@ modules_evas_engines_gl_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static endif diff --git a/src/modules/evas/engines/drm/Evas_Engine_Drm.h b/src/modules/evas/engines/drm/Evas_Engine_Drm.h index 136eb919db..457db625e7 100644 --- a/src/modules/evas/engines/drm/Evas_Engine_Drm.h +++ b/src/modules/evas/engines/drm/Evas_Engine_Drm.h @@ -1,11 +1,7 @@ #ifndef _EVAS_ENGINE_DRM_H # define _EVAS_ENGINE_DRM_H -# include - -typedef struct _Evas_Engine_Info_Drm Evas_Engine_Info_Drm; - -struct _Evas_Engine_Info_Drm +typedef struct _Evas_Engine_Info_Drm { /* PRIVATE - don't mess with this baby or evas will poke its tongue out */ /* at you and make nasty noises */ @@ -13,18 +9,17 @@ struct _Evas_Engine_Info_Drm struct { - unsigned int rotation, depth; - Eina_Bool destination_alpha : 1; + int fd; + int depth, bpp; + unsigned int format, rotation; + + void *output; + Eina_Bool alpha : 1; Eina_Bool vsync : 1; - - unsigned int crtc_id, conn_id, buffer_id; - - Eina_Bool use_hw_accel : 1; - Ecore_Drm_Device *dev; } info; /* non-blocking or blocking mode */ Evas_Engine_Render_Mode render_mode; -}; +} Evas_Engine_Info_Drm; #endif diff --git a/src/modules/evas/engines/drm/evas_engine.c b/src/modules/evas/engines/drm/evas_engine.c index 40365a99f1..e3cd01e576 100644 --- a/src/modules/evas/engines/drm/evas_engine.c +++ b/src/modules/evas/engines/drm/evas_engine.c @@ -1,65 +1,57 @@ #include "evas_engine.h" -/* local structures */ -typedef struct _Render_Engine Render_Engine; - -struct _Render_Engine +typedef struct _Render_Engine { Render_Engine_Software_Generic generic; -}; +} Render_Engine; -/* function tables - filled in later (func and parent func) */ static Evas_Func func, pfunc; -/* external variables */ int _evas_engine_drm_log_dom; -/* local functions */ -static void * -_output_setup(Evas_Engine_Info_Drm *info, int w, int h) +static Render_Engine * +_render_engine_setup(Evas_Engine_Info_Drm *info, int w, int h) { - Render_Engine *re = NULL; + Render_Engine *re; Outbuf *ob; - /* try to allocate space for our render engine structure */ - if (!(re = calloc(1, sizeof(Render_Engine)))) - goto on_error; + re = calloc(1, sizeof(Render_Engine)); + if (!re) return NULL; - /* try to create new outbuf */ - if (!(ob = evas_outbuf_setup(info, w, h))) - goto on_error; + ob = _outbuf_setup(info, w, h); + if (!ob) goto err; if (!evas_render_engine_software_generic_init(&re->generic, ob, - evas_outbuf_buffer_state_get, - evas_outbuf_rot_get, - evas_outbuf_reconfigure, NULL, - evas_outbuf_update_region_new, - evas_outbuf_update_region_push, - evas_outbuf_update_region_free, - NULL, evas_outbuf_flush, - evas_outbuf_free, + _outbuf_state_get, + _outbuf_rotation_get, + _outbuf_reconfigure, + NULL, + _outbuf_update_region_new, + _outbuf_update_region_push, + _outbuf_update_region_free, + NULL, + _outbuf_flush, + _outbuf_free, ob->w, ob->h)) - goto on_error; + goto init_err; - /* return the allocated render_engine structure */ return re; - on_error: - if (re) evas_render_engine_software_generic_clean(&re->generic); - +init_err: + evas_render_engine_software_generic_clean(&re->generic); +err: free(re); return NULL; } -/* engine api functions */ static void * eng_info(Evas *evas EINA_UNUSED) { Evas_Engine_Info_Drm *info; /* try to allocate space for our engine info structure */ - if (!(info = calloc(1, sizeof(Evas_Engine_Info_Drm)))) - return NULL; + info = calloc(1, sizeof(Evas_Engine_Info_Drm)); + if (!info) return NULL; /* set some engine default properties */ info->magic.magic = rand(); @@ -74,55 +66,47 @@ eng_info_free(Evas *evas EINA_UNUSED, void *einfo) Evas_Engine_Info_Drm *info; /* free the engine info */ - if ((info = (Evas_Engine_Info_Drm *)einfo)) - free(info); + info = (Evas_Engine_Info_Drm *)einfo; + free(info); } static int eng_setup(Evas *evas, void *einfo) { - Evas_Engine_Info_Drm *info; - Evas_Public_Data *epd; Render_Engine *re; + Evas_Public_Data *epd; + Evas_Engine_Info_Drm *info; - /* try to cast to our engine info structure */ - if (!(info = (Evas_Engine_Info_Drm *)einfo)) return 0; + info = (Evas_Engine_Info_Drm *)einfo; + if (!info) return 0; - /* try to get the evas public data */ - if (!(epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS))) return 0; + epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS); + if (!epd) return 0; - /* check for valid engine output */ - if (!(re = epd->engine.data.output)) + re = epd->engine.data.output; + if (!re) { - /* NB: If we have no valid output then assume we have not been - * initialized yet and call any needed common init routines */ evas_common_init(); - /* try to create a new render_engine */ - if (!(re = _output_setup(info, epd->output.w, epd->output.h))) - return 0; + re = _render_engine_setup(info, epd->output.w, epd->output.h); + if (!re) return 0; } else { Outbuf *ob; - /* try to create a new outbuf */ - ob = evas_outbuf_setup(info, epd->output.w, epd->output.h); + ob = _outbuf_setup(info, epd->output.w, epd->output.h); if (!ob) return 0; - /* if we have an existing outbuf, free it */ - evas_render_engine_software_generic_update(&re->generic, ob, + evas_render_engine_software_generic_update(&re->generic, ob, ob->w, ob->h); } - /* reassign engine output */ epd->engine.data.output = re; if (!epd->engine.data.output) return 0; - /* check for valid engine context */ if (!epd->engine.data.context) { - /* create a context if needed */ epd->engine.data.context = epd->engine.func->context_new(epd->engine.data.output); } @@ -135,7 +119,8 @@ eng_output_free(void *data) { Render_Engine *re; - if ((re = data)) + re = data; + if (re) { evas_render_engine_software_generic_clean(&re->generic); free(re); @@ -144,7 +129,6 @@ eng_output_free(void *data) evas_common_shutdown(); } -/* module api functions */ static int module_open(Evas_Module *em) { @@ -165,6 +149,8 @@ module_open(Evas_Module *em) return 0; } + ecore_init(); + /* store parent functions */ func = pfunc; @@ -185,6 +171,8 @@ module_close(Evas_Module *em EINA_UNUSED) { /* unregister the eina log domain for this engine */ eina_log_domain_unregister(_evas_engine_drm_log_dom); + + ecore_shutdown(); } static Evas_Module_Api evas_modapi = diff --git a/src/modules/evas/engines/drm/evas_engine.h b/src/modules/evas/engines/drm/evas_engine.h index d5139117ee..a1925b939e 100644 --- a/src/modules/evas/engines/drm/evas_engine.h +++ b/src/modules/evas/engines/drm/evas_engine.h @@ -6,8 +6,13 @@ # include "evas_private.h" # include "Evas.h" # include "Evas_Engine_Drm.h" +# include +# include +# include +# include +# include -#include "../software_generic/Evas_Engine_Software_Generic.h" +# include "../software_generic/Evas_Engine_Software_Generic.h" extern int _evas_engine_drm_log_dom; @@ -36,35 +41,44 @@ extern int _evas_engine_drm_log_dom; # endif # define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_drm_log_dom, __VA_ARGS__) +typedef struct _Outbuf_Fb +{ + int age; + Ecore_Drm2_Fb *fb; + + Eina_Bool valid : 1; + Eina_Bool drawn : 1; + Eina_Bool busy : 1; +} Outbuf_Fb; + struct _Outbuf { - Evas_Engine_Info_Drm *info; - - int w, h; - int rotation; - unsigned int depth; + int fd, w, h, bpp, rotation; + unsigned int depth, format; struct { - Ecore_Drm_Fb *buffer[4]; - - Eina_List *pending_writes; - - int curr, last, num; + int num; + Outbuf_Fb ofb[4], *current; + Ecore_Drm2_Output *output; + Eina_List *pending; } priv; - Eina_Bool destination_alpha : 1; + drmEventContext ctx; + Ecore_Fd_Handler *hdlr; + + Eina_Bool alpha : 1; Eina_Bool vsync : 1; }; -Outbuf *evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h); -void evas_outbuf_free(Outbuf *ob); -void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth); -Render_Engine_Swap_Mode evas_outbuf_buffer_state_get(Outbuf *ob); -int evas_outbuf_rot_get(Outbuf *ob); -void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); -void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); -void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); -void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); +Outbuf *_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h); +void _outbuf_free(Outbuf *ob); +int _outbuf_rotation_get(Outbuf *ob); +void _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth); +Render_Engine_Swap_Mode _outbuf_state_get(Outbuf *ob); +void *_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); +void _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); +void _outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); +void _outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); #endif diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c index 64b3ba9a52..4c87f2df2f 100644 --- a/src/modules/evas/engines/drm/evas_outbuf.c +++ b/src/modules/evas/engines/drm/evas_outbuf.c @@ -8,183 +8,430 @@ #define GREEN_MASK 0x00ff00 #define BLUE_MASK 0x0000ff -static void -_evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) +static void _outbuf_tick_schedule(int fd, void *data); + +static Eina_Bool ticking = EINA_FALSE; + +static void +_outbuf_tick_begin(void *data) { - Ecore_Drm_Fb *buff; + Outbuf *ob; - buff = ob->priv.buffer[ob->priv.curr]; + ob = data; + ticking = EINA_TRUE; + if (ob) _outbuf_tick_schedule(ob->fd, ob); +} - /* mark the fb as dirty */ - ecore_drm_fb_dirty(buff, rects, count); +static void +_outbuf_tick_end(void *data EINA_UNUSED) +{ + ticking = EINA_FALSE; +} - /* send this buffer to the crtc */ - ecore_drm_fb_send(ob->info->info.dev, buff, NULL, NULL); +static void +_outbuf_tick_source_set(Outbuf *ob) +{ + if (ob) + { + ecore_animator_custom_source_tick_begin_callback_set + (_outbuf_tick_begin, ob); + ecore_animator_custom_source_tick_end_callback_set + (_outbuf_tick_end, ob); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); + } + else + { + ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL); + ecore_animator_custom_source_tick_end_callback_set(NULL, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + } +} - ob->priv.last = ob->priv.curr; - ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num; +static void +_outbuf_tick_schedule(int fd EINA_UNUSED, void *data) +{ + Outbuf *ob; + Outbuf_Fb *ofb; + + ob = data; + if (!ticking) return; + + ofb = ob->priv.current; + if (!ofb) return; + + drmVBlank vbl = + { + .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + .request.sequence = 1, + .request.signal = (unsigned long)data, + }; + + if (drmWaitVBlank(fd, &vbl) < 0) + _outbuf_tick_source_set(NULL); +} + +static void +_cb_vblank(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + ecore_animator_custom_tick(); + if (ticking) _outbuf_tick_schedule(fd, data); +} + +static void +_cb_pageflip(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + Outbuf *ob; + Outbuf_Fb *ofb; + Ecore_Drm2_Fb *next; + + ob = data; + + ofb = ob->priv.current; + if (ofb) ofb->busy = EINA_FALSE; + + next = ecore_drm2_output_next_fb_get(ob->priv.output); + if (next) + { + ecore_drm2_output_next_fb_set(ob->priv.output, NULL); + if (ecore_drm2_fb_flip(next, ob->priv.output, ob) < 0) + _outbuf_tick_source_set(NULL); + } +} + +static Eina_Bool +_cb_drm_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + Outbuf *ob; + int ret; + + ob = data; + ret = drmHandleEvent(ob->fd, &ob->ctx); + if (ret) + { + WRN("drmHandleEvent failed to read an event"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static void +_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) +{ + /* Ecore_Drm2_Plane *plane; */ + Outbuf_Fb *ofb; + + ofb = ob->priv.current; + if (!ofb) return; + + ecore_drm2_fb_dirty(ofb->fb, rects, count); + if (ecore_drm2_fb_flip(ofb->fb, ob->priv.output, ob) < 0) + { + _outbuf_tick_source_set(NULL); + return; + } + + ofb->busy = EINA_TRUE; + ofb->drawn = EINA_TRUE; + ofb->age = 0; + + /* plane = ecore_drm2_plane_find(ob->priv.output, ofb->fb, ob->format); */ + /* if (plane) */ + /* { */ + /* drmVBlank vbl = */ + /* { */ + /* .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, */ + /* .request.sequence = 1, */ + /* }; */ + + /* vbl.request.type |= ecore_drm2_output_vblank_get(ob->priv.output); */ + /* vbl.request.signal = (unsigned long)ofb; */ + + /* ecore_drm2_fb_dirty(ofb->fb, rects, count); */ + + /* if (!ecore_drm2_plane_fb_set(plane, ofb->fb)) */ + /* { */ + /* ERR("Failed to set FB on Plane"); */ + /* return; */ + /* } */ + + /* if (drmWaitVBlank(ob->fd, &vbl) < 0) */ + /* { */ + /* _outbuf_tick_source_set(NULL); */ + /* return; */ + /* } */ + + /* ofb->busy = EINA_TRUE; */ + /* ofb->drawn = EINA_TRUE; */ + /* ofb->age = 0; */ + + /* ob->priv.current = NULL; */ + /* } */ + /* else */ + /* WRN("Could not find a plane for this framebuffer"); */ +} + +static Eina_Bool +_outbuf_fb_create(Outbuf *ob, Outbuf_Fb *ofb) +{ + ofb->fb = + ecore_drm2_fb_create(ob->fd, ob->w, ob->h, + ob->depth, ob->bpp, ob->format); + if (!ofb->fb) return EINA_FALSE; + + ofb->age = 0; + ofb->busy = EINA_FALSE; + ofb->drawn = EINA_FALSE; + ofb->valid = EINA_TRUE; + + return EINA_TRUE; +} + +static void +_outbuf_fb_destroy(Outbuf_Fb *ofb) +{ + ecore_drm2_fb_destroy(ofb->fb); + + memset(ofb, 0, sizeof(*ofb)); + ofb->valid = EINA_FALSE; + ofb->busy = EINA_FALSE; + ofb->drawn = EINA_FALSE; + ofb->age = 0; } Outbuf * -evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h) +_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h) { Outbuf *ob; char *num; int i = 0; - /* try to allocate space for outbuf */ - if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL; + ob = calloc(1, sizeof(Outbuf)); + if (!ob) return NULL; - /* set properties of outbuf */ ob->w = w; ob->h = h; - - ob->info = info; - ob->depth = info->info.depth; + ob->fd = info->info.fd; + ob->alpha = info->info.alpha; ob->rotation = info->info.rotation; - ob->destination_alpha = info->info.destination_alpha; - ob->vsync = info->info.vsync; - /* we must triple-buffer to prevent problems with the page flip handler */ + ob->bpp = info->info.bpp; + ob->depth = info->info.depth; + ob->format = info->info.format; + + ob->priv.output = info->info.output; + ob->priv.num = 3; - /* check for buffer override */ - if ((num = getenv("EVAS_DRM_BUFFERS"))) + num = getenv("EVAS_DRM_BUFFERS"); + if (num) { ob->priv.num = atoi(num); - if (ob->priv.num <= 0) ob->priv.num = 1; + if (ob->priv.num <= 0) ob->priv.num = 3; else if (ob->priv.num > 4) ob->priv.num = 4; } - /* check for vsync override */ - if ((num = getenv("EVAS_DRM_VSYNC"))) - ob->vsync = atoi(num); - - /* try to create buffers */ - for (; i < ob->priv.num; i++) + for (i = 0; i < ob->priv.num; i++) { - ob->priv.buffer[i] = - ecore_drm_fb_create(ob->info->info.dev, ob->w, ob->h); - if (!ob->priv.buffer[i]) + if (!_outbuf_fb_create(ob, &(ob->priv.ofb[i]))) { - ERR("Failed to create buffer %d", i); - break; + WRN("Failed to create framebuffer %d", i); + continue; } - - DBG("Evas Engine Created Dumb Buffer"); - DBG("\tFb: %d", ob->priv.buffer[i]->id); - DBG("\tHandle: %d", ob->priv.buffer[i]->hdl); - DBG("\tStride: %d", ob->priv.buffer[i]->stride); - DBG("\tSize: %d", ob->priv.buffer[i]->size); - DBG("\tW: %d\tH: %d", - ob->priv.buffer[i]->w, ob->priv.buffer[i]->h); } - /* set the front buffer to be the one on the crtc */ - ecore_drm_fb_send(info->info.dev, ob->priv.buffer[0], NULL, NULL); + /* setup vblank handler */ + memset(&ob->ctx, 0, sizeof(ob->ctx)); + ob->ctx.version = DRM_EVENT_CONTEXT_VERSION; + ob->ctx.vblank_handler = _cb_vblank; + ob->ctx.page_flip_handler = _cb_pageflip; + + ob->hdlr = + ecore_main_fd_handler_add(ob->fd, ECORE_FD_READ, _cb_drm_event, ob, + NULL, NULL); + + _outbuf_tick_source_set(ob); return ob; } void -evas_outbuf_free(Outbuf *ob) +_outbuf_free(Outbuf *ob) { int i = 0; - /* destroy the old buffers */ - for (; i < ob->priv.num; i++) - ecore_drm_fb_destroy(ob->priv.buffer[i]); + for (i = 0; i < ob->priv.num; i++) + _outbuf_fb_destroy(&ob->priv.ofb[i]); + + ecore_main_fd_handler_del(ob->hdlr); - /* free allocate space for outbuf */ free(ob); } +int +_outbuf_rotation_get(Outbuf *ob) +{ + return ob->rotation; +} + void -evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth) +_outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth) { int i = 0; + unsigned int format = DRM_FORMAT_ARGB8888; - /* check if we are inheriting the old buffer depth */ - if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth; + switch (depth) + { + case OUTBUF_DEPTH_RGB_16BPP_565_565_DITHERED: + format = DRM_FORMAT_RGB565; + break; + case OUTBUF_DEPTH_RGB_16BPP_555_555_DITHERED: + format = DRM_FORMAT_RGBX5551; + break; + case OUTBUF_DEPTH_RGB_16BPP_444_444_DITHERED: + format = DRM_FORMAT_RGBX4444; + break; + case OUTBUF_DEPTH_RGB_16BPP_565_444_DITHERED: + format = DRM_FORMAT_RGB565; + break; + case OUTBUF_DEPTH_RGB_32BPP_888_8888: + format = DRM_FORMAT_RGBX8888; + break; + case OUTBUF_DEPTH_ARGB_32BPP_8888_8888: + format = DRM_FORMAT_ARGB8888; + break; + case OUTBUF_DEPTH_BGRA_32BPP_8888_8888: + format = DRM_FORMAT_BGRA8888; + break; + case OUTBUF_DEPTH_BGR_32BPP_888_8888: + format = DRM_FORMAT_BGRX8888; + break; + case OUTBUF_DEPTH_RGB_24BPP_888_888: + format = DRM_FORMAT_RGB888; + break; + case OUTBUF_DEPTH_BGR_24BPP_888_888: + format = DRM_FORMAT_BGR888; + break; + case OUTBUF_DEPTH_INHERIT: + default: + depth = ob->depth; + format = ob->format; + break; + } - /* check for changes */ - if ((ob->w == w) && (ob->h == h) && - (ob->destination_alpha == ob->info->info.destination_alpha) && - (ob->rotation == rot) && - (ob->depth == depth)) + if ((ob->w == w) && (ob->h == h) && (ob->rotation == rotation) && + (ob->depth == depth) && (ob->format == format)) return; - /* set new outbuf properties */ - ob->rotation = rot; ob->depth = depth; - ob->destination_alpha = ob->info->info.destination_alpha; + ob->format = format; + ob->rotation = rotation; - /* handle rotation */ - if ((ob->rotation == 0) || (ob->rotation == 180)) - { - ob->w = w; - ob->h = h; - } - else + ob->w = w; + ob->h = h; + if ((ob->rotation == 90) || (ob->rotation == 270)) { ob->w = h; ob->h = w; } - /* destroy the old buffers */ - for (; i < ob->priv.num; i++) - ecore_drm_fb_destroy(ob->priv.buffer[i]); + for (i = 0; i < ob->priv.num; i++) + _outbuf_fb_destroy(&ob->priv.ofb[i]); for (i = 0; i < ob->priv.num; i++) { - ob->priv.buffer[i] = - ecore_drm_fb_create(ob->info->info.dev, ob->w, ob->h); - if (!ob->priv.buffer[i]) + if (!_outbuf_fb_create(ob, &(ob->priv.ofb[i]))) { - ERR("Failed to create buffer %d", i); - break; + WRN("Failed to create framebuffer %d", i); + continue; } } } -Render_Engine_Swap_Mode -evas_outbuf_buffer_state_get(Outbuf *ob) +static Outbuf_Fb * +_outbuf_fb_wait(Outbuf *ob) { - int delta; + int iter = 0, i = 0; - /* check for valid output buffer */ - if (!ob) return MODE_FULL; - - delta = (ob->priv.last - ob->priv.curr + ob->priv.num) % ob->priv.num; - - /* This is the number of frame since last frame */ - switch (delta) + while (iter++ < 10) { - case 0: - return MODE_COPY; - case 1: - return MODE_DOUBLE; - case 2: - return MODE_TRIPLE; - case 3: - return MODE_QUADRUPLE; - default: - return MODE_FULL; + for (i = 0; i < ob->priv.num; i++) + { + if (ob->priv.ofb[i].busy) continue; + if (ob->priv.ofb[i].valid) return &(ob->priv.ofb[i]); + } + + drmHandleEvent(ob->fd, &ob->ctx); } + + return NULL; +} + +static Eina_Bool +_outbuf_fb_assign(Outbuf *ob) +{ + int i; + + ob->priv.current = _outbuf_fb_wait(ob); + + if (!ob->priv.current) + { + WRN("No Free Buffers. Dropping a frame"); + for (i = 0; i < ob->priv.num; i++) + { + if (ob->priv.ofb[i].valid) + { + ob->priv.ofb[i].age = 0; + ob->priv.ofb[i].drawn = EINA_FALSE; + } + } + + return EINA_FALSE; + } + + for (i = 0; i < ob->priv.num; i++) + { + if ((ob->priv.ofb[i].valid) && (ob->priv.ofb[i].drawn)) + { + ob->priv.ofb[i].age++; + if (ob->priv.ofb[i].age > ob->priv.num) + { + ob->priv.ofb[i].age = 0; + ob->priv.ofb[i].drawn = EINA_FALSE; + } + } + } + + return EINA_TRUE; +} + +Render_Engine_Swap_Mode +_outbuf_state_get(Outbuf *ob) +{ + int age; + + if (!_outbuf_fb_assign(ob)) return MODE_FULL; + + age = ob->priv.current->age; + if (age > ob->priv.num) return MODE_FULL; + else if (age == 1) return MODE_COPY; + else if (age == 2) return MODE_DOUBLE; + else if (age == 3) return MODE_TRIPLE; + else if (age == 4) return MODE_QUADRUPLE; + + return MODE_FULL; } void * -evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch) +_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch) { RGBA_Image *img = NULL; if ((w <= 0) || (h <= 0)) return NULL; - /* DBG("Outbuf Region New: %d %d %d %d", x, y, w, h); */ - RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h); - if ((ob->rotation == 0) && (ob->depth == 32)) + if ((ob->rotation == 0))// && (ob->depth == 32)) { Eina_Rectangle *rect; @@ -204,7 +451,7 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i return NULL; } - img->cache_entry.flags.alpha = ob->destination_alpha; + img->cache_entry.flags.alpha = ob->alpha; #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) @@ -221,48 +468,52 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i if (ch) *ch = h; /* add this cached image data to pending writes */ - ob->priv.pending_writes = - eina_list_append(ob->priv.pending_writes, img); + ob->priv.pending = + eina_list_append(ob->priv.pending, img); } return img; } -void -evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h) +void +_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h) { Gfx_Func_Convert func = NULL; Eina_Rectangle rect = {0, 0, 0, 0}, pr; DATA32 *src; DATA8 *dst; - Ecore_Drm_Fb *buff; + Ecore_Drm2_Fb *buff; int bpp = 0, bpl = 0; int rx = 0, ry = 0; + int bw = 0, bh = 0; /* check for valid output buffer */ if (!ob) return; /* check for pending writes */ - if (!ob->priv.pending_writes) return; + if (!ob->priv.pending) return; /* check for valid source data */ if (!(src = update->image.data)) return; /* check for valid desination data */ - buff = ob->priv.buffer[ob->priv.curr]; - if (!(dst = buff->mmap)) return; + if (!ob->priv.current) return; + buff = ob->priv.current->fb; + + dst = ecore_drm2_fb_data_get(buff); + if (!dst) return; if ((ob->rotation == 0) || (ob->rotation == 180)) { func = - evas_common_convert_func_get(0, w, h, ob->depth, + evas_common_convert_func_get(0, w, h, ob->bpp, RED_MASK, GREEN_MASK, BLUE_MASK, PAL_MODE_NONE, ob->rotation); } else if ((ob->rotation == 90) || (ob->rotation == 270)) { func = - evas_common_convert_func_get(0, h, w, ob->depth, + evas_common_convert_func_get(0, h, w, ob->bpp, RED_MASK, GREEN_MASK, BLUE_MASK, PAL_MODE_NONE, ob->rotation); } @@ -304,15 +555,18 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int rect.h = w; } - bpp = (ob->depth / 8); - if (bpp <= 0) return; + bpp = ob->bpp / 8; + bw = ob->w; + bh = ob->h; + /* bpp = (ob->depth / 8); */ + /* if (bpp <= 0) return; */ - bpl = buff->stride; + bpl = ecore_drm2_fb_stride_get(buff); if (ob->rotation == 0) { RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); dst += (bpl * rect.y) + (rect.x * bpp); w -= rx; } @@ -320,7 +574,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); rx = pr.w - rect.w; ry = pr.h - rect.h; src += (update->cache_entry.w * ry) + rx; @@ -330,7 +584,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); rx = pr.w - rect.w; ry = pr.h - rect.h; src += ry; w -= ry; @@ -339,7 +593,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); rx = pr.w - rect.w; ry = pr.h - rect.h; src += (update->cache_entry.w * rx); w -= ry; @@ -352,13 +606,13 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int } void -evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED) +_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED) { - /* evas_cache_image_drop(&update->cache_entry); */ + } void -evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode) +_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode) { Eina_Rectangle *r; RGBA_Image *img; @@ -367,19 +621,21 @@ evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; /* get number of pending writes */ - n = eina_list_count(ob->priv.pending_writes); + n = eina_list_count(ob->priv.pending); if (n == 0) return; /* allocate rectangles */ - if (!(r = alloca(n * sizeof(Eina_Rectangle)))) return; + r = alloca(n * sizeof(Eina_Rectangle)); + if (!r) return; /* loop the pending writes */ - EINA_LIST_FREE(ob->priv.pending_writes, img) + EINA_LIST_FREE(ob->priv.pending, img) { Eina_Rectangle *rect; int x = 0, y = 0, w = 0, h = 0; - if (!(rect = img->extended_info)) continue; + rect = img->extended_info; + if (!rect) continue; x = rect->x; y = rect->y; w = rect->w; h = rect->h; @@ -430,11 +686,5 @@ evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode } /* force a buffer swap */ - _evas_outbuf_buffer_swap(ob, r, n); -} - -int -evas_outbuf_rot_get(Outbuf *ob) -{ - return ob->rotation; + _outbuf_buffer_swap(ob, r, n); } diff --git a/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h index 71ab60cefc..514aa80c09 100644 --- a/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h +++ b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h @@ -1,7 +1,7 @@ #ifndef _EVAS_ENGINE_GL_DRM_H # define _EVAS_ENGINE_GL_DRM_H -# include +# include # include typedef enum _Evas_Engine_Info_GL_Drm_Swap_Mode @@ -26,11 +26,11 @@ struct _Evas_Engine_Info_GL_Drm { struct gbm_device *gbm; + int fd, bpp; unsigned int rotation, depth; - unsigned int crtc_id, conn_id, buffer_id; unsigned int format, flags; - Ecore_Drm_Device *dev; + void *output; Eina_Bool destination_alpha : 1; Eina_Bool vsync : 1; diff --git a/src/modules/evas/engines/gl_drm/evas_engine.c b/src/modules/evas/engines/gl_drm/evas_engine.c index d8d4312aee..29f2e0c533 100644 --- a/src/modules/evas/engines/gl_drm/evas_engine.c +++ b/src/modules/evas/engines/gl_drm/evas_engine.c @@ -118,12 +118,9 @@ static const EVGL_Interface evgl_funcs = Eina_Bool eng_gbm_init(Evas_Engine_Info_GL_Drm *info) { - Ecore_Drm_Device *dev; - if (!info) return EINA_FALSE; - if (!(dev = info->info.dev)) return EINA_FALSE; - if (!(info->info.gbm = gbm_create_device(dev->drm.fd))) + if (!(info->info.gbm = gbm_create_device(info->info.fd))) { ERR("Coult not create gbm device"); return EINA_FALSE; @@ -146,13 +143,6 @@ eng_gbm_shutdown(Evas_Engine_Info_GL_Drm *info) return EINA_TRUE; } -/* local inline functions */ -static inline Outbuf * -eng_get_ob(Render_Engine *re) -{ - return re->generic.software.ob; -} - /* local functions */ static void gl_symbols(void) @@ -362,6 +352,8 @@ evgl_eng_native_window_create(void *data) Render_Engine *re; struct gbm_surface *surface; Evas_Engine_Info_GL_Drm *info; + unsigned int format = GBM_FORMAT_XRGB8888; + unsigned int flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; re = (Render_Engine *)data; if (!re) @@ -377,9 +369,9 @@ evgl_eng_native_window_create(void *data) return NULL; } - surface = gbm_surface_create(info->info.gbm, - eng_get_ob(re)->w, eng_get_ob(re)->h, - info->info.format, info->info.flags); + surface = + gbm_surface_create(info->info.gbm, + eng_get_ob(re)->w, eng_get_ob(re)->h, format, flags); if (!surface) { ERR("Could not create gl drm window"); @@ -786,6 +778,37 @@ _native_cb_free(void *image) free(n); } +static void +_cb_vblank(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + evas_outbuf_vblank(data, fd); +} + +static void +_cb_page_flip(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + evas_outbuf_page_flip(data, fd); +} + +static Eina_Bool +_cb_drm_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + Render_Engine *re; + int ret; + + re = data; + if (!re) return EINA_TRUE; + + ret = drmHandleEvent(re->fd, &re->ctx); + if (ret) + { + ERR("drmHandleEvent failed to read an event: %m"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + /* engine specific override functions */ static void * eng_info(Evas *eo_e EINA_UNUSED) @@ -899,6 +922,17 @@ eng_setup(Evas *evas, void *in) return 0; } + re->fd = info->info.fd; + + memset(&re->ctx, 0, sizeof(re->ctx)); + re->ctx.version = DRM_EVENT_CONTEXT_VERSION; + re->ctx.vblank_handler = _cb_vblank; + re->ctx.page_flip_handler = _cb_page_flip; + + re->hdlr = + ecore_main_fd_handler_add(info->info.fd, ECORE_FD_READ, + _cb_drm_event, re, NULL, NULL); + /* try to create new outbuf */ ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode); if (!ob) @@ -970,16 +1004,16 @@ eng_setup(Evas *evas, void *in) re->generic.software.ob = NULL; gl_wins--; + if (ob_old) evas_outbuf_free(ob_old); + ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode); if (!ob) { - if (ob_old) evas_outbuf_free(ob_old); free(re); return 0; } evas_outbuf_use(ob); - if (ob_old) evas_outbuf_free(ob_old); ob->evas = evas; @@ -1439,6 +1473,8 @@ module_open(Evas_Module *em) return 0; } + ecore_init(); + /* store it for later use */ func = pfunc; @@ -1471,6 +1507,8 @@ module_close(Evas_Module *em EINA_UNUSED) /* unregister the eina log domain for this engine */ eina_log_domain_unregister(_evas_engine_gl_drm_log_dom); _evas_engine_gl_drm_log_dom = -1; + + ecore_shutdown(); } static Evas_Module_Api evas_modapi = diff --git a/src/modules/evas/engines/gl_drm/evas_engine.h b/src/modules/evas/engines/gl_drm/evas_engine.h index f45a1995e6..8a51d59c93 100644 --- a/src/modules/evas/engines/gl_drm/evas_engine.h +++ b/src/modules/evas/engines/gl_drm/evas_engine.h @@ -7,6 +7,11 @@ # include "Evas.h" # include "Evas_Engine_GL_Drm.h" +# include +# include +# include +# include + # define EGL_EGLEXT_PROTOTYPES # define GL_GLEXT_PROTOTYPES @@ -64,6 +69,10 @@ typedef struct _Render_Engine Render_Engine; struct _Render_Engine { Render_Engine_GL_Generic generic; + + int fd; + drmEventContext ctx; + Ecore_Fd_Handler *hdlr; }; struct _Context_3D @@ -80,11 +89,10 @@ struct _Outbuf Evas *evas; // used for pre_swap, post_swap - int w, h; - unsigned int rotation, depth; + int fd, w, h, bpp; + unsigned int rotation, depth, format; Render_Engine_Swap_Mode swap_mode; - /* struct gbm_device *gbm; */ struct gbm_surface *surface; struct @@ -98,6 +106,7 @@ struct _Outbuf struct { struct gbm_bo *bo[2]; + Ecore_Drm2_Output *output; } priv; Eina_Bool destination_alpha : 1; @@ -123,6 +132,9 @@ void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); +void evas_outbuf_vblank(void *data, int fd); +void evas_outbuf_page_flip(void *data, int fd); + Evas_Engine_GL_Context* evas_outbuf_gl_context_get(Outbuf *ob); void *evas_outbuf_egl_display_get(Outbuf *ob); Context_3D *evas_outbuf_gl_context_new(Outbuf *ob); @@ -138,6 +150,12 @@ _re_wincheck(Outbuf *ob) return EINA_FALSE; } +static inline Outbuf * +eng_get_ob(Render_Engine *re) +{ + return re->generic.software.ob; +} + extern unsigned int (*glsym_eglSwapBuffersWithDamage)(EGLDisplay a, void *b, const EGLint *d, EGLint c); extern unsigned int (*glsym_eglSetDamageRegionKHR)(EGLDisplay a, EGLSurface b, EGLint *c, EGLint d); diff --git a/src/modules/evas/engines/gl_drm/evas_outbuf.c b/src/modules/evas/engines/gl_drm/evas_outbuf.c index b120216608..ad3f2a0414 100644 --- a/src/modules/evas/engines/gl_drm/evas_outbuf.c +++ b/src/modules/evas/engines/gl_drm/evas_outbuf.c @@ -5,12 +5,86 @@ static Outbuf *_evas_gl_drm_window = NULL; static EGLContext context = EGL_NO_CONTEXT; static int win_count = 0; +static Eina_Bool ticking = EINA_FALSE; #ifdef EGL_MESA_platform_gbm static PFNEGLGETPLATFORMDISPLAYEXTPROC dlsym_eglGetPlatformDisplayEXT = NULL; static PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC dlsym_eglCreatePlatformWindowSurfaceEXT = NULL; #endif +static void +_outbuf_tick_schedule(int fd, void *data) +{ + if (!ticking) return; + + drmVBlank vbl = + { + .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + .request.sequence = 1, + .request.signal = (unsigned long)data, + }; + + drmWaitVBlank(fd, &vbl); +} + +static void +_outbuf_tick_begin(void *data) +{ + Outbuf *ob; + + ob = data; + ticking = EINA_TRUE; + if (ob) _outbuf_tick_schedule(ob->fd, ob); +} + +static void +_outbuf_tick_end(void *data EINA_UNUSED) +{ + ticking = EINA_FALSE; +} + +static void +_outbuf_tick_source_set(Outbuf *ob) +{ + if (ob) + { + ecore_animator_custom_source_tick_begin_callback_set + (_outbuf_tick_begin, ob); + ecore_animator_custom_source_tick_end_callback_set + (_outbuf_tick_end, ob); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); + } + else + { + ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL); + ecore_animator_custom_source_tick_end_callback_set(NULL, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + } +} + +void +evas_outbuf_vblank(void *data, int fd) +{ + ecore_animator_custom_tick(); + if (ticking) _outbuf_tick_schedule(fd, data); +} + +void +evas_outbuf_page_flip(void *data, int fd EINA_UNUSED) +{ + Outbuf *ob; + Ecore_Drm2_Fb *next; + + ob = data; + next = ecore_drm2_output_next_fb_get(ob->priv.output); + if (next) + { + ecore_drm2_output_next_fb_set(ob->priv.output, NULL); + if (ecore_drm2_fb_flip(next, ob->priv.output, ob) < 0) + _outbuf_tick_source_set(NULL); + } +} + static void _evas_outbuf_gbm_surface_destroy(Outbuf *ob) { @@ -25,63 +99,51 @@ _evas_outbuf_gbm_surface_destroy(Outbuf *ob) static void _evas_outbuf_gbm_surface_create(Outbuf *ob, int w, int h) { + unsigned int format = GBM_FORMAT_XRGB8888; + unsigned int flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; + if (!ob) return; ob->surface = - gbm_surface_create(ob->info->info.gbm, w, h, - ob->info->info.format, ob->info->info.flags); + gbm_surface_create(ob->info->info.gbm, w, h, format, flags); if (!ob->surface) ERR("Failed to create gbm surface"); } static void -_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data) +_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo EINA_UNUSED, void *data) { - Ecore_Drm_Fb *fb; + Ecore_Drm2_Fb *fb; fb = data; - if (fb) - { - struct gbm_device *gbm; - - gbm = gbm_bo_get_device(bo); - drmModeRmFB(gbm_device_get_fd(gbm), fb->id); - free(fb); - } + if (fb) ecore_drm2_fb_destroy(fb); } -static Ecore_Drm_Fb * -_evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo) +static Ecore_Drm2_Fb * +_evas_outbuf_fb_get(Outbuf *ob, struct gbm_bo *bo) { - int ret; - Ecore_Drm_Fb *fb; - uint32_t format; - uint32_t handles[4], pitches[4], offsets[4]; + Ecore_Drm2_Fb *fb; + uint32_t format, hdl, stride; + int w, h; fb = gbm_bo_get_user_data(bo); if (fb) return fb; - if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL; - format = gbm_bo_get_format(bo); + w = gbm_bo_get_width(bo); + h = gbm_bo_get_height(bo); + hdl = gbm_bo_get_handle(bo).u32; + stride = gbm_bo_get_stride(bo); + /* fb->size = fb->stride * fb->h; */ - fb->w = gbm_bo_get_width(bo); - fb->h = gbm_bo_get_height(bo); - fb->hdl = gbm_bo_get_handle(bo).u32; - fb->stride = gbm_bo_get_stride(bo); - fb->size = fb->stride * fb->h; - - handles[0] = fb->hdl; - pitches[0] = fb->stride; - offsets[0] = 0; - - ret = drmModeAddFB2(dev->drm.fd, fb->w, fb->h, format, - handles, pitches, offsets, &(fb->id), 0); - if (ret) - ret = drmModeAddFB(dev->drm.fd, fb->w, fb->h, 24, 32, - fb->stride, fb->hdl, &(fb->id)); - - if (ret) ERR("FAILED TO ADD FB: %m"); + fb = + ecore_drm2_fb_gbm_create(ob->fd, w, h, ob->depth, ob->bpp, + format, hdl, stride); + if (!fb) + { + ERR("Failed to create FBO"); + return NULL; + } gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy); @@ -91,7 +153,9 @@ _evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo) static void _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) { - Ecore_Drm_Fb *fb; + Ecore_Drm2_Fb *fb; + + if (ob->priv.bo[1]) gbm_surface_release_buffer(ob->surface, ob->priv.bo[1]); /* Repulsive hack: Right now we don't actually have a proper way to retire * buffers because the ticker and the flip handler are out of sync, the @@ -106,15 +170,48 @@ _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) ob->priv.bo[0] = gbm_surface_lock_front_buffer(ob->surface); if (!ob->priv.bo[0]) { - WRN("Could not lock front buffer"); + WRN("Could not lock front buffer: %m"); return; } - fb = _evas_outbuf_fb_get(ob->info->info.dev, ob->priv.bo[0]); + + fb = _evas_outbuf_fb_get(ob, ob->priv.bo[0]); if (fb) { - ecore_drm_fb_dirty(fb, rects, count); - ecore_drm_fb_send(ob->info->info.dev, fb, NULL, NULL); + ecore_drm2_fb_dirty(fb, rects, count); + if (ecore_drm2_fb_flip(fb, ob->priv.output, ob) < 0) + _outbuf_tick_source_set(NULL); + + /* Ecore_Drm2_Plane *plane; */ + + /* plane = ecore_drm2_plane_find(ob->priv.output, fb, ob->format); */ + /* if (plane) */ + /* { */ + /* int ret; */ + /* drmVBlank vbl = */ + /* { */ + /* .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, */ + /* .request.sequence = 1, */ + /* }; */ + + /* vbl.request.type |= ecore_drm2_output_vblank_get(ob->priv.output); */ + /* vbl.request.signal = (unsigned long)ob; */ + + /* ecore_drm2_fb_dirty(fb, rects, count); */ + + /* if (!ecore_drm2_plane_fb_set(plane, fb)) */ + /* { */ + /* ERR("Failed to set FB on Plane"); */ + /* return; */ + /* } */ + + /* ret = drmWaitVBlank(ob->fd, &vbl); */ + /* if (ret) return; */ + /* } */ + /* else */ + /* WRN("NO PLANE FOUND"); */ } + else + WRN("Could not get FBO from Bo"); } static Eina_Bool @@ -253,9 +350,6 @@ _evas_outbuf_egl_setup(Outbuf *ob) return EINA_FALSE; } - DBG("Config Format: %d", format); - DBG("OB Format: %d", ob->info->info.format); - if (format == (int)ob->info->info.format) { ob->egl.config = cfgs[i]; @@ -369,6 +463,11 @@ evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_ /* ob->vsync = info->info.vsync; */ ob->swap_mode = swap_mode; + ob->fd = info->info.fd; + ob->bpp = info->info.bpp; + ob->format = info->info.format; + ob->priv.output = info->info.output; + /* if ((num = getenv("EVAS_GL_DRM_VSYNC"))) */ /* ob->vsync = atoi(num); */ @@ -383,6 +482,8 @@ evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_ return NULL; } + _outbuf_tick_source_set(ob); + return ob; } @@ -577,9 +678,7 @@ evas_outbuf_buffer_state_get(Outbuf *ob) return swap_mode; } else - { - return MODE_FULL; - } + return MODE_FULL; return ob->swap_mode; } From 93178199a6c302e899438a32e8c296dc5bd2d248 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Tue, 3 May 2016 12:03:00 -0400 Subject: [PATCH 09/35] ecore-evas: Port ecore_evas drm engine to use Ecore_Drm2 library Signed-off-by: Chris Michael --- configure.ac | 4 +- src/Makefile_Ecore_Evas.am | 2 +- .../ecore_evas/engines/drm/ecore_evas_drm.c | 1319 +++++++---------- 3 files changed, 547 insertions(+), 778 deletions(-) diff --git a/configure.ac b/configure.ac index 0912ac2e29..ff5c2ad188 100644 --- a/configure.ac +++ b/configure.ac @@ -4404,9 +4404,9 @@ ECORE_EVAS_MODULE([extn], [${want_ecore_evas_extn}]) ECORE_EVAS_MODULE([ews], [yes]) ECORE_EVAS_MODULE([fb], [${want_fb}]) ECORE_EVAS_MODULE([drm], [${want_drm}], - [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm])]) + [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_drm}], [ecore-drm2])]) ECORE_EVAS_MODULE([gl-drm], [${want_gl_drm}], - [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm])]) + [EFL_OPTIONAL_INTERNAL_DEPEND_PKG([ECORE_EVAS], [${want_gl_drm}], [ecore-drm2])]) ECORE_EVAS_MODULE([psl1ght], [${have_ps3}]) ECORE_EVAS_MODULE([opengl-cocoa], [${want_ecore_evas_gl_cocoa}]) diff --git a/src/Makefile_Ecore_Evas.am b/src/Makefile_Ecore_Evas.am index 25af963eb2..747a426b8a 100644 --- a/src/Makefile_Ecore_Evas.am +++ b/src/Makefile_Ecore_Evas.am @@ -269,7 +269,7 @@ $(install_ecoreevasenginedrmpkgLTLIBRARIES): install-libLTLIBRARIES modules_ecore_evas_engines_drm_module_la_SOURCES = $(DRMSOURCES) modules_ecore_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ @ECORE_EVAS_CFLAGS@ \ -@ECORE_DRM_CFLAGS@ \ +@ECORE_DRM2_CFLAGS@ \ -I$(top_srcdir)/src/modules/evas/engines/drm \ -I$(top_srcdir)/src/modules/evas/engines/gl_drm modules_ecore_evas_engines_drm_module_la_LIBADD = \ 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..3cdc7011f3 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 @@ # include #endif -#include -#include #include #include #include "ecore_private.h" @@ -12,12 +10,12 @@ #include #include "ecore_evas_private.h" #include "ecore_evas_drm.h" -#include +#include #include +#include #ifdef BUILD_ECORE_EVAS_GL_DRM # include -# include # include #endif @@ -43,715 +41,218 @@ # endif #endif /* ! _WIN32 */ -typedef struct _Ecore_Evas_Engine_Drm_Data Ecore_Evas_Engine_Drm_Data; - -struct _Ecore_Evas_Engine_Drm_Data +typedef struct _Ecore_Evas_Engine_Drm_Data { - int w, h; -}; + int fd; + int cw, ch; + int clockid; + int x, y, w, h; + int depth, bpp; + unsigned int format; + Ecore_Drm2_Device *dev; + Ecore_Drm2_Output *output; +} Ecore_Evas_Engine_Drm_Data; + +static int _drm_init_count = 0; -/* local function prototypes */ -static int _ecore_evas_drm_init(const char *device); -static int _ecore_evas_drm_shutdown(void); -static Ecore_Evas_Interface_Drm *_ecore_evas_drm_interface_new(void); -static void _ecore_evas_drm_free(Ecore_Evas *ee); -static void _ecore_evas_drm_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); -static void _ecore_evas_drm_callback_move_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); -static void _ecore_evas_drm_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); -static void _ecore_evas_drm_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); -static void _ecore_evas_drm_callback_mouse_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); -static void _ecore_evas_drm_callback_mouse_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); -static void _ecore_evas_drm_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); -static void _ecore_evas_drm_move(Ecore_Evas *ee, int x, int y); -static void _ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h); -static void _ecore_evas_drm_move_resize(Ecore_Evas *ee, int x, int y, int w, int h); -static void _ecore_evas_drm_rotation_set(Ecore_Evas *ee, int rotation, int resize); -static void _ecore_evas_drm_show(Ecore_Evas *ee); -static void _ecore_evas_drm_hide(Ecore_Evas *ee); -static void _ecore_evas_drm_title_set(Ecore_Evas *ee, const char *title); -static void _ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c); -static void _ecore_evas_drm_size_min_set(Ecore_Evas *ee, int w, int h); -static void _ecore_evas_drm_size_max_set(Ecore_Evas *ee, int w, int h); -static void _ecore_evas_drm_size_base_set(Ecore_Evas *ee, int w, int h); -static void _ecore_evas_drm_size_step_set(Ecore_Evas *ee, int w, int h); -static void _ecore_evas_drm_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y); -static void _ecore_evas_drm_object_cursor_unset(Ecore_Evas *ee); -static void _ecore_evas_drm_layer_set(Ecore_Evas *ee, int layer); -static void _ecore_evas_drm_iconified_set(Ecore_Evas *ee, Eina_Bool on); -static void _ecore_evas_drm_borderless_set(Ecore_Evas *ee, Eina_Bool on); -static void _ecore_evas_drm_maximized_set(Ecore_Evas *ee, Eina_Bool on); -static void _ecore_evas_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on); -static void _ecore_evas_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on); -static void _ecore_evas_drm_ignore_events_set(Ecore_Evas *ee, int ignore); -static void _ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha); -static void _ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent); -static void _ecore_evas_drm_aspect_set(Ecore_Evas *ee, double aspect); - -static int _ecore_evas_drm_render(Ecore_Evas *ee); -static void _ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event); -static int _ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates); - -static void _ecore_evas_drm_screen_geometry_get(const Ecore_Evas *ee EINA_UNUSED, int *x, int *y, int *w, int *h); -static void _ecore_evas_drm_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y); -Eina_Bool _ecore_evas_drm_pointer_warp(const Ecore_Evas *ee EINA_UNUSED, Evas_Coord x, Evas_Coord y); - -/* local variables */ -static int _ecore_evas_init_count = 0; -static Ecore_Drm_Device *dev = NULL; - -static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = -{ - _ecore_evas_drm_free, - _ecore_evas_drm_callback_resize_set, - _ecore_evas_drm_callback_move_set, - NULL, //void (*fn_callback_show_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - NULL, //void (*fn_callback_hide_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - _ecore_evas_drm_delete_request_set, - NULL, //void (*fn_callback_destroy_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - _ecore_evas_drm_callback_focus_in_set, - _ecore_evas_drm_callback_focus_out_set, - _ecore_evas_drm_callback_mouse_in_set, - _ecore_evas_drm_callback_mouse_out_set, - NULL, //void (*fn_callback_sticky_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - NULL, //void (*fn_callback_unsticky_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - NULL, //void (*fn_callback_pre_render_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - NULL, //void (*fn_callback_post_render_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - _ecore_evas_drm_move, - NULL, //void (*fn_managed_move) (Ecore_Evas *ee, int x, int y); - _ecore_evas_drm_resize, - _ecore_evas_drm_move_resize, - _ecore_evas_drm_rotation_set, - NULL, //void (*fn_shaped_set) (Ecore_Evas *ee, int shaped); - _ecore_evas_drm_show, - _ecore_evas_drm_hide, - NULL, //void (*fn_raise) (Ecore_Evas *ee); - NULL, //void (*fn_lower) (Ecore_Evas *ee); - NULL, //void (*fn_activate) (Ecore_Evas *ee); - _ecore_evas_drm_title_set, - _ecore_evas_drm_name_class_set, - _ecore_evas_drm_size_min_set, - _ecore_evas_drm_size_max_set, - _ecore_evas_drm_size_base_set, - _ecore_evas_drm_size_step_set, - _ecore_evas_drm_object_cursor_set, - _ecore_evas_drm_object_cursor_unset, - _ecore_evas_drm_layer_set, - NULL, //void (*fn_focus_set) (Ecore_Evas *ee, Eina_Bool on); - _ecore_evas_drm_iconified_set, - _ecore_evas_drm_borderless_set, - NULL, //void (*fn_override_set) (Ecore_Evas *ee, Eina_Bool on); - _ecore_evas_drm_maximized_set, - _ecore_evas_drm_fullscreen_set, - NULL, //void (*fn_avoid_damage_set) (Ecore_Evas *ee, int on); - _ecore_evas_drm_withdrawn_set, - NULL, //void (*fn_sticky_set) (Ecore_Evas *ee, Eina_Bool on); - _ecore_evas_drm_ignore_events_set, - _ecore_evas_drm_alpha_set, - _ecore_evas_drm_transparent_set, - NULL, //void (*fn_profiles_set) (Ecore_Evas *ee, const char **profiles, int count); - NULL, //void (*fn_profile_set) (Ecore_Evas *ee, const char *profile); - - NULL, //void (*fn_window_group_set) (Ecore_Evas *ee, const Ecore_Evas *ee_group); - _ecore_evas_drm_aspect_set, - NULL, //void (*fn_urgent_set) (Ecore_Evas *ee, Eina_Bool on); - NULL, //void (*fn_modal_set) (Ecore_Evas *ee, Eina_Bool on); - NULL, //void (*fn_demands_attention_set) (Ecore_Evas *ee, Eina_Bool on); - NULL, //void (*fn_focus_skip_set) (Ecore_Evas *ee, Eina_Bool on); - - _ecore_evas_drm_render, - - _ecore_evas_drm_screen_geometry_get, - NULL, //void (*fn_screen_dpi_get) (const Ecore_Evas *ee, int *xdpi, int *ydpi); - NULL, //void (*fn_msg_parent_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); - NULL, //void (*fn_msg_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); - - _ecore_evas_drm_pointer_xy_get, - _ecore_evas_drm_pointer_warp, - - NULL, // wm_rot_preferred_rotation_set - NULL, // wm_rot_available_rotations_set - NULL, // wm_rot_manual_rotation_done_set - NULL, // wm_rot_manual_rotation_done - - NULL, // aux_hints_set - - NULL, // fn_animator_register - NULL // fn_animator_unregister -}; - -EAPI Ecore_Evas * -ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h) -{ - Ecore_Evas *ee; - Evas_Engine_Info_Drm *einfo; - Ecore_Evas_Interface_Drm *iface; - Ecore_Evas_Engine_Drm_Data *edata; - int method; - - /* try to find the evas drm engine */ - if (!(method = evas_render_method_lookup("drm"))) - { - ERR("Render method lookup failed for Drm"); - return NULL; - } - - /* try to init drm */ - if (_ecore_evas_drm_init(device) < 1) return NULL; - - if (!ecore_drm_device_software_setup(dev)) - { - ERR("Could not setup device for software"); - goto soft_err; - } - - /* try to allocate space for new ecore_evas */ - if (!(ee = calloc(1, sizeof(Ecore_Evas)))) - { - ERR("Failed to allocate space for new Ecore_Evas"); - goto ee_err; - } - - if (!(edata = calloc(1, sizeof(Ecore_Evas_Engine_Drm_Data)))) - { - ERR("Failed to allocate space for new Ecore_Evas_Engine_Data"); - free(ee); - goto ee_err; - } - - ee->engine.data = edata; - - ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); - - ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func; - - iface = _ecore_evas_drm_interface_new(); - ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface); - - /* set some engine properties */ - ee->driver = "drm"; - if (device) ee->name = strdup(device); - else - ee->name = strdup(ecore_drm_device_name_get(dev)); - - if (w < 1) w = 1; - if (h < 1) h = 1; - - ee->x = ee->req.x = x; - ee->y = ee->req.y = y; - ee->w = ee->req.w = w; - ee->h = ee->req.h = h; - - ee->prop.max.w = 32767; - ee->prop.max.h = 32767; - ee->prop.layer = 4; - ee->prop.request_pos = 0; - ee->prop.sticky = 0; - ee->prop.withdrawn = EINA_TRUE; - ee->alpha = EINA_FALSE; - - ee->can_async_render = 1; - if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER")) - ee->can_async_render = 0; - - /* try to initialize evas */ - ee->evas = evas_new(); - evas_data_attach_set(ee->evas, ee); - evas_output_method_set(ee->evas, method); - - if ((ee->rotation == 90) || (ee->rotation == 270)) - { - evas_output_size_set(ee->evas, h, w); - evas_output_viewport_set(ee->evas, 0, 0, h, w); - } - else - { - evas_output_size_set(ee->evas, w, h); - evas_output_viewport_set(ee->evas, 0, 0, w, h); - } - - if (ee->can_async_render) - evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST, - _ecore_evas_drm_render_updates, ee); - - if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas))) - { - Ecore_Drm_Output *output; - char *num; - - einfo->info.depth = 32; // FIXME - einfo->info.destination_alpha = ee->alpha; - einfo->info.rotation = ee->rotation; - - if ((num = getenv("EVAS_DRM_VSYNC"))) - { - if (!atoi(num)) - einfo->info.vsync = EINA_FALSE; - else - einfo->info.vsync = EINA_TRUE; - } - else - einfo->info.vsync = EINA_TRUE; - - einfo->info.use_hw_accel = EINA_FALSE; - einfo->info.dev = dev; - - if ((output = ecore_drm_device_output_find(dev, x, y))) - { - einfo->info.conn_id = ecore_drm_output_connector_id_get(output); - einfo->info.crtc_id = ecore_drm_output_crtc_id_get(output); - einfo->info.buffer_id = ecore_drm_output_crtc_buffer_get(output); - } - - if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) - { - ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver); - goto eng_err; - } - } - else - { - ERR("Failed to get Evas Engine Info for '%s'", ee->driver); - goto eng_err; - } - - ee->prop.window = einfo->info.buffer_id; - - _ecore_evas_register(ee); - ecore_evas_input_event_register(ee); - - ecore_drm_device_window_set(dev, ee->prop.window); - ecore_event_window_register(ee->prop.window, ee, ee->evas, - (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, - (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, - (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, - (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); - - /* NB: Send a fake mouse move event so that E-Wl gets an updated - * pointer position, else we end up with buggers (ref: T2854) */ - { - Ecore_Event_Mouse_Move *ev; - - ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)); - ev->window = ee->prop.window; - ev->event_window = ee->prop.window; - ev->root_window = ee->prop.window; - ev->same_screen = 1; - - ecore_drm_device_pointer_xy_get(dev, &ev->x, &ev->y); - - ev->root.x = ev->x; - ev->root.y = ev->y; - - ecore_event_evas_mouse_move(NULL, ECORE_EVENT_MOUSE_MOVE, ev); - } - - return ee; - -eng_err: - ecore_evas_free(ee); -soft_err: -ee_err: - _ecore_evas_drm_shutdown(); - return NULL; -} - -#ifdef BUILD_ECORE_EVAS_GL_DRM -EAPI Ecore_Evas * -ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h) -{ - Ecore_Evas *ee; - Evas_Engine_Info_GL_Drm *einfo; - Ecore_Evas_Interface_Drm *iface; - Ecore_Evas_Engine_Drm_Data *edata; - int method; - uint32_t format = GBM_FORMAT_XRGB8888; - uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; - char *num; - - /* try to find the evas drm engine */ - if (!(method = evas_render_method_lookup("gl_drm"))) - { - ERR("Render method lookup failed for GL Drm"); - return NULL; - } - - /* try to init drm */ - if (_ecore_evas_drm_init(device) < 1) return NULL; - - /* try to load gl libary, gbm libary */ - /* Typically, gbm loads the dri driver However some versions of Mesa - * do not have libglapi symbols linked in the driver. Because of this, - * using hardware accel for our drm code Could fail with a - * message that the driver could not load. Let's be proactive and - * work around this for the user by preloading the glapi library */ - dlopen("libglapi.so.0", (RTLD_LAZY | RTLD_GLOBAL)); - if (dlerror()) - { - _ecore_evas_drm_shutdown(); - return NULL; - } - - /* try to allocate space for new ecore_evas */ - if (!(ee = calloc(1, sizeof(Ecore_Evas)))) - { - ERR("Failed to allocate space for new Ecore_Evas"); - goto ee_err; - } - - if (!(edata = calloc(1, sizeof(Ecore_Evas_Engine_Drm_Data)))) - { - ERR("Failed to allocate space for new Ecore_Evas_Engine_Data"); - free(ee); - goto ee_err; - } - - ee->engine.data = edata; - - ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); - - ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func; - - iface = _ecore_evas_drm_interface_new(); - ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface); - - /* set some engine properties */ - ee->driver = "gl_drm"; - if (device) ee->name = strdup(device); - else - ee->name = strdup(ecore_drm_device_name_get(dev)); - - if (w < 1) w = 1; - if (h < 1) h = 1; - - ee->x = ee->req.x = x; - ee->y = ee->req.y = y; - ee->w = ee->req.w = w; - ee->h = ee->req.h = h; - - ee->prop.max.w = 32767; - ee->prop.max.h = 32767; - ee->prop.layer = 4; - ee->prop.request_pos = 0; - ee->prop.sticky = 0; - ee->prop.withdrawn = EINA_TRUE; - ee->alpha = EINA_FALSE; - - /* NB: Disable async rendering for egl. Not Applicable as EGL is sync only */ - ee->can_async_render = 0; - /* if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER")) */ - /* ee->can_async_render = 0; */ - - /* try to initialize evas */ - ee->evas = evas_new(); - evas_data_attach_set(ee->evas, ee); - evas_output_method_set(ee->evas, method); - - if ((ee->rotation == 90) || (ee->rotation == 270)) - { - evas_output_size_set(ee->evas, h, w); - evas_output_viewport_set(ee->evas, 0, 0, h, w); - } - else - { - evas_output_size_set(ee->evas, w, h); - evas_output_viewport_set(ee->evas, 0, 0, w, h); - } - - if (ee->can_async_render) - evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST, - _ecore_evas_drm_render_updates, ee); - - if ((einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(ee->evas))) - { - Ecore_Drm_Output *output; - - einfo->info.depth = 32; - einfo->info.destination_alpha = ee->alpha; - einfo->info.rotation = ee->rotation; - - if ((num = getenv("EVAS_DRM_VSYNC"))) - { - if (!atoi(num)) - einfo->info.vsync = EINA_FALSE; - else - einfo->info.vsync = EINA_TRUE; - } - else - einfo->info.vsync = EINA_TRUE; - - einfo->info.dev = dev; - einfo->info.format = format; - einfo->info.flags = flags; - - if ((output = ecore_drm_device_output_find(dev, x, y))) - { - einfo->info.conn_id = ecore_drm_output_connector_id_get(output); - einfo->info.crtc_id = ecore_drm_output_crtc_id_get(output); - einfo->info.buffer_id = ecore_drm_output_crtc_buffer_get(output); - } - - if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) - { - ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver); - goto eng_err; - } - } - else - { - ERR("Failed to get Evas Engine Info for '%s'", ee->driver); - goto eng_err; - } - - ee->prop.window = einfo->info.buffer_id; - - _ecore_evas_register(ee); - ecore_evas_input_event_register(ee); - - ecore_drm_device_window_set(dev, ee->prop.window); - ecore_event_window_register(ee->prop.window, ee, ee->evas, - (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, - (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, - (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, - (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); - - return ee; - -eng_err: - ecore_evas_free(ee); -ee_err: - _ecore_evas_drm_shutdown(); - return NULL; -} -#endif - -/* local functions */ static int -_ecore_evas_drm_init(const char *device) +_ecore_evas_drm_init(Ecore_Evas_Engine_Drm_Data *edata, const char *device) { - if (++_ecore_evas_init_count != 1) return _ecore_evas_init_count; + int mw, mh; - /* try to init ecore_drm */ - if (!ecore_drm_init()) + if (++_drm_init_count != 1) return _drm_init_count; + + if (!ecore_drm2_init()) { - ERR("Could not initialize Ecore_Drm"); - return --_ecore_evas_init_count; + ERR("Failed to init Ecore_Drm2 library"); + goto init_err; } - /* try to find the device */ - if (!(dev = ecore_drm_device_find(device, NULL))) + if (!device) device = "seat0"; + + edata->dev = ecore_drm2_device_find(device, 0, EINA_TRUE); + if (!edata->dev) { - ERR("Could not find drm device with name: %s. Falling back to default device.", device); - - /* if we already passed in NULL as device name, then no point in - * calling the find function below with no name either */ - if (!device) goto dev_err; - - /* try getting the default drm device */ - if (!(dev = ecore_drm_device_find(NULL, NULL))) - goto dev_err; + ERR("Failed to create device"); + goto dev_err; } - if (!ecore_drm_launcher_connect(dev)) + edata->fd = ecore_drm2_device_open(edata->dev); + if (edata->fd < 0) { - ERR("Could not connect DRM launcher"); - goto launcher_err; + ERR("Failed to open device"); + goto open_err; } - /* try to open the graphics card */ - if (!ecore_drm_device_open(dev)) - { - ERR("Could not open drm device"); - goto dev_open_err; - } + edata->clockid = ecore_drm2_device_clock_id_get(edata->dev); + ecore_drm2_device_cursor_size_get(edata->dev, &edata->cw, &edata->ch); - /* try to create sprites */ - if (!ecore_drm_sprites_create(dev)) - { - ERR("Could not create sprites"); - goto sprite_err; - } - - /* try to create outputs */ - if (!ecore_drm_outputs_create(dev)) + if (!ecore_drm2_outputs_create(edata->dev)) { ERR("Could not create outputs"); goto output_err; } - /* try to create inputs */ - if (!ecore_drm_inputs_create(dev)) - { - ERR("Could not create inputs"); - goto input_err; - } + edata->output = ecore_drm2_output_find(edata->dev, edata->x, edata->y); + if (!edata->output) + WRN("Could not find output at %d %d", edata->x, edata->y); + + ecore_drm2_output_crtc_size_get(edata->output, &mw, &mh); + ecore_drm2_device_pointer_max_set(edata->dev, mw, mh); ecore_event_evas_init(); - return _ecore_evas_init_count; + return _drm_init_count; output_err: - ecore_drm_inputs_destroy(dev); -input_err: - ecore_drm_sprites_destroy(dev); -sprite_err: - ecore_drm_device_close(dev); -dev_open_err: - ecore_drm_launcher_disconnect(dev); - ecore_drm_device_free(dev); - dev = NULL; -launcher_err: + ecore_drm2_device_close(edata->dev); +open_err: + ecore_drm2_device_free(edata->dev); dev_err: - ecore_drm_shutdown(); - return --_ecore_evas_init_count; + ecore_drm2_shutdown(); +init_err: + return --_drm_init_count; } static int -_ecore_evas_drm_shutdown(void) +_ecore_evas_drm_shutdown(Ecore_Evas_Engine_Drm_Data *edata) { - Ecore_Drm_Output *output; - - if (--_ecore_evas_init_count != 0) return _ecore_evas_init_count; - - ecore_drm_inputs_destroy(dev); - - EINA_LIST_FREE(dev->outputs, output) - ecore_drm_output_free(output); - - ecore_drm_sprites_destroy(dev); - ecore_drm_device_close(dev); - ecore_drm_launcher_disconnect(dev); - ecore_drm_device_free(dev); - ecore_drm_shutdown(); - dev = NULL; + if (--_drm_init_count != 0) return _drm_init_count; + ecore_drm2_outputs_destroy(edata->dev); + ecore_drm2_device_close(edata->dev); + ecore_drm2_device_free(edata->dev); + ecore_drm2_shutdown(); ecore_event_evas_shutdown(); - return _ecore_evas_init_count; + return _drm_init_count; } -static Ecore_Evas_Interface_Drm * -_ecore_evas_drm_interface_new(void) -{ - Ecore_Evas_Interface_Drm *iface; - - if (!(iface = calloc(1, sizeof(Ecore_Evas_Interface_Drm)))) - return NULL; - - iface->base.name = "drm"; - iface->base.version = 1; - - return iface; -} - -/* local ecore_evas functions */ static void -_ecore_evas_drm_free(Ecore_Evas *ee) +_drm_free(Ecore_Evas *ee) { - Ecore_Evas_Engine_Drm_Data *data; + Ecore_Evas_Engine_Drm_Data *edata; - data = ee->engine.data; ecore_evas_input_event_unregister(ee); - free(data); - _ecore_evas_drm_shutdown(); + + edata = ee->engine.data; + _ecore_evas_drm_shutdown(edata); + free(edata); } -static void -_ecore_evas_drm_callback_resize_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) +static int +_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates) { - ee->func.fn_resize = func; + int rend = 0; + + if ((ee->visible) && (updates)) + { + _ecore_evas_idle_timeout_update(ee); + rend = 1; + } + else + evas_norender(ee->evas); + + if (ee->func.fn_post_render) ee->func.fn_post_render(ee); + + return rend; } static void -_ecore_evas_drm_callback_move_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) +_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event) { - ee->func.fn_move = func; + Evas_Event_Render_Post *ev; + Ecore_Evas *ee; + + ev = event; + if (!ev) return; + + ee = data; + if (!ee) return; + + ee->in_async_render = EINA_FALSE; + _drm_render_updates_process(ee, ev->updated_area); } -static void -_ecore_evas_drm_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) +static int +_drm_render(Ecore_Evas *ee) { - ee->func.fn_focus_in = func; + int rend = 0; + Eina_List *l; + Ecore_Evas *ee2; + + if (ee->in_async_render) return 0; + + if (!ee->visible) + { + evas_norender(ee->evas); + return 0; + } + + EINA_LIST_FOREACH(ee->sub_ecore_evas, l, ee2) + { + if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); + if (ee2->engine.func->fn_render) + rend |= ee2->engine.func->fn_render(ee2); + if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); + } + + if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); + + if (!ee->can_async_render) + { + Eina_List *updates; + + updates = evas_render_updates(ee->evas); + rend = _drm_render_updates_process(ee, updates); + evas_render_updates_free(updates); + } + else if (evas_render_async(ee->evas)) + { + ee->in_async_render = EINA_TRUE; + rend = 1; + } + + return rend; } static void -_ecore_evas_drm_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) +_drm_screen_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h) { - ee->func.fn_focus_out = func; + Ecore_Evas_Engine_Drm_Data *edata; + + edata = ee->engine.data; + ecore_drm2_output_geometry_get(edata->output, x, y, w, h); } static void -_ecore_evas_drm_callback_mouse_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) +_drm_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y) { - ee->func.fn_mouse_in = func; + Ecore_Evas_Engine_Drm_Data *edata; + + edata = ee->engine.data; + ecore_drm2_device_pointer_xy_get(edata->dev, x, y); } -static void -_ecore_evas_drm_callback_mouse_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) +static Eina_Bool +_drm_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y) { - ee->func.fn_mouse_out = func; + Ecore_Evas_Engine_Drm_Data *edata; + + edata = ee->engine.data; + ecore_drm2_device_pointer_warp(edata->dev, x, y); + return EINA_TRUE; } static void -_ecore_evas_drm_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) -{ - ee->func.fn_delete_request = func; -} - -static void -_ecore_evas_drm_move(Ecore_Evas *ee, int x, int y) -{ - ee->req.x = x; - ee->req.y = y; - if ((ee->x == x) && (ee->y == y)) return; - ee->x = x; - ee->y = y; - if (ee->func.fn_move) ee->func.fn_move(ee); -} - -static void -_ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h) -{ - ee->req.w = w; - ee->req.h = h; - if ((ee->w == w) && (ee->h == h)) return; - ee->w = w; - ee->h = h; - evas_output_size_set(ee->evas, w, h); - evas_output_viewport_set(ee->evas, 0, 0, w, h); - if (ee->func.fn_resize) ee->func.fn_resize(ee); -} - -static void -_ecore_evas_drm_move_resize(Ecore_Evas *ee, int x, int y, int w, int h) -{ - if ((ee->x != x) || (ee->y != y)) - _ecore_evas_drm_move(ee, x, y); - if ((ee->w != w) || (ee->h != h)) - _ecore_evas_drm_resize(ee, w, h); -} - -static void -_ecore_evas_drm_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSED) -{ - Evas_Engine_Info_Drm *einfo; - - if (ee->rotation == rotation) return; - einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas); - if (!einfo) return; - einfo->info.rotation = rotation; - if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) - ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver); -} - -static void -_ecore_evas_drm_show(Ecore_Evas *ee) +_drm_show(Ecore_Evas *ee) { if ((!ee) || (ee->visible)) return; ee->should_be_visible = 1; if (ee->prop.avoid_damage) - _ecore_evas_drm_render(ee); + _drm_render(ee); if (ee->prop.override) { @@ -771,7 +272,7 @@ _ecore_evas_drm_show(Ecore_Evas *ee) } static void -_ecore_evas_drm_hide(Ecore_Evas *ee) +_drm_hide(Ecore_Evas *ee) { if ((!ee) || (!ee->visible)) return; @@ -790,7 +291,53 @@ _ecore_evas_drm_hide(Ecore_Evas *ee) } static void -_ecore_evas_drm_title_set(Ecore_Evas *ee, const char *title) +_drm_move(Ecore_Evas *ee, int x, int y) +{ + ee->req.x = x; + ee->req.y = y; + if ((ee->x == x) && (ee->y == y)) return; + ee->x = x; + ee->y = y; + if (ee->func.fn_move) ee->func.fn_move(ee); +} + +static void +_drm_resize(Ecore_Evas *ee, int w, int h) +{ + ee->req.w = w; + ee->req.h = h; + if ((ee->w == w) && (ee->h == h)) return; + ee->w = w; + ee->h = h; + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + if (ee->func.fn_resize) ee->func.fn_resize(ee); +} + +static void +_drm_move_resize(Ecore_Evas *ee, int x, int y, int w, int h) +{ + if ((ee->x != x) || (ee->y != y)) + _drm_move(ee, x, y); + if ((ee->w != w) || (ee->h != h)) + _drm_resize(ee, w, h); +} + +static void +_drm_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSED) +{ + Evas_Engine_Info_Drm *einfo; + + if (ee->rotation == rotation) return; + einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas); + if (!einfo) return; + einfo->info.rotation = rotation; + if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) + ERR("evas_engine_info_set() for engine '%s' failed", ee->driver); +} + +static void +_drm_title_set(Ecore_Evas *ee, const char *title) { if (eina_streq(ee->prop.title, title)) return; if (ee->prop.title) free(ee->prop.title); @@ -799,7 +346,7 @@ _ecore_evas_drm_title_set(Ecore_Evas *ee, const char *title) } static void -_ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c) +_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c) { if (!eina_streq(ee->prop.name, n)) { @@ -807,6 +354,7 @@ _ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c) ee->prop.name = NULL; if (n) ee->prop.name = strdup(n); } + if (!eina_streq(ee->prop.clas, c)) { if (ee->prop.clas) free(ee->prop.clas); @@ -816,67 +364,54 @@ _ecore_evas_drm_name_class_set(Ecore_Evas *ee, const char *n, const char *c) } static void -_ecore_evas_drm_size_min_set(Ecore_Evas *ee, int w, int h) +_drm_size_min_set(Ecore_Evas *ee, int w, int h) { - if (w < 0) w = 0; - if (h < 0) h = 0; if ((ee->prop.min.w == w) && (ee->prop.min.h == h)) return; ee->prop.min.w = w; ee->prop.min.h = h; } static void -_ecore_evas_drm_size_max_set(Ecore_Evas *ee, int w, int h) +_drm_size_max_set(Ecore_Evas *ee, int w, int h) { - if (w < 0) w = 0; - if (h < 0) h = 0; if ((ee->prop.max.w == w) && (ee->prop.max.h == h)) return; ee->prop.max.w = w; ee->prop.max.h = h; } static void -_ecore_evas_drm_size_base_set(Ecore_Evas *ee, int w, int h) +_drm_size_base_set(Ecore_Evas *ee, int w, int h) { - if (w < 0) w = 0; - if (h < 0) h = 0; if ((ee->prop.base.w == w) && (ee->prop.base.h == h)) return; ee->prop.base.w = w; ee->prop.base.h = h; } static void -_ecore_evas_drm_size_step_set(Ecore_Evas *ee, int w, int h) +_drm_size_step_set(Ecore_Evas *ee, int w, int h) { - if (w < 0) w = 0; - if (h < 0) h = 0; if ((ee->prop.step.w == w) && (ee->prop.step.h == h)) return; ee->prop.step.w = w; ee->prop.step.h = h; } static void -_ecore_evas_drm_object_cursor_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_drm_object_cursor_del(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED) { Ecore_Evas *ee; - if ((ee = data)) ee->prop.cursor.object = NULL; + ee = data; + if (ee) ee->prop.cursor.object = NULL; } static void -_ecore_evas_drm_object_cursor_unset(Ecore_Evas *ee) +_drm_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y) { - evas_object_event_callback_del_full(ee->prop.cursor.object, EVAS_CALLBACK_DEL, _ecore_evas_drm_object_cursor_del, ee); -} - -static void -_ecore_evas_drm_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y) -{ - int x, y; Evas_Object *old; + int x, y; old = ee->prop.cursor.object; - if (obj == NULL) + if (!obj) { ee->prop.cursor.object = NULL; ee->prop.cursor.layer = 0; @@ -899,7 +434,7 @@ _ecore_evas_drm_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, i if (evas_pointer_inside_get(ee->evas)) evas_object_show(ee->prop.cursor.object); evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, - _ecore_evas_drm_object_cursor_del, ee); + _drm_object_cursor_del, ee); } evas_object_move(ee->prop.cursor.object, x - ee->prop.cursor.hot.x, @@ -909,13 +444,21 @@ end: if ((old) && (obj != old)) { evas_object_event_callback_del_full - (old, EVAS_CALLBACK_DEL, _ecore_evas_drm_object_cursor_del, ee); + (old, EVAS_CALLBACK_DEL, _drm_object_cursor_del, ee); evas_object_del(old); } } static void -_ecore_evas_drm_layer_set(Ecore_Evas *ee, int layer) +_drm_object_cursor_unset(Ecore_Evas *ee) +{ + evas_object_event_callback_del_full(ee->prop.cursor.object, + EVAS_CALLBACK_DEL, + _drm_object_cursor_del, ee); +} + +static void +_drm_layer_set(Ecore_Evas *ee, int layer) { if (layer < 1) layer = 1; else if (layer > 255) layer = 255; @@ -924,44 +467,44 @@ _ecore_evas_drm_layer_set(Ecore_Evas *ee, int layer) } static void -_ecore_evas_drm_iconified_set(Ecore_Evas *ee, Eina_Bool on) +_drm_iconified_set(Ecore_Evas *ee, Eina_Bool on) { if (ee->prop.iconified == on) return; ee->prop.iconified = on; } static void -_ecore_evas_drm_borderless_set(Ecore_Evas *ee, Eina_Bool on) +_drm_borderless_set(Ecore_Evas *ee, Eina_Bool on) { if (ee->prop.borderless == on) return; ee->prop.borderless = on; } static void -_ecore_evas_drm_maximized_set(Ecore_Evas *ee, Eina_Bool on) +_drm_maximized_set(Ecore_Evas *ee, Eina_Bool on) { if (ee->prop.maximized == on) return; ee->prop.maximized = on; } static void -_ecore_evas_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) +_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) { Eina_Bool resized = EINA_FALSE; Ecore_Evas_Engine_Drm_Data *edata; edata = ee->engine.data; if (ee->prop.fullscreen == on) return; + ee->prop.fullscreen = on; + if (on) { - Evas_Engine_Info_Drm *einfo; int ow = 0, oh = 0; edata->w = ee->w; edata->h = ee->h; - if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas))) - ecore_drm_output_size_get(dev, einfo->info.buffer_id, &ow, &oh); + ecore_drm2_output_geometry_get(edata->output, NULL, NULL, &ow, &oh); if ((ow == 0) || (oh == 0)) { ow = ee->w; @@ -992,7 +535,7 @@ _ecore_evas_drm_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) } static void -_ecore_evas_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on) +_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on) { if (ee->prop.withdrawn == on) return; ee->prop.withdrawn = on; @@ -1001,145 +544,371 @@ _ecore_evas_drm_withdrawn_set(Ecore_Evas *ee, Eina_Bool on) } static void -_ecore_evas_drm_ignore_events_set(Ecore_Evas *ee, int ignore) +_drm_ignore_events_set(Ecore_Evas *ee, int on) { - if (ee->ignore_events == ignore) return; - ee->ignore_events = ignore; + if (ee->ignore_events == on) return; + ee->ignore_events = on; } static void -_ecore_evas_drm_alpha_set(Ecore_Evas *ee, int alpha) +_drm_alpha_set(Ecore_Evas *ee, int alpha) { if (ee->in_async_render) { ee->delayed.alpha = alpha; ee->delayed.alpha_changed = EINA_TRUE; - return; } - - /* FIXME: TODO: Finish */ } static void -_ecore_evas_drm_transparent_set(Ecore_Evas *ee, int transparent) +_drm_transparent_set(Ecore_Evas *ee, int transparent) { if (ee->in_async_render) { ee->delayed.transparent = transparent; ee->delayed.transparent_changed = EINA_TRUE; - return; } - - /* FIXME: TODO: Finish */ } static void -_ecore_evas_drm_aspect_set(Ecore_Evas *ee, double aspect) +_drm_aspect_set(Ecore_Evas *ee, double aspect) { if (ee->prop.aspect == aspect) return; ee->prop.aspect = aspect; } -static int -_ecore_evas_drm_render(Ecore_Evas *ee) +static Ecore_Evas_Interface_Drm * +_ecore_evas_drm_interface_new(void) { - int rend = 0; - Eina_List *l; - Ecore_Evas *ee2; + Ecore_Evas_Interface_Drm *iface; - if (ee->in_async_render) return 0; + iface = calloc(1, sizeof(Ecore_Evas_Interface_Drm)); + if (!iface) return NULL; - if (!ee->visible) - { - evas_norender(ee->evas); - return 0; - } + iface->base.name = "drm"; + iface->base.version = 1; - EINA_LIST_FOREACH(ee->sub_ecore_evas, l, ee2) - { - if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); - if (ee2->engine.func->fn_render) - rend |= ee2->engine.func->fn_render(ee2); - if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); - } - - if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); - - if (!ee->can_async_render) - { - Eina_List *updates; - - updates = evas_render_updates(ee->evas); - rend = _ecore_evas_drm_render_updates_process(ee, updates); - evas_render_updates_free(updates); - } - else if (evas_render_async(ee->evas)) - { - ee->in_async_render = EINA_TRUE; - rend = 1; - } - - return rend; + return iface; } -static void -_ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event) +static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = +{ + _drm_free, + NULL, //void (*fn_callback_resize_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //void (*fn_callback_move_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //void (*fn_callback_show_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //void (*fn_callback_hide_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //_ecore_evas_drm_delete_request_set, + NULL, //void (*fn_callback_destroy_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //_ecore_evas_drm_callback_focus_in_set, + NULL, //_ecore_evas_drm_callback_focus_out_set, + NULL, //_ecore_evas_drm_callback_mouse_in_set, + NULL, //_ecore_evas_drm_callback_mouse_out_set, + NULL, //void (*fn_callback_sticky_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //void (*fn_callback_unsticky_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //void (*fn_callback_pre_render_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + NULL, //void (*fn_callback_post_render_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + _drm_move, + NULL, //void (*fn_managed_move) (Ecore_Evas *ee, int x, int y); + _drm_resize, + _drm_move_resize, + _drm_rotation_set, + NULL, //void (*fn_shaped_set) (Ecore_Evas *ee, int shaped); + _drm_show, + _drm_hide, + NULL, //void (*fn_raise) (Ecore_Evas *ee); + NULL, //void (*fn_lower) (Ecore_Evas *ee); + NULL, //void (*fn_activate) (Ecore_Evas *ee); + _drm_title_set, + _drm_name_class_set, + _drm_size_min_set, + _drm_size_max_set, + _drm_size_base_set, + _drm_size_step_set, + _drm_object_cursor_set, + _drm_object_cursor_unset, + _drm_layer_set, + NULL, //void (*fn_focus_set) (Ecore_Evas *ee, Eina_Bool on); + _drm_iconified_set, + _drm_borderless_set, + NULL, //void (*fn_override_set) (Ecore_Evas *ee, Eina_Bool on); + _drm_maximized_set, + _drm_fullscreen_set, + NULL, //void (*fn_avoid_damage_set) (Ecore_Evas *ee, int on); + _drm_withdrawn_set, + NULL, //void (*fn_sticky_set) (Ecore_Evas *ee, Eina_Bool on); + _drm_ignore_events_set, + _drm_alpha_set, + _drm_transparent_set, + NULL, //void (*fn_profiles_set) (Ecore_Evas *ee, const char **profiles, int count); + NULL, //void (*fn_profile_set) (Ecore_Evas *ee, const char *profile); + + NULL, //void (*fn_window_group_set) (Ecore_Evas *ee, const Ecore_Evas *ee_group); + _drm_aspect_set, + NULL, //void (*fn_urgent_set) (Ecore_Evas *ee, Eina_Bool on); + NULL, //void (*fn_modal_set) (Ecore_Evas *ee, Eina_Bool on); + NULL, //void (*fn_demands_attention_set) (Ecore_Evas *ee, Eina_Bool on); + NULL, //void (*fn_focus_skip_set) (Ecore_Evas *ee, Eina_Bool on); + + _drm_render, + + _drm_screen_geometry_get, + NULL, //void (*fn_screen_dpi_get) (const Ecore_Evas *ee, int *xdpi, int *ydpi); + NULL, //void (*fn_msg_parent_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); + NULL, //void (*fn_msg_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); + + _drm_pointer_xy_get, + _drm_pointer_warp, + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL, // wm_rot_manual_rotation_done + + NULL, // aux_hints_set + + NULL, // animator_register + NULL // animator_unregister +}; + +EAPI Ecore_Evas * +ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h) { - Evas_Event_Render_Post *ev; Ecore_Evas *ee; + Evas_Engine_Info_Drm *einfo; + Ecore_Evas_Interface_Drm *iface; + Ecore_Evas_Engine_Drm_Data *edata; + int method; - if (!(ev = event)) return; - if (!(ee = data)) return; + method = evas_render_method_lookup("drm"); + if (!method) return NULL; - ee->in_async_render = EINA_FALSE; + ee = calloc(1, sizeof(Ecore_Evas)); + if (!ee) return NULL; - _ecore_evas_drm_render_updates_process(ee, ev->updated_area); - - /* TODO: handle delayed changes */ -} - -static int -_ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates) -{ - int rend = 0; - - if ((ee->visible) && (updates)) + edata = calloc(1, sizeof(Ecore_Evas_Engine_Drm_Data)); + if (!edata) { -// Eina_List *l = NULL; -// Eina_Rectangle *r; -// -// EINA_LIST_FOREACH(updates, l, r) -// { -// /* TODO */ -// } - - _ecore_evas_idle_timeout_update(ee); - rend = 1; + free(ee); + return NULL; } - else - evas_norender(ee->evas); - if (ee->func.fn_post_render) ee->func.fn_post_render(ee); + edata->x = x; + edata->y = y; + edata->w = w; + edata->h = h; + edata->depth = 24; // FIXME: Remove hardcode + edata->bpp = 32; // FIXME: Remove hardcode + edata->format = DRM_FORMAT_XRGB8888; - return rend; + if (_ecore_evas_drm_init(edata, device) < 1) + { + free(edata); + free(ee); + return NULL; + } + + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); + + ee->driver = "drm"; + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func; + ee->engine.data = edata; + + /* FIXME */ + /* if (edata->device) ee->name = strdup(edata->device); */ + + iface = _ecore_evas_drm_interface_new(); + ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface); + + ee->x = ee->req.x = x; + ee->y = ee->req.y = y; + ee->w = ee->req.w = w; + ee->h = ee->req.h = h; + + ee->prop.max.w = 32767; + ee->prop.max.h = 32767; + ee->prop.layer = 4; + ee->prop.request_pos = 0; + ee->prop.sticky = 0; + ee->prop.withdrawn = EINA_TRUE; + ee->alpha = EINA_FALSE; + + ee->can_async_render = 1; + if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER")) + ee->can_async_render = 0; + + ee->evas = evas_new(); + evas_data_attach_set(ee->evas, ee); + evas_output_method_set(ee->evas, method); + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + if (ee->can_async_render) + evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST, + _drm_render_updates, ee); + + einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas); + if (einfo) + { + einfo->info.fd = edata->fd; + einfo->info.bpp = edata->bpp; + einfo->info.depth = edata->depth; + einfo->info.format = edata->format; + einfo->info.rotation = ee->rotation; + einfo->info.output = edata->output; + if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) + { + ERR("evas_engine_info_set() for engine '%s' failed", ee->driver); + goto eng_err; + } + } + + ee->prop.window = ecore_drm2_output_crtc_get(edata->output); + ecore_drm2_device_window_set(edata->dev, ee->prop.window); + + ecore_evas_data_set(ee, "device", edata->dev); + + _ecore_evas_register(ee); + ecore_evas_input_event_register(ee); + ecore_event_window_register(ee->prop.window, ee, ee->evas, + (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, + (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, + (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, + (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); + + return ee; + +eng_err: + ecore_evas_free(ee); + return NULL; } -static void -_ecore_evas_drm_screen_geometry_get(const Ecore_Evas *ee EINA_UNUSED, int *x, int *y, int *w, int *h) +#ifdef BUILD_ECORE_EVAS_GL_DRM +EAPI Ecore_Evas * +ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, int x, int y, int w, int h) { - ecore_drm_outputs_geometry_get(dev, x, y, w, h); -} + Ecore_Evas *ee; + Evas_Engine_Info_GL_Drm *einfo; + Ecore_Evas_Interface_Drm *iface; + Ecore_Evas_Engine_Drm_Data *edata; + int method; -static void -_ecore_evas_drm_pointer_xy_get(const Ecore_Evas *ee EINA_UNUSED, Evas_Coord *x, Evas_Coord *y) -{ - /* get pointer position from input */ - ecore_drm_device_pointer_xy_get(dev, x, y); -} + method = evas_render_method_lookup("gl_drm"); + if (!method) return NULL; -Eina_Bool -_ecore_evas_drm_pointer_warp(const Ecore_Evas *ee EINA_UNUSED, Evas_Coord x, Evas_Coord y) -{ - ecore_drm_device_pointer_warp(dev, x, y); - return EINA_TRUE; + ee = calloc(1, sizeof(Ecore_Evas)); + if (!ee) return NULL; + + edata = calloc(1, sizeof(Ecore_Evas_Engine_Drm_Data)); + if (!edata) + { + free(ee); + return NULL; + } + + edata->x = x; + edata->y = y; + edata->w = w; + edata->h = h; + edata->depth = 24; // FIXME: Remove hardcode + edata->bpp = 32; // FIXME: Remove hardcode + edata->format = DRM_FORMAT_XRGB8888; + + dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL); + if (dlerror()) + { + free(edata); + free(ee); + return NULL; + } + + if (_ecore_evas_drm_init(edata, device) < 1) + { + free(edata); + free(ee); + return NULL; + } + + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); + + ee->driver = "gl_drm"; + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func; + ee->engine.data = edata; + + /* FIXME */ + /* if (edata->device) ee->name = strdup(edata->device); */ + + iface = _ecore_evas_drm_interface_new(); + ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface); + + ee->x = ee->req.x = x; + ee->y = ee->req.y = y; + ee->w = ee->req.w = w; + ee->h = ee->req.h = h; + + ee->prop.max.w = 32767; + ee->prop.max.h = 32767; + ee->prop.layer = 4; + ee->prop.request_pos = 0; + ee->prop.sticky = 0; + ee->prop.withdrawn = EINA_TRUE; + ee->alpha = EINA_FALSE; + + ee->can_async_render = 0; // FIXME ?? + if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER")) + ee->can_async_render = 0; + + ee->evas = evas_new(); + evas_data_attach_set(ee->evas, ee); + evas_output_method_set(ee->evas, method); + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + if (ee->can_async_render) + evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST, + _drm_render_updates, ee); + + einfo = (Evas_Engine_Info_GL_Drm *)evas_engine_info_get(ee->evas); + if (einfo) + { + char *num; + + einfo->info.vsync = EINA_TRUE; + + num = getenv("EVAS_DRM_VSYNC"); + if ((num) && (!atoi(num))) + einfo->info.vsync = EINA_FALSE; + + einfo->info.fd = edata->fd; + einfo->info.bpp = edata->bpp; + einfo->info.depth = edata->depth; + einfo->info.format = edata->format; + einfo->info.rotation = ee->rotation; + einfo->info.output = edata->output; + if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) + { + ERR("evas_engine_info_set() for engine '%s' failed", ee->driver); + goto eng_err; + } + } + + ee->prop.window = ecore_drm2_output_crtc_get(edata->output); + ecore_drm2_device_window_set(edata->dev, ee->prop.window); + + ecore_evas_data_set(ee, "device", edata->dev); + + _ecore_evas_register(ee); + ecore_evas_input_event_register(ee); + ecore_event_window_register(ee->prop.window, ee, ee->evas, + (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, + (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, + (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, + (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); + + return ee; + +eng_err: + ecore_evas_free(ee); + return NULL; } +#endif From b1892111b1fa17cbe2b53696d091a12f27ff85a1 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 18 May 2016 14:33:37 -0400 Subject: [PATCH 10/35] elementary: Port elementary to use Ecore_Drm2 Signed-off-by: Chris Michael --- src/lib/elementary/elm_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ #include #endif #ifdef HAVE_ELEMENTARY_DRM -#include +#include #endif #ifdef HAVE_ELEMENTARY_COCOA /* Ecore_Cocoa is still in Beta. In Elementary, we know what we are From 758ce917193d82462d684ddbaad6d6a493a2cf41 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:21:17 -0400 Subject: [PATCH 11/35] ecore-drm2: Add API functions to get/set if an output is primary Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 23 +++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 14 ++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 480b373617..bcbffcb958 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -391,6 +391,29 @@ EAPI void ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb */ EAPI void ecore_drm2_output_crtc_size_get(Ecore_Drm2_Output *output, int *w, int *h); +/** + * Get if a given output is marked as the primary output + * + * @param output + * + * @return EINA_TRUE if output is primary, EINA_FALSE otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_output_primary_get(Ecore_Drm2_Output *output); + +/** + * Set a given output to be primary + * + * @param output + * @param primary + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_primary_set(Ecore_Drm2_Output *output, Eina_Bool primary); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 9922cd7f82..285ca84c91 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -917,3 +917,17 @@ ecore_drm2_output_crtc_size_get(Ecore_Drm2_Output *output, int *w, int *h) drmModeFreeCrtc(crtc); } + +EAPI Eina_Bool +ecore_drm2_output_primary_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + return output->primary; +} + +EAPI void +ecore_drm2_output_primary_set(Ecore_Drm2_Output *output, Eina_Bool primary) +{ + EINA_SAFETY_ON_NULL_RETURN(output); + output->primary = primary; +} From b634f9485a837bd1a3a708a23f996c70d53ce138 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:24:12 -0400 Subject: [PATCH 12/35] ecore-drm2: Add API functions to get/set if an output is enabled Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 23 +++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index bcbffcb958..3b4ffdfebc 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -414,6 +414,29 @@ EAPI Eina_Bool ecore_drm2_output_primary_get(Ecore_Drm2_Output *output); */ EAPI void ecore_drm2_output_primary_set(Ecore_Drm2_Output *output, Eina_Bool primary); +/** + * Get if a given output is enabled + * + * @param output + * + * @return EINA_TRUE if enabled, EINA_FALSE otherwise. + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_output_enabled_get(Ecore_Drm2_Output *output); + +/** + * Set if a given output is enabled + * + * @param output + * @param enabled + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_enabled_set(Ecore_Drm2_Output *output, Eina_Bool enabled); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 285ca84c91..553c91101c 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -931,3 +931,26 @@ ecore_drm2_output_primary_set(Ecore_Drm2_Output *output, Eina_Bool primary) EINA_SAFETY_ON_NULL_RETURN(output); output->primary = primary; } + +EAPI Eina_Bool +ecore_drm2_output_enabled_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + return output->enabled; +} + +EAPI void +ecore_drm2_output_enabled_set(Ecore_Drm2_Output *output, Eina_Bool enabled) +{ + EINA_SAFETY_ON_NULL_RETURN(output); + + if (output->enabled == enabled) return; + output->enabled = enabled; + + if (output->enabled) + ecore_drm2_output_dpms_set(output, DRM_MODE_DPMS_ON); + else + ecore_drm2_output_dpms_set(output, DRM_MODE_DPMS_OFF); + + _output_event_send(output); +} From ad58670c5632b6ce5dcb9d8afc7f04e1f8d7c0e3 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:25:36 -0400 Subject: [PATCH 13/35] ecore-drm2: Add API function to return physical size of a given output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 14 ++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 3b4ffdfebc..41c1b41323 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -437,6 +437,20 @@ EAPI Eina_Bool ecore_drm2_output_enabled_get(Ecore_Drm2_Output *output); */ EAPI void ecore_drm2_output_enabled_set(Ecore_Drm2_Output *output, Eina_Bool enabled); +/** + * Get the physical size of a given output + * + * This function will give the physical size (in mm) of an output + * + * @param output + * @param *w + * @param *h + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_physical_size_get(Ecore_Drm2_Output *output, int *w, int *h); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 553c91101c..1c8c576fc6 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -954,3 +954,15 @@ ecore_drm2_output_enabled_set(Ecore_Drm2_Output *output, Eina_Bool enabled) _output_event_send(output); } + +EAPI void +ecore_drm2_output_physical_size_get(Ecore_Drm2_Output *output, int *w, int *h) +{ + if (w) *w = 0; + if (h) *h = 0; + + EINA_SAFETY_ON_NULL_RETURN(output); + + if (w) *w = output->pw; + if (h) *h = output->ph; +} From ed58056e06a7b3bd2eb6d9c329cedc90ce353f07 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:26:52 -0400 Subject: [PATCH 14/35] ecore-drm2: Add API function to return list of output modes for a given output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 14 ++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 41c1b41323..7032afedbe 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -451,6 +451,20 @@ EAPI void ecore_drm2_output_enabled_set(Ecore_Drm2_Output *output, Eina_Bool ena */ EAPI void ecore_drm2_output_physical_size_get(Ecore_Drm2_Output *output, int *w, int *h); +/** + * Get a list of the modes supported on a given output + * + * @param output + * + * @return An Eina_List of the modes supported for this output + * + * @note The returned list should not be freed + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI const Eina_List *ecore_drm2_output_modes_get(Ecore_Drm2_Output *output); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 1c8c576fc6..83ff1f3587 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -966,3 +966,10 @@ ecore_drm2_output_physical_size_get(Ecore_Drm2_Output *output, int *w, int *h) if (w) *w = output->pw; if (h) *h = output->ph; } + +EAPI const Eina_List * +ecore_drm2_output_modes_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); + return output->modes; +} From 55f228a238ed93fa3e18af8531691371ce96eb36 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:28:20 -0400 Subject: [PATCH 15/35] ecore-drm2: Add API function to return information about a given output mode Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 14 ++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 7032afedbe..508c0fd91f 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -465,6 +465,20 @@ EAPI void ecore_drm2_output_physical_size_get(Ecore_Drm2_Output *output, int *w, */ EAPI const Eina_List *ecore_drm2_output_modes_get(Ecore_Drm2_Output *output); +/** + * Get information from an existing output mode + * + * @param mode + * @param w + * @param h + * @param refresh + * @param flags + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_mode_info_get(Ecore_Drm2_Output_Mode *mode, int *w, int *h, unsigned int *refresh, unsigned int *flags); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 83ff1f3587..0f89fe748a 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -973,3 +973,19 @@ ecore_drm2_output_modes_get(Ecore_Drm2_Output *output) EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); return output->modes; } + +EAPI void +ecore_drm2_output_mode_info_get(Ecore_Drm2_Output_Mode *mode, int *w, int *h, unsigned int *refresh, unsigned int *flags) +{ + if (w) *w = 0; + if (h) *h = 0; + if (refresh) *refresh = 0; + if (flags) *flags = 0; + + EINA_SAFETY_ON_NULL_RETURN(mode); + + if (w) *w = mode->width; + if (h) *h = mode->height; + if (refresh) *refresh = mode->refresh; + if (flags) *flags = mode->flags; +} From a6b018a2a8283e9244182152cc9187db818b7b63 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:29:48 -0400 Subject: [PATCH 16/35] ecore-drm2: Add API function to set the mode of an output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 15 +++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 43 +++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 508c0fd91f..df07a3316e 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -479,6 +479,21 @@ EAPI const Eina_List *ecore_drm2_output_modes_get(Ecore_Drm2_Output *output); */ EAPI void ecore_drm2_output_mode_info_get(Ecore_Drm2_Output_Mode *mode, int *w, int *h, unsigned int *refresh, unsigned int *flags); +/** + * Set a given mode to be used on a given output + * + * @param output + * @param mode + * @param x + * @param y + * + * @return EINA_TRUE on success, EINA_FALSE otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_output_mode_set(Ecore_Drm2_Output *output, Ecore_Drm2_Output_Mode *mode, int x, int y); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 0f89fe748a..4a4fe0bd99 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -989,3 +989,46 @@ ecore_drm2_output_mode_info_get(Ecore_Drm2_Output_Mode *mode, int *w, int *h, un if (refresh) *refresh = mode->refresh; if (flags) *flags = mode->flags; } + +EAPI Eina_Bool +ecore_drm2_output_mode_set(Ecore_Drm2_Output *output, Ecore_Drm2_Output_Mode *mode, int x, int y) +{ + Eina_Bool ret = EINA_TRUE; + unsigned int buffer = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL((output->fd < 0), EINA_FALSE); + + output->x = x; + output->y = y; + output->current_mode = mode; + + if (mode) + { + if (output->current) + buffer = output->current->id; + else if (output->next) + buffer = output->next->id; + else + buffer = output->ocrtc->buffer_id; + + if (drmModeSetCrtc(output->fd, output->crtc_id, buffer, + x, y, &output->conn_id, 1, &mode->info) < 0) + { + ERR("Failed to set Mode %dx%d for Output %s: %m", + mode->width, mode->height, output->name); + ret = EINA_FALSE; + } + } + else + { + if (drmModeSetCrtc(output->fd, output->crtc_id, 0, + 0, 0, 0, 0, NULL) < 0) + { + ERR("Failed to turn off Output %s: %m", output->name); + ret = EINA_FALSE; + } + } + + return ret; +} From bdddc912d78a028c3e6066ead64bdc868536a2ab Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:31:38 -0400 Subject: [PATCH 17/35] ecore-drm2: Add API functions to get name & model of an output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 24 ++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 16 ++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index df07a3316e..390f5d057a 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -494,6 +494,30 @@ EAPI void ecore_drm2_output_mode_info_get(Ecore_Drm2_Output_Mode *mode, int *w, */ EAPI Eina_Bool ecore_drm2_output_mode_set(Ecore_Drm2_Output *output, Ecore_Drm2_Output_Mode *mode, int x, int y); +/** + * Get the name of a given output + * + * @param output + * + * @return A string representing the output's name. Caller should free this return. + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI char *ecore_drm2_output_name_get(Ecore_Drm2_Output *output); + +/** + * Get the model of a given output + * + * @param output + * + * @return A string representing the output's model. Caller should free this return. + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI char *ecore_drm2_output_model_get(Ecore_Drm2_Output *output); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 4a4fe0bd99..8b909bef28 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -1032,3 +1032,19 @@ ecore_drm2_output_mode_set(Ecore_Drm2_Output *output, Ecore_Drm2_Output_Mode *mo return ret; } + +EAPI char * +ecore_drm2_output_name_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->name, NULL); + return strdup(output->name); +} + +EAPI char * +ecore_drm2_output_model_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(output->model, NULL); + return strdup(output->model); +} From bd2ab7de9636ef55809ae997226e7d2b5be7448a Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:33:15 -0400 Subject: [PATCH 18/35] ecore-drm2: Add API function to get cloned & connected properties of an output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 24 ++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 14 ++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 390f5d057a..e9250ecab7 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -518,6 +518,30 @@ EAPI char *ecore_drm2_output_name_get(Ecore_Drm2_Output *output); */ EAPI char *ecore_drm2_output_model_get(Ecore_Drm2_Output *output); +/** + * Get if a given output is connected + * + * @param output + * + * @return EINA_TRUE if connected, EINA_FALSE otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_output_connected_get(Ecore_Drm2_Output *output); + +/** + * Get if a given output is cloned + * + * @param output + * + * @return EINA_TRUE if cloned, EINA_FALSE otherwise. + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_output_cloned_get(Ecore_Drm2_Output *output); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 8b909bef28..a39117ab50 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -1048,3 +1048,17 @@ ecore_drm2_output_model_get(Ecore_Drm2_Output *output) EINA_SAFETY_ON_NULL_RETURN_VAL(output->model, NULL); return strdup(output->model); } + +EAPI Eina_Bool +ecore_drm2_output_connected_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + return output->connected; +} + +EAPI Eina_Bool +ecore_drm2_output_cloned_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + return output->cloned; +} From 1eb85aab57b1663d95889cb58924dd761f0e9ecd Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:34:32 -0400 Subject: [PATCH 19/35] ecore-drm2: Add API function to return connector type of an output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 12 ++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index e9250ecab7..9792395d06 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -542,6 +542,18 @@ EAPI Eina_Bool ecore_drm2_output_connected_get(Ecore_Drm2_Output *output); */ EAPI Eina_Bool ecore_drm2_output_cloned_get(Ecore_Drm2_Output *output); +/** + * Get the connector type of a given output + * + * @param output + * + * @return An unsigned integer representing the type of connector for this output + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI unsigned int ecore_drm2_output_connector_type_get(Ecore_Drm2_Output *output); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index a39117ab50..da2ca928ca 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -1062,3 +1062,10 @@ ecore_drm2_output_cloned_get(Ecore_Drm2_Output *output) EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); return output->cloned; } + +EAPI unsigned int +ecore_drm2_output_connector_type_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0); + return output->conn_type; +} From d08d7e18e3a43f12ee9c109031a80b950d552868 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:36:34 -0400 Subject: [PATCH 20/35] ecore-drm2: Add API to return current resolution of a given output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 13 +++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 9792395d06..494d03ad83 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -554,6 +554,19 @@ EAPI Eina_Bool ecore_drm2_output_cloned_get(Ecore_Drm2_Output *output); */ EAPI unsigned int ecore_drm2_output_connector_type_get(Ecore_Drm2_Output *output); +/** + * Get the current resolution of a given output + * + * @param output + * @param *w + * @param *h + * @param *refresh + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI void ecore_drm2_output_resolution_get(Ecore_Drm2_Output *output, int *w, int *h, unsigned int *refresh); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index da2ca928ca..87f962861c 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -1069,3 +1069,18 @@ ecore_drm2_output_connector_type_get(Ecore_Drm2_Output *output) EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0); return output->conn_type; } + +EAPI void +ecore_drm2_output_resolution_get(Ecore_Drm2_Output *output, int *w, int *h, unsigned int *refresh) +{ + if (w) *w = 0; + if (h) *h = 0; + if (refresh) *refresh = 0; + + EINA_SAFETY_ON_NULL_RETURN(output); + EINA_SAFETY_ON_TRUE_RETURN(!output->current_mode); + + if (w) *w = output->current_mode->width; + if (h) *h = output->current_mode->height; + if (refresh) *refresh = output->current_mode->refresh; +} From 253f88b3ec596d47b3d0c63d3bead3d8c0bdef5c Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:37:50 -0400 Subject: [PATCH 21/35] ecore-drm2: Add API to return current fb used on a given output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 12 ++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 494d03ad83..925a9466b9 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -368,6 +368,18 @@ EAPI unsigned int ecore_drm2_output_crtc_get(Ecore_Drm2_Output *output); */ EAPI Ecore_Drm2_Fb *ecore_drm2_output_next_fb_get(Ecore_Drm2_Output *output); +/** + * Return the current Ecore_Drm2_Fb used on a given output + * + * @param output + * + * @return The current Ecore_Drm2_Fb used on this output, or NULL otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Ecore_Drm2_Fb *ecore_drm2_output_current_fb_get(Ecore_Drm2_Output *output); + /** * Set the next Ecore_Drm2_Fb to be used on a given output * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 87f962861c..b55c0d8417 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -899,6 +899,13 @@ ecore_drm2_output_next_fb_set(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *fb) output->next = fb; } +EAPI Ecore_Drm2_Fb * +ecore_drm2_output_current_fb_get(Ecore_Drm2_Output *output) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL); + return output->current; +} + EAPI void ecore_drm2_output_crtc_size_get(Ecore_Drm2_Output *output, int *w, int *h) { From 0c0dd22b5f22d683e92aa3ddc454a882805ea636 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:39:46 -0400 Subject: [PATCH 22/35] ecore-drm2: Add API function to get possible crtc of a given output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 16 ++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 66 ++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 925a9466b9..f06fa409eb 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -579,6 +579,22 @@ EAPI unsigned int ecore_drm2_output_connector_type_get(Ecore_Drm2_Output *output */ EAPI void ecore_drm2_output_resolution_get(Ecore_Drm2_Output *output, int *w, int *h, unsigned int *refresh); +/** + * Get if an output can be used on a given crtc + * + * This function will loop the possible crtcs of an encoder to determine if + * a given output can be assigned to a given crtc + * + * @param output + * @param crtc + * + * @return EINA_TRUE if the output can be assigned to given crtc, EINA_FALSE otherwise + * + * @ingroup Ecore_Drm2_Output_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_output_possible_crtc_get(Ecore_Drm2_Output *output, unsigned int crtc); + /** * @defgroup Ecore_Drm2_Fb_Group Drm framebuffer functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index b55c0d8417..1b9313f000 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -219,7 +219,7 @@ static int _output_crtc_find(const drmModeRes *res, const drmModeConnector *conn, Ecore_Drm2_Device *dev) { drmModeEncoder *enc; - uint32_t pcrtcs; + uint32_t crtc; int i = 0, j = 0; for (j = 0; j < conn->count_encoders; j++) @@ -227,15 +227,12 @@ _output_crtc_find(const drmModeRes *res, const drmModeConnector *conn, Ecore_Drm enc = drmModeGetEncoder(dev->fd, conn->encoders[j]); if (!enc) continue; - pcrtcs = enc->possible_crtcs; + crtc = enc->crtc_id; drmModeFreeEncoder(enc); for (i = 0; i < res->count_crtcs; i++) - { - if ((pcrtcs & (1 << i)) && - (!(dev->alloc.crtc & (1 << res->crtcs[i])))) - return i; - } + if (crtc == res->crtcs[i]) + return i; } return -1; @@ -1091,3 +1088,58 @@ ecore_drm2_output_resolution_get(Ecore_Drm2_Output *output, int *w, int *h, unsi if (h) *h = output->current_mode->height; if (refresh) *refresh = output->current_mode->refresh; } + +EAPI Eina_Bool +ecore_drm2_output_possible_crtc_get(Ecore_Drm2_Output *output, unsigned int crtc) +{ + drmModeRes *res; + drmModeConnector *conn; + drmModeEncoder *enc; + int i = 0, j = 0, k = 0; + unsigned int p = 0; + Eina_Bool ret = EINA_FALSE; + + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL((output->fd < 0), EINA_FALSE); + + res = drmModeGetResources(output->fd); + if (!res) return EINA_FALSE; + + for (; i < res->count_connectors; i++) + { + conn = drmModeGetConnector(output->fd, res->connectors[i]); + if (!conn) continue; + + for (j = 0; j < conn->count_encoders; j++) + { + enc = drmModeGetEncoder(output->fd, conn->encoders[j]); + if (!enc) continue; + + if (enc->crtc_id != crtc) goto next; + + p = enc->possible_crtcs; + + for (k = 0; k < res->count_crtcs; k++) + { + if (res->crtcs[k] != output->crtc_id) continue; + + if (p & (1 << k)) + { + ret = EINA_TRUE; + break; + } + } + +next: + drmModeFreeEncoder(enc); + if (ret) break; + } + + drmModeFreeConnector(conn); + if (ret) break; + } + + drmModeFreeResources(res); + + return ret; +} From f3b767255154454fe43c5d40f3d9b3b7a97b96c0 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:41:21 -0400 Subject: [PATCH 23/35] ecore-drm2: Add API function to return available crtcs Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 13 +++++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index f06fa409eb..3d3c7d0e91 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -228,6 +228,19 @@ EAPI void ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int w */ EAPI void ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h); +/** + * Get the crtcs of a given device + * + * @param device + * @param num + * + * @return The crtcs of this given device or NULL on failure + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI unsigned int *ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num); + /** * @defgroup Ecore_Drm2_Output_Group Drm output functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index 4b3afea2b1..550d6e3afb 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -259,3 +259,12 @@ ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h) elput_input_pointer_max_set(device->em, w, h); } + +EAPI unsigned int * +ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL); + + if (num) *num = device->num_crtcs; + return device->crtcs; +} From e934f546ad10e6aed599d7f4968e8c19871bfcd2 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:42:42 -0400 Subject: [PATCH 24/35] ecore-drm2: Add API function to get screen size range Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 14 ++++++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 16 ++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_outputs.c | 4 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 3d3c7d0e91..4872793b17 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -241,6 +241,20 @@ EAPI void ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, in */ EAPI unsigned int *ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num); +/** + * Get the minimum and maximum screen size range + * + * @param device + * @param *minw + * @param *minh + * @param *maxw + * @param *maxh + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, int *minh, int *maxw, int *maxh); + /** * @defgroup Ecore_Drm2_Output_Group Drm output functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index 550d6e3afb..ec180adade 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -268,3 +268,19 @@ ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num) if (num) *num = device->num_crtcs; return device->crtcs; } + +EAPI void +ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, int *minh, int *maxw, int *maxh) +{ + if (minw) *minw = 0; + if (minh) *minh = 0; + if (maxw) *maxw = 0; + if (maxh) *maxh = 0; + + EINA_SAFETY_ON_NULL_RETURN(device); + + if (minw) *minw = device->min.width; + if (minh) *minh = device->min.height; + if (maxw) *maxw = device->max.width; + if (maxh) *maxh = device->max.height; +} diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 1b9313f000..81e0018047 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -58,8 +58,8 @@ _output_debug(Ecore_Drm2_Output *output, const drmModeConnector *conn) EINA_LIST_FOREACH(output->modes, l, omode) { - DBG("\tAdded Mode: %dx%d@%.1f%s%s%s", - omode->width, omode->height, (omode->refresh / 1000.0), + DBG("\tAdded Mode: %dx%d@%d%s%s%s", + omode->width, omode->height, omode->refresh, (omode->flags & DRM_MODE_TYPE_PREFERRED) ? ", preferred" : "", (omode->flags & DRM_MODE_TYPE_DEFAULT) ? ", current" : "", (conn->count_modes == 0) ? ", built-in" : ""); From 6697584fb9d553c2cd317ab3adffba04b5f710a3 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:43:53 -0400 Subject: [PATCH 25/35] ecore-drm2: Fix potential invalid access to output current_mode Signed-off-by: Chris Michael --- src/lib/ecore_drm2/ecore_drm2_outputs.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 81e0018047..7596164f73 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -90,11 +90,21 @@ _output_event_send(Ecore_Drm2_Output *output) ev->x = output->x; ev->y = output->y; - ev->w = output->current_mode->width; - ev->h = output->current_mode->height; + if (output->current_mode) + { + ev->w = output->current_mode->width; + ev->h = output->current_mode->height; + ev->refresh = output->current_mode->refresh; + } + else + { + ev->w = output->ocrtc->width; + ev->h = output->ocrtc->height; + ev->refresh = 0; + } + ev->phys_width = output->pw; ev->phys_height = output->ph; - ev->refresh = output->current_mode->refresh; ev->scale = output->scale; ev->subpixel = output->subpixel; From 92553e167e6c03611e299f41fe538f8963e45723 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 11 May 2016 09:45:38 -0400 Subject: [PATCH 26/35] ecore-drm2: Initialize elput input when device gets opened Signed-off-by: Chris Michael --- src/lib/ecore_drm2/ecore_drm2_device.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index ec180adade..530adcf6d9 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -134,6 +134,12 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device) device->fd = elput_manager_open(device->em, device->path, -1); + if (!elput_input_init(device->em, NULL)) + { + ERR("Could not initialize Elput Input"); + goto err; + } + DBG("Device Path: %s", device->path); DBG("Device Fd: %d", device->fd); @@ -146,6 +152,10 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device) /* ERR("Could not set Universal Plane support: %m"); */ return device->fd; + +err: + elput_manager_close(device->em, device->fd); + return -1; } EAPI void @@ -154,6 +164,7 @@ ecore_drm2_device_close(Ecore_Drm2_Device *device) EINA_SAFETY_ON_NULL_RETURN(device); EINA_SAFETY_ON_TRUE_RETURN(device->fd < 0); + elput_input_shutdown(device->em); elput_manager_close(device->em, device->fd); } From 8b3e05a7f1d5f7e96047d6c11d6e807c96a3b5ed Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Sat, 14 May 2016 04:13:38 -0400 Subject: [PATCH 27/35] ecore-drm2: Check return of elput_manager_open We should check to make sure that opening the device has succeeded before trying to continue Signed-off-by: Chris Michael --- src/lib/ecore_drm2/ecore_drm2_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index 530adcf6d9..5c42902940 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -133,11 +133,12 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device) EINA_SAFETY_ON_NULL_RETURN_VAL(device, -1); device->fd = elput_manager_open(device->em, device->path, -1); + if (device->fd < 0) goto open_err; if (!elput_input_init(device->em, NULL)) { ERR("Could not initialize Elput Input"); - goto err; + goto input_err; } DBG("Device Path: %s", device->path); @@ -153,8 +154,9 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device) return device->fd; -err: +input_err: elput_manager_close(device->em, device->fd); +open_err: return -1; } From bdcd84cd2cf3a9f30b38963af66d826487c8ed11 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Fri, 20 May 2016 11:46:46 -0500 Subject: [PATCH 28/35] evas-drm: Don't re-use the current buffer immediately If we don't block the current buffer from being assigned to the new current buffer we'll end up rendering into the same buffer over and over and never actually double buffer. --- src/modules/evas/engines/drm/evas_outbuf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c index 4c87f2df2f..38feffd029 100644 --- a/src/modules/evas/engines/drm/evas_outbuf.c +++ b/src/modules/evas/engines/drm/evas_outbuf.c @@ -357,6 +357,7 @@ _outbuf_fb_wait(Outbuf *ob) { for (i = 0; i < ob->priv.num; i++) { + if (&ob->priv.ofb[i] == ob->priv.current) continue; if (ob->priv.ofb[i].busy) continue; if (ob->priv.ofb[i].valid) return &(ob->priv.ofb[i]); } From 5535c049cdfeb0a5a3b192b08ccfeec7a78c7c99 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Fri, 20 May 2016 11:56:38 -0500 Subject: [PATCH 29/35] evas-drm: Fix occasoinaly freezes We need to continue to tick even if we can't find a buffer - otherwise we'll stop updating forever. We also need to reset buffer busy bits to 0 if we run out of buffers or we'll never try to assign one. (The page flip handler would eventually clear the busy bit for the current buffer, but a few lines ago we just set that to NULL so it will never happen...) --- src/modules/evas/engines/drm/evas_outbuf.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c index 38feffd029..ce7be06462 100644 --- a/src/modules/evas/engines/drm/evas_outbuf.c +++ b/src/modules/evas/engines/drm/evas_outbuf.c @@ -50,15 +50,8 @@ _outbuf_tick_source_set(Outbuf *ob) static void _outbuf_tick_schedule(int fd EINA_UNUSED, void *data) { - Outbuf *ob; - Outbuf_Fb *ofb; - - ob = data; if (!ticking) return; - ofb = ob->priv.current; - if (!ofb) return; - drmVBlank vbl = { .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, @@ -382,6 +375,7 @@ _outbuf_fb_assign(Outbuf *ob) { if (ob->priv.ofb[i].valid) { + ob->priv.ofb[i].busy = 0; ob->priv.ofb[i].age = 0; ob->priv.ofb[i].drawn = EINA_FALSE; } From 7b5af2f0df36e896878c3609ec870ecd73c953f5 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Tue, 24 May 2016 09:32:21 -0400 Subject: [PATCH 30/35] ecore-drm2: Add API function to set left-handed mouse mode This commit adds an API function used to set a mouse to be left-handed @feature Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 13 +++++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 4872793b17..0afe1054ac 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -205,6 +205,19 @@ EAPI void ecore_drm2_device_pointer_xy_get(Ecore_Drm2_Device *device, int *x, in */ EAPI void ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y); +/** + * Set a left handed mode for the given device + * + * @param device + * @param left + * + * @return EINA_TRUE on success, EINA_FALSE otherwise + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI Eina_Bool ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device *device, Eina_Bool left); + /** * Set which window is to be used for input events * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index 5c42902940..1e9ded816e 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -240,6 +240,14 @@ ecore_drm2_device_pointer_warp(Ecore_Drm2_Device *device, int x, int y) elput_input_pointer_xy_set(device->em, NULL, x, y); } +EAPI Eina_Bool +ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device *device, Eina_Bool left) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE); + + return elput_input_pointer_left_handed_set(device->em, NULL, left); +} + EAPI void ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window) { From c1253164b2bc944b37b5d04b7b5814f6bbcde8bb Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Mon, 23 May 2016 12:53:49 -0400 Subject: [PATCH 31/35] ecore-drm2: perform logind connection after finding device path in ecore_drm2_device_find --- src/lib/ecore_drm2/ecore_drm2_device.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index 1e9ded816e..ca43bcff95 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -104,13 +104,6 @@ ecore_drm2_device_find(const char *seat, unsigned int tty, Eina_Bool sync) dev = calloc(1, sizeof(Ecore_Drm2_Device)); if (!dev) return NULL; - dev->em = elput_manager_connect(seat, tty, sync); - if (!dev->em) - { - ERR("Could not connect to input manager"); - goto man_err; - } - dev->path = _drm2_device_find(seat); if (!dev->path) { @@ -118,11 +111,18 @@ ecore_drm2_device_find(const char *seat, unsigned int tty, Eina_Bool sync) goto path_err; } + dev->em = elput_manager_connect(seat, tty, sync); + if (!dev->em) + { + ERR("Could not connect to input manager"); + goto man_err; + } + return dev; -path_err: - elput_manager_disconnect(dev->em); man_err: + eina_stringshare_del(dev->path); +path_err: free(dev); return NULL; } From da8bcbc7c64da8e02543f201675d42b58760b21f Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 24 May 2016 16:18:46 -0400 Subject: [PATCH 32/35] ecore-drm2: update to latest elput --- src/lib/ecore_drm2/Ecore_Drm2.h | 2 +- src/lib/ecore_drm2/ecore_drm2_device.c | 24 ++++--------------- .../ecore_evas/engines/drm/ecore_evas_drm.c | 2 +- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 0afe1054ac..c083d1a9f2 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -123,7 +123,7 @@ EAPI int ecore_drm2_shutdown(void); * @ingroup Ecore_Drm2_Device_Group * @since 1.18 */ -EAPI Ecore_Drm2_Device *ecore_drm2_device_find(const char *seat, unsigned int tty, Eina_Bool sync); +EAPI Ecore_Drm2_Device *ecore_drm2_device_find(const char *seat, unsigned int tty); /** * Try to open a given Ecore_Drm2_Device diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index ca43bcff95..df4f99173f 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -97,7 +97,7 @@ out: } EAPI Ecore_Drm2_Device * -ecore_drm2_device_find(const char *seat, unsigned int tty, Eina_Bool sync) +ecore_drm2_device_find(const char *seat, unsigned int tty) { Ecore_Drm2_Device *dev; @@ -111,7 +111,7 @@ ecore_drm2_device_find(const char *seat, unsigned int tty, Eina_Bool sync) goto path_err; } - dev->em = elput_manager_connect(seat, tty, sync); + dev->em = elput_manager_connect(seat, tty); if (!dev->em) { ERR("Could not connect to input manager"); @@ -135,7 +135,7 @@ ecore_drm2_device_open(Ecore_Drm2_Device *device) device->fd = elput_manager_open(device->em, device->path, -1); if (device->fd < 0) goto open_err; - if (!elput_input_init(device->em, NULL)) + if (!elput_input_init(device->em)) { ERR("Could not initialize Elput Input"); goto input_err; @@ -251,25 +251,9 @@ ecore_drm2_device_pointer_left_handed_set(Ecore_Drm2_Device *device, Eina_Bool l EAPI void ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int window) { - const Eina_List *seats, *l; - const Eina_List *devs, *ll; - Elput_Seat *seat; - Elput_Device *dev; - EINA_SAFETY_ON_NULL_RETURN(device); EINA_SAFETY_ON_NULL_RETURN(device->em); - - seats = elput_manager_seats_get(device->em); - if (!seats) return; - - EINA_LIST_FOREACH(seats, l, seat) - { - devs = elput_input_devices_get(seat); - if (!devs) continue; - - EINA_LIST_FOREACH(devs, ll, dev) - elput_device_window_set(dev, window); - } + elput_manager_window_set(device->em, window); } EAPI void 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 3cdc7011f3..f6f4e0c0a9 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -70,7 +70,7 @@ _ecore_evas_drm_init(Ecore_Evas_Engine_Drm_Data *edata, const char *device) if (!device) device = "seat0"; - edata->dev = ecore_drm2_device_find(device, 0, EINA_TRUE); + edata->dev = ecore_drm2_device_find(device, 0); if (!edata->dev) { ERR("Failed to create device"); From 0416aa6bf34f19d618d84344f6cfd22f4774609f Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 26 May 2016 10:43:35 -0400 Subject: [PATCH 33/35] ecore-drm2: Add API function to calibrate input devices This adds a new API function that Ecore_Evas can call to calibrate input devices given size of the output Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 12 ++++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index c083d1a9f2..d8a1c3e31c 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -268,6 +268,18 @@ EAPI unsigned int *ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *n */ EAPI void ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, int *minh, int *maxw, int *maxh); +/** + * Calibrate any input devices for given screen size + * + * @param device + * @param w + * @param h + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_calibrate(Ecore_Drm2_Device *device, int w, int h); + /** * @defgroup Ecore_Drm2_Output_Group Drm output functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index df4f99173f..b4948d4121 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -289,3 +289,11 @@ ecore_drm2_device_screen_size_range_get(Ecore_Drm2_Device *device, int *minw, in if (maxw) *maxw = device->max.width; if (maxh) *maxh = device->max.height; } + +EAPI void +ecore_drm2_device_calibrate(Ecore_Drm2_Device *device, int w, int h) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + + elput_input_devices_calibrate(device->em, w, h); +} From 593961c2e21b1bb1023e04231619d21af30ab767 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 26 May 2016 10:46:40 -0400 Subject: [PATCH 34/35] ecore-evas-drm: Fix issue of mouse pointer not centering on startup This patch fixes an issue where starting Enlightenment would not center the mouse pointer. Basically the issue is that we cannot warp the mouse pointer until After the ee->prop.window has been set else E will not process the mouse_move event @fix Signed-off-by: Chris Michael --- .../ecore_evas/engines/drm/ecore_evas_drm.c | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) 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 f6f4e0c0a9..e14254b381 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -58,8 +58,6 @@ static int _drm_init_count = 0; static int _ecore_evas_drm_init(Ecore_Evas_Engine_Drm_Data *edata, const char *device) { - int mw, mh; - if (++_drm_init_count != 1) return _drm_init_count; if (!ecore_drm2_init()) @@ -97,9 +95,6 @@ _ecore_evas_drm_init(Ecore_Evas_Engine_Drm_Data *edata, const char *device) if (!edata->output) WRN("Could not find output at %d %d", edata->x, edata->y); - ecore_drm2_output_crtc_size_get(edata->output, &mw, &mh); - ecore_drm2_device_pointer_max_set(edata->dev, mw, mh); - ecore_event_evas_init(); return _drm_init_count; @@ -678,7 +673,7 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, Evas_Engine_Info_Drm *einfo; Ecore_Evas_Interface_Drm *iface; Ecore_Evas_Engine_Drm_Data *edata; - int method; + int method, mw, mh; method = evas_render_method_lookup("drm"); if (!method) return NULL; @@ -776,6 +771,12 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); + ecore_drm2_output_crtc_size_get(edata->output, &mw, &mh); + + ecore_drm2_device_calibrate(edata->dev, mw, mh); + ecore_drm2_device_pointer_max_set(edata->dev, mw, mh); + ecore_drm2_device_pointer_warp(edata->dev, mw / 2, mh / 2); + return ee; eng_err: @@ -791,7 +792,7 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS Evas_Engine_Info_GL_Drm *einfo; Ecore_Evas_Interface_Drm *iface; Ecore_Evas_Engine_Drm_Data *edata; - int method; + int method, mw, mh; method = evas_render_method_lookup("gl_drm"); if (!method) return NULL; @@ -905,6 +906,12 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process); + ecore_drm2_output_crtc_size_get(edata->output, &mw, &mh); + + ecore_drm2_device_calibrate(edata->dev, mw, mh); + ecore_drm2_device_pointer_max_set(edata->dev, mw, mh); + ecore_drm2_device_pointer_warp(edata->dev, mw / 2, mh / 2); + return ee; eng_err: From 09805d2b15a71a361ec4bf3154f797fe3314775d Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Fri, 27 May 2016 09:55:11 -0400 Subject: [PATCH 35/35] ecore-drm2: Add API functions to support cacheing of context & keymap @feature Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 22 ++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_device.c | 16 ++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index d8a1c3e31c..fa2e916c76 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -241,6 +241,28 @@ EAPI void ecore_drm2_device_window_set(Ecore_Drm2_Device *device, unsigned int w */ EAPI void ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h); +/** + * Set a cached context to be used on keyboards + * + * @param device + * @param context + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_keyboard_cached_context_set(Ecore_Drm2_Device *device, void *context); + +/** + * Set a cached keymap to be used on keyboards + * + * @param device + * @param keymap + * + * @ingroup Ecore_Drm2_Device_Group + * @since 1.18 + */ +EAPI void ecore_drm2_device_keyboard_cached_keymap_set(Ecore_Drm2_Device *device, void *keymap); + /** * Get the crtcs of a given device * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index b4948d4121..95b7315935 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -265,6 +265,22 @@ ecore_drm2_device_pointer_max_set(Ecore_Drm2_Device *device, int w, int h) elput_input_pointer_max_set(device->em, w, h); } +EAPI void +ecore_drm2_device_keyboard_cached_context_set(Ecore_Drm2_Device *device, void *context) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + + elput_input_keyboard_cached_context_set(device->em, context); +} + +EAPI void +ecore_drm2_device_keyboard_cached_keymap_set(Ecore_Drm2_Device *device, void *keymap) +{ + EINA_SAFETY_ON_NULL_RETURN(device); + + elput_input_keyboard_cached_keymap_set(device->em, keymap); +} + EAPI unsigned int * ecore_drm2_device_crtcs_get(Ecore_Drm2_Device *device, int *num) {