mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-15 14:50:06 +00:00
broadway: Optimize color matrix + texture nodes to pre-colorized texture
This commit is contained in:
parent
b58a366dc6
commit
f932d35c95
@ -326,6 +326,145 @@ add_new_node (GskRenderer *renderer,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct ColorizedTexture {
|
||||||
|
GdkTexture *texture;
|
||||||
|
graphene_matrix_t color_matrix;
|
||||||
|
graphene_vec4_t color_offset;
|
||||||
|
} ColorizedTexture;
|
||||||
|
|
||||||
|
static void
|
||||||
|
colorized_texture_free (ColorizedTexture *colorized)
|
||||||
|
{
|
||||||
|
g_object_unref (colorized->texture);
|
||||||
|
g_free (colorized);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ColorizedTexture *
|
||||||
|
colorized_texture_new (GdkTexture *texture,
|
||||||
|
const graphene_matrix_t *color_matrix,
|
||||||
|
const graphene_vec4_t *color_offset)
|
||||||
|
{
|
||||||
|
ColorizedTexture *colorized = g_new0 (ColorizedTexture, 1);
|
||||||
|
colorized->texture = g_object_ref (texture);
|
||||||
|
colorized->color_matrix = *color_matrix;
|
||||||
|
colorized->color_offset = *color_offset;
|
||||||
|
return colorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
colorized_texture_free_list (GList *list)
|
||||||
|
{
|
||||||
|
g_list_free_full (list, (GDestroyNotify)colorized_texture_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
matrix_equal (const graphene_matrix_t *a,
|
||||||
|
const graphene_matrix_t *b)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i ++)
|
||||||
|
{
|
||||||
|
graphene_vec4_t ra, rb;
|
||||||
|
graphene_matrix_get_row (a, i, &ra);
|
||||||
|
graphene_matrix_get_row (b, i, &rb);
|
||||||
|
if (!graphene_vec4_equal (&ra, &rb))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkTexture *
|
||||||
|
get_colorized_texture (GdkTexture *texture,
|
||||||
|
const graphene_matrix_t *color_matrix,
|
||||||
|
const graphene_vec4_t *color_offset)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface = gdk_texture_download_surface (texture);
|
||||||
|
cairo_surface_t *image_surface;
|
||||||
|
graphene_vec4_t pixel;
|
||||||
|
guint32* pixel_data;
|
||||||
|
guchar *data;
|
||||||
|
gsize x, y, width, height, stride;
|
||||||
|
float alpha;
|
||||||
|
GdkTexture *colorized_texture;
|
||||||
|
GList *colorized_list, *l;
|
||||||
|
ColorizedTexture *colorized;
|
||||||
|
|
||||||
|
colorized_list = g_object_get_data (G_OBJECT (texture), "broadway-colorized");
|
||||||
|
|
||||||
|
for (l = colorized_list; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
colorized = l->data;
|
||||||
|
|
||||||
|
if (graphene_vec4_equal (&colorized->color_offset, color_offset) &&
|
||||||
|
matrix_equal (&colorized->color_matrix, color_matrix))
|
||||||
|
return g_object_ref (colorized->texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
image_surface = cairo_surface_map_to_image (surface, NULL);
|
||||||
|
data = cairo_image_surface_get_data (image_surface);
|
||||||
|
width = cairo_image_surface_get_width (image_surface);
|
||||||
|
height = cairo_image_surface_get_height (image_surface);
|
||||||
|
stride = cairo_image_surface_get_stride (image_surface);
|
||||||
|
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
pixel_data = (guint32 *) data;
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
alpha = ((pixel_data[x] >> 24) & 0xFF) / 255.0;
|
||||||
|
|
||||||
|
if (alpha == 0)
|
||||||
|
{
|
||||||
|
graphene_vec4_init (&pixel, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
graphene_vec4_init (&pixel,
|
||||||
|
((pixel_data[x] >> 16) & 0xFF) / (255.0 * alpha),
|
||||||
|
((pixel_data[x] >> 8) & 0xFF) / (255.0 * alpha),
|
||||||
|
( pixel_data[x] & 0xFF) / (255.0 * alpha),
|
||||||
|
alpha);
|
||||||
|
graphene_matrix_transform_vec4 (color_matrix, &pixel, &pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphene_vec4_add (&pixel, color_offset, &pixel);
|
||||||
|
|
||||||
|
alpha = graphene_vec4_get_w (&pixel);
|
||||||
|
if (alpha > 0.0)
|
||||||
|
{
|
||||||
|
alpha = MIN (alpha, 1.0);
|
||||||
|
pixel_data[x] = (((guint32) (alpha * 255)) << 24) |
|
||||||
|
(((guint32) (CLAMP (graphene_vec4_get_x (&pixel), 0, 1) * alpha * 255)) << 16) |
|
||||||
|
(((guint32) (CLAMP (graphene_vec4_get_y (&pixel), 0, 1) * alpha * 255)) << 8) |
|
||||||
|
((guint32) (CLAMP (graphene_vec4_get_z (&pixel), 0, 1) * alpha * 255));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pixel_data[x] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_mark_dirty (image_surface);
|
||||||
|
cairo_surface_unmap_image (surface, image_surface);
|
||||||
|
|
||||||
|
colorized_texture = gdk_texture_new_for_surface (surface);
|
||||||
|
|
||||||
|
colorized = colorized_texture_new (colorized_texture, color_matrix, color_offset);
|
||||||
|
if (colorized_list)
|
||||||
|
colorized_list = g_list_append (colorized_list, colorized);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colorized_list = g_list_append (NULL, colorized);
|
||||||
|
g_object_set_data_full (G_OBJECT (texture), "broadway-colorized",
|
||||||
|
colorized_list, (GDestroyNotify)colorized_texture_free_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorized_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Note: This tracks the offset so that we can convert
|
/* Note: This tracks the offset so that we can convert
|
||||||
the absolute coordinates of the GskRenderNodes to
|
the absolute coordinates of the GskRenderNodes to
|
||||||
parent-relative which is what the dom uses, and
|
parent-relative which is what the dom uses, and
|
||||||
@ -571,6 +710,27 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case GSK_COLOR_MATRIX_NODE:
|
case GSK_COLOR_MATRIX_NODE:
|
||||||
|
{
|
||||||
|
GskRenderNode *child = gsk_color_matrix_node_get_child (node);
|
||||||
|
if (gsk_render_node_get_node_type (child) == GSK_TEXTURE_NODE)
|
||||||
|
{
|
||||||
|
const graphene_matrix_t *color_matrix = gsk_color_matrix_node_peek_color_matrix (node);
|
||||||
|
const graphene_vec4_t *color_offset = gsk_color_matrix_node_peek_color_offset (node);
|
||||||
|
GdkTexture *texture = gsk_texture_node_get_texture (child);
|
||||||
|
GdkTexture *colorized_texture = get_colorized_texture (texture, color_matrix, color_offset);
|
||||||
|
if (add_new_node (renderer, node, BROADWAY_NODE_TEXTURE))
|
||||||
|
{
|
||||||
|
guint32 texture_id = gdk_broadway_display_ensure_texture (display, colorized_texture);
|
||||||
|
add_rect (nodes, &child->bounds, offset_x, offset_y);
|
||||||
|
add_uint32 (nodes, texture_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case GSK_TEXT_NODE:
|
case GSK_TEXT_NODE:
|
||||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||||
case GSK_REPEAT_NODE:
|
case GSK_REPEAT_NODE:
|
||||||
|
Loading…
Reference in New Issue
Block a user