Add background to subsurfaces

Make it possible for subsurfaces to have a black background on a
secondary subsurface below the actual subsurface. Using a single-pixel
buffer for that background increases the changes that the compositor
will use direct scanout for the actual subsurface.

This changes the private subsurface API. All callers have been
updated to pass an empty background rect.
This commit is contained in:
Matthias Clasen 2024-04-13 14:20:01 -04:00
parent a70998aa50
commit 3f9bdaa4c8
9 changed files with 551 additions and 21 deletions

View File

@ -114,6 +114,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
const graphene_rect_t *background,
gboolean above,
GdkSubsurface *sibling)
{
@ -156,7 +157,14 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
}
}
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, source, dest, transform, above, sibling);
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface,
texture,
source,
dest,
transform,
background,
above,
sibling);
}
void
@ -213,3 +221,12 @@ gdk_subsurface_get_transform (GdkSubsurface *subsurface)
return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface);
}
void
gdk_subsurface_get_background (GdkSubsurface *subsurface,
graphene_rect_t *background)
{
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
g_return_if_fail (background != NULL);
GDK_SUBSURFACE_GET_CLASS (subsurface)->get_background (subsurface, background);
}

222
gdk/gdksubsurface.c.orig Normal file
View File

@ -0,0 +1,222 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdksubsurfaceprivate.h"
#include "gdksurfaceprivate.h"
#include "gdktexture.h"
#include "gsk/gskrectprivate.h"
G_DEFINE_TYPE (GdkSubsurface, gdk_subsurface, G_TYPE_OBJECT)
static void
gdk_subsurface_init (GdkSubsurface *self)
{
}
static void
gdk_subsurface_finalize (GObject *object)
{
GdkSubsurface *subsurface = GDK_SUBSURFACE (object);
g_ptr_array_remove (subsurface->parent->subsurfaces, subsurface);
g_clear_object (&subsurface->parent);
G_OBJECT_CLASS (gdk_subsurface_parent_class)->finalize (object);
}
static void
gdk_subsurface_class_init (GdkSubsurfaceClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = gdk_subsurface_finalize;
}
GdkSurface *
gdk_subsurface_get_parent (GdkSubsurface *subsurface)
{
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), NULL);
return subsurface->parent;
}
static void
remove_subsurface (GdkSubsurface *subsurface)
{
GdkSurface *parent = subsurface->parent;
if (parent->subsurfaces_above == subsurface)
parent->subsurfaces_above = subsurface->sibling_above;
if (parent->subsurfaces_below == subsurface)
parent->subsurfaces_below = subsurface->sibling_below;
if (subsurface->sibling_above)
subsurface->sibling_above->sibling_below = subsurface->sibling_below;
if (subsurface->sibling_below)
subsurface->sibling_below->sibling_above = subsurface->sibling_above;
subsurface->sibling_above = NULL;
subsurface->sibling_below = NULL;
}
static void
insert_subsurface (GdkSubsurface *subsurface,
gboolean above,
GdkSubsurface *sibling)
{
GdkSurface *parent = subsurface->parent;
subsurface->above_parent = sibling->above_parent;
if (above)
{
subsurface->sibling_above = sibling->sibling_above;
sibling->sibling_above = subsurface;
subsurface->sibling_below = sibling;
if (subsurface->sibling_above)
subsurface->sibling_above->sibling_below = subsurface;
if (parent->subsurfaces_below == sibling)
parent->subsurfaces_below = subsurface;
}
else
{
subsurface->sibling_below = sibling->sibling_below;
sibling->sibling_below = subsurface;
subsurface->sibling_above = sibling;
if (subsurface->sibling_below)
subsurface->sibling_below->sibling_above = subsurface;
if (parent->subsurfaces_above == sibling)
parent->subsurfaces_above = subsurface;
}
}
gboolean
gdk_subsurface_attach (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
const graphene_rect_t *background,
gboolean above,
GdkSubsurface *sibling)
{
GdkSurface *parent = subsurface->parent;
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), FALSE);
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
g_return_val_if_fail (source != NULL &&
gsk_rect_contains_rect (&GRAPHENE_RECT_INIT (0, 0,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture)),
source), FALSE);
g_return_val_if_fail (dest != NULL, FALSE);
g_return_val_if_fail (sibling != subsurface, FALSE);
g_return_val_if_fail (sibling == NULL || GDK_IS_SUBSURFACE (sibling), FALSE);
g_return_val_if_fail (sibling == NULL || sibling->parent == subsurface->parent, FALSE);
remove_subsurface (subsurface);
if (sibling)
{
insert_subsurface (subsurface, above, sibling);
}
else
{
sibling = above ? parent->subsurfaces_above : parent->subsurfaces_below;
if (sibling)
{
insert_subsurface (subsurface, !above, sibling);
}
else
{
subsurface->above_parent = above;
if (above)
parent->subsurfaces_above = subsurface;
else
parent->subsurfaces_below = subsurface;
}
}
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface,
texture,
source,
dest,
transform,
background,
above,
sibling);
}
void
gdk_subsurface_detach (GdkSubsurface *subsurface)
{
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
remove_subsurface (subsurface);
GDK_SUBSURFACE_GET_CLASS (subsurface)->detach (subsurface);
}
GdkTexture *
gdk_subsurface_get_texture (GdkSubsurface *subsurface)
{
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), NULL);
return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_texture (subsurface);
}
void
gdk_subsurface_get_source (GdkSubsurface *subsurface,
graphene_rect_t *source)
{
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
g_return_if_fail (source != NULL);
GDK_SUBSURFACE_GET_CLASS (subsurface)->get_source (subsurface, source);
}
void
gdk_subsurface_get_dest (GdkSubsurface *subsurface,
graphene_rect_t *dest)
{
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
g_return_if_fail (dest != NULL);
GDK_SUBSURFACE_GET_CLASS (subsurface)->get_dest (subsurface, dest);
}
gboolean
gdk_subsurface_is_above_parent (GdkSubsurface *subsurface)
{
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), TRUE);
return subsurface->above_parent;
}
GdkTextureTransform
gdk_subsurface_get_transform (GdkSubsurface *subsurface)
{
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), GDK_TEXTURE_TRANSFORM_NORMAL);
return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface);
}

16
gdk/gdksubsurface.c.rej Normal file
View File

@ -0,0 +1,16 @@
--- gdk/gdksubsurface.c
+++ gdk/gdksubsurface.c
@@ -213,3 +213,13 @@ gdk_subsurface_get_transform (GdkSubsurface *subsurface)
return GDK_SUBSURFACE_GET_CLASS (subsurface)->get_transform (subsurface);
}
+void
+gdk_subsurface_get_background (GdkSubsurface *subsurface,
+ graphene_rect_t *background)
+{
+ g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
+ g_return_if_fail (background != NULL);
+
+ GDK_SUBSURFACE_GET_CLASS (subsurface)->get_background (subsurface, background);
+}
+

View File

@ -67,6 +67,7 @@ struct _GdkSubsurfaceClass
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
const graphene_rect_t *bg,
gboolean above,
GdkSubsurface *sibling);
void (* detach) (GdkSubsurface *subsurface);
@ -77,6 +78,8 @@ struct _GdkSubsurfaceClass
graphene_rect_t *dest);
GdkTextureTransform
(* get_transform) (GdkSubsurface *subsurface);
void (* get_background) (GdkSubsurface *subsurface,
graphene_rect_t *background);
};
GType gdk_subsurface_get_type (void) G_GNUC_CONST;
@ -88,6 +91,7 @@ gboolean gdk_subsurface_attach (GdkSubsurface *subsurfac
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
const graphene_rect_t *background,
gboolean above,
GdkSubsurface *sibling);
void gdk_subsurface_detach (GdkSubsurface *subsurface);
@ -95,10 +99,12 @@ GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurfac
void gdk_subsurface_get_source (GdkSubsurface *subsurface,
graphene_rect_t *source);
void gdk_subsurface_get_dest (GdkSubsurface *subsurface,
graphene_rect_t *dest);
graphene_rect_t *dest);
gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface);
GdkTextureTransform
gdk_subsurface_get_transform (GdkSubsurface *subsurface);
void gdk_subsurface_get_background (GdkSubsurface *subsurface,
graphene_rect_t *background);
G_END_DECLS

View File

@ -0,0 +1,107 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2023 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Uninstalled header defining types and functions internal to GDK */
#pragma once
#include "gdkenumtypes.h"
#include "gdksurface.h"
#include <graphene.h>
G_BEGIN_DECLS
typedef struct _GdkSubsurface GdkSubsurface;
typedef struct _GdkSubsurfaceClass GdkSubsurfaceClass;
#define GDK_TYPE_SUBSURFACE (gdk_subsurface_get_type ())
#define GDK_SUBSURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SUBSURFACE, GdkSubsurface))
#define GDK_SUBSURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SUBSURFACE, GdkSubsurfaceClass))
#define GDK_IS_SUBSURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SUBSURFACE))
#define GDK_SUBSURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SUBSURFACE, GdkSubsurfaceClass))
struct _GdkSubsurface
{
GObject parent_instance;
GdkSurface *parent;
int ref_count;
gboolean above_parent;
GdkSubsurface *sibling_above;
GdkSubsurface *sibling_below;
};
typedef enum {
GDK_TEXTURE_TRANSFORM_NORMAL,
GDK_TEXTURE_TRANSFORM_90,
GDK_TEXTURE_TRANSFORM_180,
GDK_TEXTURE_TRANSFORM_270,
GDK_TEXTURE_TRANSFORM_FLIPPED,
GDK_TEXTURE_TRANSFORM_FLIPPED_90,
GDK_TEXTURE_TRANSFORM_FLIPPED_180,
GDK_TEXTURE_TRANSFORM_FLIPPED_270,
} GdkTextureTransform;
struct _GdkSubsurfaceClass
{
GObjectClass parent_class;
gboolean (* attach) (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
const graphene_rect_t *bg,
gboolean above,
GdkSubsurface *sibling);
void (* detach) (GdkSubsurface *subsurface);
GdkTexture * (* get_texture) (GdkSubsurface *subsurface);
void (* get_source) (GdkSubsurface *subsurface,
graphene_rect_t *source);
void (* get_dest) (GdkSubsurface *subsurface,
graphene_rect_t *dest);
GdkTextureTransform
(* get_transform) (GdkSubsurface *subsurface);
};
GType gdk_subsurface_get_type (void) G_GNUC_CONST;
GdkSurface * gdk_subsurface_get_parent (GdkSubsurface *subsurface);
gboolean gdk_subsurface_attach (GdkSubsurface *subsurface,
GdkTexture *texture,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
const graphene_rect_t *background,
gboolean above,
GdkSubsurface *sibling);
void gdk_subsurface_detach (GdkSubsurface *subsurface);
GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurface);
void gdk_subsurface_get_source (GdkSubsurface *subsurface,
graphene_rect_t *source);
void gdk_subsurface_get_dest (GdkSubsurface *subsurface,
graphene_rect_t *dest);
gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface);
GdkTextureTransform
gdk_subsurface_get_transform (GdkSubsurface *subsurface);
G_END_DECLS

View File

@ -29,6 +29,12 @@ struct _GdkWaylandSubsurface
struct wl_region *opaque_region;
struct wl_callback *frame_callback;
struct wl_surface *bg_surface;
struct wl_subsurface *bg_subsurface;
struct wp_viewport *bg_viewport;
cairo_rectangle_int_t bg_rect;
gboolean bg_attached;
};
struct _GdkWaylandSubsurfaceClass

View File

@ -25,6 +25,8 @@
#include "gdkdmabuftextureprivate.h"
#include "gdksurface-wayland-private.h"
#include "gdksubsurfaceprivate.h"
#include "gdkdebugprivate.h"
#include "gsk/gskrectprivate.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h"
@ -46,6 +48,9 @@ gdk_wayland_subsurface_finalize (GObject *object)
g_clear_pointer (&self->viewport, wp_viewport_destroy);
g_clear_pointer (&self->subsurface, wl_subsurface_destroy);
g_clear_pointer (&self->surface, wl_surface_destroy);
g_clear_pointer (&self->bg_viewport, wp_viewport_destroy);
g_clear_pointer (&self->bg_subsurface, wl_subsurface_destroy);
g_clear_pointer (&self->bg_surface, wl_surface_destroy);
G_OBJECT_CLASS (gdk_wayland_subsurface_parent_class)->finalize (object);
}
@ -209,6 +214,33 @@ get_wl_buffer (GdkWaylandSubsurface *self,
return buffer;
}
static void
sp_buffer_release (void *data,
struct wl_buffer *buffer)
{
wl_buffer_destroy (buffer);
}
static const struct wl_buffer_listener sp_buffer_listener = {
sp_buffer_release,
};
static struct wl_buffer *
get_sp_buffer (GdkWaylandSubsurface *self)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SUBSURFACE (self)->parent));
struct wl_buffer *buffer = NULL;
if (display->single_pixel_buffer)
buffer = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (display->single_pixel_buffer,
0, 0, 0, 0xffffffffU);
if (buffer)
wl_buffer_add_listener (buffer, &sp_buffer_listener, self);
return buffer;
}
static inline enum wl_output_transform
gdk_texture_transform_to_wl (GdkTextureTransform transform)
{
@ -221,12 +253,59 @@ wl_output_transform_to_gdk (enum wl_output_transform transform)
return (GdkTextureTransform) transform;
}
static void
ensure_bg_surface (GdkWaylandSubsurface *self)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (GDK_SUBSURFACE (self)->parent);
GdkDisplay *display = gdk_surface_get_display (GDK_SUBSURFACE (self)->parent);
GdkWaylandDisplay *disp = GDK_WAYLAND_DISPLAY (display);
struct wl_region *region;
if (self->bg_surface)
return;
self->bg_surface = wl_compositor_create_surface (disp->compositor);
self->bg_subsurface = wl_subcompositor_get_subsurface (disp->subcompositor,
self->bg_surface,
impl->display_server.wl_surface);
self->bg_viewport = wp_viewporter_get_viewport (disp->viewporter, self->bg_surface);
/* We are opaque */
wl_surface_set_opaque_region (self->bg_surface, self->opaque_region);
/* No input, please */
region = wl_compositor_create_region (disp->compositor);
wl_surface_set_input_region (self->bg_surface, region);
wl_region_destroy (region);
}
static inline gboolean
scaled_rect_is_integral (const graphene_rect_t *rect,
float scale,
graphene_rect_t *device_rect)
{
cairo_rectangle_int_t device_int;
gsk_rect_scale (rect, scale, scale, device_rect);
device_int.x = device_rect->origin.x;
device_int.y = device_rect->origin.y;
device_int.width = device_rect->size.width;
device_int.height = device_rect->size.height;
return device_int.x == device_rect->origin.x &&
device_int.y == device_rect->origin.y &&
device_int.width == device_rect->size.width &&
device_int.height == device_rect->size.height;
}
static gboolean
gdk_wayland_subsurface_attach (GdkSubsurface *sub,
GdkTexture *texture,
const graphene_rect_t *source,
const graphene_rect_t *dest,
GdkTextureTransform transform,
const graphene_rect_t *background,
gboolean above,
GdkSubsurface *sibling)
{
@ -238,7 +317,7 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
gboolean will_be_above;
double scale;
graphene_rect_t device_rect;
cairo_rectangle_int_t device_dest;
gboolean has_background;
if (sibling)
will_be_above = sibling->above_parent;
@ -265,15 +344,22 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
scale = gdk_fractional_scale_to_double (&parent->scale);
device_rect.origin.x = dest->origin.x * scale;
device_rect.origin.y = dest->origin.y * scale;
device_rect.size.width = dest->size.width * scale;
device_rect.size.height = dest->size.height * scale;
if (background)
{
self->bg_rect.x = background->origin.x;
self->bg_rect.y = background->origin.y;
self->bg_rect.width = background->size.width;
self->bg_rect.height = background->size.height;
}
else
{
self->bg_rect.x = 0;
self->bg_rect.y = 0;
self->bg_rect.width = 0;
self->bg_rect.height = 0;
}
device_dest.x = device_rect.origin.x;
device_dest.y = device_rect.origin.y;
device_dest.width = device_rect.size.width;
device_dest.height = device_rect.size.height;
has_background = self->bg_rect.width > 0 && self->bg_rect.height > 0;
if (self->dest.x != dest->origin.x ||
self->dest.y != dest->origin.y ||
@ -288,15 +374,21 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
gdk_texture_get_height (texture),
self);
}
else if (device_dest.x != device_rect.origin.x ||
device_dest.y != device_rect.origin.y ||
device_dest.width != device_rect.size.width ||
device_dest.height != device_rect.size.height)
else if (!scaled_rect_is_integral (dest, scale, &device_rect))
{
GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD,
"Non-integral device coordinates %g %g %g %g (fractional scale %.2f), hiding subsurface %p",
device_rect.origin.x, device_rect.origin.y,
device_rect.size.width, device_rect.size.width,
device_rect.size.width, device_rect.size.height,
scale,
self);
}
else if (background && !scaled_rect_is_integral (background, scale, &device_rect))
{
GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD,
"Non-integral background device coordinates %g %g %g %g (fractional scale %.2f), hiding background of subsurface %p",
device_rect.origin.x, device_rect.origin.y,
device_rect.size.width, device_rect.size.height,
scale,
self);
}
@ -397,6 +489,38 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
}
if (has_background)
{
ensure_bg_surface (self);
if (self->bg_surface)
{
wl_subsurface_set_position (self->bg_subsurface, self->bg_rect.x, self->bg_rect.y);
wp_viewport_set_destination (self->bg_viewport, self->bg_rect.width, self->bg_rect.height);
wp_viewport_set_source (self->bg_viewport,
wl_fixed_from_int (0),
wl_fixed_from_int (0),
wl_fixed_from_int (1),
wl_fixed_from_int (1));
if (!self->bg_attached)
{
self->bg_attached = TRUE;
wl_surface_attach (self->bg_surface, get_sp_buffer (self), 0, 0);
wl_surface_damage_buffer (self->bg_surface, 0, 0, 1, 1);
}
}
}
else
{
if (self->bg_surface && self->bg_attached)
{
self->bg_attached = FALSE;
wl_surface_attach (self->bg_surface, NULL, 0, 0);
}
}
result = TRUE;
}
else
@ -404,6 +528,11 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
g_set_object (&self->texture, NULL);
wl_surface_attach (self->surface, NULL, 0, 0);
if (self->bg_surface)
{
self->bg_attached = FALSE;
wl_surface_attach (self->bg_surface, NULL, 0, 0);
}
}
if (sib)
@ -423,7 +552,12 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
GDK_WAYLAND_SURFACE (sub->parent)->display_server.wl_surface);
}
if (self->bg_attached)
wl_subsurface_place_below (self->bg_subsurface, self->surface);
wl_surface_commit (self->surface);
if (self->bg_surface)
wl_surface_commit (self->bg_surface);
((GdkWaylandSurface *)sub->parent)->has_pending_subsurface_commits = TRUE;
GDK_WAYLAND_SURFACE (sub->parent)->opaque_region_dirty = TRUE;
@ -447,6 +581,13 @@ gdk_wayland_subsurface_detach (GdkSubsurface *sub)
wl_surface_set_opaque_region (self->surface, self->opaque_region);
wl_surface_commit (self->surface);
if (self->bg_attached)
{
wl_surface_attach (self->bg_surface, NULL, 0, 0);
wl_surface_commit (self->bg_surface);
self->bg_attached = FALSE;
}
((GdkWaylandSurface *)sub->parent)->has_pending_subsurface_commits = TRUE;
GDK_WAYLAND_SURFACE (sub->parent)->opaque_region_dirty = TRUE;
}
@ -491,6 +632,18 @@ gdk_wayland_subsurface_get_transform (GdkSubsurface *sub)
return wl_output_transform_to_gdk (self->transform);
}
static void
gdk_wayland_subsurface_get_background (GdkSubsurface *sub,
graphene_rect_t *background)
{
GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub);
background->origin.x = self->bg_rect.x;
background->origin.y = self->bg_rect.y;
background->size.width = self->bg_rect.width;
background->size.height = self->bg_rect.height;
}
static void
gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
{
@ -505,6 +658,7 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
subsurface_class->get_source = gdk_wayland_subsurface_get_source;
subsurface_class->get_dest = gdk_wayland_subsurface_get_dest;
subsurface_class->get_transform = gdk_wayland_subsurface_get_transform;
subsurface_class->get_background = gdk_wayland_subsurface_get_background;
};
static void

View File

@ -691,6 +691,7 @@ gsk_offload_new (GdkSurface *surface,
&info->source,
&info->dest,
info->transform,
&GRAPHENE_RECT_INIT (0, 0, 0, 0),
TRUE, NULL);
else
info->is_offloaded = gdk_subsurface_attach (info->subsurface,
@ -698,6 +699,7 @@ gsk_offload_new (GdkSurface *surface,
&info->source,
&info->dest,
info->transform,
&GRAPHENE_RECT_INIT (0, 0, 0, 0),
info->place_above != NULL,
info->place_above);
}

View File

@ -42,9 +42,9 @@ test_subsurface_stacking (void)
texture = gdk_texture_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/media-eject.png");
gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, NULL);
gdk_subsurface_attach (sub0, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, NULL);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, NULL);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, NULL);
g_assert_true (surface->subsurfaces_above == sub2);
g_assert_true (sub2->sibling_below == NULL);
@ -67,7 +67,7 @@ test_subsurface_stacking (void)
g_assert_true (sub0->sibling_above == NULL);
g_assert_true (sub0->above_parent);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, FALSE, NULL);
gdk_subsurface_attach (sub2, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, FALSE, NULL);
g_assert_true (surface->subsurfaces_above == sub0);
g_assert_true (sub0->sibling_below == NULL);
@ -79,7 +79,7 @@ test_subsurface_stacking (void)
g_assert_true (sub2->sibling_above == NULL);
g_assert_false (sub2->above_parent);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, TRUE, sub2);
gdk_subsurface_attach (sub1, texture, &TEXTURE_RECT (texture), &GRAPHENE_RECT_INIT (0, 0, 10, 10), GDK_TEXTURE_TRANSFORM_NORMAL, NULL, TRUE, sub2);
g_assert_true (surface->subsurfaces_below == sub1);
g_assert_true (sub1->sibling_above == NULL);