#include "gskglprofilerprivate.h"
#include "gskprofilerprivate.h"
#include "gskrendererprivate.h"
+#include "gskrendernodeprivate.h"
#include "gsktransformprivate.h"
#include "gskshaderbuilderprivate.h"
#include "gskglglyphcacheprivate.h"
};
RenderOpBuilder op_builder;
- GArray *render_ops;
GskGLTextureAtlases *atlases;
GskGLGlyphCache *glyph_cache;
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);
{
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);
}
GskRenderNode *child = gsk_blur_node_get_child (node);
TextureRegion region;
gboolean is_offscreen;
- RenderOp *op;
+ OpBlur *op;
if (blur_radius <= 0)
{
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);
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)
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);
}
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);
}
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;
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);
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. */
{
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 }, },
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);
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 }, },
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);
}
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))
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)
}
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);
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);
}
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);
}
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,
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];
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
{
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);
/* 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);
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));
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);*/
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);
}
}
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:
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 ();
}
{
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
{
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
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;
{
gsk_transform_unref (builder->program_state[i].modelview);
}
+
+ op_buffer_destroy (&builder->render_ops);
}
void
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)
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);
}
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;
}
}
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;
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.
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)
{
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;
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 &&
ops_set_texture (RenderOpBuilder *builder,
int texture_id)
{
- RenderOp *op;
+ OpTexture *op;
if (builder->current_texture == texture_id)
return;
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)
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;
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;
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;
current_program_state->color = *color;
op = ops_begin (builder, OP_CHANGE_COLOR);
- op->color = color;
+ op->rgba = *color;
}
void
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,
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
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)
current_program_state->border.outline = *outline;
op = ops_begin (builder, OP_CHANGE_BORDER);
- op->border.outline = *outline;
+ op->outline = *outline;
}
void
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)
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
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 */
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;
}