summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Aguirre <aguirre.nicolas@gmail.com>2016-03-18 08:56:59 +0100
committerCedric Bail <cedric@osg.samsung.com>2016-03-18 10:17:49 -0700
commit290fc88e3f375a2b5054780bd797be11ad526d90 (patch)
tree447cbf9236d7639bf7306acdd2302ce10b785cca
parent652895ad4ab33be714152adee85eeb7883c06593 (diff)
evas: add eglfs evas module.
EGL Fullscreen is a module intended to support many proprietary GL driver that come with custom API to create framebuffer/window. This one is starting by covering Android with libhybris/hwcomposer. Later on, it should be able to support easily the Raspberry Pi driver. At this moment this does not work properly. Activate it at your own risk ! Do not report bug if you don't know what you are doing :-) A backend for Ecore_Evas will come later on along with a patch for Ecore_FB to use libinput. Finally a few patch should hopefully enable this backend to work and compile more easily (relying on proper header detection and dlopen/dlsym for access to proprietary function). You can read more about the goal of this patch by reading our wiki at : https://phab.enlightenment.org/w/boot2efl/ Signed-off-by: Cedric Bail <cedric@osg.samsung.com>
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac17
-rw-r--r--m4/evas_check_engine.m443
-rw-r--r--pc/.gitignore1
-rw-r--r--pc/evas-eglfs.pc.in3
-rw-r--r--src/Makefile_Evas.am42
-rw-r--r--src/modules/evas/engines/eglfs/Evas_Engine_Eglfs.h45
-rw-r--r--src/modules/evas/engines/eglfs/evas_engine.c1254
-rw-r--r--src/modules/evas/engines/eglfs/evas_engine.h133
-rw-r--r--src/modules/evas/engines/eglfs/evas_outbuf.c703
10 files changed, 2245 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 8206b16..ef7c8a4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -188,6 +188,10 @@ if BUILD_ENGINE_FB
188pkgconfig_DATA += pc/evas-fb.pc 188pkgconfig_DATA += pc/evas-fb.pc
189endif 189endif
190 190
191if BUILD_ENGINE_EGLFS
192pkgconfig_DATA += pc/evas-eglfs.pc
193endif
194
191if BUILD_ENGINE_BUFFER 195if BUILD_ENGINE_BUFFER
192pkgconfig_DATA += pc/evas-software-buffer.pc 196pkgconfig_DATA += pc/evas-software-buffer.pc
193endif 197endif
diff --git a/configure.ac b/configure.ac
index 0768936..da7e012 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1624,6 +1624,19 @@ AC_ARG_ENABLE([fb],
1624 ], 1624 ],
1625 [want_fb="no"]) 1625 [want_fb="no"])
1626 1626
1627# Eglfs
1628AC_ARG_ENABLE([eglfs],
1629 [AS_HELP_STRING([--enable-eglfs],[enable hardware accelerated framebuffer access. @<:@default=disabled@:>@])],
1630 [
1631 if test "x${enableval}" = "xyes" ; then
1632 want_eglfs="yes"
1633 want_fb="yes"
1634 else
1635 want_eglfs="no"
1636 fi
1637 ],
1638 [want_eglfs="no"])
1639
1627# SDL 1640# SDL
1628AC_ARG_ENABLE([sdl], 1641AC_ARG_ENABLE([sdl],
1629 [AS_HELP_STRING([--enable-sdl],[enable SDL support. @<:@default=disabled@:>@])], 1642 [AS_HELP_STRING([--enable-sdl],[enable SDL support. @<:@default=disabled@:>@])],
@@ -2080,6 +2093,7 @@ EVAS_CHECK_ENGINE([wayland-egl], [${want_evas_engine_wayland_egl}], [no], [Wayla
2080EVAS_CHECK_ENGINE([wayland-shm], [${want_wayland}], [no], [Wayland Shm]) 2093EVAS_CHECK_ENGINE([wayland-shm], [${want_wayland}], [no], [Wayland Shm])
2081EVAS_CHECK_ENGINE([drm], [${want_drm}], [no], [Drm]) 2094EVAS_CHECK_ENGINE([drm], [${want_drm}], [no], [Drm])
2082EVAS_CHECK_ENGINE([gl-drm], [${want_gl_drm}], [no], [OpenGL Drm]) 2095EVAS_CHECK_ENGINE([gl-drm], [${want_gl_drm}], [no], [OpenGL Drm])
2096EVAS_CHECK_ENGINE([eglfs], [${want_eglfs}], [no], [OpenGL Fb])
2083 2097
2084 2098
2085# Software XCB 2099# Software XCB
@@ -2236,6 +2250,7 @@ if test "x$have_evas_engine_gl_xlib" = "xyes" || \
2236 test "x$have_evas_engine_gl_sdl" = "xyes" || \ 2250 test "x$have_evas_engine_gl_sdl" = "xyes" || \
2237 test "x$have_evas_engine_gl_cocoa" = "xyes" || \ 2251 test "x$have_evas_engine_gl_cocoa" = "xyes" || \
2238 test "x$have_evas_engine_gl_drm" = "xyes" || \ 2252 test "x$have_evas_engine_gl_drm" = "xyes" || \
2253 test "x$have_evas_engine_eglfs" = "xyes" || \
2239 test "x$have_evas_engine_wayland_egl" = "xyes"; then 2254 test "x$have_evas_engine_wayland_egl" = "xyes"; then
2240 have_evas_engine_gl_common="yes" 2255 have_evas_engine_gl_common="yes"
2241fi 2256fi
@@ -2244,6 +2259,7 @@ if test "x$have_evas_engine_gl_xlib" = "xstatic" || \
2244 test "x$have_evas_engine_gl_sdl" = "xstatic" || \ 2259 test "x$have_evas_engine_gl_sdl" = "xstatic" || \
2245 test "x$have_evas_engine_gl_cocoa" = "xstatic" || \ 2260 test "x$have_evas_engine_gl_cocoa" = "xstatic" || \
2246 test "x$have_evas_engine_gl_drm" = "xstatic" || \ 2261 test "x$have_evas_engine_gl_drm" = "xstatic" || \
2262 test "x$have_evas_engine_eglfs" = "xstatic" || \
2247 test "x$have_evas_engine_wayland_egl" = "xstatic"; then 2263 test "x$have_evas_engine_wayland_egl" = "xstatic"; then
2248 have_evas_engine_gl_common="yes" 2264 have_evas_engine_gl_common="yes"
2249 have_static_evas_engine_gl_common="yes" 2265 have_static_evas_engine_gl_common="yes"
@@ -5095,6 +5111,7 @@ pc/eo-js.pc
5095pc/efl.pc 5111pc/efl.pc
5096pc/efl-cxx.pc 5112pc/efl-cxx.pc
5097pc/evas-fb.pc 5113pc/evas-fb.pc
5114pc/evas-eglfs.pc
5098pc/evas-opengl-x11.pc 5115pc/evas-opengl-x11.pc
5099pc/evas-opengl-sdl.pc 5116pc/evas-opengl-sdl.pc
5100pc/evas-opengl-cocoa.pc 5117pc/evas-opengl-cocoa.pc
diff --git a/m4/evas_check_engine.m4 b/m4/evas_check_engine.m4
index 42ecc89..e38589c 100644
--- a/m4/evas_check_engine.m4
+++ b/m4/evas_check_engine.m4
@@ -661,6 +661,49 @@ AS_IF([test "x${have_dep}" = "xyes"], [$4], [$5])
661 661
662]) 662])
663 663
664dnl use: EVAS_CHECK_ENGINE_DEP_EGLFS(engine, simple, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
665
666AC_DEFUN([EVAS_CHECK_ENGINE_DEP_EGLFS],
667[
668
669requirement=""
670have_dep="no"
671have_hw_dep="no"
672evas_engine_[]$1[]_cflags=""
673evas_engine_[]$1[]_libs=""
674
675if test "x${with_opengl}" = "xes" ; then
676 gl_library="glesv2"
677else
678 AC_MSG_ERROR([We do not support Eglfs without OpenGL ES. Please consider OpenGL ES if you want to use it.])
679fi
680
681PKG_CHECK_EXISTS([egl >= 7.10 ${gl_library}],
682 [
683 have_dep="yes"
684 requirement="egl >= 7.10 ${gl_library}"
685 ],
686 [have_dep="no"])
687
688if test "x${have_dep}" = "xyes" ; then
689 if test "x$3" = "xstatic" ; then
690 requirements_pc_evas="${requirement} ${requirements_pc_evas}"
691 requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}"
692 else
693 PKG_CHECK_MODULES([EGLFS], [${requirement}])
694 evas_engine_[]$1[]_cflags="${EGLFS_CFLAGS}"
695 evas_engine_[]$1[]_libs="${EGLFS_LIBS}"
696 evas_engine_gl_common_libs="$evas_engine_[]$1[]_libdirs -lGLESv2 -lm -lEGL"
697 fi
698fi
699
700AC_SUBST([evas_engine_$1_cflags])
701AC_SUBST([evas_engine_$1_libs])
702
703AS_IF([test "x${have_dep}" = "xyes"], [$4], [$5])
704
705])
706
664 707
665dnl use: EVAS_ENGINE(name, want_engine, [DEPENDENCY-CHECK-CODE]) 708dnl use: EVAS_ENGINE(name, want_engine, [DEPENDENCY-CHECK-CODE])
666dnl 709dnl
diff --git a/pc/.gitignore b/pc/.gitignore
index c3422d5..ee97ef9 100644
--- a/pc/.gitignore
+++ b/pc/.gitignore
@@ -44,6 +44,7 @@
44/ethumb_client.pc 44/ethumb_client.pc
45/evas-drm.pc 45/evas-drm.pc
46/evas-fb.pc 46/evas-fb.pc
47/evas-eglfs.pc
47/evas-opengl-cocoa.pc 48/evas-opengl-cocoa.pc
48/evas-opengl-sdl.pc 49/evas-opengl-sdl.pc
49/evas-opengl-x11.pc 50/evas-opengl-x11.pc
diff --git a/pc/evas-eglfs.pc.in b/pc/evas-eglfs.pc.in
new file mode 100644
index 0000000..c8dfc5c
--- /dev/null
+++ b/pc/evas-eglfs.pc.in
@@ -0,0 +1,3 @@
1Name: evas-eglfs
2Description: Evas eglfs engine
3Version: @VERSION@
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index 4f56564..47642aa 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -874,6 +874,9 @@ endif
874if BUILD_ENGINE_GL_DRM 874if BUILD_ENGINE_GL_DRM
875modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_gl_drm_cflags@ 875modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_gl_drm_cflags@
876endif 876endif
877if BUILD_ENGINE_EGLFS
878modules_evas_engines_gl_common_libevas_engine_gl_common_la_CPPFLAGS += @evas_engine_eglfs_cflags@
879endif
877modules_evas_engines_gl_common_libevas_engine_gl_common_la_LIBADD = @USE_EVAS_LIBS@ 880modules_evas_engines_gl_common_libevas_engine_gl_common_la_LIBADD = @USE_EVAS_LIBS@
878modules_evas_engines_gl_common_libevas_engine_gl_common_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ 881modules_evas_engines_gl_common_libevas_engine_gl_common_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@
879modules_evas_engines_gl_common_libevas_engine_gl_common_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ 882modules_evas_engines_gl_common_libevas_engine_gl_common_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
@@ -1330,6 +1333,45 @@ modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
1330endif 1333endif
1331endif 1334endif
1332 1335
1336if BUILD_ENGINE_EGLFS
1337dist_installed_evasmainheaders_DATA += modules/evas/engines/eglfs/Evas_Engine_Eglfs.h
1338EGLFS_SOURCES = \
1339modules/evas/engines/eglfs/evas_outbuf.c \
1340modules/evas/engines/eglfs/evas_engine.c \
1341modules/evas/engines/eglfs/evas_engine.h \
1342modules/evas/engines/eglfs/Evas_Engine_Eglfs.h
1343if EVAS_STATIC_BUILD_EGLFS
1344lib_evas_libevas_la_SOURCES += $(EGLFS_SOURCES)
1345lib_evas_libevas_la_CPPFLAGS += @evas_engine_eglfs_cflags@
1346lib_evas_libevas_la_LIBADD += @evas_engine_eglfs_libs@
1347else
1348engineeglfspkgdir = $(libdir)/evas/modules/engines/eglfs/$(MODULE_ARCH)
1349engineeglfspkg_LTLIBRARIES = modules/evas/engines/eglfs/module.la
1350
1351# Workaround for broken parallel install support in automake (relink issue)
1352# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7328
1353install_engineeglfspkgLTLIBRARIES = install-engineeglfspkgLTLIBRARIES
1354$(install_engineeglfspkgLTLIBRARIES): install-libLTLIBRARIES
1355
1356modules_evas_engines_eglfs_module_la_SOURCES = $(EGLFS_SOURCES)
1357modules_evas_engines_eglfs_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1358-I$(top_srcdir)/src/lib/evas/include \
1359-I$(top_srcdir)/src/lib/evas/cserve2 \
1360-I$(top_srcdir)/src/modules/evas/engines/eglfs \
1361@EVAS_CFLAGS@ \
1362@ECORE_DRM_CFLAGS@ \
1363@evas_engine_eglfs_cflags@
1364modules_evas_engines_eglfs_module_la_LIBADD = \
1365@USE_EVAS_LIBS@ \
1366@USE_ECORE_DRM_LIBS@ \
1367@evas_engine_eglfs_libs@ \
1368@USE_EEZE_INTERNAL_LIBS@
1369modules_evas_engines_eglfs_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_EEZE_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@
1370modules_evas_engines_eglfs_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
1371modules_evas_engines_eglfs_module_la_LIBTOOLFLAGS = --tag=disable-static
1372endif
1373endif
1374
1333### Cserve2 binary 1375### Cserve2 binary
1334 1376
1335if EVAS_CSERVE2 1377if EVAS_CSERVE2
diff --git a/src/modules/evas/engines/eglfs/Evas_Engine_Eglfs.h b/src/modules/evas/engines/eglfs/Evas_Engine_Eglfs.h
new file mode 100644
index 0000000..7472c7b
--- /dev/null
+++ b/src/modules/evas/engines/eglfs/Evas_Engine_Eglfs.h
@@ -0,0 +1,45 @@
1#ifndef _EVAS_ENGINE_EGLFS_H
2# define _EVAS_ENGINE_EGLFS_H
3
4typedef enum _Evas_Engine_Info_Eglfs_Swap_Mode
5{
6 EVAS_ENGINE_EGLFS_SWAP_MODE_AUTO = 0,
7 EVAS_ENGINE_EGLFS_SWAP_MODE_FULL = 1,
8 EVAS_ENGINE_EGLFS_SWAP_MODE_COPY = 2,
9 EVAS_ENGINE_EGLFS_SWAP_MODE_DOUBLE = 3,
10 EVAS_ENGINE_EGLFS_SWAP_MODE_TRIPLE = 4,
11 EVAS_ENGINE_EGLFS_SWAP_MODE_QUADRUPLE = 5
12} Evas_Engine_Info_Eglfs_Swap_Mode;
13
14typedef struct _Evas_Engine_Info_Eglfs Evas_Engine_Info_Eglfs;
15
16struct _Evas_Engine_Info_Eglfs
17{
18 /* PRIVATE - don't mess with this baby or evas will poke its tongue out */
19 /* at you and make nasty noises */
20 Evas_Engine_Info magic;
21
22 struct
23 {
24 unsigned int rotation, depth;
25 unsigned int crtc_id, conn_id, buffer_id;
26 unsigned int format, flags;
27
28 Eina_Bool destination_alpha : 1;
29 Eina_Bool vsync : 1;
30 Eina_Bool indirect : 1;
31 unsigned char swap_mode : 4;
32 } info;
33
34 struct
35 {
36 void (*pre_swap)(void *data, Evas *evas);
37 void (*post_swap)(void *data, Evas *evas);
38 void *data;
39 } callback;
40
41 /* non-blocking or blocking mode */
42 Evas_Engine_Render_Mode render_mode;
43};
44
45#endif
diff --git a/src/modules/evas/engines/eglfs/evas_engine.c b/src/modules/evas/engines/eglfs/evas_engine.c
new file mode 100644
index 0000000..c408375
--- /dev/null
+++ b/src/modules/evas/engines/eglfs/evas_engine.c
@@ -0,0 +1,1254 @@
1#include "config.h"
2#include "evas_engine.h"
3#include <wayland-client.h>
4
5#ifdef HAVE_DLSYM
6# include <dlfcn.h> /* dlopen,dlclose,etc */
7#else
8# error eglfs should not get compiled if dlsym is not found on the system!
9#endif
10
11#ifdef EVAS_CSERVE2
12# include "evas_cs2_private.h"
13#endif
14
15#define EVAS_GL_NO_GL_H_CHECK 1
16#include "Evas_GL.h"
17
18#define EVAS_GL_UPDATE_TILE_SIZE 16
19
20#ifndef EGL_NATIVE_PIXMAP_KHR
21# define EGL_NATIVE_PIXMAP_KHR 0x30b0
22#endif
23
24/* external variables */
25int _evas_engine_eglfs_log_dom = -1;
26int _extn_have_buffer_age = 1;
27
28/* local variables */
29static Eina_Bool initted = EINA_FALSE;
30static int gl_wins = 0;
31
32/* local structures */
33typedef struct _Render_Engine Render_Engine;
34struct _Render_Engine
35{
36 Render_Engine_GL_Generic generic;
37};
38
39typedef struct _Native Native;
40struct _Native
41{
42 Evas_Native_Surface ns;
43 struct wl_buffer *wl_buf;
44 void *egl_surface;
45};
46
47/* local function prototype types */
48typedef void (*_eng_fn)(void);
49typedef _eng_fn (*glsym_func_eng_fn)();
50typedef void (*glsym_func_void)();
51typedef void *(*glsym_func_void_ptr)();
52typedef int (*glsym_func_int)();
53typedef unsigned int (*glsym_func_uint)();
54typedef const char *(*glsym_func_const_char_ptr)();
55
56/* external dynamic loaded Evas_GL function pointers */
57Evas_GL_Common_Image_Call glsym_evas_gl_common_image_ref = NULL;
58Evas_GL_Common_Image_Call glsym_evas_gl_common_image_unref = NULL;
59Evas_GL_Common_Image_Call glsym_evas_gl_common_image_free = NULL;
60Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_disable = NULL;
61Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_enable = NULL;
62Evas_GL_Common_Image_New_From_Data glsym_evas_gl_common_image_new_from_data = NULL;
63Evas_GL_Common_Context_Call glsym_evas_gl_common_image_all_unload = NULL;
64Evas_GL_Preload glsym_evas_gl_preload_init = NULL;
65Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL;
66EVGL_Engine_Call glsym_evgl_engine_shutdown = NULL;
67EVGL_Current_Native_Context_Get_Call glsym_evgl_current_native_context_get = NULL;
68Evas_Gl_Symbols glsym_evas_gl_symbols = NULL;
69
70Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL;
71Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush = NULL;
72Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free = NULL;
73Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use = NULL;
74Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe = NULL;
75Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done = NULL;
76Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize = NULL;
77Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump = NULL;
78Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL;
79Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL;
80Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL;
81
82glsym_func_void_ptr glsym_evas_gl_common_current_context_get = NULL;
83
84/* dynamic loaded local egl function pointers */
85_eng_fn (*glsym_eglGetProcAddress)(const char *a) = NULL;
86void *(*glsym_eglCreateImage)(EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL;
87void (*glsym_eglDestroyImage)(EGLDisplay a, void *b) = NULL;
88void (*glsym_glEGLImageTargetTexture2DOES)(int a, void *b) = NULL;
89unsigned int (*glsym_eglSwapBuffersWithDamage)(EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL;
90unsigned int (*glsym_eglQueryWaylandBufferWL)(EGLDisplay a, struct wl_resource *b, EGLint c, EGLint *d) = NULL;
91
92/* local function prototypes */
93static void gl_symbols(void);
94static void gl_extn_veto(Render_Engine *re);
95
96static void *evgl_eng_display_get(void *data);
97static void *evgl_eng_evas_surface_get(void *data);
98static int evgl_eng_make_current(void *data, void *surface, void *context, int flush);
99static void *evgl_eng_native_window_create(void *data);
100static int evgl_eng_native_window_destroy(void *data, void *native_window);
101static void *evgl_eng_window_surface_create(void *data, void *native_window);
102static int evgl_eng_window_surface_destroy(void *data, void *surface);
103static void *evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version version);
104static int evgl_eng_context_destroy(void *data, void *context);
105static const char *evgl_eng_string_get(void *data);
106static void *evgl_eng_proc_address_get(const char *name);
107static int evgl_eng_rotation_angle_get(void *data);
108
109/* function tables - filled in later (func and parent func) */
110static Evas_Func func, pfunc;
111static const EVGL_Interface evgl_funcs =
112{
113 evgl_eng_display_get,
114 evgl_eng_evas_surface_get,
115 evgl_eng_native_window_create,
116 evgl_eng_native_window_destroy,
117 evgl_eng_window_surface_create,
118 evgl_eng_window_surface_destroy,
119 evgl_eng_context_create,
120 evgl_eng_context_destroy,
121 evgl_eng_make_current,
122 evgl_eng_proc_address_get,
123 evgl_eng_string_get,
124 evgl_eng_rotation_angle_get,
125 NULL, // PBuffer
126 NULL, // PBuffer
127 NULL, // OpenGL-ES 1
128 NULL, // OpenGL-ES 1
129 NULL, // OpenGL-ES 1
130 NULL, // native_win_surface_config_get
131};
132
133
134/* local inline functions */
135static inline Outbuf *
136eng_get_ob(Render_Engine *re)
137{
138 return re->generic.software.ob;
139}
140
141/* local functions */
142static void
143gl_symbols(void)
144{
145 static Eina_Bool done = EINA_FALSE;
146
147 if (done) return;
148
149#define LINK2GENERIC(sym) \
150 glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
151
152 // Get function pointer to evas_gl_common that is now provided through the link of GL_Generic.
153 LINK2GENERIC(evas_gl_common_image_all_unload);
154 LINK2GENERIC(evas_gl_common_image_ref);
155 LINK2GENERIC(evas_gl_common_image_unref);
156 LINK2GENERIC(evas_gl_common_image_new_from_data);
157 LINK2GENERIC(evas_gl_common_image_native_disable);
158 LINK2GENERIC(evas_gl_common_image_free);
159 LINK2GENERIC(evas_gl_common_image_native_enable);
160 LINK2GENERIC(evas_gl_common_context_new);
161 LINK2GENERIC(evas_gl_common_context_flush);
162 LINK2GENERIC(evas_gl_common_context_free);
163 LINK2GENERIC(evas_gl_common_context_use);
164 LINK2GENERIC(evas_gl_common_context_newframe);
165 LINK2GENERIC(evas_gl_common_context_done);
166 LINK2GENERIC(evas_gl_common_context_resize);
167 LINK2GENERIC(evas_gl_common_buffer_dump);
168 LINK2GENERIC(evas_gl_preload_render_lock);
169 LINK2GENERIC(evas_gl_preload_render_unlock);
170 LINK2GENERIC(evas_gl_preload_render_relax);
171 LINK2GENERIC(evas_gl_preload_init);
172 LINK2GENERIC(evas_gl_preload_shutdown);
173 LINK2GENERIC(evgl_engine_shutdown);
174 LINK2GENERIC(evas_gl_symbols);
175
176#define FINDSYM(dst, sym, typ) \
177 if (glsym_eglGetProcAddress) { \
178 if (!dst) dst = (typ)glsym_eglGetProcAddress(sym); \
179 } else { \
180 if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym); \
181 }
182
183 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressKHR", glsym_func_eng_fn);
184 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressEXT", glsym_func_eng_fn);
185 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressARB", glsym_func_eng_fn);
186 FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddress", glsym_func_eng_fn);
187
188 glsym_evas_gl_symbols((void*)glsym_eglGetProcAddress);
189
190 FINDSYM(glsym_eglCreateImage, "eglCreateImageKHR", glsym_func_void_ptr);
191 FINDSYM(glsym_eglCreateImage, "eglCreateImageEXT", glsym_func_void_ptr);
192 FINDSYM(glsym_eglCreateImage, "eglCreateImageARB", glsym_func_void_ptr);
193 FINDSYM(glsym_eglCreateImage, "eglCreateImage", glsym_func_void_ptr);
194
195 FINDSYM(glsym_eglDestroyImage, "eglDestroyImageKHR", glsym_func_void);
196 FINDSYM(glsym_eglDestroyImage, "eglDestroyImageEXT", glsym_func_void);
197 FINDSYM(glsym_eglDestroyImage, "eglDestroyImageARB", glsym_func_void);
198 FINDSYM(glsym_eglDestroyImage, "eglDestroyImage", glsym_func_void);
199
200 FINDSYM(glsym_glEGLImageTargetTexture2DOES,
201 "glEGLImageTargetTexture2DOES", glsym_func_void);
202
203 FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageEXT",
204 glsym_func_uint);
205 FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageINTEL",
206 glsym_func_uint);
207 FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage",
208 glsym_func_uint);
209
210 FINDSYM(glsym_eglQueryWaylandBufferWL, "eglQueryWaylandBufferWL",
211 glsym_func_uint);
212
213 done = EINA_TRUE;
214}
215
216static void
217gl_extn_veto(Render_Engine *re)
218{
219 const char *str = NULL;
220
221 str = eglQueryString(eng_get_ob(re)->egl.disp, EGL_EXTENSIONS);
222 if (str)
223 {
224 const char *s = NULL;
225
226 if (getenv("EVAS_GL_INFO")) printf("EGL EXTN:\n%s\n", str);
227
228 // Disable Partial Rendering
229 s = getenv("EVAS_GL_PARTIAL_DISABLE");
230 if ((s) && (atoi(s)))
231 {
232 _extn_have_buffer_age = 0;
233 glsym_eglSwapBuffersWithDamage = NULL;
234 }
235 if (!strstr(str, "EGL_EXT_buffer_age")) _extn_have_buffer_age = 0;
236 if (!strstr(str, "EGL_EXT_swap_buffers_with_damage"))
237 glsym_eglSwapBuffersWithDamage = NULL;
238 }
239 else
240 {
241 if (getenv("EVAS_GL_INFO")) printf("NO EGL EXTN!\n");
242 _extn_have_buffer_age = 0;
243 }
244}
245
246static void *
247evgl_eng_display_get(void *data)
248{
249 Render_Engine *re;
250
251 re = (Render_Engine *)data;
252 if (!re)
253 {
254 ERR("Invalid Render Engine Data!");
255 return NULL;
256 }
257
258 if (eng_get_ob(re))
259 return (void *)eng_get_ob(re)->egl.disp;
260 else
261 return NULL;
262}
263
264static void *
265evgl_eng_evas_surface_get(void *data)
266{
267 Render_Engine *re;
268
269 re = (Render_Engine *)data;
270 if (!re)
271 {
272 ERR("Invalid Render Engine Data!");
273 return NULL;
274 }
275
276 if (eng_get_ob(re))
277 return (void *)eng_get_ob(re)->egl.surface[0];
278 else
279 return NULL;
280}
281
282static int
283evgl_eng_make_current(void *data, void *surface, void *context, int flush)
284{
285 Render_Engine *re;
286 EGLContext ctx;
287 EGLSurface sfc;
288 EGLDisplay dpy;
289 int ret = 0;
290
291 re = (Render_Engine *)data;
292 if (!re)
293 {
294 ERR("Invalid Render Engine Data!");
295 return 0;
296 }
297
298 dpy = eng_get_ob(re)->egl.disp;
299 ctx = (EGLContext)context;
300 sfc = (EGLSurface)surface;
301
302 if ((!context) && (!surface))
303 {
304 ret = eglMakeCurrent(dpy, EGL_NO_SURFACE,
305 EGL_NO_SURFACE, EGL_NO_CONTEXT);
306 if (!ret)
307 {
308 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
309 return 0;
310 }
311
312 return 1;
313 }
314
315 if ((eglGetCurrentContext() != ctx) ||
316 (eglGetCurrentSurface(EGL_READ) != sfc) ||
317 (eglGetCurrentSurface(EGL_DRAW) != sfc) )
318 {
319 if (flush) evas_outbuf_use(NULL);
320
321 ret = eglMakeCurrent(dpy, sfc, sfc, ctx);
322 if (!ret)
323 {
324 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
325 return 0;
326 }
327 }
328
329 return 1;
330}
331
332static void _hwc_present_cb(void *user_data, struct ANativeWindow *window,
333 struct ANativeWindowBuffer *buffer)
334{
335
336}
337
338static void *
339evgl_eng_native_window_create(void *data)
340{
341 Render_Engine *re;
342 Evas_Engine_Info_Eglfs *info;
343 struct ANativeWindow *native_window;
344
345 re = (Render_Engine *)data;
346 if (!re)
347 {
348 ERR("Invalid Render Engine Data!");
349 return NULL;
350 }
351
352 info = eng_get_ob(re)->info;
353 if (!info)
354 {
355 ERR("Invalid Evas Engine Eglfs Info!");
356 return NULL;
357 }
358 EGLNativeWindowType win;
359 win = create_hwcomposernativewindow();
360 return (void *)win;
361}
362
363static int
364evgl_eng_native_window_destroy(void *data, void *native_window)
365{
366 Render_Engine *re = (Render_Engine *)data;
367
368 if (!re)
369 {
370 ERR("Invalid Render Engine Data!");
371 return 0;
372 }
373
374 if (!native_window)
375 {
376 ERR("Invalid native surface.");
377 return 0;
378 }
379
380 HWCNativeWindowDestroy(native_window);
381
382 return 1;
383}
384
385static void *
386evgl_eng_window_surface_create(void *data, void *native_window)
387{
388 Render_Engine *re;
389 EGLSurface surface = EGL_NO_SURFACE;
390
391 re = (Render_Engine *)data;
392 if (!re)
393 {
394 ERR("Invalid Render Engine Data!");
395 return NULL;
396 }
397
398 // Create resource surface for EGL
399 surface = eglCreateWindowSurface(eng_get_ob(re)->egl.disp,
400 eng_get_ob(re)->egl.config,
401 (EGLNativeWindowType)native_window,
402 NULL);
403 if (!surface)
404 {
405 ERR("Creating window surface failed. Error: %#x.", eglGetError());
406 return NULL;
407 }
408
409 return (void *)surface;
410}
411
412static int
413evgl_eng_window_surface_destroy(void *data, void *surface)
414{
415 Render_Engine *re;
416 EGLBoolean ret = EGL_FALSE;
417
418 re = (Render_Engine *)data;
419 if (!re)
420 {
421 ERR("Invalid Render Engine Data!");
422 return 0;
423 }
424
425 if (!surface)
426 {
427 ERR("Invalid surface.");
428 return 0;
429 }
430
431 ret = eglDestroySurface(eng_get_ob(re)->egl.disp, (EGLSurface)surface);
432 if (ret == EGL_TRUE) return 1;
433
434 return 0;
435}
436
437static void *
438evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version version)
439{
440 Render_Engine *re;
441 EGLContext context = EGL_NO_CONTEXT;
442 int context_attrs[3];
443
444 re = (Render_Engine *)data;
445 if (!re)
446 {
447 ERR("Invalid Render Engine Data!");
448 return NULL;
449 }
450
451 if (version != EVAS_GL_GLES_2_X)
452 {
453 ERR("This engine only supports OpenGL-ES 2.0 contexts for now!");
454 return NULL;
455 }
456
457 context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
458 context_attrs[1] = 2;
459 context_attrs[2] = EGL_NONE;
460
461 // Share context already assumes that it's sharing with evas' context
462 if (share_ctx)
463 {
464 context = eglCreateContext(eng_get_ob(re)->egl.disp,
465 eng_get_ob(re)->egl.config,
466 (EGLContext)share_ctx,
467 context_attrs);
468 }
469 else
470 {
471 context = eglCreateContext(eng_get_ob(re)->egl.disp,
472 eng_get_ob(re)->egl.config,
473 eng_get_ob(re)->egl.context[0], // Evas' GL Context
474 context_attrs);
475 }
476
477 if (!context)
478 {
479 ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError());
480 return NULL;
481 }
482
483 return (void *)context;
484}
485
486static int
487evgl_eng_context_destroy(void *data, void *context)
488{
489 Render_Engine *re;
490 EGLBoolean ret = EGL_FALSE;
491
492 re = (Render_Engine *)data;
493 if ((!re) || (!context))
494 {
495 ERR("Invalid Render Input Data. Engine: %p, Context: %p",
496 data, context);
497 return 0;
498 }
499
500 ret = eglDestroyContext(eng_get_ob(re)->egl.disp, (EGLContext)context);
501 if (ret == EGL_TRUE) return 1;
502
503 return 0;
504}
505
506static const char *
507evgl_eng_string_get(void *data)
508{
509 Render_Engine *re;
510
511 re = (Render_Engine *)data;
512 if (!re)
513 {
514 ERR("Invalid Render Engine Data!");
515 return NULL;
516 }
517
518 return eglQueryString(eng_get_ob(re)->egl.disp, EGL_EXTENSIONS);
519}
520
521static void *
522evgl_eng_proc_address_get(const char *name)
523{
524 if (glsym_eglGetProcAddress) return glsym_eglGetProcAddress(name);
525 return dlsym(RTLD_DEFAULT, name);
526}
527
528static int
529evgl_eng_rotation_angle_get(void *data)
530{
531 Render_Engine *re;
532
533 re = (Render_Engine *)data;
534 if (!re)
535 {
536 ERR("Invalid Render Engine Data!");
537 return 0;
538 }
539
540 if ((eng_get_ob(re)) && (eng_get_ob(re)->gl_context))
541 return eng_get_ob(re)->gl_context->rot;
542 else
543 {
544 ERR("Unable to retrieve rotation angle.");
545 return 0;
546 }
547}
548
549static Eina_Bool
550eng_preload_make_current(void *data, void *doit)
551{
552 Outbuf *ob;
553
554 ob = (Outbuf *)data;
555 if (!ob) return EINA_FALSE;
556
557 if (doit)
558 {
559 if (!eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
560 ob->egl.surface[0], ob->egl.context[0]))
561 return EINA_FALSE;
562 }
563 else
564 {
565 if (!eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
566 EGL_NO_SURFACE, EGL_NO_CONTEXT))
567 return EINA_FALSE;
568 }
569
570 return EINA_TRUE;
571}
572
573static void
574_re_winfree(Render_Engine *re)
575{
576 if (!re) return;
577 if (!eng_get_ob(re)->surf) return;
578 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re));
579 evas_outbuf_unsurf(eng_get_ob(re));
580}
581
582static void
583_native_cb_bind(void *data EINA_UNUSED, void *image)
584{
585 Evas_GL_Image *img;
586 Native *n;
587
588 if (!(img = image)) return;
589 if (!(n = img->native.data)) return;
590
591 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
592 {
593 if (n->egl_surface)
594 {
595 if (glsym_glEGLImageTargetTexture2DOES)
596 {
597 glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, n->egl_surface);
598 if (eglGetError() != EGL_SUCCESS)
599 ERR("glEGLImageTargetTexture2DOES() failed.");
600 }
601 else
602 ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
603 }
604 }
605 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
606 glBindTexture(GL_TEXTURE_2D, n->ns.data.opengl.texture_id);
607
608 /* TODO: NATIVE_SURFACE_TBM and NATIVE_SURFACE_EVASGL */
609}
610
611static void
612_native_cb_unbind(void *data EINA_UNUSED, void *image)
613{
614 Evas_GL_Image *img;
615 Native *n;
616
617 if (!(img = image)) return;
618 if (!(n = img->native.data)) return;
619
620 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
621 glBindTexture(GL_TEXTURE_2D, 0);
622
623 /* TODO: NATIVE_SURFACE_TBM and NATIVE_SURFACE_EVASGL */
624}
625
626static void
627_native_cb_free(void *data, void *image)
628{
629 Render_Engine *re;
630 Outbuf *ob;
631 Evas_GL_Image *img;
632 Native *n;
633 uint32_t texid;
634 void *wlid;
635
636 if (!(re = (Render_Engine *)data)) return;
637 if (!(img = image)) return;
638 if (!(n = img->native.data)) return;
639 if (!(ob = eng_get_ob(re))) return;
640
641 if (n->ns.type == EVAS_NATIVE_SURFACE_WL)
642 {
643 wlid = (void*)n->wl_buf;
644 eina_hash_del(ob->gl_context->shared->native_wl_hash, &wlid, img);
645 if (n->egl_surface)
646 {
647 if (glsym_eglDestroyImage)
648 {
649 glsym_eglDestroyImage(ob->egl.disp, n->egl_surface);
650 if (eglGetError() != EGL_SUCCESS)
651 ERR("eglDestroyImage() failed.");
652 }
653 else
654 ERR("Try eglDestroyImage on EGL with no support");
655 }
656 }
657 else if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL)
658 {
659 texid = n->ns.data.opengl.texture_id;
660 eina_hash_del(ob->gl_context->shared->native_tex_hash, &texid, img);
661 }
662
663 img->native.data = NULL;
664 img->native.func.data = NULL;
665 img->native.func.bind = NULL;
666 img->native.func.unbind = NULL;
667 img->native.func.free = NULL;
668
669 free(n);
670}
671
672/* engine specific override functions */
673static void *
674eng_info(Evas *eo_e EINA_UNUSED)
675{
676 Evas_Engine_Info_Eglfs *info;
677
678 /* try to allocate space for our engine info */
679 if (!(info = calloc(1, sizeof(Evas_Engine_Info_Eglfs))))
680 return NULL;
681
682 info->magic.magic = rand();
683 info->render_mode = EVAS_RENDER_MODE_BLOCKING;
684
685 return info;
686}
687
688static void
689eng_info_free(Evas *eo_e EINA_UNUSED, void *in)
690{
691 Evas_Engine_Info_Eglfs *info;
692
693 if ((info = (Evas_Engine_Info_Eglfs *)in))
694 free(info);
695}
696
697static int
698eng_setup(Evas *evas, void *in)
699{
700 Evas_Engine_Info_Eglfs *info;
701 Evas_Public_Data *epd;
702 Render_Engine *re;
703 Render_Engine_Swap_Mode swap_mode = MODE_FULL;
704 const char *s = NULL;
705
706 /* try to cast to our engine info structure */
707 if (!(info = (Evas_Engine_Info_Eglfs *)in)) return 0;
708
709 /* try to get the evas public data */
710 if (!(epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS))) return 0;
711
712 s = getenv("EVAS_GL_SWAP_MODE");
713 if (s)
714 {
715 if ((!strcasecmp(s, "full")) || (!strcasecmp(s, "f")))
716 swap_mode = MODE_FULL;
717 else if ((!strcasecmp(s, "copy")) || (!strcasecmp(s, "c")))
718 swap_mode = MODE_COPY;
719 else if ((!strcasecmp(s, "double")) ||
720 (!strcasecmp(s, "d")) || (!strcasecmp(s, "2")))
721 swap_mode = MODE_DOUBLE;
722 else if ((!strcasecmp(s, "triple")) ||
723 (!strcasecmp(s, "t")) || (!strcasecmp(s, "3")))
724 swap_mode = MODE_TRIPLE;
725 else if ((!strcasecmp(s, "quadruple")) ||
726 (!strcasecmp(s, "q")) || (!strcasecmp(s, "4")))
727 swap_mode = MODE_QUADRUPLE;
728 }
729 else
730 {
731// in most gl implementations - egl and glx here that we care about the TEND
732// to either swap or copy backbuffer and front buffer, but strictly that is
733// not true. technically backbuffer content is totally undefined after a swap
734// and thus you MUST re-render all of it, thus MODE_FULL
735 swap_mode = MODE_FULL;
736// BUT... reality is that lmost every implementation copies or swaps so
737// triple buffer mode can be used as it is a superset of double buffer and
738// copy (though using those explicitly is more efficient). so let's play with
739// triple buffer mdoe as a default and see.
740// re->mode = MODE_TRIPLE;
741// XXX: note - the above seems to break on some older intel chipsets and
742// drivers. it seems we CANT depend on backbuffer staying around. bugger!
743 switch (info->info.swap_mode)
744 {
745 case EVAS_ENGINE_EGLFS_SWAP_MODE_FULL:
746 swap_mode = MODE_FULL;
747 break;
748 case EVAS_ENGINE_EGLFS_SWAP_MODE_COPY:
749 swap_mode = MODE_COPY;
750 break;
751 case EVAS_ENGINE_EGLFS_SWAP_MODE_DOUBLE:
752 swap_mode = MODE_DOUBLE;
753 break;
754 case EVAS_ENGINE_EGLFS_SWAP_MODE_TRIPLE:
755 swap_mode = MODE_TRIPLE;
756 break;
757 case EVAS_ENGINE_EGLFS_SWAP_MODE_QUADRUPLE:
758 swap_mode = MODE_QUADRUPLE;
759 break;
760 default:
761 swap_mode = MODE_AUTO;
762 break;
763 }
764 }
765
766 if (!(re = epd->engine.data.output))
767 {
768 Outbuf *ob;
769 Render_Engine_Merge_Mode merge_mode = MERGE_BOUNDING;
770
771 if (!initted)
772 {
773 evas_common_init();
774 glsym_evas_gl_preload_init();
775 }
776
777 if (!(re = calloc(1, sizeof(Render_Engine)))) return 0;
778
779 /* try to create new outbuf */
780 ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode);
781 if (!ob)
782 {
783 free(re);
784 return 0;
785 }
786
787 ob->evas = evas;
788
789 if (!evas_render_engine_gl_generic_init(&re->generic, ob,
790 evas_outbuf_buffer_state_get,
791 evas_outbuf_rot_get,
792 evas_outbuf_reconfigure,
793 evas_outbuf_update_region_first_rect,
794 evas_outbuf_update_region_new,
795 evas_outbuf_update_region_push,
796 evas_outbuf_update_region_free,
797 NULL,
798 evas_outbuf_flush,
799 evas_outbuf_free,
800 evas_outbuf_use,
801 evas_outbuf_gl_context_get,
802 evas_outbuf_egl_display_get,
803 evas_outbuf_gl_context_new,
804 evas_outbuf_gl_context_use,
805 &evgl_funcs, ob->w, ob->h))
806 {
807 /* free outbuf */
808
809 evas_outbuf_free(ob);
810 free(re);
811 return 0;
812 }
813
814 epd->engine.data.output = re;
815 gl_wins++;
816
817 s = getenv("EVAS_GL_PARTIAL_MERGE");
818 if (s)
819 {
820 if ((!strcmp(s, "bounding")) || (!strcmp(s, "b")))
821 merge_mode = MERGE_BOUNDING;
822 else if ((!strcmp(s, "full")) || (!strcmp(s, "f")))
823 merge_mode = MERGE_FULL;
824 }
825
826 evas_render_engine_software_generic_merge_mode_set(&re->generic.software, merge_mode);
827
828 if (!initted)
829 {
830 gl_extn_veto(re);
831 initted = EINA_TRUE;
832 }
833 }
834 else
835 {
836 if (eng_get_ob(re) && _re_wincheck(eng_get_ob(re)))
837 {
838 if ((info->info.depth != eng_get_ob(re)->depth) ||
839 (info->info.destination_alpha != eng_get_ob(re)->destination_alpha))
840 {
841 Outbuf *ob, *ob_old;
842
843 ob_old = re->generic.software.ob;
844 re->generic.software.ob = NULL;
845 gl_wins--;
846
847 ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode);
848 if (!ob)
849 {
850 if (ob_old) evas_outbuf_free(ob_old);
851 free(re);
852 return 0;
853 }
854
855 evas_outbuf_use(ob);
856 if (ob_old) evas_outbuf_free(ob_old);
857
858 ob->evas = evas;
859
860 evas_render_engine_software_generic_update(&re->generic.software, ob,
861 epd->output.w, epd->output.h);
862
863 gl_wins++;
864 }
865 else if ((eng_get_ob(re)->w != epd->output.w) ||
866 (eng_get_ob(re)->h != epd->output.h) ||
867 (info->info.rotation != eng_get_ob(re)->rotation))
868 {
869 evas_outbuf_reconfigure(eng_get_ob(re),
870 epd->output.w, epd->output.h,
871 info->info.rotation,
872 info->info.depth);
873 }
874 }
875 }
876
877 if (!eng_get_ob(re))
878 {
879 free(re);
880 return 0;
881 }
882
883 if (!epd->engine.data.output)
884 {
885 if (eng_get_ob(re))
886 {
887 evas_outbuf_free(eng_get_ob(re));
888 gl_wins--;
889 }
890 free(re);
891 return 0;
892 }
893
894 if (re->generic.software.tb)
895 evas_common_tilebuf_free(re->generic.software.tb);
896 re->generic.software.tb =
897 evas_common_tilebuf_new(epd->output.w, epd->output.h);
898 if (re->generic.software.tb)
899 evas_common_tilebuf_set_tile_size(re->generic.software.tb,
900 TILESIZE, TILESIZE);
901
902 if (re->generic.software.tb)
903 evas_render_engine_software_generic_tile_strict_set(&re->generic.software, EINA_TRUE);
904
905 if (!epd->engine.data.context)
906 {
907 epd->engine.data.context =
908 epd->engine.func->context_new(epd->engine.data.output);
909 }
910
911 evas_outbuf_use(eng_get_ob(re));
912
913 return 1;
914}
915
916static void
917eng_output_free(void *data)
918{
919 Render_Engine *re;
920
921 re = (Render_Engine *)data;
922 if (re)
923 {
924 glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re));
925
926 if (gl_wins == 1) glsym_evgl_engine_shutdown(re);
927
928 /* NB: evas_render_engine_software_generic_clean() frees ob */
929 evas_render_engine_software_generic_clean(&re->generic.software);
930
931 gl_wins--;
932
933 free(re);
934 }
935
936 if ((initted == EINA_TRUE) && (gl_wins == 0))
937 {
938 glsym_evas_gl_preload_shutdown();
939 evas_common_shutdown();
940 initted = EINA_FALSE;
941 }
942}
943
944static Eina_Bool
945eng_canvas_alpha_get(void *data, void *info EINA_UNUSED)
946{
947 Render_Engine *re;
948
949 re = (Render_Engine *)data;
950 if (!re) return EINA_FALSE;
951
952 return eng_get_ob(re)->destination_alpha;
953}
954
955static void
956eng_output_dump(void *data)
957{
958 Render_Engine *re;
959
960 re = (Render_Engine *)data;
961 if (!re) return;
962
963 evas_common_image_image_all_unload();
964 evas_common_font_font_all_unload();
965 glsym_evas_gl_common_image_all_unload(eng_get_ob(re)->gl_context);
966 _re_winfree(re);
967}
968
969static void *
970eng_image_native_set(void *data, void *image, void *native)
971{
972 Render_Engine *re;
973 Outbuf *ob;
974 Native *n;
975 Evas_Native_Surface *ns;
976 Evas_GL_Image *img, *img2;
977 unsigned int tex = 0, fbo = 0;
978 uint32_t texid;
979 void *wlid, *wl_buf = NULL;
980
981 re = (Render_Engine *)data;
982 if (!re) return NULL;
983
984 ob = eng_get_ob(re);
985 if (!ob) return NULL;
986
987 ns = native;
988
989 if (!(img = image))
990 {
991 if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_OPENGL))
992 {
993 img =
994 glsym_evas_gl_common_image_new_from_data(ob->gl_context,
995 ns->data.opengl.w,
996 ns->data.opengl.h,
997 NULL, 1,
998 EVAS_COLORSPACE_ARGB8888);
999 }
1000 else
1001 return NULL;
1002 }
1003
1004 if (ns)
1005 {
1006 if (ns->type == EVAS_NATIVE_SURFACE_WL)
1007 {
1008 wl_buf = ns->data.wl.legacy_buffer;
1009 if (img->native.data)
1010 {
1011 Evas_Native_Surface *ens;
1012
1013 ens = img->native.data;
1014 if (ens->data.wl.legacy_buffer == wl_buf)
1015 return img;
1016 }
1017 }
1018 else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL)
1019 {
1020 tex = ns->data.opengl.texture_id;
1021 fbo = ns->data.opengl.framebuffer_id;
1022 if (img->native.data)
1023 {
1024 Evas_Native_Surface *ens;
1025
1026 ens = img->native.data;
1027 if ((ens->data.opengl.texture_id == tex) &&
1028 (ens->data.opengl.framebuffer_id == fbo))
1029 return img;
1030 }
1031 }
1032 }
1033
1034 if ((!ns) && (!img->native.data)) return img;
1035
1036 evas_outbuf_use(ob);
1037
1038 if (img->native.data)
1039 {
1040 if (img->native.func.free)
1041 img->native.func.free(img->native.func.data, img);
1042 glsym_evas_gl_common_image_native_disable(img);
1043 }
1044
1045 if (!ns) return img;
1046
1047 if (ns->type == EVAS_NATIVE_SURFACE_WL)
1048 {
1049 wlid = wl_buf;
1050 img2 = eina_hash_find(ob->gl_context->shared->native_wl_hash, &wlid);
1051 if (img2 == img) return img;
1052 if (img2)
1053 {
1054 if((n = img2->native.data))
1055 {
1056 glsym_evas_gl_common_image_ref(img2);
1057 glsym_evas_gl_common_image_free(img);
1058 return img2;
1059 }
1060 }
1061 }
1062 else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL)
1063 {
1064 texid = tex;
1065 img2 = eina_hash_find(ob->gl_context->shared->native_tex_hash, &texid);
1066 if (img2 == img) return img;
1067 if (img2)
1068 {
1069 if ((n = img2->native.data))
1070 {
1071 glsym_evas_gl_common_image_ref(img2);
1072 glsym_evas_gl_common_image_free(img);
1073 return img2;
1074 }
1075 }
1076 }
1077
1078 img2 = glsym_evas_gl_common_image_new_from_data(ob->gl_context, img->w,
1079 img->h, NULL, img->alpha,
1080 EVAS_COLORSPACE_ARGB8888);
1081 glsym_evas_gl_common_image_free(img);
1082
1083 if (!(img = img2)) return NULL;
1084
1085 if (ns->type == EVAS_NATIVE_SURFACE_WL)
1086 {
1087 if (native)
1088 {
1089 if ((n = calloc(1, sizeof(Native))))
1090 {
1091 EGLint attribs[3];
1092 int format, yinvert = 1;
1093
1094 glsym_eglQueryWaylandBufferWL(ob->egl.disp, wl_buf,
1095 EGL_TEXTURE_FORMAT, &format);
1096 if ((format != EGL_TEXTURE_RGB) &&
1097 (format != EGL_TEXTURE_RGBA))
1098 {
1099 ERR("eglQueryWaylandBufferWL() %d format is not supported ", format);
1100 glsym_evas_gl_common_image_free(img);
1101 free(n);
1102 return NULL;
1103 }
1104
1105 attribs[0] = EGL_WAYLAND_PLANE_WL;
1106 attribs[1] = 0; //if plane is 1 then 0, if plane is 2 then 1
1107 attribs[2] = EGL_NONE;
1108
1109 memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
1110 glsym_eglQueryWaylandBufferWL(ob->egl.disp, wl_buf,
1111 EGL_WAYLAND_Y_INVERTED_WL,
1112 &yinvert);
1113 eina_hash_add(ob->gl_context->shared->native_wl_hash,
1114 &wlid, img);
1115
1116 n->wl_buf = wl_buf;
1117 if (glsym_eglCreateImage)
1118 n->egl_surface = glsym_eglCreateImage(ob->egl.disp,
1119 NULL,
1120 EGL_WAYLAND_BUFFER_WL,
1121 wl_buf, attribs);
1122 else
1123 {
1124 ERR("Try eglCreateImage on EGL with no support");
1125 eina_hash_del(ob->gl_context->shared->native_wl_hash,
1126 &wlid, img);
1127 glsym_evas_gl_common_image_free(img);
1128 free(n);
1129 return NULL;
1130 }
1131
1132 if (!n->egl_surface)
1133 {
1134 ERR("eglCreatePixmapSurface() for %p failed", wl_buf);
1135 eina_hash_del(ob->gl_context->shared->native_wl_hash,
1136 &wlid, img);
1137 glsym_evas_gl_common_image_free(img);
1138 free(n);
1139 return NULL;
1140 }
1141
1142 //XXX: workaround for mesa-10.2.8
1143 // mesa's eglQueryWaylandBufferWL() with EGL_WAYLAND_Y_INVERTED_WL works incorrect.
1144 //img->native.yinvert = yinvert;
1145 img->native.yinvert = 1;
1146 img->native.loose = 0;
1147 img->native.data = n;
1148 img->native.func.data = re;
1149 img->native.func.bind = _native_cb_bind;
1150 img->native.func.unbind = _native_cb_unbind;
1151 img->native.func.free = _native_cb_free;
1152 img->native.target = GL_TEXTURE_2D;
1153 img->native.mipmap = 0;
1154
1155 glsym_evas_gl_common_image_native_enable(img);
1156 }
1157 }
1158 }
1159 else if (ns->type == EVAS_NATIVE_SURFACE_OPENGL)
1160 {
1161 if (native)
1162 {
1163 if ((n = calloc(1, sizeof(Native))))
1164 {
1165 memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
1166 eina_hash_add(ob->gl_context->shared->native_tex_hash,
1167 &texid, img);
1168
1169 n->egl_surface = 0;
1170
1171 img->native.yinvert = 0;
1172 img->native.loose = 0;
1173 img->native.data = n;
1174 img->native.func.data = re;
1175 img->native.func.bind = _native_cb_bind;
1176 img->native.func.unbind = _native_cb_unbind;
1177 img->native.func.free = _native_cb_free;
1178 img->native.target = GL_TEXTURE_2D;
1179 img->native.mipmap = 0;
1180
1181 glsym_evas_gl_common_image_native_enable(img);
1182 }
1183 }
1184 }
1185
1186 /* TODO: NATIVE_SURFACE_TBM and NATIVE_SURFACE_EVASGL */
1187
1188 return img;
1189}
1190
1191/* module api functions */
1192static int
1193module_open(Evas_Module *em)
1194{
1195 /* check for valid evas module */
1196 if (!em) return 0;
1197
1198 /* get whatever engine module we inherit from */
1199 if (!_evas_module_engine_inherit(&pfunc, "gl_generic")) return 0;
1200
1201 /* try to create eina logging domain */
1202 if (_evas_engine_eglfs_log_dom < 0)
1203 {
1204 _evas_engine_eglfs_log_dom =
1205 eina_log_domain_register("evas-eglfs", EVAS_DEFAULT_LOG_COLOR);
1206 }
1207
1208 /* if we could not create a logging domain, error out */
1209 if (_evas_engine_eglfs_log_dom < 0)
1210 {
1211 EINA_LOG_ERR("Can not create a module log domain.");
1212 return 0;
1213 }
1214
1215 /* store it for later use */
1216 func = pfunc;
1217
1218 /* now to override methods */
1219 EVAS_API_OVERRIDE(info, &func, eng_);
1220 EVAS_API_OVERRIDE(info_free, &func, eng_);
1221 EVAS_API_OVERRIDE(setup, &func, eng_);
1222 EVAS_API_OVERRIDE(canvas_alpha_get, &func, eng_);
1223 EVAS_API_OVERRIDE(output_free, &func, eng_);
1224 EVAS_API_OVERRIDE(output_dump, &func, eng_);
1225 EVAS_API_OVERRIDE(image_native_set, &func, eng_);
1226
1227 setenv("EGL_PLATFORM", "fbdev", 1);
1228
1229 gl_symbols();
1230
1231 /* now advertise out own api */
1232 em->functions = (void *)(&func);
1233
1234 return 1;
1235}
1236
1237static void
1238module_close(Evas_Module *em EINA_UNUSED)
1239{
1240 /* unregister the eina log domain for this engine */
1241 eina_log_domain_unregister(_evas_engine_eglfs_log_dom);
1242 _evas_engine_eglfs_log_dom = -1;
1243}
1244
1245static Evas_Module_Api evas_modapi =
1246{
1247 EVAS_MODULE_API_VERSION, "eglfs", "none", { module_open, module_close }
1248};
1249
1250EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, eglfs);
1251
1252#ifndef EVAS_STATIC_BUILD_EGLFS
1253EVAS_EINA_MODULE_DEFINE(engine, eglfs);
1254#endif
diff --git a/src/modules/evas/engines/eglfs/evas_engine.h b/src/modules/evas/engines/eglfs/evas_engine.h
new file mode 100644
index 0000000..e02acb0
--- /dev/null
+++ b/src/modules/evas/engines/eglfs/evas_engine.h
@@ -0,0 +1,133 @@
1#ifndef EVAS_ENGINE_H
2# define EVAS_ENGINE_H
3
4# include "evas_common_private.h"
5# include "evas_macros.h"
6# include "evas_private.h"
7# include "Evas.h"
8# include "Evas_Engine_Eglfs.h"
9
10# define EGL_EGLEXT_PROTOTYPES
11# define GL_GLEXT_PROTOTYPES
12
13# include <EGL/egl.h>
14# include <EGL/eglext.h>
15# include <EGL/eglmesaext.h>
16# include <GLES2/gl2.h>
17# include <GLES2/gl2ext.h>
18# include <hwcomposer.h>
19# include <hardware/hardware.h>
20# include <hardware/hwcomposer.h>
21# include "../gl_generic/Evas_Engine_GL_Generic.h"
22
23extern int _evas_engine_eglfs_log_dom;
24extern int _extn_have_buffer_age;
25
26# ifdef ERR
27# undef ERR
28# endif
29# define ERR(...) EINA_LOG_DOM_ERR(_evas_engine_eglfs_log_dom, __VA_ARGS__)
30
31# ifdef DBG
32# undef DBG
33# endif
34# define DBG(...) EINA_LOG_DOM_DBG(_evas_engine_eglfs_log_dom, __VA_ARGS__)
35
36# ifdef INF
37# undef INF
38# endif
39# define INF(...) EINA_LOG_DOM_INFO(_evas_engine_eglfs_log_dom, __VA_ARGS__)
40
41# ifdef WRN
42# undef WRN
43# endif
44# define WRN(...) EINA_LOG_DOM_WARN(_evas_engine_eglfs_log_dom, __VA_ARGS__)
45
46# ifdef CRI
47# undef CRI
48# endif
49# define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_eglfs_log_dom, __VA_ARGS__)
50
51extern Evas_GL_Common_Context_New glsym_evas_gl_common_context_new;
52extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush;
53extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free;
54extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use;
55extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe;
56extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done;
57extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize;
58extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump;
59extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock;
60extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock;
61
62struct _Context_3D
63{
64 EGLDisplay display;
65 EGLContext context;
66 EGLSurface surface;
67};
68
69struct _Outbuf
70{
71 Evas_Engine_Info_Eglfs *info;
72 Evas_Engine_GL_Context *gl_context;
73
74 Evas *evas; // used for pre_swap, post_swap
75
76 int w, h;
77 unsigned int rotation, depth;
78 Render_Engine_Swap_Mode swap_mode;
79
80 struct
81 {
82 EGLContext context[1];
83 EGLSurface surface[1];
84 EGLConfig config;
85 EGLDisplay disp;
86 } egl;
87
88 struct
89 {
90 int prev_age, frame_cnt;
91 int curr, last, num;
92 Eina_List *pending_writes;
93 } priv;
94
95 Eina_Bool destination_alpha : 1;
96 Eina_Bool vsync : 1;
97 Eina_Bool lost_back : 1;
98 Eina_Bool surf : 1;
99 Eina_Bool drew : 1;
100};
101
102Outbuf *evas_outbuf_new(Evas_Engine_Info_Eglfs *info, int w, int h, Render_Engine_Swap_Mode swap_mode);
103void evas_outbuf_free(Outbuf *ob);
104void evas_outbuf_use(Outbuf *ob);
105void evas_outbuf_resurf(Outbuf *ob);
106void evas_outbuf_unsurf(Outbuf *ob);
107void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
108Render_Engine_Swap_Mode evas_outbuf_buffer_state_get(Outbuf *ob);
109int evas_outbuf_rot_get(Outbuf *ob);
110Eina_Bool evas_outbuf_update_region_first_rect(Outbuf *ob);
111void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
112void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
113void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
114void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
115Evas_Engine_GL_Context* evas_outbuf_gl_context_get(Outbuf *ob);
116void *evas_outbuf_egl_display_get(Outbuf *ob);
117Context_3D *evas_outbuf_gl_context_new(Outbuf *ob);
118void evas_outbuf_gl_context_use(Context_3D *ctx);
119EGLNativeWindowType create_hwcomposernativewindow(void);
120
121static inline Eina_Bool
122_re_wincheck(Outbuf *ob)
123{
124 if (ob->surf) return EINA_TRUE;
125 evas_outbuf_resurf(ob);
126 ob->lost_back = 1;
127 if (!ob->surf) ERR("GL engine can't re-create window surface!");
128 return EINA_FALSE;
129}
130
131extern unsigned int (*glsym_eglSwapBuffersWithDamage)(EGLDisplay a, void *b, const EGLint *d, EGLint c);
132
133#endif
diff --git a/src/modules/evas/engines/eglfs/evas_outbuf.c b/src/modules/evas/engines/eglfs/evas_outbuf.c
new file mode 100644
index 0000000..aa3cd8a
--- /dev/null
+++ b/src/modules/evas/engines/eglfs/evas_outbuf.c
@@ -0,0 +1,703 @@
1#include "evas_engine.h"
2
3#include <hybris/hwcomposerwindow/hwcomposer.h>
4#include <hardware/hwcomposer.h>
5#include <hardware/hardware.h>
6#include <android-config.h>
7
8static hwc_layer_1_t *fblayer;
9static hwc_composer_device_1_t *hwcDevicePtr;
10static hwc_display_contents_1_t **mList;
11
12void present(void *user_data, struct ANativeWindow *window,
13 struct ANativeWindowBuffer *buffer)
14{
15
16 int oldretire = mList[0]->retireFenceFd;
17 mList[0]->retireFenceFd = -1;
18 fblayer->handle = buffer->handle;
19 fblayer->acquireFenceFd = HWCNativeBufferGetFence(buffer);
20 fblayer->releaseFenceFd = -1;
21 int err = hwcDevicePtr->prepare(hwcDevicePtr, HWC_NUM_DISPLAY_TYPES, mList);
22 //assert(err == 0);
23
24 err = hwcDevicePtr->set(hwcDevicePtr, HWC_NUM_DISPLAY_TYPES, mList);
25 //assert(err == 0);
26 HWCNativeBufferSetFence(buffer, fblayer->releaseFenceFd);
27
28 if (oldretire != -1)
29 {
30 sync_wait(oldretire, -1);
31 close(oldretire);
32 }
33}
34
35
36EGLNativeWindowType create_hwcomposernativewindow(void)
37{
38 int err;
39 hw_module_t *hwcModule = 0;
40 hwcDevicePtr = 0;
41
42 err = hw_get_module(HWC_HARDWARE_MODULE_ID, (const hw_module_t **) &hwcModule);
43 //assert(err == 0);
44
45 err = hwc_open_1(hwcModule, &hwcDevicePtr);
46 //assert(err == 0);
47
48 hwcDevicePtr->blank(hwcDevicePtr, 0, 0);
49
50 uint32_t configs[5];
51 size_t numConfigs = 5;
52
53 err = hwcDevicePtr->getDisplayConfigs(hwcDevicePtr, 0, configs, &numConfigs);
54 //assert (err == 0);
55
56 int32_t attr_values[2];
57 uint32_t attributes[] = { HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_NO_ATTRIBUTE };
58
59 hwcDevicePtr->getDisplayAttributes(hwcDevicePtr, 0,
60 configs[0], attributes, attr_values);
61
62 size_t size = sizeof(hwc_display_contents_1_t) + 2 * sizeof(hwc_layer_1_t);
63 hwc_display_contents_1_t *list = (hwc_display_contents_1_t *) malloc(size);
64 mList = (hwc_display_contents_1_t **) malloc(HWC_NUM_DISPLAY_TYPES * sizeof(hwc_display_contents_1_t *));
65 const hwc_rect_t r = { 0, 0, attr_values[0], attr_values[1] };
66
67 int counter = 0;
68 for (; counter < HWC_NUM_DISPLAY_TYPES; counter++)
69 mList[counter] = NULL;
70 // Assign buffer only to the first item, otherwise you get tearing
71 // if passed the same to multiple places
72 mList[0] = list;
73
74 fblayer = &list->hwLayers[0];
75 memset(fblayer, 0, sizeof(hwc_layer_1_t));
76 fblayer->compositionType = HWC_FRAMEBUFFER;
77 fblayer->hints = 0;
78 fblayer->flags = 0;
79 fblayer->handle = 0;
80 fblayer->transform = 0;
81 fblayer->blending = HWC_BLENDING_NONE;
82 fblayer->sourceCrop = r;
83 fblayer->displayFrame = r;
84 fblayer->visibleRegionScreen.numRects = 1;
85 fblayer->visibleRegionScreen.rects = &fblayer->displayFrame;
86 fblayer->acquireFenceFd = -1;
87 fblayer->releaseFenceFd = -1;
88 fblayer = &list->hwLayers[1];
89 memset(fblayer, 0, sizeof(hwc_layer_1_t));
90 fblayer->compositionType = HWC_FRAMEBUFFER_TARGET;
91 fblayer->hints = 0;
92 fblayer->flags = 0;
93 fblayer->handle = 0;
94 fblayer->transform = 0;
95 fblayer->blending = HWC_BLENDING_NONE;
96 fblayer->sourceCrop = r;
97 fblayer->displayFrame = r;
98 fblayer->visibleRegionScreen.numRects = 1;
99 fblayer->visibleRegionScreen.rects = &fblayer->displayFrame;
100 fblayer->acquireFenceFd = -1;
101 fblayer->releaseFenceFd = -1;
102
103 list->retireFenceFd = -1;
104 list->flags = HWC_GEOMETRY_CHANGED;
105 list->numHwLayers = 2;
106
107 EGLNativeWindowType win = NULL;
108 win = (EGLNativeWindowType)HWCNativeWindowCreate(attr_values[0], attr_values[1], HAL_PIXEL_FORMAT_RGBA_8888, present, NULL);
109 return win;
110}
111
112/* local variables */
113static Outbuf *_evas_eglfs_window = NULL;
114static EGLContext context = EGL_NO_CONTEXT;
115static int win_count = 0;
116
117static Eina_Bool
118_evas_outbuf_make_current(void *data, void *doit)
119{
120 Outbuf *ob;
121
122 if (!(ob = data)) return EINA_FALSE;
123
124 if (doit)
125 {
126 if (!eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
127 ob->egl.surface[0], ob->egl.context[0]))
128 return EINA_FALSE;
129 }
130 else
131 {
132 if (!eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
133 EGL_NO_SURFACE, EGL_NO_CONTEXT))
134 return EINA_FALSE;
135 }
136
137 return EINA_TRUE;
138}
139
140void _hwcomposer_present_cb(void *user_data, struct ANativeWindow *window, struct ANativeWindowBuffer *buffer)
141{
142}
143
144static Eina_Bool
145_evas_outbuf_egl_setup(Outbuf *ob)
146{
147 int ctx_attr[3];
148 int cfg_attr[40];
149 int maj = 0, min = 0, n = 0, i = 0;
150 EGLint ncfg;
151 EGLConfig *cfgs;
152 const GLubyte *vendor, *renderer, *version, *glslversion;
153 Eina_Bool blacklist = EINA_FALSE;
154
155 /* setup egl surface */
156 ctx_attr[0] = EGL_CONTEXT_CLIENT_VERSION;
157 ctx_attr[1] = 2;
158 ctx_attr[2] = EGL_NONE;
159
160 cfg_attr[n++] = EGL_BUFFER_SIZE;
161 cfg_attr[n++] = 32;
162 cfg_attr[n++] = EGL_DEPTH_SIZE;
163 cfg_attr[n++] = EGL_DONT_CARE;
164 cfg_attr[n++] = EGL_STENCIL_SIZE;
165 cfg_attr[n++] = EGL_DONT_CARE;
166 cfg_attr[n++] = EGL_RENDERABLE_TYPE;
167 cfg_attr[n++] = EGL_OPENGL_ES2_BIT;
168 cfg_attr[n++] = EGL_SURFACE_TYPE;
169 cfg_attr[n++] = EGL_WINDOW_BIT;
170
171 cfg_attr[n++] = EGL_ALPHA_SIZE;
172 if (ob->destination_alpha) cfg_attr[n++] = 1;
173 else cfg_attr[n++] = 0;
174 cfg_attr[n++] = EGL_NONE;
175
176 int err;
177 hw_module_t *hwcModule = 0;
178 hwc_composer_device_1_t *hwcDevicePtr = 0;
179
180 err = hw_get_module(HWC_HARDWARE_MODULE_ID, (const hw_module_t **) &hwcModule);
181 if (err != 0)
182 {
183 ERR("hw_get_module() fail. code=%d", err);
184 return EINA_FALSE;
185 }
186 err = hwc_open_1(hwcModule, &hwcDevicePtr);
187 if (err != 0)
188 {
189 ERR("hwc_open_1 fail. code=%d", err);
190 return EINA_FALSE;
191 }
192 hwcDevicePtr->blank(hwcDevicePtr, 0, 0);
193
194 uint32_t configs[5];
195 size_t numConfigs = 5;
196
197 err = hwcDevicePtr->getDisplayConfigs(hwcDevicePtr, 0, configs, &numConfigs);
198 if (err != 0)
199 {
200 ERR("getDisplayConfig. code=%d", err);
201 return EINA_FALSE;
202 }
203
204 int32_t attr_values[2];
205 uint32_t attributes[] = { HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_NO_ATTRIBUTE };
206
207 hwcDevicePtr->getDisplayAttributes(hwcDevicePtr, 0,
208 configs[0], attributes, attr_values);
209
210 DBG("width: %i height: %i\n", attr_values[0], attr_values[1]);
211
212 size_t size = sizeof(hwc_display_contents_1_t) + 2 * sizeof(hwc_layer_1_t);
213 hwc_display_contents_1_t *list = (hwc_display_contents_1_t *) malloc(size);
214 hwc_display_contents_1_t **mList = (hwc_display_contents_1_t **) malloc(HWC_NUM_DISPLAY_TYPES * sizeof(hwc_display_contents_1_t *));
215 const hwc_rect_t r = { 0, 0, attr_values[0], attr_values[1] };
216
217 int counter = 0;
218 for (; counter < HWC_NUM_DISPLAY_TYPES; counter++)
219 mList[counter] = NULL;
220 mList[0] = list;
221
222 hwc_layer_1_t *layer = &list->hwLayers[0];
223 memset(layer, 0, sizeof(hwc_layer_1_t));
224 layer->compositionType = HWC_FRAMEBUFFER;
225 layer->hints = 0;
226 layer->flags = 0;
227 layer->handle = 0;
228 layer->transform = 0;
229 layer->blending = HWC_BLENDING_NONE;
230 layer->sourceCrop = r;
231 layer->displayFrame = r;
232 layer->visibleRegionScreen.numRects = 1;
233 layer->visibleRegionScreen.rects = &layer->displayFrame;
234 layer->acquireFenceFd = -1;
235 layer->releaseFenceFd = -1;
236 layer = &list->hwLayers[1];
237 memset(layer, 0, sizeof(hwc_layer_1_t));
238 layer->compositionType = HWC_FRAMEBUFFER_TARGET;
239 layer->hints = 0;
240 layer->flags = 0;
241 layer->handle = 0;
242 layer->transform = 0;
243 layer->blending = HWC_BLENDING_NONE;
244 layer->sourceCrop = r;
245 layer->displayFrame = r;
246 layer->visibleRegionScreen.numRects = 1;
247 layer->visibleRegionScreen.rects = &layer->displayFrame;
248 layer->acquireFenceFd = -1;
249 layer->releaseFenceFd = -1;
250
251 list->retireFenceFd = -1;
252 list->flags = HWC_GEOMETRY_CHANGED;
253 list->numHwLayers = 2;
254
255 ob->egl.disp = eglGetDisplay(NULL);
256 if (ob->egl.disp == EGL_NO_DISPLAY)
257 {
258 ERR("eglGetDisplay() fail. code=%#x", eglGetError());
259 return EINA_FALSE;
260 }
261
262 if (!eglInitialize(ob->egl.disp, &maj, &min))
263 {
264 ERR("eglInitialize() fail. code=%#x", eglGetError());
265 return EINA_FALSE;
266 }
267
268 eglBindAPI(EGL_OPENGL_ES_API);
269 if (eglGetError() != EGL_SUCCESS)
270 {
271 ERR("eglBindAPI() fail. code=%#x", eglGetError());
272 return EINA_FALSE;
273 }
274
275 if (!eglGetConfigs(ob->egl.disp, NULL, 0, &ncfg) || (ncfg == 0))
276 {
277 ERR("eglGetConfigs() fail. code=%#x", eglGetError());
278 return EINA_FALSE;
279 }
280
281 cfgs = malloc(ncfg * sizeof(EGLConfig));
282 if (!cfgs)
283 {
284 ERR("Failed to malloc space for egl configs");
285 return EINA_FALSE;
286 }
287
288 if (!eglChooseConfig(ob->egl.disp, cfg_attr, cfgs,
289 ncfg, &ncfg) || (ncfg == 0))
290 {
291 ERR("eglChooseConfig() fail. code=%#x", eglGetError());
292 return EINA_FALSE;
293 }
294
295 // First is always best...
296 ob->egl.config = cfgs[0];
297
298 EGLNativeWindowType win = create_hwcomposernativewindow();
299 ob->egl.surface[0] =
300 eglCreateWindowSurface(ob->egl.disp, ob->egl.config,
301 (EGLNativeWindowType)win, NULL);
302
303 if (ob->egl.surface[0] == EGL_NO_SURFACE)
304 {
305 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
306 NULL, eglGetError());
307 return EINA_FALSE;
308 }
309
310 ob->egl.context[0] =
311 eglCreateContext(ob->egl.disp, ob->egl.config, EGL_NO_CONTEXT, ctx_attr);
312 if (ob->egl.context[0] == EGL_NO_CONTEXT)
313 {
314 ERR("eglCreateContext() fail. code=%#x", eglGetError());
315 return EINA_FALSE;
316 }
317
318 if (context == EGL_NO_CONTEXT) context = ob->egl.context[0];
319
320 if (eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
321 ob->egl.surface[0], ob->egl.context[0]) == EGL_FALSE)
322 {
323 ERR("eglMakeCurrent() fail. code=%#x", eglGetError());
324 return EINA_FALSE;
325 }
326
327 vendor = glGetString(GL_VENDOR);
328 renderer = glGetString(GL_RENDERER);
329 version = glGetString(GL_VERSION);
330 glslversion = glGetString(GL_SHADING_LANGUAGE_VERSION);
331 if (!vendor) vendor = (unsigned char *)"-UNKNOWN-";
332 if (!renderer) renderer = (unsigned char *)"-UNKNOWN-";
333 if (!version) version = (unsigned char *)"-UNKNOWN-";
334 if (!glslversion) glslversion = (unsigned char *)"-UNKNOWN-";
335 if (getenv("EVAS_GL_INFO"))
336 {
337 fprintf(stderr, "vendor : %s\n", vendor);
338 fprintf(stderr, "renderer: %s\n", renderer);
339 fprintf(stderr, "version : %s\n", version);
340 fprintf(stderr, "glsl ver: %s\n", glslversion);
341 }
342
343 if (strstr((const char *)vendor, "Mesa Project"))
344 {
345 if (strstr((const char *)renderer, "Software Rasterizer"))
346 blacklist = EINA_TRUE;
347 }
348 if (strstr((const char *)renderer, "softpipe"))
349 blacklist = EINA_TRUE;
350 if (strstr((const char *)renderer, "llvmpipe"))
351 blacklist = EINA_TRUE;
352
353 if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST")))
354 {
355 ERR("OpenGL Driver blacklisted:");
356 ERR("Vendor: %s", (const char *)vendor);
357 ERR("Renderer: %s", (const char *)renderer);
358 ERR("Version: %s", (const char *)version);
359 return EINA_FALSE;
360 }
361
362 ob->gl_context = glsym_evas_gl_common_context_new();
363 if (!ob->gl_context) return EINA_FALSE;
364
365#ifdef GL_GLES
366 ob->gl_context->egldisp = ob->egl.disp;
367 ob->gl_context->eglctxt = ob->egl.context[0];
368#endif
369
370 evas_outbuf_use(ob);
371 glsym_evas_gl_common_context_resize(ob->gl_context,
372 ob->w, ob->h, ob->rotation);
373
374 ob->surf = EINA_TRUE;
375
376 return EINA_TRUE;
377}
378
379Outbuf *
380evas_outbuf_new(Evas_Engine_Info_Eglfs *info, int w, int h, Render_Engine_Swap_Mode swap_mode)
381{
382 Outbuf *ob;
383 char *num;
384
385 if (!info) return NULL;
386
387 /* try to allocate space for outbuf */
388 if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
389
390 win_count++;
391
392 ob->w = w;
393 ob->h = h;
394 ob->info = info;
395 ob->depth = info->info.depth;
396 ob->rotation = info->info.rotation;
397 ob->destination_alpha = info->info.destination_alpha;
398 ob->swap_mode = swap_mode;
399 ob->priv.num = 2;
400
401 if ((num = getenv("EVAS_EGLFS_BUFFERS")))
402 {
403 ob->priv.num = atoi(num);
404 if (ob->priv.num <= 0) ob->priv.num = 1;
405 else if (ob->priv.num > 4) ob->priv.num = 4;
406 }
407
408 if ((num = getenv("EVAS_EGLFS_VSYNC")))
409 ob->vsync = atoi(num);
410
411 if (!_evas_outbuf_egl_setup(ob))
412 {
413 evas_outbuf_free(ob);
414 return NULL;
415 }
416
417 return ob;
418}
419
420void
421evas_outbuf_free(Outbuf *ob)
422{
423 int ref = 0;
424
425 win_count--;
426 evas_outbuf_use(ob);
427
428 if (ob == _evas_eglfs_window) _evas_eglfs_window = NULL;
429
430 if (ob->gl_context)
431 {
432 ref = ob->gl_context->references - 1;
433 glsym_evas_gl_common_context_free(ob->gl_context);
434 }
435
436 eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
437
438 if (ob->egl.context[0] != context)
439 eglDestroyContext(ob->egl.disp, ob->egl.context[0]);
440
441 if (ob->egl.surface[0] != EGL_NO_SURFACE)
442 eglDestroySurface(ob->egl.disp, ob->egl.surface[0]);
443
444 if (ref == 0)
445 {
446 if (context) eglDestroyContext(ob->egl.disp, context);
447 eglTerminate(ob->egl.disp);
448 eglReleaseThread();
449 context = EGL_NO_CONTEXT;
450 }
451
452 free(ob);
453}
454
455void
456evas_outbuf_use(Outbuf *ob)
457{
458 Eina_Bool force = EINA_FALSE;
459
460 glsym_evas_gl_preload_render_lock(_evas_outbuf_make_current, ob);
461
462 if (_evas_eglfs_window)
463 {
464 if (eglGetCurrentContext() != _evas_eglfs_window->egl.context[0])
465 force = EINA_TRUE;
466 }
467
468 if ((_evas_eglfs_window != ob) || (force))
469 {
470 if (_evas_eglfs_window)
471 {
472 glsym_evas_gl_common_context_use(_evas_eglfs_window->gl_context);
473 glsym_evas_gl_common_context_flush(_evas_eglfs_window->gl_context);
474 }
475
476 _evas_eglfs_window = ob;
477
478 if (ob)
479 {
480 if (ob->egl.surface[0] != EGL_NO_SURFACE)
481 {
482 if (eglMakeCurrent(ob->egl.disp, ob->egl.surface[0],
483 ob->egl.surface[0],
484 ob->egl.context[0]) == EGL_FALSE)
485 ERR("eglMakeCurrent() failed!");
486 }
487 }
488 }
489
490 if (ob) glsym_evas_gl_common_context_use(ob->gl_context);
491}
492
493void
494evas_outbuf_resurf(Outbuf *ob)
495{
496 if (ob->surf) return;
497 if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", ob);
498
499 ob->egl.surface[0] =
500 eglCreateWindowSurface(ob->egl.disp, ob->egl.config,
501 NULL, NULL);
502
503 if (ob->egl.surface[0] == EGL_NO_SURFACE)
504 {
505 ERR("eglCreateWindowSurface() fail for %p. code=%#x",
506 NULL, eglGetError());
507 return;
508 }
509
510 if (eglMakeCurrent(ob->egl.disp, ob->egl.surface[0], ob->egl.surface[0],
511 ob->egl.context[0]) == EGL_FALSE)
512 ERR("eglMakeCurrent() failed!");
513
514 ob->surf = EINA_TRUE;
515}
516
517void
518evas_outbuf_unsurf(Outbuf *ob)
519{
520 if (!ob->surf) return;
521 if (!getenv("EVAS_GL_WIN_RESURF")) return;
522 if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", ob);
523
524 if (_evas_eglfs_window)
525 glsym_evas_gl_common_context_flush(_evas_eglfs_window->gl_context);
526 if (_evas_eglfs_window == ob)
527 {
528 eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
529 EGL_NO_SURFACE, EGL_NO_CONTEXT);
530 if (ob->egl.surface[0] != EGL_NO_SURFACE)
531 eglDestroySurface(ob->egl.disp, ob->egl.surface[0]);
532 ob->egl.surface[0] = EGL_NO_SURFACE;
533
534 _evas_eglfs_window = NULL;
535 }
536
537 ob->surf = EINA_FALSE;
538}
539
540void
541evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth)
542{
543 if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth;
544
545 ob->w = w;
546 ob->h = h;
547 ob->depth = depth;
548 ob->rotation = rot;
549
550 evas_outbuf_use(ob);
551 glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot);
552}
553
554Render_Engine_Swap_Mode
555evas_outbuf_buffer_state_get(Outbuf *ob)
556{
557 return MODE_FULL;
558 // Forces re-rendering all the screen, that is bad for performance. However
559 // partial rendering makes black area. We should try to find a better solution.
560}
561
562int
563evas_outbuf_rot_get(Outbuf *ob)
564{
565 return ob->rotation;
566}
567
568Eina_Bool
569evas_outbuf_update_region_first_rect(Outbuf *ob)
570{
571 glsym_evas_gl_preload_render_lock(_evas_outbuf_make_current, ob);
572 evas_outbuf_use(ob);
573
574 if (!_re_wincheck(ob)) return EINA_TRUE;
575
576 glsym_evas_gl_common_context_flush(ob->gl_context);
577 glsym_evas_gl_common_context_newframe(ob->gl_context);
578
579 return EINA_FALSE;
580}
581
582void *
583evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx EINA_UNUSED, int *cy EINA_UNUSED, int *cw EINA_UNUSED, int *ch EINA_UNUSED)
584{
585 if ((w == ob->w) && (h == ob->h))
586 ob->gl_context->master_clip.enabled = EINA_FALSE;
587 else
588 {
589 ob->gl_context->master_clip.enabled = EINA_TRUE;
590 ob->gl_context->master_clip.x = x;
591 ob->gl_context->master_clip.y = y;
592 ob->gl_context->master_clip.w = w;
593 ob->gl_context->master_clip.h = h;
594 }
595
596 return ob->gl_context->def_surface;
597}
598
599void
600evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
601{
602 /* Is it really necessary to flush per region ? Shouldn't we be able to
603 still do that for the full canvas when doing partial update */
604 if (!_re_wincheck(ob)) return;
605 ob->drew = EINA_TRUE;
606 glsym_evas_gl_common_context_flush(ob->gl_context);
607}
608
609void
610evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
611{
612 /* Nothing to do here as we don't really create an image per area */
613}
614
615void
616evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
617{
618 if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
619
620 if (!_re_wincheck(ob)) goto end;
621 if (!ob->drew) goto end;
622
623 ob->drew = EINA_FALSE;
624 evas_outbuf_use(ob);
625 glsym_evas_gl_common_context_done(ob->gl_context);
626
627 if (!ob->vsync)
628 {
629 if (ob->info->info.vsync) eglSwapInterval(ob->egl.disp, 1);
630 else eglSwapInterval(ob->egl.disp, 0);
631 ob->vsync = 1;
632 }
633
634 if (ob->info->callback.pre_swap)
635 ob->info->callback.pre_swap(ob->info->callback.data, ob->evas);
636
637 eglSwapBuffers(ob->egl.disp, ob->egl.surface[0]);
638
639 if (ob->info->callback.post_swap)
640 ob->info->callback.post_swap(ob->info->callback.data, ob->evas);
641
642 ob->priv.frame_cnt++;
643
644end:
645 glsym_evas_gl_preload_render_unlock(_evas_outbuf_make_current, ob);
646}
647
648Evas_Engine_GL_Context *
649evas_outbuf_gl_context_get(Outbuf *ob)
650{
651 return ob->gl_context;
652}
653
654void *
655evas_outbuf_egl_display_get(Outbuf *ob)
656{
657 return ob->egl.disp;
658}
659
660Context_3D *
661evas_outbuf_gl_context_new(Outbuf *ob)
662{
663 Context_3D *ctx;
664 int context_attrs[3] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
665
666 if (!ob) return NULL;
667
668 ctx = calloc(1, sizeof(Context_3D));
669 if (!ctx) return NULL;
670
671 ctx->context = eglCreateContext(ob->egl.disp, ob->egl.config,
672 ob->egl.context[0], context_attrs);
673
674 if (!ctx->context)
675 {
676 ERR("EGL context creation failed.");
677 goto error;
678 }
679
680 ctx->display = ob->egl.disp;
681 ctx->surface = ob->egl.surface[0];
682
683 return ctx;
684
685error:
686 free(ctx);
687 return NULL;
688}
689
690void
691evas_outbuf_gl_context_free(Context_3D *ctx)
692{
693 eglDestroyContext(ctx->display, ctx->context);
694 free(ctx);
695}
696
697void
698evas_outbuf_gl_context_use(Context_3D *ctx)
699{
700 if (eglMakeCurrent(ctx->display, ctx->surface,
701 ctx->surface, ctx->context) == EGL_FALSE)
702 ERR("eglMakeCurrent() failed.");
703}