diff --git a/docs/reference/gtk/running.md b/docs/reference/gtk/running.md index 879e23d2e9..3ddae2cc36 100644 --- a/docs/reference/gtk/running.md +++ b/docs/reference/gtk/running.md @@ -217,6 +217,10 @@ A number of options affect behavior instead of logging: `no-portals` : Disable use of [portals](https://docs.flatpak.org/en/latest/portals.html) +`force-offload` +: Force graphics offload for all textures, even when slower. This allows + to debug offloading in the absence of dmabufs. + `gl-disable` : Disable OpenGL support diff --git a/gdk/gdk.c b/gdk/gdk.c index 9787b437b8..95521522f2 100644 --- a/gdk/gdk.c +++ b/gdk/gdk.c @@ -122,6 +122,7 @@ static const GdkDebugKey gdk_debug_keys[] = { { "portals", GDK_DEBUG_PORTALS, "Force use of portals" }, { "no-portals", GDK_DEBUG_NO_PORTALS, "Disable use of portals" }, + { "force-offload", GDK_DEBUG_FORCE_OFFLOAD, "Force graphics offload for all textures" }, { "gl-disable", GDK_DEBUG_GL_DISABLE, "Disable OpenGL support" }, { "gl-no-fractional", GDK_DEBUG_GL_NO_FRACTIONAL, "Disable fractional scaling for OpenGL" }, { "gl-debug", GDK_DEBUG_GL_DEBUG, "Insert debugging information in OpenGL" }, diff --git a/gdk/gdkdebugprivate.h b/gdk/gdkdebugprivate.h index ba709fb5e9..359f13e6fa 100644 --- a/gdk/gdkdebugprivate.h +++ b/gdk/gdkdebugprivate.h @@ -44,7 +44,7 @@ typedef enum { GDK_DEBUG_NO_PORTALS = 1 << 15, GDK_DEBUG_GL_DISABLE = 1 << 16, GDK_DEBUG_GL_NO_FRACTIONAL= 1 << 17, - + GDK_DEBUG_FORCE_OFFLOAD = 1 << 18, GDK_DEBUG_GL_DISABLE_GL = 1 << 19, GDK_DEBUG_GL_DISABLE_GLES = 1 << 20, GDK_DEBUG_GL_PREFER_GL = 1 << 21, diff --git a/gdk/wayland/gdksubsurface-wayland.c b/gdk/wayland/gdksubsurface-wayland.c index cecd10cb28..45d03daeea 100644 --- a/gdk/wayland/gdksubsurface-wayland.c +++ b/gdk/wayland/gdksubsurface-wayland.c @@ -50,6 +50,48 @@ gdk_wayland_subsurface_finalize (GObject *object) G_OBJECT_CLASS (gdk_wayland_subsurface_parent_class)->finalize (object); } +static void +shm_buffer_release (void *data, + struct wl_buffer *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_SUBSURFACE (self)->parent)); + int width, height; + cairo_surface_t *surface; + GdkTextureDownloader *downloader; + struct wl_buffer *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); + + buffer = _gdk_wayland_shm_surface_get_wl_buffer (surface); + wl_buffer_add_listener (buffer, &shm_buffer_listener, surface); + + return buffer; +} + static void dmabuf_buffer_release (void *data, struct wl_buffer *buffer) @@ -96,8 +138,8 @@ static const struct zwp_linux_buffer_params_v1_listener params_listener = { }; static struct wl_buffer * -get_wl_buffer (GdkWaylandSubsurface *self, - GdkTexture *texture) +get_dmabuf_wl_buffer (GdkWaylandSubsurface *self, + GdkTexture *texture) { GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SUBSURFACE (self)->parent)); const GdkDmabuf *dmabuf; @@ -148,6 +190,25 @@ get_wl_buffer (GdkWaylandSubsurface *self, return buffer; } +static struct wl_buffer * +get_wl_buffer (GdkWaylandSubsurface *self, + GdkTexture *texture) +{ + GdkDisplay *display = gdk_surface_get_display (GDK_SUBSURFACE (self)->parent); + struct wl_buffer *buffer = NULL; + + if (GDK_IS_DMABUF_TEXTURE (texture)) + buffer = get_dmabuf_wl_buffer (self, texture); + + if (GDK_DISPLAY_DEBUG_CHECK (display, FORCE_OFFLOAD)) + { + if (!buffer) + buffer = get_shm_wl_buffer (self, texture); + } + + return buffer; +} + static inline enum wl_output_transform gdk_texture_transform_to_wl (GdkTextureTransform transform) { @@ -239,7 +300,8 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub, scale, self); } - else if (!GDK_IS_DMABUF_TEXTURE (texture)) + else if (!GDK_IS_DMABUF_TEXTURE (texture) && + !GDK_DISPLAY_DEBUG_CHECK (gdk_surface_get_display (sub->parent), FORCE_OFFLOAD)) { GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD, "%dx%d %s is not a GdkDmabufTexture, hiding subsurface %p",