From: Christian Hergert Date: Fri, 11 Oct 2019 14:23:33 +0000 (-0400) Subject: prototype OpBuffer helper for building op buffer X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~20^2~705^2~13 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=a00d12c62aea1f51a2ffdf3ec970084c670c4ce9;p=gtk4.git prototype OpBuffer helper for building op buffer --- diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 82b5e3018c..07d7938d19 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -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" @@ -328,7 +329,6 @@ struct _GskGLRenderer }; RenderOpBuilder op_builder; - GArray *render_ops; GskGLTextureAtlases *atlases; GskGLGlyphCache *glyph_cache; @@ -1047,7 +1047,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); @@ -1062,18 +1062,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.x = start->x + builder->dx; - op->linear_gradient.start_point.y = start->y + builder->dy; - op->linear_gradient.end_point.x = end->x + builder->dx; - op->linear_gradient.end_point.y = end->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); } @@ -1280,7 +1280,7 @@ render_blur_node (GskGLRenderer *self, GskRenderNode *child = gsk_blur_node_get_child (node); TextureRegion region; gboolean is_offscreen; - RenderOp *op; + OpBlur *op; if (blur_radius <= 0) { @@ -1302,8 +1302,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); @@ -1334,7 +1334,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) @@ -1346,16 +1346,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); } @@ -1371,21 +1371,21 @@ render_unblurred_outset_shadow_node (GskGLRenderer *self, const float spread = gsk_outset_shadow_node_get_spread (node); const float dx = gsk_outset_shadow_node_get_dx (node); const float dy = gsk_outset_shadow_node_get_dy (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); rounded_rect_to_floats (self, builder, outline, - 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 = spread * scale; - op->unblurred_outset_shadow.offset[0] = dx * scale; - op->unblurred_outset_shadow.offset[1] = - dy * scale; + op->spread = spread * scale; + op->offset[0] = dx * scale; + op->offset[1] = - dy * scale; ops_draw (builder, vertex_data); } @@ -1407,7 +1407,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; @@ -1494,9 +1495,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); @@ -1531,12 +1532,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. */ { @@ -1875,7 +1876,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 }, }, @@ -1904,8 +1905,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); @@ -1926,7 +1927,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 }, }, @@ -1955,8 +1956,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); } @@ -1974,7 +1975,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)) @@ -1995,23 +1996,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) @@ -2045,10 +2046,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); @@ -2057,38 +2060,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); @@ -2101,29 +2104,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->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); @@ -2134,22 +2134,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, @@ -2180,85 +2180,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]; @@ -2283,63 +2283,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 @@ -2347,7 +2347,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); @@ -2635,7 +2634,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); @@ -2664,7 +2663,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)); @@ -2976,11 +2975,13 @@ static void gsk_gl_renderer_render_ops (GskGLRenderer *self, gsize vertex_data_size) { - 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); + OpBuffer *buffer; + OpBufferIter iter; + OpKind kind; + gpointer ptr; /*g_message ("%s: Buffer size: %ld", __FUNCTION__, vertex_data_size);*/ @@ -2992,15 +2993,16 @@ 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 ++) + buffer = ops_get_buffer (&self->op_builder); + op_buffer_iter_init (&iter, buffer); + while ((ptr = op_buffer_iter_next (&iter, &kind))) { - const RenderOp *op = &g_array_index (self->render_ops, RenderOp, i); - - if (op->op == OP_CHANGE_VAO) + if (kind == OP_CHANGE_VAO) { - memcpy (vertex_data + buffer_index, &op->vertex_data, sizeof (GskQuadVertex) * GL_N_VERTICES); + const OpVao *vao = ptr; + + memcpy (vertex_data + buffer_index, &vao->vertex_data, sizeof (GskQuadVertex) * GL_N_VERTICES); buffer_index += sizeof (GskQuadVertex) * GL_N_VERTICES / sizeof (float); } } @@ -3021,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 || kind == OP_CHANGE_VAO) 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: @@ -3064,95 +3067,109 @@ 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_CHANGE_VAO: + case OP_NONE: + case OP_LAST: default: g_warn_if_reached (); } @@ -3451,11 +3468,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 { diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c index 98736bcaca..663403aa2b 100644 --- a/gsk/gl/gskglrenderops.c +++ b/gsk/gl/gskglrenderops.c @@ -57,23 +57,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 +182,8 @@ ops_init (RenderOpBuilder *builder) builder->current_opacity = 1.0f; + op_buffer_init (&builder->render_ops); + for (i = 0; i < GL_N_PROGRAMS; i ++) { builder->program_state[i].opacity = 1.0f; @@ -197,6 +199,8 @@ ops_free (RenderOpBuilder *builder) { gsk_transform_unref (builder->program_state[i].modelview); } + + op_buffer_destroy (&builder->render_ops); } void @@ -208,7 +212,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 +229,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 +250,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 +281,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 (¤t_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 (last_op->op == OP_CHANGE_CLIP) - { - last_op->clip = *clip; - } - else - { - RenderOp *op; - - op = ops_begin (builder, OP_CHANGE_CLIP); - op->clip = *clip; - } - } + if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_CLIP))) + op = op_buffer_add (&builder->render_ops, OP_CHANGE_CLIP); + + op->clip = *clip; if (builder->current_program != NULL) current_program_state->clip = *clip; @@ -343,8 +345,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 +357,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 +478,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 +500,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 +523,7 @@ void ops_set_texture (RenderOpBuilder *builder, int texture_id) { - RenderOp *op; + OpTexture *op; if (builder->current_texture == texture_id) return; @@ -563,7 +537,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 +545,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 +560,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 (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; - } + if (!(op = op_buffer_peek_tail_checked (&builder->render_ops, OP_CHANGE_OPACITY))) + op = op_buffer_add (&builder->render_ops, OP_CHANGE_OPACITY); + + op->opacity = opacity; prev_opacity = builder->current_opacity; builder->current_opacity = opacity; @@ -641,7 +585,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, ¤t_program_state->color)) return; @@ -649,7 +593,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 +602,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, ¤t_program_state->color_matrix.matrix, @@ -672,8 +616,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 +625,7 @@ ops_set_border (RenderOpBuilder *builder, const GskRoundedRect *outline) { ProgramState *current_program_state = get_current_program_state (builder); - RenderOp *op; + OpBorder *op; if (memcmp (¤t_program_state->border.outline, outline, sizeof (GskRoundedRect)) == 0) @@ -690,7 +634,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 +642,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 +652,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,64 +663,50 @@ 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, ¤t_program_state->border.color, - sizeof (float) * 4) == 0) - return; + rgba_to_float (color, fcolor); - rgba_to_float (color, current_program_state->border.color); + if (memcmp (fcolor, ¤t_program_state->border.color, sizeof fcolor) == 0) + return; - 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; + OpVao *vao; - 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; + gsize old_vao_offset = op->vao_offset; + gsize old_vao_size = op->vao_size; - new_draw = ops_begin (builder, OP_DRAW); + op_buffer_pop_tail (&builder->render_ops); - /* last_op may have moved in memory */ - last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 2); + vao = op_buffer_add (&builder->render_ops, OP_CHANGE_VAO); + memcpy (vao->vertex_data, vertex_data, sizeof vao->vertex_data); - 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 = op_buffer_add (&builder->render_ops, OP_DRAW); + op->vao_offset = old_vao_offset; + op->vao_size = old_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); + vao = op_buffer_add (&builder->render_ops, OP_CHANGE_VAO); + memcpy (vao->vertex_data, vertex_data, sizeof vao->vertex_data); - 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 = offset; + op->vao_size = GL_N_VERTICES; } /* We added new vertex data in both cases so increase the buffer size */ @@ -795,15 +725,21 @@ ops_offset (RenderOpBuilder *builder, builder->dy += y; } -RenderOp * +gpointer ops_begin (RenderOpBuilder *builder, - guint kind) + OpKind kind) { - RenderOp *op; + return op_buffer_add (&builder->render_ops, kind); +} - 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; +void +ops_reset (RenderOpBuilder *builder) +{ + op_buffer_clear (&builder->render_ops); +} - return op; +OpBuffer * +ops_get_buffer (RenderOpBuilder *builder) +{ + return &builder->render_ops; } diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index 5f43eace61..85765ad44f 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -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; - const 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 { @@ -278,7 +155,8 @@ typedef struct gsize buffer_size; - GArray *render_ops; + OpBuffer render_ops; + GskGLRenderer *renderer; /* Stack of modelview matrices */ @@ -298,6 +176,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 +237,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 diff --git a/gsk/gl/opbuffer.c b/gsk/gl/opbuffer.c new file mode 100644 index 0000000000..2d3b16ffb6 --- /dev/null +++ b/gsk/gl/opbuffer.c @@ -0,0 +1,134 @@ +#include "opbuffer.h" + +#include + +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 (OpVao), + 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), + sizeof (OpRepeat), +}; + +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]; +} diff --git a/gsk/gl/opbuffer.h b/gsk/gl/opbuffer.h new file mode 100644 index 0000000000..d777e2ae41 --- /dev/null +++ b/gsk/gl/opbuffer.h @@ -0,0 +1,263 @@ +#ifndef __OP_BUFFER_H__ +#define __OP_BUFFER_H__ + +#include +#include +#include + +#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_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, + 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 +{ + GskQuadVertex vertex_data[6]; +} OpVao; + +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__ */ diff --git a/gsk/meson.build b/gsk/meson.build index 6819ac5426..ed621284bb 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -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', ])