mirror of
https://gitlab.gnome.org/GNOME/libmks.git
synced 2025-04-14 08:27:16 +00:00
lib: tweak cairo drawing a bit and fix invalidation
This commit is contained in:
parent
6beaf8b925
commit
441b7355ef
@ -66,10 +66,14 @@ struct _MksCairoFramebuffer
|
|||||||
/* Number of bytes per-pixel */
|
/* Number of bytes per-pixel */
|
||||||
guint bpp;
|
guint bpp;
|
||||||
|
|
||||||
/* The height and width of our cairo surface */
|
/* The height and width the framebuffer was created with */
|
||||||
guint height;
|
guint height;
|
||||||
guint width;
|
guint width;
|
||||||
|
|
||||||
|
/* The real width and height when tiling is taken into account */
|
||||||
|
guint real_height;
|
||||||
|
guint real_width;
|
||||||
|
|
||||||
/* The number of tiles horizontally and vertically */
|
/* The number of tiles horizontally and vertically */
|
||||||
guint n_columns;
|
guint n_columns;
|
||||||
guint n_rows;
|
guint n_rows;
|
||||||
@ -113,17 +117,12 @@ mks_cairo_framebuffer_snapshot (GdkPaintable *paintable,
|
|||||||
double height)
|
double height)
|
||||||
{
|
{
|
||||||
MksCairoFramebuffer *self = MKS_CAIRO_FRAMEBUFFER (paintable);
|
MksCairoFramebuffer *self = MKS_CAIRO_FRAMEBUFFER (paintable);
|
||||||
static GdkRGBA black = {0,0,0,1};
|
|
||||||
|
|
||||||
gtk_snapshot_save (snapshot);
|
gtk_snapshot_save (snapshot);
|
||||||
gtk_snapshot_scale (snapshot,
|
gtk_snapshot_scale (snapshot,
|
||||||
width / (double)self->width,
|
width / (double)self->width,
|
||||||
height / (double)self->height);
|
height / (double)self->height);
|
||||||
|
|
||||||
gtk_snapshot_append_color (snapshot,
|
|
||||||
&black,
|
|
||||||
&GRAPHENE_RECT_INIT (0, 0, self->width, self->height));
|
|
||||||
|
|
||||||
for (guint row = 0; row < self->n_rows; row++)
|
for (guint row = 0; row < self->n_rows; row++)
|
||||||
{
|
{
|
||||||
guint row_pos = row * self->n_columns;
|
guint row_pos = row * self->n_columns;
|
||||||
@ -199,8 +198,6 @@ static void
|
|||||||
mks_cairo_framebuffer_constructed (GObject *object)
|
mks_cairo_framebuffer_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
MksCairoFramebuffer *self = (MksCairoFramebuffer *)object;
|
MksCairoFramebuffer *self = (MksCairoFramebuffer *)object;
|
||||||
guint real_width;
|
|
||||||
guint real_height;
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (mks_cairo_framebuffer_parent_class)->constructed (object);
|
G_OBJECT_CLASS (mks_cairo_framebuffer_parent_class)->constructed (object);
|
||||||
|
|
||||||
@ -228,37 +225,37 @@ mks_cairo_framebuffer_constructed (GObject *object)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
real_width = self->width;
|
self->real_width = self->width;
|
||||||
real_height = self->height;
|
self->real_height = self->height;
|
||||||
|
|
||||||
realign (&real_width, TILE_WIDTH);
|
realign (&self->real_width, TILE_WIDTH);
|
||||||
realign (&real_height, TILE_HEIGHT);
|
realign (&self->real_height, TILE_HEIGHT);
|
||||||
|
|
||||||
g_assert (real_width % TILE_WIDTH == 0);
|
g_assert (self->real_width % TILE_WIDTH == 0);
|
||||||
g_assert (real_height % TILE_HEIGHT == 0);
|
g_assert (self->real_height % TILE_HEIGHT == 0);
|
||||||
|
|
||||||
self->surface = cairo_image_surface_create (self->format, real_width, real_height);
|
self->surface = cairo_image_surface_create (self->format, self->real_width, self->real_height);
|
||||||
|
|
||||||
if (self->surface == NULL)
|
if (self->surface == NULL)
|
||||||
{
|
{
|
||||||
g_warning ("Cairo surface creation failed: format=0x%x width=%u height=%u",
|
g_warning ("Cairo surface creation failed: format=0x%x width=%u height=%u",
|
||||||
self->format, real_width, real_height);
|
self->format, self->real_width, self->real_height);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->stride = cairo_format_stride_for_width (self->format, real_width);
|
self->stride = cairo_format_stride_for_width (self->format, self->real_width);
|
||||||
self->bpp = self->stride / real_width;
|
self->bpp = self->stride / self->real_width;
|
||||||
|
|
||||||
/* Currently only 4bbp are supported */
|
/* Currently only 4bbp are supported */
|
||||||
g_assert (self->bpp == 4);
|
g_assert (self->bpp == 4);
|
||||||
|
|
||||||
self->content = g_bytes_new_with_free_func (cairo_image_surface_get_data (self->surface),
|
self->content = g_bytes_new_with_free_func (cairo_image_surface_get_data (self->surface),
|
||||||
self->stride * real_height,
|
self->stride * self->real_height,
|
||||||
(GDestroyNotify) cairo_surface_destroy,
|
(GDestroyNotify) cairo_surface_destroy,
|
||||||
cairo_surface_reference (self->surface));
|
cairo_surface_reference (self->surface));
|
||||||
|
|
||||||
self->n_columns = real_width / TILE_WIDTH;
|
self->n_columns = self->real_width / TILE_WIDTH;
|
||||||
self->n_rows = real_height / TILE_HEIGHT;
|
self->n_rows = self->real_height / TILE_HEIGHT;
|
||||||
|
|
||||||
self->tiles = g_ptr_array_new_full (self->n_columns * self->n_rows, texture_clear);
|
self->tiles = g_ptr_array_new_full (self->n_columns * self->n_rows, texture_clear);
|
||||||
g_ptr_array_set_size (self->tiles, self->n_columns * self->n_rows);
|
g_ptr_array_set_size (self->tiles, self->n_columns * self->n_rows);
|
||||||
@ -381,10 +378,11 @@ mks_cairo_framebuffer_new (cairo_format_t format,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
invalidate_on_destroy (gpointer data)
|
flush_and_invalidate_on_destroy (gpointer data)
|
||||||
{
|
{
|
||||||
g_autoptr(MksCairoFramebuffer) self = data;
|
g_autoptr(MksCairoFramebuffer) self = data;
|
||||||
|
|
||||||
|
cairo_surface_flush (self->surface);
|
||||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,6 +400,9 @@ mks_cairo_framebuffer_update (MksCairoFramebuffer *self,
|
|||||||
g_return_val_if_fail (MKS_IS_CAIRO_FRAMEBUFFER (self), NULL);
|
g_return_val_if_fail (MKS_IS_CAIRO_FRAMEBUFFER (self), NULL);
|
||||||
g_return_val_if_fail (self->surface != NULL, NULL);
|
g_return_val_if_fail (self->surface != NULL, NULL);
|
||||||
|
|
||||||
|
g_assert (self->n_columns > 0);
|
||||||
|
g_assert (self->n_rows > 0);
|
||||||
|
|
||||||
col1 = MIN (x / TILE_WIDTH, self->n_columns-1);
|
col1 = MIN (x / TILE_WIDTH, self->n_columns-1);
|
||||||
col2 = MIN ((x + width) / TILE_WIDTH, self->n_columns-1);
|
col2 = MIN ((x + width) / TILE_WIDTH, self->n_columns-1);
|
||||||
|
|
||||||
@ -410,7 +411,7 @@ mks_cairo_framebuffer_update (MksCairoFramebuffer *self,
|
|||||||
|
|
||||||
for (guint row = row1; row <= row2; row++)
|
for (guint row = row1; row <= row2; row++)
|
||||||
{
|
{
|
||||||
guint row_pos = row * self->n_rows;
|
guint row_pos = row * self->n_columns;
|
||||||
|
|
||||||
for (guint col = col1; col <= col2; col++)
|
for (guint col = col1; col <= col2; col++)
|
||||||
{
|
{
|
||||||
@ -423,13 +424,14 @@ mks_cairo_framebuffer_update (MksCairoFramebuffer *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cr = cairo_create (self->surface);
|
cr = cairo_create (self->surface);
|
||||||
cairo_rectangle (cr, x, y, width, height);
|
cairo_translate (cr, x, y);
|
||||||
|
cairo_rectangle (cr, 0, 0, width, height);
|
||||||
cairo_clip (cr);
|
cairo_clip (cr);
|
||||||
|
|
||||||
cairo_set_user_data (cr,
|
cairo_set_user_data (cr,
|
||||||
&invalidate_key,
|
&invalidate_key,
|
||||||
g_object_ref (self),
|
g_object_ref (self),
|
||||||
invalidate_on_destroy);
|
flush_and_invalidate_on_destroy);
|
||||||
|
|
||||||
return cr;
|
return cr;
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,26 @@ mks_paintable_init (MksPaintable *self)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mks_paintable_invalidate_contents_cb (MksPaintable *self,
|
||||||
|
GdkPaintable *paintable)
|
||||||
|
{
|
||||||
|
g_assert (MKS_IS_PAINTABLE (self));
|
||||||
|
g_assert (GDK_IS_PAINTABLE (paintable));
|
||||||
|
|
||||||
|
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mks_paintable_invalidate_size_cb (MksPaintable *self,
|
||||||
|
GdkPaintable *paintable)
|
||||||
|
{
|
||||||
|
g_assert (MKS_IS_PAINTABLE (self));
|
||||||
|
g_assert (GDK_IS_PAINTABLE (paintable));
|
||||||
|
|
||||||
|
gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mks_paintable_set_framebuffer (MksPaintable *self,
|
mks_paintable_set_framebuffer (MksPaintable *self,
|
||||||
MksCairoFramebuffer *framebuffer)
|
MksCairoFramebuffer *framebuffer)
|
||||||
@ -193,12 +213,12 @@ mks_paintable_set_framebuffer (MksPaintable *self,
|
|||||||
self->framebuffer = g_object_ref (framebuffer);
|
self->framebuffer = g_object_ref (framebuffer);
|
||||||
g_signal_connect_object (self->framebuffer,
|
g_signal_connect_object (self->framebuffer,
|
||||||
"invalidate-size",
|
"invalidate-size",
|
||||||
G_CALLBACK (gdk_paintable_invalidate_size),
|
G_CALLBACK (mks_paintable_invalidate_size_cb),
|
||||||
self,
|
self,
|
||||||
G_CONNECT_SWAPPED);
|
G_CONNECT_SWAPPED);
|
||||||
g_signal_connect_object (self->framebuffer,
|
g_signal_connect_object (self->framebuffer,
|
||||||
"invalidate-contents",
|
"invalidate-contents",
|
||||||
G_CALLBACK (gdk_paintable_invalidate_contents),
|
G_CALLBACK (mks_paintable_invalidate_contents_cb),
|
||||||
self,
|
self,
|
||||||
G_CONNECT_SWAPPED);
|
G_CONNECT_SWAPPED);
|
||||||
self->mode = MODE_FRAMEBUFFER;
|
self->mode = MODE_FRAMEBUFFER;
|
||||||
@ -267,6 +287,8 @@ mks_paintable_listener_update (MksPaintable *self,
|
|||||||
guint8 *data;
|
guint8 *data;
|
||||||
cairo_format_t format;
|
cairo_format_t format;
|
||||||
gsize data_len;
|
gsize data_len;
|
||||||
|
static int counter;
|
||||||
|
char name[32];
|
||||||
|
|
||||||
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));
|
||||||
@ -319,10 +341,13 @@ mks_paintable_listener_update (MksPaintable *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
source = cairo_image_surface_create_for_data (data, format, width, height, stride);
|
source = cairo_image_surface_create_for_data (data, format, width, height, stride);
|
||||||
|
g_snprintf (name, sizeof name, "update-%u.png", counter++ % 10);
|
||||||
|
cairo_surface_write_to_png (source, name);
|
||||||
cr = mks_cairo_framebuffer_update (self->framebuffer, x, y, width, height);
|
cr = mks_cairo_framebuffer_update (self->framebuffer, x, y, width, height);
|
||||||
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_set_source_surface (cr, source, 0, 0);
|
cairo_set_source_surface (cr, source, 0, 0);
|
||||||
cairo_rectangle (cr, x, y, width, height);
|
cairo_rectangle (cr, 0, 0, width, height);
|
||||||
cairo_paint (cr);
|
cairo_fill (cr);
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
cairo_surface_destroy (source);
|
cairo_surface_destroy (source);
|
||||||
|
|
||||||
@ -385,6 +410,7 @@ mks_paintable_listener_scanout (MksPaintable *self,
|
|||||||
source = cairo_image_surface_create_for_data (data, format, width, height, stride);
|
source = cairo_image_surface_create_for_data (data, format, width, height, stride);
|
||||||
cr = mks_cairo_framebuffer_update (self->framebuffer, 0, 0, width, height);
|
cr = mks_cairo_framebuffer_update (self->framebuffer, 0, 0, width, height);
|
||||||
cairo_set_source_surface (cr, source, 0, 0);
|
cairo_set_source_surface (cr, source, 0, 0);
|
||||||
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||||
cairo_rectangle (cr, 0, 0, width, height);
|
cairo_rectangle (cr, 0, 0, width, height);
|
||||||
cairo_paint (cr);
|
cairo_paint (cr);
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user