Compare commits

...

4 Commits

Author SHA1 Message Date
Matthias Clasen
843537c8e7 gl: Drop buffer_size
No need to maintain buffer_size separately.
It is always vertices->len * sizeof (GskQuadVertex).
2019-10-11 14:45:06 -04:00
Matthias Clasen
0acb26a076 Drop OP_CHANGE_VAO
Instead, we accumulate vertices in a separate
array, which simplifies various things and lets
us avoid the extra copying step for the vao.
2019-10-11 14:45:06 -04:00
Matthias Clasen
f6a36fe834 gl: fix linear gradients
The opbuffer conversion introduced this bug.
2019-10-11 14:45:06 -04:00
Christian Hergert
675cbcc1e7 prototype OpBuffer helper for building op buffer 2019-10-11 10:23:33 -04:00
6 changed files with 725 additions and 540 deletions

View File

@@ -8,6 +8,7 @@
#include "gskglprofilerprivate.h"
#include "gskprofilerprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeprivate.h"
#include "gsktransformprivate.h"
#include "gskshaderbuilderprivate.h"
#include "gskglglyphcacheprivate.h"
@@ -345,7 +346,6 @@ struct _GskGLRenderer
};
RenderOpBuilder op_builder;
GArray *render_ops;
GskGLTextureAtlases *atlases;
GskGLGlyphCache *glyph_cache;
@@ -1064,7 +1064,7 @@ render_linear_gradient_node (GskGLRenderer *self,
RenderOpBuilder *builder,
const GskQuadVertex *vertex_data)
{
RenderOp *op;
OpLinearGradient *op;
int n_color_stops = MIN (8, gsk_linear_gradient_node_get_n_color_stops (node));
const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node);
const graphene_point_t *start = gsk_linear_gradient_node_peek_start (node);
@@ -1079,20 +1079,18 @@ render_linear_gradient_node (GskGLRenderer *self,
{
const GskColorStop *stop = stops + i;
op->linear_gradient.color_stops[(i * 4) + 0] = stop->color.red;
op->linear_gradient.color_stops[(i * 4) + 1] = stop->color.green;
op->linear_gradient.color_stops[(i * 4) + 2] = stop->color.blue;
op->linear_gradient.color_stops[(i * 4) + 3] = stop->color.alpha;
op->linear_gradient.color_offsets[i] = stop->offset;
op->color_stops[(i * 4) + 0] = stop->color.red;
op->color_stops[(i * 4) + 1] = stop->color.green;
op->color_stops[(i * 4) + 2] = stop->color.blue;
op->color_stops[(i * 4) + 3] = stop->color.alpha;
op->color_offsets[i] = stop->offset;
}
op->linear_gradient.n_color_stops = n_color_stops;
op->linear_gradient.start_point = *start;
op->linear_gradient.start_point.x += builder->dx;
op->linear_gradient.start_point.y += builder->dy;
op->linear_gradient.end_point = *end;
op->linear_gradient.end_point.x += builder->dx;
op->linear_gradient.end_point.y += builder->dy;
op->n_color_stops = n_color_stops;
op->start_point.x = start->x + builder->dx;
op->start_point.y = start->y + builder->dy;
op->end_point.x = end->x + builder->dx;
op->end_point.y = end->y + builder->dy;
ops_draw (builder, vertex_data);
}
@@ -1298,7 +1296,7 @@ render_blur_node (GskGLRenderer *self,
const float blur_radius = gsk_blur_node_get_radius (node);
TextureRegion region;
gboolean is_offscreen;
RenderOp *op;
OpBlur *op;
if (blur_radius <= 0)
{
@@ -1320,8 +1318,8 @@ render_blur_node (GskGLRenderer *self,
ops_set_program (builder, &self->blur_program);
op = ops_begin (builder, OP_CHANGE_BLUR);
graphene_size_init_from_size (&op->blur.size, &node->bounds.size);
op->blur.radius = blur_radius;
graphene_size_init_from_size (&op->size, &node->bounds.size);
op->radius = blur_radius;
ops_set_texture (builder, region.texture_id);
@@ -1352,7 +1350,7 @@ render_inset_shadow_node (GskGLRenderer *self,
const GskQuadVertex *vertex_data)
{
const float scale = ops_get_scale (builder);
RenderOp *op;
OpShadow *op;
/* TODO: Implement blurred inset shadows as well */
if (gsk_inset_shadow_node_get_blur_radius (node) > 0)
@@ -1364,16 +1362,16 @@ render_inset_shadow_node (GskGLRenderer *self,
ops_set_program (builder, &self->inset_shadow_program);
op = ops_begin (builder, OP_CHANGE_INSET_SHADOW);
rgba_to_float (gsk_inset_shadow_node_peek_color (node), op->inset_shadow.color);
rgba_to_float (gsk_inset_shadow_node_peek_color (node), op->color);
rounded_rect_to_floats (self, builder,
gsk_inset_shadow_node_peek_outline (node),
op->inset_shadow.outline,
op->inset_shadow.corner_widths,
op->inset_shadow.corner_heights);
op->inset_shadow.radius = gsk_inset_shadow_node_get_blur_radius (node) * scale;
op->inset_shadow.spread = gsk_inset_shadow_node_get_spread (node) * scale;
op->inset_shadow.offset[0] = gsk_inset_shadow_node_get_dx (node) * scale;
op->inset_shadow.offset[1] = -gsk_inset_shadow_node_get_dy (node) * scale;
op->outline,
op->corner_widths,
op->corner_heights);
op->radius = gsk_inset_shadow_node_get_blur_radius (node) * scale;
op->spread = gsk_inset_shadow_node_get_spread (node) * scale;
op->offset[0] = gsk_inset_shadow_node_get_dx (node) * scale;
op->offset[1] = -gsk_inset_shadow_node_get_dy (node) * scale;
ops_draw (builder, vertex_data);
}
@@ -1387,24 +1385,24 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self,
const float scale = ops_get_scale (builder);
const float spread = gsk_outset_shadow_node_get_spread (node);
GskRoundedRect r = *gsk_outset_shadow_node_peek_outline (node);
RenderOp *op;
OpShadow *op;
ops_set_program (builder, &self->unblurred_outset_shadow_program);
op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
rgba_to_float (gsk_outset_shadow_node_peek_color (node), op->unblurred_outset_shadow.color);
rgba_to_float (gsk_outset_shadow_node_peek_color (node), op->color);
gsk_rounded_rect_shrink (&r, -spread, -spread, -spread, -spread);
rounded_rect_to_floats (self, builder,
&r,
op->unblurred_outset_shadow.outline,
op->unblurred_outset_shadow.corner_widths,
op->unblurred_outset_shadow.corner_heights);
op->outline,
op->corner_widths,
op->corner_heights);
op->unblurred_outset_shadow.spread = gsk_outset_shadow_node_get_spread (node) * scale;
op->unblurred_outset_shadow.offset[0] = gsk_outset_shadow_node_get_dx (node) * scale;
op->unblurred_outset_shadow.offset[1] = -gsk_outset_shadow_node_get_dy (node) * scale;
op->spread = gsk_outset_shadow_node_get_spread (node) * scale;
op->offset[0] = gsk_outset_shadow_node_get_dx (node) * scale;
op->offset[1] = -gsk_outset_shadow_node_get_dy (node) * scale;
ops_draw (builder, vertex_data);
}
@@ -1426,7 +1424,8 @@ render_outset_shadow_node (GskGLRenderer *self,
const float max_x = min_x + outline->bounds.size.width + (spread + blur_extra/2.0) * 2;
const float max_y = min_y + outline->bounds.size.height + (spread + blur_extra/2.0) * 2;
float texture_width, texture_height;
RenderOp *op;
OpBlur *op;
OpShadow *shadow;
graphene_matrix_t prev_projection;
graphene_rect_t prev_viewport;
graphene_matrix_t item_proj;
@@ -1513,9 +1512,9 @@ render_outset_shadow_node (GskGLRenderer *self,
ops_set_program (builder, &self->blur_program);
op = ops_begin (builder, OP_CHANGE_BLUR);
op->blur.size.width = texture_width;
op->blur.size.height = texture_height;
op->blur.radius = blur_radius;
op->size.width = texture_width;
op->size.height = texture_height;
op->radius = blur_radius;
ops_push_clip (builder, &blit_clip);
ops_set_texture (builder, texture_id);
@@ -1550,12 +1549,12 @@ render_outset_shadow_node (GskGLRenderer *self,
ops_set_program (builder, &self->outset_shadow_program);
ops_set_texture (builder, blurred_texture_id);
op = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
shadow = ops_begin (builder, OP_CHANGE_OUTSET_SHADOW);
rounded_rect_to_floats (self, builder,
outline,
op->outset_shadow.outline,
op->outset_shadow.corner_widths,
op->outset_shadow.corner_heights);
shadow->outline,
shadow->corner_widths,
shadow->corner_heights);
/* We use the one outset shadow op from above to draw all 8 sides/corners. */
{
@@ -1891,7 +1890,7 @@ render_cross_fade_node (GskGLRenderer *self,
TextureRegion start_region;
TextureRegion end_region;
gboolean is_offscreen1, is_offscreen2;
RenderOp *op;
OpCrossFade *op;
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
@@ -1920,8 +1919,8 @@ render_cross_fade_node (GskGLRenderer *self,
ops_set_program (builder, &self->cross_fade_program);
op = ops_begin (builder, OP_CHANGE_CROSS_FADE);
op->cross_fade.progress = progress;
op->cross_fade.source2 = end_region.texture_id;
op->progress = progress;
op->source2 = end_region.texture_id;
ops_set_texture (builder, start_region.texture_id);
@@ -1942,7 +1941,7 @@ render_blend_node (GskGLRenderer *self,
TextureRegion top_region;
TextureRegion bottom_region;
gboolean is_offscreen1, is_offscreen2;
RenderOp *op;
OpBlend *op;
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
@@ -1971,8 +1970,8 @@ render_blend_node (GskGLRenderer *self,
ops_set_texture (builder, bottom_region.texture_id);
op = ops_begin (builder, OP_CHANGE_BLEND);
op->blend.source2 = top_region.texture_id;
op->blend.mode = gsk_blend_node_get_blend_mode (node);
op->source2 = top_region.texture_id;
op->mode = gsk_blend_node_get_blend_mode (node);
ops_draw (builder, vertex_data);
}
@@ -1990,7 +1989,7 @@ render_repeat_node (GskGLRenderer *self,
const graphene_rect_t *child_bounds = gsk_repeat_node_peek_child_bounds (node);
TextureRegion region;
gboolean is_offscreen;
RenderOp *op;
OpRepeat *op;
if (child_bounds != NULL &&
!graphene_rect_equal (child_bounds, &child->bounds))
@@ -2011,23 +2010,23 @@ render_repeat_node (GskGLRenderer *self,
ops_set_texture (builder, region.texture_id);
op = ops_begin (builder, OP_CHANGE_REPEAT);
op->repeat.child_bounds[0] = 0; /* Both currently unused */
op->repeat.child_bounds[1] = 0;
op->repeat.child_bounds[2] = node->bounds.size.width / child_bounds->size.width;
op->repeat.child_bounds[3] = node->bounds.size.height / child_bounds->size.height;
op->child_bounds[0] = 0; /* Both currently unused */
op->child_bounds[1] = 0;
op->child_bounds[2] = node->bounds.size.width / child_bounds->size.width;
op->child_bounds[3] = node->bounds.size.height / child_bounds->size.height;
op->repeat.texture_rect[0] = region.x;
op->repeat.texture_rect[2] = region.x2;
op->texture_rect[0] = region.x;
op->texture_rect[2] = region.x2;
if (is_offscreen)
{
op->repeat.texture_rect[1] = region.y2;
op->repeat.texture_rect[3] = region.y;
op->texture_rect[1] = region.y2;
op->texture_rect[3] = region.y;
}
else
{
op->repeat.texture_rect[1] = region.y;
op->repeat.texture_rect[3] = region.y2;
op->texture_rect[1] = region.y;
op->texture_rect[3] = region.y2;
}
if (is_offscreen)
@@ -2061,10 +2060,12 @@ render_repeat_node (GskGLRenderer *self,
}
static inline void
apply_viewport_op (const Program *program,
const RenderOp *op)
apply_viewport_op (const Program *program,
const OpViewport *op)
{
OP_PRINT (" -> New Viewport: %f, %f, %f, %f", op->viewport.origin.x, op->viewport.origin.y, op->viewport.size.width, op->viewport.size.height);
OP_PRINT (" -> New Viewport: %f, %f, %f, %f",
op->viewport.origin.x, op->viewport.origin.y,
op->viewport.size.width, op->viewport.size.height);
glUniform4f (program->viewport_location,
op->viewport.origin.x, op->viewport.origin.y,
op->viewport.size.width, op->viewport.size.height);
@@ -2073,38 +2074,38 @@ apply_viewport_op (const Program *program,
static inline void
apply_modelview_op (const Program *program,
const RenderOp *op)
const OpMatrix *op)
{
float mat[16];
OP_PRINT (" -> Modelview");
graphene_matrix_to_float (&op->modelview, mat);
graphene_matrix_to_float (&op->matrix, mat);
glUniformMatrix4fv (program->modelview_location, 1, GL_FALSE, mat);
}
static inline void
apply_projection_op (const Program *program,
const RenderOp *op)
const OpMatrix *op)
{
float mat[16];
OP_PRINT (" -> Projection");
graphene_matrix_to_float (&op->projection, mat);
graphene_matrix_to_float (&op->matrix, mat);
glUniformMatrix4fv (program->projection_location, 1, GL_FALSE, mat);
}
static inline void
apply_program_op (const Program *program,
const RenderOp *op)
const OpProgram *op)
{
OP_PRINT (" -> Program: %d", op->program->index);
glUseProgram (op->program->id);
}
static inline void
apply_render_target_op (GskGLRenderer *self,
const Program *program,
const RenderOp *op)
apply_render_target_op (GskGLRenderer *self,
const Program *program,
const OpRenderTarget *op)
{
OP_PRINT (" -> Render Target: %d", op->render_target_id);
@@ -2117,25 +2118,26 @@ apply_render_target_op (GskGLRenderer *self,
}
static inline void
apply_color_op (const Program *program,
const RenderOp *op)
apply_color_op (const Program *program,
const OpColor *op)
{
OP_PRINT (" -> Color: (%f, %f, %f, %f)", op->color.red, op->color.green, op->color.blue, op->color.alpha);
OP_PRINT (" -> Color: (%f, %f, %f, %f)",
op->rgba.red, op->rgba.green, op->rgba.blue, op->rgba.alpha);
glUniform4f (program->color.color_location,
op->color.red, op->color.green, op->color.blue, op->color.alpha);
op->rgba.red, op->rgba.green, op->rgba.blue, op->rgba.alpha);
}
static inline void
apply_opacity_op (const Program *program,
const RenderOp *op)
apply_opacity_op (const Program *program,
const OpOpacity *op)
{
OP_PRINT (" -> Opacity %f", op->opacity);
glUniform1f (program->alpha_location, op->opacity);
}
static inline void
apply_source_texture_op (const Program *program,
const RenderOp *op)
apply_source_texture_op (const Program *program,
const OpTexture *op)
{
g_assert(op->texture_id != 0);
OP_PRINT (" -> New texture: %d", op->texture_id);
@@ -2146,22 +2148,22 @@ apply_source_texture_op (const Program *program,
}
static inline void
apply_color_matrix_op (const Program *program,
const RenderOp *op)
apply_color_matrix_op (const Program *program,
const OpColorMatrix *op)
{
float mat[16];
float vec[4];
OP_PRINT (" -> Color Matrix");
graphene_matrix_to_float (&op->color_matrix.matrix, mat);
graphene_matrix_to_float (&op->matrix, mat);
glUniformMatrix4fv (program->color_matrix.color_matrix_location, 1, GL_FALSE, mat);
graphene_vec4_to_float (&op->color_matrix.offset, vec);
graphene_vec4_to_float (&op->offset, vec);
glUniform4fv (program->color_matrix.color_offset_location, 1, vec);
}
static inline void
apply_clip_op (const Program *program,
const RenderOp *op)
apply_clip_op (const Program *program,
const OpClip *op)
{
OP_PRINT (" -> Clip (%f, %f, %f, %f) (%f, %f, %f, %f), (%f, %f, %f, %f)",
op->clip.bounds.origin.x, op->clip.bounds.origin.y,
@@ -2192,85 +2194,85 @@ apply_clip_op (const Program *program,
static inline void
apply_inset_shadow_op (const Program *program,
const RenderOp *op)
const OpShadow *op)
{
OP_PRINT (" -> inset shadow. Color: (%f, %f, %f, %f), Offset: (%f, %f), Spread: %f, Outline: (%f, %f, %f, %f) Corner widths: (%f, %f, %f, %f), Corner Heights: (%f, %f, %f, %f)",
op->inset_shadow.color[0],
op->inset_shadow.color[1],
op->inset_shadow.color[2],
op->inset_shadow.color[3],
op->inset_shadow.offset[0],
op->inset_shadow.offset[1],
op->inset_shadow.spread,
op->inset_shadow.outline[0],
op->inset_shadow.outline[1],
op->inset_shadow.outline[2],
op->inset_shadow.outline[3],
op->inset_shadow.corner_widths[0],
op->inset_shadow.corner_widths[1],
op->inset_shadow.corner_widths[2],
op->inset_shadow.corner_widths[3],
op->inset_shadow.corner_heights[0],
op->inset_shadow.corner_heights[1],
op->inset_shadow.corner_heights[2],
op->inset_shadow.corner_heights[3]);
glUniform4fv (program->inset_shadow.color_location, 1, op->inset_shadow.color);
glUniform2fv (program->inset_shadow.offset_location, 1, op->inset_shadow.offset);
glUniform1f (program->inset_shadow.spread_location, op->inset_shadow.spread);
glUniform4fv (program->inset_shadow.outline_location, 1, op->inset_shadow.outline);
glUniform4fv (program->inset_shadow.corner_widths_location, 1, op->inset_shadow.corner_widths);
glUniform4fv (program->inset_shadow.corner_heights_location, 1, op->inset_shadow.corner_heights);
op->color[0],
op->color[1],
op->color[2],
op->color[3],
op->offset[0],
op->offset[1],
op->spread,
op->outline[0],
op->outline[1],
op->outline[2],
op->outline[3],
op->corner_widths[0],
op->corner_widths[1],
op->corner_widths[2],
op->corner_widths[3],
op->corner_heights[0],
op->corner_heights[1],
op->corner_heights[2],
op->corner_heights[3]);
glUniform4fv (program->inset_shadow.color_location, 1, op->color);
glUniform2fv (program->inset_shadow.offset_location, 1, op->offset);
glUniform1f (program->inset_shadow.spread_location, op->spread);
glUniform4fv (program->inset_shadow.outline_location, 1, op->outline);
glUniform4fv (program->inset_shadow.corner_widths_location, 1, op->corner_widths);
glUniform4fv (program->inset_shadow.corner_heights_location, 1, op->corner_heights);
}
static inline void
apply_unblurred_outset_shadow_op (const Program *program,
const RenderOp *op)
const OpShadow *op)
{
OP_PRINT (" -> unblurred outset shadow");
glUniform4fv (program->unblurred_outset_shadow.color_location, 1, op->unblurred_outset_shadow.color);
glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->unblurred_outset_shadow.offset);
glUniform1f (program->unblurred_outset_shadow.spread_location, op->unblurred_outset_shadow.spread);
glUniform4fv (program->unblurred_outset_shadow.outline_location, 1, op->unblurred_outset_shadow.outline);
glUniform4fv (program->unblurred_outset_shadow.color_location, 1, op->color);
glUniform2fv (program->unblurred_outset_shadow.offset_location, 1, op->offset);
glUniform1f (program->unblurred_outset_shadow.spread_location, op->spread);
glUniform4fv (program->unblurred_outset_shadow.outline_location, 1, op->outline);
glUniform4fv (program->unblurred_outset_shadow.corner_widths_location, 1,
op->unblurred_outset_shadow.corner_widths);
op->corner_widths);
glUniform4fv (program->unblurred_outset_shadow.corner_heights_location, 1,
op->unblurred_outset_shadow.corner_heights);
op->corner_heights);
}
static inline void
apply_outset_shadow_op (const Program *program,
const RenderOp *op)
const OpShadow *op)
{
OP_PRINT (" -> outset shadow");
glUniform4fv (program->outset_shadow.outline_location, 1, op->outset_shadow.outline);
glUniform4fv (program->outset_shadow.corner_widths_location, 1, op->outset_shadow.corner_widths);
glUniform4fv (program->outset_shadow.corner_heights_location, 1, op->outset_shadow.corner_heights);
glUniform4fv (program->outset_shadow.outline_location, 1, op->outline);
glUniform4fv (program->outset_shadow.corner_widths_location, 1, op->corner_widths);
glUniform4fv (program->outset_shadow.corner_heights_location, 1, op->corner_heights);
}
static inline void
apply_linear_gradient_op (const Program *program,
const RenderOp *op)
apply_linear_gradient_op (const Program *program,
const OpLinearGradient *op)
{
OP_PRINT (" -> Linear gradient");
glUniform1i (program->linear_gradient.num_color_stops_location,
op->linear_gradient.n_color_stops);
op->n_color_stops);
glUniform4fv (program->linear_gradient.color_stops_location,
op->linear_gradient.n_color_stops,
op->linear_gradient.color_stops);
op->n_color_stops,
op->color_stops);
glUniform1fv (program->linear_gradient.color_offsets_location,
op->linear_gradient.n_color_stops,
op->linear_gradient.color_offsets);
op->n_color_stops,
op->color_offsets);
glUniform2f (program->linear_gradient.start_point_location,
op->linear_gradient.start_point.x, op->linear_gradient.start_point.y);
op->start_point.x, op->start_point.y);
glUniform2f (program->linear_gradient.end_point_location,
op->linear_gradient.end_point.x, op->linear_gradient.end_point.y);
op->end_point.x, op->end_point.y);
}
static inline void
apply_border_op (const Program *program,
const RenderOp *op)
const OpBorder *op)
{
const GskRoundedRect *o = &op->border.outline;
const GskRoundedRect *o = &op->outline;
float outline[4];
float widths[4];
float heights[4];
@@ -2295,63 +2297,63 @@ apply_border_op (const Program *program,
static inline void
apply_border_width_op (const Program *program,
const RenderOp *op)
const OpBorder *op)
{
OP_PRINT (" -> Border width (%f, %f, %f, %f)",
op->border.widths[0], op->border.widths[1], op->border.widths[2], op->border.widths[3]);
op->widths[0], op->widths[1], op->widths[2], op->widths[3]);
glUniform4fv (program->border.widths_location, 1, op->border.widths);
glUniform4fv (program->border.widths_location, 1, op->widths);
}
static inline void
apply_border_color_op (const Program *program,
const RenderOp *op)
const OpBorder *op)
{
OP_PRINT (" -> Border color (%f, %f, %f, %f)",
op->border.color[0], op->border.color[1], op->border.color[2], op->border.color[3]);
glUniform4fv (program->border.color_location, 1, op->border.color);
op->color[0], op->color[1], op->color[2], op->color[3]);
glUniform4fv (program->border.color_location, 1, op->color);
}
static inline void
apply_blur_op (const Program *program,
const RenderOp *op)
apply_blur_op (const Program *program,
const OpBlur *op)
{
OP_PRINT (" -> Blur");
glUniform1f (program->blur.blur_radius_location, op->blur.radius);
glUniform2f (program->blur.blur_size_location, op->blur.size.width, op->blur.size.height);
/*glUniform2f (program->blur.dir_location, op->blur.dir[0], op->blur.dir[1]);*/
glUniform1f (program->blur.blur_radius_location, op->radius);
glUniform2f (program->blur.blur_size_location, op->size.width, op->size.height);
/*glUniform2f (program->blur.dir_location, op->dir[0], op->dir[1]);*/
}
static inline void
apply_cross_fade_op (const Program *program,
const RenderOp *op)
apply_cross_fade_op (const Program *program,
const OpCrossFade *op)
{
/* End texture id */
glUniform1i (program->cross_fade.source2_location, 1);
glActiveTexture (GL_TEXTURE0 + 1);
glBindTexture (GL_TEXTURE_2D, op->cross_fade.source2);
glBindTexture (GL_TEXTURE_2D, op->source2);
/* progress */
glUniform1f (program->cross_fade.progress_location, op->cross_fade.progress);
glUniform1f (program->cross_fade.progress_location, op->progress);
}
static inline void
apply_blend_op (const Program *program,
const RenderOp *op)
apply_blend_op (const Program *program,
const OpBlend *op)
{
/* End texture id */
glUniform1i (program->blend.source2_location, 1);
glActiveTexture (GL_TEXTURE0 + 1);
glBindTexture (GL_TEXTURE_2D, op->blend.source2);
glBindTexture (GL_TEXTURE_2D, op->source2);
/* progress */
glUniform1i (program->blend.mode_location, op->blend.mode);
glUniform1i (program->blend.mode_location, op->mode);
}
static inline void
apply_repeat_op (const Program *program,
const RenderOp *op)
const OpRepeat *op)
{
glUniform4fv (program->repeat.child_bounds_location, 1, op->repeat.child_bounds);
glUniform4fv (program->repeat.texture_rect_location, 1, op->repeat.texture_rect);
glUniform4fv (program->repeat.child_bounds_location, 1, op->child_bounds);
glUniform4fv (program->repeat.texture_rect_location, 1, op->texture_rect);
}
static void
@@ -2359,7 +2361,6 @@ gsk_gl_renderer_dispose (GObject *gobject)
{
GskGLRenderer *self = GSK_GL_RENDERER (gobject);
g_clear_pointer (&self->render_ops, g_array_unref);
ops_free (&self->op_builder);
G_OBJECT_CLASS (gsk_gl_renderer_parent_class)->dispose (gobject);
@@ -2647,7 +2648,7 @@ gsk_gl_renderer_unrealize (GskRenderer *renderer)
/* We don't need to iterate to destroy the associated GL resources,
* as they will be dropped when we finalize the GskGLDriver
*/
g_array_set_size (self->render_ops, 0);
ops_reset (&self->op_builder);
for (i = 0; i < GL_N_PROGRAMS; i ++)
glDeleteProgram (self->programs[i].id);
@@ -2676,7 +2677,7 @@ gsk_gl_renderer_clear_tree (GskGLRenderer *self)
gdk_gl_context_make_current (self->gl_context);
g_array_remove_range (self->render_ops, 0, self->render_ops->len);
ops_reset (&self->op_builder);
removed_textures = gsk_gl_driver_collect_textures (self->gl_driver);
GSK_RENDERER_NOTE (GSK_RENDERER (self), OPENGL, g_message ("Collected: %d textures", removed_textures));
@@ -2987,14 +2988,14 @@ add_offscreen_ops (GskGLRenderer *self,
}
static void
gsk_gl_renderer_render_ops (GskGLRenderer *self,
gsize vertex_data_size)
gsk_gl_renderer_render_ops (GskGLRenderer *self)
{
guint i;
guint n_ops = self->render_ops->len;
const Program *program = NULL;
gsize buffer_index = 0;
float *vertex_data = g_malloc (vertex_data_size);
gsize vertex_data_size = self->op_builder.vertices->len * sizeof (GskQuadVertex);
float *vertex_data = (float*)self->op_builder.vertices->data;
OpBufferIter iter;
OpKind kind;
gpointer ptr;
/*g_message ("%s: Buffer size: %ld", __FUNCTION__, vertex_data_size);*/
@@ -3006,19 +3007,6 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
glGenBuffers (1, &buffer_id);
glBindBuffer (GL_ARRAY_BUFFER, buffer_id);
// Fill buffer data
for (i = 0; i < n_ops; i ++)
{
const RenderOp *op = &g_array_index (self->render_ops, RenderOp, i);
if (op->op == OP_CHANGE_VAO)
{
memcpy (vertex_data + buffer_index, &op->vertex_data, sizeof (GskQuadVertex) * GL_N_VERTICES);
buffer_index += sizeof (GskQuadVertex) * GL_N_VERTICES / sizeof (float);
}
}
// Set buffer data
glBufferData (GL_ARRAY_BUFFER, vertex_data_size, vertex_data, GL_STATIC_DRAW);
@@ -3035,41 +3023,42 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
sizeof (GskQuadVertex),
(void *) G_STRUCT_OFFSET (GskQuadVertex, uv));
for (i = 0; i < n_ops; i ++)
op_buffer_iter_init (&iter, ops_get_buffer (&self->op_builder));
while ((ptr = op_buffer_iter_next (&iter, &kind)))
{
const RenderOp *op = &g_array_index (self->render_ops, RenderOp, i);
if (op->op == OP_NONE ||
op->op == OP_CHANGE_VAO)
if (kind == OP_NONE)
continue;
if (program == NULL &&
op->op != OP_PUSH_DEBUG_GROUP &&
op->op != OP_POP_DEBUG_GROUP &&
op->op != OP_CHANGE_PROGRAM &&
op->op != OP_CHANGE_RENDER_TARGET &&
op->op != OP_CLEAR)
kind != OP_PUSH_DEBUG_GROUP &&
kind != OP_POP_DEBUG_GROUP &&
kind != OP_CHANGE_PROGRAM &&
kind != OP_CHANGE_RENDER_TARGET &&
kind != OP_CLEAR)
continue;
OP_PRINT ("Op %u: %u", i, op->op);
OP_PRINT ("Op %u: %u", iter.pos - 2, kind);
switch (op->op)
switch (kind)
{
case OP_CHANGE_PROJECTION:
apply_projection_op (program, op);
apply_projection_op (program, ptr);
break;
case OP_CHANGE_MODELVIEW:
apply_modelview_op (program, op);
apply_modelview_op (program, ptr);
break;
case OP_CHANGE_PROGRAM:
apply_program_op (program, op);
program = op->program;
break;
{
const OpProgram *op = ptr;
apply_program_op (program, op);
program = op->program;
break;
}
case OP_CHANGE_RENDER_TARGET:
apply_render_target_op (self, program, op);
apply_render_target_op (self, program, ptr);
break;
case OP_CLEAR:
@@ -3078,95 +3067,108 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
break;
case OP_CHANGE_VIEWPORT:
apply_viewport_op (program, op);
apply_viewport_op (program, ptr);
break;
case OP_CHANGE_OPACITY:
apply_opacity_op (program, op);
apply_opacity_op (program, ptr);
break;
case OP_CHANGE_COLOR_MATRIX:
apply_color_matrix_op (program, op);
apply_color_matrix_op (program, ptr);
break;
case OP_CHANGE_COLOR:
/*g_assert (program == &self->color_program || program == &self->coloring_program ||*/
/*program == &self->shadow_program);*/
apply_color_op (program, op);
apply_color_op (program, ptr);
break;
case OP_CHANGE_BORDER_COLOR:
apply_border_color_op (program, op);
apply_border_color_op (program, ptr);
break;
case OP_CHANGE_CLIP:
apply_clip_op (program, op);
apply_clip_op (program, ptr);
break;
case OP_CHANGE_SOURCE_TEXTURE:
apply_source_texture_op (program, op);
apply_source_texture_op (program, ptr);
break;
case OP_CHANGE_CROSS_FADE:
g_assert (program == &self->cross_fade_program);
apply_cross_fade_op (program, op);
apply_cross_fade_op (program, ptr);
break;
case OP_CHANGE_BLEND:
g_assert (program == &self->blend_program);
apply_blend_op (program, op);
apply_blend_op (program, ptr);
break;
case OP_CHANGE_LINEAR_GRADIENT:
apply_linear_gradient_op (program, op);
apply_linear_gradient_op (program, ptr);
break;
case OP_CHANGE_BLUR:
apply_blur_op (program, op);
apply_blur_op (program, ptr);
break;
case OP_CHANGE_INSET_SHADOW:
apply_inset_shadow_op (program, op);
apply_inset_shadow_op (program, ptr);
break;
case OP_CHANGE_OUTSET_SHADOW:
apply_outset_shadow_op (program, op);
apply_outset_shadow_op (program, ptr);
break;
case OP_CHANGE_BORDER:
apply_border_op (program, op);
apply_border_op (program, ptr);
break;
case OP_CHANGE_BORDER_WIDTH:
apply_border_width_op (program, op);
apply_border_width_op (program, ptr);
break;
case OP_CHANGE_UNBLURRED_OUTSET_SHADOW:
apply_unblurred_outset_shadow_op (program, op);
apply_unblurred_outset_shadow_op (program, ptr);
break;
case OP_CHANGE_REPEAT:
apply_repeat_op (program, op);
apply_repeat_op (program, ptr);
break;
case OP_DRAW:
OP_PRINT (" -> draw %ld, size %ld and program %d\n",
op->draw.vao_offset, op->draw.vao_size, program->index);
glDrawArrays (GL_TRIANGLES, op->draw.vao_offset, op->draw.vao_size);
break;
{
const OpDraw *op = ptr;
OP_PRINT (" -> draw %ld, size %ld and program %d\n",
op->vao_offset, op->vao_size, program->index);
glDrawArrays (GL_TRIANGLES, op->vao_offset, op->vao_size);
break;
}
case OP_DUMP_FRAMEBUFFER:
dump_framebuffer (op->dump.filename, op->dump.width, op->dump.height);
break;
{
const OpDumpFrameBuffer *op = ptr;
dump_framebuffer (op->filename, op->width, op->height);
break;
}
case OP_PUSH_DEBUG_GROUP:
gdk_gl_context_push_debug_group (self->gl_context, op->debug_group.text);
break;
{
const OpDebugGroup *op = ptr;
gdk_gl_context_push_debug_group (self->gl_context, op->text);
break;
}
case OP_POP_DEBUG_GROUP:
gdk_gl_context_pop_debug_group (self->gl_context);
break;
case OP_NONE:
case OP_LAST:
default:
g_warn_if_reached ();
}
@@ -3174,9 +3176,6 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
OP_PRINT ("\n");
}
/* Done drawing, destroy the buffer again.
* TODO: Can we reuse the memory, though? */
g_free (vertex_data);
glDeleteVertexArrays (1, &vao_id);
glDeleteBuffers (1, &buffer_id);
}
@@ -3190,7 +3189,6 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
{
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
graphene_matrix_t projection;
gsize buffer_size;
#ifdef G_ENABLE_DEBUG
GskProfiler *profiler;
gint64 gpu_time, cpu_time, start_time;
@@ -3267,7 +3265,6 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
g_assert_cmpint (self->op_builder.current_render_target, ==, fbo_id);
ops_pop_modelview (&self->op_builder);
ops_pop_clip (&self->op_builder);
buffer_size = self->op_builder.buffer_size;
ops_finish (&self->op_builder);
/*g_message ("Ops: %u", self->render_ops->len);*/
@@ -3295,7 +3292,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
glBlendEquation (GL_FUNC_ADD);
gdk_gl_context_push_debug_group (self->gl_context, "Rendering ops");
gsk_gl_renderer_render_ops (self, buffer_size);
gsk_gl_renderer_render_ops (self);
gdk_gl_context_pop_debug_group (self->gl_context);
#ifdef G_ENABLE_DEBUG
@@ -3462,11 +3459,8 @@ gsk_gl_renderer_init (GskGLRenderer *self)
{
gsk_ensure_resources ();
self->render_ops = g_array_new (FALSE, FALSE, sizeof (RenderOp));
ops_init (&self->op_builder);
self->op_builder.renderer = self;
self->op_builder.render_ops = self->render_ops;
#ifdef G_ENABLE_DEBUG
{

View File

@@ -28,7 +28,6 @@ ops_finish (RenderOpBuilder *builder)
g_array_free (builder->clip_stack, TRUE);
builder->clip_stack = NULL;
builder->buffer_size = 0;
builder->dx = 0;
builder->dy = 0;
builder->current_modelview = NULL;
@@ -57,23 +56,23 @@ ops_dump_framebuffer (RenderOpBuilder *builder,
int width,
int height)
{
RenderOp *op;
OpDumpFrameBuffer *op;
op = ops_begin (builder, OP_DUMP_FRAMEBUFFER);
op->dump.filename = g_strdup (filename);
op->dump.width = width;
op->dump.height = height;
op->filename = g_strdup (filename);
op->width = width;
op->height = height;
}
void
ops_push_debug_group (RenderOpBuilder *builder,
const char *text)
{
RenderOp *op;
OpDebugGroup *op;
op = ops_begin (builder, OP_PUSH_DEBUG_GROUP);
strncpy (op->debug_group.text, text, sizeof(op->debug_group.text) - 1);
op->debug_group.text[sizeof(op->debug_group.text) - 1] = 0; /* Ensure zero terminated */
strncpy (op->text, text, sizeof(op->text) - 1);
op->text[sizeof(op->text) - 1] = 0; /* Ensure zero terminated */
}
void
@@ -182,6 +181,9 @@ ops_init (RenderOpBuilder *builder)
builder->current_opacity = 1.0f;
op_buffer_init (&builder->render_ops);
builder->vertices = g_array_new (FALSE, TRUE, sizeof (GskQuadVertex));
for (i = 0; i < GL_N_PROGRAMS; i ++)
{
builder->program_state[i].opacity = 1.0f;
@@ -197,6 +199,9 @@ ops_free (RenderOpBuilder *builder)
{
gsk_transform_unref (builder->program_state[i].modelview);
}
g_array_unref (builder->vertices);
op_buffer_destroy (&builder->render_ops);
}
void
@@ -208,7 +213,7 @@ ops_set_program (RenderOpBuilder *builder,
static const GskRoundedRect empty_clip;
static const graphene_matrix_t empty_matrix;
static const graphene_rect_t empty_rect;
RenderOp *op;
OpProgram *op;
ProgramState *program_state;
if (builder->current_program == program)
@@ -225,16 +230,20 @@ ops_set_program (RenderOpBuilder *builder,
if (memcmp (&empty_matrix, &program_state->projection, sizeof (graphene_matrix_t)) == 0 ||
memcmp (&builder->current_projection, &program_state->projection, sizeof (graphene_matrix_t)) != 0)
{
op = ops_begin (builder, OP_CHANGE_PROJECTION);
op->projection = builder->current_projection;
OpMatrix *opm;
opm = ops_begin (builder, OP_CHANGE_PROJECTION);
opm->matrix = builder->current_projection;
program_state->projection = builder->current_projection;
}
if (program_state->modelview == NULL ||
!gsk_transform_equal (builder->current_modelview, program_state->modelview))
{
op = ops_begin (builder, OP_CHANGE_MODELVIEW);
gsk_transform_to_matrix (builder->current_modelview, &op->modelview);
OpMatrix *opm;
opm = ops_begin (builder, OP_CHANGE_MODELVIEW);
gsk_transform_to_matrix (builder->current_modelview, &opm->matrix);
gsk_transform_unref (program_state->modelview);
program_state->modelview = gsk_transform_ref (builder->current_modelview);
}
@@ -242,23 +251,29 @@ ops_set_program (RenderOpBuilder *builder,
if (rect_equal (&empty_rect, &program_state->viewport) ||
!rect_equal (&builder->current_viewport, &program_state->viewport))
{
op = ops_begin (builder, OP_CHANGE_VIEWPORT);
op->viewport = builder->current_viewport;
OpViewport *opv;
opv = ops_begin (builder, OP_CHANGE_VIEWPORT);
opv->viewport = builder->current_viewport;
program_state->viewport = builder->current_viewport;
}
if (memcmp (&empty_clip, &program_state->clip, sizeof (GskRoundedRect)) == 0 ||
memcmp (&builder->current_clip, &program_state->clip, sizeof (GskRoundedRect)) != 0)
{
op = ops_begin (builder, OP_CHANGE_CLIP);
op->clip = *builder->current_clip;
OpClip *opc;
opc = ops_begin (builder, OP_CHANGE_CLIP);
opc->clip = *builder->current_clip;
program_state->clip = *builder->current_clip;
}
if (program_state->opacity != builder->current_opacity)
{
op = ops_begin (builder, OP_CHANGE_OPACITY);
op->opacity = builder->current_opacity;
OpOpacity *opo;
opo = ops_begin (builder, OP_CHANGE_OPACITY);
opo->opacity = builder->current_opacity;
program_state->opacity = builder->current_opacity;
}
}
@@ -267,29 +282,17 @@ static void
ops_set_clip (RenderOpBuilder *builder,
const GskRoundedRect *clip)
{
RenderOp *last_op;
ProgramState *current_program_state = get_current_program_state (builder);
OpClip *op;
if (current_program_state &&
memcmp (&current_program_state->clip, clip,sizeof (GskRoundedRect)) == 0)
return;
if (builder->render_ops->len > 0)
{
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_CLIP)))
op = op_buffer_add (&builder->render_ops, OP_CHANGE_CLIP);
if (last_op->op == OP_CHANGE_CLIP)
{
last_op->clip = *clip;
}
else
{
RenderOp *op;
op = ops_begin (builder, OP_CHANGE_CLIP);
op->clip = *clip;
}
}
op->clip = *clip;
if (builder->current_program != NULL)
current_program_state->clip = *clip;
@@ -343,8 +346,8 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
GskTransform *transform)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
graphene_matrix_t matrix;
OpMatrix *op;
#if 0
XXX This is not possible if we want pop() to work.
@@ -355,24 +358,10 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
gsk_transform_to_matrix (transform, &matrix);
if (builder->render_ops->len > 0)
{
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
if (last_op->op == OP_CHANGE_MODELVIEW)
{
last_op->modelview = matrix;
}
else
{
op = ops_begin (builder, OP_CHANGE_MODELVIEW);
op->modelview = matrix;
}
}
else
{
op = ops_begin (builder, OP_CHANGE_MODELVIEW);
op->modelview = matrix;
}
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_MODELVIEW)))
op = op_buffer_add (&builder->render_ops, OP_CHANGE_MODELVIEW);
op->matrix = matrix;
if (builder->current_program != NULL)
{
@@ -490,27 +479,13 @@ ops_set_projection (RenderOpBuilder *builder,
const graphene_matrix_t *projection)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
graphene_matrix_t prev_mv;
OpMatrix *op;
if (builder->render_ops->len > 0)
{
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
if (last_op->op == OP_CHANGE_PROJECTION)
{
last_op->projection = *projection;
}
else
{
op = ops_begin (builder, OP_CHANGE_PROJECTION);
op->projection = *projection;
}
}
else
{
op = ops_begin (builder, OP_CHANGE_PROJECTION);
op->projection = *projection;
}
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_PROJECTION)))
op = op_buffer_add (&builder->render_ops, OP_CHANGE_PROJECTION);
op->matrix = *projection;
if (builder->current_program != NULL)
current_program_state->projection = *projection;
@@ -526,7 +501,7 @@ ops_set_viewport (RenderOpBuilder *builder,
const graphene_rect_t *viewport)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
OpViewport *op;
graphene_rect_t prev_viewport;
if (current_program_state != NULL &&
@@ -549,7 +524,7 @@ void
ops_set_texture (RenderOpBuilder *builder,
int texture_id)
{
RenderOp *op;
OpTexture *op;
if (builder->current_texture == texture_id)
return;
@@ -563,7 +538,7 @@ int
ops_set_render_target (RenderOpBuilder *builder,
int render_target_id)
{
RenderOp *op;
OpRenderTarget *op;
int prev_render_target;
if (builder->current_render_target == render_target_id)
@@ -571,24 +546,10 @@ ops_set_render_target (RenderOpBuilder *builder,
prev_render_target = builder->current_render_target;
if (builder->render_ops->len > 0)
{
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
if (last_op->op == OP_CHANGE_RENDER_TARGET)
{
last_op->render_target_id = render_target_id;
}
else
{
op = ops_begin (builder, OP_CHANGE_RENDER_TARGET);
op->render_target_id = render_target_id;
}
}
else
{
op = ops_begin (builder, OP_CHANGE_RENDER_TARGET);
op->render_target_id = render_target_id;
}
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_RENDER_TARGET)))
op = op_buffer_add (&builder->render_ops, OP_CHANGE_RENDER_TARGET);
op->render_target_id = render_target_id;
builder->current_render_target = render_target_id;
@@ -600,32 +561,16 @@ ops_set_opacity (RenderOpBuilder *builder,
float opacity)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
OpOpacity *op;
float prev_opacity;
RenderOp *last_op;
if (builder->current_opacity == opacity)
return opacity;
if (builder->render_ops->len > 0)
{
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_OPACITY)))
op = op_buffer_add (&builder->render_ops, OP_CHANGE_OPACITY);
if (last_op->op == OP_CHANGE_OPACITY)
{
last_op->opacity = opacity;
}
else
{
op = ops_begin (builder, OP_CHANGE_OPACITY);
op->opacity = opacity;
}
}
else
{
op = ops_begin (builder, OP_CHANGE_OPACITY);
op->opacity = opacity;
}
op->opacity = opacity;
prev_opacity = builder->current_opacity;
builder->current_opacity = opacity;
@@ -641,7 +586,7 @@ ops_set_color (RenderOpBuilder *builder,
const GdkRGBA *color)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
OpColor *op;
if (gdk_rgba_equal (color, &current_program_state->color))
return;
@@ -649,7 +594,7 @@ ops_set_color (RenderOpBuilder *builder,
current_program_state->color = *color;
op = ops_begin (builder, OP_CHANGE_COLOR);
op->color = *color;
op->rgba = *color;
}
void
@@ -658,7 +603,7 @@ ops_set_color_matrix (RenderOpBuilder *builder,
const graphene_vec4_t *offset)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
OpColorMatrix *op;
if (memcmp (matrix,
&current_program_state->color_matrix.matrix,
@@ -672,8 +617,8 @@ ops_set_color_matrix (RenderOpBuilder *builder,
current_program_state->color_matrix.offset = *offset;
op = ops_begin (builder, OP_CHANGE_COLOR_MATRIX);
op->color_matrix.matrix = *matrix;
op->color_matrix.offset = *offset;
op->matrix = *matrix;
op->offset = *offset;
}
void
@@ -681,7 +626,7 @@ ops_set_border (RenderOpBuilder *builder,
const GskRoundedRect *outline)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
OpBorder *op;
if (memcmp (&current_program_state->border.outline,
outline, sizeof (GskRoundedRect)) == 0)
@@ -690,7 +635,7 @@ ops_set_border (RenderOpBuilder *builder,
current_program_state->border.outline = *outline;
op = ops_begin (builder, OP_CHANGE_BORDER);
op->border.outline = *outline;
op->outline = *outline;
}
void
@@ -698,7 +643,7 @@ ops_set_border_width (RenderOpBuilder *builder,
const float *widths)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp *op;
OpBorder *op;
if (memcmp (current_program_state->border.widths,
widths, sizeof (float) * 4) == 0)
@@ -708,10 +653,10 @@ ops_set_border_width (RenderOpBuilder *builder,
widths, sizeof (float) * 4);
op = ops_begin (builder, OP_CHANGE_BORDER_WIDTH);
op->border.widths[0] = widths[0];
op->border.widths[1] = widths[1];
op->border.widths[2] = widths[2];
op->border.widths[3] = widths[3];
op->widths[0] = widths[0];
op->widths[1] = widths[1];
op->widths[2] = widths[2];
op->widths[3] = widths[3];
}
void
@@ -719,68 +664,37 @@ ops_set_border_color (RenderOpBuilder *builder,
const GdkRGBA *color)
{
ProgramState *current_program_state = get_current_program_state (builder);
RenderOp op;
op.op = OP_CHANGE_BORDER_COLOR;
rgba_to_float (color, op.border.color);
OpBorder *op;
float fcolor[4];
if (memcmp (&op.border.color, &current_program_state->border.color,
sizeof (float) * 4) == 0)
rgba_to_float (color, fcolor);
if (memcmp (fcolor, &current_program_state->border.color, sizeof fcolor) == 0)
return;
rgba_to_float (color, current_program_state->border.color);
g_array_append_val (builder->render_ops, op);
op = op_buffer_add (&builder->render_ops, OP_CHANGE_BORDER_COLOR);
memcpy (op->color, fcolor, sizeof (float[4]));
memcpy (current_program_state->border.color, fcolor, sizeof (float[4]));
}
void
ops_draw (RenderOpBuilder *builder,
const GskQuadVertex vertex_data[GL_N_VERTICES])
{
RenderOp *last_op;
OpDraw *op;
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
/* If the previous op was a DRAW as well, we didn't change anything between the two calls,
* so these are just 2 subsequent draw calls. Same VAO, same program etc.
* And the offsets into the vao are in order as well, so make it one draw call. */
if (last_op->op == OP_DRAW)
if ((op = op_buffer_peek_tail_checked (&builder->render_ops, OP_DRAW)))
{
/* We allow ourselves a little trick here. We still have to add a CHANGE_VAO op for
* this draw call so we can add our vertex data there, but we want it to be placed before
* the last draw call, so we reorder those. */
RenderOp *new_draw;
new_draw = ops_begin (builder, OP_DRAW);
/* last_op may have moved in memory */
last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 2);
new_draw->draw.vao_offset = last_op->draw.vao_offset;
new_draw->draw.vao_size = last_op->draw.vao_size + GL_N_VERTICES;
last_op->op = OP_CHANGE_VAO;
memcpy (&last_op->vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
op->vao_size += GL_N_VERTICES;
}
else
{
const gsize n_ops = builder->render_ops->len;
RenderOp *op;
gsize offset = builder->buffer_size / sizeof (GskQuadVertex);
/* We will add two render ops here. */
g_array_set_size (builder->render_ops, n_ops + 2);
op = &g_array_index (builder->render_ops, RenderOp, n_ops);
op->op = OP_CHANGE_VAO;
memcpy (&op->vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
op = &g_array_index (builder->render_ops, RenderOp, n_ops + 1);
op->op = OP_DRAW;
op->draw.vao_offset = offset;
op->draw.vao_size = GL_N_VERTICES;
op = op_buffer_add (&builder->render_ops, OP_DRAW);
op->vao_offset = builder->vertices->len;
op->vao_size = GL_N_VERTICES;
}
/* We added new vertex data in both cases so increase the buffer size */
builder->buffer_size += sizeof (GskQuadVertex) * GL_N_VERTICES;
g_array_append_vals (builder->vertices, vertex_data, GL_N_VERTICES);
}
/* The offset is only valid for the current modelview.
@@ -795,15 +709,22 @@ ops_offset (RenderOpBuilder *builder,
builder->dy += y;
}
RenderOp *
gpointer
ops_begin (RenderOpBuilder *builder,
guint kind)
OpKind kind)
{
RenderOp *op;
g_array_set_size (builder->render_ops, builder->render_ops->len + 1);
op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
op->op = kind;
return op;
return op_buffer_add (&builder->render_ops, kind);
}
void
ops_reset (RenderOpBuilder *builder)
{
op_buffer_clear (&builder->render_ops);
g_array_set_size (builder->vertices, 0);
}
OpBuffer *
ops_get_buffer (RenderOpBuilder *builder)
{
return &builder->render_ops;
}

View File

@@ -10,6 +10,8 @@
#include "gskglrenderer.h"
#include "gskrendernodeprivate.h"
#include "opbuffer.h"
#define GL_N_VERTICES 6
#define GL_N_PROGRAMS 13
@@ -32,38 +34,7 @@ typedef struct
OpsMatrixMetadata metadata;
} MatrixStackEntry;
enum {
OP_NONE,
OP_CHANGE_OPACITY = 1,
OP_CHANGE_COLOR = 2,
OP_CHANGE_PROJECTION = 3,
OP_CHANGE_MODELVIEW = 4,
OP_CHANGE_PROGRAM = 5,
OP_CHANGE_RENDER_TARGET = 6,
OP_CHANGE_CLIP = 7,
OP_CHANGE_VIEWPORT = 8,
OP_CHANGE_SOURCE_TEXTURE = 9,
OP_CHANGE_VAO = 10,
OP_CHANGE_LINEAR_GRADIENT = 11,
OP_CHANGE_COLOR_MATRIX = 12,
OP_CHANGE_BLUR = 13,
OP_CHANGE_INSET_SHADOW = 14,
OP_CHANGE_OUTSET_SHADOW = 15,
OP_CHANGE_BORDER = 16,
OP_CHANGE_BORDER_COLOR = 17,
OP_CHANGE_BORDER_WIDTH = 18,
OP_CHANGE_CROSS_FADE = 19,
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
OP_CLEAR = 21,
OP_DRAW = 22,
OP_DUMP_FRAMEBUFFER = 23,
OP_PUSH_DEBUG_GROUP = 24,
OP_POP_DEBUG_GROUP = 25,
OP_CHANGE_BLEND = 26,
OP_CHANGE_REPEAT = 27,
};
typedef struct
struct _Program
{
int index; /* Into the renderer's program array */
@@ -145,101 +116,7 @@ typedef struct
int texture_rect_location;
} repeat;
};
} Program;
typedef struct
{
guint op;
union {
float opacity;
graphene_matrix_t modelview;
graphene_matrix_t projection;
const Program *program;
int texture_id;
int render_target_id;
GdkRGBA color;
GskQuadVertex vertex_data[6];
GskRoundedRect clip;
graphene_rect_t viewport;
struct {
int n_color_stops;
float color_offsets[8];
float color_stops[4 * 8];
graphene_point_t start_point;
graphene_point_t end_point;
} linear_gradient;
struct {
gsize vao_offset;
gsize vao_size;
} draw;
struct {
graphene_matrix_t matrix;
graphene_vec4_t offset;
} color_matrix;
struct {
float radius;
graphene_size_t size;
float dir[2];
} blur;
struct {
float outline[4];
float corner_widths[4];
float corner_heights[4];
float radius;
float spread;
float offset[2];
float color[4];
} inset_shadow;
struct {
float outline[4];
float corner_widths[4];
float corner_heights[4];
float radius;
float spread;
float offset[2];
float color[4];
} outset_shadow;
struct {
float outline[4];
float corner_widths[4];
float corner_heights[4];
float radius;
float spread;
float offset[2];
float color[4];
} unblurred_outset_shadow;
struct {
float color[4];
} shadow;
struct {
float widths[4];
float color[4];
GskRoundedRect outline;
} border;
struct {
float progress;
int source2;
} cross_fade;
struct {
int source2;
int mode;
} blend;
struct {
float child_bounds[4];
float texture_rect[4];
} repeat;
struct {
char *filename;
int width;
int height;
} dump;
struct {
char text[180]; /* Size of linear_gradient, so 'should be enough' without growing RenderOp */
} debug_group;
};
} RenderOp;
};
typedef struct
{
@@ -276,9 +153,9 @@ typedef struct
float current_opacity;
float dx, dy;
gsize buffer_size;
OpBuffer render_ops;
GArray *vertices;
GArray *render_ops;
GskGLRenderer *renderer;
/* Stack of modelview matrices */
@@ -298,6 +175,7 @@ void ops_dump_framebuffer (RenderOpBuilder *builder,
int height);
void ops_init (RenderOpBuilder *builder);
void ops_free (RenderOpBuilder *builder);
void ops_reset (RenderOpBuilder *builder);
void ops_push_debug_group (RenderOpBuilder *builder,
const char *text);
void ops_pop_debug_group (RenderOpBuilder *builder);
@@ -358,7 +236,8 @@ void ops_offset (RenderOpBuilder *builder,
float x,
float y);
RenderOp *ops_begin (RenderOpBuilder *builder,
guint kind);
gpointer ops_begin (RenderOpBuilder *builder,
OpKind kind);
OpBuffer *ops_get_buffer (RenderOpBuilder *builder);
#endif

133
gsk/gl/opbuffer.c Normal file
View File

@@ -0,0 +1,133 @@
#include "opbuffer.h"
#include <string.h>
static guint op_sizes[OP_LAST] = {
0,
sizeof (OpOpacity),
sizeof (OpColor),
sizeof (OpMatrix),
sizeof (OpMatrix),
sizeof (OpProgram),
sizeof (OpRenderTarget),
sizeof (OpClip),
sizeof (OpViewport),
sizeof (OpTexture),
sizeof (OpRepeat),
sizeof (OpLinearGradient),
sizeof (OpColorMatrix),
sizeof (OpBlur),
sizeof (OpShadow),
sizeof (OpShadow),
sizeof (OpBorder),
sizeof (OpBorder),
sizeof (OpBorder),
sizeof (OpCrossFade),
sizeof (OpShadow),
0,
sizeof (OpDraw),
sizeof (OpDumpFrameBuffer),
sizeof (OpDebugGroup),
0,
sizeof (OpBlend),
};
void
op_buffer_init (OpBuffer *buffer)
{
static gsize initialized = FALSE;
if (g_once_init_enter (&initialized))
{
guint i;
for (i = 0; i < G_N_ELEMENTS (op_sizes); i++)
{
guint size = op_sizes[i];
if (size > 0)
{
/* Round all op entry sizes to the nearest 16 to ensure
* that we guarantee proper alignments for all op entries.
* This is only done once on first use.
*/
#define CHECK_SIZE(s) else if (size < (s)) { size = s; }
if (0) {}
CHECK_SIZE (16)
CHECK_SIZE (32)
CHECK_SIZE (48)
CHECK_SIZE (64)
CHECK_SIZE (80)
CHECK_SIZE (96)
CHECK_SIZE (112)
CHECK_SIZE (128)
CHECK_SIZE (144)
CHECK_SIZE (160)
CHECK_SIZE (176)
CHECK_SIZE (192)
else g_assert_not_reached ();
#undef CHECK_SIZE
op_sizes[i] = size;
}
}
g_once_init_leave (&initialized, TRUE);
}
memset (buffer, 0, sizeof *buffer);
buffer->buflen = 4096;
buffer->bufpos = 0;
buffer->buf = g_malloc (buffer->buflen);
buffer->index = g_array_new (FALSE, FALSE, sizeof (OpBufferEntry));
/* Add dummy entry to guarantee non-empty index */
op_buffer_add (buffer, OP_NONE);
}
void
op_buffer_destroy (OpBuffer *buffer)
{
g_free (buffer->buf);
g_array_unref (buffer->index);
}
void
op_buffer_clear (OpBuffer *buffer)
{
if (buffer->index->len > 1)
g_array_remove_range (buffer->index, 1, buffer->index->len - 1);
buffer->bufpos = 0;
}
static inline void
ensure_buffer_space_for (OpBuffer *buffer,
guint size)
{
if G_UNLIKELY (buffer->bufpos + size >= buffer->buflen)
{
buffer->buflen *= 2;
buffer->buf = g_realloc (buffer->buf, buffer->buflen);
}
}
gpointer
op_buffer_add (OpBuffer *buffer,
OpKind kind)
{
guint size = op_sizes[kind];
OpBufferEntry entry;
entry.pos = buffer->bufpos;
entry.kind = kind;
if (size > 0)
ensure_buffer_space_for (buffer, size);
g_array_append_val (buffer->index, entry);
buffer->bufpos += size;
return &buffer->buf[entry.pos];
}

257
gsk/gl/opbuffer.h Normal file
View File

@@ -0,0 +1,257 @@
#ifndef __OP_BUFFER_H__
#define __OP_BUFFER_H__
#include <gdk/gdk.h>
#include <gsk/gsk.h>
#include <graphene.h>
#include "gskgldriverprivate.h"
typedef struct _Program Program;
typedef enum
{
OP_NONE = 0,
OP_CHANGE_OPACITY = 1,
OP_CHANGE_COLOR = 2,
OP_CHANGE_PROJECTION = 3,
OP_CHANGE_MODELVIEW = 4,
OP_CHANGE_PROGRAM = 5,
OP_CHANGE_RENDER_TARGET = 6,
OP_CHANGE_CLIP = 7,
OP_CHANGE_VIEWPORT = 8,
OP_CHANGE_SOURCE_TEXTURE = 9,
OP_CHANGE_REPEAT = 10,
OP_CHANGE_LINEAR_GRADIENT = 11,
OP_CHANGE_COLOR_MATRIX = 12,
OP_CHANGE_BLUR = 13,
OP_CHANGE_INSET_SHADOW = 14,
OP_CHANGE_OUTSET_SHADOW = 15,
OP_CHANGE_BORDER = 16,
OP_CHANGE_BORDER_COLOR = 17,
OP_CHANGE_BORDER_WIDTH = 18,
OP_CHANGE_CROSS_FADE = 19,
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
OP_CLEAR = 21,
OP_DRAW = 22,
OP_DUMP_FRAMEBUFFER = 23,
OP_PUSH_DEBUG_GROUP = 24,
OP_POP_DEBUG_GROUP = 25,
OP_CHANGE_BLEND = 26,
OP_LAST
} OpKind;
/* OpNode are allocated within OpBuffer.pos, but we keep
* a secondary index into the locations of that buffer
* from OpBuffer.index. This allows peeking at the kind
* and quickly replacing existing entries when necessary.
*/
typedef struct
{
guint pos;
OpKind kind;
} OpBufferEntry;
typedef struct
{
guint8 *buf;
gsize buflen;
gsize bufpos;
GArray *index;
} OpBuffer;
typedef struct
{
float opacity;
} OpOpacity;
typedef struct
{
graphene_matrix_t matrix;
} OpMatrix;
typedef struct
{
const Program *program;
} OpProgram;
typedef struct
{
GdkRGBA rgba;
} OpColor;
typedef struct
{
int render_target_id;
} OpRenderTarget;
typedef struct
{
GskRoundedRect clip;
} OpClip;
typedef struct
{
graphene_rect_t viewport;
} OpViewport;
typedef struct
{
int texture_id;
} OpTexture;
typedef struct
{
gsize vao_offset;
gsize vao_size;
} OpDraw;
typedef struct
{
float color_offsets[8];
float color_stops[4 * 8];
graphene_point_t start_point;
graphene_point_t end_point;
int n_color_stops;
} OpLinearGradient;
typedef struct
{
graphene_matrix_t matrix;
graphene_vec4_t offset;
} OpColorMatrix;
typedef struct
{
float radius;
graphene_size_t size;
float dir[2];
} OpBlur;
typedef struct
{
float outline[4];
float corner_widths[4];
float corner_heights[4];
float radius;
float spread;
float offset[2];
float color[4];
} OpShadow;
typedef struct
{
float widths[4];
float color[4];
GskRoundedRect outline;
} OpBorder;
typedef struct
{
float progress;
int source2;
} OpCrossFade;
typedef struct
{
char *filename;
int width;
int height;
} OpDumpFrameBuffer;
typedef struct
{
char text[64];
} OpDebugGroup;
typedef struct
{
int source2;
int mode;
} OpBlend;
typedef struct
{
float child_bounds[4];
float texture_rect[4];
} OpRepeat;
void op_buffer_init (OpBuffer *buffer);
void op_buffer_destroy (OpBuffer *buffer);
void op_buffer_clear (OpBuffer *buffer);
gpointer op_buffer_add (OpBuffer *buffer,
OpKind kind);
typedef struct
{
GArray *index;
OpBuffer *buffer;
guint pos;
} OpBufferIter;
static inline void
op_buffer_iter_init (OpBufferIter *iter,
OpBuffer *buffer)
{
iter->index = buffer->index;
iter->buffer = buffer;
iter->pos = 1; /* Skip first OP_NONE */
}
static inline gpointer
op_buffer_iter_next (OpBufferIter *iter,
OpKind *kind)
{
const OpBufferEntry *entry;
if (iter->pos == iter->index->len)
return NULL;
entry = &g_array_index (iter->index, OpBufferEntry, iter->pos);
iter->pos++;
*kind = entry->kind;
return &iter->buffer->buf[entry->pos];
}
static inline void
op_buffer_pop_tail (OpBuffer *buffer)
{
/* Never truncate the first OP_NONE */
if G_LIKELY (buffer->index->len > 0)
buffer->index->len--;
}
static inline gpointer
op_buffer_peek_tail (OpBuffer *buffer,
OpKind *kind)
{
const OpBufferEntry *entry;
entry = &g_array_index (buffer->index, OpBufferEntry, buffer->index->len - 1);
*kind = entry->kind;
return &buffer->buf[entry->pos];
}
static inline gpointer
op_buffer_peek_tail_checked (OpBuffer *buffer,
OpKind kind)
{
const OpBufferEntry *entry;
entry = &g_array_index (buffer->index, OpBufferEntry, buffer->index->len - 1);
if (entry->kind == kind)
return &buffer->buf[entry->pos];
return NULL;
}
static inline guint
op_buffer_n_ops (OpBuffer *buffer)
{
return buffer->index->len - 1;
}
#endif /* __OP_BUFFER_H__ */

View File

@@ -48,6 +48,7 @@ gsk_private_sources = files([
'gl/gskglnodesample.c',
'gl/gskgltextureatlas.c',
'gl/gskgliconcache.c',
'gl/opbuffer.c',
'gl/stb_rect_pack.c',
])