From 4aac0760b32ad122e9b9c2a31f05e9cb642e900e Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 17 Apr 2018 23:05:41 +0200 Subject: [PATCH] wayland: Rewrite Cairo rendering Also, split it into its own file - which was the original reason for looking at this code, the rewrite was an unintentional side effect. This changes the context to create surfaces on demand. So whenever the compositor holds onto a surface while GDK wants to render, it just creates a new surface. If the compositor releases surfaces, we will retain one for the next frame to be rendered, but free all extra ones. This way, we should get to a stage where we have exactly as many surfaces as needed and never allocate/free any. --- gdk/wayland/gdkcairocontext-wayland.c | 219 ++++++++++++++++++++- gdk/wayland/gdkcairocontext-wayland.h | 4 + gdk/wayland/gdkprivate-wayland.h | 3 + gdk/wayland/gdksurface-wayland.c | 269 ++------------------------ 4 files changed, 238 insertions(+), 257 deletions(-) diff --git a/gdk/wayland/gdkcairocontext-wayland.c b/gdk/wayland/gdkcairocontext-wayland.c index f5ee327543..fe4237f63d 100644 --- a/gdk/wayland/gdkcairocontext-wayland.c +++ b/gdk/wayland/gdkcairocontext-wayland.c @@ -18,15 +18,230 @@ #include "config.h" -#include "gdkconfig.h" - #include "gdkcairocontext-wayland.h" +#include "gdkprivate-wayland.h" + +#include "gdkinternals.h" + +static const cairo_user_data_key_t gdk_wayland_cairo_context_key; +static const cairo_user_data_key_t gdk_wayland_cairo_region_key; + G_DEFINE_TYPE (GdkWaylandCairoContext, gdk_wayland_cairo_context, GDK_TYPE_CAIRO_CONTEXT) +static void +gdk_wayland_cairo_context_surface_add_region (cairo_surface_t *surface, + const cairo_region_t *region) +{ + cairo_region_t *surface_region; + + surface_region = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_region_key); + if (surface_region == NULL) + { + surface_region = cairo_region_copy (region); + cairo_surface_set_user_data (surface, + &gdk_wayland_cairo_region_key, + surface_region, + (cairo_destroy_func_t) cairo_region_destroy); + } + else + { + cairo_region_union (surface_region, region); + } +} + +static void +gdk_wayland_cairo_context_surface_clear_region (cairo_surface_t *surface) +{ + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_region_key, NULL, NULL); +} + +static const cairo_region_t * +gdk_wayland_cairo_context_surface_get_region (cairo_surface_t *surface) +{ + return cairo_surface_get_user_data (surface, &gdk_wayland_cairo_region_key); +} + +static GdkWaylandCairoContext * +gdk_wayland_cairo_context_get_from_surface (cairo_surface_t *surface) +{ + return cairo_surface_get_user_data (surface, &gdk_wayland_cairo_context_key); +} + +static void +gdk_wayland_cairo_context_add_surface (GdkWaylandCairoContext *self, + cairo_surface_t *surface) +{ + cairo_surface_reference (surface); + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_context_key, self, NULL); + + self->surfaces = g_slist_prepend (self->surfaces, surface); +} + +static void +gdk_wayland_cairo_context_remove_surface (GdkWaylandCairoContext *self, + cairo_surface_t *surface) +{ + self->surfaces = g_slist_remove (self->surfaces, surface); + + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_context_key, NULL, NULL); + cairo_surface_destroy (surface); +} + +static void +gdk_wayland_cairo_context_buffer_release (void *_data, + struct wl_buffer *wl_buffer) +{ + cairo_surface_t *cairo_surface = _data; + GdkWaylandCairoContext *self = gdk_wayland_cairo_context_get_from_surface (cairo_surface); + + /* context was destroyed before compositor released this buffer */ + if (self == NULL) + return; + + /* Cache one surface for reuse when drawing */ + if (self->cached_surface == NULL) + { + self->cached_surface = cairo_surface; + return; + } + + /* Get rid of all the extra ones */ + gdk_wayland_cairo_context_remove_surface (self, cairo_surface); +} + +static const struct wl_buffer_listener buffer_listener = { + gdk_wayland_cairo_context_buffer_release +}; + +static cairo_surface_t * +gdk_wayland_cairo_context_create_surface (GdkWaylandCairoContext *self) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self))); + GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self)); + cairo_surface_t *cairo_surface; + struct wl_buffer *buffer; + cairo_region_t *region; + int width, height; + + width = gdk_surface_get_width (surface); + height = gdk_surface_get_height (surface); + cairo_surface = _gdk_wayland_display_create_shm_surface (display_wayland, + width, height, + gdk_surface_get_scale_factor (surface)); + buffer = _gdk_wayland_shm_surface_get_wl_buffer (cairo_surface); + wl_buffer_add_listener (buffer, &buffer_listener, cairo_surface); + gdk_wayland_cairo_context_add_surface (self, cairo_surface); + + region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { 0, 0, width, height }); + gdk_wayland_cairo_context_surface_add_region (cairo_surface, region); + cairo_region_destroy (region); + + return cairo_surface; +} + +static void +gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context, + cairo_region_t *region) +{ + GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context); + const cairo_region_t *surface_region; + GSList *l; + cairo_t *cr; + + if (self->cached_surface) + self->paint_surface = g_steal_pointer (&self->cached_surface); + else + self->paint_surface = gdk_wayland_cairo_context_create_surface (self); + + surface_region = gdk_wayland_cairo_context_surface_get_region (self->paint_surface); + if (surface_region) + cairo_region_union (region, surface_region); + + for (l = self->surfaces; l; l = l->next) + { + gdk_wayland_cairo_context_surface_add_region (l->data, region); + } + + /* clear the repaint area */ + cr = cairo_create (self->paint_surface); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + gdk_cairo_region (cr, region); + cairo_fill (cr); + cairo_destroy (cr); +} + +static void +gdk_wayland_cairo_context_end_frame (GdkDrawContext *draw_context, + cairo_region_t *painted, + cairo_region_t *damage) +{ + GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context); + GdkSurface *surface = gdk_draw_context_get_surface (draw_context); + + gdk_wayland_surface_attach_image (surface, self->paint_surface, painted); + gdk_wayland_surface_sync (surface); + + gdk_wayland_cairo_context_surface_clear_region (self->paint_surface); + self->paint_surface = NULL; +} + +static void +gdk_wayland_cairo_context_clear_all_cairo_surfaces (GdkWaylandCairoContext *self) +{ + self->cached_surface = NULL; + while (self->surfaces) + gdk_wayland_cairo_context_remove_surface (self, self->surfaces->data); +} + +static void +gdk_wayland_cairo_context_surface_resized (GdkDrawContext *draw_context) +{ + GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (draw_context); + + gdk_wayland_cairo_context_clear_all_cairo_surfaces (self); +} + +static cairo_t * +gdk_wayland_cairo_context_cairo_create (GdkCairoContext *context) +{ + GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (context); + cairo_t *cr; + + if (self->paint_surface == NULL) + return NULL; + + cr = cairo_create (self->paint_surface); + gdk_cairo_region (cr, gdk_wayland_cairo_context_surface_get_region (self->paint_surface)); + cairo_clip (cr); + + return cr; +} + +static void +gdk_wayland_cairo_context_dispose (GObject *object) +{ + GdkWaylandCairoContext *self = GDK_WAYLAND_CAIRO_CONTEXT (object); + + gdk_wayland_cairo_context_clear_all_cairo_surfaces (self); + + G_OBJECT_CLASS (gdk_wayland_cairo_context_parent_class)->dispose (object); +} + static void gdk_wayland_cairo_context_class_init (GdkWaylandCairoContextClass *klass) { + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass); + GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass); + + gobject_class->dispose = gdk_wayland_cairo_context_dispose; + + draw_context_class->begin_frame = gdk_wayland_cairo_context_begin_frame; + draw_context_class->end_frame = gdk_wayland_cairo_context_end_frame; + draw_context_class->surface_resized = gdk_wayland_cairo_context_surface_resized; + + cairo_context_class->cairo_create = gdk_wayland_cairo_context_cairo_create; } static void diff --git a/gdk/wayland/gdkcairocontext-wayland.h b/gdk/wayland/gdkcairocontext-wayland.h index 278415dded..1cad7a6547 100644 --- a/gdk/wayland/gdkcairocontext-wayland.h +++ b/gdk/wayland/gdkcairocontext-wayland.h @@ -38,6 +38,10 @@ typedef struct _GdkWaylandCairoContextClass GdkWaylandCairoContextClass; struct _GdkWaylandCairoContext { GdkCairoContext parent_instance; + + GSList *surfaces; + cairo_surface_t *cached_surface; + cairo_surface_t *paint_surface; }; struct _GdkWaylandCairoContextClass diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 8de1b63831..db1c916264 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -90,6 +90,9 @@ guint _gdk_wayland_cursor_get_next_image_index (GdkWaylandDisplay *display, void gdk_wayland_surface_sync (GdkSurface *surface); void gdk_wayland_surface_request_frame (GdkSurface *surface); +void gdk_wayland_surface_attach_image (GdkSurface *surface, + cairo_surface_t *cairo_surface, + const cairo_region_t *damage); void _gdk_wayland_surface_register_dnd (GdkSurface *surface); GdkDragContext *_gdk_wayland_surface_drag_begin (GdkSurface *surface, diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c index 7823589938..f774ad13dd 100644 --- a/gdk/wayland/gdksurface-wayland.c +++ b/gdk/wayland/gdksurface-wayland.c @@ -123,7 +123,6 @@ struct _GdkSurfaceImplWayland unsigned int initial_configure_received : 1; unsigned int mapped : 1; unsigned int use_custom_surface : 1; - unsigned int pending_buffer_attached : 1; unsigned int pending_commit : 1; unsigned int awaiting_frame : 1; GdkSurfaceTypeHint hint; @@ -131,10 +130,6 @@ struct _GdkSurfaceImplWayland GdkSurface *popup_parent; PositionMethod position_method; - cairo_surface_t *staging_cairo_surface; - cairo_surface_t *committed_cairo_surface; - cairo_surface_t *backfill_cairo_surface; - int pending_buffer_offset_x; int pending_buffer_offset_y; @@ -173,8 +168,6 @@ struct _GdkSurfaceImplWayland cairo_region_t *input_region; gboolean input_region_dirty; - cairo_region_t *staged_updates_region; - int saved_width; int saved_height; @@ -262,20 +255,6 @@ _gdk_wayland_screen_add_orphan_dialog (GdkSurface *surface) g_list_prepend (display_wayland->orphan_dialogs, surface); } -static void -drop_cairo_surfaces (GdkSurface *surface) -{ - GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl); - - g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy); - g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy); - - /* We nullify this so if a buffer release comes in later, we won't - * try to reuse that buffer since it's no longer suitable - */ - impl->committed_cairo_surface = NULL; -} - static void _gdk_wayland_surface_save_size (GdkSurface *surface) { @@ -320,8 +299,6 @@ gdk_wayland_surface_update_size (GdkSurface *surface, (impl->scale == scale)) return; - drop_cairo_surfaces (surface); - surface->width = width; surface->height = height; impl->scale = scale; @@ -392,37 +369,6 @@ fill_presentation_time_from_frame_time (GdkFrameTimings *timings, } } -static void -read_back_cairo_surface (GdkSurface *surface) -{ - GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl); - cairo_t *cr; - cairo_region_t *paint_region = NULL; - - if (!impl->backfill_cairo_surface) - goto out; - - paint_region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { 0, 0, surface->width, surface->height }); - cairo_region_subtract (paint_region, impl->staged_updates_region); - - if (cairo_region_is_empty (paint_region)) - goto out; - - cr = cairo_create (impl->staging_cairo_surface); - cairo_set_source_surface (cr, impl->backfill_cairo_surface, 0, 0); - gdk_cairo_region (cr, paint_region); - cairo_clip (cr); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - cairo_destroy (cr); - cairo_surface_flush (impl->staging_cairo_surface); - -out: - g_clear_pointer (&paint_region, cairo_region_destroy); - g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy); - g_clear_pointer (&impl->backfill_cairo_surface, cairo_surface_destroy); -} - static void frame_callback (void *data, struct wl_callback *callback, @@ -544,12 +490,6 @@ on_frame_clock_after_paint (GdkFrameClock *clock, gdk_wayland_surface_request_frame (surface); - /* Before we commit a new buffer, make sure we've backfilled - * undrawn parts from any old committed buffer - */ - if (impl->pending_buffer_attached) - read_back_cairo_surface (surface); - /* From this commit forward, we can't write to the buffer, * it's "live". In the future, if we need to stage more changes * we have to allocate a new staging buffer and draw to it instead. @@ -560,10 +500,6 @@ on_frame_clock_after_paint (GdkFrameClock *clock, */ wl_surface_commit (impl->display_server.wl_surface); - if (impl->pending_buffer_attached) - impl->committed_cairo_surface = g_steal_pointer (&impl->staging_cairo_surface); - - impl->pending_buffer_attached = FALSE; impl->pending_commit = FALSE; g_signal_emit (impl, signals[COMMITTED], 0); @@ -667,20 +603,24 @@ _gdk_wayland_display_create_surface_impl (GdkDisplay *display, g_signal_connect (frame_clock, "after-paint", G_CALLBACK (on_frame_clock_after_paint), surface); } -static void -gdk_wayland_surface_attach_image (GdkSurface *surface) +void +gdk_wayland_surface_attach_image (GdkSurface *surface, + cairo_surface_t *cairo_surface, + const cairo_region_t *damage) { - GdkWaylandDisplay *display; GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl); + GdkWaylandDisplay *display; + cairo_rectangle_int_t rect; + int i, n; if (GDK_SURFACE_DESTROYED (surface)) return; - g_assert (_gdk_wayland_is_shm_surface (impl->staging_cairo_surface)); + g_assert (_gdk_wayland_is_shm_surface (cairo_surface)); /* Attach this new buffer to the surface */ wl_surface_attach (impl->display_server.wl_surface, - _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface), + _gdk_wayland_shm_surface_get_wl_buffer (cairo_surface), impl->pending_buffer_offset_x, impl->pending_buffer_offset_y); impl->pending_buffer_offset_x = 0; @@ -691,185 +631,13 @@ gdk_wayland_surface_attach_image (GdkSurface *surface) if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE) wl_surface_set_buffer_scale (impl->display_server.wl_surface, impl->scale); - impl->pending_buffer_attached = TRUE; - impl->pending_commit = TRUE; -} - -static const cairo_user_data_key_t gdk_wayland_surface_cairo_key; - -static void -buffer_release_callback (void *_data, - struct wl_buffer *wl_buffer) -{ - cairo_surface_t *cairo_surface = _data; - GdkSurfaceImplWayland *impl = cairo_surface_get_user_data (cairo_surface, &gdk_wayland_surface_cairo_key); - - g_return_if_fail (GDK_IS_SURFACE_IMPL_WAYLAND (impl)); - - /* The released buffer isn't the latest committed one, we have no further - * use for it, so clean it up. - */ - if (impl->committed_cairo_surface != cairo_surface) - { - /* If this fails, then the surface buffer got reused before it was - * released from the compositor - */ - g_warn_if_fail (impl->staging_cairo_surface != cairo_surface); - - cairo_surface_destroy (cairo_surface); - return; - } - - if (impl->staged_updates_region != NULL) - { - /* If this fails, then we're tracking staged updates on a staging surface - * that doesn't exist. - */ - g_warn_if_fail (impl->staging_cairo_surface != NULL); - - /* If we've staged updates into a new buffer before the release for this - * buffer came in, then we can't reuse this buffer, so unref it. It may still - * be alive as a readback buffer though (via impl->backfill_cairo_surface). - * - * It's possible a staging surface was allocated but no updates were staged. - * If that happened, clean up that staging surface now, since the old commit - * buffer is available again, and reusing the old commit buffer for future - * updates will save having to do a read back later. - */ - if (!cairo_region_is_empty (impl->staged_updates_region)) - { - g_clear_pointer (&impl->committed_cairo_surface, cairo_surface_destroy); - return; - } - else - { - g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy); - g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy); - } - } - - /* Release came in, we haven't done any interim updates, so we can just use - * the old committed buffer again. - */ - impl->staging_cairo_surface = g_steal_pointer (&impl->committed_cairo_surface); -} - -static const struct wl_buffer_listener buffer_listener = { - buffer_release_callback -}; - -static void -gdk_wayland_surface_ensure_cairo_surface (GdkSurface *surface) -{ - GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl); - - /* If we are drawing using OpenGL then we only need a logical 1x1 surface. */ - if (impl->display_server.egl_window) - { - if (impl->staging_cairo_surface && - _gdk_wayland_is_shm_surface (impl->staging_cairo_surface)) - g_clear_pointer (&impl->staging_cairo_surface, cairo_surface_destroy); - - if (!impl->staging_cairo_surface) - { - impl->staging_cairo_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - impl->scale, - impl->scale); - cairo_surface_set_device_scale (impl->staging_cairo_surface, - impl->scale, impl->scale); - } - } - else if (!impl->staging_cairo_surface) + n = cairo_region_num_rectangles (damage); + for (i = 0; i < n; i++) { - GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (impl->wrapper)); - struct wl_buffer *buffer; - - impl->staging_cairo_surface = _gdk_wayland_display_create_shm_surface (display_wayland, - impl->wrapper->width, - impl->wrapper->height, - impl->scale); - cairo_surface_set_user_data (impl->staging_cairo_surface, - &gdk_wayland_surface_cairo_key, - g_object_ref (impl), - (cairo_destroy_func_t) - g_object_unref); - buffer = _gdk_wayland_shm_surface_get_wl_buffer (impl->staging_cairo_surface); - wl_buffer_add_listener (buffer, &buffer_listener, impl->staging_cairo_surface); + cairo_region_get_rectangle (damage, i, &rect); + wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height); } -} - -/* The cairo surface returned here uses a memory segment that's shared - * with the display server. This is not a temporary buffer that gets - * copied to the display server, but the actual buffer the display server - * will ultimately end up sending to the GPU. At the time this happens - * impl->committed_cairo_surface gets set to impl->staging_cairo_surface, and - * impl->staging_cairo_surface gets nullified. - */ -static cairo_surface_t * -gdk_wayland_surface_ref_cairo_surface (GdkSurface *surface) -{ - GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl); - - if (GDK_SURFACE_DESTROYED (impl->wrapper)) - return NULL; - - gdk_wayland_surface_ensure_cairo_surface (surface); - - cairo_surface_reference (impl->staging_cairo_surface); - - return impl->staging_cairo_surface; -} - -static gboolean -gdk_surface_impl_wayland_begin_paint (GdkSurface *surface) -{ - gdk_wayland_surface_ensure_cairo_surface (surface); - - return FALSE; -} - -static void -gdk_surface_impl_wayland_end_paint (GdkSurface *surface) -{ - GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl); - cairo_rectangle_int_t rect; - int i, n; - - if (impl->staging_cairo_surface && - _gdk_wayland_is_shm_surface (impl->staging_cairo_surface) && - !cairo_region_is_empty (surface->current_paint.region)) - { - gdk_wayland_surface_attach_image (surface); - - /* If there's a committed buffer pending, then track which - * updates are staged until the next frame, so we can back - * fill the unstaged parts of the staging buffer with the - * last frame. - */ - if (impl->committed_cairo_surface != NULL) - { - if (impl->staged_updates_region == NULL) - { - impl->staged_updates_region = cairo_region_copy (surface->current_paint.region); - impl->backfill_cairo_surface = cairo_surface_reference (impl->committed_cairo_surface); - } - else - { - cairo_region_union (impl->staged_updates_region, surface->current_paint.region); - } - } - - n = cairo_region_num_rectangles (surface->current_paint.region); - for (i = 0; i < n; i++) - { - cairo_region_get_rectangle (surface->current_paint.region, i, &rect); - wl_surface_damage (impl->display_server.wl_surface, rect.x, rect.y, rect.width, rect.height); - } - - impl->pending_commit = TRUE; - } - - gdk_wayland_surface_sync (surface); + impl->pending_commit = TRUE; } void @@ -913,7 +681,6 @@ gdk_surface_impl_wayland_finalize (GObject *object) g_clear_pointer (&impl->opaque_region, cairo_region_destroy); g_clear_pointer (&impl->input_region, cairo_region_destroy); - g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy); g_clear_pointer (&impl->shortcuts_inhibitors, g_hash_table_unref); G_OBJECT_CLASS (_gdk_surface_impl_wayland_parent_class)->finalize (object); @@ -2389,10 +2156,6 @@ gdk_wayland_surface_show (GdkSurface *surface, gdk_wayland_surface_map (surface); _gdk_make_event (surface, GDK_MAP, NULL, FALSE); - - if (impl->staging_cairo_surface && - _gdk_wayland_is_shm_surface (impl->staging_cairo_surface)) - gdk_wayland_surface_attach_image (surface); } static void @@ -2527,7 +2290,6 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface) unset_transient_for_exported (surface); _gdk_wayland_surface_clear_saved_size (surface); - drop_cairo_surfaces (surface); impl->pending_commit = FALSE; impl->mapped = FALSE; } @@ -3599,7 +3361,6 @@ _gdk_surface_impl_wayland_class_init (GdkSurfaceImplWaylandClass *klass) object_class->finalize = gdk_surface_impl_wayland_finalize; - impl_class->ref_cairo_surface = gdk_wayland_surface_ref_cairo_surface; impl_class->show = gdk_wayland_surface_show; impl_class->hide = gdk_wayland_surface_hide; impl_class->withdraw = gdk_surface_wayland_withdraw; @@ -3615,8 +3376,6 @@ _gdk_surface_impl_wayland_class_init (GdkSurfaceImplWaylandClass *klass) impl_class->get_device_state = gdk_surface_wayland_get_device_state; impl_class->input_shape_combine_region = gdk_surface_wayland_input_shape_combine_region; impl_class->destroy = gdk_wayland_surface_destroy; - impl_class->begin_paint = gdk_surface_impl_wayland_begin_paint; - impl_class->end_paint = gdk_surface_impl_wayland_end_paint; impl_class->beep = gdk_surface_impl_wayland_beep; impl_class->focus = gdk_wayland_surface_focus; -- 2.30.2