Compare commits

...

4 Commits

Author SHA1 Message Date
Rafael Antognolli eefb2386e6 evas/wayland_egl: Subsurfaces handled as native surfaces.
This code assumes that a wl_buffer will be passed as a native surface to
an Evas image, and then Evas will handle it as appropriate. The image
will be used as is, or converted to a subsurface if possible.
2013-09-23 19:28:36 -03:00
Rafael Antognolli 0258a7c466 ecore/wayland: Add subsurface handling APIs. 2013-09-23 11:03:23 -03:00
Rafael Antognolli 0046e5b40f ecore/wayland: Add and initialize subcompositor inside Ecore_Wayland. 2013-09-23 11:03:23 -03:00
Rafael Antognolli 0f96c92b64 adding wayland subsurfaces protocol file. 2013-09-23 11:03:23 -03:00
14 changed files with 786 additions and 7 deletions

View File

@ -1000,6 +1000,7 @@ AC_ARG_ENABLE([wayland],
if test "${want_wayland}" = "yes"; then
EFL_PKG_CHECK_STRICT([wayland-client])
WAYLAND_SCANNER_RULES(['$(top_srcdir)/data/ecore/ecore_wayland/protocol'])
fi
# Fb

View File

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="subsurface">
<copyright>
Copyright © 2012-2013 Collabora, Ltd.
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>
<interface name="wl_subcompositor" version="1">
<description summary="sub-surface compositing">
The global interface exposing sub-surface compositing capabilities.
A wl_surface, that has sub-surfaces associated, is called the
parent surface. Sub-surfaces can be arbitrarily nested and create
a tree of sub-surfaces.
The root surface in a tree of sub-surfaces is the main
surface. The main surface cannot be a sub-surface, because
sub-surfaces must always have a parent.
A main surface with its sub-surfaces forms a (compound) window.
For window management purposes, this set of wl_surface objects is
to be considered as a single window, and it should also behave as
such.
The aim of sub-surfaces is to offload some of the compositing work
within a window from clients to the compositor. A prime example is
a video player with decorations and video in separate wl_surface
objects. This should allow the compositor to pass YUV video buffer
processing to dedicated overlay hardware when possible.
</description>
<request name="destroy" type="destructor">
<description summary="unbind from the subcompositor interface">
Informs the server that the client will not be using this
protocol object anymore. This does not affect any other
objects, wl_subsurface objects included.
</description>
</request>
<enum name="error">
<entry name="bad_surface" value="0"
summary="the to-be sub-surface is invalid"/>
</enum>
<request name="get_subsurface">
<description summary="give a surface the role sub-surface">
Create a sub-surface interface for the given surface, and
associate it with the given parent surface. This turns a
plain wl_surface into a sub-surface.
The to-be sub-surface must not already have a dedicated
purpose, like any shell surface type, cursor image, drag icon,
or sub-surface. Otherwise a protocol error is raised.
</description>
<arg name="id" type="new_id" interface="wl_subsurface"
summary="the new subsurface object id"/>
<arg name="surface" type="object" interface="wl_surface"
summary="the surface to be turned into a sub-surface"/>
<arg name="parent" type="object" interface="wl_surface"
summary="the parent surface"/>
</request>
</interface>
<interface name="wl_subsurface" version="1">
<description summary="sub-surface interface to a wl_surface">
An additional interface to a wl_surface object, which has been
made a sub-surface. A sub-surface has one parent surface. A
sub-surface's size and position are not limited to that of the parent.
Particularly, a sub-surface is not automatically clipped to its
parent's area.
A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
and the parent surface is mapped. The order of which one happens
first is irrelevant. A sub-surface is hidden if the parent becomes
hidden, or if a NULL wl_buffer is applied. These rules apply
recursively through the tree of surfaces.
The behaviour of wl_surface.commit request on a sub-surface
depends on the sub-surface's mode. The possible modes are
synchronized and desynchronized, see methods
wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
mode caches the wl_surface state to be applied when the parent's
state gets applied, and desynchronized mode applies the pending
wl_surface state directly. A sub-surface is initially in the
synchronized mode.
Sub-surfaces have also other kind of state, which is managed by
wl_subsurface requests, as opposed to wl_surface requests. This
state includes the sub-surface position relative to the parent
surface (wl_subsurface.set_position), and the stacking order of
the parent and its sub-surfaces (wl_subsurface.place_above and
.place_below). This state is applied when the parent surface's
wl_surface state is applied, regardless of the sub-surface's mode.
As the exception, set_sync and set_desync are effective immediately.
The main surface can be thought to be always in desynchronized mode,
since it does not have a parent in the sub-surfaces sense.
Even if a sub-surface is in desynchronized mode, it will behave as
in synchronized mode, if its parent surface behaves as in
synchronized mode. This rule is applied recursively throughout the
tree of surfaces. This means, that one can set a sub-surface into
synchronized mode, and then assume that all its child and grand-child
sub-surfaces are synchronized, too, without explicitly setting them.
If the wl_surface associated with the wl_subsurface is destroyed, the
wl_subsurface object becomes inert. Note, that destroying either object
takes effect immediately. If you need to synchronize the removal
of a sub-surface to the parent surface update, unmap the sub-surface
first by attaching a NULL wl_buffer, update parent, and then destroy
the sub-surface.
If the parent wl_surface object is destroyed, the sub-surface is
unmapped.
</description>
<request name="destroy" type="destructor">
<description summary="remove sub-surface interface">
The sub-surface interface is removed from the wl_surface object
that was turned into a sub-surface with
wl_subcompositor.get_subsurface request. The wl_surface's association
to the parent is deleted, and the wl_surface loses its role as
a sub-surface. The wl_surface is unmapped.
</description>
</request>
<enum name="error">
<entry name="bad_surface" value="0"
summary="wl_surface is not a sibling or the parent"/>
</enum>
<request name="set_position">
<description summary="reposition the sub-surface">
This schedules a sub-surface position change.
The sub-surface will be moved so, that its origin (top-left
corner pixel) will be at the location x, y of the parent surface
coordinate system. The coordinates are not restricted to the parent
surface area. Negative values are allowed.
The next wl_surface.commit on the parent surface will reset
the sub-surface's position to the scheduled coordinates.
The initial position is 0, 0.
</description>
<arg name="x" type="int" summary="coordinate in the parent surface"/>
<arg name="y" type="int" summary="coordinate in the parent surface"/>
</request>
<request name="place_above">
<description summary="restack the sub-surface">
This sub-surface is taken from the stack, and put back just
above the reference surface, changing the z-order of the sub-surfaces.
The reference surface must be one of the sibling surfaces, or the
parent surface. Using any other surface, including this sub-surface,
will cause a protocol error.
The z-order is double-buffered state, and will be applied on the
next commit of the parent surface.
See wl_surface.commit and wl_subcompositor.get_subsurface.
A new sub-surface is initially added as the top-most in the stack
of its siblings and parent.
</description>
<arg name="sibling" type="object" interface="wl_surface"
summary="the reference surface"/>
</request>
<request name="place_below">
<description summary="restack the sub-surface">
The sub-surface is placed just below of the reference surface.
See wl_subsurface.place_above.
</description>
<arg name="sibling" type="object" interface="wl_surface"
summary="the reference surface"/>
</request>
<request name="set_sync">
<description summary="set sub-surface to synchronized mode">
Change the commit behaviour of the sub-surface to synchronized
mode, also described as the parent dependant mode.
In synchronized mode, wl_surface.commit on a sub-surface will
accumulate the committed state in a cache, but the state will
not be applied and hence will not change the compositor output.
The cached state is applied to the sub-surface immediately after
the parent surface's state is applied. This ensures atomic
updates of the parent and all its synchronized sub-surfaces.
Applying the cached state will invalidate the cache, so further
parent surface commits do not (re-)apply old state.
See wl_subsurface for the recursive effect of this mode.
</description>
</request>
<request name="set_desync">
<description summary="set sub-surface to desynchronized mode">
Change the commit behaviour of the sub-surface to desynchronized
mode, also described as independent or freely running mode.
In desynchronized mode, wl_surface.commit on a sub-surface will
apply the pending state directly, without caching, as happens
normally with a wl_surface. Calling wl_surface.commit on the
parent surface has no effect on the sub-surface's wl_surface
state. This mode allows a sub-surface to be updated on its own.
If cached state exists when wl_surface.commit is called in
desynchronized mode, the pending state is added to the cached
state, and applied as whole. This invalidates the cache.
Note: even if a sub-surface is set to desynchronized, a parent
sub-surface may override it to behave as synchronized. For details,
see wl_subsurface.
If a surface's parent surface behaves as desynchronized, then
the cached state is applied on set_desync.
</description>
</request>
</interface>
</protocol>

View File

@ -14,10 +14,28 @@ lib/ecore_wayland/ecore_wl_dnd.c \
lib/ecore_wayland/ecore_wl_input.c \
lib/ecore_wayland/ecore_wl_output.c \
lib/ecore_wayland/ecore_wl_window.c \
lib/ecore_wayland/ecore_wl_subsurf.c \
lib/ecore_wayland/ecore_wl_private.h
lib_ecore_wayland_libecore_wayland_la_BUILT_SOURCES = \
lib/ecore_wayland/subsurface-protocol.c \
lib/ecore_wayland/subsurface-client-protocol.h
CLEANFILES += $(lib_ecore_wayland_libecore_wayland_la_BUILT_SOURCES)
lib_ecore_wayland_libecore_wayland_la_SOURCES += $(lib_ecore_wayland_libecore_wayland_la_BUILT_SOURCES)
BUILT_SOURCES += $(lib_ecore_wayland_libecore_wayland_la_BUILT_SOURCES)
lib_ecore_wayland_libecore_wayland_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_WAYLAND_CFLAGS@
lib_ecore_wayland_libecore_wayland_la_LIBADD = @ECORE_WAYLAND_LIBS@
lib_ecore_wayland_libecore_wayland_la_DEPENDENCIES = @ECORE_WAYLAND_INTERNAL_LIBS@
lib_ecore_wayland_libecore_wayland_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
lib/ecore_wayland/subsurface-protocol.c: $(wayland_protocoldir)/subsurface.xml
$(AM_V_GEN)$(wayland_scanner) code < $< > $@
lib/ecore_wayland/subsurface-client-protocol.h: $(wayland_protocoldir)/subsurface.xml
$(AM_V_GEN)$(wayland_scanner) client-header < $< > $@
endif

View File

@ -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

2
src/lib/ecore_wayland/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
subsurface-protocol.c
subsurface-client-protocol.h

View File

@ -35,6 +35,7 @@ typedef struct _Ecore_Wl_Display Ecore_Wl_Display;
typedef struct _Ecore_Wl_Output Ecore_Wl_Output;
typedef struct _Ecore_Wl_Input Ecore_Wl_Input;
typedef struct _Ecore_Wl_Global Ecore_Wl_Global; /** @since 1.7.6 */
typedef struct _Ecore_Wl_Subsurf Ecore_Wl_Subsurf; /** @since 1.8 */
# ifndef _ECORE_WAYLAND_WINDOW_PREDEF
typedef struct _Ecore_Wl_Window Ecore_Wl_Window;
@ -101,6 +102,7 @@ struct _Ecore_Wl_Display
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_subcompositor *subcompositor;
struct wl_shell *shell;
struct wl_shell *desktop_shell;
struct wl_shm *shm;
@ -250,6 +252,8 @@ struct _Ecore_Wl_Window
/* FIXME: Ideally we should record the cursor name for this window
* so we can compare and avoid unnecessary cursor set calls to wayland */
Ecore_Wl_Subsurf *subsurfs;
void *data;
};
@ -380,6 +384,7 @@ struct _Ecore_Wl_Event_Interfaces_Bound
* @li @ref Ecore_Wl_Window_Group
* @li @ref Ecore_Wl_Input_Group
* @li @ref Ecore_Wl_Dnd_Group
* @li @ref Ecore_Wl_Subsurf
*/
EAPI extern int ECORE_WL_EVENT_MOUSE_IN;
@ -483,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.
*
@ -863,6 +870,96 @@ EAPI struct wl_array *ecore_wl_dnd_drag_types_get(Ecore_Wl_Input *input);
EAPI void ecore_wl_server_mode_set(Eina_Bool on);
/**
* @defgroup Ecore_Wl_Subsurf Functions to manipulate subsurfaces.
* @ingroup Ecore_Wl_Group
*
* Functions to manipulate wayland subsurfaces, using Ecore_Wl_Subsurf.
*
* This API is intended to expose Wayland subsurface functionality, although it
* should not be necessary for most applications to use it, as soon as we have
* means to make Evas automatically switch Evas images to use subsurfaces.
*
* It can/should be used, for instance, when subsurfaces are needed to be not
* in sync with the main window surface.
*/
/**
* Create and return a new subsurface.
*
* Create a new surface (and subsurface interface), with the parent surface
* being the one associated with the given @param win.
*
* The @param win must be visible, otherwise there will be no surface created
* for it yet.
*
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI Ecore_Wl_Subsurf *ecore_wl_subsurf_create(Ecore_Wl_Window *win);
/**
* Destroy the given subsurface, as well as the surface associated with it.
*
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI void ecore_wl_subsurf_del(Ecore_Wl_Subsurf *ess);
/**
* Return the wl_surface associated with this subsurface.
*
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI struct wl_surface *ecore_wl_subsurf_surface_get(Ecore_Wl_Subsurf *ess);
/**
* Set the position of this subsurface, relative to its parent surface.
*
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI void ecore_wl_subsurf_position_set(Ecore_Wl_Subsurf *ess, int x, int y);
/**
* Get the position of this subsurface, relative to its parent surface.
*
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI void ecore_wl_subsurf_position_get(Ecore_Wl_Subsurf *ess, int *x, int *y);
/**
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI void ecore_wl_subsurf_place_above(Ecore_Wl_Subsurf *ess, struct wl_surface *surface);
/**
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI void ecore_wl_subsurf_place_below(Ecore_Wl_Subsurf *ess, struct wl_surface *surface);
/**
* @ingroup Ecore_Wl_Subsurf
* @since 1.8
*/
EAPI void ecore_wl_subsurf_sync_set(Ecore_Wl_Subsurf *ess, Eina_Bool val);
/**
* Set an opaque region for the given subsurface.
*
* Use a 0x0 region size to unset the opaque region.
*
* @ingroup Ecore_Wl_Subsurf
* @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

View File

@ -4,6 +4,7 @@
#include <fcntl.h>
#include "ecore_wl_private.h"
#include <subsurface-client-protocol.h>
/* local function prototypes */
static Eina_Bool _ecore_wl_shutdown(Eina_Bool close);
@ -352,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)
@ -397,6 +428,8 @@ _ecore_wl_shutdown(Eina_Bool close)
wl_data_device_manager_destroy(_ecore_wl_disp->wl.data_device_manager);
if (_ecore_wl_disp->wl.compositor)
wl_compositor_destroy(_ecore_wl_disp->wl.compositor);
if (_ecore_wl_disp->wl.subcompositor)
wl_subcompositor_destroy(_ecore_wl_disp->wl.subcompositor);
if (_ecore_wl_disp->wl.display)
{
wl_registry_destroy(_ecore_wl_disp->wl.registry);
@ -515,6 +548,11 @@ _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned in
ewd->wl.compositor =
wl_registry_bind(registry, id, &wl_compositor_interface, 3);
}
else if (!strcmp(interface, "wl_subcompositor"))
{
ewd->wl.subcompositor =
wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
}
else if (!strcmp(interface, "wl_output"))
_ecore_wl_output_add(ewd, id);
else if (!strcmp(interface, "wl_seat"))

View File

@ -95,4 +95,6 @@ void _ecore_wl_dnd_del(Ecore_Wl_Dnd_Source *source);
void _ecore_wl_events_init(void);
void _ecore_wl_events_shutdown(void);
void _ecore_wl_subsurfs_del_all(Ecore_Wl_Window *win);
#endif

View File

@ -0,0 +1,192 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "ecore_wl_private.h"
#include <subsurface-client-protocol.h>
struct _Ecore_Wl_Subsurf
{
EINA_INLIST;
Ecore_Wl_Window *parent_win;
struct wl_surface *surface;
struct wl_subsurface *subsurface;
int x, y;
Eina_Bool sync : 1;
};
EAPI Ecore_Wl_Subsurf *
ecore_wl_subsurf_create(Ecore_Wl_Window *win)
{
struct wl_subsurface *subsurface;
struct wl_surface *surface;
Ecore_Wl_Subsurf *ess;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!win) return NULL;
if (!win->surface) return NULL;
if (!_ecore_wl_disp->wl.subcompositor) return NULL;
surface = wl_compositor_create_surface(_ecore_wl_disp->wl.compositor);
if (!surface)
return NULL;
subsurface = wl_subcompositor_get_subsurface
(_ecore_wl_disp->wl.subcompositor, surface, win->surface);
if (!subsurface)
{
wl_surface_destroy(surface);
return NULL;
}
ess = calloc(1, sizeof(*ess));
ess->surface = surface;
ess->subsurface = subsurface;
ess->parent_win = win;
win->subsurfs = (Ecore_Wl_Subsurf *)eina_inlist_append
(EINA_INLIST_GET(win->subsurfs), EINA_INLIST_GET(ess));
return ess;
}
static void
_ecore_wl_subsurf_destroy(Ecore_Wl_Subsurf *ess)
{
wl_subsurface_destroy(ess->subsurface);
wl_surface_destroy(ess->surface);
free(ess);
}
EAPI void
ecore_wl_subsurf_del(Ecore_Wl_Subsurf *ess)
{
Ecore_Wl_Window *parent;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return;
parent = ess->parent_win;
parent->subsurfs = (Ecore_Wl_Subsurf *)eina_inlist_remove
(EINA_INLIST_GET(parent->subsurfs), EINA_INLIST_GET(ess));
_ecore_wl_subsurf_destroy(ess);
}
void
_ecore_wl_subsurfs_del_all(Ecore_Wl_Window *win)
{
Ecore_Wl_Subsurf *ess;
if (!win) return;
EINA_INLIST_FREE(win->subsurfs, ess)
{
_ecore_wl_subsurf_destroy(ess);
}
}
EAPI struct wl_surface *
ecore_wl_subsurf_surface_get(Ecore_Wl_Subsurf *ess)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return NULL;
return ess->surface;
}
EAPI void
ecore_wl_subsurf_position_set(Ecore_Wl_Subsurf *ess, int x, int y)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return;
if ((x == ess->x) && (y == ess->y))
return;
ess->x = x;
ess->y = y;
wl_subsurface_set_position(ess->subsurface, x, y);
}
EAPI void
ecore_wl_subsurf_position_get(Ecore_Wl_Subsurf *ess, int *x, int *y)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return;
if (x) *x = ess->x;
if (y) *y = ess->y;
}
EAPI void
ecore_wl_subsurf_place_above(Ecore_Wl_Subsurf *ess, struct wl_surface *surface)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return;
if (!surface) return;
wl_subsurface_place_above(ess->subsurface, surface);
}
EAPI void
ecore_wl_subsurf_place_below(Ecore_Wl_Subsurf *ess, struct wl_surface *surface)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return;
if (!surface) return;
wl_subsurface_place_below(ess->subsurface, surface);
}
EAPI void
ecore_wl_subsurf_sync_set(Ecore_Wl_Subsurf *ess, Eina_Bool val)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return;
val = !!val;
if (val == ess->sync) return;
ess->sync = val;
if (ess->sync)
wl_subsurface_set_sync(ess->subsurface);
else
wl_subsurface_set_desync(ess->subsurface);
}
EAPI void
ecore_wl_subsurf_opaque_region_set(Ecore_Wl_Subsurf *ess, int x, int y, int w, int h)
{
Ecore_Wl_Window *parent;
struct wl_region *region = NULL;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ess) return;
if ((w > 0) && (h > 0))
{
parent = ess->parent_win;
region = wl_compositor_create_region(parent->display->wl.compositor);
wl_region_add(region, x, y, w, h);
wl_surface_set_opaque_region(ess->surface, region);
wl_region_destroy(region);
}
else
wl_surface_set_opaque_region(ess->surface, NULL);
}

View File

@ -114,6 +114,8 @@ ecore_wl_window_free(Ecore_Wl_Window *win)
if (win->anim_callback) wl_callback_destroy(win->anim_callback);
win->anim_callback = NULL;
if (win->subsurfs) _ecore_wl_subsurfs_del_all(win);
if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
win->shell_surface = NULL;
if (win->surface) wl_surface_destroy(win->surface);

View File

@ -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;
};

View File

@ -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);

View File

@ -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;

View File

@ -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 <dlfcn.h>
@ -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;
}