Compare commits
6 Commits
gsk-unity-
...
subsurface
Author | SHA1 | Date | |
---|---|---|---|
|
a77fde155d | ||
|
004c2b8cc2 | ||
|
0605888ac6 | ||
|
ef5b1ba044 | ||
|
5fa7457171 | ||
|
f50edb6910 |
@@ -493,6 +493,12 @@ gdk_surface_real_get_scale (GdkSurface *surface)
|
|||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GdkSubsurface *
|
||||||
|
gdk_surface_real_create_subsurface (GdkSurface *surface)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_surface_constructed (GObject *object)
|
gdk_surface_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -515,6 +521,7 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
|||||||
|
|
||||||
klass->beep = gdk_surface_real_beep;
|
klass->beep = gdk_surface_real_beep;
|
||||||
klass->get_scale = gdk_surface_real_get_scale;
|
klass->get_scale = gdk_surface_real_get_scale;
|
||||||
|
klass->create_subsurface = gdk_surface_real_create_subsurface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GdkSurface:cursor: (attributes org.gtk.Property.get=gdk_surface_get_cursor org.gtk.Property.set=gdk_surface_set_cursor)
|
* GdkSurface:cursor: (attributes org.gtk.Property.get=gdk_surface_get_cursor org.gtk.Property.set=gdk_surface_set_cursor)
|
||||||
@@ -3054,3 +3061,40 @@ gdk_surface_leave_monitor (GdkSurface *surface,
|
|||||||
{
|
{
|
||||||
g_signal_emit (surface, signals[LEAVE_MONITOR], 0, monitor);
|
g_signal_emit (surface, signals[LEAVE_MONITOR], 0, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GdkSubsurface *
|
||||||
|
gdk_surface_create_subsurface (GdkSurface *surface)
|
||||||
|
{
|
||||||
|
return GDK_SURFACE_GET_CLASS (surface)->create_subsurface (surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdk_subsurface_destroy (GdkSubsurface *subsurface)
|
||||||
|
{
|
||||||
|
subsurface->class->destroy (subsurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||||
|
GdkTexture *texture,
|
||||||
|
const graphene_rect_t *bounds)
|
||||||
|
{
|
||||||
|
subsurface->class->attach (subsurface, texture, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If sibling is NULL, place the subsurface above its parent */
|
||||||
|
void
|
||||||
|
gdk_subsurface_place_above (GdkSubsurface *subsurface,
|
||||||
|
GdkSubsurface *sibling)
|
||||||
|
{
|
||||||
|
subsurface->class->place_above (subsurface, sibling);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If sibling is NULL, place the subsurface below its parent */
|
||||||
|
void
|
||||||
|
gdk_subsurface_place_below (GdkSubsurface *subsurface,
|
||||||
|
GdkSubsurface *sibling)
|
||||||
|
{
|
||||||
|
subsurface->class->place_below (subsurface, sibling);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -23,9 +23,14 @@
|
|||||||
#include "gdkenumtypes.h"
|
#include "gdkenumtypes.h"
|
||||||
#include "gdksurface.h"
|
#include "gdksurface.h"
|
||||||
#include "gdktoplevel.h"
|
#include "gdktoplevel.h"
|
||||||
|
#include <graphene.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GdkSubsurface GdkSubsurface;
|
||||||
|
|
||||||
|
typedef struct _GskRenderNode GskRenderNode;
|
||||||
|
|
||||||
struct _GdkSurface
|
struct _GdkSurface
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
@@ -146,6 +151,9 @@ struct _GdkSurfaceClass
|
|||||||
cairo_region_t *region);
|
cairo_region_t *region);
|
||||||
void (* request_layout) (GdkSurface *surface);
|
void (* request_layout) (GdkSurface *surface);
|
||||||
gboolean (* compute_size) (GdkSurface *surface);
|
gboolean (* compute_size) (GdkSurface *surface);
|
||||||
|
|
||||||
|
GdkSubsurface *
|
||||||
|
(* create_subsurface) (GdkSurface *surface);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GDK_SURFACE_DESTROYED(d) (((GdkSurface *)(d))->destroyed)
|
#define GDK_SURFACE_DESTROYED(d) (((GdkSurface *)(d))->destroyed)
|
||||||
@@ -334,7 +342,34 @@ void gdk_surface_request_motion (GdkSurface *surface);
|
|||||||
|
|
||||||
gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface);
|
gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface);
|
||||||
|
|
||||||
|
GdkSubsurface * gdk_surface_create_subsurface (GdkSurface *surface);
|
||||||
|
|
||||||
|
typedef struct _GdkSubsurfaceClass GdkSubsurfaceClass;
|
||||||
|
struct _GdkSubsurfaceClass
|
||||||
|
{
|
||||||
|
void (* destroy) (GdkSubsurface *subsurface);
|
||||||
|
void (* attach) (GdkSubsurface *subsurface,
|
||||||
|
GdkTexture *texture,
|
||||||
|
const graphene_rect_t *bounds);
|
||||||
|
void (* place_above) (GdkSubsurface *subsurface,
|
||||||
|
GdkSubsurface *sibling);
|
||||||
|
void (* place_below) (GdkSubsurface *subsurface,
|
||||||
|
GdkSubsurface *sibling);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GdkSubsurface
|
||||||
|
{
|
||||||
|
const GdkSubsurfaceClass *class;
|
||||||
|
};
|
||||||
|
|
||||||
|
void gdk_subsurface_destroy (GdkSubsurface *subsurface);
|
||||||
|
void gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||||
|
GdkTexture *texture,
|
||||||
|
const graphene_rect_t *bounds);
|
||||||
|
void gdk_subsurface_place_above (GdkSubsurface *subsurface,
|
||||||
|
GdkSubsurface *sibling);
|
||||||
|
void gdk_subsurface_place_below (GdkSubsurface *subsurface,
|
||||||
|
GdkSubsurface *sibling);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_MEMFD_H
|
#ifdef HAVE_LINUX_MEMFD_H
|
||||||
#include <linux/memfd.h>
|
#include <linux/memfd.h>
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
#include <wayland/xdg-foreign-unstable-v1-client-protocol.h>
|
#include <wayland/xdg-foreign-unstable-v1-client-protocol.h>
|
||||||
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
|
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
|
||||||
#include <wayland/server-decoration-client-protocol.h>
|
#include <wayland/server-decoration-client-protocol.h>
|
||||||
|
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
#include "wm-button-layout-translation.h"
|
#include "wm-button-layout-translation.h"
|
||||||
|
|
||||||
@@ -267,45 +269,105 @@ postpone_on_globals_closure (GdkWaylandDisplay *display_wayland,
|
|||||||
g_list_append (display_wayland->on_has_globals_closures, closure);
|
g_list_append (display_wayland->on_has_globals_closures, closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
get_format_name (uint32_t format,
|
|
||||||
char name[10])
|
|
||||||
{
|
|
||||||
if (format == 0)
|
|
||||||
g_strlcpy (name, "ARGB8888", 10);
|
|
||||||
else if (format == 1)
|
|
||||||
g_strlcpy (name, "XRGB8888", 10);
|
|
||||||
else
|
|
||||||
g_snprintf (name, 10, "4cc %c%c%c%c",
|
|
||||||
(char) (format & 0xff),
|
|
||||||
(char) ((format >> 8) & 0xff),
|
|
||||||
(char) ((format >> 16) & 0xff),
|
|
||||||
(char) ((format >> 24) & 0xff));
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_shm_format (void *data,
|
wl_shm_format (void *data,
|
||||||
struct wl_shm *wl_shm,
|
struct wl_shm *wl_shm,
|
||||||
uint32_t format)
|
uint32_t format)
|
||||||
{
|
{
|
||||||
#ifdef G_ENABLE_DEBUG
|
GDK_DEBUG (MISC, "supported shm pixel format %.4s (0x%X)", (char *) &format, format);
|
||||||
char buf[10];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GDK_DEBUG (MISC, "supported pixel format %s (0x%X)",
|
|
||||||
get_format_name (format, buf), (guint) format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_shm_listener wl_shm_listener = {
|
static const struct wl_shm_listener wl_shm_listener = {
|
||||||
wl_shm_format
|
wl_shm_format
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_dmabuf_done (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
|
||||||
|
{
|
||||||
|
GDK_DEBUG (MISC, "dmabuf feedback done");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_dmabuf_format_table (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
|
||||||
|
int32_t fd,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
GdkWaylandDisplay *display_wayland = data;
|
||||||
|
|
||||||
|
display_wayland->linux_dmabuf_n_formats = size / 16;
|
||||||
|
display_wayland->linux_dmabuf_formats = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
|
||||||
|
GDK_DEBUG (MISC, "got dmabuf format table (%lu entries)", display_wayland->linux_dmabuf_n_formats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_dmabuf_main_device (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
|
||||||
|
struct wl_array *device)
|
||||||
|
{
|
||||||
|
dev_t dev = *(dev_t *)device->data;
|
||||||
|
|
||||||
|
GDK_DEBUG (MISC, "got dmabuf main device: %u %u", major (dev), minor (dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_dmabuf_tranche_done (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1)
|
||||||
|
{
|
||||||
|
GDK_DEBUG (MISC, "dmabuf feedback tranche done");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_dmabuf_tranche_target_device (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
|
||||||
|
struct wl_array *device)
|
||||||
|
{
|
||||||
|
dev_t dev = *(dev_t *)device->data;
|
||||||
|
|
||||||
|
GDK_DEBUG (MISC, "got dmabuf tranche target device: %u %u", major (dev), minor (dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_dmabuf_tranche_formats (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
|
||||||
|
struct wl_array *indices)
|
||||||
|
{
|
||||||
|
GdkWaylandDisplay *display_wayland = data;
|
||||||
|
|
||||||
|
GDK_DEBUG (MISC, "got dmabuf tranche formats (%lu entries):", indices->size / sizeof (guint16));
|
||||||
|
guint16 *pos;
|
||||||
|
|
||||||
|
wl_array_for_each (pos, indices)
|
||||||
|
{
|
||||||
|
LinuxDmabufFormat *fmt = &display_wayland->linux_dmabuf_formats[*pos];
|
||||||
|
uint32_t f = fmt->fourcc;
|
||||||
|
uint64_t m = fmt->modifier;
|
||||||
|
GDK_DEBUG (MISC, " %.4s:%#" G_GINT64_MODIFIER "x", (char *) &f, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_dmabuf_tranche_flags (void *data,
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
GDK_DEBUG (MISC,
|
||||||
|
"got dmabuf tranche flags: %s",
|
||||||
|
flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT ? "scanout" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_linux_dmabuf_feedback_v1_listener linux_dmabuf_feedback_listener = {
|
||||||
|
linux_dmabuf_done,
|
||||||
|
linux_dmabuf_format_table,
|
||||||
|
linux_dmabuf_main_device,
|
||||||
|
linux_dmabuf_tranche_done,
|
||||||
|
linux_dmabuf_tranche_target_device,
|
||||||
|
linux_dmabuf_tranche_formats,
|
||||||
|
linux_dmabuf_tranche_flags,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
server_decoration_manager_default_mode (void *data,
|
server_decoration_manager_default_mode (void *data,
|
||||||
struct org_kde_kwin_server_decoration_manager *manager,
|
struct org_kde_kwin_server_decoration_manager *manager,
|
||||||
@@ -382,6 +444,16 @@ gdk_registry_handle_global (void *data,
|
|||||||
wl_registry_bind (display_wayland->wl_registry, id, &wl_shm_interface, 1);
|
wl_registry_bind (display_wayland->wl_registry, id, &wl_shm_interface, 1);
|
||||||
wl_shm_add_listener (display_wayland->shm, &wl_shm_listener, display_wayland);
|
wl_shm_add_listener (display_wayland->shm, &wl_shm_listener, display_wayland);
|
||||||
}
|
}
|
||||||
|
else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0 && version >= 4)
|
||||||
|
{
|
||||||
|
display_wayland->linux_dmabuf =
|
||||||
|
wl_registry_bind (display_wayland->wl_registry, id, &zwp_linux_dmabuf_v1_interface, version);
|
||||||
|
display_wayland->linux_dmabuf_feedback =
|
||||||
|
zwp_linux_dmabuf_v1_get_default_feedback (display_wayland->linux_dmabuf);
|
||||||
|
zwp_linux_dmabuf_feedback_v1_add_listener (display_wayland->linux_dmabuf_feedback,
|
||||||
|
&linux_dmabuf_feedback_listener, display_wayland);
|
||||||
|
_gdk_wayland_display_async_roundtrip (display_wayland);
|
||||||
|
}
|
||||||
else if (strcmp (interface, "xdg_wm_base") == 0)
|
else if (strcmp (interface, "xdg_wm_base") == 0)
|
||||||
{
|
{
|
||||||
display_wayland->xdg_wm_base_id = id;
|
display_wayland->xdg_wm_base_id = id;
|
||||||
@@ -726,6 +798,10 @@ gdk_wayland_display_dispose (GObject *object)
|
|||||||
g_clear_pointer (&display_wayland->xdg_activation, xdg_activation_v1_destroy);
|
g_clear_pointer (&display_wayland->xdg_activation, xdg_activation_v1_destroy);
|
||||||
g_clear_pointer (&display_wayland->fractional_scale, wp_fractional_scale_manager_v1_destroy);
|
g_clear_pointer (&display_wayland->fractional_scale, wp_fractional_scale_manager_v1_destroy);
|
||||||
g_clear_pointer (&display_wayland->viewporter, wp_viewporter_destroy);
|
g_clear_pointer (&display_wayland->viewporter, wp_viewporter_destroy);
|
||||||
|
g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy);
|
||||||
|
g_clear_pointer (&display_wayland->linux_dmabuf_feedback, zwp_linux_dmabuf_feedback_v1_destroy);
|
||||||
|
if (display_wayland->linux_dmabuf_formats)
|
||||||
|
munmap (display_wayland->linux_dmabuf_formats, display_wayland->linux_dmabuf_n_formats * 16);
|
||||||
|
|
||||||
g_clear_pointer (&display_wayland->shm, wl_shm_destroy);
|
g_clear_pointer (&display_wayland->shm, wl_shm_destroy);
|
||||||
g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy);
|
g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy);
|
||||||
|
@@ -71,6 +71,13 @@ typedef enum _GdkWaylandShellVariant
|
|||||||
GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6
|
GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6
|
||||||
} GdkWaylandShellVariant;
|
} GdkWaylandShellVariant;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t fourcc;
|
||||||
|
uint32_t padding;
|
||||||
|
uint64_t modifier;
|
||||||
|
} LinuxDmabufFormat;
|
||||||
|
|
||||||
struct _GdkWaylandDisplay
|
struct _GdkWaylandDisplay
|
||||||
{
|
{
|
||||||
GdkDisplay parent_instance;
|
GdkDisplay parent_instance;
|
||||||
@@ -95,6 +102,10 @@ struct _GdkWaylandDisplay
|
|||||||
struct wl_registry *wl_registry;
|
struct wl_registry *wl_registry;
|
||||||
struct wl_compositor *compositor;
|
struct wl_compositor *compositor;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
|
struct zwp_linux_dmabuf_v1 *linux_dmabuf;
|
||||||
|
struct zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback;
|
||||||
|
gsize linux_dmabuf_n_formats;
|
||||||
|
LinuxDmabufFormat *linux_dmabuf_formats;
|
||||||
struct xdg_wm_base *xdg_wm_base;
|
struct xdg_wm_base *xdg_wm_base;
|
||||||
struct zxdg_shell_v6 *zxdg_shell_v6;
|
struct zxdg_shell_v6 *zxdg_shell_v6;
|
||||||
struct gtk_shell1 *gtk_shell;
|
struct gtk_shell1 *gtk_shell;
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include <gdk/wayland/gdkdisplay-wayland.h>
|
#include <gdk/wayland/gdkdisplay-wayland.h>
|
||||||
#include <gdk/wayland/gdkseat-wayland.h>
|
#include <gdk/wayland/gdkseat-wayland.h>
|
||||||
|
|
||||||
|
#include <gsk/gsk.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -222,4 +223,3 @@ void gdk_wayland_surface_update_scale (GdkSurface *surface);
|
|||||||
|
|
||||||
GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
|
GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
|
||||||
guint32 mods);
|
guint32 mods);
|
||||||
|
|
||||||
|
@@ -86,6 +86,8 @@ struct _GdkWaylandSurface
|
|||||||
uint32_t last_configure_serial;
|
uint32_t last_configure_serial;
|
||||||
|
|
||||||
int state_freeze_count;
|
int state_freeze_count;
|
||||||
|
|
||||||
|
GPtrArray *subsurfaces;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
|
typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
|
||||||
|
@@ -33,9 +33,11 @@
|
|||||||
#include "gdksurfaceprivate.h"
|
#include "gdksurfaceprivate.h"
|
||||||
#include "gdktoplevelprivate.h"
|
#include "gdktoplevelprivate.h"
|
||||||
#include "gdkdevice-wayland-private.h"
|
#include "gdkdevice-wayland-private.h"
|
||||||
|
#include "gdkdmabuftextureprivate.h"
|
||||||
|
|
||||||
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
|
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
|
||||||
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
|
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
|
||||||
|
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -48,6 +50,7 @@
|
|||||||
#include "gdksurface-wayland-private.h"
|
#include "gdksurface-wayland-private.h"
|
||||||
#include "gdktoplevel-wayland-private.h"
|
#include "gdktoplevel-wayland-private.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GdkWaylandSurface:
|
* GdkWaylandSurface:
|
||||||
*
|
*
|
||||||
@@ -154,11 +157,15 @@ wl_region_from_cairo_region (GdkWaylandDisplay *display,
|
|||||||
/* }}} */
|
/* }}} */
|
||||||
/* {{{ Surface implementation */
|
/* {{{ Surface implementation */
|
||||||
|
|
||||||
|
static void gdk_wayland_subsurface_destroy (GdkSubsurface *sub);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_wayland_surface_init (GdkWaylandSurface *impl)
|
gdk_wayland_surface_init (GdkWaylandSurface *impl)
|
||||||
{
|
{
|
||||||
impl->scale = GDK_FRACTIONAL_SCALE_INIT_INT (1);
|
impl->scale = GDK_FRACTIONAL_SCALE_INIT_INT (1);
|
||||||
impl->viewport_dirty = TRUE;
|
impl->viewport_dirty = TRUE;
|
||||||
|
|
||||||
|
impl->subsurfaces = g_ptr_array_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -552,6 +559,7 @@ gdk_wayland_surface_finalize (GObject *object)
|
|||||||
|
|
||||||
g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
|
g_clear_pointer (&impl->opaque_region, cairo_region_destroy);
|
||||||
g_clear_pointer (&impl->input_region, cairo_region_destroy);
|
g_clear_pointer (&impl->input_region, cairo_region_destroy);
|
||||||
|
g_clear_pointer (&impl->subsurfaces, g_ptr_array_unref);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->finalize (object);
|
G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
@@ -1135,6 +1143,17 @@ gdk_wayland_surface_set_input_region (GdkSurface *surface,
|
|||||||
impl->input_region_dirty = TRUE;
|
impl->input_region_dirty = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_wayland_surface_destroy_subsurfaces (GdkWaylandSurface *impl)
|
||||||
|
{
|
||||||
|
for (gsize i = 0; i < impl->subsurfaces->len; i++)
|
||||||
|
{
|
||||||
|
GdkSubsurface *sub = g_ptr_array_index (impl->subsurfaces, i);
|
||||||
|
gdk_subsurface_destroy (sub);
|
||||||
|
}
|
||||||
|
g_ptr_array_set_size (impl->subsurfaces, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_wayland_surface_destroy (GdkSurface *surface,
|
gdk_wayland_surface_destroy (GdkSurface *surface,
|
||||||
gboolean foreign_destroy)
|
gboolean foreign_destroy)
|
||||||
@@ -1151,6 +1170,7 @@ gdk_wayland_surface_destroy (GdkSurface *surface,
|
|||||||
if (GDK_IS_TOPLEVEL (surface))
|
if (GDK_IS_TOPLEVEL (surface))
|
||||||
gdk_wayland_toplevel_destroy (GDK_TOPLEVEL (surface));
|
gdk_wayland_toplevel_destroy (GDK_TOPLEVEL (surface));
|
||||||
|
|
||||||
|
gdk_wayland_surface_destroy_subsurfaces (GDK_WAYLAND_SURFACE (surface));
|
||||||
gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE (surface));
|
gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE (surface));
|
||||||
|
|
||||||
frame_clock = gdk_surface_get_frame_clock (surface);
|
frame_clock = gdk_surface_get_frame_clock (surface);
|
||||||
@@ -1207,6 +1227,8 @@ gdk_wayland_surface_default_hide_surface (GdkWaylandSurface *surface)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GdkSubsurface *gdk_wayland_surface_create_subsurface (GdkSurface *surface);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
|
gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
|
||||||
{
|
{
|
||||||
@@ -1230,6 +1252,7 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
|
|||||||
surface_class->get_scale = gdk_wayland_surface_get_scale;
|
surface_class->get_scale = gdk_wayland_surface_get_scale;
|
||||||
surface_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
|
surface_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
|
||||||
surface_class->request_layout = gdk_wayland_surface_request_layout;
|
surface_class->request_layout = gdk_wayland_surface_request_layout;
|
||||||
|
surface_class->create_subsurface = gdk_wayland_surface_create_subsurface;
|
||||||
|
|
||||||
klass->handle_configure = gdk_wayland_surface_default_handle_configure;
|
klass->handle_configure = gdk_wayland_surface_default_handle_configure;
|
||||||
klass->handle_frame = gdk_wayland_surface_default_handle_frame;
|
klass->handle_frame = gdk_wayland_surface_default_handle_frame;
|
||||||
@@ -1305,4 +1328,236 @@ gdk_wayland_surface_get_wl_surface (GdkSurface *surface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* }}}} */
|
/* }}}} */
|
||||||
|
/* {{{ Subsurface */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GdkSubsurface subsurface;
|
||||||
|
|
||||||
|
GdkWaylandSurface *parent;
|
||||||
|
|
||||||
|
struct wl_surface *wl_surface;
|
||||||
|
struct wl_subsurface *wl_subsurface;
|
||||||
|
struct wp_viewport *wp_viewport;
|
||||||
|
} GdkWaylandSubsurface;
|
||||||
|
|
||||||
|
static void
|
||||||
|
dmabuf_buffer_release (void *data,
|
||||||
|
struct wl_buffer *wl_buffer)
|
||||||
|
{
|
||||||
|
GdkTexture *texture = data;
|
||||||
|
|
||||||
|
g_object_unref (texture);
|
||||||
|
wl_buffer_destroy (wl_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_buffer_listener dmabuf_buffer_listener = {
|
||||||
|
dmabuf_buffer_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct wl_buffer *
|
||||||
|
get_dmabuf_wl_buffer (GdkWaylandSubsurface *self,
|
||||||
|
GdkTexture *texture)
|
||||||
|
{
|
||||||
|
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
|
||||||
|
const GdkDmabuf *dmabuf;
|
||||||
|
struct zwp_linux_buffer_params_v1 *params;
|
||||||
|
struct wl_buffer *wl_buffer;
|
||||||
|
|
||||||
|
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
|
||||||
|
|
||||||
|
params = zwp_linux_dmabuf_v1_create_params (display->linux_dmabuf);
|
||||||
|
|
||||||
|
for (gsize i = 0; i < dmabuf->n_planes; i++)
|
||||||
|
zwp_linux_buffer_params_v1_add (params,
|
||||||
|
dmabuf->planes[i].fd,
|
||||||
|
i,
|
||||||
|
dmabuf->planes[i].offset,
|
||||||
|
dmabuf->planes[i].stride,
|
||||||
|
dmabuf->modifier >> 32,
|
||||||
|
dmabuf->modifier & 0xffffffff);
|
||||||
|
|
||||||
|
wl_buffer = zwp_linux_buffer_params_v1_create_immed (params,
|
||||||
|
gdk_texture_get_width (texture),
|
||||||
|
gdk_texture_get_height (texture),
|
||||||
|
dmabuf->fourcc,
|
||||||
|
0);
|
||||||
|
|
||||||
|
wl_buffer_add_listener (wl_buffer, &dmabuf_buffer_listener, g_object_ref (texture));
|
||||||
|
|
||||||
|
return wl_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shm_buffer_release (void *data,
|
||||||
|
struct wl_buffer *wl_buffer)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface = data;
|
||||||
|
|
||||||
|
/* Note: the wl_buffer is destroyed as cairo user data */
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_buffer_listener shm_buffer_listener = {
|
||||||
|
shm_buffer_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct wl_buffer *
|
||||||
|
get_shm_wl_buffer (GdkWaylandSubsurface *self,
|
||||||
|
GdkTexture *texture)
|
||||||
|
{
|
||||||
|
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self->parent)));
|
||||||
|
int width, height;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
GdkTextureDownloader *downloader;
|
||||||
|
struct wl_buffer *wl_buffer;
|
||||||
|
|
||||||
|
width = gdk_texture_get_width (texture);
|
||||||
|
height = gdk_texture_get_height (texture);
|
||||||
|
surface = gdk_wayland_display_create_shm_surface (display, width, height, &GDK_FRACTIONAL_SCALE_INIT_INT (1));
|
||||||
|
|
||||||
|
downloader = gdk_texture_downloader_new (texture);
|
||||||
|
|
||||||
|
gdk_texture_downloader_download_into (downloader,
|
||||||
|
cairo_image_surface_get_data (surface),
|
||||||
|
cairo_image_surface_get_stride (surface));
|
||||||
|
|
||||||
|
gdk_texture_downloader_free (downloader);
|
||||||
|
|
||||||
|
wl_buffer = _gdk_wayland_shm_surface_get_wl_buffer (surface);
|
||||||
|
wl_buffer_add_listener (wl_buffer, &shm_buffer_listener, surface);
|
||||||
|
|
||||||
|
return wl_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wl_buffer *
|
||||||
|
get_wl_buffer (GdkWaylandSubsurface *self,
|
||||||
|
GdkTexture *texture)
|
||||||
|
{
|
||||||
|
if (GDK_IS_DMABUF_TEXTURE (texture))
|
||||||
|
return get_dmabuf_wl_buffer (self, texture);
|
||||||
|
else
|
||||||
|
return get_shm_wl_buffer (self, texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||||
|
GdkTexture *texture,
|
||||||
|
const graphene_rect_t *rect)
|
||||||
|
{
|
||||||
|
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||||
|
|
||||||
|
GDK_DEBUG (DMABUF,
|
||||||
|
"Attaching texture %p at %f %f %f %f",
|
||||||
|
texture,
|
||||||
|
rect->origin.x, rect->origin.y, rect->size.width, rect->size.height);
|
||||||
|
|
||||||
|
if (rect)
|
||||||
|
{
|
||||||
|
wl_subsurface_set_position (self->wl_subsurface,
|
||||||
|
floorf (rect->origin.x),
|
||||||
|
floorf (rect->origin.y));
|
||||||
|
wp_viewport_set_destination (self->wp_viewport,
|
||||||
|
ceilf (rect->origin.x + rect->size.width) - floorf (rect->origin.x),
|
||||||
|
ceilf (rect->origin.y + rect->size.height) - floorf (rect->origin.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
wl_surface_attach (self->wl_surface, get_wl_buffer (self, texture), 0, 0);
|
||||||
|
wl_surface_damage_buffer (self->wl_surface,
|
||||||
|
0, 0,
|
||||||
|
gdk_texture_get_width (texture),
|
||||||
|
gdk_texture_get_height (texture));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wl_surface_attach (self->wl_surface, NULL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_surface_commit (self->wl_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_wayland_subsurface_destroy (GdkSubsurface *sub)
|
||||||
|
{
|
||||||
|
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||||
|
|
||||||
|
g_clear_pointer (&self->wp_viewport, wp_viewport_destroy);
|
||||||
|
g_clear_pointer (&self->wl_subsurface, wl_subsurface_destroy);
|
||||||
|
g_clear_pointer (&self->wl_surface, wl_surface_destroy);
|
||||||
|
|
||||||
|
g_ptr_array_remove (self->parent->subsurfaces, self);
|
||||||
|
|
||||||
|
g_free (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_wayland_subsurface_place_above (GdkSubsurface *sub,
|
||||||
|
GdkSubsurface *sibling)
|
||||||
|
{
|
||||||
|
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||||
|
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
|
||||||
|
|
||||||
|
g_return_if_fail (sib == NULL || self->parent == sib->parent);
|
||||||
|
|
||||||
|
wl_subsurface_place_above (self->wl_subsurface,
|
||||||
|
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_wayland_subsurface_place_below (GdkSubsurface *sub,
|
||||||
|
GdkSubsurface *sibling)
|
||||||
|
{
|
||||||
|
GdkWaylandSubsurface *self = (GdkWaylandSubsurface *)sub;
|
||||||
|
GdkWaylandSubsurface *sib = (GdkWaylandSubsurface *)sibling;
|
||||||
|
|
||||||
|
g_return_if_fail (sib == NULL || self->parent == sib->parent);
|
||||||
|
|
||||||
|
wl_subsurface_place_below (self->wl_subsurface,
|
||||||
|
sib ? sib->wl_surface : self->parent->display_server.wl_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GdkSubsurfaceClass subsurface_class = {
|
||||||
|
gdk_wayland_subsurface_destroy,
|
||||||
|
gdk_wayland_subsurface_attach,
|
||||||
|
gdk_wayland_subsurface_place_above,
|
||||||
|
gdk_wayland_subsurface_place_below,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GdkSubsurface *
|
||||||
|
gdk_wayland_surface_create_subsurface (GdkSurface *surface)
|
||||||
|
{
|
||||||
|
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||||
|
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||||
|
GdkWaylandSubsurface *sub;
|
||||||
|
struct wl_region *wl_region;
|
||||||
|
|
||||||
|
if (display->viewporter == NULL)
|
||||||
|
{
|
||||||
|
GDK_DEBUG (DMABUF, "Can't use subsurfaces without viewporter");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub = g_new0 (GdkWaylandSubsurface, 1);
|
||||||
|
|
||||||
|
sub->subsurface.class = &subsurface_class;
|
||||||
|
|
||||||
|
sub->parent = impl;
|
||||||
|
g_ptr_array_add (sub->parent->subsurfaces, sub);
|
||||||
|
|
||||||
|
sub->wl_surface = wl_compositor_create_surface (display->compositor);
|
||||||
|
wl_region = wl_compositor_create_region (display->compositor);
|
||||||
|
wl_surface_set_input_region (sub->wl_surface, wl_region);
|
||||||
|
wl_region_destroy (wl_region);
|
||||||
|
sub->wl_subsurface = wl_subcompositor_get_subsurface (display->subcompositor,
|
||||||
|
sub->wl_surface,
|
||||||
|
impl->display_server.wl_surface);
|
||||||
|
sub->wp_viewport = wp_viewporter_get_viewport (display->viewporter, sub->wl_surface);
|
||||||
|
|
||||||
|
GDK_DEBUG (DMABUF, "Subsurface created");
|
||||||
|
|
||||||
|
return (GdkSubsurface *) sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
/* vim:set foldmethod=marker expandtab: */
|
/* vim:set foldmethod=marker expandtab: */
|
||||||
|
@@ -67,6 +67,7 @@ proto_sources = [
|
|||||||
['idle-inhibit', 'unstable', 'v1', ],
|
['idle-inhibit', 'unstable', 'v1', ],
|
||||||
['xdg-activation', 'staging', 'v1', ],
|
['xdg-activation', 'staging', 'v1', ],
|
||||||
['fractional-scale', 'staging', 'v1', ],
|
['fractional-scale', 'staging', 'v1', ],
|
||||||
|
['linux-dmabuf', 'unstable', 'v1', ],
|
||||||
]
|
]
|
||||||
|
|
||||||
gdk_wayland_gen_headers = []
|
gdk_wayland_gen_headers = []
|
||||||
|
@@ -149,3 +149,11 @@ foreach t: gtk_tests
|
|||||||
dependencies: [libgtk_dep, libm],
|
dependencies: [libgtk_dep, libm],
|
||||||
)
|
)
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
executable('testsubsurface',
|
||||||
|
sources: '@0@.c'.format('testsubsurface'),
|
||||||
|
c_args: common_cflags + ['-DGTK_COMPILATION'],
|
||||||
|
dependencies: libgtk_static_dep,
|
||||||
|
install: false,
|
||||||
|
)
|
||||||
|
|
||||||
|
257
tests/testsubsurface.c
Normal file
257
tests/testsubsurface.c
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "gtk/gtkwidgetprivate.h"
|
||||||
|
#include "gdk/gdksurfaceprivate.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <linux/dma-heap.h>
|
||||||
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
|
static int dma_heap_fd = -1;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
initialize_dma_heap (void)
|
||||||
|
{
|
||||||
|
dma_heap_fd = open ("/dev/dma_heap/system", O_RDONLY | O_CLOEXEC);
|
||||||
|
return dma_heap_fd != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
allocate_dma_buf (gsize size)
|
||||||
|
{
|
||||||
|
struct dma_heap_allocation_data heap_data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
heap_data.len = size;
|
||||||
|
heap_data.fd = 0;
|
||||||
|
heap_data.fd_flags = O_RDWR | O_CLOEXEC;
|
||||||
|
heap_data.heap_flags = 0;
|
||||||
|
|
||||||
|
ret = ioctl (dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &heap_data);
|
||||||
|
if (ret)
|
||||||
|
g_error ("dma-buf allocation failed");
|
||||||
|
|
||||||
|
return heap_data.fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_dmabuf (gpointer data)
|
||||||
|
{
|
||||||
|
close (GPOINTER_TO_INT (data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkTexture *
|
||||||
|
make_dmabuf_color_texture (int width,
|
||||||
|
int height,
|
||||||
|
GdkRGBA *color)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
guchar *buf;
|
||||||
|
GdkDmabufTextureBuilder *builder;
|
||||||
|
GdkTexture *texture;
|
||||||
|
gsize stride, size;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
stride = width * 4;
|
||||||
|
size = height * stride;
|
||||||
|
fd = allocate_dma_buf (size);
|
||||||
|
|
||||||
|
buf = mmap (NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
|
||||||
|
for (gsize i = 0; i < width * height * 4; i += 4)
|
||||||
|
{
|
||||||
|
buf[i] = 255 * color->blue;
|
||||||
|
buf[i + 1] = 255 * color->green;
|
||||||
|
buf[i + 2] = 255 * color->red;
|
||||||
|
buf[i + 3] = 255 * color->alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap (buf, size);
|
||||||
|
|
||||||
|
builder = gdk_dmabuf_texture_builder_new ();
|
||||||
|
gdk_dmabuf_texture_builder_set_display (builder, gdk_display_get_default ());
|
||||||
|
gdk_dmabuf_texture_builder_set_width (builder, width);
|
||||||
|
gdk_dmabuf_texture_builder_set_height (builder, height);
|
||||||
|
gdk_dmabuf_texture_builder_set_fourcc (builder, DRM_FORMAT_ARGB8888);
|
||||||
|
gdk_dmabuf_texture_builder_set_modifier (builder, DRM_FORMAT_MOD_LINEAR);
|
||||||
|
gdk_dmabuf_texture_builder_set_n_planes (builder, 1);
|
||||||
|
gdk_dmabuf_texture_builder_set_fd (builder, 0, fd);
|
||||||
|
gdk_dmabuf_texture_builder_set_offset (builder, 0, 0);
|
||||||
|
gdk_dmabuf_texture_builder_set_stride (builder, 0, stride);
|
||||||
|
|
||||||
|
texture = gdk_dmabuf_texture_builder_build (builder, free_dmabuf, GINT_TO_POINTER (fd), &error);
|
||||||
|
if (texture == NULL)
|
||||||
|
g_error ("%s", error->message);
|
||||||
|
|
||||||
|
g_object_unref (builder);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkTexture *
|
||||||
|
make_shm_color_texture (int width,
|
||||||
|
int height,
|
||||||
|
GdkRGBA *color)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_t *cr;
|
||||||
|
guchar *data;
|
||||||
|
gsize stride;
|
||||||
|
GBytes *bytes;
|
||||||
|
GdkTexture *texture;
|
||||||
|
|
||||||
|
stride = 4 * width;
|
||||||
|
data = g_new (guchar, stride * height);
|
||||||
|
|
||||||
|
surface = cairo_image_surface_create_for_data (data,
|
||||||
|
CAIRO_FORMAT_ARGB32,
|
||||||
|
width, height,
|
||||||
|
stride);
|
||||||
|
cr = cairo_create (surface);
|
||||||
|
gdk_cairo_set_source_rgba (cr, color);
|
||||||
|
cairo_paint (cr);
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
|
bytes = g_bytes_new_take (data, stride * height);
|
||||||
|
texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
|
||||||
|
g_bytes_unref (bytes);
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkTexture *
|
||||||
|
make_color_texture (int width,
|
||||||
|
int height,
|
||||||
|
GdkRGBA *color)
|
||||||
|
{
|
||||||
|
if (dma_heap_fd != -1)
|
||||||
|
return make_dmabuf_color_texture (width, height, color);
|
||||||
|
else
|
||||||
|
return make_shm_color_texture (width, height, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkSubsurface *
|
||||||
|
add_subsurface (GtkWidget *window,
|
||||||
|
GdkRGBA *color,
|
||||||
|
const graphene_rect_t *rect)
|
||||||
|
{
|
||||||
|
GdkSurface *surface;
|
||||||
|
GdkSubsurface *subsurface;
|
||||||
|
GdkTexture *texture;
|
||||||
|
|
||||||
|
surface = gtk_widget_get_surface (GTK_WIDGET (window));
|
||||||
|
|
||||||
|
subsurface = gdk_surface_create_subsurface (surface);
|
||||||
|
|
||||||
|
texture = make_color_texture (20, 20, color);
|
||||||
|
|
||||||
|
gdk_subsurface_attach (subsurface, texture, rect);
|
||||||
|
|
||||||
|
g_object_unref (texture);
|
||||||
|
|
||||||
|
return subsurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkSubsurface *red, *blue;
|
||||||
|
|
||||||
|
static void red_above_blue (GtkButton *button) { gdk_subsurface_place_above (red, blue); }
|
||||||
|
static void red_below_blue (GtkButton *button) { gdk_subsurface_place_below (red, blue); }
|
||||||
|
static void blue_above_red (GtkButton *button) { gdk_subsurface_place_above (blue, red); }
|
||||||
|
static void blue_below_red (GtkButton *button) { gdk_subsurface_place_below (blue, red); }
|
||||||
|
static void red_above_main (GtkButton *button) { gdk_subsurface_place_above (red, NULL); }
|
||||||
|
static void red_below_main (GtkButton *button) { gdk_subsurface_place_below (red, NULL); }
|
||||||
|
static void blue_above_main (GtkButton *button) { gdk_subsurface_place_above (blue, NULL); }
|
||||||
|
static void blue_below_main (GtkButton *button) { gdk_subsurface_place_below (blue, NULL); }
|
||||||
|
|
||||||
|
static GtkWidget *
|
||||||
|
make_button (const char *name, gpointer cb)
|
||||||
|
{
|
||||||
|
GtkWidget *button;
|
||||||
|
|
||||||
|
button = gtk_button_new_with_label (name);
|
||||||
|
g_signal_connect (button, "clicked", G_CALLBACK (cb), NULL);
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
change_colors (GtkButton *button)
|
||||||
|
{
|
||||||
|
GdkRGBA color;
|
||||||
|
GdkTexture *texture;
|
||||||
|
|
||||||
|
color.red = g_random_double_range (0.5, 1);
|
||||||
|
color.green = g_random_double_range (0, 0.5);
|
||||||
|
color.blue = g_random_double_range (0, 0.5);
|
||||||
|
color.alpha = 1;
|
||||||
|
|
||||||
|
texture = make_color_texture (20, 20, &color);
|
||||||
|
gdk_subsurface_attach (red, texture, &GRAPHENE_RECT_INIT (200, 100, 50, 50));
|
||||||
|
g_object_unref (texture);
|
||||||
|
|
||||||
|
color.red = g_random_double_range (0, 0.5);
|
||||||
|
color.green = g_random_double_range (0, 0.5);
|
||||||
|
color.blue = g_random_double_range (0.5, 1);
|
||||||
|
color.alpha = 1;
|
||||||
|
|
||||||
|
texture = make_color_texture (20, 20, &color);
|
||||||
|
gdk_subsurface_attach (blue, texture, &GRAPHENE_RECT_INIT (180, 120, 100, 20));
|
||||||
|
g_object_unref (texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget *
|
||||||
|
make_buttons (void)
|
||||||
|
{
|
||||||
|
GtkWidget *box;
|
||||||
|
|
||||||
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Red above blue", red_above_blue));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Red below blue", red_below_blue));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Red above main", red_above_main));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Red below main", red_below_main));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Blue above red", blue_above_red));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Blue below red", blue_below_red));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Blue above main", blue_above_main));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Blue below main", blue_below_main));
|
||||||
|
gtk_box_append (GTK_BOX (box), make_button ("Change colors", change_colors));
|
||||||
|
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GtkWidget *window, *box;
|
||||||
|
|
||||||
|
gtk_init ();
|
||||||
|
|
||||||
|
window = gtk_window_new ();
|
||||||
|
gtk_window_set_default_size (GTK_WINDOW (window), 210, -1);
|
||||||
|
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
||||||
|
|
||||||
|
gtk_widget_realize (window);
|
||||||
|
|
||||||
|
if (initialize_dma_heap ())
|
||||||
|
g_print ("Using dambufs\n");
|
||||||
|
else
|
||||||
|
g_print ("Failed to initialize dma-heap, using shm\n");
|
||||||
|
|
||||||
|
red = add_subsurface (window, &(GdkRGBA) { 1, 0, 0, 1 }, &GRAPHENE_RECT_INIT (200, 100, 50, 50));
|
||||||
|
blue = add_subsurface (window, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (180, 120, 100, 20));
|
||||||
|
|
||||||
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||||
|
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||||
|
|
||||||
|
gtk_box_append (GTK_BOX (box), make_buttons ());
|
||||||
|
|
||||||
|
gtk_window_present (GTK_WINDOW (window));
|
||||||
|
|
||||||
|
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
|
||||||
|
g_main_context_iteration (NULL, TRUE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user