From 59294c7381648b55850b159afa7a5028312ee932 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 4 Aug 2014 15:42:17 -0400 Subject: [PATCH 1/5] evas-wayland-egl: Fix includes for using GL Generic Recent changes to evas engines require using evas_gl_generic now, so let's sort out the headers and include the gl_generic one we need Signed-off-by: Chris Michael --- .../evas/engines/wayland_egl/evas_engine.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.h b/src/modules/evas/engines/wayland_egl/evas_engine.h index 3fc12ce026..7465844d2a 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.h +++ b/src/modules/evas/engines/wayland_egl/evas_engine.h @@ -2,24 +2,23 @@ # define EVAS_ENGINE_H # include "config.h" +# include "evas_common_private.h" +# include "evas_private.h" +# include "Evas.h" +# include "Evas_Engine_Wayland_Egl.h" /* NB: This already includes wayland-client.h */ # include +# define GL_GLEXT_PROTOTYPES + # ifdef GL_GLES # include -/* NB: These are already included from gl_common */ -/* # include */ -/* # include */ +# include +# include # endif -# include "evas_common_private.h" -# include "evas_private.h" -# include "evas_gl_common.h" -# include "Evas.h" -# include "Evas_Engine_Wayland_Egl.h" - -# define GL_GLEXT_PROTOTYPES +# include "../gl_generic/Evas_Engine_GL_Generic.h" extern int _evas_engine_wl_egl_log_dom; From 7cf7ca213b871a88ecb40bc0a2df300ac768ba7a Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 4 Aug 2014 16:01:45 -0400 Subject: [PATCH 2/5] evas-wayland-egl: Rename Evas_GL_Wl_Window to Outbuf Signed-off-by: Chris Michael --- .../evas/engines/wayland_egl/evas_engine.c | 2 +- .../evas/engines/wayland_egl/evas_engine.h | 14 +++++++------- .../evas/engines/wayland_egl/evas_wl_main.c | 18 +++++++++--------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.c b/src/modules/evas/engines/wayland_egl/evas_engine.c index bce7453a15..caa245264b 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.c +++ b/src/modules/evas/engines/wayland_egl/evas_engine.c @@ -32,7 +32,7 @@ struct _Render_Engine Tilebuf_Rect *rects_prev[3]; Eina_Inlist *cur_rect; - Evas_GL_Wl_Window *win; + Outbuf *win; Evas_Engine_Info_Wayland_Egl *info; Evas *evas; diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.h b/src/modules/evas/engines/wayland_egl/evas_engine.h index 7465844d2a..7d02fbf15e 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.h +++ b/src/modules/evas/engines/wayland_egl/evas_engine.h @@ -47,9 +47,9 @@ extern int _evas_engine_wl_egl_log_dom; # endif # define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_wl_egl_log_dom, __VA_ARGS__) -typedef struct _Evas_GL_Wl_Window Evas_GL_Wl_Window; +typedef struct _Outbuf Outbuf; -struct _Evas_GL_Wl_Window +struct _Outbuf { struct wl_display *disp; struct wl_egl_window *win; @@ -74,11 +74,11 @@ struct _Evas_GL_Wl_Window Eina_Bool surf : 1; }; -Evas_GL_Wl_Window *eng_window_new(struct wl_display *disp, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect, int alpha, int rot); -void eng_window_free(Evas_GL_Wl_Window *gw); -void eng_window_use(Evas_GL_Wl_Window *gw); -void eng_window_unsurf(Evas_GL_Wl_Window *gw); -void eng_window_resurf(Evas_GL_Wl_Window *gw); +Outbuf *eng_window_new(struct wl_display *disp, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect, int alpha, int rot); +void eng_window_free(Outbuf *gw); +void eng_window_use(Outbuf *gw); +void eng_window_unsurf(Outbuf *gw); +void eng_window_resurf(Outbuf *gw); Eina_Bool eng_window_make_current(void *data, void *doit); #endif diff --git a/src/modules/evas/engines/wayland_egl/evas_wl_main.c b/src/modules/evas/engines/wayland_egl/evas_wl_main.c index 4c495700aa..88d56b46b8 100644 --- a/src/modules/evas/engines/wayland_egl/evas_wl_main.c +++ b/src/modules/evas/engines/wayland_egl/evas_wl_main.c @@ -3,14 +3,14 @@ /* local function prototypes */ /* local variables */ -static Evas_GL_Wl_Window *_evas_gl_wl_window = NULL; +static Outbuf *_evas_gl_wl_window = NULL; static EGLContext context = EGL_NO_CONTEXT; static int win_count = 0; -Evas_GL_Wl_Window * +Outbuf * eng_window_new(struct wl_display *display, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect EINA_UNUSED, int alpha, int rot) { - Evas_GL_Wl_Window *gw; + Outbuf *gw; int context_attrs[3]; int config_attrs[40]; int major_version, minor_version; @@ -19,7 +19,7 @@ eng_window_new(struct wl_display *display, struct wl_surface *surface, int scree Eina_Bool blacklist = EINA_FALSE; /* try to allocate space for our window */ - if (!(gw = calloc(1, sizeof(Evas_GL_Wl_Window)))) + if (!(gw = calloc(1, sizeof(Outbuf)))) return NULL; win_count++; @@ -182,7 +182,7 @@ eng_window_new(struct wl_display *display, struct wl_surface *surface, int scree } void -eng_window_free(Evas_GL_Wl_Window *gw) +eng_window_free(Outbuf *gw) { int ref = 0; @@ -220,7 +220,7 @@ eng_window_free(Evas_GL_Wl_Window *gw) } void -eng_window_use(Evas_GL_Wl_Window *gw) +eng_window_use(Outbuf *gw) { Eina_Bool force = EINA_FALSE; @@ -258,7 +258,7 @@ eng_window_use(Evas_GL_Wl_Window *gw) } void -eng_window_unsurf(Evas_GL_Wl_Window *gw) +eng_window_unsurf(Outbuf *gw) { if (!gw->surf) return; if (!getenv("EVAS_GL_WIN_RESURF")) return; @@ -281,7 +281,7 @@ eng_window_unsurf(Evas_GL_Wl_Window *gw) } void -eng_window_resurf(Evas_GL_Wl_Window *gw) +eng_window_resurf(Outbuf *gw) { if (gw->surf) return; if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", gw); @@ -307,7 +307,7 @@ eng_window_resurf(Evas_GL_Wl_Window *gw) Eina_Bool eng_window_make_current(void *data, void *doit) { - Evas_GL_Wl_Window *gw; + Outbuf *gw; if (!(gw = data)) return EINA_FALSE; From e2c08ffec29fc8b70d0a1625667d1261789ca2fb Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Aug 2014 14:19:15 -0400 Subject: [PATCH 3/5] evas-wayland-egl: Add support for SWAP_MODE_QUADRUPLE and use Eina_Bool for boolean values Signed-off-by: Chris Michael --- .../evas/engines/wayland_egl/Evas_Engine_Wayland_Egl.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/modules/evas/engines/wayland_egl/Evas_Engine_Wayland_Egl.h b/src/modules/evas/engines/wayland_egl/Evas_Engine_Wayland_Egl.h index 259ccf7060..e06f82cf37 100644 --- a/src/modules/evas/engines/wayland_egl/Evas_Engine_Wayland_Egl.h +++ b/src/modules/evas/engines/wayland_egl/Evas_Engine_Wayland_Egl.h @@ -11,7 +11,8 @@ typedef enum _Evas_Engine_Info_Wayland_Egl_Swap_Mode EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_FULL = 1, EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_COPY = 2, EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_DOUBLE = 3, - EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_TRIPLE = 4 + EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_TRIPLE = 4, + EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_QUADRUPLE = 5 } Evas_Engine_Info_Wayland_Egl_Swap_Mode; struct _Evas_Engine_Info_Wayland_Egl @@ -25,6 +26,7 @@ struct _Evas_Engine_Info_Wayland_Egl { struct wl_display *display; struct wl_surface *surface; + struct wl_egl_window *win; int depth, screen, rotation, edges; unsigned int destination_alpha : 1; } info; @@ -39,8 +41,8 @@ struct _Evas_Engine_Info_Wayland_Egl /* non-blocking or blocking mode */ Evas_Engine_Render_Mode render_mode; - unsigned char vsync : 1; - unsigned char indirect : 1; + Eina_Bool vsync : 1; + Eina_Bool indirect : 1; unsigned char swap_mode : 4; }; From 9419e48fb42d59232c192e96afe73454d6b6394a Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Aug 2014 14:19:55 -0400 Subject: [PATCH 4/5] evas-wayland-egl: Add support for EGL_BUFFER_AGE_EXT and add external function pointers for glsym_evas_gl functions Signed-off-by: Chris Michael --- .../evas/engines/wayland_egl/evas_engine.h | 75 ++++++++++++++++--- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.h b/src/modules/evas/engines/wayland_egl/evas_engine.h index 7d02fbf15e..165ff752a6 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.h +++ b/src/modules/evas/engines/wayland_egl/evas_engine.h @@ -12,11 +12,9 @@ # define GL_GLEXT_PROTOTYPES -# ifdef GL_GLES -# include -# include -# include -# endif +# include +# include +# include # include "../gl_generic/Evas_Engine_GL_Generic.h" @@ -47,6 +45,10 @@ extern int _evas_engine_wl_egl_log_dom; # endif # define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_wl_egl_log_dom, __VA_ARGS__) +# ifndef EGL_BUFFER_AGE_EXT +# define EGL_BUFFER_AGE_EXT 0x313d +# endif + typedef struct _Outbuf Outbuf; struct _Outbuf @@ -57,28 +59,83 @@ struct _Outbuf int w, h; int depth, screen, rot, alpha; + Evas *evas; + Evas_Engine_Info_Wayland_Egl *info; Evas_Engine_GL_Context *gl_context; + Render_Engine_Swap_Mode swap_mode; + int prev_age, vsync; + int frame_cnt; + struct { Eina_Bool drew : 1; } draw; -#ifdef GL_GLES EGLContext egl_context[1]; EGLSurface egl_surface[1]; EGLConfig egl_config; EGLDisplay egl_disp; -#endif + Eina_Bool lost_back : 1; Eina_Bool surf : 1; }; -Outbuf *eng_window_new(struct wl_display *disp, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect, int alpha, int rot); +struct _Context_3D +{ + EGLDisplay display; + EGLContext context; + EGLSurface surface; +}; + +extern Eina_Bool extn_have_buffer_age; +extern Eina_Bool extn_have_y_inverted; + +extern Evas_GL_Common_Context_New glsym_evas_gl_common_context_new; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe; +extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done; +extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize; +extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump; +extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock; +extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock; + +extern unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c); + +Outbuf *eng_window_new(struct wl_display *disp, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect, int alpha, int rot, Render_Engine_Swap_Mode swap_mode); void eng_window_free(Outbuf *gw); void eng_window_use(Outbuf *gw); void eng_window_unsurf(Outbuf *gw); void eng_window_resurf(Outbuf *gw); -Eina_Bool eng_window_make_current(void *data, void *doit); + +void eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth); +int eng_outbuf_rotation_get(Outbuf *ob); +Render_Engine_Swap_Mode eng_outbuf_swap_mode_get(Outbuf *ob); +Eina_Bool eng_outbuf_region_first_rect(Outbuf *ob); +void *eng_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); +void eng_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); +void eng_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); +void eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); + +Evas_Engine_GL_Context *eng_outbuf_gl_context_get(Outbuf *ob); +void *eng_outbuf_egl_display_get(Outbuf *ob); +Eina_Bool eng_preload_make_current(void *data, void *doit); + +Context_3D *eng_gl_context_new(Outbuf *win); +void eng_gl_context_free(Context_3D *context); +void eng_gl_context_use(Context_3D *context); + +static inline int +_re_wincheck(Outbuf *ob) +{ + if (ob->surf) return 1; + eng_window_resurf(ob); + ob->lost_back = EINA_TRUE; + if (!ob->surf) + ERR("Wayland EGL Engine cannot recreate window surface"); + return 0; +} #endif From 423506a0aa6c362f9788a48e51e90505a9bc498b Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Wed, 6 Aug 2014 14:24:29 -0400 Subject: [PATCH 5/5] evas-wayland-egl: Fix wayland egl engine to work again Previous (french) changes to evas_gl code broke the wayland egl engine. This batch of changes fixes that by rewriting to engine to work with new evas_gl functions. Fixes Phab ticket T1478 @fix Signed-off-by: Chris Michael --- .../evas/engines/wayland_egl/evas_engine.c | 3094 ++++------------- .../evas/engines/wayland_egl/evas_wl_main.c | 215 +- 2 files changed, 916 insertions(+), 2393 deletions(-) diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.c b/src/modules/evas/engines/wayland_egl/evas_engine.c index caa245264b..4ef9be20a2 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.c +++ b/src/modules/evas/engines/wayland_egl/evas_engine.c @@ -1,54 +1,32 @@ #include "evas_common_private.h" #include "evas_engine.h" -#include "evas_gl_core_private.h" #ifdef HAVE_DLSYM # include #endif +#ifdef EVAS_CSERVE2 +# include "evas_cs2_private.h" +#endif + #define EVAS_GL_NO_GL_H_CHECK 1 #include "Evas_GL.h" -enum -{ - MERGE_BOUNDING, - MERGE_FULL -}; +#define EVAS_GL_UPDATE_TILE_SIZE 16 -enum -{ - MODE_FULL, - MODE_COPY, - MODE_DOUBLE, - MODE_TRIPLE -}; +#ifndef EGL_NATIVE_PIXMAP_KHR +# define EGL_NATIVE_PIXMAP_KHR 0x30b0 +#endif + +#ifndef EGL_Y_INVERTED_NOK +# define EGL_Y_INVERTED_NOK 0x307F +#endif /* local structures */ typedef struct _Render_Engine Render_Engine; struct _Render_Engine { - Tilebuf *tb; - Tilebuf_Rect *rects; - Tilebuf_Rect *rects_prev[3]; - Eina_Inlist *cur_rect; - - Outbuf *win; - Evas_Engine_Info_Wayland_Egl *info; - Evas *evas; - - int w, h, mode, vsync, prev_age; - - Eina_Bool lost_back : 1; - Eina_Bool end : 1; - Eina_Bool evgl_initted : 1; - int frame_cnt; - - struct - { - Evas_Object_Image_Pixels_Get_Cb pixels_get; - void *pixels_data_get; - Evas_Object *obj; - } func; + Render_Engine_GL_Generic generic; }; typedef struct _Native Native; @@ -67,49 +45,406 @@ typedef int (*glsym_func_int) (); typedef unsigned int (*glsym_func_uint) (); typedef const char *(*glsym_func_const_char_ptr) (); -static Eina_Bool evgl_init(Render_Engine *re); -static void evgl_symbols(void); -static void evgl_extn_veto(Render_Engine *re); -static void *evgl_eng_display_get(void *data); -static void *evgl_eng_evas_surface_get(void *data); -static int evgl_eng_make_current(void *data, void *surface, void *context, int flush); -static void *evgl_eng_native_window_create(void *data); -static int evgl_eng_native_window_destroy(void *data, void *native_window); -static void *evgl_eng_window_surface_create(void *data, void *native_window); -static int evgl_eng_window_surface_destroy(void *data, void *surface); -static void *evgl_eng_context_create(void *data, void *share_context); -static int evgl_eng_context_destroy(void *data, void *context); -static const char *evgl_eng_string_get(void *data); -static void *evgl_eng_proc_address_get(const char *name); -static int evgl_eng_rotation_angle_get(void *data); +Evas_GL_Common_Image_Call glsym_evas_gl_common_image_ref = NULL; +Evas_GL_Common_Image_Call glsym_evas_gl_common_image_unref = NULL; +Evas_GL_Common_Image_Call glsym_evas_gl_common_image_free = NULL; +Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_disable = NULL; +Evas_GL_Common_Image_Call glsym_evas_gl_common_image_native_enable = NULL; +Evas_GL_Common_Image_New_From_Data glsym_evas_gl_common_image_new_from_data = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_image_all_unload = NULL; +Evas_GL_Preload glsym_evas_gl_preload_init = NULL; +Evas_GL_Preload glsym_evas_gl_preload_shutdown = NULL; +EVGL_Engine_Call glsym_evgl_engine_shutdown = NULL; +Evas_Gl_Symbols glsym_evas_gl_symbols = NULL; -static Eina_Bool _re_wincheck(Render_Engine *re); -static void _re_winfree(Render_Engine *re); -static Tilebuf_Rect *_merge_rects(Tilebuf *tb, Tilebuf_Rect *r1, Tilebuf_Rect *r2, Tilebuf_Rect *r3); -static void _native_bind_cb(void *data EINA_UNUSED, void *image); -static void _native_unbind_cb(void *data EINA_UNUSED, void *image); -static void _native_free_cb(void *data, void *image); +Evas_GL_Common_Context_New glsym_evas_gl_common_context_new = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_flush = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_free = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe = NULL; +Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done = NULL; +Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize = NULL; +Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump = NULL; +Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL; +Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL; +Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL; -static Evas_Colorspace eng_image_colorspace_get(void *data EINA_UNUSED, void *image); -static int eng_image_alpha_get(void *data EINA_UNUSED, void *image); - -static Eina_Bool eng_gl_preload_make_current(void *data, void *doit); - -#define EVGLINIT(_re, _ret) if (!evgl_init(_re)) return _ret; +_eng_fn (*glsym_eglGetProcAddress) (const char *a) = NULL; +void *(*glsym_eglCreateImage) (EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL; +void (*glsym_eglDestroyImage) (EGLDisplay a, void *b) = NULL; +void (*glsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL; +unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL; /* local variables */ +static int safe_native = -1; static Eina_Bool initted = EINA_FALSE; static int gl_wins = 0; -static Eina_Bool extn_have_buffer_age = EINA_TRUE; -static int safe_native = -1; -static int partial_rect_union_mode = -1; - -static int swap_buffer_debug_mode = -1; -static int swap_buffer_debug = 0; - -/* function tables - filled in later (func and parent func) */ static Evas_Func func, pfunc; -static EVGL_Interface evgl_funcs = + +/* external variables */ +Eina_Bool extn_have_buffer_age = EINA_TRUE; +Eina_Bool extn_have_y_inverted = EINA_TRUE; + +/* local functions */ +static inline Outbuf * +eng_get_ob(Render_Engine *re) +{ + return re->generic.software.ob; +} + +static void +gl_symbols(void) +{ + static Eina_Bool done = EINA_FALSE; + + if (done) return; + +#define LINK2GENERIC(sym) \ + glsym_##sym = dlsym(RTLD_DEFAULT, #sym); + + // Get function pointer to evas_gl_common now provided through GL_Generic. + LINK2GENERIC(evas_gl_common_image_all_unload); + LINK2GENERIC(evas_gl_common_image_ref); + LINK2GENERIC(evas_gl_common_image_unref); + LINK2GENERIC(evas_gl_common_image_new_from_data); + LINK2GENERIC(evas_gl_common_image_native_disable); + LINK2GENERIC(evas_gl_common_image_free); + LINK2GENERIC(evas_gl_common_image_native_enable); + LINK2GENERIC(evas_gl_common_context_new); + LINK2GENERIC(evas_gl_common_context_flush); + LINK2GENERIC(evas_gl_common_context_free); + LINK2GENERIC(evas_gl_common_context_use); + LINK2GENERIC(evas_gl_common_context_newframe); + LINK2GENERIC(evas_gl_common_context_done); + LINK2GENERIC(evas_gl_common_context_resize); + LINK2GENERIC(evas_gl_common_buffer_dump); + LINK2GENERIC(evas_gl_preload_render_lock); + LINK2GENERIC(evas_gl_preload_render_unlock); + LINK2GENERIC(evas_gl_preload_render_relax); + LINK2GENERIC(evas_gl_preload_init); + LINK2GENERIC(evas_gl_preload_shutdown); + LINK2GENERIC(evgl_engine_shutdown); + LINK2GENERIC(evas_gl_symbols); + +#define FINDSYM(dst, sym, typ) \ + if (glsym_eglGetProcAddress) { \ + if (!dst) dst = (typ)glsym_eglGetProcAddress(sym); \ + } else { \ + if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym); \ + } + + FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressKHR", glsym_func_eng_fn); + FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressEXT", glsym_func_eng_fn); + FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressARB", glsym_func_eng_fn); + FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddress", glsym_func_eng_fn); + + glsym_evas_gl_symbols((void*)glsym_eglGetProcAddress); + + FINDSYM(glsym_eglCreateImage, "eglCreateImageKHR", glsym_func_void_ptr); + FINDSYM(glsym_eglCreateImage, "eglCreateImageEXT", glsym_func_void_ptr); + FINDSYM(glsym_eglCreateImage, "eglCreateImageARB", glsym_func_void_ptr); + FINDSYM(glsym_eglCreateImage, "eglCreateImage", glsym_func_void_ptr); + + FINDSYM(glsym_eglDestroyImage, "eglDestroyImageKHR", glsym_func_void); + FINDSYM(glsym_eglDestroyImage, "eglDestroyImageEXT", glsym_func_void); + FINDSYM(glsym_eglDestroyImage, "eglDestroyImageARB", glsym_func_void); + FINDSYM(glsym_eglDestroyImage, "eglDestroyImage", glsym_func_void); + + FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", + glsym_func_void); + + FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageEXT", + glsym_func_uint); + FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageINTEL", + glsym_func_uint); + FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage", + glsym_func_uint); + + done = EINA_TRUE; +} + +static void +gl_extn_veto(Render_Engine *re) +{ + const char *str = NULL; + + str = eglQueryString(eng_get_ob(re)->egl_disp, EGL_EXTENSIONS); + if (str) + { + if (getenv("EVAS_GL_INFO")) + printf("EGL EXTN:\n%s\n", str); + if (!strstr(str, "EGL_EXT_buffer_age")) + { + extn_have_buffer_age = EINA_FALSE; + } + if (!strstr(str, "EGL_NOK_texture_from_pixmap")) + { + extn_have_y_inverted = EINA_FALSE; + } + else + { + const GLubyte *vendor, *renderer; + + vendor = glGetString(GL_VENDOR); + renderer = glGetString(GL_RENDERER); + // XXX: workaround mesa bug! + // looking for mesa and intel build which is known to + // advertise the EGL_NOK_texture_from_pixmap extension + // but not set it correctly. guessing vendor/renderer + // strings will be like the following: + // OpenGL vendor string: Intel Open Source Technology Center + // OpenGL renderer string: Mesa DRI Intel(R) Sandybridge Desktop + if (((vendor) && (strstr((const char *)vendor, "Intel"))) && + ((renderer) && (strstr((const char *)renderer, "Mesa"))) && + ((renderer) && (strstr((const char *)renderer, "Intel"))) + ) + extn_have_y_inverted = EINA_FALSE; + } + if (!strstr(str, "EGL_EXT_swap_buffers_with_damage")) + { + glsym_eglSwapBuffersWithDamage = NULL; + } + } + else + { + if (getenv("EVAS_GL_INFO")) + printf("NO EGL EXTN!\n"); + extn_have_buffer_age = EINA_FALSE; + } +} + +static void +_re_winfree(Render_Engine *re) +{ + Outbuf *ob; + + if (!(ob = eng_get_ob(re))) return; + if (!ob->surf) return; + glsym_evas_gl_preload_render_relax(eng_preload_make_current, ob); + eng_window_unsurf(ob); +} + +static void * +evgl_eng_display_get(void *data) +{ + Render_Engine *re; + Outbuf *ob; + + if (!(re = (Render_Engine *)data)) return NULL; + if (!(ob = eng_get_ob(re))) return NULL; + return (void *)ob->egl_disp; +} + +static void * +evgl_eng_evas_surface_get(void *data) +{ + Render_Engine *re; + Outbuf *ob; + + if (!(re = (Render_Engine *)data)) return NULL; + if (!(ob = eng_get_ob(re))) return NULL; + return (void *)ob->egl_surface[0]; +} + +static void * +evgl_eng_native_window_create(void *data) +{ + Render_Engine *re; + Outbuf *ob; + struct wl_egl_window *win; + + if (!(re = (Render_Engine *)data)) return NULL; + if (!(ob = eng_get_ob(re))) return NULL; + + if (!(win = wl_egl_window_create(ob->info->info.surface, 1, 1))) + { + ERR("Could not create wl_egl window: %m"); + return NULL; + } + + return (void *)win; +} + +static int +evgl_eng_native_window_destroy(void *data, void *win) +{ + Render_Engine *re; + + if (!(re = (Render_Engine *)data)) return 0; + if (!win) return 0; + + wl_egl_window_destroy((struct wl_egl_window *)win); + win = NULL; + + return 1; +} + +static void * +evgl_eng_window_surface_create(void *data, void *win) +{ + Render_Engine *re; + Outbuf *ob; + EGLSurface surface = EGL_NO_SURFACE; + + if (!(re = (Render_Engine *)data)) return NULL; + if (!(ob = eng_get_ob(re))) return NULL; + + surface = eglCreateWindowSurface(ob->egl_disp, ob->egl_config, + (EGLNativeWindowType)win, NULL); + if (!surface) + { + ERR("Could not create egl window surface: %#x", eglGetError()); + return NULL; + } + + return (void *)surface; +} + +static int +evgl_eng_window_surface_destroy(void *data, void *surface) +{ + Render_Engine *re; + Outbuf *ob; + + if (!(re = (Render_Engine *)data)) return 0; + if (!(ob = eng_get_ob(re))) return 0; + if (!surface) return 0; + + eglDestroySurface(ob->egl_disp, (EGLSurface)surface); + return 1; +} + +static void * +evgl_eng_context_create(void *data, void *ctxt) +{ + Render_Engine *re; + Outbuf *ob; + EGLContext context = EGL_NO_CONTEXT; + int attrs[3]; + + if (!(re = (Render_Engine *)data)) return NULL; + if (!(ob = eng_get_ob(re))) return NULL; + + attrs[0] = EGL_CONTEXT_CLIENT_VERSION; + attrs[1] = 2; + attrs[3] = EGL_NONE; + + if (ctxt) + { + context = + eglCreateContext(ob->egl_disp, ob->egl_config, + (EGLContext)ctxt, attrs); + } + else + { + context = + eglCreateContext(ob->egl_disp, ob->egl_config, + ob->egl_context[0], attrs); + } + + if (!context) + { + ERR("Failed to create egl context: %#x", eglGetError()); + return NULL; + } + + return (void *)context; +} + +static int +evgl_eng_context_destroy(void *data, void *ctxt) +{ + Render_Engine *re; + Outbuf *ob; + + if (!(re = (Render_Engine *)data)) return 0; + if (!(ob = eng_get_ob(re))) return 0; + if (!ctxt) return 0; + + eglDestroyContext(ob->egl_disp, (EGLContext)ctxt); + return 1; +} + +static int +evgl_eng_make_current(void *data, void *surface, void *ctxt, int flush) +{ + Render_Engine *re; + Outbuf *ob; + EGLContext ctx; + EGLSurface surf; + int ret = 0; + + if (!(re = (Render_Engine *)data)) return 0; + if (!(ob = eng_get_ob(re))) return 0; + + ctx = (EGLContext)ctxt; + surf = (EGLSurface)surface; + + if ((!ctxt) && (!surface)) + { + ret = + eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!ret) + { + ERR("eglMakeCurrent Failed: %#x", eglGetError()); + return 0; + } + return 1; + } + + if ((eglGetCurrentContext() != ctx) || + (eglGetCurrentSurface(EGL_READ) != surf) || + (eglGetCurrentSurface(EGL_DRAW) != surf)) + { + if (flush) eng_window_use(NULL); + + ret = eglMakeCurrent(ob->egl_disp, surf, surf, ctx); + if (!ret) + { + ERR("eglMakeCurrent Failed: %#x", eglGetError()); + return 0; + } + } + + return 1; +} + +static void * +evgl_eng_proc_address_get(const char *name) +{ + if (glsym_eglGetProcAddress) return glsym_eglGetProcAddress(name); + return dlsym(RTLD_DEFAULT, name); +} + +static const char * +evgl_eng_string_get(void *data) +{ + Render_Engine *re; + Outbuf *ob; + + if (!(re = (Render_Engine *)data)) return NULL; + if (!(ob = eng_get_ob(re))) return NULL; + + return eglQueryString(ob->egl_disp, EGL_EXTENSIONS); +} + +static int +evgl_eng_rotation_angle_get(void *data) +{ + Render_Engine *re; + Outbuf *ob; + + if (!(re = (Render_Engine *)data)) return 0; + if (!(ob = eng_get_ob(re))) return 0; + + if (ob->gl_context) + return ob->gl_context->rot; + + return 0; +} + +static const EVGL_Interface evgl_funcs = { evgl_eng_display_get, evgl_eng_evas_surface_get, @@ -125,491 +460,7 @@ static EVGL_Interface evgl_funcs = evgl_eng_rotation_angle_get }; -/* external variables */ -int _evas_engine_wl_egl_log_dom = -1; - -#ifdef GL_GLES - -# ifndef EGL_NATIVE_PIXMAP_KHR -# define EGL_NATIVE_PIXMAP_KHR 0x30b0 -# endif - -# ifndef EGL_BUFFER_AGE_EXT -# define EGL_BUFFER_AGE_EXT 0x313d -# endif - -_eng_fn (*glsym_eglGetProcAddress) (const char *a) = NULL; -void *(*glsym_eglCreateImage) (EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL; -void (*glsym_eglDestroyImage) (EGLDisplay a, void *b) = NULL; -void (*glsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL; -void *(*glsym_eglMapImageSEC) (void *a, void *b, int c, int d) = NULL; -unsigned int (*glsym_eglUnmapImageSEC) (void *a, void *b, int c) = NULL; -unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c) = NULL; - -#endif - -/* local functions */ -static Eina_Bool -evgl_init(Render_Engine *re) -{ - if (!re) return EINA_FALSE; - if (re->evgl_initted) return EINA_TRUE; - if (!evgl_engine_init(re, &evgl_funcs)) return EINA_FALSE; - re->evgl_initted = EINA_TRUE; - return EINA_TRUE; -} - -static void -evgl_symbols(void) -{ - static Eina_Bool done = EINA_FALSE; - - if (done) return; - -#define FINDSYM(dst, sym, typ) \ - if (glsym_eglGetProcAddress) { \ - if (!dst) dst = (typ)glsym_eglGetProcAddress(sym); \ - } \ - if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym); - - FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressKHR", glsym_func_eng_fn); - FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressEXT", glsym_func_eng_fn); - FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressARB", glsym_func_eng_fn); - FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddress", glsym_func_eng_fn); - - FINDSYM(glsym_eglCreateImage, "eglCreateImageKHR", glsym_func_void_ptr); - FINDSYM(glsym_eglCreateImage, "eglCreateImageEXT", glsym_func_void_ptr); - FINDSYM(glsym_eglCreateImage, "eglCreateImageARB", glsym_func_void_ptr); - FINDSYM(glsym_eglCreateImage, "eglCreateImage", glsym_func_void_ptr); - - FINDSYM(glsym_eglDestroyImage, "eglDestroyImageKHR", glsym_func_void); - FINDSYM(glsym_eglDestroyImage, "eglDestroyImageEXT", glsym_func_void); - FINDSYM(glsym_eglDestroyImage, "eglDestroyImageARB", glsym_func_void); - FINDSYM(glsym_eglDestroyImage, "eglDestroyImage", glsym_func_void); - - FINDSYM(glsym_glEGLImageTargetTexture2DOES, - "glEGLImageTargetTexture2DOES", glsym_func_void); - - FINDSYM(glsym_eglMapImageSEC, "eglMapImageSEC", glsym_func_void_ptr); - FINDSYM(glsym_eglUnmapImageSEC, "eglUnmapImageSEC", glsym_func_uint); - - FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageEXT", - glsym_func_uint); - FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageINTEL", - glsym_func_uint); - FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage", - glsym_func_uint); - - done = EINA_TRUE; -} - -static void -evgl_extn_veto(Render_Engine *re) -{ - const char *str = NULL; - - if ((!re) || (!re->win)) return; - - str = eglQueryString(re->win->egl_disp, EGL_EXTENSIONS); - if (str) - { - if (getenv("EVAS_GL_INFO")) printf("EGL EXTENSION:\n%s\n", str); - if (!strstr(str, "EGL_EXT_buffer_age")) - extn_have_buffer_age = EINA_FALSE; - /* if (!strstr(str, "swap_buffers_with_damage")) */ - /* glsym_eglSwapBuffersWithDamage = NULL; */ - } - else - { - if (getenv("EVAS_GL_INFO")) printf("NO EGL EXTENSIONS !!\n"); - extn_have_buffer_age = EINA_FALSE; - glsym_eglSwapBuffersWithDamage = NULL; - } -} - -static void * -evgl_eng_display_get(void *data) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - - EVGLINIT(re, NULL); - if (re->win) return re->win->egl_disp; - return NULL; -} - -static void * -evgl_eng_evas_surface_get(void *data) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - - EVGLINIT(re, NULL); - if (re->win) return re->win->egl_surface[0]; - return NULL; -} - -static int -evgl_eng_make_current(void *data, void *surface, void *context, int flush) -{ - Render_Engine *re; - EGLContext ctx; - EGLSurface sfc; - EGLDisplay dpy; - int ret = 0; - - if (!(re = (Render_Engine *)data)) return 0; - - EVGLINIT(re, 0); - - dpy = re->win->egl_disp; - ctx = (EGLContext)context; - sfc = (EGLSurface)surface; - - if ((!context) && (!surface)) - { - ret = eglMakeCurrent(dpy, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!ret) - { - ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError()); - return 0; - } - - return 1; - } - - if ((eglGetCurrentContext() != ctx) || - (eglGetCurrentSurface(EGL_READ) != sfc) || - (eglGetCurrentSurface(EGL_DRAW) != sfc) ) - { - - //!!!! Does it need to be flushed with it's set to NULL above?? - // Flush remainder of what's in Evas' pipeline - if (flush) eng_window_use(NULL); - - // Do a make current - ret = eglMakeCurrent(dpy, sfc, sfc, ctx); - if (!ret) - { - ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError()); - return 0; - } - } - - return 1; -} - -static void * -evgl_eng_native_window_create(void *data) -{ - Render_Engine *re; - struct wl_egl_window *win; - - if (!(re = (Render_Engine *)data)) return NULL; - if (!re->info) return NULL; -// if (!re->info->info.surface) return NULL; - - EVGLINIT(re, NULL); - - win = wl_egl_window_create(re->info->info.surface, 1, 1); - - return win; -} - -static int -evgl_eng_native_window_destroy(void *data, void *native_window) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return 0; - - EVGLINIT(re, 0); - - wl_egl_window_destroy((struct wl_egl_window *)native_window); - - return 1; -} - -static void * -evgl_eng_window_surface_create(void *data, void *native_window) -{ - Render_Engine *re; - EGLSurface surface = EGL_NO_SURFACE; - - if (!(re = (Render_Engine *)data)) return NULL; - - EVGLINIT(re, NULL); - - surface = - eglCreateWindowSurface(re->win->egl_disp, re->win->egl_config, - (EGLNativeWindowType)native_window, NULL); - if (!surface) - { - ERR("Creating window surface failed. Error: %#x.", eglGetError()); - return NULL; - } - - return surface; -} - -static int -evgl_eng_window_surface_destroy(void *data, void *surface) -{ - Render_Engine *re; - EGLBoolean ret = EGL_FALSE; - - if (!(re = (Render_Engine *)data)) return 0; - if (!surface) return 0; - - ret = eglDestroySurface(re->win->egl_disp, (EGLSurface)surface); - if (ret == EGL_TRUE) return 1; - - return 0; -} - -static void * -evgl_eng_context_create(void *data, void *share_context) -{ - Render_Engine *re; - EGLContext context = EGL_NO_CONTEXT; - int context_attrs[3]; - - if (!(re = (Render_Engine *)data)) return NULL; - - EVGLINIT(re, NULL); - - context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION; - context_attrs[1] = 2; - context_attrs[2] = EGL_NONE; - - // Share context already assumes that it's sharing with evas' context - if (share_context) - { - context = eglCreateContext(re->win->egl_disp, re->win->egl_config, - (EGLContext)share_context, context_attrs); - } - else - { - context = eglCreateContext(re->win->egl_disp, re->win->egl_config, - re->win->egl_context[0], context_attrs); - } - - if (!context) - { - ERR("Engine Context Creations Failed. Error: %#x.", eglGetError()); - return NULL; - } - - return (void*)context; -} - -static int -evgl_eng_context_destroy(void *data, void *context) -{ - Render_Engine *re; - EGLBoolean ret = EGL_FALSE; - - if (!(re = (Render_Engine *)data)) return 0; - - EVGLINIT(re, 0); - - if (!context) return 0; - - ret = eglDestroyContext(re->win->egl_disp, (EGLContext)context); - if (ret == EGL_TRUE) return 1; - - return 0; -} - -static const char * -evgl_eng_string_get(void *data) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - - EVGLINIT(re, NULL); - - return eglQueryString(re->win->egl_disp, EGL_EXTENSIONS); -} - -static void * -evgl_eng_proc_address_get(const char *name) -{ - if (glsym_eglGetProcAddress) return glsym_eglGetProcAddress(name); - return dlsym(RTLD_DEFAULT, name); -} - -static int -evgl_eng_rotation_angle_get(void *data) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return 0; - - EVGLINIT(re, 0); - - if ((re->win) && (re->win->gl_context)) - return re->win->gl_context->rot; - - return 0; -} - -static Eina_Bool -_re_wincheck(Render_Engine *re) -{ - if (!re) return EINA_FALSE; - if (re->win) - { - if (re->win->surf) return EINA_TRUE; - - eng_window_resurf(re->win); - re->lost_back = EINA_TRUE; - - if (!re->win->surf) - ERR("EGL engine can't re-create window surface!"); - } - - return EINA_FALSE; -} - -static void -_re_winfree(Render_Engine *re) -{ - if ((!re) || (!re->win)) return; - if (!re->win->surf) return; - evas_gl_preload_render_relax(eng_gl_preload_make_current, re); - eng_window_unsurf(re->win); -} - -static Tilebuf_Rect * -_merge_rects(Tilebuf *tb, Tilebuf_Rect *r1, Tilebuf_Rect *r2, Tilebuf_Rect *r3) -{ - Tilebuf_Rect *r, *rects; - Evas_Point p1, p2; - - if (r1) - { - EINA_INLIST_FOREACH(EINA_INLIST_GET(r1), r) - evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h); - } - if (r2) - { - EINA_INLIST_FOREACH(EINA_INLIST_GET(r2), r) - evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h); - } - if (r3) - { - EINA_INLIST_FOREACH(EINA_INLIST_GET(r3), r) - evas_common_tilebuf_add_redraw(tb, r->x, r->y, r->w, r->h); - } - - rects = evas_common_tilebuf_get_render_rects(tb); - - if (partial_rect_union_mode == -1) - { - const char *s; - - if ((s = getenv("EVAS_GL_PARTIAL_MERGE"))) - { - if ((!strcmp(s, "bounding")) || (!strcmp(s, "b"))) - partial_rect_union_mode = MERGE_BOUNDING; - else if ((!strcmp(s, "full")) || (!strcmp(s, "f"))) - partial_rect_union_mode = MERGE_FULL; - } - else - partial_rect_union_mode = MERGE_BOUNDING; - } - - if (partial_rect_union_mode == MERGE_BOUNDING) - { -// bounding box -> make a bounding box single region update of all regions. -// yes we could try and be smart and figure out size of regions, how far -// apart etc. etc. to try and figure out an optimal "set". this is a tradeoff -// between multiple update regions to render and total pixels to render. - if (rects) - { - p1.x = rects->x; p1.y = rects->y; - p2.x = rects->x + rects->w; p2.y = rects->y + rects->h; - EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r) - { - if (r->x < p1.x) p1.x = r->x; - if (r->y < p1.y) p1.y = r->y; - if ((r->x + r->w) > p2.x) p2.x = r->x + r->w; - if ((r->y + r->h) > p2.y) p2.y = r->y + r->h; - } - evas_common_tilebuf_free_render_rects(rects); - rects = calloc(1, sizeof(Tilebuf_Rect)); - if (rects) - { - rects->x = p1.x; - rects->y = p1.y; - rects->w = p2.x - p1.x; - rects->h = p2.y - p1.y; - } - } - } - - evas_common_tilebuf_clear(tb); - return rects; -} - -static void -_native_bind_cb(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; - Native *n; - - if (!(im = image)) return; - if (!(n = im->native.data)) return; - - if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) - glBindTexture(GL_TEXTURE_2D, n->ns.data.opengl.texture_id); -} - -static void -_native_unbind_cb(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; - Native *n; - - if (!(im = image)) return; - if (!(n = im->native.data)) return; - if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) - glBindTexture(GL_TEXTURE_2D, 0); -} - -static void -_native_free_cb(void *data, void *image) -{ - Render_Engine *re; - Evas_GL_Image *im; - Native *n; - unsigned int texid; - - if (!(re = (Render_Engine *)data)) return; - if (!(im = image)) return; - if (!(n = im->native.data)) return; - - if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) - { - texid = n->ns.data.opengl.texture_id; - eina_hash_del(re->win->gl_context->shared->native_tex_hash, - &texid, im); - } - - im->native.data = NULL; - im->native.func.data = NULL; - im->native.func.bind = NULL; - im->native.func.unbind = NULL; - im->native.func.free = NULL; - free(n); -} - -/* engine specific override functions */ +/* engine functions */ static void * eng_info(Evas *evas EINA_UNUSED) { @@ -630,24 +481,102 @@ eng_info_free(Evas *evas EINA_UNUSED, void *info) { Evas_Engine_Info_Wayland_Egl *inf; - inf = (Evas_Engine_Info_Wayland_Egl *)info; - free(inf); + if ((inf = (Evas_Engine_Info_Wayland_Egl *)info)) + free(inf); } static int eng_setup(Evas *evas, void *info) { + Render_Engine_Swap_Mode swap_mode = MODE_FULL; Evas_Engine_Info_Wayland_Egl *inf; Evas_Public_Data *epd; Render_Engine *re; + Outbuf *ob; const char *s; inf = (Evas_Engine_Info_Wayland_Egl *)info; epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS); - /* check for existing engine output */ - if (!epd->engine.data.output) + if ((s = getenv("EVAS_GL_SWAP_MODE"))) { + if ((!strcasecmp(s, "full")) || + (!strcasecmp(s, "f"))) + swap_mode = MODE_FULL; + else if ((!strcasecmp(s, "copy")) || + (!strcasecmp(s, "c"))) + swap_mode = MODE_COPY; + else if ((!strcasecmp(s, "double")) || + (!strcasecmp(s, "d")) || + (!strcasecmp(s, "2"))) + swap_mode = MODE_DOUBLE; + else if ((!strcasecmp(s, "triple")) || + (!strcasecmp(s, "t")) || + (!strcasecmp(s, "3"))) + swap_mode = MODE_TRIPLE; + else if ((!strcasecmp(s, "quadruple")) || + (!strcasecmp(s, "q")) || + (!strcasecmp(s, "4"))) + swap_mode = MODE_QUADRUPLE; + } + else + { +// in most gl implementations - egl and glx here that we care about the TEND +// to either swap or copy backbuffer and front buffer, but strictly that is +// not true. technically backbuffer content is totally undefined after a swap +// and thus you MUST re-render all of it, thus MODE_FULL + swap_mode = MODE_FULL; +// BUT... reality is that lmost every implementation copies or swaps so +// triple buffer mode can be used as it is a superset of double buffer and +// copy (though using those explicitly is more efficient). so let's play with +// triple buffer mdoe as a default and see. +// re->mode = MODE_TRIPLE; +// XXX: note - the above seems to break on some older intel chipsets and +// drivers. it seems we CANT depend on backbuffer staying around. bugger! + switch (inf->swap_mode) + { + case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_FULL: + swap_mode = MODE_FULL; + break; + case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_COPY: + swap_mode = MODE_COPY; + break; + case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_DOUBLE: + swap_mode = MODE_DOUBLE; + break; + case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_TRIPLE: + swap_mode = MODE_TRIPLE; + break; + case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_QUADRUPLE: + swap_mode = MODE_QUADRUPLE; + break; + default: + swap_mode = MODE_AUTO; + break; + } + } + + if (safe_native == -1) + { + s = getenv("EVAS_GL_SAFE_NATIVE"); + safe_native = 0; + if (s) safe_native = atoi(s); + else + { + s = (const char *)glGetString(GL_RENDERER); + if (s) + { + if (strstr(s, "PowerVR SGX 540") || + strstr(s, "Mali-400 MP")) + safe_native = 1; + } + } + } + + if (!(re = epd->engine.data.output)) + { + Render_Engine_Merge_Mode merge = MERGE_BOUNDING; + /* FIXME: Remove this line as soon as eglGetDisplay() autodetection * gets fixed. Currently it is incorrectly detecting wl_display and * returning _EGL_PLATFORM_X11 instead of _EGL_PLATFORM_WAYLAND. @@ -660,16 +589,9 @@ eng_setup(Evas *evas, void *info) if (!(re = calloc(1, sizeof(Render_Engine)))) return 0; - /* set some properties of the render engine */ - re->info = inf; - re->evas = evas; - re->w = epd->output.w; - re->h = epd->output.h; - /* if we have not initialize gl & evas, do it */ if (!initted) { - evgl_symbols(); evas_common_cpu_init(); evas_common_blend_init(); evas_common_image_init(); @@ -681,176 +603,136 @@ eng_setup(Evas *evas, void *info) evas_common_font_init(); evas_common_draw_init(); evas_common_tilebuf_init(); - evas_gl_preload_init(); - evgl_extn_veto(re); -// evgl_engine_init(re, &evgl_funcs); - initted = EINA_TRUE; + glsym_evas_gl_preload_init(); } - /* try to create a new window */ - re->win = eng_window_new(inf->info.display, inf->info.surface, - inf->info.screen, inf->info.depth, - re->w, re->h, inf->indirect, - inf->info.destination_alpha, - inf->info.rotation); - if (!re->win) + ob = eng_window_new(inf->info.display, inf->info.surface, + inf->info.screen, inf->info.depth, + epd->output.w, epd->output.h, + inf->indirect, + inf->info.destination_alpha, + inf->info.rotation, swap_mode); + if (!ob) goto ob_err; + + if (!evas_render_engine_gl_generic_init(&re->generic, ob, + eng_outbuf_swap_mode_get, + eng_outbuf_rotation_get, + eng_outbuf_reconfigure, + eng_outbuf_region_first_rect, + eng_outbuf_update_region_new, + eng_outbuf_update_region_push, + eng_outbuf_update_region_free, + NULL, + eng_outbuf_flush, + eng_window_free, + eng_window_use, + eng_outbuf_gl_context_get, + eng_outbuf_egl_display_get, + eng_gl_context_new, + eng_gl_context_use, + &evgl_funcs, + epd->output.w, epd->output.h)) { - free(re); - return 0; + /* TODO: free Outbuf */ + goto ob_err; } - /* tell the engine to use this render_engine for output */ epd->engine.data.output = re; gl_wins++; + + if ((s = getenv("EVAS_GL_PARTIAL_MERGE"))) + { + if ((!strcmp(s, "bounding")) || (!strcmp(s, "b"))) + merge = MERGE_BOUNDING; + else if ((!strcmp(s, "full")) || (!strcmp(s, "f"))) + merge = MERGE_FULL; + } + + evas_render_engine_software_generic_merge_mode_set(&re->generic.software, merge); + + if (!initted) + { + gl_extn_veto(re); + initted = EINA_TRUE; + } } else { re = epd->engine.data.output; - if (_re_wincheck(re)) + ob = eng_get_ob(re); + if ((ob) && (_re_wincheck(ob))) { - re->info = inf; - if ((re->info->info.display != re->win->disp) || - (re->info->info.surface != re->win->surface) || - (re->info->info.screen != re->win->screen) || - (re->info->info.depth != re->win->depth) || - (re->info->info.rotation != re->win->rot) || - (re->info->info.destination_alpha != re->win->alpha)) + if ((ob->info->info.display != ob->disp) || + (ob->info->info.surface != ob->surface) || + (ob->info->info.win != ob->win) || + (ob->info->info.depth != ob->depth) || + (ob->info->info.screen != ob->screen) || + (ob->info->info.destination_alpha != ob->alpha)) { - Eina_Bool inc = EINA_FALSE; + ob->gl_context->references++; + gl_wins--; - if (re->win) - { - re->win->gl_context->references++; - eng_window_free(re->win); - inc = EINA_TRUE; - gl_wins--; - } + ob = eng_window_new(inf->info.display, inf->info.surface, + inf->info.screen, inf->info.depth, + epd->output.w, epd->output.h, + inf->indirect, + inf->info.destination_alpha, + inf->info.rotation, swap_mode); + if (!ob) goto ob_err; - re->w = epd->output.w; - re->h = epd->output.h; + eng_window_free(eng_get_ob(re)); + re->generic.software.ob = NULL; + + eng_window_use(ob); - re->win = eng_window_new(re->info->info.display, - re->info->info.surface, - re->info->info.screen, - re->info->info.depth, - epd->output.w, epd->output.h, - re->info->indirect, - re->info->info.destination_alpha, - re->info->info.rotation); - - eng_window_use(re->win); - if (re->win) gl_wins++; - if ((re->win) && (inc)) - re->win->gl_context->references--; + evas_render_engine_software_generic_update(&re->generic.software, ob, + epd->output.w, epd->output.h); + gl_wins++; + eng_get_ob(re)->gl_context->references--; } - else if ((re->win->w != epd->output.w) || - (re->win->h != epd->output.h)) + else if ((ob->w != epd->output.w) || (ob->h != epd->output.h) || + (ob->info->info.rotation != ob->rot)) { - re->w = epd->output.w; - re->h = epd->output.h; - re->win->w = epd->output.w; - re->win->h = epd->output.h; - eng_window_use(re->win); - evas_gl_common_context_resize(re->win->gl_context, - re->win->w, re->win->h, - re->win->rot); + eng_outbuf_reconfigure(ob, epd->output.w, epd->output.h, + ob->info->info.rotation, 0); + if (re->generic.software.tb) + evas_common_tilebuf_free(re->generic.software.tb); + re->generic.software.tb = + evas_common_tilebuf_new(epd->output.w, epd->output.h); + if (re->generic.software.tb) + evas_common_tilebuf_set_tile_size(re->generic.software.tb, + TILESIZE, TILESIZE); } } } - if ((s = getenv("EVAS_GL_SWAP_MODE"))) - { - if ((!strcasecmp(s, "full")) || (!strcasecmp(s, "f"))) - re->mode = MODE_FULL; - else if ((!strcasecmp(s, "copy")) || (!strcasecmp(s, "c"))) - re->mode = MODE_COPY; - else if ((!strcasecmp(s, "double")) || (!strcasecmp(s, "d")) || - (!strcasecmp(s, "2"))) - re->mode = MODE_DOUBLE; - else if ((!strcasecmp(s, "triple")) || (!strcasecmp(s, "t")) || - (!strcasecmp(s, "3"))) - re->mode = MODE_TRIPLE; - } - else - { -// in most gl implementations - egl and glx here that we care about the TEND -// to either swap or copy backbuffer and front buffer, but strictly that is -// not true. technically backbuffer content is totally undefined after a swap -// and thus you MUST re-render all of it, thus MODE_FULL - re->mode = MODE_FULL; -// BUT... reality is that lmost every implementation copies or swaps so -// triple buffer mode can be used as it is a superset of double buffer and -// copy (though using those explicitly is more efficient). so let's play with -// triple buffer mdoe as a default and see. -// re->mode = MODE_TRIPLE; -// XXX: note - the above seems to break on some older intel chipsets and -// drivers. it seems we CANT depend on backbuffer staying around. bugger! - switch (inf->swap_mode) - { - case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_FULL: - re->mode = MODE_FULL; - break; - case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_COPY: - re->mode = MODE_COPY; - break; - case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_DOUBLE: - re->mode = MODE_DOUBLE; - break; - case EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_TRIPLE: - re->mode = MODE_TRIPLE; - break; - default: - break; - } - } - - if (!re->win) - { - free(re); - epd->engine.data.output = NULL; - return 0; - } + if (!eng_get_ob(re)) goto ob_err; if (!epd->engine.data.output) { - if (re->win) + if (eng_get_ob(re)) { - eng_window_free(re->win); + eng_window_free(eng_get_ob(re)); gl_wins--; } - free(re); - epd->engine.data.output = NULL; - return 0; + goto ob_err; } - if (re->tb) evas_common_tilebuf_free(re->tb); - re->tb = evas_common_tilebuf_new(re->win->w, re->win->h); - if (!re->tb) - { - if (re->win) - { - eng_window_free(re->win); - gl_wins--; - } - free(re); - epd->engine.data.output = NULL; - return 0; - } - - evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); - evas_common_tilebuf_tile_strict_set(re->tb, EINA_TRUE); + evas_render_engine_software_generic_tile_strict_set(&re->generic.software, EINA_TRUE); if (!epd->engine.data.context) { - epd->engine.data.context = + epd->engine.data.context = epd->engine.func->context_new(epd->engine.data.output); } - eng_window_use(re->win); - - re->vsync = 0; + eng_window_use(eng_get_ob(re)); return 1; + +ob_err: + free(re); + return 0; } static Eina_Bool @@ -858,13 +740,8 @@ eng_canvas_alpha_get(void *data, void *info EINA_UNUSED) { Render_Engine *re; - if (!(re = (Render_Engine *)data)) - return EINA_FALSE; - - if (re->win) - return re->win->alpha; - else if (re->info) - return re->info->info.destination_alpha; + if ((re = (Render_Engine *)data)) + return re->generic.software.ob->alpha; return EINA_FALSE; } @@ -876,32 +753,20 @@ eng_output_free(void *data) if ((re = (Render_Engine *)data)) { - evas_gl_preload_render_relax(eng_gl_preload_make_current, re); + glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re)); - if (re->win) - { - if (gl_wins == 1) evgl_engine_shutdown(re); + if (gl_wins == 1) glsym_evgl_engine_shutdown(re); - eng_window_free(re->win); - gl_wins--; - } + evas_render_engine_software_generic_clean(&re->generic.software); - evas_common_tilebuf_free(re->tb); - if (re->rects) - evas_common_tilebuf_free_render_rects(re->rects); - if (re->rects_prev[0]) - evas_common_tilebuf_free_render_rects(re->rects_prev[0]); - if (re->rects_prev[1]) - evas_common_tilebuf_free_render_rects(re->rects_prev[1]); - if (re->rects_prev[2]) - evas_common_tilebuf_free_render_rects(re->rects_prev[2]); + gl_wins--; free(re); } - if ((initted) && (!gl_wins)) + if ((initted == EINA_TRUE) && (gl_wins == 0)) { - evas_gl_preload_shutdown(); + glsym_evas_gl_preload_shutdown(); evas_common_image_shutdown(); evas_common_font_shutdown(); initted = EINA_FALSE; @@ -912,427 +777,58 @@ static void eng_output_resize(void *data, int w, int h) { Render_Engine *re; + Outbuf *ob; if (!(re = (Render_Engine *)data)) return; + if (!(ob = eng_get_ob(re))) return; - if (re->win) - { - re->win->w = w; - re->win->h = h; - eng_window_use(re->win); - } + eng_window_use(ob); - if (re->win->win) + if (ob->win) { int aw, ah, dx = 0, dy = 0; - if ((re->win->rot == 90) || (re->win->rot == 270)) - wl_egl_window_get_attached_size(re->win->win, &ah, &aw); + if ((ob->rot == 90) || (ob->rot == 270)) + wl_egl_window_get_attached_size(ob->win, &ah, &aw); else - wl_egl_window_get_attached_size(re->win->win, &aw, &ah); + wl_egl_window_get_attached_size(ob->win, &aw, &ah); - if (re->info->info.edges & 4) // resize from left + if (ob->info->info.edges & 4) // resize from left { - if ((re->win->rot == 90) || (re->win->rot == 270)) + if ((ob->rot == 90) || (ob->rot == 270)) dx = ah - h; else dx = aw - w; } - if (re->info->info.edges & 1) // resize from top + if (ob->info->info.edges & 1) // resize from top { - if ((re->win->rot == 90) || (re->win->rot == 270)) + if ((ob->rot == 90) || (ob->rot == 270)) dy = aw - w; else dy = ah - h; } - if ((re->win->rot == 90) || (re->win->rot == 270)) - wl_egl_window_resize(re->win->win, h, w, dx, dy); + if ((ob->rot == 90) || (ob->rot == 270)) + wl_egl_window_resize(ob->win, h, w, dx, dy); else - wl_egl_window_resize(re->win->win, w, h, dx, dy); + wl_egl_window_resize(ob->win, w, h, dx, dy); + + glsym_evas_gl_common_context_resize(ob->gl_context, w, h, ob->rot); } - if (re->win) - evas_gl_common_context_resize(re->win->gl_context, w, h, re->win->rot); + if (re->generic.software.tb) + evas_common_tilebuf_free(re->generic.software.tb); - evas_common_tilebuf_free(re->tb); - if ((re->tb = evas_common_tilebuf_new(w, h))) + re->generic.software.tb = evas_common_tilebuf_new(w, h); + if (re->generic.software.tb) { - evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE); - evas_common_tilebuf_tile_strict_set(re->tb, EINA_TRUE); + evas_common_tilebuf_set_tile_size(re->generic.software.tb, + TILESIZE, TILESIZE); + evas_common_tilebuf_tile_strict_set(re->generic.software.tb, EINA_TRUE); } } -static void -eng_output_tile_size_set(void *data, int w, int h) -{ - Render_Engine *re; - - 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; - - if (!(re = (Render_Engine *)data)) return; - if (re->win) - { - eng_window_use(re->win); - evas_gl_common_context_resize(re->win->gl_context, - re->win->w, re->win->h, re->win->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; - - 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; - - 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; - Tilebuf_Rect *rect; - Eina_Bool first_rect = EINA_FALSE; - -#define CLEAR_PREV_RECTS(x) \ - do { \ - if (re->rects_prev[x]) \ - evas_common_tilebuf_free_render_rects(re->rects_prev[x]); \ - re->rects_prev[x] = NULL; \ - } while (0) - - if (!(re = (Render_Engine *)data)) return NULL; - - if (re->end) - { - re->end = EINA_FALSE; - return NULL; - } - - if (!re->rects) - { - re->rects = evas_common_tilebuf_get_render_rects(re->tb); - if (re->rects) - { - if (re->info->swap_mode == EVAS_ENGINE_WAYLAND_EGL_SWAP_MODE_AUTO) - { - if (extn_have_buffer_age) - { - EGLint age = 0; - - if (!eglQuerySurface(re->win->egl_disp, - re->win->egl_surface[0], - EGL_BUFFER_AGE_EXT, &age)) - age = 0; - - if (age == 1) re->mode = MODE_COPY; - else if (age == 2) re->mode = MODE_DOUBLE; - else if (age == 3) re->mode = MODE_TRIPLE; - else re->mode = MODE_FULL; - if ((int)age != re->prev_age) re->mode = MODE_FULL; - re->prev_age = age; - } - } - - /* NB: Disabled this OR for now as it causes some very strange things in the GLView/Simple tests */ - if ((re->lost_back))// || (re->mode == MODE_FULL)) - { - re->lost_back = EINA_FALSE; - evas_common_tilebuf_add_redraw(re->tb, 0, 0, - re->win->w, re->win->h); - evas_common_tilebuf_free_render_rects(re->rects); - re->rects = evas_common_tilebuf_get_render_rects(re->tb); - } - - evas_common_tilebuf_clear(re->tb); - CLEAR_PREV_RECTS(2); - re->rects_prev[2] = re->rects_prev[1]; - re->rects_prev[1] = re->rects_prev[0]; - re->rects_prev[0] = re->rects; - re->rects = NULL; - switch (re->mode) - { - case MODE_FULL: - case MODE_COPY: // no prev rects needed - re->rects = - _merge_rects(re->tb, re->rects_prev[0], NULL, NULL); - break; - case MODE_DOUBLE: // double mode - only 1 level of prev rect - re->rects = - _merge_rects(re->tb, re->rects_prev[0], - re->rects_prev[1], NULL); - break; - case MODE_TRIPLE: // keep all - re->rects = - _merge_rects(re->tb, re->rects_prev[0], - re->rects_prev[1], re->rects_prev[2]); - break; - default: - break; - } - first_rect = EINA_TRUE; - } - evas_common_tilebuf_clear(re->tb); - re->cur_rect = EINA_INLIST_GET(re->rects); - } - - if (!re->cur_rect) return NULL; - - rect = (Tilebuf_Rect *)re->cur_rect; - if (re->rects) - { - switch (re->mode) - { - case MODE_COPY: - case MODE_DOUBLE: - case MODE_TRIPLE: - rect = (Tilebuf_Rect *)re->cur_rect; - *x = rect->x; - *y = rect->y; - *w = rect->w; - *h = rect->h; - *cx = rect->x; - *cy = rect->y; - *cw = rect->w; - *ch = rect->h; - re->cur_rect = re->cur_rect->next; - re->win->gl_context->master_clip.enabled = EINA_TRUE; - re->win->gl_context->master_clip.x = rect->x; - re->win->gl_context->master_clip.y = rect->y; - re->win->gl_context->master_clip.w = rect->w; - re->win->gl_context->master_clip.h = rect->h; - break; - case MODE_FULL: - re->cur_rect = NULL; - if (x) *x = 0; - if (y) *y = 0; - if (w) *w = re->win->w; - if (h) *h = re->win->h; - if (cx) *cx = 0; - if (cy) *cy = 0; - if (cw) *cw = re->win->w; - if (ch) *ch = re->win->h; - re->win->gl_context->master_clip.enabled = EINA_FALSE; - break; - default: - break; - } - - if (first_rect) - { - evas_gl_preload_render_lock(eng_gl_preload_make_current, re); - - eng_window_use(re->win); - if (!_re_wincheck(re)) return NULL; - - evas_gl_common_context_flush(re->win->gl_context); - evas_gl_common_context_newframe(re->win->gl_context); - } - - if (!re->cur_rect) re->end = EINA_TRUE; - - return re->win->gl_context->def_surface; - } - - return NULL; -} - -static void -eng_output_redraws_next_update_push(void *data, void *surface EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED, Evas_Render_Mode render_mode) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - - if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; - - if (!_re_wincheck(re)) return; - - re->win->draw.drew = EINA_TRUE; - if (re->win->gl_context) - evas_gl_common_context_flush(re->win->gl_context); - - if (safe_native == -1) - { - const char *s; - - safe_native = 0; - if ((s = getenv("EVAS_GL_SAFE_NATIVE"))) - safe_native = atoi(s); - else - { - if ((s = (const char *)glGetString(GL_RENDERER))) - { - if (strstr(s, "PowerVR SGX 540") || strstr(s, "Mali-400 MP")) - safe_native = 1; - } - } - } -} - -static void -eng_output_flush(void *data, Evas_Render_Mode render_mode) -{ - Render_Engine *re; - static char *dname = NULL; - - if (!(re = (Render_Engine *)data)) return; - - if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end; - - if (!_re_wincheck(re)) goto end; - - if (!re->win->draw.drew) goto end; - re->win->draw.drew = EINA_FALSE; - eng_window_use(re->win); - - evas_gl_common_context_done(re->win->gl_context); - - // Save contents of the framebuffer to a file - if (swap_buffer_debug_mode == -1) - { - if ((dname = getenv("EVAS_GL_SWAP_BUFFER_DEBUG_DIR"))) - { - int stat; - // Create a directory with 0775 permission - stat = mkdir(dname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); - if ((!stat) || errno == EEXIST) swap_buffer_debug_mode = 1; - } - else - swap_buffer_debug_mode = 0; - } - - if (swap_buffer_debug_mode == 1) - { - // Set this env var to dump files every frame - // Or set the global var in gdb to 1|0 to turn it on and off - if (getenv("EVAS_GL_SWAP_BUFFER_DEBUG_ALWAYS")) - swap_buffer_debug = 1; - - if (swap_buffer_debug) - { - char fname[100]; - int ret = 0; - sprintf(fname, "%p", (void*)re->win); - - ret = evas_gl_common_buffer_dump(re->win->gl_context, - (const char*)dname, - (const char*)fname, - re->frame_cnt, - NULL); - if (!ret) swap_buffer_debug_mode = 0; - } - } - - if (!re->vsync) - { - if (re->info->vsync) eglSwapInterval(re->win->egl_disp, 1); - else eglSwapInterval(re->win->egl_disp, 0); - re->vsync = 1; - } - - if (re->info->callback.pre_swap) - re->info->callback.pre_swap(re->info->callback.data, re->evas); - - if ((glsym_eglSwapBuffersWithDamage) && (re->mode != MODE_FULL)) - { - EGLint num = 0, *rects = NULL, i = 0; - Tilebuf_Rect *r; - - // if partial swaps can be done use re->rects - EINA_INLIST_FOREACH(EINA_INLIST_GET(re->rects), r) num++; - if (num > 0) - { - rects = alloca(sizeof(EGLint) * 4 * num); - EINA_INLIST_FOREACH(EINA_INLIST_GET(re->rects), r) - { - int gw, gh; - - gw = re->win->gl_context->w; - gh = re->win->gl_context->h; - switch (re->win->rot) - { - case 0: - rects[i + 0] = r->x; - rects[i + 1] = gh - (r->y + r->h); - rects[i + 2] = r->w; - rects[i + 3] = r->h; - break; - case 90: - rects[i + 0] = r->y; - rects[i + 1] = r->x; - rects[i + 2] = r->h; - rects[i + 3] = r->w; - break; - case 180: - rects[i + 0] = gw - (r->x + r->w); - rects[i + 1] = r->y; - rects[i + 2] = r->w; - rects[i + 3] = r->h; - break; - case 270: - rects[i + 0] = gh - (r->y + r->h); - rects[i + 1] = gw - (r->x + r->w); - rects[i + 2] = r->h; - rects[i + 3] = r->w; - break; - default: - rects[i + 0] = r->x; - rects[i + 1] = gh - (r->y + r->h); - rects[i + 2] = r->w; - rects[i + 3] = r->h; - break; - } - i += 4; - } - glsym_eglSwapBuffersWithDamage(re->win->egl_disp, - re->win->egl_surface[0], - rects, num); - } - } - else - eglSwapBuffers(re->win->egl_disp, re->win->egl_surface[0]); - - if (re->info->callback.post_swap) - re->info->callback.post_swap(re->info->callback.data, re->evas); - - if (re->rects) - { - evas_common_tilebuf_free_render_rects(re->rects); - re->rects = NULL; - } - - re->frame_cnt++; - -end: - evas_gl_preload_render_unlock(eng_gl_preload_make_current, re); -} - -static void -eng_output_idle_flush(void *data EINA_UNUSED) -{ - -} - static void eng_output_dump(void *data) { @@ -1342,1266 +838,202 @@ eng_output_dump(void *data) evas_common_image_image_all_unload(); evas_common_font_font_all_unload(); - if (re->win) evas_gl_common_image_all_unload(re->win->gl_context); + glsym_evas_gl_common_image_all_unload(eng_get_ob(re)->gl_context); _re_winfree(re); } static void -eng_context_cutout_add(void *data EINA_UNUSED, void *context, int x, int y, int w, int h) +_native_cb_bind(void *data EINA_UNUSED, void *image) { - evas_common_draw_context_add_cutout(context, x, y, w, h); -} - -static void -eng_context_cutout_clear(void *data EINA_UNUSED, void *context) -{ - evas_common_draw_context_clear_cutouts(context); -} - -static void -eng_context_flush(void *data) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - if (re->win) - { - eng_window_use(re->win); - evas_gl_common_context_flush(re->win->gl_context); - } -} - -static void * -eng_gl_surface_create(void *data, void *config, int w, int h) -{ - Evas_GL_Config *cfg; - - cfg = (Evas_GL_Config *)config; - EVGLINIT(data, NULL); - return evgl_surface_create(data, cfg, w, h); -} - -static int -eng_gl_surface_destroy(void *data, void *surface) -{ - EVGL_Surface *sfc; - - sfc = (EVGL_Surface *)surface; - EVGLINIT(data, 0); - return evgl_surface_destroy(data, sfc); -} - -static void * -eng_gl_context_create(void *data, void *share_context) -{ - EVGL_Context *sctx; - - sctx = (EVGL_Context *)share_context; - EVGLINIT(data, NULL); - return evgl_context_create(data, sctx); -} - -static int -eng_gl_context_destroy(void *data, void *context) -{ - EVGL_Context *sctx; - - sctx = (EVGL_Context *)context; - EVGLINIT(data, 0); - return evgl_context_destroy(data, sctx); -} - -static int -eng_gl_make_current(void *data, void *surface, void *context) -{ - EVGL_Surface *sfc; - EVGL_Context *ctx; - - sfc = (EVGL_Surface *)surface; - ctx = (EVGL_Context *)context; - EVGLINIT(data, 0); - return evgl_make_current(data, sfc, ctx); -} - -static void * -eng_gl_string_query(void *data, int name) -{ - EVGLINIT(data, NULL); - return (void *)evgl_string_query(name); -} - -// Need to deprecate this function.. -static void * -eng_gl_proc_address_get(void *data EINA_UNUSED, const char *name EINA_UNUSED) -{ - return NULL; -} - -static int -eng_gl_native_surface_get(void *data EINA_UNUSED, void *surface, void *native_surface) -{ - EVGL_Surface *sfc; - Evas_Native_Surface *ns; - - sfc = (EVGL_Surface *)surface; - ns = (Evas_Native_Surface *)native_surface; - return evgl_native_surface_get(sfc, ns); -} - -static void * -eng_gl_api_get(void *data) -{ - EVGLINIT(data, NULL); - return evgl_api_get(); -} - -static void -eng_gl_direct_override_get(void *data, int *override, int *force_off) -{ - EVGLINIT(data, ); - evgl_direct_override_get(override, force_off); -} - -static void -eng_gl_get_pixels_set(void *data, void *get_pixels, void *get_pixels_data, void *obj) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - - EVGLINIT(data, ); - re->func.pixels_get = get_pixels; - re->func.pixels_data_get = get_pixels_data; - re->func.obj = (Evas_Object*)obj; -} - -static Eina_Bool -eng_gl_preload_make_current(void *data, void *doit) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) - return EINA_FALSE; - - if (doit) - { - if (!eglMakeCurrent(re->win->egl_disp, re->win->egl_surface[0], - re->win->egl_surface[0], re->win->egl_context[0])) - return EINA_FALSE; - } - else - { - if (!eglMakeCurrent(re->win->egl_disp, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT)) - return EINA_FALSE; - } - - return EINA_TRUE; -} - -static void -eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - eng_window_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_rect_draw(re->win->gl_context, x, y, w, h); -} - -static void -eng_line_draw(void *data, void *context, void *surface, int p1x, int p1y, int p2x, int p2y, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - eng_window_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_line_draw(re->win->gl_context, p1x, p1y, p2x, p2y); -} - -static Eina_Bool -eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font EINA_UNUSED, int x, int y, int w EINA_UNUSED, int h EINA_UNUSED, int ow EINA_UNUSED, int oh EINA_UNUSED, Evas_Text_Props *intl_props, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - static RGBA_Image *im = NULL; - - if (!(re = (Render_Engine *)data)) return EINA_FALSE; - eng_window_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - - // FIXME: put im into context so we can free it - - if (!im) - im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get()); - - im->cache_entry.w = re->win->gl_context->shared->w; - im->cache_entry.h = re->win->gl_context->shared->h; - - evas_common_draw_context_font_ext_set(context, re->win->gl_context, - evas_gl_font_texture_new, - evas_gl_font_texture_free, - evas_gl_font_texture_draw); - evas_common_font_draw_prepare(intl_props); - evas_common_font_draw(im, context, x, y, intl_props->glyphs); - evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL); - - return EINA_FALSE; -} - -static void -eng_polygon_draw(void *data, void *context, void *surface EINA_UNUSED, void *polygon, int x, int y, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - eng_window_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_poly_draw(re->win->gl_context, polygon, x, y); -} - -static void * -eng_polygon_point_add(void *data EINA_UNUSED, void *context EINA_UNUSED, void *polygon, int x, int y) -{ - return evas_gl_common_poly_point_add(polygon, x, y); -} - -static void * -eng_polygon_points_clear(void *data EINA_UNUSED, void *context EINA_UNUSED, void *polygon) -{ - return evas_gl_common_poly_points_clear(polygon); -} - -static void * -eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - *error = EVAS_LOAD_ERROR_NONE; - eng_window_use(re->win); - return evas_gl_common_image_load(re->win->gl_context, file, key, lo, error); -} - -static void * -eng_image_mmap(void *data, Eina_File *f, const char *key, int *error, Evas_Image_Load_Opts *lo) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - *error = EVAS_LOAD_ERROR_NONE; - eng_window_use(re->win); - return evas_gl_common_image_mmap(re->win->gl_context, f, key, lo, error); -} - -static void * -eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - eng_window_use(re->win); - return evas_gl_common_image_new_from_data(re->win->gl_context, w, h, image_data, alpha, cspace); -} - -static void * -eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, Evas_Colorspace cspace) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - eng_window_use(re->win); - return evas_gl_common_image_new_from_copied_data(re->win->gl_context, w, h, image_data, alpha, cspace); -} - -static void -eng_image_free(void *data, void *image) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - if (!image) return; - eng_window_use(re->win); - evas_gl_common_image_free(image); -} - -static void -eng_image_size_get(void *data EINA_UNUSED, void *image, int *w, int *h) -{ - if (!image) - { - *w = 0; - *h = 0; - return; - } - if (w) *w = ((Evas_GL_Image *)image)->w; - if (h) *h = ((Evas_GL_Image *)image)->h; -} - -static void * -eng_image_size_set(void *data, void *image, int w, int h) -{ - Render_Engine *re; - Evas_GL_Image *im, *im_old; - - if (!(re = (Render_Engine *)data)) return NULL; - if (!(im = image)) return NULL; - - if (im->native.data) - { - im->w = w; - im->h = h; - return image; - } - eng_window_use(re->win); - if ((im->tex) && (im->tex->pt->dyn.img)) - { - evas_gl_common_texture_free(im->tex, EINA_TRUE); - im->tex = NULL; - im->w = w; - im->h = h; - im->tex = evas_gl_common_texture_dynamic_new(im->gc, im); - return image; - } - im_old = image; - - switch (eng_image_colorspace_get(data, image)) - { - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - case EVAS_COLORSPACE_YCBCR422601_PL: - case EVAS_COLORSPACE_YCBCR420NV12601_PL: - case EVAS_COLORSPACE_YCBCR420TM12601_PL: - w &= ~0x1; - break; - default: - break; - } - - evas_gl_common_image_alloc_ensure(im); - if ((im_old->im) && - ((int)im_old->im->cache_entry.w == w) && - ((int)im_old->im->cache_entry.h == h)) - return image; - - if (im_old) - { - im = evas_gl_common_image_new(re->win->gl_context, w, h, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - evas_gl_common_image_free(im_old); - } - else - im = evas_gl_common_image_new(re->win->gl_context, w, h, - 1, EVAS_COLORSPACE_ARGB8888); - return im; -} - -static void * -eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h) -{ - Render_Engine *re; - Evas_GL_Image *im; - - if (!(re = (Render_Engine *)data)) return NULL; - if (!(im = image)) return NULL; - if (im->native.data) return image; - eng_window_use(re->win); - evas_gl_common_image_dirty(image, x, y, w, h); - return image; -} - -static void * -eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, int *err) -{ - Render_Engine *re; - Evas_GL_Image *im; - int error; - - if (!(re = (Render_Engine *)data)) return NULL; - if (!image) - { - *image_data = NULL; - if (err) *err = EVAS_LOAD_ERROR_GENERIC; - return NULL; - } - im = image; - if (im->native.data) - { - *image_data = NULL; - if (err) *err = EVAS_LOAD_ERROR_NONE; - return im; - } - -#ifdef GL_GLES - eng_window_use(re->win); - - if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.img) && - (im->cs.space == EVAS_COLORSPACE_ARGB8888)) - { - if (im->tex->pt->dyn.checked_out > 0) - { - im->tex->pt->dyn.checked_out++; - *image_data = im->tex->pt->dyn.data; - if (err) *err = EVAS_LOAD_ERROR_NONE; - return im; - } - *image_data = im->tex->pt->dyn.data = - glsym_eglMapImageSEC(re->win->egl_disp, - im->tex->pt->dyn.img, - EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC, - EGL_MAP_GL_TEXTURE_OPTION_WRITE_SEC); - - if (!im->tex->pt->dyn.data) - { - if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - return im; - } - im->tex->pt->dyn.checked_out++; - - if (err) *err = EVAS_LOAD_ERROR_NONE; - return im; - } -#endif - - /* Engine can be fail to create texture after cache drop like eng_image_content_hint_set function, - so it is need to add code which check im->im's NULL value*/ - - if (!im->im) - { - *image_data = NULL; - if (err) *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - return NULL; - } - - error = evas_cache_image_load_data(&im->im->cache_entry); - evas_gl_common_image_alloc_ensure(im); - switch (im->cs.space) - { - case EVAS_COLORSPACE_ARGB8888: - if (to_write) - { - if (im->references > 1) - { - Evas_GL_Image *im_new; - - im_new = evas_gl_common_image_new_from_copied_data - (im->gc, im->im->cache_entry.w, im->im->cache_entry.h, - im->im->image.data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im_new) - { - *image_data = NULL; - if (err) - *err = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - return NULL; - } - evas_gl_common_image_free(im); - im = im_new; - } - else - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - } - *image_data = im->im->image.data; - break; - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - case EVAS_COLORSPACE_YCBCR422601_PL: - case EVAS_COLORSPACE_YCBCR420NV12601_PL: - case EVAS_COLORSPACE_YCBCR420TM12601_PL: - *image_data = im->cs.data; - break; - default: - abort(); - break; - } - if (err) *err = error; - return im; -} - -static void * -eng_image_data_put(void *data, void *image, DATA32 *image_data) -{ - Render_Engine *re; - Evas_GL_Image *im, *im2; - - if (!(re = (Render_Engine *)data)) return NULL; - if (!(im = image)) return NULL; - if (im->native.data) return image; - eng_window_use(re->win); - evas_gl_common_image_alloc_ensure(im); - if ((im->tex) && (im->tex->pt) - && (im->tex->pt->dyn.data) - && (im->cs.space == EVAS_COLORSPACE_ARGB8888)) - { - if (im->tex->pt->dyn.data == image_data) - { - if (im->tex->pt->dyn.checked_out > 0) - { - im->tex->pt->dyn.checked_out--; -#ifdef GL_GLES - if (im->tex->pt->dyn.checked_out == 0) - glsym_eglUnmapImageSEC(re->win->egl_disp, - im->tex->pt->dyn.img, - EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC); -#endif - } - - return image; - } - im2 = eng_image_new_from_data(data, im->w, im->h, image_data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im2) return im; - evas_gl_common_image_free(im); - im = im2; - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - return im; - } - switch (im->cs.space) - { - case EVAS_COLORSPACE_ARGB8888: - if ((!im->im) || (image_data != im->im->image.data)) - { - im2 = eng_image_new_from_data(data, im->w, im->h, image_data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im2) return im; - evas_gl_common_image_free(im); - im = im2; - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - } - break; - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - case EVAS_COLORSPACE_YCBCR422601_PL: - case EVAS_COLORSPACE_YCBCR420NV12601_PL: - case EVAS_COLORSPACE_YCBCR420TM12601_PL: - if (image_data != im->cs.data) - { - if (im->cs.data) - { - if (!im->cs.no_free) free(im->cs.data); - } - im->cs.data = image_data; - } - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - break; - default: - abort(); - break; - } - return im; -} - -static void -eng_image_data_preload_request(void *data, void *image, const Eo *target) -{ - Evas_GL_Image *gim; - RGBA_Image *im; - Render_Engine *re; - - if (!(gim = image)) return; - if (gim->native.data) return; - im = (RGBA_Image *)gim->im; - if (!im) return; - evas_cache_image_preload_data(&im->cache_entry, target, NULL, NULL, NULL); - if (!(re = (Render_Engine *)data)) return; - if (!gim->tex) - gim->tex = evas_gl_common_texture_new(re->win->gl_context, gim->im); - evas_gl_preload_target_register(gim->tex, (Eo *)target); -} - -static void -eng_image_data_preload_cancel(void *data EINA_UNUSED, void *image, const Eo *target) -{ - Evas_GL_Image *gim; - RGBA_Image *im; - - if (!(gim = image)) return; - if (gim->native.data) return; - im = (RGBA_Image *)gim->im; - if (!im) return; - evas_cache_image_preload_cancel(&im->cache_entry, target); - evas_gl_preload_target_unregister(gim->tex, (Eo *)target); -} - -static void * -eng_image_alpha_set(void *data, void *image, int has_alpha) -{ - Render_Engine *re; - Evas_GL_Image *im; - - if (!(re = (Render_Engine *)data)) return NULL; - if (!(im = image)) return NULL; - if (im->alpha == has_alpha) return image; - if (im->native.data) - { - im->alpha = has_alpha; - return image; - } - eng_window_use(re->win); - if ((im->tex) && (im->tex->pt->dyn.img)) - { - im->alpha = has_alpha; - im->tex->alpha = im->alpha; - return image; - } - /* FIXME: can move to gl_common */ - if (im->cs.space != EVAS_COLORSPACE_ARGB8888) return im; - if ((has_alpha) && (im->im->cache_entry.flags.alpha)) return image; - else if ((!has_alpha) && (!im->im->cache_entry.flags.alpha)) return image; - if (im->references > 1) - { - Evas_GL_Image *im_new; - - if (!im->im->image.data) - evas_cache_image_load_data(&im->im->cache_entry); - evas_gl_common_image_alloc_ensure(im); - im_new = evas_gl_common_image_new_from_copied_data - (im->gc, im->im->cache_entry.w, im->im->cache_entry.h, - im->im->image.data, - eng_image_alpha_get(data, image), - eng_image_colorspace_get(data, image)); - if (!im_new) return im; - evas_gl_common_image_free(im); - im = im_new; - } - else - evas_gl_common_image_dirty(im, 0, 0, 0, 0); - return evas_gl_common_image_alpha_set(im, has_alpha ? 1 : 0); -// im->im->cache_entry.flags.alpha = has_alpha ? 1 : 0; -// return image; -} - -static int -eng_image_alpha_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; - - if (!(im = image)) return 1; - return im->alpha; -} - -static void * -eng_image_border_set(void *data EINA_UNUSED, void *image, int l EINA_UNUSED, int r EINA_UNUSED, int t EINA_UNUSED, int b EINA_UNUSED) -{ - return image; -} - -static void -eng_image_border_get(void *data EINA_UNUSED, void *image EINA_UNUSED, int *l EINA_UNUSED, int *r EINA_UNUSED, int *t EINA_UNUSED, int *b EINA_UNUSED) -{ -} - -static Eina_Bool -eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth, Eina_Bool do_async EINA_UNUSED) -{ - Render_Engine *re; - Evas_GL_Image *im; + Evas_GL_Image *img; Native *n; - if (!(re = (Render_Engine *)data)) return EINA_FALSE; - if (!(im = image)) return EINA_FALSE; - n = im->native.data; + if (!(img = image)) return; + if (!(n = img->native.data)) return; - if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) && - (n->ns.data.opengl.framebuffer_id == 0) && - (re->func.pixels_get)) + if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) { - DBG("Rendering Directly to the window: %p", data); - - re->win->gl_context->dc = context; - - // Set necessary info for direct rendering - evgl_direct_info_set(re->win->gl_context->w, - re->win->gl_context->h, - re->win->gl_context->rot, - dst_x, dst_y, dst_w, dst_h, - re->win->gl_context->dc->clip.x, - re->win->gl_context->dc->clip.y, - re->win->gl_context->dc->clip.w, - re->win->gl_context->dc->clip.h); - - // Call pixel get function - re->func.pixels_get(re->func.pixels_data_get, re->func.obj); - - // Clear direct rendering info - evgl_direct_info_clear(); + glBindTexture(GL_TEXTURE_2D, n->ns.data.opengl.texture_id); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); } - else +} + +static void +_native_cb_unbind(void *data EINA_UNUSED, void *image) +{ + Evas_GL_Image *img; + Native *n; + + if (!(img = image)) return; + if (!(n = img->native.data)) return; + + if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) { - eng_window_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - evas_gl_common_image_draw(re->win->gl_context, image, - src_x, src_y, src_w, src_h, - dst_x, dst_y, dst_w, dst_h, - smooth); + glBindTexture(GL_TEXTURE_2D, 0); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); } - - return EINA_FALSE; } -static char * -eng_image_comment_get(void *data EINA_UNUSED, void *image, char *key EINA_UNUSED) -{ - Evas_GL_Image *im; - - if (!(im = image)) return NULL; - if (!im->im) return NULL; - return im->im->info.comment; -} - -static char * -eng_image_format_get(void *data EINA_UNUSED, void *image EINA_UNUSED) -{ - return NULL; -} - -static void -eng_image_colorspace_set(void *data, void *image, Evas_Colorspace cspace) +static void +_native_cb_free(void *data, void *image) { Render_Engine *re; - Evas_GL_Image *im; + Outbuf *ob; + Evas_GL_Image *img; + Native *n; + uint32_t texid; if (!(re = (Render_Engine *)data)) return; - if (!(im = image)) return; - if (im->native.data) return; - /* FIXME: can move to gl_common */ - if (im->cs.space == cspace) return; - eng_window_use(re->win); - evas_gl_common_image_alloc_ensure(im); - evas_cache_image_colorspace(&im->im->cache_entry, cspace); - switch (cspace) + if (!(img = image)) return; + if (!(n = img->native.data)) return; + if (!(ob = eng_get_ob(re))) return; + + if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) { - case EVAS_COLORSPACE_ARGB8888: - if (im->cs.data) - { - if (!im->cs.no_free) free(im->cs.data); - im->cs.data = NULL; - im->cs.no_free = 0; - } - break; - case EVAS_COLORSPACE_YCBCR422P601_PL: - case EVAS_COLORSPACE_YCBCR422P709_PL: - case EVAS_COLORSPACE_YCBCR422601_PL: - case EVAS_COLORSPACE_YCBCR420NV12601_PL: - case EVAS_COLORSPACE_YCBCR420TM12601_PL: - if (im->tex) evas_gl_common_texture_free(im->tex, EINA_TRUE); - im->tex = NULL; - if (im->cs.data) - { - if (!im->cs.no_free) free(im->cs.data); - } - if (im->im->cache_entry.h > 0) - im->cs.data = - calloc(1, im->im->cache_entry.h * sizeof(unsigned char *) * 2); - else - im->cs.data = NULL; - im->cs.no_free = 0; - break; - default: - abort(); - break; + texid = n->ns.data.opengl.texture_id; + eina_hash_del(ob->gl_context->shared->native_tex_hash, &texid, img); } - im->cs.space = cspace; -} -static Evas_Colorspace -eng_image_colorspace_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; + img->native.data = NULL; + img->native.func.data = NULL; + img->native.func.bind = NULL; + img->native.func.unbind = NULL; + img->native.func.free = NULL; - if (!(im = image)) return EVAS_COLORSPACE_ARGB8888; - return im->cs.space; -} - -static Eina_Bool -eng_image_can_region_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim; - Image_Entry *im; - - if (!(gim = image)) return EINA_FALSE; - if (!(im = (Image_Entry *)gim->im)) return EINA_FALSE; - return ((Evas_Image_Load_Func*) im->info.loader)->do_region; + free(n); } static void * eng_image_native_set(void *data, void *image, void *native) { Render_Engine *re; + Outbuf *ob; + Native *n; Evas_Native_Surface *ns; - Evas_GL_Image *im, *im2 = NULL; - Native *n = NULL; - unsigned int texid; - unsigned int tex = 0; - unsigned int fbo = 0; + Evas_GL_Image *img, *img2; + unsigned int tex = 0, fbo = 0; + uint32_t texid; if (!(re = (Render_Engine *)data)) return NULL; + if (!(ob = eng_get_ob(re))) return NULL; ns = native; - im = image; - if (!im) + + if (!(img = image)) { if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_OPENGL)) { - im = evas_gl_common_image_new_from_data(re->win->gl_context, - ns->data.opengl.w, - ns->data.opengl.h, - NULL, 1, - EVAS_COLORSPACE_ARGB8888); + img = + glsym_evas_gl_common_image_new_from_data(ob->gl_context, + ns->data.opengl.w, + ns->data.opengl.h, + NULL, 1, + EVAS_COLORSPACE_ARGB8888); } else return NULL; } - if (ns) + if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_OPENGL)) { - if (ns->type == EVAS_NATIVE_SURFACE_OPENGL) + tex = ns->data.opengl.texture_id; + fbo = ns->data.opengl.framebuffer_id; + if (img->native.data) { - tex = ns->data.opengl.texture_id; - fbo = ns->data.opengl.framebuffer_id; - if (im->native.data) - { - Evas_Native_Surface *ens; + Evas_Native_Surface *ens; - ens = im->native.data; - if ((ens->data.opengl.texture_id == tex) && - (ens->data.opengl.framebuffer_id == fbo)) - return im; - } + ens = img->native.data; + if ((ens->data.opengl.texture_id == tex) && + (ens->data.opengl.framebuffer_id == fbo)) + return img; } } - if ((!ns) && (!im->native.data)) return im; + if ((!ns) && (!img->native.data)) return img; - eng_window_use(re->win); + eng_window_use(ob); - if (im->native.data) + if (img->native.data) { - if (im->native.func.free) - im->native.func.free(im->native.func.data, im); - evas_gl_common_image_native_disable(im); + if (img->native.func.free) + img->native.func.free(img->native.func.data, img); + glsym_evas_gl_common_image_native_disable(img); } - if (!ns) return im; + if (!ns) return img; if (ns->type == EVAS_NATIVE_SURFACE_OPENGL) { texid = tex; - im2 = eina_hash_find(re->win->gl_context->shared->native_tex_hash, &texid); - if (im2 == im) return im; - if (im2) - { - n = im2->native.data; - if (n) + img2 = eina_hash_find(ob->gl_context->shared->native_tex_hash, &texid); + if (img2 == img) return img; + if (img2) + { + if ((n = img2->native.data)) { - evas_gl_common_image_ref(im2); - evas_gl_common_image_free(im); - return im2; + glsym_evas_gl_common_image_ref(img2); + glsym_evas_gl_common_image_free(img); + return img2; } } } - im2 = evas_gl_common_image_new_from_data(re->win->gl_context, - im->w, im->h, NULL, im->alpha, - EVAS_COLORSPACE_ARGB8888); - evas_gl_common_image_free(im); - if (!(im = im2)) return NULL; + img2 = glsym_evas_gl_common_image_new_from_data(ob->gl_context, img->w, + img->h, NULL, img->alpha, + EVAS_COLORSPACE_ARGB8888); + glsym_evas_gl_common_image_free(img); + + if (!(img = img2)) return NULL; if (ns->type == EVAS_NATIVE_SURFACE_OPENGL) { if (native) { - n = calloc(1, sizeof(Native)); - if (n) + if ((n = calloc(1, sizeof(Native)))) { memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface)); - - eina_hash_add(re->win->gl_context->shared->native_tex_hash, - &texid, im); + eina_hash_add(ob->gl_context->shared->native_tex_hash, &texid, img); n->egl_surface = 0; - im->native.yinvert = 0; - im->native.loose = 0; - im->native.data = n; - im->native.func.data = re; - im->native.func.bind = _native_bind_cb; - im->native.func.unbind = _native_unbind_cb; - im->native.func.free = _native_free_cb; - im->native.target = GL_TEXTURE_2D; - im->native.mipmap = 0; - // FIXME: need to implement mapping sub texture regions - // x, y, w, h for possible texture atlasing + img->native.yinvert = 0; + img->native.loose = 0; + img->native.data = n; + img->native.func.data = re; + img->native.func.bind = _native_cb_bind; + img->native.func.unbind = _native_cb_unbind; + img->native.func.free = _native_cb_free; + img->native.target = GL_TEXTURE_2D; + img->native.mipmap = 0; - evas_gl_common_image_native_enable(im); + glsym_evas_gl_common_image_native_enable(img); } } - } + } - return im; + return img; } -static void * -eng_image_native_get(void *data EINA_UNUSED, void *image) +Eina_Bool +eng_preload_make_current(void *data, void *doit) { - Evas_GL_Image *im; - Native *n; + Outbuf *ob; - if (!(im = image)) return NULL; - if (!(n = im->native.data)) return NULL; - return &(n->ns); -} + if (!(ob = data)) return EINA_FALSE; -static void -eng_image_scale_hint_set(void *data EINA_UNUSED, void *image, int hint) -{ - if (image) evas_gl_common_image_scale_hint_set(image, hint); -} - -static int -eng_image_scale_hint_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim; - - if (!(gim = image)) return EVAS_IMAGE_SCALE_HINT_NONE; - return gim->scale_hint; -} - -static void -eng_image_stride_get(void *data EINA_UNUSED, void *image, int *stride) -{ - Evas_GL_Image *im; - - if (!(im = image)) return; - if ((im->tex) && (im->tex->pt->dyn.img)) + if (doit) { - if (stride) *stride = im->tex->pt->dyn.stride; + if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0], + ob->egl_surface[0], ob->egl_context[0])) + return EINA_FALSE; } else { - if (stride) *stride = im->w * 4; - } -} - -static void -eng_image_content_hint_set(void *data, void *image, int hint) -{ - Render_Engine *re; - re = (Render_Engine *)data; - - if (re) eng_window_use(re->win); - if (image) evas_gl_common_image_content_hint_set(image, hint); -} - -static int -eng_image_content_hint_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim; - - if (!(gim = image)) return EVAS_IMAGE_CONTENT_HINT_NONE; - return gim->content_hint; -} - -static void -eng_image_cache_flush(void *data) -{ - Render_Engine *re; - int tmp_size; - - re = (Render_Engine *)data; - - if (re) eng_window_use(re->win); - - tmp_size = evas_common_image_get_cache(); - evas_common_image_set_cache(0); - evas_common_rgba_image_scalecache_flush(); - evas_gl_common_image_cache_flush(re->win->gl_context); -// if ((re = (Render_Engine *)data)) -// evas_gl_common_image_cache_flush(re->win->gl_context); - evas_common_image_set_cache(tmp_size); -} - -static void -eng_image_cache_set(void *data, int bytes) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - - if (re) eng_window_use(re->win); - - evas_common_image_set_cache(bytes); - evas_common_rgba_image_scalecache_size_set(bytes); - evas_gl_common_image_cache_flush(re->win->gl_context); -// if (!(re = (Render_Engine *)data)) return; -// if (re->win) evas_gl_common_image_cache_flush(re->win->gl_context); -} - -static int -eng_image_cache_get(void *data EINA_UNUSED) -{ - return evas_common_image_get_cache(); -} - -static int -eng_image_load_error_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *im; - - if (!(im = image)) return EVAS_LOAD_ERROR_NONE; - return im->im->cache_entry.load_error; -} - -static void -eng_image_max_size_get(void *data, int *maxw, int *maxh) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return; - if (maxw) *maxw = re->win->gl_context->shared->info.max_texture_size; - if (maxh) *maxh = re->win->gl_context->shared->info.max_texture_size; -} - -static Eina_Bool -eng_image_map_draw(void *data, void *context, void *surface, void *image, RGBA_Map *m, int smooth, int level, Eina_Bool do_async) -{ - Evas_GL_Image *gim; - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return EINA_FALSE; - if (!(gim = image)) return EINA_FALSE; - eng_window_use(re->win); - evas_gl_common_context_target_surface_set(re->win->gl_context, surface); - re->win->gl_context->dc = context; - if (m->count != 4) - { - // FIXME: nash - you didn't fix this - abort(); - } - if ((m->pts[0].x == m->pts[3].x) && - (m->pts[1].x == m->pts[2].x) && - (m->pts[0].y == m->pts[1].y) && - (m->pts[3].y == m->pts[2].y) && - (m->pts[0].x <= m->pts[1].x) && - (m->pts[0].y <= m->pts[2].y) && - (m->pts[0].u == 0) && - (m->pts[0].v == 0) && - (m->pts[1].u == (gim->w << FP)) && - (m->pts[1].v == 0) && - (m->pts[2].u == (gim->w << FP)) && - (m->pts[2].v == (gim->h << FP)) && - (m->pts[3].u == 0) && - (m->pts[3].v == (gim->h << FP)) && - (m->pts[0].col == 0xffffffff) && - (m->pts[1].col == 0xffffffff) && - (m->pts[2].col == 0xffffffff) && - (m->pts[3].col == 0xffffffff)) - { - int dx, dy, dw, dh; - - dx = m->pts[0].x >> FP; - dy = m->pts[0].y >> FP; - dw = (m->pts[2].x >> FP) - dx; - dh = (m->pts[2].y >> FP) - dy; - eng_image_draw(data, context, surface, image, - 0, 0, gim->w, gim->h, dx, dy, dw, dh, smooth, do_async); - } - else - evas_gl_common_image_map_draw(re->win->gl_context, image, m->count, - &m->pts[0], smooth, level); - - return EINA_FALSE; -} - -static void * -eng_image_map_surface_new(void *data, int w, int h, int alpha) -{ - Render_Engine *re; - - if (!(re = (Render_Engine *)data)) return NULL; - eng_window_use(re->win); - return evas_gl_common_image_surface_new(re->win->gl_context, w, h, alpha); -} - -static void -eng_image_map_surface_free(void *data, void *surface) -{ - Render_Engine *re; - - re = (Render_Engine *)data; - eng_window_use(re->win); - evas_gl_common_image_free(surface); -} - -static void -eng_image_map_clean(void *data EINA_UNUSED, RGBA_Map *m EINA_UNUSED) -{ -} - -static Eina_Bool -eng_image_animated_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim; - Image_Entry *im; - - if (!(gim = image)) return EINA_FALSE; - if (!(im = (Image_Entry *)gim->im)) return EINA_FALSE; - return im->animated.animated; -} - -static int -eng_image_animated_frame_count_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim; - Image_Entry *im; - - if (!(gim = image)) return -1; - if (!(im = (Image_Entry *)gim->im)) return -1; - if (!im->animated.animated) return -1; - return im->animated.frame_count; -} - -static Evas_Image_Animated_Loop_Hint -eng_image_animated_loop_type_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim; - Image_Entry *im; - - if (!(gim = image)) return EVAS_IMAGE_ANIMATED_HINT_NONE; - if (!(im = (Image_Entry *)gim->im)) return EVAS_IMAGE_ANIMATED_HINT_NONE; - if (!im->animated.animated) return EVAS_IMAGE_ANIMATED_HINT_NONE; - return im->animated.loop_hint; -} - -static int -eng_image_animated_loop_count_get(void *data EINA_UNUSED, void *image) -{ - Evas_GL_Image *gim; - Image_Entry *im; - - if (!(gim = image)) return -1; - if (!(im = (Image_Entry *)gim->im)) return -1; - if (!im->animated.animated) return -1; - return im->animated.loop_count; -} - -static double -eng_image_animated_frame_duration_get(void *data EINA_UNUSED, void *image, int start_frame, int frame_num) -{ - Evas_GL_Image *gim; - Image_Entry *im; - - if (!(gim = image)) return -1; - if (!(im = (Image_Entry *)gim->im)) return -1; - if (!im->animated.animated) return -1; - return evas_common_load_rgba_image_frame_duration_from_file(im, start_frame, frame_num); -} - -static Eina_Bool -eng_image_animated_frame_set(void *data EINA_UNUSED, void *image, int frame_index) -{ - Evas_GL_Image *gim; - Image_Entry *im; - - if (!(gim = image)) return EINA_FALSE; - if (!(im = (Image_Entry *)gim->im)) return EINA_FALSE; - if (!im->animated.animated) return EINA_FALSE; - if (im->animated.cur_frame == frame_index) return EINA_FALSE; - - im->animated.cur_frame = frame_index; - return EINA_TRUE; -} - -static Eina_Bool -eng_pixel_alpha_get(void *image, int x, int y, DATA8 *alpha, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h) -{ - Evas_GL_Image *im; - int px, py, dx, dy, sx, sy, src_w, src_h; - double scale_w, scale_h; - - if (!(im = image)) return EINA_FALSE; - - if ((dst_region_x > x) || (x >= (dst_region_x + dst_region_w)) || - (dst_region_y > y) || (y >= (dst_region_y + dst_region_h))) - { - *alpha = 0; - return EINA_FALSE; + if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT)) + return EINA_FALSE; } - evas_gl_common_image_alloc_ensure(im); - src_w = im->im->cache_entry.w; - src_h = im->im->cache_entry.h; - if ((src_w == 0) || (src_h == 0)) - { - *alpha = 0; - return EINA_TRUE; - } - - EINA_SAFETY_ON_TRUE_GOTO(src_region_x < 0, error_oob); - EINA_SAFETY_ON_TRUE_GOTO(src_region_y < 0, error_oob); - EINA_SAFETY_ON_TRUE_GOTO(src_region_x + src_region_w > src_w, error_oob); - EINA_SAFETY_ON_TRUE_GOTO(src_region_y + src_region_h > src_h, error_oob); - - scale_w = (double)dst_region_w / (double)src_region_w; - scale_h = (double)dst_region_h / (double)src_region_h; - - /* point at destination */ - dx = x - dst_region_x; - dy = y - dst_region_y; - - /* point at source */ - sx = dx / scale_w; - sy = dy / scale_h; - - /* pixel point (translated) */ - px = src_region_x + sx; - py = src_region_y + sy; - EINA_SAFETY_ON_TRUE_GOTO(px >= src_w, error_oob); - EINA_SAFETY_ON_TRUE_GOTO(py >= src_h, error_oob); - - switch (im->im->cache_entry.space) - { - case EVAS_COLORSPACE_ARGB8888: - { - DATA32 *pixel; - - evas_cache_image_load_data(&im->im->cache_entry); - if (!im->im->cache_entry.flags.loaded) - { - ERR("im %p has no pixels loaded yet", im); - return EINA_FALSE; - } - - pixel = im->im->image.data; - pixel += ((py * src_w) + px); - *alpha = ((*pixel) >> 24) & 0xff; - } - break; - - default: - ERR("Colorspace %d not supported.", im->im->cache_entry.space); - *alpha = 0; - } - - return EINA_TRUE; - -error_oob: - ERR("Invalid region src=(%d, %d, %d, %d), dst=(%d, %d, %d, %d), image=%dx%d", - src_region_x, src_region_y, src_region_w, src_region_h, - dst_region_x, dst_region_y, dst_region_w, dst_region_h, - src_w, src_h); - *alpha = 0; return EINA_TRUE; } @@ -2616,7 +1048,7 @@ module_open(Evas_Module *em) if (!evas_gl_common_module_open()) return 0; /* get whatever engine module we inherit from */ - if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0; + if (!_evas_module_engine_inherit(&pfunc, "gl_generic")) return 0; /* setup logging domain */ if (_evas_engine_wl_egl_log_dom < 0) @@ -2643,88 +1075,11 @@ module_open(Evas_Module *em) 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(context_cutout_add); - ORD(context_cutout_clear); - ORD(context_flush); - - ORD(gl_surface_create); - ORD(gl_surface_destroy); - ORD(gl_context_create); - ORD(gl_context_destroy); - ORD(gl_make_current); - ORD(gl_string_query); - ORD(gl_proc_address_get); - ORD(gl_native_surface_get); - ORD(gl_api_get); - ORD(gl_direct_override_get); - ORD(gl_get_pixels_set); - - ORD(rectangle_draw); - ORD(line_draw); - ORD(font_draw); - - ORD(polygon_draw); - ORD(polygon_point_add); - ORD(polygon_points_clear); - - ORD(image_load); - ORD(image_mmap); - ORD(image_new_from_data); - ORD(image_new_from_copied_data); - ORD(image_free); - ORD(image_size_get); - ORD(image_size_set); - ORD(image_dirty_region); - ORD(image_data_get); - ORD(image_data_put); - ORD(image_data_preload_request); - ORD(image_data_preload_cancel); - ORD(image_alpha_set); - ORD(image_alpha_get); - ORD(image_border_set); - ORD(image_border_get); - ORD(image_draw); - ORD(image_comment_get); - ORD(image_format_get); - ORD(image_colorspace_set); - ORD(image_colorspace_get); - ORD(image_can_region_get); ORD(image_native_set); - ORD(image_native_get); - ORD(image_scale_hint_set); - ORD(image_scale_hint_get); - ORD(image_stride_get); - ORD(image_content_hint_set); - ORD(image_content_hint_get); - ORD(image_cache_flush); - ORD(image_cache_set); - ORD(image_cache_get); - ORD(image_load_error_get); - ORD(image_max_size_get); - ORD(image_map_draw); - ORD(image_map_surface_new); - ORD(image_map_surface_free); - ORD(image_map_clean); - - ORD(image_animated_get); - ORD(image_animated_frame_count_get); - ORD(image_animated_loop_type_get); - ORD(image_animated_loop_count_get); - ORD(image_animated_frame_duration_get); - ORD(image_animated_frame_set); - - ORD(pixel_alpha_get); + gl_symbols(); /* advertise out which functions we support */ em->functions = (void *)(&func); @@ -2736,7 +1091,6 @@ static void module_close(Evas_Module *em EINA_UNUSED) { eina_log_domain_unregister(_evas_engine_wl_egl_log_dom); - evas_gl_common_module_close(); } static Evas_Module_Api evas_modapi = diff --git a/src/modules/evas/engines/wayland_egl/evas_wl_main.c b/src/modules/evas/engines/wayland_egl/evas_wl_main.c index 88d56b46b8..c073dd7602 100644 --- a/src/modules/evas/engines/wayland_egl/evas_wl_main.c +++ b/src/modules/evas/engines/wayland_egl/evas_wl_main.c @@ -8,7 +8,7 @@ static EGLContext context = EGL_NO_CONTEXT; static int win_count = 0; Outbuf * -eng_window_new(struct wl_display *display, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect EINA_UNUSED, int alpha, int rot) +eng_window_new(struct wl_display *disp, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect EINA_UNUSED, int alpha, int rot, Render_Engine_Swap_Mode swap_mode) { Outbuf *gw; int context_attrs[3]; @@ -23,7 +23,7 @@ eng_window_new(struct wl_display *display, struct wl_surface *surface, int scree return NULL; win_count++; - gw->disp = display; + gw->disp = disp; gw->surface = surface; gw->screen = screen; gw->depth = depth; @@ -31,6 +31,7 @@ eng_window_new(struct wl_display *display, struct wl_surface *surface, int scree gw->h = h; gw->alpha = alpha; gw->rot = rot; + gw->swap_mode = swap_mode; context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION; context_attrs[1] = 2; @@ -164,7 +165,7 @@ eng_window_new(struct wl_display *display, struct wl_surface *surface, int scree return NULL; } - if (!(gw->gl_context = evas_gl_common_context_new())) + if (!(gw->gl_context = glsym_evas_gl_common_context_new())) { eng_window_free(gw); return NULL; @@ -174,7 +175,7 @@ eng_window_new(struct wl_display *display, struct wl_surface *surface, int scree gw->gl_context->eglctxt = gw->egl_context[0]; eng_window_use(gw); - evas_gl_common_context_resize(gw->gl_context, w, h, rot); + glsym_evas_gl_common_context_resize(gw->gl_context, w, h, rot); gw->surf = EINA_TRUE; @@ -194,7 +195,7 @@ eng_window_free(Outbuf *gw) if (gw->gl_context) { ref = gw->gl_context->references - 1; - evas_gl_common_context_free(gw->gl_context); + glsym_evas_gl_common_context_free(gw->gl_context); } eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, @@ -224,7 +225,7 @@ eng_window_use(Outbuf *gw) { Eina_Bool force = EINA_FALSE; - evas_gl_preload_render_lock(eng_window_make_current, gw); + glsym_evas_gl_preload_render_lock(eng_preload_make_current, gw); if (_evas_gl_wl_window) { @@ -236,8 +237,8 @@ eng_window_use(Outbuf *gw) { if (_evas_gl_wl_window) { - evas_gl_common_context_use(_evas_gl_wl_window->gl_context); - evas_gl_common_context_flush(_evas_gl_wl_window->gl_context); + glsym_evas_gl_common_context_use(_evas_gl_wl_window->gl_context); + glsym_evas_gl_common_context_flush(_evas_gl_wl_window->gl_context); } _evas_gl_wl_window = gw; @@ -254,7 +255,7 @@ eng_window_use(Outbuf *gw) } } - if (gw) evas_gl_common_context_use(gw->gl_context); + if (gw) glsym_evas_gl_common_context_use(gw->gl_context); } void @@ -265,13 +266,14 @@ eng_window_unsurf(Outbuf *gw) if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", gw); if (_evas_gl_wl_window) - evas_gl_common_context_flush(_evas_gl_wl_window->gl_context); + glsym_evas_gl_common_context_flush(_evas_gl_wl_window->gl_context); + if (_evas_gl_wl_window == gw) { eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (gw->egl_surface[0] != EGL_NO_SURFACE) - eglDestroySurface(gw->egl_disp, gw->egl_surface[0]); + eglDestroySurface(gw->egl_disp, gw->egl_surface[0]); gw->egl_surface[0] = EGL_NO_SURFACE; _evas_gl_wl_window = NULL; @@ -304,25 +306,192 @@ eng_window_resurf(Outbuf *gw) gw->surf = EINA_TRUE; } -Eina_Bool -eng_window_make_current(void *data, void *doit) +void +eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth EINA_UNUSED) { - Outbuf *gw; + ob->w = w; + ob->h = h; + ob->rot = rot; + eng_window_use(ob); + glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot); +} - if (!(gw = data)) return EINA_FALSE; +int +eng_outbuf_rotation_get(Outbuf *ob) +{ + return ob->rot; +} - if (doit) +Render_Engine_Swap_Mode +eng_outbuf_swap_mode_get(Outbuf *ob) +{ + if ((ob->swap_mode == MODE_AUTO) && (extn_have_buffer_age)) { - if (!eglMakeCurrent(gw->egl_disp, gw->egl_surface[0], - gw->egl_surface[0], gw->egl_context[0])) - return EINA_FALSE; + Render_Engine_Swap_Mode swap_mode; + EGLint age = 0; + + if (!eglQuerySurface(ob->egl_disp, ob->egl_surface[0], + EGL_BUFFER_AGE_EXT, &age)) + age = 0; + + if (age == 1) swap_mode = MODE_COPY; + else if (age == 2) swap_mode = MODE_DOUBLE; + else if (age == 3) swap_mode = MODE_TRIPLE; + else if (age == 4) swap_mode = MODE_QUADRUPLE; + else swap_mode = MODE_FULL; + + if ((int)age != ob->prev_age) swap_mode = MODE_FULL; + ob->prev_age = age; + + return swap_mode; } + + return ob->swap_mode; +} + +Eina_Bool +eng_outbuf_region_first_rect(Outbuf *ob) +{ + ob->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM; + + glsym_evas_gl_preload_render_lock(eng_preload_make_current, ob); + + eng_window_use(ob); + if (!_re_wincheck(ob)) return EINA_TRUE; + + glsym_evas_gl_common_context_resize(ob->gl_context, ob->w, ob->h, ob->rot); + glsym_evas_gl_common_context_flush(ob->gl_context); + glsym_evas_gl_common_context_newframe(ob->gl_context); + + return EINA_FALSE; +} + +void * +eng_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) +{ + if ((ob->w == w) && (ob->h == h)) + ob->gl_context->master_clip.enabled = EINA_FALSE; else { - if (!eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT)) - return EINA_FALSE; + ob->gl_context->master_clip.enabled = EINA_TRUE; + ob->gl_context->master_clip.x = x; + ob->gl_context->master_clip.y = y; + ob->gl_context->master_clip.w = w; + ob->gl_context->master_clip.h = h; } - return EINA_TRUE; + return ob->gl_context->def_surface; +} + +void +eng_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED) +{ + +} + +void +eng_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) +{ + if (!_re_wincheck(ob)) return; + ob->draw.drew = EINA_TRUE; + glsym_evas_gl_common_context_flush(ob->gl_context); +} + +void +eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode) +{ + if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end; + + if (!_re_wincheck(ob)) goto end; + if (!ob->draw.drew) goto end; + + ob->draw.drew = EINA_FALSE; + eng_window_use(ob); + glsym_evas_gl_common_context_done(ob->gl_context); + + if (!ob->vsync) + { + if (ob->info->vsync) eglSwapInterval(ob->egl_disp, 1); + else eglSwapInterval(ob->egl_disp, 0); + ob->vsync = EINA_TRUE; + } + + if (ob->info->callback.pre_swap) + ob->info->callback.pre_swap(ob->info->callback.data, ob->evas); + + if ((glsym_eglSwapBuffersWithDamage) && (ob->swap_mode != MODE_FULL)) + { + EGLint num = 0, *result = NULL, i = 0; + Tilebuf_Rect *r; + + // if partial swaps can be done use re->rects + num = eina_inlist_count(EINA_INLIST_GET(rects)); + if (num > 0) + { + result = alloca(sizeof(EGLint) * 4 * num); + EINA_INLIST_FOREACH(EINA_INLIST_GET(rects), r) + { + int gw, gh; + + gw = ob->gl_context->w; + gh = ob->gl_context->h; + switch (ob->rot) + { + case 0: + result[i + 0] = r->x; + result[i + 1] = gh - (r->y + r->h); + result[i + 2] = r->w; + result[i + 3] = r->h; + break; + case 90: + result[i + 0] = r->y; + result[i + 1] = r->x; + result[i + 2] = r->h; + result[i + 3] = r->w; + break; + case 180: + result[i + 0] = gw - (r->x + r->w); + result[i + 1] = r->y; + result[i + 2] = r->w; + result[i + 3] = r->h; + break; + case 270: + result[i + 0] = gh - (r->y + r->h); + result[i + 1] = gw - (r->x + r->w); + result[i + 2] = r->h; + result[i + 3] = r->w; + break; + default: + result[i + 0] = r->x; + result[i + 1] = gh - (r->y + r->h); + result[i + 2] = r->w; + result[i + 3] = r->h; + break; + } + i += 4; + } + glsym_eglSwapBuffersWithDamage(ob->egl_disp, ob->egl_surface[0], + result, num); + } + } + else + eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]); + + if (ob->info->callback.post_swap) + ob->info->callback.post_swap(ob->info->callback.data, ob->evas); + + end: + glsym_evas_gl_preload_render_unlock(eng_preload_make_current, ob); +} + +Evas_Engine_GL_Context * +eng_outbuf_gl_context_get(Outbuf *ob) +{ + return ob->gl_context; +} + +void * +eng_outbuf_egl_display_get(Outbuf *ob) +{ + return ob->egl_disp; }