From 84d1d827c123b56ba156f66ba8247b7cd49cc768 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Sun, 12 Feb 2023 10:39:14 -0800 Subject: [PATCH] lib: start wiring up framebuffer to paintable Still things to sort out here, but just wanted to lay some plumbing between the two objects. --- lib/mks-framebuffer.c | 15 ++++++++---- lib/mks-paintable.c | 54 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/lib/mks-framebuffer.c b/lib/mks-framebuffer.c index 0ac57a9..8e7b4d7 100644 --- a/lib/mks-framebuffer.c +++ b/lib/mks-framebuffer.c @@ -147,9 +147,7 @@ mks_framebuffer_snapshot (GdkPaintable *paintable, * composited over on the GPU. It saves us a large GPU upload since * the GL renderer will cache the texture in VRAM in many cases. */ - gtk_snapshot_append_texture (snapshot, - GDK_TEXTURE (self->base_texture), - &GRAPHENE_RECT_INIT (0, 0, self->width, self->height)); + gdk_paintable_snapshot (GDK_PAINTABLE (self->base_texture), snapshot, width, height); /* Now draw our damage rectangles which are going to require an upload * since we can't reuse them between frames without a lot of tracking. @@ -245,7 +243,16 @@ mks_framebuffer_update (MksFramebuffer *self, cairo_surface_destroy (surface); cairo_destroy (cr); - cairo_region_union_rectangle (self->damage, &(cairo_rectangle_int_t) { x, y, width, height }); + if (x == 0 && y == 0 && width == self->width && height == self->height) + { + g_clear_pointer (&self->damage, cairo_region_destroy); + self->damage = cairo_region_create (); + } + else + { + cairo_region_union_rectangle (self->damage, + &(cairo_rectangle_int_t) { x, y, width, height }); + } } static void diff --git a/lib/mks-paintable.c b/lib/mks-paintable.c index 45526e6..db608d9 100644 --- a/lib/mks-paintable.c +++ b/lib/mks-paintable.c @@ -27,6 +27,7 @@ #include #include +#include "mks-framebuffer-private.h" #include "mks-paintable-private.h" #include "mks-qemu.h" @@ -34,11 +35,20 @@ struct _MksPaintable { GObject parent_instance; + MksQemuListener *listener; + GDBusConnection *connection; + MksFramebuffer *framebuffer; + guint width; guint height; - MksQemuListener *listener; - GDBusConnection *connection; + guint mode : 2; +}; + +enum { + MODE_INITIAL = 0, + MODE_FRAMEBUFFER, + MODE_DMABUF, }; static cairo_format_t @@ -96,6 +106,14 @@ mks_paintable_snapshot (GdkPaintable *paintable, double width, double height) { + MksPaintable *self = (MksPaintable *)paintable; + + g_assert (MKS_IS_PAINTABLE (self)); + g_assert (GDK_IS_SNAPSHOT (snapshot)); + + if (self->mode == MODE_FRAMEBUFFER) + gdk_paintable_snapshot (GDK_PAINTABLE (self->framebuffer), + snapshot, width, height); } static void @@ -214,9 +232,19 @@ mks_paintable_listener_update (MksPaintable *self, return TRUE; } - gdk_paintable_invalidate_contents (GDK_PAINTABLE (self)); + if (self->mode == MODE_FRAMEBUFFER) + { + const guint8 *data; + gsize data_len; + + data_len = g_variant_n_children (bytes); + data = (const guint8 *)g_variant_get_bytestring (bytes); + + mks_framebuffer_update (self->framebuffer, x, y, width, height, stride, format, data, data_len); + + gdk_paintable_invalidate_contents (GDK_PAINTABLE (self)); + } - g_print ("Update {%d,%d,%d,%d}\n", x, y, width, height); mks_qemu_listener_complete_update (listener, invocation); return TRUE; @@ -234,10 +262,13 @@ mks_paintable_listener_scanout (MksPaintable *self, { cairo_format_t format; gboolean size_changed; + const guint8 *data; + gsize data_len; g_assert (MKS_IS_PAINTABLE (self)); g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_assert (MKS_QEMU_IS_LISTENER (listener)); + g_assert (g_variant_is_of_type (bytes, G_VARIANT_TYPE_BYTESTRING)); if (!(format = _pixman_format_to_cairo_format (pixman_format))) { @@ -250,7 +281,20 @@ mks_paintable_listener_scanout (MksPaintable *self, size_changed = width != self->width || height != self->height; - g_print ("Scannout!\n"); + if (size_changed || self->framebuffer == NULL) + { + g_clear_object (&self->framebuffer); + self->framebuffer = mks_framebuffer_new (width, height, format); + } + + data_len = g_variant_n_children (bytes); + data = (const guint8 *)g_variant_get_bytestring (bytes); + mks_framebuffer_update (self->framebuffer, + 0, 0, width, height, + stride, format, + data, data_len); + + self->mode = MODE_FRAMEBUFFER; if (size_changed) gdk_paintable_invalidate_size (GDK_PAINTABLE (self));