mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 11:20:12 +00:00
gl renderer: Render non-trivial transforms to a texture
This way we can e.g. render rotated clips, borders, etc.
This commit is contained in:
parent
7c020bfaaa
commit
5907ff694f
@ -219,6 +219,31 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
|
||||
MAX (self->corner[2].height, self->corner[3].height)) * 2);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
node_supports_transform (GskRenderNode *node)
|
||||
{
|
||||
/* Some nodes can't handle non-trivial transforms without being
|
||||
* rendered to a texture (e.g. rotated clips, etc.). Some however
|
||||
* work just fine, mostly because they already draw their child
|
||||
* to a texture and just render the texture manipulated in some
|
||||
* way, think opacity or color matrix. */
|
||||
const guint node_type = gsk_render_node_get_node_type (node);
|
||||
|
||||
switch (node_type)
|
||||
{
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_OPACITY_NODE:
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
case GSK_TEXTURE_NODE:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void gsk_gl_renderer_setup_render_mode (GskGLRenderer *self);
|
||||
static void add_offscreen_ops (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
@ -736,7 +761,43 @@ render_transform_node (GskGLRenderer *self,
|
||||
graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
|
||||
|
||||
ops_push_modelview (builder, &transformed_mv);
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
if (ops_modelview_is_simple (builder) ||
|
||||
node_supports_transform (child))
|
||||
{
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float min_x = builder->dx + child->bounds.origin.x;
|
||||
const float min_y = builder->dy + child->bounds.origin.y;
|
||||
const float max_x = min_x + child->bounds.size.width;
|
||||
const float max_y = min_y + child->bounds.size.height;
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
|
||||
{ { min_x, min_y }, { 0, 1 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
|
||||
{ { max_x, max_y }, { 1, 0 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
};
|
||||
int texture_id;
|
||||
gboolean is_offscreen;
|
||||
/* For non-trivial transforms, we draw everything on a texture and then
|
||||
* draw the texture transformed. */
|
||||
/* TODO: We should compute a modelview containing only the "non-trivial"
|
||||
* part (e.g. the rotation) and use that. We want to keep the scale
|
||||
* for the texture.
|
||||
*/
|
||||
add_offscreen_ops (self, builder,
|
||||
min_x, max_x, min_y, max_y,
|
||||
child,
|
||||
&texture_id, &is_offscreen,
|
||||
FALSE, TRUE);
|
||||
ops_set_texture (builder, texture_id);
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
ops_draw (builder, vertex_data);
|
||||
}
|
||||
ops_pop_modelview (builder);
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,19 @@ ops_transform_bounds_modelview (const RenderOpBuilder *builder,
|
||||
graphene_rect_offset (dst, builder->dx, builder->dy);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ops_modelview_is_simple (const RenderOpBuilder *builder)
|
||||
{
|
||||
const MatrixStackEntry *head;
|
||||
|
||||
g_assert (builder->mv_stack != NULL);
|
||||
g_assert (builder->mv_stack->len >= 1);
|
||||
|
||||
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
|
||||
|
||||
return head->metadata.simple;
|
||||
}
|
||||
|
||||
void
|
||||
ops_set_program (RenderOpBuilder *builder,
|
||||
const Program *program)
|
||||
|
@ -263,6 +263,7 @@ void ops_finish (RenderOpBuilder *builder);
|
||||
void ops_push_modelview (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *mv);
|
||||
void ops_pop_modelview (RenderOpBuilder *builder);
|
||||
gboolean ops_modelview_is_simple (const RenderOpBuilder *builder);
|
||||
float ops_get_scale (const RenderOpBuilder *builder);
|
||||
|
||||
void ops_set_program (RenderOpBuilder *builder,
|
||||
|
Loading…
Reference in New Issue
Block a user