gl: avoid copying RenderOp to GArray
authorChristian Hergert <chergert@redhat.com>
Wed, 9 Oct 2019 22:41:53 +0000 (15:41 -0700)
committerChristian Hergert <chergert@redhat.com>
Wed, 9 Oct 2019 22:41:53 +0000 (15:41 -0700)
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
gsk/gl/gskglrenderops.c
gsk/gl/gskglrenderopsprivate.h

index 118b67c0ec0b59fe7dd0792eeaa2587b1c49a8dd..3835aaa2bb34ffe636a972be5be4764ddee27f10 100644 (file)
@@ -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,
index d34f2c24057d1ac701fb9e45accd46c6b3185871..f7105f202a5b2fb0c3ef00c966cd899169994d45 100644 (file)
@@ -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;
 }
index 60e9317f7c4f8fb078415eda413e4be9a7bc74e4..91ff2faa88b97129a077324e2bae8c451e9179be 100644 (file)
@@ -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