From: devilhorns Date: Mon, 26 Dec 2011 23:13:52 +0000 (+0000) Subject: Evas: Add Wayland EGL engine (still experimental). X-Git-Tag: 2.0_alpha~153^2~34 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fc97797ffa4f4084aafdacd24e78a758e68ff24f;p=framework%2Fuifw%2Fevas.git Evas: Add Wayland EGL engine (still experimental). git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@66541 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/Makefile.am b/Makefile.am index 8a9445e..b42e7f9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,6 +46,7 @@ evas-software-16-wince.pc.in \ evas-software-sdl.pc.in \ evas-psl1ght.pc.in \ evas-wayland-shm.pc.in \ +evas-wayland-egl.pc.in \ evas.spec.in \ evas.spec \ m4/efl_attribute.m4 \ @@ -132,6 +133,10 @@ if BUILD_ENGINE_WAYLAND_SHM pkgconfig_DATA += evas-wayland-shm.pc endif +if BUILD_ENGINE_WAYLAND_EGL +pkgconfig_DATA += evas-wayland-egl.pc +endif + .PHONY: doc coverage doc: diff --git a/configure.ac b/configure.ac index ef7d7a6..9781e78 100644 --- a/configure.ac +++ b/configure.ac @@ -113,6 +113,7 @@ want_evas_engine_fb="no" want_evas_engine_directfb="no" want_evas_engine_psl1ght="no" want_evas_engine_wayland_shm="no" +want_evas_engine_wayland_egl="no" want_evas_image_loader_edb="yes" want_evas_image_loader_eet="yes" @@ -159,6 +160,8 @@ case "$host_os" in want_evas_engine_software_xcb="no" want_evas_engine_gl_xcb="no" want_evas_engine_fb="auto" + want_evas_engine_wayland_shm="auto" + want_evas_engine_wayland_egl="auto" ### no - not ready/usable/complete # want_evas_engine_software_8_x11="auto" # want_evas_engine_software_16_x11="auto" @@ -769,6 +772,8 @@ EVAS_CHECK_ENGINE([software-16-sdl], [${want_evas_engine_software_16_sdl}], [no] EVAS_CHECK_ENGINE([wayland-shm], [${want_evas_engine_wayland_shm}], [no], [Wayland Shm]) +EVAS_CHECK_ENGINE([wayland-egl], [${want_evas_engine_wayland_egl}], [no], [Wayland Egl]) + # SDL primitive sdl_primitive="no" @@ -1887,6 +1892,7 @@ evas-software-16-wince.pc evas-software-sdl.pc evas-psl1ght.pc evas-wayland-shm.pc +evas-wayland-egl.pc evas.pc doc/evas.dox doc/Makefile @@ -1932,6 +1938,7 @@ src/modules/engines/software_16_x11/Makefile src/modules/engines/software_16_ddraw/Makefile src/modules/engines/software_16_sdl/Makefile src/modules/engines/wayland_shm/Makefile +src/modules/engines/wayland_egl/Makefile src/modules/loaders/Makefile src/modules/loaders/edb/Makefile src/modules/loaders/eet/Makefile @@ -2029,6 +2036,7 @@ echo " Software 16bit Directdraw..: $have_evas_engine_software_16_ddraw" echo " Software 16bit WinCE.......: $have_evas_engine_software_16_wince" echo " Software 16bit SDL.........: $have_evas_engine_software_16_sdl (primitive: $sdl_primitive)" echo " Wayland Shm................: $have_evas_engine_wayland_shm" +echo " Wayland Egl................: $have_evas_engine_wayland_egl" echo echo "Image Loaders:" echo " BMP.....................: $have_evas_image_loader_bmp" diff --git a/m4/evas_check_engine.m4 b/m4/evas_check_engine.m4 index 45a5871..e88022b 100644 --- a/m4/evas_check_engine.m4 +++ b/m4/evas_check_engine.m4 @@ -906,10 +906,10 @@ evas_engine_[]$1[]_cflags="" evas_engine_[]$1[]_libs="" PKG_CHECK_MODULES([WAYLAND_EGL], - [wayland-egl], + [egl >= 7.10 glesv2 gl wayland-client wayland-egl], [ have_dep="yes" - requirement="wayland-egl" + requirement="egl >= 7.10 glesv2 gl wayland-client wayland-egl" evas_engine_[]$1[]_cflags="${WAYLAND_EGL_CFLAGS}" evas_engine_[]$1[]_libs="${WAYLAND_EGL_LIBS}" ],[ @@ -918,16 +918,18 @@ PKG_CHECK_MODULES([WAYLAND_EGL], ) if test "x${have_dep}" = "xyes" ; then + PKG_CHECK_MODULES([GL_EET], [eet >= 1.5.0], [have_dep="yes"], [have_dep="no"]) AC_CHECK_HEADER([GLES2/gl2.h], [have_egl="yes"], [have_egl="no"], [ #include #include +#include ]) if test "x${have_egl}" = "xyes" ; then evas_engine_[]$1[]_cflags="${WAYLAND_EGL_CFLAGS}" - evas_engine_[]$1[]_libs="${WAYLAND_EGL_LIBS} -lGLESv2 -lEGL" + evas_engine_[]$1[]_libs="${WAYLAND_EGL_LIBS} -lGL -lGLESv2 -lEGL" fi fi diff --git a/src/modules/engines/Makefile.am b/src/modules/engines/Makefile.am index 2fdac8c..42585cc 100644 --- a/src/modules/engines/Makefile.am +++ b/src/modules/engines/Makefile.am @@ -71,3 +71,6 @@ endif if !EVAS_STATIC_BUILD_WAYLAND_SHM SUBDIRS += wayland_shm endif +if !EVAS_STATIC_BUILD_WAYLAND_EGL +SUBDIRS += wayland_egl +endif diff --git a/src/modules/engines/wayland_egl/Evas_Engine_Wayland_Egl.h b/src/modules/engines/wayland_egl/Evas_Engine_Wayland_Egl.h new file mode 100644 index 0000000..bc85a21 --- /dev/null +++ b/src/modules/engines/wayland_egl/Evas_Engine_Wayland_Egl.h @@ -0,0 +1,26 @@ +#ifndef _EVAS_ENGINE_WAYLAND_EGL_H +# define _EVAS_ENGINE_WAYLAND_EGL_H + +# include +# include + +typedef struct _Evas_Engine_Info_Wayland_Egl Evas_Engine_Info_Wayland_Egl; +struct _Evas_Engine_Info_Wayland_Egl +{ + Evas_Engine_Info magic; + + struct + { + struct wl_display *disp; + struct wl_compositor *comp; + struct wl_shell *shell; + + int rotation; + + Eina_Bool debug : 1; + } info; + + Evas_Engine_Render_Mode render_mode; +}; + +#endif diff --git a/src/modules/engines/wayland_egl/Makefile.am b/src/modules/engines/wayland_egl/Makefile.am new file mode 100644 index 0000000..d259fcc --- /dev/null +++ b/src/modules/engines/wayland_egl/Makefile.am @@ -0,0 +1,46 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/lib/include \ +-I$(top_srcdir)/src/modules/engines/gl_common \ +@FREETYPE_CFLAGS@ \ +@GL_EET_CFLAGS@ \ +@EINA_CFLAGS@ \ +@evas_engine_wayland_egl_cflags@ + +if BUILD_ENGINE_WAYLAND_EGL + +WAYLAND_EGL_SOURCES = \ +evas_engine.c \ +evas_outbuf.c + +WAYLAND_EGL_LIBADD = @FREETYPE_LIBS@ @GL_EET_LIBS@ @EINA_LIBS@ @evas_engine_wayland_egl_libs@ $(top_builddir)/src/modules/engines/gl_common/libevas_engine_gl_common.la + +includes_HEADERS = Evas_Engine_Wayland_Egl.h +includesdir = $(includedir)/evas-@VMAJ@ + +if !EVAS_STATIC_BUILD_WAYLAND_EGL + +pkgdir = $(libdir)/evas/modules/engines/wayland_egl/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = $(WAYLAND_EGL_SOURCES) +module_la_LIBADD = $(WAYLAND_EGL_LIBADD) $(top_builddir)/src/lib/libevas.la +module_la_LDFLAGS = -no-undefined -module -avoid-version +module_la_LIBTOOLFLAGS = --tag=disable-static + +else + +noinst_LTLIBRARIES = libevas_engine_wayland_egl.la + +libevas_engine_wayland_egl_la_SOURCES = $(WAYLAND_EGL_SOURCES) +libevas_engine_wayland_egl_la_LIBADD = $(WAYLAND_EGL_LIBADD) + +endif +endif + +EXTRA_DIST = \ +evas_engine.h diff --git a/src/modules/engines/wayland_egl/evas_engine.c b/src/modules/engines/wayland_egl/evas_engine.c new file mode 100644 index 0000000..1bd575a --- /dev/null +++ b/src/modules/engines/wayland_egl/evas_engine.c @@ -0,0 +1,409 @@ +#include "evas_common.h" +#include "evas_engine.h" + +#define EVAS_GL_NO_GL_H_CHECK 1 +#include "Evas_GL.h" + +/* local structures */ +typedef struct _Render_Engine Render_Engine; +struct _Render_Engine +{ + Tilebuf *tb; + Outbuf *ob; + + Eina_Bool end : 1; + + void (*outbuf_free)(Outbuf *ob); + void (*outbuf_resize)(Outbuf *ob, int w, int h); +}; + +/* local function prototypes */ +static void *_output_setup(struct wl_display *disp, struct wl_compositor *comp, struct wl_shell *shell, int w, int h, int rotation); + +/* engine function prototypes */ +static void *eng_info(Evas *evas __UNUSED__); +static void eng_info_free(Evas *evas __UNUSED__, void *info); +static int eng_setup(Evas *evas, void *info); +static void eng_output_free(void *data); +static void eng_output_resize(void *data, int w, int h); +static void eng_output_tile_size_set(void *data, int w, int h); +static void eng_output_redraws_rect_add(void *data, int x, int y, int w, int h); +static void eng_output_redraws_rect_del(void *data, int x, int y, int w, int h); +static void eng_output_redraws_clear(void *data); +static void *eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch); +static void eng_output_redraws_next_update_push(void *data, void *surface __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__); +static void eng_output_flush(void *data); +static void eng_output_idle_flush(void *data); +static void eng_output_dump(void *data); +static void *eng_gl_api_get(void *data); +static const GLubyte *evgl_glGetString(GLenum name); + +/* local variables */ +static Evas_Func func, pfunc; +static Evas_GL_API gl_funcs; + +/* external variables */ +int _evas_engine_way_egl_log_dom = -1; + +/* local functions */ +static void * +_output_setup(struct wl_display *disp, struct wl_compositor *comp, struct wl_shell *shell, int w, int h, int rotation) +{ + Render_Engine *re = NULL; + + if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL; + + if (!(re->ob = evas_outbuf_setup(disp, comp, shell, w, h, rotation))) + { + free(re); + return NULL; + } + + if (!(re->tb = evas_common_tilebuf_new(w, h))) + { + evas_outbuf_free(re->ob); + free(re); + return NULL; + } + + evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); + return re; +} + +/* engine functions */ +static void * +eng_info(Evas *evas __UNUSED__) +{ + Evas_Engine_Info_Wayland_Egl *info; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(info = calloc(1, sizeof(Evas_Engine_Info_Wayland_Egl)))) + return NULL; + + info->magic.magic = rand(); + info->info.debug = EINA_FALSE; + info->render_mode = EVAS_RENDER_MODE_BLOCKING; + + return info; +} + +static void +eng_info_free(Evas *evas __UNUSED__, void *info) +{ + Evas_Engine_Info_Wayland_Egl *in; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(in = (Evas_Engine_Info_Wayland_Egl *)info)) return; + free(in); +} + +static int +eng_setup(Evas *evas, void *info) +{ + Evas_Engine_Info_Wayland_Egl *in; + Render_Engine *re = NULL; + + if (!(in = (Evas_Engine_Info_Wayland_Egl *)info)) return 0; + + if (!evas->engine.data.output) + { + evas_common_cpu_init(); + evas_common_blend_init(); + evas_common_image_init(); + evas_common_convert_init(); + evas_common_scale_init(); + evas_common_rectangle_init(); + evas_common_polygon_init(); + evas_common_line_init(); + evas_common_font_init(); + evas_common_draw_init(); + evas_common_tilebuf_init(); + + re = _output_setup(in->info.disp, in->info.comp, in->info.shell, + evas->output.w, evas->output.h, + in->info.rotation); + if (!re) return 0; + + re->outbuf_free = evas_outbuf_free; + re->outbuf_resize = evas_outbuf_resize; + } + else + { + if (!(re = (Render_Engine *)evas->engine.data.output)) return 0; + if (re->ob) re->outbuf_free(re->ob); + re->ob = evas_outbuf_setup(in->info.disp, in->info.comp, in->info.shell, + evas->output.w, evas->output.h, + in->info.rotation); + if (re->tb) evas_common_tilebuf_free(re->tb); + if ((re->tb = evas_common_tilebuf_new(evas->output.w, evas->output.h))) + evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); + } + + evas->engine.data.output = re; + if (!evas->engine.data.output) + { + if (re) free(re); + return 0; + } + + if (!evas->engine.data.context) + { + evas->engine.data.context = + evas->engine.func->context_new(evas->engine.data.output); + } + + return 1; +} + +static void +eng_output_free(void *data) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((re = (Render_Engine *)data)) + { + if (re->ob) re->outbuf_free(re->ob); + if (re->tb) evas_common_tilebuf_free(re->tb); + free(re); + } + evas_common_font_shutdown(); + evas_common_image_shutdown(); +} + +static void +eng_output_resize(void *data, int w, int h) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + if (re->ob) re->outbuf_resize(re->ob, w, h); + if (re->tb) evas_common_tilebuf_free(re->tb); + if ((re->tb = evas_common_tilebuf_new(w, h))) + evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); +} + +static void +eng_output_tile_size_set(void *data, int w, int h) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + if (re->tb) evas_common_tilebuf_set_tile_size(re->tb, w, h); +} + +static void +eng_output_redraws_rect_add(void *data, int x, int y, int w, int h) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + if (re->ob->priv.gl.context) + evas_gl_common_context_resize(re->ob->priv.gl.context, + w, h, re->ob->rot); + if (re->tb) evas_common_tilebuf_add_redraw(re->tb, x, y, w, h); +} + +static void +eng_output_redraws_rect_del(void *data, int x, int y, int w, int h) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + if (re->tb) evas_common_tilebuf_del_redraw(re->tb, x, y, w, h); +} + +static void +eng_output_redraws_clear(void *data) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + if (re->tb) evas_common_tilebuf_clear(re->tb); +} + +static void * +eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch) +{ + Render_Engine *re = NULL; + Tilebuf_Rect *rects; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return NULL; + if ((rects = evas_common_tilebuf_get_render_rects(re->tb))) + { + evas_common_tilebuf_free_render_rects(rects); + evas_common_tilebuf_clear(re->tb); + if (re->ob->priv.gl.context) + { + evas_gl_common_context_flush(re->ob->priv.gl.context); + evas_gl_common_context_newframe(re->ob->priv.gl.context); + } + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = re->ob->w; + if (h) *h = re->ob->h; + if (cx) *cx = 0; + if (cy) *cy = 0; + if (cw) *cw = re->ob->w; + if (ch) *ch = re->ob->h; + return re->ob->priv.gl.context->def_surface; + } + + /* NB: Fixme: This may need to return the wayland surface */ + return NULL; +} + +static void +eng_output_redraws_next_update_push(void *data, void *surface __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + if (re->ob->priv.gl.context) + evas_gl_common_context_flush(re->ob->priv.gl.context); + + eglWaitNative(EGL_CORE_NATIVE_ENGINE); +} + +static void +eng_output_flush(void *data) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + + eglSwapInterval(re->ob->priv.egl.disp, 0); + + /* TODO: callback pre swap */ + + eglSwapBuffers(re->ob->priv.egl.disp, re->ob->priv.egl.surface); + eglWaitGL(); + + /* TODO: Callback post swap */ +} + +static void +eng_output_idle_flush(void *data) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; +} + +static void +eng_output_dump(void *data) +{ + Render_Engine *re = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(re = (Render_Engine *)data)) return; + evas_common_image_image_all_unload(); + evas_common_font_font_all_unload(); + evas_gl_common_image_all_unload(re->ob->priv.gl.context); +} + +static void * +eng_gl_api_get(void *data) +{ + Render_Engine *re = NULL; + + re = (Render_Engine *)data; + + gl_funcs.version = EVAS_GL_API_VERSION; + +#define ORD(f) EVAS_API_OVERRIDE(f, &gl_funcs, evgl_) + ORD(glGetString); +#undef ORD + + return &gl_funcs; +} + +static const GLubyte * +evgl_glGetString(GLenum name) +{ + if (name == GL_EXTENSIONS) + return (GLubyte *)glGetString(GL_EXTENSIONS); + else + return glGetString(name); +} + +/* module functions */ +static int +module_open(Evas_Module *em) +{ + if (!em) return 0; + if (!evas_gl_common_module_open()) return 0; + + if (!_evas_module_engine_inherit(&pfunc, "software_generic")) + return 0; + + _evas_engine_way_egl_log_dom = + eina_log_domain_register("evas-wayland_egl", EVAS_DEFAULT_LOG_COLOR); + if (_evas_engine_way_egl_log_dom < 0) + { + EINA_LOG_ERR("Could not create module log domain."); + return 0; + } + + func = pfunc; + +#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_) + ORD(info); + ORD(info_free); + ORD(setup); + ORD(output_free); + ORD(output_resize); + ORD(output_tile_size_set); + ORD(output_redraws_rect_add); + ORD(output_redraws_rect_del); + ORD(output_redraws_clear); + ORD(output_redraws_next_update_get); + ORD(output_redraws_next_update_push); + ORD(output_flush); + ORD(output_idle_flush); + ORD(output_dump); + ORD(gl_api_get); +#undef ORD + + em->functions = (void *)(&func); + return 1; +} + +static void +module_close(Evas_Module *em __UNUSED__) +{ + eina_log_domain_unregister(_evas_engine_way_egl_log_dom); +} + +static Evas_Module_Api evas_modapi = +{ + EVAS_MODULE_API_VERSION, "wayland_egl", "none", {module_open, module_close} +}; + +EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, wayland_egl); + +#ifndef EVAS_STATIC_BUILD_WAYLAND_EGL +EVAS_EINA_MODULE_DEFINE(engine, wayland_egl); +#endif diff --git a/src/modules/engines/wayland_egl/evas_engine.h b/src/modules/engines/wayland_egl/evas_engine.h new file mode 100644 index 0000000..f613509 --- /dev/null +++ b/src/modules/engines/wayland_egl/evas_engine.h @@ -0,0 +1,86 @@ +#ifndef _EVAS_ENGINE_H +# define _EVAS_ENGINE_H + +# include "config.h" +# include "evas_common.h" +# include "evas_private.h" +# include "evas_gl_common.h" +# include "Evas.h" +# include "Evas_Engine_Wayland_Egl.h" + +# define GL_GLEXT_PROTOTYPES + +# include +// # include +# include + +# if defined (GLES_VARIETY_SGX) +# include +# endif + +//# define LOGFNS 1 + +# ifdef LOGFNS +# include +# define LOGFN(fl, ln, fn) printf("-EVAS-WL: %25s: %5i - %s\n", fl, ln, fn); +# else +# define LOGFN(fl, ln, fn) +# endif + +extern int _evas_engine_way_egl_log_dom; + +# ifdef ERR +# undef ERR +# endif +# define ERR(...) EINA_LOG_DOM_ERR(_evas_engine_way_egl_log_dom, __VA_ARGS__) + +# ifdef DBG +# undef DBG +# endif +# define DBG(...) EINA_LOG_DOM_DBG(_evas_engine_way_egl_log_dom, __VA_ARGS__) + +# ifdef INF +# undef INF +# endif +# define INF(...) EINA_LOG_DOM_INFO(_evas_engine_way_egl_log_dom, __VA_ARGS__) + +# ifdef WRN +# undef WRN +# endif +# define WRN(...) EINA_LOG_DOM_WARN(_evas_engine_way_egl_log_dom, __VA_ARGS__) + +# ifdef CRIT +# undef CRIT +# endif +# define CRIT(...) EINA_LOG_DOM_CRIT(_evas_engine_way_egl_log_dom, __VA_ARGS__) + +typedef struct _Outbuf Outbuf; +struct _Outbuf +{ + int w, h, rot; + int depth, alpha; + + struct + { + struct wl_egl_window *win; + struct wl_surface *surface; + struct wl_shell *shell; + struct + { + Evas_Engine_GL_Context *context; + } gl; + struct + { + EGLDisplay disp; + EGLConfig config; + EGLSurface surface; + EGLContext context; + } egl; + } priv; +}; + +void evas_outbuf_free(Outbuf *ob); +void evas_outbuf_resize(Outbuf *ob, int w, int h); +Outbuf *evas_outbuf_setup(struct wl_display *disp, struct wl_compositor *comp, struct wl_shell *shell, int w, int h, int rot); + +#endif diff --git a/src/modules/engines/wayland_egl/evas_outbuf.c b/src/modules/engines/wayland_egl/evas_outbuf.c new file mode 100644 index 0000000..f915558 --- /dev/null +++ b/src/modules/engines/wayland_egl/evas_outbuf.c @@ -0,0 +1,167 @@ +#include "evas_engine.h" + +/* local function prototypes */ +static Eina_Bool _evas_outbuf_config_get(Outbuf *ob); + +/* local variables */ + +void +evas_outbuf_free(Outbuf *ob) +{ + if (!ob) return; + if (ob->priv.egl.disp) + { + if (ob->priv.gl.context) + evas_gl_common_context_free(ob->priv.gl.context); + + if (ob->priv.egl.surface != EGL_NO_SURFACE) + eglDestroySurface(ob->priv.egl.disp, ob->priv.egl.surface); + + if (ob->priv.egl.context) + eglDestroyContext(ob->priv.egl.disp, ob->priv.egl.context); + + if (ob->priv.win) wl_egl_window_destroy(ob->priv.win); + + /* NB: Fixme: This may close display, have to test */ + eglTerminate(ob->priv.egl.disp); + + eglMakeCurrent(ob->priv.egl.disp, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } + free(ob); +} + +void +evas_outbuf_resize(Outbuf *ob, int w, int h) +{ + if (!ob) return; + if ((ob->w == w) && (ob->h == h)) return; + ob->w = w; + ob->h = h; + wl_egl_window_resize(ob->priv.win, w, h, 0, 0); + if (ob->priv.gl.context) + { + evas_gl_common_context_use(ob->priv.gl.context); + evas_gl_common_context_resize(ob->priv.gl.context, w, h, ob->rot); + evas_gl_common_context_flush(ob->priv.gl.context); + } +} + +Outbuf * +evas_outbuf_setup(struct wl_display *disp, struct wl_compositor *comp, struct wl_shell *shell, int w, int h, int rot) +{ + Outbuf *ob = NULL; + EGLint major, minor; + struct wl_shell_surface *ssurface; + int cattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + int sattr[] = { EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE, EGL_NONE }; + + if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL; + + ob->w = w; + ob->h = h; + ob->rot = rot; + ob->priv.shell = shell; + + if (!(ob->priv.egl.disp = eglGetDisplay(disp))) + { + ERR("eglGetDisplay failed: %#x", eglGetError()); + evas_outbuf_free(ob); + return NULL; + } + + if (!eglInitialize(ob->priv.egl.disp, &major, &minor)) + { + ERR("eglInitialize failed: %#x", eglGetError()); + evas_outbuf_free(ob); + return NULL; + } + + eglBindAPI(EGL_OPENGL_ES_API); + if (eglGetError() != EGL_SUCCESS) + { + ERR("eglBindAPI failed: %#x", eglGetError()); + evas_outbuf_free(ob); + return NULL; + } + + if (!_evas_outbuf_config_get(ob)) + { + evas_outbuf_free(ob); + return NULL; + } + + ob->priv.egl.context = + eglCreateContext(ob->priv.egl.disp, ob->priv.egl.config, + EGL_NO_CONTEXT, cattr); + if (ob->priv.egl.context == EGL_NO_CONTEXT) + { + ERR("eglCreateContext failed: %#x", eglGetError()); + evas_outbuf_free(ob); + return NULL; + } + + /* create wayland surface & window */ + ob->priv.surface = wl_compositor_create_surface(comp); + ob->priv.win = wl_egl_window_create(ob->priv.surface, w, h); + + ob->priv.egl.surface = + eglCreateWindowSurface(ob->priv.egl.disp, ob->priv.egl.config, + ob->priv.win, sattr); + if (ob->priv.egl.surface == EGL_NO_SURFACE) + { + ERR("eglCreateWindowSurface failed: %#x", eglGetError()); + evas_outbuf_free(ob); + return NULL; + } + + ssurface = wl_shell_get_shell_surface(ob->priv.shell, ob->priv.surface); + wl_shell_surface_set_toplevel(ssurface); + + if (eglMakeCurrent(ob->priv.egl.disp, ob->priv.egl.surface, + ob->priv.egl.surface, ob->priv.egl.context) == EGL_FALSE) + { + ERR("eglMakeCurrent failed: %#x", eglGetError()); + evas_outbuf_free(ob); + return NULL; + } + + if (!(ob->priv.gl.context = evas_gl_common_context_new())) + { + ERR("Cannot create evas gl common context."); + evas_outbuf_free(ob); + return NULL; + } + + evas_gl_common_context_use(ob->priv.gl.context); + evas_gl_common_context_resize(ob->priv.gl.context, w, h, rot); + evas_gl_common_context_flush(ob->priv.gl.context); + + return ob; +} + +/* local functions */ +static Eina_Bool +_evas_outbuf_config_get(Outbuf *ob) +{ + int num = 0; + int attrs[] = + { + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT, + EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, + EGL_DEPTH_SIZE, 1, EGL_ALPHA_SIZE, 1, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + if (!ob) return EINA_FALSE; + if (!eglChooseConfig(ob->priv.egl.disp, attrs, &ob->priv.egl.config, + 1, &num) || (num != 1)) + { + ERR("eglChooseConfig failed: %#x", eglGetError()); + return EINA_FALSE; + } + + return EINA_TRUE; +}