[gtk+/wip/baedert/gl: 150/216] gl renderer: Move render ops into separate file
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/baedert/gl: 150/216] gl renderer: Move render ops into separate file
- Date: Mon, 18 Dec 2017 20:57:46 +0000 (UTC)
commit a9867e29cead11167692693c290845910693b850
Author: Timm Bäder <mail baedert org>
Date: Wed Nov 22 21:02:50 2017 +0100
gl renderer: Move render ops into separate file
gsk/gl/gskglrenderer.c | 508 +++++++---------------------------------
gsk/gl/gskglrenderops.c | 244 +++++++++++++++++++
gsk/gl/gskglrenderopsprivate.h | 162 +++++++++++++
gsk/meson.build | 1 +
4 files changed, 488 insertions(+), 427 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 3398861..9dba958 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -12,6 +12,7 @@
#include "gskshaderbuilderprivate.h"
#include "gskglglyphcacheprivate.h"
#include "gdk/gdktextureprivate.h"
+#include "gskglrenderopsprivate.h"
#include "gskprivate.h"
@@ -26,9 +27,6 @@
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
-#define N_VERTICES 6
-#define N_PROGRAMS 6
-
#define HIGHLIGHT_FALLBACK 0
#define DEBUG_OPS 0
@@ -54,7 +52,7 @@ dump_framebuffer (const char *filename, int w, int h)
cairo_surface_t *s;
glReadPixels (0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, data);
- s = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24, w, h, stride);
+ s = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, w, h, stride);
cairo_surface_write_to_png (s, filename);
cairo_surface_destroy (s);
@@ -81,102 +79,6 @@ font_has_color_glyphs (const PangoFont *font)
static void
gsk_gl_renderer_setup_render_mode (GskGLRenderer *self);
-typedef struct
-{
- int index; /* Into the renderer's program array */
- const char *name; /* For debugging */
-
- int id;
- /* Common locations (gl_common)*/
- int source_location;
- int mask_location;
- int uv_location;
- int position_location;
- int alpha_location;
- int blend_mode_location;
- int viewport_location;
- int projection_location;
- int modelview_location;
- int clip_location;
- int clip_corner_widths_location;
- int clip_corner_heights_location;
-
- /* Program-specific locations */
- union {
- struct {
- int color_location;
- };
- struct {
- int color_matrix_location;
- int color_offset_location;
- };
- struct {
- int n_color_stops_location;
- int color_stops_location;
- int color_offsets_location;
- int start_point_location;
- int end_point_location;
- };
- struct {
- int clip_bounds_location;
- int corner_widths_location;
- int corner_heights_location;
- };
- };
-} Program;
-
-enum {
- MODE_BLIT = 1,
- MODE_COLOR,
- MODE_COLORING,
- MODE_TEXTURE,
- MODE_COLOR_MATRIX,
- MODE_LINEAR_GRADIENT,
- N_MODES
-};
-
-enum {
- OP_NONE,
- OP_CHANGE_OPACITY = 1,
- OP_CHANGE_COLOR = 2,
- OP_CHANGE_PROJECTION = 3,
- OP_CHANGE_MODELVIEW = 4,
- OP_CHANGE_PROGRAM = 5,
- OP_CHANGE_RENDER_TARGET = 6,
- OP_CHANGE_CLIP = 7,
- OP_CHANGE_VIEWPORT = 8,
- OP_CHANGE_SOURCE_TEXTURE = 9,
- OP_CHANGE_VAO = 10,
- OP_CHANGE_LINEAR_GRADIENT = 11,
- OP_DRAW = 12,
-};
-
-typedef struct
-{
- guint op;
-
- union {
- float opacity;
- graphene_matrix_t modelview; // TODO: Make both matrix members just "matrix".
- graphene_matrix_t projection;
- const Program *program;
- GdkRGBA color;
- gsize vao_offset;
- GskQuadVertex vertex_data[N_VERTICES]; // New Quad
- int texture_id;
- int render_target_id;
- GskRoundedRect clip;
- graphene_rect_t viewport;
- struct {
- int n_color_stops;
- float color_offsets[8];
- float color_stops[4 * 8];
- graphene_point_t start_point;
- graphene_point_t end_point;
- } linear_gradient;
- };
-} RenderOp;
-
#ifdef G_ENABLE_DEBUG
typedef struct
{
@@ -216,7 +118,7 @@ struct _GskGLRenderer
GskGLProfiler *gl_profiler;
union {
- Program programs[N_PROGRAMS];
+ Program programs[GL_N_PROGRAMS];
struct {
Program blend_program;
Program blit_program;
@@ -250,264 +152,6 @@ struct _GskGLRendererClass
G_DEFINE_TYPE (GskGLRenderer, gsk_gl_renderer, GSK_TYPE_RENDERER)
-typedef struct
-{
- /* Per-Program State */
- struct {
- GskRoundedRect clip;
- graphene_matrix_t modelview;
- graphene_matrix_t projection;
- int source_texture;
- graphene_rect_t viewport;
- } program_state[N_PROGRAMS];
-
- /* Current global state */
- const Program *current_program;
- int current_render_target;
- int current_vao;
- int current_texture;
- GskRoundedRect current_clip;
- graphene_matrix_t current_modelview;
- graphene_matrix_t current_projection;
- graphene_rect_t current_viewport;
- float current_opacity;
-
- gsize buffer_size;
-
- GskGLRenderer *renderer;
-} RenderOpBuilder;
-
-static void
-add_program_op (RenderOpBuilder *builder,
- const Program *new_program)
-{
- static const GskRoundedRect empty_clip;
- static const graphene_matrix_t empty_matrix;
- static const graphene_rect_t empty_rect;
- RenderOp op;
-
- if (builder->current_program == new_program)
- return;
-
- op.op = OP_CHANGE_PROGRAM;
- op.program = new_program;
- g_array_append_val (builder->renderer->render_ops, op);
- builder->current_program = new_program;
-
- /* If the projection is not yet set for this program, we use the current one. */
- if (memcmp (&empty_matrix, &builder->program_state[new_program->index].projection, sizeof
(graphene_matrix_t)) == 0 ||
- memcmp (&builder->current_projection, &builder->program_state[new_program->index].projection, sizeof
(graphene_matrix_t)) != 0)
- {
- op.op = OP_CHANGE_PROJECTION;
- op.projection = builder->current_projection;
- g_array_append_val (builder->renderer->render_ops, op);
- builder->program_state[new_program->index].projection = builder->current_projection;
- }
-
- if (memcmp (&empty_matrix, &builder->program_state[new_program->index].modelview, sizeof
(graphene_matrix_t)) == 0 ||
- memcmp (&builder->current_modelview, &builder->program_state[new_program->index].modelview, sizeof
(graphene_matrix_t)) != 0)
- {
- op.op = OP_CHANGE_MODELVIEW;
- op.modelview = builder->current_modelview;
- g_array_append_val (builder->renderer->render_ops, op);
- builder->program_state[new_program->index].modelview = builder->current_modelview;
- }
-
- if (memcmp (&empty_rect, &builder->program_state[new_program->index].viewport, sizeof (graphene_rect_t))
== 0 ||
- memcmp (&builder->current_viewport, &builder->program_state[new_program->index].viewport, sizeof
(graphene_rect_t)) != 0)
- {
- op.op = OP_CHANGE_VIEWPORT;
- op.viewport = builder->current_viewport;
- g_array_append_val (builder->renderer->render_ops, op);
- builder->program_state[new_program->index].viewport = builder->current_viewport;
- }
-
- if (memcmp (&empty_clip, &builder->program_state[new_program->index].clip, sizeof (GskRoundedRect)) == 0 ||
- memcmp (&builder->current_clip, &builder->program_state[new_program->index].clip, sizeof
(GskRoundedRect)) != 0)
- {
- op.op = OP_CHANGE_CLIP;
- op.clip = builder->current_clip;
- g_array_append_val (builder->renderer->render_ops, op);
- builder->program_state[new_program->index].clip = builder->current_clip;
- }
-
- if (graphene_rect_equal (&empty_rect, &builder->program_state[new_program->index].viewport) ||
- !graphene_rect_equal (&builder->current_viewport,
&builder->program_state[new_program->index].viewport))
- {
- op.op = OP_CHANGE_VIEWPORT;
- op.viewport = builder->current_viewport;
- g_array_append_val (builder->renderer->render_ops, op);
- builder->program_state[new_program->index].viewport = builder->current_viewport;
- }
-}
-
-static GskRoundedRect
-add_clip_op (RenderOpBuilder *builder,
- const GskRoundedRect *new_clip)
-{
- RenderOp op;
- GskRoundedRect prev_clip;
-
- op.op = OP_CHANGE_CLIP;
- op.clip = *new_clip;
- g_array_append_val (builder->renderer->render_ops, op);
-
- if (builder->current_program != NULL)
- builder->program_state[builder->current_program->index].clip = *new_clip;
-
- prev_clip = builder->current_clip;
- builder->current_clip = *new_clip;
-
- return prev_clip;
-}
-
-static graphene_matrix_t
-add_modelview_op (RenderOpBuilder *builder,
- const graphene_matrix_t *matrix)
-{
- RenderOp op;
- graphene_matrix_t prev_mv;
- RenderOp *last_op;
-
- last_op = &g_array_index (builder->renderer->render_ops, RenderOp, builder->renderer->render_ops->len - 1);
- if (last_op->op == OP_CHANGE_MODELVIEW)
- {
- last_op->modelview = *matrix;
- }
- else
- {
- op.op = OP_CHANGE_MODELVIEW;
- op.modelview = *matrix;
- g_array_append_val (builder->renderer->render_ops, op);
- }
-
- if (builder->current_program != NULL)
- builder->program_state[builder->current_program->index].modelview = *matrix;
-
- prev_mv = builder->current_modelview;
- builder->current_modelview = *matrix;
-
- return prev_mv;
-}
-
-static graphene_matrix_t
-add_projection_op (RenderOpBuilder *builder,
- const graphene_matrix_t *matrix)
-{
- RenderOp op;
- graphene_matrix_t prev_proj;
-
- op.op = OP_CHANGE_PROJECTION;
- op.projection = *matrix;
- g_array_append_val (builder->renderer->render_ops, op);
-
- if (builder->current_program != NULL)
- builder->program_state[builder->current_program->index].projection = *matrix;
-
- prev_proj = builder->current_projection;
- builder->current_projection = *matrix;
-
- return prev_proj;
-}
-
-static graphene_rect_t
-add_viewport_op (RenderOpBuilder *builder,
- const graphene_rect_t *viewport)
-{
- RenderOp op;
- graphene_rect_t prev_viewport;
-
- op.op = OP_CHANGE_VIEWPORT;
- op.viewport = *viewport;
- g_array_append_val (builder->renderer->render_ops, op);
-
- if (builder->current_program != NULL)
- builder->program_state[builder->current_program->index].viewport = *viewport;
-
- prev_viewport = builder->current_viewport;
- builder->current_viewport = *viewport;
-
- return prev_viewport;
-}
-
-static void
-add_texture_op (RenderOpBuilder *builder,
- int texture_id)
-{
- 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->renderer->render_ops, op);
- builder->current_texture = texture_id;
-}
-
-static float
-add_opacity_op (RenderOpBuilder *builder,
- float opacity)
-{
- RenderOp op;
- float prev_opacity;
-
- if (builder->current_opacity == opacity)
- return opacity;
-
- op.op = OP_CHANGE_OPACITY;
- op.opacity = opacity;
- g_array_append_val (builder->renderer->render_ops, op);
-
- prev_opacity = builder->current_opacity;
- builder->current_opacity = opacity;
-
- return prev_opacity;
-}
-
-static int
-add_render_target_op (RenderOpBuilder *builder,
- int render_target_id)
-{
- RenderOp op;
- int prev_render_target;
-
- if (builder->current_render_target == render_target_id)
- return render_target_id;
-
- prev_render_target = builder->current_render_target;
- op.op = OP_CHANGE_RENDER_TARGET;
- op.render_target_id = render_target_id;
- g_array_append_val (builder->renderer->render_ops, op);
- builder->current_render_target = render_target_id;
-
- return prev_render_target;
-}
-
-static void
-add_draw_op (RenderOpBuilder *builder,
- const GskQuadVertex vertex_data[N_VERTICES])
-{
- RenderOp op;
- gsize offset = builder->buffer_size / sizeof (GskQuadVertex);
-
- op.op = OP_CHANGE_VAO;
- memcpy (&op.vertex_data, vertex_data, sizeof(GskQuadVertex) * N_VERTICES);
- g_array_append_val (builder->renderer->render_ops, op);
- builder->buffer_size += sizeof (GskQuadVertex) * N_VERTICES;
-
- op.op = OP_DRAW;
- op.vao_offset = offset;
- g_array_append_val (builder->renderer->render_ops, op);
-}
-
-static void
-add_op (RenderOpBuilder *builder,
- const RenderOp *op)
-{
- g_array_append_val (builder->renderer->render_ops, *op);
-}
-
static void
gsk_gl_renderer_dispose (GObject *gobject)
{
@@ -643,6 +287,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
goto out;
}
self->blend_program.index = 0;
+ self->blend_program.name = "blend";
init_common_locations (self, builder, &self->blend_program);
self->blit_program.id = gsk_shader_builder_create_program (builder,
@@ -656,6 +301,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
goto out;
}
self->blit_program.index = 1;
+ self->blit_program.name = "blit";
init_common_locations (self, builder, &self->blit_program);
self->color_program.id = gsk_shader_builder_create_program (builder,
@@ -669,6 +315,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
goto out;
}
self->color_program.index = 2;
+ self->color_program.name = "color";
init_common_locations (self, builder, &self->color_program);
INIT_PROGRAM_UNIFORM_LOCATION (color_program, color_location, "uColor");
@@ -733,7 +380,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
GError **error)
{
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
- GskQuadVertex vertex_data[N_VERTICES] = {
+ GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { 0, 0 }, { 0, 0 }, },
{ { 0, 1 }, { 0, 1 }, },
{ { 1, 0 }, { 1, 0 }, },
@@ -771,7 +418,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
gsk_gl_glyph_cache_init (&self->glyph_cache, self->gl_driver);
- gsk_gl_driver_create_permanent_vao_for_quad (self->gl_driver, N_VERTICES, vertex_data,
+ gsk_gl_driver_create_permanent_vao_for_quad (self->gl_driver, GL_N_VERTICES, vertex_data,
&self->full_vao_id, &self->full_vao_buffer_id);
return TRUE;
@@ -971,7 +618,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
float max_y = min_y + node->bounds.size.height;
/* Default vertex data */
- GskQuadVertex vertex_data[N_VERTICES] = {
+ GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { min_x, min_y }, { 0, 0 }, },
{ { min_x, max_y }, { 0, 1 }, },
{ { max_x, min_y }, { 1, 0 }, },
@@ -981,10 +628,11 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
{ { max_x, min_y }, { 1, 0 }, },
};
- /*if (gsk_render_node_get_node_type (node) != GSK_CONTAINER_NODE)*/
- /*g_message ("Adding ops for node %s with type %u", node->name,*/
- /*gsk_render_node_get_node_type (node));*/
-
+#if DEBUG_OPS
+ if (gsk_render_node_get_node_type (node) != GSK_CONTAINER_NODE)
+ g_message ("Adding ops for node %s with type %u", node->name,
+ gsk_render_node_get_node_type (node));
+#endif
switch (gsk_render_node_get_node_type (node))
{
@@ -1008,11 +656,11 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
{
RenderOp op;
- add_program_op (builder, &self->color_program);
+ ops_set_program (builder, &self->color_program);
op.op = OP_CHANGE_COLOR;
op.color = *gsk_color_node_peek_color (node);
- add_op (builder, &op);
- add_draw_op (builder, vertex_data);
+ ops_add (builder, &op);
+ ops_draw (builder, vertex_data);
}
break;
@@ -1028,9 +676,9 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
texture,
gl_min_filter,
gl_mag_filter);
- add_program_op (builder, &self->blit_program);
- add_texture_op (builder, texture_id);
- add_draw_op (builder, vertex_data);
+ ops_set_program (builder, &self->blit_program);
+ ops_set_texture (builder, texture_id);
+ ops_draw (builder, vertex_data);
}
break;
@@ -1042,18 +690,18 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node));
graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv);
- prev_mv = add_modelview_op (builder, &transformed_mv);
+ prev_mv = ops_set_modelview (builder, &transformed_mv);
gsk_gl_renderer_add_render_ops (self, child, builder);
- add_modelview_op (builder, &prev_mv);
+ ops_set_modelview (builder, &prev_mv);
}
break;
case GSK_OPACITY_NODE:
{
int render_target;
- int texture;
+ int texture_id;
int prev_render_target;
float prev_opacity;
graphene_matrix_t identity;
@@ -1061,7 +709,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
graphene_matrix_t prev_modelview;
graphene_rect_t prev_viewport;
graphene_matrix_t item_proj;
- GskQuadVertex vertex_data[N_VERTICES] = {
+ GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
@@ -1071,12 +719,14 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
{ { max_x, min_y }, { 1, 1 }, },
};
- texture = gsk_gl_driver_create_texture (self->gl_driver,
- node->bounds.size.width,
- node->bounds.size.height);
- gsk_gl_driver_bind_source_texture (self->gl_driver, texture);
- gsk_gl_driver_init_texture_empty (self->gl_driver, texture);
- render_target = gsk_gl_driver_create_render_target (self->gl_driver, texture, TRUE, TRUE);
+ texture_id = gsk_gl_driver_create_texture (self->gl_driver, max_x - min_x, max_y - min_y);
+ gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
+ gsk_gl_driver_init_texture_empty (self->gl_driver, texture_id);
+ render_target = gsk_gl_driver_create_render_target (self->gl_driver, texture_id, TRUE, TRUE);
+
+ /* Clear the framebuffer now, once */
+ RenderOp op;
+ op.op = OP_CLEAR;
graphene_matrix_init_ortho (&item_proj,
min_x, max_x,
@@ -1085,23 +735,26 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
graphene_matrix_scale (&item_proj, 1, -1, 1);
graphene_matrix_init_identity (&identity);
- prev_render_target = add_render_target_op (builder, render_target);
- prev_projection = add_projection_op (builder, &item_proj);
- prev_modelview = add_modelview_op (builder, &identity);
- prev_viewport = add_viewport_op (builder, &node->bounds);
+ prev_render_target = ops_set_render_target (builder, render_target);
+ /* Clear since we use this rendertarget for the first time */
+ ops_add (builder, &op);
+ prev_projection = ops_set_projection (builder, &item_proj);
+ prev_modelview = ops_set_modelview (builder, &identity);
+ prev_viewport = ops_set_viewport (builder, &node->bounds);
gsk_gl_renderer_add_render_ops (self, gsk_opacity_node_get_child (node), builder);
- add_viewport_op (builder, &prev_viewport);
- add_modelview_op (builder, &prev_modelview);
- add_projection_op (builder, &prev_projection);
- add_render_target_op (builder, prev_render_target);
-
- add_program_op (builder, &self->blit_program);
- prev_opacity = add_opacity_op (builder, gsk_opacity_node_get_opacity (node));
- add_texture_op (builder, texture);
- add_draw_op (builder, vertex_data);
- add_opacity_op (builder, prev_opacity);
+ ops_set_viewport (builder, &prev_viewport);
+ ops_set_modelview (builder, &prev_modelview);
+ ops_set_projection (builder, &prev_projection);
+ ops_set_render_target (builder, prev_render_target);
+
+ /* Now draw the texture with the node's opacity */
+ ops_set_program (builder, &self->blit_program);
+ prev_opacity = ops_set_opacity (builder, gsk_opacity_node_get_opacity (node));
+ ops_set_texture (builder, texture_id);
+ ops_draw (builder, vertex_data);
+ ops_set_opacity (builder, prev_opacity);
}
break;
@@ -1125,14 +778,14 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
op.linear_gradient.color_offsets[i] = stop->offset;
}
- add_program_op (builder, &self->linear_gradient_program);
+ 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.end_point = *end;
- add_op (builder, &op);
+ ops_add (builder, &op);
- add_draw_op (builder, vertex_data);
+ ops_draw (builder, vertex_data);
}
break;
@@ -1153,9 +806,9 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
gsk_rounded_rect_init_from_rect (&child_clip, &intersection, 0.0f);
- prev_clip = add_clip_op (builder, &child_clip);
+ prev_clip = ops_set_clip (builder, &child_clip);
gsk_gl_renderer_add_render_ops (self, child, builder);
- add_clip_op (builder, &prev_clip);
+ ops_set_clip (builder, &prev_clip);
}
break;
@@ -1179,9 +832,9 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
&rounded_clip->corner[2],
&rounded_clip->corner[3]);
- prev_clip = add_clip_op (builder, &child_clip);
+ prev_clip = ops_set_clip (builder, &child_clip);
gsk_gl_renderer_add_render_ops (self, child, builder);
- add_clip_op (builder, &prev_clip);
+ ops_set_clip (builder, &prev_clip);
}
break;
@@ -1228,20 +881,20 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
/* If the font has color glyphs, we don't need to recolor anything */
if (font_has_color_glyphs (font))
{
- add_program_op (builder, &self->blit_program);
+ ops_set_program (builder, &self->blit_program);
}
else
{
RenderOp op;
- add_program_op (builder, &self->coloring_program);
+ ops_set_program (builder, &self->coloring_program);
op.op = OP_CHANGE_COLOR;
op.color = *gsk_text_node_peek_color (node);
- add_op (builder, &op);
+ ops_add (builder, &op);
}
- add_texture_op (builder, gsk_gl_glyph_cache_get_glyph_image (&self->glyph_cache,
+ ops_set_texture (builder, gsk_gl_glyph_cache_get_glyph_image (&self->glyph_cache,
glyph)->texture_id);
{
@@ -1255,7 +908,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
glyph_w = glyph->draw_width;
glyph_h = glyph->draw_height;
- GskQuadVertex vertex_data[N_VERTICES] = {
+ GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { glyph_x, glyph_y }, { tx, ty }, },
{ { glyph_x, glyph_y + glyph_h }, { tx, ty2 }, },
{ { glyph_x + glyph_w, glyph_y }, { tx2, ty }, },
@@ -1265,7 +918,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
{ { glyph_x + glyph_w, glyph_y }, { tx2, ty }, },
};
- add_draw_op (builder, vertex_data);
+ ops_draw (builder, vertex_data);
}
x_position += gi->geometry.width;
@@ -1274,7 +927,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
}
break;
-
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_BORDER_NODE:
case GSK_INSET_SHADOW_NODE:
@@ -1324,9 +976,9 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
cairo_surface_destroy (surface);
- add_program_op (builder, &self->blit_program);
- add_texture_op (builder, texture_id);
- add_draw_op (builder, vertex_data);
+ ops_set_program (builder, &self->blit_program);
+ ops_set_texture (builder, texture_id);
+ ops_draw (builder, vertex_data);
}
}
}
@@ -1360,8 +1012,8 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
if (op->op == OP_CHANGE_VAO)
{
- memcpy (vertex_data + buffer_index, &op->vertex_data, sizeof (GskQuadVertex) * N_VERTICES);
- buffer_index += sizeof (GskQuadVertex) * N_VERTICES / sizeof (float);
+ memcpy (vertex_data + buffer_index, &op->vertex_data, sizeof (GskQuadVertex) * GL_N_VERTICES);
+ buffer_index += sizeof (GskQuadVertex) * GL_N_VERTICES / sizeof (float);
}
}
@@ -1410,24 +1062,24 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
case OP_CHANGE_PROGRAM:
program = op->program;
glUseProgram (op->program->id);
- OP_PRINT (" -> Program: %d", op->program->id);
+ OP_PRINT (" -> Program: %d(%s)", op->program->index, op->program->name);
break;
case OP_CHANGE_RENDER_TARGET:
OP_PRINT (" -> Render Target: %d", op->render_target_id);
glBindFramebuffer (GL_FRAMEBUFFER, op->render_target_id);
+
if (op->render_target_id != 0)
- {
- glDisable (GL_SCISSOR_TEST);
- glClearColor (0.0, 0.0, 0.0, 0.0);
- glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- }
+ glDisable (GL_SCISSOR_TEST);
else
- {
- /* Reset glScissor, etc. */
- gsk_gl_renderer_setup_render_mode (self);
- }
+ gsk_gl_renderer_setup_render_mode (self); /* Reset glScissor etc. */
+
+ break;
+
+ case OP_CLEAR:
+ glClearColor (0, 0, 0, 0);
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
break;
case OP_CHANGE_VIEWPORT:
@@ -1439,6 +1091,7 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
break;
case OP_CHANGE_OPACITY:
+ OP_PRINT (" -> Opacity %f", op->opacity);
glUniform1f (program->alpha_location, op->opacity);
break;
@@ -1494,8 +1147,8 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
break;
case OP_DRAW:
- OP_PRINT (" -> draw %ld\n", op->vao_offset);
- glDrawArrays (GL_TRIANGLES, op->vao_offset, N_VERTICES);
+ OP_PRINT (" -> draw %ld and program %s\n", op->vao_offset, program->name);
+ glDrawArrays (GL_TRIANGLES, op->vao_offset, GL_N_VERTICES);
break;
default:
@@ -1559,6 +1212,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
render_op_builder.current_viewport = *viewport;
render_op_builder.current_render_target = self->texture_id;
render_op_builder.current_opacity = 1.0f;
+ render_op_builder.render_ops = self->render_ops;
gsk_rounded_rect_init_from_rect (&render_op_builder.current_clip, &self->viewport, 0.0f);
gsk_gl_renderer_add_render_ops (self, root, &render_op_builder);
diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c
new file mode 100644
index 0000000..a1621c6
--- /dev/null
+++ b/gsk/gl/gskglrenderops.c
@@ -0,0 +1,244 @@
+#include "gskglrenderopsprivate.h"
+
+
+void
+ops_set_program (RenderOpBuilder *builder,
+ const Program *program)
+{
+ /* The tricky part about this is that we want to initialize all uniforms of a program
+ * to the current value from the builder, but only once. */
+ static const GskRoundedRect empty_clip;
+ static const graphene_matrix_t empty_matrix;
+ static const graphene_rect_t empty_rect;
+ RenderOp op;
+
+ if (builder->current_program == program)
+ return;
+
+ op.op = OP_CHANGE_PROGRAM;
+ op.program = program;
+ g_array_append_val (builder->render_ops, op);
+ builder->current_program = program;
+
+ /* If the projection is not yet set for this program, we use the current one. */
+ if (memcmp (&empty_matrix, &builder->program_state[program->index].projection, sizeof (graphene_matrix_t))
== 0 ||
+ memcmp (&builder->current_projection, &builder->program_state[program->index].projection, sizeof
(graphene_matrix_t)) != 0)
+ {
+ op.op = OP_CHANGE_PROJECTION;
+ op.projection = builder->current_projection;
+ g_array_append_val (builder->render_ops, op);
+ builder->program_state[program->index].projection = builder->current_projection;
+ }
+
+ if (memcmp (&empty_matrix, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t))
== 0 ||
+ memcmp (&builder->current_modelview, &builder->program_state[program->index].modelview, sizeof
(graphene_matrix_t)) != 0)
+ {
+ op.op = OP_CHANGE_MODELVIEW;
+ op.modelview = builder->current_modelview;
+ g_array_append_val (builder->render_ops, op);
+ builder->program_state[program->index].modelview = builder->current_modelview;
+ }
+
+ if (memcmp (&empty_rect, &builder->program_state[program->index].viewport, sizeof (graphene_rect_t)) == 0
||
+ memcmp (&builder->current_viewport, &builder->program_state[program->index].viewport, sizeof
(graphene_rect_t)) != 0)
+ {
+ op.op = OP_CHANGE_VIEWPORT;
+ op.viewport = builder->current_viewport;
+ g_array_append_val (builder->render_ops, op);
+ builder->program_state[program->index].viewport = builder->current_viewport;
+ }
+
+ if (memcmp (&empty_clip, &builder->program_state[program->index].clip, sizeof (GskRoundedRect)) == 0 ||
+ memcmp (&builder->current_clip, &builder->program_state[program->index].clip, sizeof (GskRoundedRect))
!= 0)
+ {
+ op.op = OP_CHANGE_CLIP;
+ op.clip = builder->current_clip;
+ g_array_append_val (builder->render_ops, op);
+ builder->program_state[program->index].clip = builder->current_clip;
+ }
+
+ if (graphene_rect_equal (&empty_rect, &builder->program_state[program->index].viewport) ||
+ !graphene_rect_equal (&builder->current_viewport, &builder->program_state[program->index].viewport))
+ {
+ op.op = OP_CHANGE_VIEWPORT;
+ op.viewport = builder->current_viewport;
+ g_array_append_val (builder->render_ops, op);
+ builder->program_state[program->index].viewport = builder->current_viewport;
+ }
+}
+
+GskRoundedRect
+ops_set_clip (RenderOpBuilder *builder,
+ const GskRoundedRect *clip)
+{
+ RenderOp op;
+ GskRoundedRect prev_clip;
+
+ op.op = OP_CHANGE_CLIP;
+ op.clip = *clip;
+ g_array_append_val (builder->render_ops, op);
+
+ if (builder->current_program != NULL)
+ builder->program_state[builder->current_program->index].clip = *clip;
+
+ prev_clip = builder->current_clip;
+ builder->current_clip = *clip;
+
+ return prev_clip;
+}
+
+graphene_matrix_t
+ops_set_modelview (RenderOpBuilder *builder,
+ const graphene_matrix_t *modelview)
+{
+ RenderOp op;
+ graphene_matrix_t prev_mv;
+ RenderOp *last_op;
+
+ last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
+ if (last_op->op == OP_CHANGE_MODELVIEW)
+ {
+ last_op->modelview = *modelview;
+ }
+ else
+ {
+ op.op = OP_CHANGE_MODELVIEW;
+ op.modelview = *modelview;
+ g_array_append_val (builder->render_ops, op);
+ }
+
+ if (builder->current_program != NULL)
+ builder->program_state[builder->current_program->index].modelview = *modelview;
+
+ prev_mv = builder->current_modelview;
+ builder->current_modelview = *modelview;
+
+ return prev_mv;
+}
+
+graphene_matrix_t
+ops_set_projection (RenderOpBuilder *builder,
+ const graphene_matrix_t *projection)
+{
+ RenderOp op;
+ graphene_matrix_t prev_mv;
+ RenderOp *last_op;
+
+ 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.op = OP_CHANGE_PROJECTION;
+ op.projection = *projection;
+ g_array_append_val (builder->render_ops, op);
+ }
+
+ if (builder->current_program != NULL)
+ builder->program_state[builder->current_program->index].projection = *projection;
+
+ prev_mv = builder->current_projection;
+ builder->current_projection = *projection;
+
+ return prev_mv;
+}
+
+graphene_rect_t
+ops_set_viewport (RenderOpBuilder *builder,
+ const graphene_rect_t *viewport)
+{
+ RenderOp op;
+ graphene_rect_t prev_viewport;
+
+ op.op = OP_CHANGE_VIEWPORT;
+ op.viewport = *viewport;
+ g_array_append_val (builder->render_ops, op);
+
+ if (builder->current_program != NULL)
+ builder->program_state[builder->current_program->index].viewport = *viewport;
+
+ prev_viewport = builder->current_viewport;
+ builder->current_viewport = *viewport;
+
+ return prev_viewport;
+}
+
+void
+ops_set_texture (RenderOpBuilder *builder,
+ int texture_id)
+{
+ 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);
+ builder->current_texture = texture_id;
+}
+
+int
+ops_set_render_target (RenderOpBuilder *builder,
+ int render_target_id)
+{
+ RenderOp op;
+ int prev_render_target;
+
+ if (builder->current_render_target == render_target_id)
+ return render_target_id;
+
+ prev_render_target = builder->current_render_target;
+ op.op = OP_CHANGE_RENDER_TARGET;
+ op.render_target_id = render_target_id;
+ g_array_append_val (builder->render_ops, op);
+ builder->current_render_target = render_target_id;
+
+ return prev_render_target;
+}
+
+float
+ops_set_opacity (RenderOpBuilder *builder,
+ float opacity)
+{
+ RenderOp op;
+ float prev_opacity;
+
+ if (builder->current_opacity == opacity)
+ return opacity;
+
+ op.op = OP_CHANGE_OPACITY;
+ op.opacity = opacity;
+ g_array_append_val (builder->render_ops, op);
+
+ prev_opacity = builder->current_opacity;
+ builder->current_opacity = opacity;
+
+ return prev_opacity;
+}
+
+void
+ops_draw (RenderOpBuilder *builder,
+ const GskQuadVertex vertex_data[GL_N_VERTICES])
+{
+ RenderOp op;
+ gsize offset = builder->buffer_size / sizeof (GskQuadVertex);
+
+ op.op = OP_CHANGE_VAO;
+ memcpy (&op.vertex_data, vertex_data, sizeof(GskQuadVertex) * GL_N_VERTICES);
+ g_array_append_val (builder->render_ops, op);
+ builder->buffer_size += sizeof (GskQuadVertex) * GL_N_VERTICES;
+
+ op.op = OP_DRAW;
+ op.vao_offset = offset;
+ g_array_append_val (builder->render_ops, op);
+}
+
+void
+ops_add (RenderOpBuilder *builder,
+ const RenderOp *op)
+{
+ g_array_append_val (builder->render_ops, *op);
+}
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
new file mode 100644
index 0000000..11d69df
--- /dev/null
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -0,0 +1,162 @@
+#ifndef __GSK_GL_RENDER_OPS_H__
+#define __GSK_GL_RENDER_OPS_H__
+
+#include <glib.h>
+#include <graphene.h>
+#include <gdk/gdk.h>
+
+#include "gskgldriverprivate.h"
+#include "gskroundedrectprivate.h"
+#include "gskglrendererprivate.h"
+
+#define GL_N_VERTICES 6
+#define GL_N_PROGRAMS 6
+
+enum {
+ OP_NONE,
+ OP_CHANGE_OPACITY = 1,
+ OP_CHANGE_COLOR = 2,
+ OP_CHANGE_PROJECTION = 3,
+ OP_CHANGE_MODELVIEW = 4,
+ OP_CHANGE_PROGRAM = 5,
+ OP_CHANGE_RENDER_TARGET = 6,
+ OP_CHANGE_CLIP = 7,
+ OP_CHANGE_VIEWPORT = 8,
+ OP_CHANGE_SOURCE_TEXTURE = 9,
+ OP_CHANGE_VAO = 10,
+ OP_CHANGE_LINEAR_GRADIENT = 11,
+ OP_CLEAR = 12,
+ OP_DRAW = 13,
+};
+
+typedef struct
+{
+ int index; /* Into the renderer's program array */
+ const char *name; /* For debugging */
+
+ int id;
+ /* Common locations (gl_common)*/
+ int source_location;
+ int mask_location;
+ int uv_location;
+ int position_location;
+ int alpha_location;
+ int blend_mode_location;
+ int viewport_location;
+ int projection_location;
+ int modelview_location;
+ int clip_location;
+ int clip_corner_widths_location;
+ int clip_corner_heights_location;
+
+ /* Program-specific locations */
+ union {
+ struct {
+ int color_location;
+ };
+ struct {
+ int color_matrix_location;
+ int color_offset_location;
+ };
+ struct {
+ int n_color_stops_location;
+ int color_stops_location;
+ int color_offsets_location;
+ int start_point_location;
+ int end_point_location;
+ };
+ struct {
+ int clip_bounds_location;
+ int corner_widths_location;
+ int corner_heights_location;
+ };
+ };
+} Program;
+
+typedef struct
+{
+ guint op;
+
+ union {
+ float opacity;
+ graphene_matrix_t modelview; /* TODO: Make both matrix members just "matrix" */
+ graphene_matrix_t projection;
+ const Program *program;
+ int texture_id;
+ int render_target_id;
+ GdkRGBA color;
+ gsize vao_offset;
+ GskQuadVertex vertex_data[6];
+ GskRoundedRect clip;
+ graphene_rect_t viewport;
+ struct {
+ int n_color_stops;
+ float color_offsets[8];
+ float color_stops[4 * 8];
+ graphene_point_t start_point;
+ graphene_point_t end_point;
+ } linear_gradient;
+ };
+} RenderOp;
+
+typedef struct
+{
+ /* Per-Program State */
+ struct {
+ GskRoundedRect clip;
+ graphene_matrix_t modelview;
+ graphene_matrix_t projection;
+ int source_texture;
+ graphene_rect_t viewport;
+ } program_state[GL_N_PROGRAMS];
+
+ /* Current global state */
+ const Program *current_program;
+ int current_render_target;
+ int current_vao;
+ int current_texture;
+ GskRoundedRect current_clip;
+ graphene_matrix_t current_modelview;
+ graphene_matrix_t current_projection;
+ graphene_rect_t current_viewport;
+ float current_opacity;
+
+ gsize buffer_size;
+
+ GArray *render_ops;
+ GskGLRenderer *renderer;
+} RenderOpBuilder;
+
+
+
+void ops_set_program (RenderOpBuilder *builder,
+ const Program *program);
+
+GskRoundedRect ops_set_clip (RenderOpBuilder *builder,
+ const GskRoundedRect *clip);
+
+graphene_matrix_t ops_set_modelview (RenderOpBuilder *builder,
+ const graphene_matrix_t *modelview);
+
+graphene_matrix_t ops_set_projection (RenderOpBuilder *builder,
+ const graphene_matrix_t *projection);
+
+graphene_rect_t ops_set_viewport (RenderOpBuilder *builder,
+ const graphene_rect_t *viewport);
+
+void ops_set_texture (RenderOpBuilder *builder,
+ int texture_id);
+
+int ops_set_render_target (RenderOpBuilder *builder,
+ int render_target_id);
+
+float ops_set_opacity (RenderOpBuilder *builder,
+ float opacity);
+
+void ops_draw (RenderOpBuilder *builder,
+ const GskQuadVertex vertex_data[GL_N_VERTICES]);
+
+void ops_add (RenderOpBuilder *builder,
+ const RenderOp *op);
+
+#endif
diff --git a/gsk/meson.build b/gsk/meson.build
index 89de8bb..c544a6c 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -34,6 +34,7 @@ gsk_private_sources = files([
'gl/gskglglyphcache.c',
'gl/gskglimage.c',
'gl/gskgldriver.c',
+ 'gl/gskglrenderops.c'
])
gsk_public_headers = files([
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]