summaryrefslogtreecommitdiff
path: root/gsk/gskcairorenderer.c
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2016-03-17 13:48:19 +0000
committerEmmanuele Bassi <ebassi@gnome.org>2016-10-18 11:29:34 +0100
commit7afdd3fdb5c5fda9da87555b40a61e6a321c2414 (patch)
treedf0af389900df9bf676695f95925dce9e8239d9d /gsk/gskcairorenderer.c
parentd519e4aafe325106f6a5f2139921bf246cb4848d (diff)
downloadgtk+-7afdd3fdb5c5fda9da87555b40a61e6a321c2414.tar.gz
Initial implementation of GSK rendering pipeline
GSK is conceptually split into two scene graphs: * a simple rendering tree of operations * a complex set of logical layers The latter is built on the former, and adds convenience and high level API for application developers. The lower layer, though, is what gets transformed into the rendering pipeline, as it's simple and thus can be transformed into appropriate rendering commands with minimal state changes. The lower layer is also suitable for reuse from more complex higher layers, like the CSS machinery in GTK, without necessarily port those layers to the GSK high level API. This lower layer is based on GskRenderNode instances, which represent the tree of rendering operations; and a GskRenderer instance, which takes the render nodes and submits them (after potentially reordering and transforming them to a more appropriate representation) to the underlying graphic system.
Diffstat (limited to 'gsk/gskcairorenderer.c')
-rw-r--r--gsk/gskcairorenderer.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
new file mode 100644
index 0000000000..62b7a47cfe
--- /dev/null
+++ b/gsk/gskcairorenderer.c
@@ -0,0 +1,195 @@
+#include "config.h"
+
+#include "gskcairorendererprivate.h"
+
+#include "gskdebugprivate.h"
+#include "gskrendererprivate.h"
+#include "gskrendernodeiter.h"
+#include "gskrendernodeprivate.h"
+
+struct _GskCairoRenderer
+{
+ GskRenderer parent_instance;
+
+ graphene_rect_t viewport;
+};
+
+struct _GskCairoRendererClass
+{
+ GskRendererClass parent_class;
+};
+
+G_DEFINE_TYPE (GskCairoRenderer, gsk_cairo_renderer, GSK_TYPE_RENDERER)
+
+static gboolean
+gsk_cairo_renderer_realize (GskRenderer *renderer)
+{
+ return TRUE;
+}
+
+static void
+gsk_cairo_renderer_unrealize (GskRenderer *renderer)
+{
+
+}
+
+static void
+gsk_cairo_renderer_render_node (GskCairoRenderer *self,
+ GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskRenderNodeIter iter;
+ GskRenderNode *child;
+ gboolean pop_group = FALSE;
+ graphene_matrix_t mvp;
+ cairo_matrix_t ctm;
+ graphene_rect_t frame;
+
+ if (gsk_render_node_is_hidden (node))
+ return;
+
+ cairo_save (cr);
+
+ gsk_render_node_get_world_matrix (node, &mvp);
+ if (graphene_matrix_to_2d (&mvp, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
+ {
+ GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
+ ctm.xx, ctm.yx,
+ ctm.xy, ctm.yy,
+ ctm.x0, ctm.y0));
+ cairo_transform (cr, &ctm);
+ }
+ else
+ g_critical ("Invalid non-affine transformation for node %p", node);
+
+ gsk_render_node_get_bounds (node, &frame);
+ GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
+ frame.origin.x, frame.origin.y,
+ frame.size.width, frame.size.height));
+
+ if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
+ {
+ cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+ cairo_clip (cr);
+ }
+
+ if (!gsk_render_node_is_opaque (node) && gsk_render_node_get_opacity (node) != 1.0)
+ {
+ GSK_NOTE (CAIRO, g_print ("Pushing opacity group (opacity:%g)\n",
+ gsk_render_node_get_opacity (node)));
+ cairo_push_group (cr);
+ pop_group = TRUE;
+ }
+
+ GSK_NOTE (CAIRO, g_print ("Rendering surface %p for node %p at %g, %g\n",
+ gsk_render_node_get_surface (node),
+ node,
+ frame.origin.x, frame.origin.y));
+ cairo_set_source_surface (cr, gsk_render_node_get_surface (node), frame.origin.x, frame.origin.y);
+ cairo_paint (cr);
+
+ if (GSK_RENDER_MODE_CHECK (GEOMETRY))
+ {
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+ }
+
+ cairo_matrix_invert (&ctm);
+ cairo_transform (cr, &ctm);
+
+ if (gsk_render_node_get_n_children (node) != 0)
+ {
+ GSK_NOTE (CAIRO, g_print ("Drawing %d children of node [%p]\n",
+ gsk_render_node_get_n_children (node),
+ node));
+ gsk_render_node_iter_init (&iter, node);
+ while (gsk_render_node_iter_next (&iter, &child))
+ gsk_cairo_renderer_render_node (self, child, cr);
+ }
+
+ if (pop_group)
+ {
+ cairo_pop_group_to_source (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_paint_with_alpha (cr, gsk_render_node_get_opacity (node));
+ }
+
+ cairo_restore (cr);
+}
+
+static void
+gsk_cairo_renderer_resize_viewport (GskRenderer *renderer,
+ const graphene_rect_t *viewport)
+{
+ GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
+
+ self->viewport = *viewport;
+}
+
+static void
+gsk_cairo_renderer_render (GskRenderer *renderer)
+{
+ GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
+ cairo_surface_t *target = gsk_renderer_get_surface (renderer);
+ GskRenderNode *root = gsk_renderer_get_root_node (renderer);
+ cairo_t *cr = cairo_create (target);
+
+ if (GSK_RENDER_MODE_CHECK (GEOMETRY))
+ {
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_rectangle (cr,
+ self->viewport.origin.x,
+ self->viewport.origin.y,
+ self->viewport.size.width,
+ self->viewport.size.height);
+ cairo_set_source_rgba (cr, 0, 0, 0.85, 0.5);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+ }
+
+ gsk_cairo_renderer_render_node (self, root, cr);
+
+ cairo_destroy (cr);
+}
+
+static void
+gsk_cairo_renderer_clear (GskRenderer *renderer)
+{
+ cairo_surface_t *surface = gsk_renderer_get_surface (renderer);
+ cairo_t *cr = cairo_create (surface);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+ if (gsk_renderer_get_use_alpha (renderer))
+ cairo_set_source_rgba (cr, 0, 0, 0, 0);
+ else
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+}
+
+static void
+gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
+{
+ GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);
+
+ renderer_class->realize = gsk_cairo_renderer_realize;
+ renderer_class->unrealize = gsk_cairo_renderer_unrealize;
+ renderer_class->resize_viewport = gsk_cairo_renderer_resize_viewport;
+ renderer_class->clear = gsk_cairo_renderer_clear;
+ renderer_class->render = gsk_cairo_renderer_render;
+}
+
+static void
+gsk_cairo_renderer_init (GskCairoRenderer *self)
+{
+
+}