lib: start wiring up framebuffer to paintable

Still things to sort out here, but just wanted to lay some plumbing
between the two objects.
This commit is contained in:
Christian Hergert 2023-02-12 10:39:14 -08:00
parent 2a0f0be8c0
commit 84d1d827c1
2 changed files with 60 additions and 9 deletions

View File

@ -147,9 +147,7 @@ mks_framebuffer_snapshot (GdkPaintable *paintable,
* composited over on the GPU. It saves us a large GPU upload since * 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. * the GL renderer will cache the texture in VRAM in many cases.
*/ */
gtk_snapshot_append_texture (snapshot, gdk_paintable_snapshot (GDK_PAINTABLE (self->base_texture), snapshot, width, height);
GDK_TEXTURE (self->base_texture),
&GRAPHENE_RECT_INIT (0, 0, self->width, self->height));
/* Now draw our damage rectangles which are going to require an upload /* 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. * 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_surface_destroy (surface);
cairo_destroy (cr); 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 static void

View File

@ -27,6 +27,7 @@
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <pixman.h> #include <pixman.h>
#include "mks-framebuffer-private.h"
#include "mks-paintable-private.h" #include "mks-paintable-private.h"
#include "mks-qemu.h" #include "mks-qemu.h"
@ -34,11 +35,20 @@ struct _MksPaintable
{ {
GObject parent_instance; GObject parent_instance;
MksQemuListener *listener;
GDBusConnection *connection;
MksFramebuffer *framebuffer;
guint width; guint width;
guint height; guint height;
MksQemuListener *listener; guint mode : 2;
GDBusConnection *connection; };
enum {
MODE_INITIAL = 0,
MODE_FRAMEBUFFER,
MODE_DMABUF,
}; };
static cairo_format_t static cairo_format_t
@ -96,6 +106,14 @@ mks_paintable_snapshot (GdkPaintable *paintable,
double width, double width,
double height) 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 static void
@ -214,9 +232,19 @@ mks_paintable_listener_update (MksPaintable *self,
return TRUE; 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); mks_qemu_listener_complete_update (listener, invocation);
return TRUE; return TRUE;
@ -234,10 +262,13 @@ mks_paintable_listener_scanout (MksPaintable *self,
{ {
cairo_format_t format; cairo_format_t format;
gboolean size_changed; gboolean size_changed;
const guint8 *data;
gsize data_len;
g_assert (MKS_IS_PAINTABLE (self)); g_assert (MKS_IS_PAINTABLE (self));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
g_assert (MKS_QEMU_IS_LISTENER (listener)); 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))) 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; 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) if (size_changed)
gdk_paintable_invalidate_size (GDK_PAINTABLE (self)); gdk_paintable_invalidate_size (GDK_PAINTABLE (self));