[gtk/wip/chergert/avoid-renderop-copy: 2/2] gl: avoid copying RenderOp to GArray



commit 528297f5e502e7fca98938a7024c7348ac65171c
Author: Christian Hergert <chergert redhat com>
Date:   Wed Oct 9 15:41:53 2019 -0700

    gl: avoid copying RenderOp to GArray
    
    Instead of copying the (rather large) RenderOp to the GArray, we can
    simply set the fields directly in the allocated space for the struct.
    In most cases, there wont be any allocations to make as the array size
    is kept in tact across frame renderings.

 gsk/gl/gskglrenderer.c         | 170 ++++++++++++++++++-----------------
 gsk/gl/gskglrenderops.c        | 196 ++++++++++++++++++-----------------------
 gsk/gl/gskglrenderopsprivate.h |   4 +-
 3 files changed, 174 insertions(+), 196 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 118b67c0ec..3835aaa2bb 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -1064,34 +1064,35 @@ render_linear_gradient_node (GskGLRenderer       *self,
                              RenderOpBuilder     *builder,
                              const GskQuadVertex *vertex_data)
 {
-  RenderOp op;
+  RenderOp *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);
   const graphene_point_t *end = gsk_linear_gradient_node_peek_end (node);
   int i;
 
+  ops_set_program (builder, &self->linear_gradient_program);
+
+  op = ops_begin (builder, OP_CHANGE_LINEAR_GRADIENT);
+
   for (i = 0; i < n_color_stops; i ++)
     {
       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->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;
     }
 
-  ops_set_program (builder, &self->linear_gradient_program);
-  op.op = OP_CHANGE_LINEAR_GRADIENT;
-  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;
-  ops_add (builder, &op);
+  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;
 
   ops_draw (builder, vertex_data);
 }
@@ -1297,7 +1298,7 @@ render_blur_node (GskGLRenderer       *self,
   const float blur_radius = gsk_blur_node_get_radius (node);
   TextureRegion region;
   gboolean is_offscreen;
-  RenderOp op;
+  RenderOp *op;
 
   if (blur_radius <= 0)
     {
@@ -1317,10 +1318,10 @@ render_blur_node (GskGLRenderer       *self,
                      RESET_CLIP | FORCE_OFFSCREEN | RESET_OPACITY);
 
   ops_set_program (builder, &self->blur_program);
-  op.op = OP_CHANGE_BLUR;
-  graphene_size_init_from_size (&op.blur.size, &node->bounds.size);
-  op.blur.radius = blur_radius;
-  ops_add (builder, &op);
+
+  op = ops_begin (builder, OP_CHANGE_BLUR);
+  graphene_size_init_from_size (&op->blur.size, &node->bounds.size);
+  op->blur.radius = blur_radius;
 
   ops_set_texture (builder, region.texture_id);
 
@@ -1351,7 +1352,7 @@ render_inset_shadow_node (GskGLRenderer       *self,
                           const GskQuadVertex *vertex_data)
 {
   const float scale = ops_get_scale (builder);
-  RenderOp op;
+  RenderOp *op;
 
   /* TODO: Implement blurred inset shadows as well */
   if (gsk_inset_shadow_node_get_blur_radius (node) > 0)
@@ -1360,20 +1361,20 @@ render_inset_shadow_node (GskGLRenderer       *self,
       return;
     }
 
-  op.op = OP_CHANGE_INSET_SHADOW;
-  rgba_to_float (gsk_inset_shadow_node_peek_color (node), op.inset_shadow.color);
+  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);
   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->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;
 
-  ops_set_program (builder, &self->inset_shadow_program);
-  ops_add (builder, &op);
   ops_draw (builder, vertex_data);
 }
 
@@ -1386,25 +1387,25 @@ 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;
+  RenderOp *op;
+
+  ops_set_program (builder, &self->unblurred_outset_shadow_program);
 
-  op.op = OP_CHANGE_UNBLURRED_OUTSET_SHADOW;
-  rgba_to_float (gsk_outset_shadow_node_peek_color (node), op.unblurred_outset_shadow.color);
+  op = ops_begin (builder, OP_CHANGE_UNBLURRED_OUTSET_SHADOW);
+  rgba_to_float (gsk_outset_shadow_node_peek_color (node), op->unblurred_outset_shadow.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->unblurred_outset_shadow.outline,
+                          op->unblurred_outset_shadow.corner_widths,
+                          op->unblurred_outset_shadow.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->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;
 
-  ops_set_program (builder, &self->unblurred_outset_shadow_program);
-  ops_add (builder, &op);
   ops_draw (builder, vertex_data);
 }
 
@@ -1425,7 +1426,7 @@ 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;
+  RenderOp *op;
   graphene_matrix_t prev_projection;
   graphene_rect_t prev_viewport;
   graphene_matrix_t item_proj;
@@ -1476,8 +1477,7 @@ render_outset_shadow_node (GskGLRenderer       *self,
       graphene_matrix_scale (&item_proj, 1, -1, 1);
 
       prev_render_target = ops_set_render_target (builder, render_target);
-      op.op = OP_CLEAR;
-      ops_add (builder, &op);
+      ops_begin (builder, OP_CLEAR);
       prev_projection = ops_set_projection (builder, &item_proj);
       ops_set_modelview (builder, NULL); /* Modelview */
       prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
@@ -1505,18 +1505,17 @@ render_outset_shadow_node (GskGLRenderer       *self,
 
       ops_set_render_target (builder, blurred_render_target);
       ops_pop_clip (builder);
-      op.op = OP_CLEAR;
-      ops_add (builder, &op);
+      ops_begin (builder, OP_CLEAR);
 
       gsk_rounded_rect_init_from_rect (&blit_clip,
                                        &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height), 0.0f);
 
       ops_set_program (builder, &self->blur_program);
-      op.op = OP_CHANGE_BLUR;
-      op.blur.size.width = texture_width;
-      op.blur.size.height = texture_height;
-      op.blur.radius = blur_radius;
-      ops_add (builder, &op);
+
+      op = ops_begin (builder, OP_CHANGE_BLUR);
+      op->blur.size.width = texture_width;
+      op->blur.size.height = texture_height;
+      op->blur.radius = blur_radius;
 
       ops_push_clip (builder, &blit_clip);
       ops_set_texture (builder, texture_id);
@@ -1550,13 +1549,13 @@ render_outset_shadow_node (GskGLRenderer       *self,
 
   ops_set_program (builder, &self->outset_shadow_program);
   ops_set_texture (builder, blurred_texture_id);
-  op.op = OP_CHANGE_OUTSET_SHADOW;
+
+  op = 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);
-  ops_add (builder, &op);
+                          op->outset_shadow.outline,
+                          op->outset_shadow.corner_widths,
+                          op->outset_shadow.corner_heights);
 
   /* We use the one outset shadow op from above to draw all 8 sides/corners. */
   {
@@ -1892,7 +1891,7 @@ render_cross_fade_node (GskGLRenderer       *self,
   TextureRegion start_region;
   TextureRegion end_region;
   gboolean is_offscreen1, is_offscreen2;
-  RenderOp op;
+  RenderOp *op;
   const GskQuadVertex vertex_data[GL_N_VERTICES] = {
     { { min_x, min_y }, { 0, 1 }, },
     { { min_x, max_y }, { 0, 0 }, },
@@ -1919,10 +1918,11 @@ render_cross_fade_node (GskGLRenderer       *self,
                      FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY);
 
   ops_set_program (builder, &self->cross_fade_program);
-  op.op = OP_CHANGE_CROSS_FADE;
-  op.cross_fade.progress = progress;
-  op.cross_fade.source2 = end_region.texture_id;
-  ops_add (builder, &op);
+
+  op = ops_begin (builder, OP_CHANGE_CROSS_FADE);
+  op->cross_fade.progress = progress;
+  op->cross_fade.source2 = end_region.texture_id;
+
   ops_set_texture (builder, start_region.texture_id);
 
   ops_draw (builder, vertex_data);
@@ -1942,7 +1942,7 @@ render_blend_node (GskGLRenderer   *self,
   TextureRegion top_region;
   TextureRegion bottom_region;
   gboolean is_offscreen1, is_offscreen2;
-  RenderOp op;
+  RenderOp *op;
   const GskQuadVertex vertex_data[GL_N_VERTICES] = {
     { { min_x, min_y }, { 0, 1 }, },
     { { min_x, max_y }, { 0, 0 }, },
@@ -1969,10 +1969,11 @@ render_blend_node (GskGLRenderer   *self,
 
   ops_set_program (builder, &self->blend_program);
   ops_set_texture (builder, bottom_region.texture_id);
-  op.op = OP_CHANGE_BLEND;
-  op.blend.source2 = top_region.texture_id;
-  op.blend.mode = gsk_blend_node_get_blend_mode (node);
-  ops_add (builder, &op);
+
+  op = ops_begin (builder, OP_CHANGE_BLEND);
+  op->blend.source2 = top_region.texture_id;
+  op->blend.mode = gsk_blend_node_get_blend_mode (node);
+
   ops_draw (builder, vertex_data);
 }
 
@@ -1989,7 +1990,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;
+  RenderOp *op;
 
   if (child_bounds != NULL &&
       !graphene_rect_equal (child_bounds, &child->bounds))
@@ -2008,28 +2009,27 @@ render_repeat_node (GskGLRenderer   *self,
 
   ops_set_program (builder, &self->repeat_program);
   ops_set_texture (builder, region.texture_id);
-  op.op = 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.repeat.texture_rect[0] = region.x;
-  op.repeat.texture_rect[2] = region.x2;
+  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->repeat.texture_rect[0] = region.x;
+  op->repeat.texture_rect[2] = region.x2;
 
   if (is_offscreen)
     {
-      op.repeat.texture_rect[1] = region.y2;
-      op.repeat.texture_rect[3] = region.y;
+      op->repeat.texture_rect[1] = region.y2;
+      op->repeat.texture_rect[3] = region.y;
     }
   else
     {
-      op.repeat.texture_rect[1] = region.y;
-      op.repeat.texture_rect[3] = region.y2;
+      op->repeat.texture_rect[1] = region.y;
+      op->repeat.texture_rect[3] = region.y2;
     }
 
-  ops_add (builder, &op);
-
   if (is_offscreen)
     {
       const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
@@ -2885,7 +2885,6 @@ add_offscreen_ops (GskGLRenderer         *self,
   const float dy = builder->dy;
   int render_target;
   int prev_render_target;
-  RenderOp op;
   graphene_matrix_t modelview;
   graphene_matrix_t prev_projection;
   graphene_rect_t prev_viewport;
@@ -2935,8 +2934,7 @@ add_offscreen_ops (GskGLRenderer         *self,
 
   prev_render_target = ops_set_render_target (builder, render_target);
   /* Clear since we use this rendertarget for the first time */
-  op.op = OP_CLEAR;
-  ops_add (builder, &op);
+  ops_begin (builder, OP_CLEAR);
   prev_projection = ops_set_projection (builder, &item_proj);
   ops_set_modelview (builder, gsk_transform_scale (NULL, scale, scale));
   prev_viewport = ops_set_viewport (builder,
diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c
index d34f2c2405..f7105f202a 100644
--- a/gsk/gl/gskglrenderops.c
+++ b/gsk/gl/gskglrenderops.c
@@ -57,36 +57,29 @@ ops_dump_framebuffer (RenderOpBuilder *builder,
                       int              width,
                       int              height)
 {
-  RenderOp op;
-
-  op.op = OP_DUMP_FRAMEBUFFER;
-  op.dump.filename = g_strdup (filename);
-  op.dump.width = width;
-  op.dump.height = height;
+  RenderOp *op;
 
-  g_array_append_val (builder->render_ops, op);
+  op = ops_begin (builder, OP_DUMP_FRAMEBUFFER);
+  op->dump.filename = g_strdup (filename);
+  op->dump.width = width;
+  op->dump.height = height;
 }
 
 void
 ops_push_debug_group (RenderOpBuilder *builder,
                       const char      *text)
 {
-  RenderOp op;
-
-  op.op = 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 */
+  RenderOp *op;
 
-  g_array_append_val (builder->render_ops, 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 */
 }
 
 void
 ops_pop_debug_group (RenderOpBuilder *builder)
 {
-  RenderOp op;
-
-  op.op = OP_POP_DEBUG_GROUP;
-  g_array_append_val (builder->render_ops, op);
+  ops_begin (builder, OP_POP_DEBUG_GROUP);
 }
 
 float
@@ -215,15 +208,15 @@ 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;
+  RenderOp *op;
   ProgramState *program_state;
 
   if (builder->current_program == program)
     return;
 
-  op.op = OP_CHANGE_PROGRAM;
-  op.program = program;
-  g_array_append_val (builder->render_ops, op);
+  op = ops_begin (builder, OP_CHANGE_PROGRAM);
+  op->program = program;
+
   builder->current_program = program;
 
   program_state = &builder->program_state[program->index];
@@ -232,18 +225,16 @@ 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.op = OP_CHANGE_PROJECTION;
-      op.projection = builder->current_projection;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_PROJECTION);
+      op->projection = builder->current_projection;
       program_state->projection = builder->current_projection;
     }
 
   if (program_state->modelview == NULL ||
       !gsk_transform_equal (builder->current_modelview, program_state->modelview))
     {
-      op.op = OP_CHANGE_MODELVIEW;
-      gsk_transform_to_matrix (builder->current_modelview, &op.modelview);
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_MODELVIEW);
+      gsk_transform_to_matrix (builder->current_modelview, &op->modelview);
       gsk_transform_unref (program_state->modelview);
       program_state->modelview = gsk_transform_ref (builder->current_modelview);
     }
@@ -251,26 +242,23 @@ ops_set_program (RenderOpBuilder *builder,
   if (rect_equal (&empty_rect, &program_state->viewport) ||
       !rect_equal (&builder->current_viewport, &program_state->viewport))
     {
-      op.op = OP_CHANGE_VIEWPORT;
-      op.viewport = builder->current_viewport;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_VIEWPORT);
+      op->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.op = OP_CHANGE_CLIP;
-      op.clip = *builder->current_clip;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_CLIP);
+      op->clip = *builder->current_clip;
       program_state->clip = *builder->current_clip;
     }
 
   if (program_state->opacity != builder->current_opacity)
     {
-      op.op = OP_CHANGE_OPACITY;
-      op.opacity = builder->current_opacity;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_OPACITY);
+      op->opacity = builder->current_opacity;
       program_state->opacity = builder->current_opacity;
     }
 }
@@ -296,11 +284,10 @@ ops_set_clip (RenderOpBuilder      *builder,
         }
       else
         {
-          RenderOp op;
+          RenderOp *op;
 
-          op.op = OP_CHANGE_CLIP;
-          op.clip = *clip;
-          g_array_append_val (builder->render_ops, op);
+          op = ops_begin (builder, OP_CHANGE_CLIP);
+          op->clip = *clip;
         }
     }
 
@@ -356,7 +343,7 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
                             GskTransform    *transform)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
   graphene_matrix_t matrix;
 
 #if 0
@@ -377,16 +364,14 @@ ops_set_modelview_internal (RenderOpBuilder *builder,
         }
       else
         {
-          op.op = OP_CHANGE_MODELVIEW;
-          op.modelview = matrix;
-          g_array_append_val (builder->render_ops, op);
+          op = ops_begin (builder, OP_CHANGE_MODELVIEW);
+          op->modelview = matrix;
         }
     }
   else
     {
-      op.op = OP_CHANGE_MODELVIEW;
-      op.modelview = matrix;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_MODELVIEW);
+      op->modelview = matrix;
     }
 
   if (builder->current_program != NULL)
@@ -505,7 +490,7 @@ ops_set_projection (RenderOpBuilder         *builder,
                     const graphene_matrix_t *projection)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
   graphene_matrix_t prev_mv;
 
   if (builder->render_ops->len > 0)
@@ -517,16 +502,14 @@ ops_set_projection (RenderOpBuilder         *builder,
         }
       else
         {
-          op.op = OP_CHANGE_PROJECTION;
-          op.projection = *projection;
-          g_array_append_val (builder->render_ops, op);
+          op = ops_begin (builder, OP_CHANGE_PROJECTION);
+          op->projection = *projection;
         }
     }
   else
     {
-      op.op = OP_CHANGE_PROJECTION;
-      op.projection = *projection;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_PROJECTION);
+      op->projection = *projection;
     }
 
   if (builder->current_program != NULL)
@@ -543,16 +526,15 @@ ops_set_viewport (RenderOpBuilder       *builder,
                   const graphene_rect_t *viewport)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
   graphene_rect_t prev_viewport;
 
   if (current_program_state != NULL &&
       rect_equal (&current_program_state->viewport, viewport))
     return current_program_state->viewport;
 
-  op.op = OP_CHANGE_VIEWPORT;
-  op.viewport = *viewport;
-  g_array_append_val (builder->render_ops, op);
+  op = ops_begin (builder, OP_CHANGE_VIEWPORT);
+  op->viewport = *viewport;
 
   if (builder->current_program != NULL)
     current_program_state->viewport = *viewport;
@@ -567,14 +549,13 @@ void
 ops_set_texture (RenderOpBuilder *builder,
                  int              texture_id)
 {
-  RenderOp op;
+  RenderOp *op;
 
   if (builder->current_texture == texture_id)
     return;
 
-  op.op = OP_CHANGE_SOURCE_TEXTURE;
-  op.texture_id = texture_id;
-  g_array_append_val (builder->render_ops, op);
+  op = ops_begin (builder, OP_CHANGE_SOURCE_TEXTURE);
+  op->texture_id = texture_id;
   builder->current_texture = texture_id;
 }
 
@@ -582,7 +563,7 @@ int
 ops_set_render_target (RenderOpBuilder *builder,
                        int              render_target_id)
 {
-  RenderOp op;
+  RenderOp *op;
   int prev_render_target;
 
   if (builder->current_render_target == render_target_id)
@@ -599,16 +580,14 @@ ops_set_render_target (RenderOpBuilder *builder,
         }
       else
         {
-          op.op = OP_CHANGE_RENDER_TARGET;
-          op.render_target_id = render_target_id;
-          g_array_append_val (builder->render_ops, op);
+          op = ops_begin (builder, OP_CHANGE_RENDER_TARGET);
+          op->render_target_id = render_target_id;
         }
     }
   else
     {
-      op.op = OP_CHANGE_RENDER_TARGET;
-      op.render_target_id = render_target_id;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_RENDER_TARGET);
+      op->render_target_id = render_target_id;
     }
 
   builder->current_render_target = render_target_id;
@@ -621,7 +600,7 @@ ops_set_opacity (RenderOpBuilder *builder,
                  float            opacity)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
   float prev_opacity;
   RenderOp *last_op;
 
@@ -638,16 +617,14 @@ ops_set_opacity (RenderOpBuilder *builder,
         }
       else
         {
-          op.op = OP_CHANGE_OPACITY;
-          op.opacity = opacity;
-          g_array_append_val (builder->render_ops, op);
+          op = ops_begin (builder, OP_CHANGE_OPACITY);
+          op->opacity = opacity;
         }
     }
   else
     {
-      op.op = OP_CHANGE_OPACITY;
-      op.opacity = opacity;
-      g_array_append_val (builder->render_ops, op);
+      op = ops_begin (builder, OP_CHANGE_OPACITY);
+      op->opacity = opacity;
     }
 
   prev_opacity = builder->current_opacity;
@@ -664,16 +641,15 @@ ops_set_color (RenderOpBuilder *builder,
                const GdkRGBA   *color)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
 
   if (gdk_rgba_equal (color, &current_program_state->color))
     return;
 
   current_program_state->color = *color;
 
-  op.op = OP_CHANGE_COLOR;
-  op.color = *color;
-  g_array_append_val (builder->render_ops, op);
+  op = ops_begin (builder, OP_CHANGE_COLOR);
+  op->color = *color;
 }
 
 void
@@ -682,7 +658,7 @@ ops_set_color_matrix (RenderOpBuilder         *builder,
                       const graphene_vec4_t   *offset)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
 
   if (memcmp (matrix,
               &current_program_state->color_matrix.matrix,
@@ -695,10 +671,9 @@ ops_set_color_matrix (RenderOpBuilder         *builder,
   current_program_state->color_matrix.matrix = *matrix;
   current_program_state->color_matrix.offset = *offset;
 
-  op.op = OP_CHANGE_COLOR_MATRIX;
-  op.color_matrix.matrix = *matrix;
-  op.color_matrix.offset = *offset;
-  g_array_append_val (builder->render_ops, op);
+  op = ops_begin (builder, OP_CHANGE_COLOR_MATRIX);
+  op->color_matrix.matrix = *matrix;
+  op->color_matrix.offset = *offset;
 }
 
 void
@@ -706,7 +681,7 @@ ops_set_border (RenderOpBuilder      *builder,
                 const GskRoundedRect *outline)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
 
   if (memcmp (&current_program_state->border.outline,
               outline, sizeof (GskRoundedRect)) == 0)
@@ -714,9 +689,8 @@ ops_set_border (RenderOpBuilder      *builder,
 
   current_program_state->border.outline = *outline;
 
-  op.op = OP_CHANGE_BORDER;
-  op.border.outline = *outline;
-  g_array_append_val (builder->render_ops, op);
+  op = ops_begin (builder, OP_CHANGE_BORDER);
+  op->border.outline = *outline;
 }
 
 void
@@ -724,7 +698,7 @@ ops_set_border_width (RenderOpBuilder *builder,
                       const float     *widths)
 {
   ProgramState *current_program_state = get_current_program_state (builder);
-  RenderOp op;
+  RenderOp *op;
 
   if (memcmp (current_program_state->border.widths,
               widths, sizeof (float) * 4) == 0)
@@ -733,13 +707,11 @@ ops_set_border_width (RenderOpBuilder *builder,
   memcpy (&current_program_state->border.widths,
           widths, sizeof (float) * 4);
 
-  op.op = 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];
-
-  g_array_append_val (builder->render_ops, op);
+  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];
 }
 
 void
@@ -775,16 +747,18 @@ ops_draw (RenderOpBuilder     *builder,
       /* 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.op = OP_DRAW;
-      new_draw.draw.vao_offset = last_op->draw.vao_offset;
-      new_draw.draw.vao_size = last_op->draw.vao_size + GL_N_VERTICES;
+      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);
-
-      /* Now add the DRAW */
-      g_array_append_val (builder->render_ops, new_draw);
     }
   else
     {
@@ -821,9 +795,15 @@ ops_offset (RenderOpBuilder *builder,
   builder->dy += y;
 }
 
-void
-ops_add (RenderOpBuilder *builder,
-         const RenderOp  *op)
+RenderOp *
+ops_begin (RenderOpBuilder *builder,
+           guint            kind)
 {
-  g_array_append_val (builder->render_ops, *op);
+  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;
 }
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index 60e9317f7c..91ff2faa88 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -358,7 +358,7 @@ void              ops_offset             (RenderOpBuilder        *builder,
                                           float                   x,
                                           float                   y);
 
-void              ops_add                (RenderOpBuilder        *builder,
-                                          const RenderOp         *op);
+RenderOp         *ops_begin              (RenderOpBuilder        *builder,
+                                          guint                   kind);
 
 #endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]