diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 924e0e159b..dcb9f92a5b 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -895,10 +895,20 @@ WAYLAND_EGL_SOURCES = \ modules/evas/engines/wayland_egl/evas_engine.c \ modules/evas/engines/wayland_egl/evas_wl_main.c \ modules/evas/engines/wayland_egl/evas_engine.h + +module_wayland_BUILT_SOURCES = \ +modules/evas/engines/wayland_egl/subsurface-protocol.c \ +modules/evas/engines/wayland_egl/subsurface-client-protocol.h + +CLEANFILES += $(module_wayland_BUILT_SOURCES) +BUILT_SOURCES += $(module_wayland_BUILT_SOURCES) +WAYLAND_EGL_SOURCES += $(module_wayland_BUILT_SOURCES) + if EVAS_STATIC_BUILD_WAYLAND_EGL lib_evas_libevas_la_SOURCES += $(WAYLAND_EGL_SOURCES) lib_evas_libevas_la_CPPFLAGS += \ -I$(top_srcdir)/src/modules/evas/engines/gl_common \ +-I$(top_builddir)/src/modules/evas/engines/wayland_egl \ @evas_engine_wayland_egl_cflags@ lib_evas_libevas_la_LIBADD += @evas_engine_wayland_egl_libs@ else @@ -909,6 +919,7 @@ modules_evas_engines_wayland_egl_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/ -I$(top_srcdir)/src/lib/evas/include \ -I$(top_srcdir)/src/lib/evas/cserve2 \ -I$(top_srcdir)/src/modules/evas/engines/gl_common \ +-I$(top_builddir)/src/modules/evas/engines/wayland_egl \ @EVAS_CFLAGS@ \ @evas_engine_wayland_egl_cflags@ modules_evas_engines_wayland_egl_module_la_LIBADD = \ @@ -921,6 +932,14 @@ modules/evas/engines/gl_common/libevas_engine_gl_common.la modules_evas_engines_wayland_egl_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_evas_engines_wayland_egl_module_la_LIBTOOLFLAGS = --tag=disable-static endif + +modules/evas/engines/wayland_egl/subsurface-protocol.c: $(wayland_protocoldir)/subsurface.xml + $(AM_V_GEN)$(wayland_scanner) code < $< > $@ + +modules/evas/engines/wayland_egl/subsurface-client-protocol.h: $(wayland_protocoldir)/subsurface.xml + $(AM_V_GEN)$(wayland_scanner) client-header < $< > $@ + + endif if BUILD_ENGINE_WAYLAND_SHM diff --git a/src/lib/ecore_wayland/Ecore_Wayland.h b/src/lib/ecore_wayland/Ecore_Wayland.h index 145dc3bc81..db9d4d6cb0 100644 --- a/src/lib/ecore_wayland/Ecore_Wayland.h +++ b/src/lib/ecore_wayland/Ecore_Wayland.h @@ -488,6 +488,8 @@ EAPI struct wl_shm *ecore_wl_shm_get(void); */ EAPI struct wl_display *ecore_wl_display_get(void); +EAPI struct wl_compositor *ecore_wl_compositor_get(void); + /** * Retrieves the size of the current screen. * @@ -955,6 +957,9 @@ EAPI void ecore_wl_subsurf_sync_set(Ecore_Wl_Subsurf *ess, Eina_Bool val); * @since 1.8 */ EAPI void ecore_wl_subsurf_opaque_region_set(Ecore_Wl_Subsurf *ess, int x, int y, int w, int h); + +EAPI void *ecore_wl_subcompositor_get(void); + #ifdef __cplusplus } #endif diff --git a/src/lib/ecore_wayland/ecore_wl.c b/src/lib/ecore_wayland/ecore_wl.c index ee614e0e4b..af29cf7bd7 100644 --- a/src/lib/ecore_wayland/ecore_wl.c +++ b/src/lib/ecore_wayland/ecore_wl.c @@ -353,6 +353,36 @@ ecore_wl_server_mode_set(Eina_Bool on) _ecore_wl_server_mode = on; } +EAPI struct wl_compositor * +ecore_wl_compositor_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return NULL; + + if (!_ecore_wl_disp->wl.compositor) + ecore_wl_sync(); + + if (!_ecore_wl_disp->wl.compositor) return NULL; + + return _ecore_wl_disp->wl.compositor; +} + +EAPI void * +ecore_wl_subcompositor_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((!_ecore_wl_disp) || (!_ecore_wl_disp->wl.display)) return NULL; + + if (!_ecore_wl_disp->wl.subcompositor) + ecore_wl_sync(); + + if (!_ecore_wl_disp->wl.subcompositor) return NULL; + + return _ecore_wl_disp->wl.subcompositor; +} + /* local functions */ static Eina_Bool _ecore_wl_shutdown(Eina_Bool close) diff --git a/src/lib/evas/Evas_Common.h b/src/lib/evas/Evas_Common.h index 77f65bd4d6..4bde1c98b7 100644 --- a/src/lib/evas/Evas_Common.h +++ b/src/lib/evas/Evas_Common.h @@ -443,13 +443,14 @@ struct _Evas_Pixel_Import_Source }; /* magic version number to know what the native surf struct looks like */ -#define EVAS_NATIVE_SURFACE_VERSION 2 +#define EVAS_NATIVE_SURFACE_VERSION 3 typedef enum _Evas_Native_Surface_Type { EVAS_NATIVE_SURFACE_NONE, EVAS_NATIVE_SURFACE_X11, - EVAS_NATIVE_SURFACE_OPENGL + EVAS_NATIVE_SURFACE_OPENGL, + EVAS_NATIVE_SURFACE_WL_BUFFER } Evas_Native_Surface_Type; struct _Evas_Native_Surface @@ -470,6 +471,15 @@ struct _Evas_Native_Surface unsigned int format; /**< same as 'format' for glTexImage2D() */ unsigned int x, y, w, h; /**< region inside the texture to use (image size is assumed as texture size, with 0, 0 being the top-left and co-ordinates working down to the right and bottom being positive) */ } opengl; + struct + { + void *buffer; /**< wl_buffer pointer */ + void *pixels; /**< pixel buffer pointer */ + unsigned int id; /**< wl_proxy id (buffer id) */ + unsigned int format; + unsigned int w, h; + Eina_Bool alpha; + } wayland; } data; }; diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c index 9959c085ed..256971e8f7 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c @@ -209,6 +209,8 @@ ecore_evas_wayland_egl_new_internal(const char *disp_name, unsigned int parent, einfo->info.rotation = ee->rotation; einfo->info.depth = 32; einfo->info.surface = ecore_wl_window_surface_create(wdata->win); + einfo->info.compositor = ecore_wl_compositor_get(); + einfo->info.subcompositor = ecore_wl_subcompositor_get(); if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) { ERR("Failed to set Evas Engine Info for '%s'", ee->driver); 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..b593d482dd 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 @@ -25,6 +25,8 @@ struct _Evas_Engine_Info_Wayland_Egl { struct wl_display *display; struct wl_surface *surface; + void *compositor; + void *subcompositor; int depth, screen, rotation, edges; unsigned int destination_alpha : 1; } info; diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.c b/src/modules/evas/engines/wayland_egl/evas_engine.c index 28f72b08de..f0fb360a99 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.c +++ b/src/modules/evas/engines/wayland_egl/evas_engine.c @@ -1,6 +1,7 @@ #include "evas_common_private.h" #include "evas_engine.h" #include "evas_gl_core_private.h" +#include "subsurface-client-protocol.h" #ifdef HAVE_DLSYM # include @@ -51,11 +52,20 @@ struct _Render_Engine } func; }; +typedef struct _Subsurface Subsurface; +struct _Subsurface +{ + struct wl_surface *surface; + struct wl_surface *psurface; + struct wl_subsurface *subsurface; +}; + typedef struct _Native Native; struct _Native { Evas_Native_Surface ns; void *egl_surface; + Subsurface *subsurf; }; /* local function prototypes */ @@ -1707,7 +1717,12 @@ eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h) if (!(re = (Render_Engine *)data)) return NULL; if (!(im = image)) return NULL; - if (im->native.data) return image; + if (im->native.data) + { + Native *n = im->native.data; + if (n->ns.type == EVAS_NATIVE_SURFACE_OPENGL) + return image; + } eng_window_use(re->win); evas_gl_common_image_dirty(image, x, y, w, h); return image; @@ -1995,6 +2010,52 @@ eng_image_border_get(void *data EINA_UNUSED, void *image EINA_UNUSED, int *l EIN { } +static void +_subsurface_setup(Render_Engine *re, Native *n) +{ + struct wl_subcompositor *subcomp; + + if (n->subsurf) + return; + + subcomp = re->info->info.subcompositor; + if (!subcomp || !re->info->info.surface) return; + + n->subsurf = malloc(sizeof(*n->subsurf)); + n->subsurf->surface = wl_compositor_create_surface(re->info->info.compositor); + if (!n->subsurf->surface) + goto error; + + n->subsurf->psurface = re->info->info.surface; + n->subsurf->subsurface = wl_subcompositor_get_subsurface + (subcomp, n->subsurf->surface, n->subsurf->psurface); + if (!n->subsurf->subsurface) + goto subsurf_error; + + printf("**** created surface: %p\n", n->subsurf); + + return; + +subsurf_error: + wl_surface_destroy(n->subsurf->surface); +error: + free(n->subsurf); + n->subsurf = NULL; +} + +static void +_subsurface_destroy(Native *n) +{ + if (!n->subsurf) + return; + + printf("**** destroying surface: %p\n", n->subsurf); + wl_subsurface_destroy(n->subsurf->subsurface); + wl_surface_destroy(n->subsurf->surface); + free(n->subsurf); + n->subsurf = NULL; +} + 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) { @@ -2029,8 +2090,23 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, // Reset clip evgl_direct_img_clip_set(0, 0, 0, 0, 0); } + else if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_WL_BUFFER) && + ((src_w == dst_w) && (src_h == dst_h))) + { + _subsurface_setup(re, n); + if (!n->subsurf) return EINA_FALSE; + + wl_subsurface_set_position(n->subsurf->subsurface, dst_x, dst_y); + wl_surface_attach(n->subsurf->surface, n->ns.data.wayland.buffer, 0, 0); + wl_surface_damage(n->subsurf->surface, src_x, src_y, src_w, src_h); + wl_surface_commit(n->subsurf->surface); + + printf(">>> render subsurface for img: %p: %d, %d + %dx%d ==>>> %d,%d + %dx%d\n", im, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); + } else { + if ((n) && (n->ns.type == EVAS_NATIVE_SURFACE_WL_BUFFER)) + _subsurface_destroy(n); eng_window_use(re->win); evas_gl_common_context_target_surface_set(re->win->gl_context, surface); re->win->gl_context->dc = context; @@ -2038,6 +2114,7 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h, smooth); + printf(">>> render content for img: %p: %d, %d + %dx%d ==>>> %d,%d + %dx%d\n", im, src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, dst_h); } return EINA_FALSE; @@ -2152,6 +2229,15 @@ eng_image_native_set(void *data, void *image, void *native) NULL, 1, EVAS_COLORSPACE_ARGB8888); } + else if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_WL_BUFFER)) + { + im = evas_gl_common_image_new_from_data(re->win->gl_context, + ns->data.wayland.w, + ns->data.wayland.h, + ns->data.wayland.pixels, + ns->data.wayland.alpha, + ns->data.wayland.format); + } else return NULL; } @@ -2172,6 +2258,20 @@ eng_image_native_set(void *data, void *image, void *native) return im; } } + else if (ns->type == EVAS_NATIVE_SURFACE_WL_BUFFER) + { + if (im->native.data) + { + Evas_Native_Surface *ens; + void *buffer = ns->data.wayland.buffer; + unsigned int bufferid = ns->data.wayland.id; + + ens = im->native.data; + if ((ens->data.wayland.buffer == buffer) && + (ens->data.wayland.id == bufferid)) + return im; + } + } } if ((!ns) && (!im->native.data)) return im; @@ -2203,10 +2303,38 @@ eng_image_native_set(void *data, void *image, void *native) } } } + else if (ns->type == EVAS_NATIVE_SURFACE_WL_BUFFER) + { + unsigned int bufferid = ns->data.wayland.id; + im2 = eina_hash_find(re->win->gl_context->shared->native_tex_hash, &bufferid); + if (im2 == im) return im; + if (im2) + { + n = im2->native.data; + if (n) + { + evas_gl_common_image_ref(im2); + _subsurface_destroy(im->native.data); + evas_gl_common_image_free(im); + return im2; + } + } + } - im2 = evas_gl_common_image_new_from_data(re->win->gl_context, - im->w, im->h, NULL, im->alpha, - EVAS_COLORSPACE_ARGB8888); + if (ns->type == EVAS_NATIVE_SURFACE_OPENGL) + im2 = evas_gl_common_image_new_from_data(re->win->gl_context, + im->w, im->h, NULL, im->alpha, + EVAS_COLORSPACE_ARGB8888); + else + im2 = evas_gl_common_image_new_from_data(re->win->gl_context, + ns->data.wayland.w, + ns->data.wayland.h, + ns->data.wayland.pixels, + ns->data.wayland.alpha, + ns->data.wayland.format); + + if (im->native.data) + _subsurface_destroy(im->native.data); evas_gl_common_image_free(im); if (!(im = im2)) return NULL; @@ -2239,7 +2367,29 @@ eng_image_native_set(void *data, void *image, void *native) evas_gl_common_image_native_enable(im); } } - } + } + else + { + n = calloc(1, sizeof(Native)); + if (n) + { + memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface)); + + eina_hash_add(re->win->gl_context->shared->native_tex_hash, + &texid, im); + + n->egl_surface = 0; + im->native.yinvert = 1; + 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; + } + } return im; }