summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2016-06-22 17:30:36 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2016-06-22 17:47:35 +0100
commitb65a7b5efe877814b8ce6b94c0e166c9972c0c46 (patch)
tree8ff5ce4f7fa6474c6a56363ed469a18945672be6
parentfcb095fcf95de7d4218356a787d63121208e4b27 (diff)
downloadgtk+-wip/ebassi/gsk-1.tar.gz
gsk: Rework GskRenderer and GskRenderNode semanticswip/ebassi/gsk-1
This commit changes the way GskRenderer and GskRenderNode interact and are meant to be used. GskRenderNode should represent a transient tree of rendering nodes, which are submitted to the GskRenderer at render time; this allows the renderer to take ownership of the render tree. Once the toolkit and application code have finished assembling it, the render tree ownership is transferred to the renderer.
-rw-r--r--gsk/gskcairorenderer.c51
-rw-r--r--gsk/gskglrenderer.c292
-rw-r--r--gsk/gskrenderer.c575
-rw-r--r--gsk/gskrenderer.h31
-rw-r--r--gsk/gskrendererprivate.h23
-rw-r--r--gsk/gskrendernode.c338
-rw-r--r--gsk/gskrendernode.h9
-rw-r--r--gsk/gskrendernodeprivate.h46
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/testgskrenderer.c229
10 files changed, 338 insertions, 1260 deletions
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
index 62b7a47cfe..0d3591c1ff 100644
--- a/gsk/gskcairorenderer.c
+++ b/gsk/gskcairorenderer.c
@@ -123,21 +123,28 @@ gsk_cairo_renderer_render_node (GskCairoRenderer *self,
}
static void
-gsk_cairo_renderer_resize_viewport (GskRenderer *renderer,
- const graphene_rect_t *viewport)
+gsk_cairo_renderer_render (GskRenderer *renderer,
+ GskRenderNode *root,
+ GdkDrawingContext *context)
{
GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
+ cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
- self->viewport = *viewport;
-}
+ gsk_renderer_get_viewport (renderer, &self->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_renderer_get_auto_clear (renderer))
+ {
+ cairo_save (cr);
+ 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_restore (cr);
+ }
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
{
@@ -154,26 +161,6 @@ gsk_cairo_renderer_render (GskRenderer *renderer)
}
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
@@ -183,8 +170,6 @@ gsk_cairo_renderer_class_init (GskCairoRendererClass *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;
}
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index c46d7582e3..15cadb88ca 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -432,16 +432,9 @@ gsk_gl_renderer_realize (GskRenderer *renderer)
gdk_gl_context_make_current (self->context);
GSK_NOTE (OPENGL, g_print ("Creating buffers and programs\n"));
-
gsk_gl_renderer_create_buffers (self);
gsk_gl_renderer_create_program (self);
- self->opaque_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), 16);
- g_array_set_clear_func (self->opaque_render_items, render_item_clear);
-
- self->transparent_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), 16);
- g_array_set_clear_func (self->opaque_render_items, render_item_clear);
-
return TRUE;
}
@@ -466,18 +459,22 @@ gsk_gl_renderer_unrealize (GskRenderer *renderer)
}
static void
-gsk_gl_renderer_resize_viewport (GskRenderer *renderer,
+gsk_gl_renderer_resize_viewport (GskGLRenderer *self,
const graphene_rect_t *viewport)
{
+ GSK_NOTE (OPENGL, g_print ("glViewport(0, 0, %g, %g)\n",
+ viewport->size.width,
+ viewport->size.height));
+
+ glViewport (viewport->origin.x, viewport->origin.y,
+ viewport->size.width, viewport->size.height);
}
static void
-gsk_gl_renderer_update (GskRenderer *renderer,
- const graphene_matrix_t *modelview,
- const graphene_matrix_t *projection)
+gsk_gl_renderer_update_frustum (GskGLRenderer *self,
+ const graphene_matrix_t *modelview,
+ const graphene_matrix_t *projection)
{
- GskGLRenderer *self = GSK_GL_RENDERER (renderer);
-
GSK_NOTE (OPENGL, g_print ("Updating the modelview/projection\n"));
graphene_matrix_multiply (modelview, projection, &self->mvp);
@@ -662,6 +659,7 @@ get_gl_scaling_filters (GskRenderer *renderer,
}
}
+#if 0
static gboolean
check_in_frustum (const graphene_frustum_t *frustum,
RenderItem *item)
@@ -673,6 +671,7 @@ check_in_frustum (const graphene_frustum_t *frustum,
return graphene_frustum_intersects_box (frustum, &aabb);
}
+#endif
static float
project_item (const graphene_matrix_t *projection,
@@ -748,19 +747,6 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
gsk_renderer_get_projection (GSK_RENDERER (self), &projection);
item.z = project_item (&projection, &mv);
- /* Discard the item if it's outside of the frustum as determined by the
- * viewport and the projection matrix
- */
-#if 0
- if (!check_in_frustum (&self->frustum, &item))
- {
- GSK_NOTE (OPENGL, g_print ("Node <%s>[%p] culled by frustum\n",
- node->name != NULL ? node->name : "unnamed",
- node));
- return;
- }
-#endif
-
/* TODO: This should really be an asset atlas, to avoid uploading a ton
* of textures. Ideally we could use a single Cairo surface to get around
* the GL texture limits and reorder the texture data on the CPU side and
@@ -787,7 +773,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
if (gsk_render_node_is_opaque (node) && gsk_render_node_get_opacity (node) == 1.f)
g_array_append_val (self->opaque_render_items, item);
else
- g_array_append_val (self->transparent_render_items, item);
+ g_array_prepend_val (self->transparent_render_items, item);
recurse_children:
gsk_render_node_iter_init (&iter, node);
@@ -795,198 +781,72 @@ recurse_children:
gsk_gl_renderer_add_render_item (self, child);
}
-static int
-opaque_item_cmp (gconstpointer _a,
- gconstpointer _b)
-{
- const RenderItem *a = _a;
- const RenderItem *b = _b;
-
- if (a->z != b->z)
- {
- if (a->z > b->z)
- return 1;
-
- return -1;
- }
-
- if (a != b)
- {
- if ((gsize) a > (gsize) b)
- return 1;
-
- return -1;
- }
-
- return 0;
-}
-
-static int
-transparent_item_cmp (gconstpointer _a,
- gconstpointer _b)
-{
- const RenderItem *a = _a;
- const RenderItem *b = _b;
-
- if (a->z != b->z)
- {
- if (a->z < b->z)
- return 1;
-
- return -1;
- }
-
- if (a != b)
- {
- if ((gsize) a < (gsize) b)
- return 1;
-
- return -1;
- }
-
- return 0;
-}
-
-static void
-gsk_gl_renderer_validate_tree (GskRenderer *renderer,
+static gboolean
+gsk_gl_renderer_validate_tree (GskGLRenderer *self,
GskRenderNode *root)
{
- GskGLRenderer *self = GSK_GL_RENDERER (renderer);
- gboolean clear_items = FALSE;
- int i;
+ int n_children;
if (self->context == NULL)
- return;
-
- gdk_gl_context_make_current (self->context);
+ return FALSE;
- if (self->opaque_render_items->len > 0 || self->transparent_render_items->len > 0)
- {
- /* If we only changed the opacity and transformations then there is no
- * reason to clear the render items
- */
- for (i = 0; i < self->opaque_render_items->len; i++)
- {
- RenderItem *item = &g_array_index (self->opaque_render_items, RenderItem, i);
- GskRenderNodeChanges changes = gsk_render_node_get_last_state (item->node);
-
- if (changes == 0)
- continue;
-
- if ((changes & GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY) != 0)
- {
- item->opaque = gsk_render_node_is_opaque (item->node);
- item->opacity = gsk_render_node_get_opacity (item->node);
- changes &= ~GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY;
- }
-
- if (changes & GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM)
- {
- gsk_render_node_get_world_matrix (item->node, &item->mvp);
- changes &= ~ GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM;
- }
-
- if (changes != 0)
- {
- clear_items = TRUE;
- break;
- }
- }
-
- for (i = 0; i < self->transparent_render_items->len; i++)
- {
- RenderItem *item = &g_array_index (self->transparent_render_items, RenderItem, i);
- GskRenderNodeChanges changes = gsk_render_node_get_last_state (item->node);
-
- if (changes == 0)
- continue;
-
- if ((changes & GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY) != 0)
- {
- item->opaque = gsk_render_node_is_opaque (item->node);
- item->opacity = gsk_render_node_get_opacity (item->node);
- changes &= ~GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY;
- }
-
- if (changes & GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM)
- {
- gsk_render_node_get_world_matrix (item->node, &item->mvp);
- changes &= ~ GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM;
- }
-
- if (changes != 0)
- {
- clear_items = TRUE;
- break;
- }
- }
- }
- else
- clear_items = TRUE;
+ n_children = gsk_render_node_get_n_children (root);
+ if (n_children == 0)
+ return FALSE;
- if (!clear_items)
- {
- GSK_NOTE (OPENGL, g_print ("Tree is still valid\n"));
- goto out;
- }
+ gdk_gl_context_make_current (self->context);
- for (i = 0; i < self->opaque_render_items->len; i++)
- render_item_clear (&g_array_index (self->opaque_render_items, RenderItem, i));
- for (i = 0; i < self->transparent_render_items->len; i++)
- render_item_clear (&g_array_index (self->transparent_render_items, RenderItem, i));
+ self->opaque_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), n_children);
+ self->transparent_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), n_children);
- g_array_set_size (self->opaque_render_items, 0);
- g_array_set_size (self->transparent_render_items, 0);
+ g_array_set_clear_func (self->opaque_render_items, render_item_clear);
+ g_array_set_clear_func (self->transparent_render_items, render_item_clear);
GSK_NOTE (OPENGL, g_print ("RenderNode -> RenderItem\n"));
- gsk_gl_renderer_add_render_item (self, gsk_renderer_get_root_node (renderer));
-
- GSK_NOTE (OPENGL, g_print ("Sorting render nodes\n"));
- g_array_sort (self->opaque_render_items, opaque_item_cmp);
- g_array_sort (self->transparent_render_items, transparent_item_cmp);
+ gsk_gl_renderer_add_render_item (self, root);
-out:
GSK_NOTE (OPENGL, g_print ("Total render items: %d (opaque:%d, transparent:%d)\n",
self->opaque_render_items->len + self->transparent_render_items->len,
self->opaque_render_items->len,
self->transparent_render_items->len));
+
+ return TRUE;
}
static void
-gsk_gl_renderer_clear_tree (GskRenderer *renderer,
- GskRenderNode *root_node)
+gsk_gl_renderer_clear_tree (GskGLRenderer *self)
{
- GskGLRenderer *self = GSK_GL_RENDERER (renderer);
-
if (self->context == NULL)
return;
- gdk_gl_context_make_current (self->context);
-
g_clear_pointer (&self->opaque_render_items, g_array_unref);
g_clear_pointer (&self->transparent_render_items, g_array_unref);
-
- if (gsk_renderer_is_realized (renderer))
- {
- self->opaque_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), 16);
- g_array_set_clear_func (self->opaque_render_items, render_item_clear);
-
- self->transparent_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), 16);
- g_array_set_clear_func (self->opaque_render_items, render_item_clear);
- }
}
static void
-gsk_gl_renderer_clear (GskRenderer *renderer)
+gsk_gl_renderer_clear (GskGLRenderer *self)
{
+ int clear_bits = GL_COLOR_BUFFER_BIT;
+
+ if (self->has_depth_buffer)
+ clear_bits |= GL_DEPTH_BUFFER_BIT;
+ if (self->has_stencil_buffer)
+ clear_bits |= GL_STENCIL_BUFFER_BIT;
+
+ GSK_NOTE (OPENGL, g_print ("Clearing viewport\n"));
+ glClearColor (0, 0, 0, 0);
+ glClear (clear_bits);
}
static void
-gsk_gl_renderer_render (GskRenderer *renderer)
+gsk_gl_renderer_render (GskRenderer *renderer,
+ GskRenderNode *root,
+ GdkDrawingContext *context)
{
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
+ graphene_matrix_t modelview, projection;
graphene_rect_t viewport;
- int scale, status, clear_bits;
+ int status;
guint i;
if (self->context == NULL)
@@ -1008,22 +868,16 @@ gsk_gl_renderer_render (GskRenderer *renderer)
/* Ensure that the viewport is up to date */
status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
if (status == GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- GSK_NOTE (OPENGL, g_print ("glViewport(0, 0, %g, %g)\n",
- viewport.size.width,
- viewport.size.height));
- glViewport (0, 0, viewport.size.width, viewport.size.height);
- }
+ gsk_gl_renderer_resize_viewport (self, &viewport);
- clear_bits = GL_COLOR_BUFFER_BIT;
- if (self->has_depth_buffer)
- clear_bits |= GL_DEPTH_BUFFER_BIT;
- if (self->has_stencil_buffer)
- clear_bits |= GL_STENCIL_BUFFER_BIT;
+ gsk_gl_renderer_clear (self);
- GSK_NOTE (OPENGL, g_print ("Clearing viewport\n"));
- glClearColor (0, 0, 0, 0);
- glClear (clear_bits);
+ gsk_renderer_get_modelview (renderer, &modelview);
+ gsk_renderer_get_projection (renderer, &projection);
+ gsk_gl_renderer_update_frustum (self, &modelview, &projection);
+
+ if (!gsk_gl_renderer_validate_tree (self, root))
+ goto out;
/* Opaque pass: front-to-back */
GSK_NOTE (OPENGL, g_print ("Rendering %u opaque items\n", self->opaque_render_items->len));
@@ -1050,15 +904,18 @@ gsk_gl_renderer_render (GskRenderer *renderer)
/* Draw the output of the GL rendering to the window */
GSK_NOTE (OPENGL, g_print ("Drawing GL content on Cairo surface using a %s\n",
self->texture_id != 0 ? "texture" : "renderbuffer"));
- scale = 1;
- gdk_cairo_draw_from_gl (gsk_renderer_get_draw_context (renderer),
- gsk_renderer_get_window (renderer),
+
+out:
+ gdk_cairo_draw_from_gl (gdk_drawing_context_get_cairo_context (context),
+ gdk_drawing_context_get_window (context),
self->texture_id != 0 ? self->texture_id : self->render_buffer,
self->texture_id != 0 ? GL_TEXTURE : GL_RENDERBUFFER,
- scale,
+ gsk_renderer_get_scale_factor (renderer),
0, 0, viewport.size.width, viewport.size.height);
gdk_gl_context_make_current (self->context);
+
+ gsk_gl_renderer_clear_tree (self);
}
static void
@@ -1071,11 +928,6 @@ gsk_gl_renderer_class_init (GskGLRendererClass *klass)
renderer_class->realize = gsk_gl_renderer_realize;
renderer_class->unrealize = gsk_gl_renderer_unrealize;
- renderer_class->resize_viewport = gsk_gl_renderer_resize_viewport;
- renderer_class->update = gsk_gl_renderer_update;
- renderer_class->clear = gsk_gl_renderer_clear;
- renderer_class->validate_tree = gsk_gl_renderer_validate_tree;
- renderer_class->clear_tree = gsk_gl_renderer_clear_tree;
renderer_class->render = gsk_gl_renderer_render;
}
@@ -1089,27 +941,3 @@ gsk_gl_renderer_init (GskGLRenderer *self)
self->has_depth_buffer = TRUE;
self->has_stencil_buffer = TRUE;
}
-
-void
-gsk_gl_renderer_set_context (GskGLRenderer *renderer,
- GdkGLContext *context)
-{
- g_return_if_fail (GSK_IS_GL_RENDERER (renderer));
- g_return_if_fail (context == NULL || GDK_IS_GL_CONTEXT (context));
-
- if (gsk_renderer_is_realized (GSK_RENDERER (renderer)))
- return;
-
- if (gdk_gl_context_get_display (context) != gsk_renderer_get_display (GSK_RENDERER (renderer)))
- return;
-
- g_set_object (&renderer->context, context);
-}
-
-GdkGLContext *
-gsk_gl_renderer_get_context (GskGLRenderer *renderer)
-{
- g_return_val_if_fail (GSK_IS_GL_RENDERER (renderer), NULL);
-
- return renderer->context;
-}
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c
index 3a84fc9547..72717bbbdf 100644
--- a/gsk/gskrenderer.c
+++ b/gsk/gskrenderer.c
@@ -29,7 +29,6 @@
#include "gskrendererprivate.h"
#include "gskdebugprivate.h"
-#include "gskcairorendererprivate.h"
#include "gskglrendererprivate.h"
#include "gskrendernodeprivate.h"
@@ -50,9 +49,6 @@ typedef struct
{
GObject parent_instance;
- GdkDisplay *display;
- GdkWindow *window;
-
graphene_rect_t viewport;
graphene_matrix_t modelview;
graphene_matrix_t projection;
@@ -60,16 +56,14 @@ typedef struct
GskScalingFilter min_filter;
GskScalingFilter mag_filter;
+ GdkWindow *window;
+ GdkDrawingContext *drawing_context;
GskRenderNode *root_node;
+ GdkDisplay *display;
- cairo_surface_t *surface;
- cairo_t *draw_context;
+ int scale_factor;
gboolean is_realized : 1;
- gboolean needs_viewport_resize : 1;
- gboolean needs_modelview_update : 1;
- gboolean needs_projection_update : 1;
- gboolean needs_tree_validation : 1;
gboolean auto_clear : 1;
gboolean use_alpha : 1;
} GskRendererPrivate;
@@ -83,11 +77,12 @@ enum {
PROP_MINIFICATION_FILTER,
PROP_MAGNIFICATION_FILTER,
PROP_AUTO_CLEAR,
+ PROP_USE_ALPHA,
+ PROP_SCALE_FACTOR,
+ PROP_WINDOW,
PROP_ROOT_NODE,
PROP_DISPLAY,
- PROP_WINDOW,
- PROP_SURFACE,
- PROP_USE_ALPHA,
+ PROP_DRAWING_CONTEXT,
N_PROPS
};
@@ -111,37 +106,14 @@ gsk_renderer_real_unrealize (GskRenderer *self)
}
static void
-gsk_renderer_real_render (GskRenderer *self)
+gsk_renderer_real_render (GskRenderer *self,
+ GskRenderNode *root,
+ GdkDrawingContext *context)
{
GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, render);
}
static void
-gsk_renderer_real_resize_viewport (GskRenderer *self,
- const graphene_rect_t *viewport)
-{
-}
-
-static void
-gsk_renderer_real_update (GskRenderer *self,
- const graphene_matrix_t *mv,
- const graphene_matrix_t *proj)
-{
-}
-
-static void
-gsk_renderer_real_validate_tree (GskRenderer *self,
- GskRenderNode *root)
-{
-}
-
-static void
-gsk_renderer_real_clear_tree (GskRenderer *self,
- GskRenderNode *old_root)
-{
-}
-
-static void
gsk_renderer_dispose (GObject *gobject)
{
GskRenderer *self = GSK_RENDERER (gobject);
@@ -149,11 +121,7 @@ gsk_renderer_dispose (GObject *gobject)
gsk_renderer_unrealize (self);
- g_clear_pointer (&priv->surface, cairo_surface_destroy);
- g_clear_pointer (&priv->draw_context, cairo_destroy);
-
g_clear_object (&priv->window);
- g_clear_object (&priv->root_node);
g_clear_object (&priv->display);
G_OBJECT_CLASS (gsk_renderer_parent_class)->dispose (gobject);
@@ -194,12 +162,12 @@ gsk_renderer_set_property (GObject *gobject,
gsk_renderer_set_auto_clear (self, g_value_get_boolean (value));
break;
- case PROP_ROOT_NODE:
- gsk_renderer_set_root_node (self, g_value_get_object (value));
+ case PROP_USE_ALPHA:
+ gsk_renderer_set_use_alpha (self, g_value_get_boolean (value));
break;
- case PROP_SURFACE:
- gsk_renderer_set_surface (self, g_value_get_boxed (value));
+ case PROP_SCALE_FACTOR:
+ gsk_renderer_set_scale_factor (self, g_value_get_int (value));
break;
case PROP_WINDOW:
@@ -207,12 +175,9 @@ gsk_renderer_set_property (GObject *gobject,
break;
case PROP_DISPLAY:
+ /* Construct-only */
priv->display = g_value_dup_object (value);
break;
-
- case PROP_USE_ALPHA:
- gsk_renderer_set_use_alpha (self, g_value_get_boolean (value));
- break;
}
}
@@ -251,24 +216,28 @@ gsk_renderer_get_property (GObject *gobject,
g_value_set_boolean (value, priv->auto_clear);
break;
- case PROP_ROOT_NODE:
- g_value_set_object (value, priv->root_node);
- break;
-
- case PROP_SURFACE:
- g_value_set_boxed (value, priv->surface);
+ case PROP_USE_ALPHA:
+ g_value_set_boolean (value, priv->use_alpha);
break;
- case PROP_DISPLAY:
- g_value_set_object (value, priv->display);
+ case PROP_SCALE_FACTOR:
+ g_value_set_int (value, priv->scale_factor);
break;
case PROP_WINDOW:
g_value_set_object (value, priv->window);
break;
- case PROP_USE_ALPHA:
- g_value_set_boolean (value, priv->use_alpha);
+ case PROP_ROOT_NODE:
+ g_value_set_object (value, priv->root_node);
+ break;
+
+ case PROP_DRAWING_CONTEXT:
+ g_value_set_object (value, priv->drawing_context);
+ break;
+
+ case PROP_DISPLAY:
+ g_value_set_object (value, priv->display);
break;
}
}
@@ -297,10 +266,6 @@ gsk_renderer_class_init (GskRendererClass *klass)
klass->realize = gsk_renderer_real_realize;
klass->unrealize = gsk_renderer_real_unrealize;
- klass->resize_viewport = gsk_renderer_real_resize_viewport;
- klass->update = gsk_renderer_real_update;
- klass->validate_tree = gsk_renderer_real_validate_tree;
- klass->clear_tree = gsk_renderer_real_clear_tree;
klass->render = gsk_renderer_real_render;
gobject_class->constructed = gsk_renderer_constructed;
@@ -448,27 +413,8 @@ gsk_renderer_class_init (GskRendererClass *klass)
"Root Node",
"The root render node to render",
GSK_TYPE_RENDER_NODE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS |
- G_PARAM_EXPLICIT_NOTIFY);
-
- /**
- * GskRenderer:surface:
- *
- * The target rendering surface.
- *
- * See also: #GskRenderer:window.
- *
- * Since: 3.22
- */
- gsk_renderer_properties[PROP_SURFACE] =
- g_param_spec_boxed ("surface",
- "Surface",
- "The Cairo surface used to render to",
- CAIRO_GOBJECT_TYPE_SURFACE,
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS |
- G_PARAM_EXPLICIT_NOTIFY);
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
/**
* GskRenderer:display:
@@ -486,22 +432,46 @@ gsk_renderer_class_init (GskRendererClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
- /**
- * GskRenderer:window:
- *
- * The #GdkWindow used to create a target surface, if #GskRenderer:surface
- * is not explicitly set.
- *
- * Since: 3.22
- */
gsk_renderer_properties[PROP_WINDOW] =
g_param_spec_object ("window",
"Window",
- "The GdkWindow associated to the renderer",
+ "The window associated to the renderer",
GDK_TYPE_WINDOW,
G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS |
- G_PARAM_EXPLICIT_NOTIFY);
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GskRenderer:scale-factor:
+ *
+ * The scale factor used when rendering.
+ *
+ * Since: 3.22
+ */
+ gsk_renderer_properties[PROP_SCALE_FACTOR] =
+ g_param_spec_int ("scale-factor",
+ "Scale Factor",
+ "The scaling factor of the renderer",
+ 1, G_MAXINT,
+ 1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * GskRenderer:drawing-context:
+ *
+ * The drawing context used when rendering.
+ *
+ * Since: 3.22
+ */
+ gsk_renderer_properties[PROP_DRAWING_CONTEXT] =
+ g_param_spec_object ("drawing-context",
+ "Drawing Context",
+ "The drawing context used by the renderer",
+ GDK_TYPE_DRAWING_CONTEXT,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
/**
* GskRenderer:use-alpha:
@@ -531,6 +501,7 @@ gsk_renderer_init (GskRenderer *self)
graphene_matrix_init_identity (&priv->projection);
priv->auto_clear = TRUE;
+ priv->scale_factor = 1;
priv->min_filter = GSK_SCALING_FILTER_LINEAR;
priv->mag_filter = GSK_SCALING_FILTER_LINEAR;
@@ -565,9 +536,6 @@ gsk_renderer_set_viewport (GskRenderer *renderer,
return;
graphene_rect_init_from_rect (&priv->viewport, viewport);
- priv->needs_viewport_resize = TRUE;
- priv->needs_modelview_update = TRUE;
- priv->needs_projection_update = TRUE;
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_VIEWPORT]);
}
@@ -618,8 +586,6 @@ gsk_renderer_set_modelview (GskRenderer *renderer,
else
graphene_matrix_init_from_matrix (&priv->modelview, modelview);
- priv->needs_modelview_update = TRUE;
-
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_MODELVIEW]);
}
@@ -666,8 +632,6 @@ gsk_renderer_set_projection (GskRenderer *renderer,
else
graphene_matrix_init_from_matrix (&priv->projection, projection);
- priv->needs_projection_update = TRUE;
-
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_PROJECTION]);
}
@@ -692,67 +656,6 @@ gsk_renderer_get_projection (GskRenderer *renderer,
graphene_matrix_init_from_matrix (projection, &priv->projection);
}
-static void
-gsk_renderer_invalidate_tree (GskRenderNode *node,
- gpointer data)
-{
- GskRenderer *self = data;
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
-
- GSK_NOTE (RENDERER, g_print ("Invalidating tree.\n"));
-
- /* Since the scene graph has changed in some way, we need to re-validate it. */
- priv->needs_tree_validation = TRUE;
-}
-
-/**
- * gsk_renderer_set_root_node:
- * @renderer: a #GskRenderer
- * @root: (nullable): a #GskRenderNode
- *
- * Sets the root node of the scene graph to be rendered.
- *
- * The #GskRenderer will acquire a reference on @root.
- *
- * Since: 3.22
- */
-void
-gsk_renderer_set_root_node (GskRenderer *renderer,
- GskRenderNode *root)
-{
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
- GskRenderNode *old_root;
-
- g_return_if_fail (GSK_IS_RENDERER (renderer));
- g_return_if_fail (GSK_IS_RENDER_NODE (root));
-
- old_root = priv->root_node != NULL ? g_object_ref (priv->root_node) : NULL;
-
- if (g_set_object (&priv->root_node, root))
- {
- /* We need to unset the invalidate function on the old instance */
- if (old_root != NULL)
- {
- gsk_render_node_set_invalidate_func (old_root, NULL, NULL, NULL);
- gsk_renderer_clear_tree (renderer, old_root);
- g_object_unref (old_root);
- }
-
- if (priv->root_node != NULL)
- gsk_render_node_set_invalidate_func (priv->root_node,
- gsk_renderer_invalidate_tree,
- renderer,
- NULL);
-
- /* If we don't have a root node, there's really no point in validating a
- * tree that it's not going to be drawn
- */
- priv->needs_tree_validation = priv->root_node != NULL;
-
- g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_ROOT_NODE]);
- }
-}
-
/**
* gsk_renderer_set_scaling_filters:
* @renderer: a #GskRenderer
@@ -819,143 +722,73 @@ gsk_renderer_get_scaling_filters (GskRenderer *renderer,
*mag_filter = priv->mag_filter;
}
-/**
- * gsk_renderer_set_surface:
- * @renderer: a #GskRenderer
- * @surface: (nullable): a Cairo surface
- *
- * Sets the #cairo_surface_t used as the target rendering surface.
- *
- * This function will acquire a reference to @surface.
- *
- * See also: gsk_renderer_set_window()
- *
- * Since: 3.22
- */
void
-gsk_renderer_set_surface (GskRenderer *renderer,
- cairo_surface_t *surface)
+gsk_renderer_set_scale_factor (GskRenderer *renderer,
+ int scale_factor)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
g_return_if_fail (GSK_IS_RENDERER (renderer));
- if (priv->surface == surface)
- return;
-
- g_clear_pointer (&priv->surface, cairo_surface_destroy);
-
- if (surface != NULL)
- priv->surface = cairo_surface_reference (surface);
+ if (priv->scale_factor != scale_factor)
+ {
+ priv->scale_factor = scale_factor;
- g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_SURFACE]);
+ g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_SCALE_FACTOR]);
+ }
}
-/**
- * gsk_renderer_get_surface:
- * @renderer: a #GskRenderer
- *
- * Retrieve the target rendering surface used by @renderer.
- *
- * If you did not use gsk_renderer_set_surface(), a compatible surface
- * will be created by using the #GdkWindow passed to gsk_renderer_set_window().
- *
- * Returns: (transfer none) (nullable): a Cairo surface
- *
- * Since: 3.22
- */
-cairo_surface_t *
-gsk_renderer_get_surface (GskRenderer *renderer)
+int
+gsk_renderer_get_scale_factor (GskRenderer *renderer)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
-
- if (priv->surface != NULL)
- return priv->surface;
+ g_return_val_if_fail (GSK_IS_RENDERER (renderer), 1);
- if (priv->window != NULL)
- {
- int scale = gdk_window_get_scale_factor (priv->window);
- int width = gdk_window_get_width (priv->window);
- int height = gdk_window_get_height (priv->window);
- cairo_content_t content;
-
- if (priv->use_alpha)
- content = CAIRO_CONTENT_COLOR_ALPHA;
- else
- content = CAIRO_CONTENT_COLOR;
-
- GSK_NOTE (RENDERER, g_print ("Creating surface from window [%p] (w:%d, h:%d, s:%d, a:%s)\n",
- priv->window,
- width, height, scale,
- priv->use_alpha ? "y" : "n"));
-
- priv->surface = gdk_window_create_similar_surface (priv->window,
- content,
- width, height);
- }
-
- return priv->surface;
+ return priv->scale_factor;
}
void
-gsk_renderer_set_draw_context (GskRenderer *renderer,
- cairo_t *cr)
+gsk_renderer_set_window (GskRenderer *renderer,
+ GdkWindow *window)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
g_return_if_fail (GSK_IS_RENDERER (renderer));
+ g_return_if_fail (!priv->is_realized);
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
- if (priv->draw_context == cr)
- return;
-
- g_clear_pointer (&priv->draw_context, cairo_destroy);
- priv->draw_context = cr != NULL ? cairo_reference (cr) : NULL;
-}
-
-cairo_t *
-gsk_renderer_get_draw_context (GskRenderer *renderer)
-{
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
-
- g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
-
- if (priv->draw_context != NULL)
- return priv->draw_context;
-
- return cairo_create (gsk_renderer_get_surface (renderer));
+ if (g_set_object (&priv->window, window))
+ g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_WINDOW]);
}
/**
- * gsk_renderer_get_display:
+ * gsk_renderer_get_window:
* @renderer: a #GskRenderer
*
- * Retrieves the #GdkDisplay used when creating the #GskRenderer.
+ * Retrieves the #GdkWindow set using gsk_renderer_set_window().
*
- * Returns: (transfer none): a #GdkDisplay
+ * Returns: (transfer none) (nullable): a #GdkWindow
*
* Since: 3.22
*/
-GdkDisplay *
-gsk_renderer_get_display (GskRenderer *renderer)
+GdkWindow *
+gsk_renderer_get_window (GskRenderer *renderer)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
- return priv->display;
+ return priv->window;
}
-/**
+/*< private >
* gsk_renderer_get_root_node:
* @renderer: a #GskRenderer
*
- * Retrieves the root node of the scene graph.
+ * Retrieves the #GskRenderNode used by @renderer.
*
* Returns: (transfer none) (nullable): a #GskRenderNode
- *
- * Since: 3.22
*/
GskRenderNode *
gsk_renderer_get_root_node (GskRenderer *renderer)
@@ -968,68 +801,61 @@ gsk_renderer_get_root_node (GskRenderer *renderer)
}
/*< private >
- * gsk_renderer_is_realized:
+ * gsk_renderer_get_drawing_context:
* @renderer: a #GskRenderer
*
- * Checks whether the @renderer is realized or not.
+ * Retrieves the #GdkDrawingContext used by @renderer.
*
- * Returns: %TRUE if the #GskRenderer was realized, and %FALSE otherwise
- *
- * Since: 3.22
+ * Returns: (transfer none) (nullable): a #GdkDrawingContext
*/
-gboolean
-gsk_renderer_is_realized (GskRenderer *renderer)
+GdkDrawingContext *
+gsk_renderer_get_drawing_context (GskRenderer *renderer)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GSK_IS_RENDERER (renderer), FALSE);
+ g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
- return priv->is_realized;
+ return priv->drawing_context;
}
/**
- * gsk_renderer_set_window:
+ * gsk_renderer_get_display:
* @renderer: a #GskRenderer
- * @window: (nullable): a #GdkWindow
*
- * Sets the #GdkWindow used to create the target rendering surface.
+ * Retrieves the #GdkDisplay used when creating the #GskRenderer.
*
- * See also: gsk_renderer_set_surface()
+ * Returns: (transfer none): a #GdkDisplay
*
* Since: 3.22
*/
-void
-gsk_renderer_set_window (GskRenderer *renderer,
- GdkWindow *window)
+GdkDisplay *
+gsk_renderer_get_display (GskRenderer *renderer)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
- g_return_if_fail (GSK_IS_RENDERER (renderer));
- g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
- g_return_if_fail (!priv->is_realized);
+ g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
- if (g_set_object (&priv->window, window))
- g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_WINDOW]);
+ return priv->display;
}
-/**
- * gsk_renderer_get_window:
+/*< private >
+ * gsk_renderer_is_realized:
* @renderer: a #GskRenderer
*
- * Retrieves the #GdkWindow set with gsk_renderer_set_window().
+ * Checks whether the @renderer is realized or not.
*
- * Returns: (transfer none) (nullable): a #GdkWindow
+ * Returns: %TRUE if the #GskRenderer was realized, and %FALSE otherwise
*
* Since: 3.22
*/
-GdkWindow *
-gsk_renderer_get_window (GskRenderer *renderer)
+gboolean
+gsk_renderer_is_realized (GskRenderer *renderer)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
- g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
+ g_return_val_if_fail (GSK_IS_RENDERER (renderer), FALSE);
- return priv->window;
+ return priv->is_realized;
}
/**
@@ -1051,12 +877,6 @@ gsk_renderer_realize (GskRenderer *renderer)
if (priv->is_realized)
return TRUE;
- if (priv->window == NULL && priv->surface == NULL)
- {
- g_critical ("No rendering surface has been set.");
- return FALSE;
- }
-
priv->is_realized = GSK_RENDERER_GET_CLASS (renderer)->realize (renderer);
return priv->is_realized;
@@ -1085,156 +905,41 @@ gsk_renderer_unrealize (GskRenderer *renderer)
priv->is_realized = FALSE;
}
-/*< private >
- * gsk_renderer_maybe_resize_viewport:
- * @renderer: a #GskRenderer
- *
- * Optionally resize the viewport of @renderer.
- *
- * This function should be called by gsk_renderer_render().
- *
- * This function may call @GskRendererClass.resize_viewport().
- */
-void
-gsk_renderer_maybe_resize_viewport (GskRenderer *renderer)
-{
- GskRendererClass *renderer_class = GSK_RENDERER_GET_CLASS (renderer);
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
-
- if (priv->needs_viewport_resize)
- {
- renderer_class->resize_viewport (renderer, &priv->viewport);
- priv->needs_viewport_resize = FALSE;
-
- GSK_NOTE (RENDERER, g_print ("Viewport size: %g x %g\n",
- priv->viewport.size.width,
- priv->viewport.size.height));
-
- /* If the target surface has been created from a window, we need
- * to clear it, so that it gets recreated with the right size
- */
- if (priv->window != NULL && priv->surface != NULL)
- g_clear_pointer (&priv->surface, cairo_surface_destroy);
- }
-}
-
-/*< private >
- * gsk_renderer_maybe_update:
- * @renderer: a #GskRenderer
- *
- * Optionally recomputes the modelview-projection matrix used by
- * the @renderer.
- *
- * This function should be called by gsk_renderer_render().
- *
- * This function may call @GskRendererClass.update().
- */
-void
-gsk_renderer_maybe_update (GskRenderer *renderer)
-{
- GskRendererClass *renderer_class = GSK_RENDERER_GET_CLASS (renderer);
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
-
- if (priv->needs_modelview_update || priv->needs_projection_update)
- {
- renderer_class->update (renderer, &priv->modelview, &priv->projection);
- priv->needs_modelview_update = FALSE;
- priv->needs_projection_update = FALSE;
- }
-}
-
-void
-gsk_renderer_clear_tree (GskRenderer *renderer,
- GskRenderNode *old_root)
-{
- GSK_RENDERER_GET_CLASS (renderer)->clear_tree (renderer, old_root);
-}
-
-/*< private >
- * gsk_renderer_maybe_validate_tree:
- * @renderer: a #GskRenderer
- *
- * Optionally validates the #GskRenderNode scene graph, and uses it
- * to generate more efficient intermediate representations depending
- * on the type of @renderer.
- *
- * This function should be called by gsk_renderer_render().
- *
- * This function may call @GskRendererClas.validate_tree().
- */
-void
-gsk_renderer_maybe_validate_tree (GskRenderer *renderer)
-{
- GskRendererClass *renderer_class = GSK_RENDERER_GET_CLASS (renderer);
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
-
- if (priv->root_node == NULL)
- return;
-
- /* Ensure that the render nodes are valid; this will change the
- * needs_tree_validation flag on the renderer, if needed
- */
- gsk_render_node_validate (priv->root_node);
-
- if (priv->needs_tree_validation)
- {
- /* Ensure that the Renderer can update itself */
- renderer_class->validate_tree (renderer, priv->root_node);
- priv->needs_tree_validation = FALSE;
- }
-}
-
-/*< private >
- * gsk_renderer_maybe_clear:
- * @renderer: a #GskRenderer
- *
- * Optionally calls @GskRendererClass.clear(), depending on the value
- * of #GskRenderer:auto-clear.
- *
- * This function should be called by gsk_renderer_render().
- */
-void
-gsk_renderer_maybe_clear (GskRenderer *renderer)
-{
- GskRendererClass *renderer_class = GSK_RENDERER_GET_CLASS (renderer);
- GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
-
- if (priv->auto_clear)
- renderer_class->clear (renderer);
-}
-
/**
* gsk_renderer_render:
- * @renderer: a#GskRenderer
+ * @renderer: a #GskRenderer
+ * @root: a #GskRenderNode
+ * @context: a #GdkDrawingContext
+ *
+ * Renders the scene graph, described by a tree of #GskRenderNode instances,
+ * using the given #GdkDrawingContext.
*
- * Renders the scene graph associated to @renderer, using the
- * given target surface.
+ * The @renderer will acquire a reference on the #GskRenderNode tree while
+ * the rendering is in progress, and will make the tree immutable.
*
* Since: 3.22
*/
void
-gsk_renderer_render (GskRenderer *renderer)
+gsk_renderer_render (GskRenderer *renderer,
+ GskRenderNode *root,
+ GdkDrawingContext *context)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
g_return_if_fail (GSK_IS_RENDERER (renderer));
g_return_if_fail (priv->is_realized);
- g_return_if_fail (priv->root_node != NULL);
-
- /* We need to update the viewport and the modelview, to allow renderers
- * to update their clip region and/or frustum; this allows them to cull
- * render nodes in the tree validation phase
- */
- gsk_renderer_maybe_resize_viewport (renderer);
+ g_return_if_fail (GSK_IS_RENDER_NODE (root));
+ g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
- gsk_renderer_maybe_update (renderer);
+ g_set_object (&priv->root_node, root);
+ g_set_object (&priv->drawing_context, context);
- gsk_renderer_maybe_validate_tree (renderer);
+ gsk_render_node_make_immutable (root);
- /* Clear the output surface */
- gsk_renderer_maybe_clear (renderer);
+ GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, context);
- GSK_RENDERER_GET_CLASS (renderer)->render (renderer);
+ g_clear_object (&priv->root_node);
+ g_clear_object (&priv->drawing_context);
}
/**
@@ -1345,7 +1050,7 @@ gsk_renderer_get_use_alpha (GskRenderer *renderer)
*
* Creates an appropriate #GskRenderer instance for the given @display.
*
- * Returns: (transfer full): a #GskRenderer
+ * Returns: (transfer full) (nullable): a #GskRenderer
*
* Since: 3.22
*/
@@ -1364,10 +1069,7 @@ gsk_renderer_get_for_display (GdkDisplay *display)
}
if (use_software[0] != '0')
- {
- renderer_type = GSK_TYPE_CAIRO_RENDERER;
- goto out;
- }
+ return NULL;
#ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_DISPLAY (display))
@@ -1377,9 +1079,9 @@ gsk_renderer_get_for_display (GdkDisplay *display)
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY (display))
renderer_type = GSK_TYPE_GL_RENDERER;
- else
#endif
- renderer_type = GSK_TYPE_CAIRO_RENDERER;
+ else
+ return NULL;
GSK_NOTE (RENDERER, g_print ("Creating renderer of type '%s' for display '%s'\n",
g_type_name (renderer_type),
@@ -1387,6 +1089,5 @@ gsk_renderer_get_for_display (GdkDisplay *display)
g_assert (renderer_type != G_TYPE_INVALID);
-out:
return g_object_new (renderer_type, "display", display, NULL);
}
diff --git a/gsk/gskrenderer.h b/gsk/gskrenderer.h
index a18ab9b19a..ec1d3aacc2 100644
--- a/gsk/gskrenderer.h
+++ b/gsk/gskrenderer.h
@@ -69,44 +69,37 @@ void gsk_renderer_get_scaling_filters (GskRenderer
GskScalingFilter *min_filter,
GskScalingFilter *mag_filter);
GDK_AVAILABLE_IN_3_22
+void gsk_renderer_set_scale_factor (GskRenderer *renderer,
+ int scale_factor);
+GDK_AVAILABLE_IN_3_22
+int gsk_renderer_get_scale_factor (GskRenderer *renderer);
+GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_auto_clear (GskRenderer *renderer,
gboolean clear);
GDK_AVAILABLE_IN_3_22
gboolean gsk_renderer_get_auto_clear (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
-void gsk_renderer_set_root_node (GskRenderer *renderer,
- GskRenderNode *root);
-GDK_AVAILABLE_IN_3_22
-GskRenderNode * gsk_renderer_get_root_node (GskRenderer *renderer);
-GDK_AVAILABLE_IN_3_22
-void gsk_renderer_set_surface (GskRenderer *renderer,
- cairo_surface_t *surface);
+void gsk_renderer_set_use_alpha (GskRenderer *renderer,
+ gboolean use_alpha);
GDK_AVAILABLE_IN_3_22
-cairo_surface_t * gsk_renderer_get_surface (GskRenderer *renderer);
+gboolean gsk_renderer_get_use_alpha (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_window (GskRenderer *renderer,
GdkWindow *window);
GDK_AVAILABLE_IN_3_22
GdkWindow * gsk_renderer_get_window (GskRenderer *renderer);
-GDK_AVAILABLE_IN_3_22
-void gsk_renderer_set_draw_context (GskRenderer *renderer,
- cairo_t *cr);
-GDK_AVAILABLE_IN_3_22
-cairo_t * gsk_renderer_get_draw_context (GskRenderer *renderer);
+
GDK_AVAILABLE_IN_3_22
GdkDisplay * gsk_renderer_get_display (GskRenderer *renderer);
-GDK_AVAILABLE_IN_3_22
-void gsk_renderer_set_use_alpha (GskRenderer *renderer,
- gboolean use_alpha);
-GDK_AVAILABLE_IN_3_22
-gboolean gsk_renderer_get_use_alpha (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
gboolean gsk_renderer_realize (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_unrealize (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
-void gsk_renderer_render (GskRenderer *renderer);
+void gsk_renderer_render (GskRenderer *renderer,
+ GskRenderNode *root,
+ GdkDrawingContext *context);
G_END_DECLS
diff --git a/gsk/gskrendererprivate.h b/gsk/gskrendererprivate.h
index 2237c86ed1..81037193d4 100644
--- a/gsk/gskrendererprivate.h
+++ b/gsk/gskrendererprivate.h
@@ -39,28 +39,15 @@ struct _GskRendererClass
gboolean (* realize) (GskRenderer *renderer);
void (* unrealize) (GskRenderer *renderer);
- void (* resize_viewport) (GskRenderer *renderer,
- const graphene_rect_t *viewport);
- void (* update) (GskRenderer *renderer,
- const graphene_matrix_t *modelview,
- const graphene_matrix_t *projection);
- void (* validate_tree) (GskRenderer *renderer,
- GskRenderNode *root);
- void (* clear_tree) (GskRenderer *renderer,
- GskRenderNode *old_root);
- void (* clear) (GskRenderer *renderer);
- void (* render) (GskRenderer *renderer);
+ void (* render) (GskRenderer *renderer,
+ GskRenderNode *root,
+ GdkDrawingContext *context);
};
gboolean gsk_renderer_is_realized (GskRenderer *renderer);
-void gsk_renderer_clear_tree (GskRenderer *renderer,
- GskRenderNode *old_root);
-
-void gsk_renderer_maybe_resize_viewport (GskRenderer *renderer);
-void gsk_renderer_maybe_update (GskRenderer *renderer);
-void gsk_renderer_maybe_validate_tree (GskRenderer *renderer);
-void gsk_renderer_maybe_clear (GskRenderer *renderer);
+GskRenderNode * gsk_renderer_get_root_node (GskRenderer *renderer);
+GdkDrawingContext * gsk_renderer_get_drawing_context (GskRenderer *renderer);
G_END_DECLS
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index 092b96a2e3..95feb24147 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -41,8 +41,6 @@ gsk_render_node_dispose (GObject *gobject)
GskRenderNode *self = GSK_RENDER_NODE (gobject);
GskRenderNodeIter iter;
- gsk_render_node_set_invalidate_func (self, NULL, NULL, NULL);
-
gsk_render_node_iter_init (&iter, self);
while (gsk_render_node_iter_next (&iter, NULL))
gsk_render_node_iter_remove (&iter);
@@ -51,18 +49,11 @@ gsk_render_node_dispose (GObject *gobject)
}
static void
-gsk_render_node_real_resize (GskRenderNode *node)
-{
-}
-
-static void
gsk_render_node_class_init (GskRenderNodeClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gsk_render_node_dispose;
-
- klass->resize = gsk_render_node_real_resize;
}
static void
@@ -74,6 +65,8 @@ gsk_render_node_init (GskRenderNode *self)
graphene_matrix_init_identity (&self->child_transform);
self->opacity = 1.0;
+
+ self->is_mutable = TRUE;
}
/**
@@ -204,6 +197,13 @@ gsk_render_node_insert_child_internal (GskRenderNode *node,
return;
}
+ if (!node->is_mutable)
+ {
+ g_critical ("The render node of type '%s' is immutable.",
+ G_OBJECT_TYPE_NAME (node));
+ return;
+ }
+
insert_func (node, child, insert_func_data);
g_object_ref (child);
@@ -216,21 +216,6 @@ gsk_render_node_insert_child_internal (GskRenderNode *node,
node->age += 1;
node->needs_world_matrix_update = TRUE;
- /* Transfer invalidated children to the current top-level */
- if (child->invalidated_descendants != NULL)
- {
- if (node->parent == NULL)
- node->invalidated_descendants = child->invalidated_descendants;
- else
- {
- GskRenderNode *tmp = gsk_render_node_get_toplevel (node);
-
- tmp->invalidated_descendants = child->invalidated_descendants;
- }
-
- child->invalidated_descendants = NULL;
- }
-
if (child->prev_sibling == NULL)
node->first_child = child;
if (child->next_sibling == NULL)
@@ -297,6 +282,62 @@ insert_child_at_pos (GskRenderNode *node,
}
/**
+ * gsk_render_node_append_child:
+ * @node: a #GskRenderNode
+ * @child: a #GskRenderNode
+ *
+ * Appends @child to the list of children of @node.
+ *
+ * This function acquires a reference on @child.
+ *
+ * Returns: (transfer none): the #GskRenderNode
+ *
+ * Since: 3.22
+ */
+GskRenderNode *
+gsk_render_node_append_child (GskRenderNode *node,
+ GskRenderNode *child)
+{
+ g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
+ g_return_val_if_fail (GSK_IS_RENDER_NODE (child), node);
+ g_return_val_if_fail (node->is_mutable, node);
+
+ gsk_render_node_insert_child_internal (node, child,
+ insert_child_at_pos,
+ GINT_TO_POINTER (node->n_children));
+
+ return node;
+}
+
+/**
+ * gsk_render_node_prepend_child:
+ * @node: a #GskRenderNode
+ * @child: a #GskRenderNode
+ *
+ * Prepends @child to the list of children of @node.
+ *
+ * This function acquires a reference on @child.
+ *
+ * Returns: (transfer none): the #GskRenderNode
+ *
+ * Since: 3.22
+ */
+GskRenderNode *
+gsk_render_node_prepend_child (GskRenderNode *node,
+ GskRenderNode *child)
+{
+ g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
+ g_return_val_if_fail (GSK_IS_RENDER_NODE (child), node);
+ g_return_val_if_fail (node->is_mutable, node);
+
+ gsk_render_node_insert_child_internal (node, child,
+ insert_child_at_pos,
+ GINT_TO_POINTER (0));
+
+ return node;
+}
+
+/**
* gsk_render_node_insert_child_at_pos:
* @node: a #GskRenderNode
* @child: a #GskRenderNode
@@ -322,6 +363,7 @@ gsk_render_node_insert_child_at_pos (GskRenderNode *node,
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), node);
+ g_return_val_if_fail (node->is_mutable, node);
gsk_render_node_insert_child_internal (node, child,
insert_child_at_pos,
@@ -382,6 +424,7 @@ gsk_render_node_insert_child_before (GskRenderNode *node,
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), node);
g_return_val_if_fail (sibling == NULL || GSK_IS_RENDER_NODE (sibling), node);
+ g_return_val_if_fail (node->is_mutable, node);
gsk_render_node_insert_child_internal (node, child, insert_child_before, sibling);
@@ -440,6 +483,7 @@ gsk_render_node_insert_child_after (GskRenderNode *node,
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), node);
g_return_val_if_fail (sibling == NULL || GSK_IS_RENDER_NODE (sibling), node);
+ g_return_val_if_fail (node->is_mutable, node);
if (sibling != NULL)
g_return_val_if_fail (sibling->parent == node, node);
@@ -500,6 +544,8 @@ gsk_render_node_replace_child (GskRenderNode *node,
g_return_val_if_fail (new_child->parent == NULL, node);
g_return_val_if_fail (old_child->parent == node, node);
+ g_return_val_if_fail (node->is_mutable, node);
+
clos.prev_sibling = old_child->prev_sibling;
clos.next_sibling = old_child->next_sibling;
gsk_render_node_remove_child (node, old_child);
@@ -529,6 +575,7 @@ gsk_render_node_remove_child (GskRenderNode *node,
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
g_return_val_if_fail (GSK_IS_RENDER_NODE (child), node);
+ g_return_val_if_fail (node->is_mutable, node);
if (child->parent != node)
{
@@ -582,6 +629,7 @@ gsk_render_node_remove_all_children (GskRenderNode *node)
GskRenderNodeIter iter;
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
+ g_return_val_if_fail (node->is_mutable, node);
if (node->n_children == 0)
return node;
@@ -631,13 +679,12 @@ gsk_render_node_set_bounds (GskRenderNode *node,
const graphene_rect_t *bounds)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
+ g_return_if_fail (node->is_mutable);
if (bounds == NULL)
graphene_rect_init_from_rect (&node->bounds, graphene_rect_zero ());
else
graphene_rect_init_from_rect (&node->bounds, bounds);
-
- gsk_render_node_queue_invalidate (node, GSK_RENDER_NODE_CHANGES_UPDATE_BOUNDS);
}
/**
@@ -673,6 +720,7 @@ gsk_render_node_set_transform (GskRenderNode *node,
const graphene_matrix_t *transform)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
+ g_return_if_fail (node->is_mutable);
if (transform == NULL)
graphene_matrix_init_identity (&node->transform);
@@ -680,7 +728,6 @@ gsk_render_node_set_transform (GskRenderNode *node,
graphene_matrix_init_from_matrix (&node->transform, transform);
node->transform_set = !graphene_matrix_is_identity (&node->transform);
- gsk_render_node_queue_invalidate (node, GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM);
}
/**
@@ -697,10 +744,8 @@ void
gsk_render_node_set_child_transform (GskRenderNode *node,
const graphene_matrix_t *transform)
{
- GskRenderNodeIter iter;
- GskRenderNode *child;
-
g_return_if_fail (GSK_IS_RENDER_NODE (node));
+ g_return_if_fail (node->is_mutable);
if (transform == NULL)
graphene_matrix_init_identity (&node->child_transform);
@@ -708,11 +753,6 @@ gsk_render_node_set_child_transform (GskRenderNode *node,
graphene_matrix_init_from_matrix (&node->child_transform, transform);
node->child_transform_set = !graphene_matrix_is_identity (&node->child_transform);
-
- /* We need to invalidate the world matrix for our children */
- gsk_render_node_iter_init (&iter, node);
- while (gsk_render_node_iter_next (&iter, &child))
- gsk_render_node_queue_invalidate (child, GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM);
}
/**
@@ -730,10 +770,9 @@ gsk_render_node_set_opacity (GskRenderNode *node,
double opacity)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
+ g_return_if_fail (node->is_mutable);
node->opacity = CLAMP (opacity, 0.0, 1.0);
-
- gsk_render_node_queue_invalidate (node, GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY);
}
/**
@@ -770,10 +809,9 @@ gsk_render_node_set_hidden (GskRenderNode *node,
gboolean hidden)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
+ g_return_if_fail (node->is_mutable);
node->hidden = !!hidden;
-
- gsk_render_node_queue_invalidate (node, GSK_RENDER_NODE_CHANGES_UPDATE_VISIBILITY);
}
/**
@@ -813,10 +851,9 @@ gsk_render_node_set_opaque (GskRenderNode *node,
gboolean opaque)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
+ g_return_if_fail (node->is_mutable);
node->opaque = !!opaque;
-
- gsk_render_node_queue_invalidate (node, GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY);
}
/**
@@ -865,31 +902,6 @@ gsk_render_node_contains (GskRenderNode *node,
return FALSE;
}
-/**
- * gsk_render_node_set_surface:
- * @node: a #GskRenderNode
- * @surface: (nullable): a Cairo surface
- *
- * Sets the contents of the #GskRenderNode.
- *
- * The @node will acquire a reference on the given @surface.
- *
- * Since: 3.22
- */
-void
-gsk_render_node_set_surface (GskRenderNode *node,
- cairo_surface_t *surface)
-{
- g_return_if_fail (GSK_IS_RENDER_NODE (node));
-
- g_clear_pointer (&node->surface, cairo_surface_destroy);
-
- if (surface != NULL)
- node->surface = cairo_surface_reference (surface);
-
- gsk_render_node_queue_invalidate (node, GSK_RENDER_NODE_CHANGES_UPDATE_SURFACE);
-}
-
/*< private >
* gsk_render_node_get_toplevel:
* @node: a #GskRenderNode
@@ -1014,168 +1026,6 @@ gsk_render_node_get_world_matrix (GskRenderNode *node,
*mv = node->world_matrix;
}
-void
-gsk_render_node_set_invalidate_func (GskRenderNode *node,
- GskRenderNodeInvalidateFunc invalidate_func,
- gpointer func_data,
- GDestroyNotify destroy_func_data)
-{
- if (node->parent != NULL)
- {
- g_critical ("Render node of type '%s' is not a root node. Only root "
- "nodes can have an invalidation function.",
- G_OBJECT_TYPE_NAME (node));
- return;
- }
-
- if (node->invalidate_func != NULL)
- {
- if (node->destroy_func_data != NULL)
- node->destroy_func_data (node->func_data);
- }
-
- node->invalidate_func = invalidate_func;
- node->func_data = func_data;
- node->destroy_func_data = destroy_func_data;
-}
-
-GskRenderNodeChanges
-gsk_render_node_get_current_state (GskRenderNode *node)
-{
- GskRenderNodeChanges res = 0;
-
- if (node->needs_resize)
- res |= GSK_RENDER_NODE_CHANGES_UPDATE_BOUNDS;
- if (node->needs_world_matrix_update)
- res |= GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM;
- if (node->needs_content_update)
- res |= GSK_RENDER_NODE_CHANGES_UPDATE_SURFACE;
- if (node->needs_opacity_update)
- res |= GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY;
- if (node->needs_visibility_update)
- res |= GSK_RENDER_NODE_CHANGES_UPDATE_VISIBILITY;
-
- return res;
-}
-
-GskRenderNodeChanges
-gsk_render_node_get_last_state (GskRenderNode *node)
-{
- return node->last_state_change;
-}
-
-void
-gsk_render_node_queue_invalidate (GskRenderNode *node,
- GskRenderNodeChanges changes)
-{
- GskRenderNodeChanges cur_invalidated_bits = 0;
- GskRenderNode *root;
- int i;
-
- cur_invalidated_bits = gsk_render_node_get_current_state (node);
- if ((cur_invalidated_bits & changes) != 0)
- return;
-
- node->needs_resize = (changes & GSK_RENDER_NODE_CHANGES_UPDATE_BOUNDS) != 0;
- node->needs_world_matrix_update = (changes & GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM) != 0;
- node->needs_content_update = (changes & GSK_RENDER_NODE_CHANGES_UPDATE_SURFACE) != 0;
- node->needs_opacity_update = (changes & GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY) != 0;
- node->needs_visibility_update = (changes & GSK_RENDER_NODE_CHANGES_UPDATE_VISIBILITY) != 0;
-
- if (node->parent == NULL)
- {
- GSK_NOTE (RENDER_NODE, g_print ("Invalid node [%p] is top-level\n", node));
- return;
- }
-
- root = gsk_render_node_get_toplevel (node);
-
- if (root->invalidated_descendants == NULL)
- root->invalidated_descendants = g_ptr_array_new ();
-
- for (i = 0; i < root->invalidated_descendants->len; i++)
- {
- if (node == g_ptr_array_index (root->invalidated_descendants, i))
- {
- GSK_NOTE (RENDER_NODE, g_print ("Node [%p] already invalidated; skipping...\n", node));
- return;
- }
- }
-
- GSK_NOTE (RENDER_NODE, g_print ("Adding node [%p] to list of invalid descendants of [%p]\n", node, root));
- g_ptr_array_add (root->invalidated_descendants, node);
-}
-
-void
-gsk_render_node_validate (GskRenderNode *node)
-{
- GPtrArray *invalidated_descendants;
- gboolean call_invalidate_func;
- int i;
-
- node->last_state_change = gsk_render_node_get_current_state (node);
-
- /* We call the invalidation function if our state changed, or if
- * the descendants state has changed
- */
- call_invalidate_func = node->last_state_change != 0 ||
- node->invalidated_descendants != NULL;
-
- gsk_render_node_maybe_resize (node);
- gsk_render_node_update_world_matrix (node, FALSE);
- node->needs_content_update = FALSE;
- node->needs_visibility_update = FALSE;
- node->needs_opacity_update = FALSE;
-
- /* Steal the array of invalidated descendants, so that changes caused by
- * the validation will not cause recursions
- */
- invalidated_descendants = node->invalidated_descendants;
- node->invalidated_descendants = NULL;
-
- if (invalidated_descendants != NULL)
- {
- for (i = 0; i < invalidated_descendants->len; i++)
- {
- GskRenderNode *child = g_ptr_array_index (invalidated_descendants, i);
-
- child->last_state_change = 0;
-
- GSK_NOTE (RENDER_NODE, g_print ("Validating descendant node [%p] (resize:%s, transform:%s)\n",
- child,
- child->needs_resize ? "yes" : "no",
- child->needs_world_matrix_update ? "yes" : "no"));
-
- child->last_state_change = gsk_render_node_get_current_state (child);
-
- gsk_render_node_maybe_resize (child);
- gsk_render_node_update_world_matrix (child, FALSE);
-
- child->needs_content_update = FALSE;
- child->needs_visibility_update = FALSE;
- child->needs_opacity_update = FALSE;
- }
- }
-
- g_clear_pointer (&invalidated_descendants, g_ptr_array_unref);
-
- if (call_invalidate_func && node->invalidate_func != NULL)
- node->invalidate_func (node, node->func_data);
-}
-
-void
-gsk_render_node_maybe_resize (GskRenderNode *node)
-{
- g_return_if_fail (GSK_IS_RENDER_NODE (node));
-
- if (!node->needs_resize)
- return;
-
- GSK_RENDER_NODE_GET_CLASS (node)->resize (node);
-
- node->needs_resize = FALSE;
-}
-
/**
* gsk_render_node_set_name:
* @node: a #GskRenderNode
@@ -1197,23 +1047,12 @@ gsk_render_node_set_name (GskRenderNode *node,
node->name = g_strdup (name);
}
-static cairo_user_data_key_t render_node_context_key;
-
-static void
-surface_invalidate (void *data)
-{
- GskRenderNode *node = data;
-
- gsk_render_node_queue_invalidate (node, GSK_RENDER_NODE_CHANGES_UPDATE_SURFACE);
-}
-
/**
* gsk_render_node_get_draw_context:
* @node: a #GskRenderNode
*
* Creates a Cairo context for drawing using the surface associated
- * to the render node. If no surface has been attached to the render
- * node, a new surface will be created as a side effect.
+ * to the render node.
*
* Returns: (transfer full): a Cairo context used for drawing; use
* cairo_destroy() when done drawing
@@ -1226,6 +1065,7 @@ gsk_render_node_get_draw_context (GskRenderNode *node)
cairo_t *res;
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
+ g_return_val_if_fail (node->is_mutable, NULL);
if (node->surface == NULL)
node->surface = cairo_image_surface_create (node->opaque ? CAIRO_FORMAT_RGB24
@@ -1240,7 +1080,21 @@ gsk_render_node_get_draw_context (GskRenderNode *node)
node->bounds.size.width, node->bounds.size.height);
cairo_clip (res);
- cairo_set_user_data (res, &render_node_context_key, node, surface_invalidate);
-
return res;
}
+
+void
+gsk_render_node_make_immutable (GskRenderNode *node)
+{
+ GskRenderNodeIter iter;
+ GskRenderNode *child;
+
+ if (!node->is_mutable)
+ return;
+
+ node->is_mutable = FALSE;
+
+ gsk_render_node_iter_init (&iter, node);
+ while (gsk_render_node_iter_next (&iter, &child))
+ gsk_render_node_make_immutable (child);
+}
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index f729c274f0..18e56f728b 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -53,6 +53,12 @@ GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_get_previous_sibling (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
+GskRenderNode * gsk_render_node_append_child (GskRenderNode *node,
+ GskRenderNode *child);
+GDK_AVAILABLE_IN_3_22
+GskRenderNode * gsk_render_node_prepend_child (GskRenderNode *node,
+ GskRenderNode *child);
+GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_insert_child_at_pos (GskRenderNode *node,
GskRenderNode *child,
int index_);
@@ -103,9 +109,6 @@ void gsk_render_node_set_opaque (GskRenderNode *
GDK_AVAILABLE_IN_3_22
gboolean gsk_render_node_is_opaque (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
-void gsk_render_node_set_surface (GskRenderNode *node,
- cairo_surface_t *surface);
-GDK_AVAILABLE_IN_3_22
cairo_t * gsk_render_node_get_draw_context (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 72373d8e68..9e9188fe8b 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -10,18 +10,6 @@ G_BEGIN_DECLS
#define GSK_IS_RENDER_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_RENDER_NODE))
#define GSK_RENDER_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_RENDER_NODE, GskRenderNodeClass))
-typedef enum {
- GSK_RENDER_NODE_CHANGES_UPDATE_BOUNDS = 1 << 0,
- GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM = 1 << 1,
- GSK_RENDER_NODE_CHANGES_UPDATE_SURFACE = 1 << 2,
- GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY = 1 << 3,
- GSK_RENDER_NODE_CHANGES_UPDATE_VISIBILITY = 1 << 4,
- GSK_RENDER_NODE_CHANEGS_UPDATE_HIERARCHY = 1 << 5
-} GskRenderNodeChanges;
-
-typedef void (* GskRenderNodeInvalidateFunc) (GskRenderNode *node,
- gpointer data);
-
struct _GskRenderNode
{
GObject parent_instance;
@@ -59,35 +47,22 @@ struct _GskRenderNode
/* Transformations applied to the children of the node */
graphene_matrix_t child_transform;
- /* Invalidation function for root node */
- GskRenderNodeInvalidateFunc invalidate_func;
- gpointer func_data;
- GDestroyNotify destroy_func_data;
-
- /* Descendants that need to be validated; only for root node */
- GPtrArray *invalidated_descendants;
-
- GskRenderNodeChanges last_state_change;
-
/* Bit fields; leave at the end */
+ gboolean is_mutable : 1;
gboolean hidden : 1;
gboolean opaque : 1;
gboolean transform_set : 1;
gboolean child_transform_set : 1;
- gboolean needs_resize : 1;
gboolean needs_world_matrix_update : 1;
- gboolean needs_content_update : 1;
- gboolean needs_opacity_update : 1;
- gboolean needs_visibility_update : 1;
};
struct _GskRenderNodeClass
{
GObjectClass parent_class;
-
- void (* resize) (GskRenderNode *node);
};
+void gsk_render_node_make_immutable (GskRenderNode *node);
+
void gsk_render_node_get_bounds (GskRenderNode *node,
graphene_rect_t *frame);
void gsk_render_node_get_transform (GskRenderNode *node,
@@ -104,21 +79,6 @@ void gsk_render_node_update_world_matrix (GskRenderNode *node,
void gsk_render_node_get_world_matrix (GskRenderNode *node,
graphene_matrix_t *mv);
-void gsk_render_node_queue_invalidate (GskRenderNode *node,
- GskRenderNodeChanges changes);
-
-void gsk_render_node_set_invalidate_func (GskRenderNode *root,
- GskRenderNodeInvalidateFunc validate_func,
- gpointer data,
- GDestroyNotify notify);
-
-void gsk_render_node_validate (GskRenderNode *node);
-
-void gsk_render_node_maybe_resize (GskRenderNode *node);
-
-GskRenderNodeChanges gsk_render_node_get_current_state (GskRenderNode *node);
-GskRenderNodeChanges gsk_render_node_get_last_state (GskRenderNode *node);
-
G_END_DECLS
#endif /* __GSK_RENDER_NODE_PRIVATE_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d5a85d1d34..dee070e45f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -175,7 +175,6 @@ noinst_PROGRAMS = $(TEST_PROGS) \
gdkgears \
listmodel \
testpopup \
- testgskrenderer \
$(NULL)
if USE_X11
@@ -304,7 +303,6 @@ testtitlebar_DEPENDENCIES = $(TEST_DEPS)
testwindowsize_DEPENDENCIES = $(TEST_DEPS)
listmodel_DEPENDENCIES = $(TEST_DEPS)
foreigndrawing_DEPENDENCIES = $(TEST_DEPS)
-testgskrenderer_DEPENDENCIES = $(TEST_DEPS)
animated_resizing_SOURCES = \
animated-resizing.c \
@@ -545,8 +543,6 @@ listmodel_SOURCES = listmodel.c
foreigndrawing_SOURCES = foreigndrawing.c
-testgskrenderer_SOURCES = testgskrenderer.c
-
EXTRA_DIST += \
gradient1.png \
testgtk.1 \
diff --git a/tests/testgskrenderer.c b/tests/testgskrenderer.c
deleted file mode 100644
index a7a9eeb051..0000000000
--- a/tests/testgskrenderer.c
+++ /dev/null
@@ -1,229 +0,0 @@
-#include "config.h"
-
-#include <graphene.h>
-#include <cairo.h>
-#include <gsk/gsk.h>
-#include <gtk/gtk.h>
-
-#define BOX_SIZE 50.f
-#define PADDING 10.f
-#define ROOT_SIZE BOX_SIZE * 2 + PADDING * 2
-
-static void
-create_color_surface (cairo_t *cr, GdkRGBA *color, int w, int h)
-{
- cairo_set_source_rgba (cr, color->red, color->green, color->blue, color->alpha);
- cairo_rectangle (cr, 0, 0, w, h);
- cairo_fill (cr);
-}
-
-static GskRenderer *
-get_renderer (GtkWidget *widget)
-{
- GskRenderer *res;
-
- res = g_object_get_data (G_OBJECT (widget), "-gsk-renderer");
- if (res == NULL)
- {
- res = gsk_renderer_get_for_display (gtk_widget_get_display (widget));
-
- g_object_set_data_full (G_OBJECT (widget), "-gsk-renderer",
- res,
- (GDestroyNotify) g_object_unref);
- }
-
- return res;
-}
-
-static void
-create_scene (GskRenderer *renderer)
-{
- GskRenderNode *root, *node;
- graphene_matrix_t ctm;
- cairo_t *cr;
-
- root = gsk_render_node_new ();
- gsk_render_node_set_name (root, "Root node");
- gsk_render_node_set_bounds (root, &(graphene_rect_t) {
- .origin.x = 0.f,
- .origin.y = 0.f,
- .size.width = ROOT_SIZE,
- .size.height = ROOT_SIZE
- });
- cr = gsk_render_node_get_draw_context (root);
- create_color_surface (cr, &(GdkRGBA) { .red = 1, .green = 0, .blue = 0, .alpha = 1 }, ROOT_SIZE, ROOT_SIZE);
- cairo_destroy (cr);
- gsk_renderer_set_root_node (renderer, root);
- g_object_set_data (G_OBJECT (renderer), "-gsk-renderer-root-node", root);
-
- g_object_unref (root);
-
- node = gsk_render_node_new ();
- gsk_render_node_set_name (node, "Green node");
- gsk_render_node_set_bounds (node, &(graphene_rect_t) {
- .origin.x = 0.f,
- .origin.y = 0.f,
- .size.width = BOX_SIZE,
- .size.height = BOX_SIZE
- });
- cr = gsk_render_node_get_draw_context (node);
- create_color_surface (cr, &(GdkRGBA) { .red = 0, .green = 1, .blue = 0, .alpha = 1 }, BOX_SIZE, BOX_SIZE);
- cairo_destroy (cr);
- graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) { .x = -0.5, .y = -0.5, .z = 0.f });
- gsk_render_node_set_transform (node, &ctm);
- gsk_render_node_insert_child_at_pos (root, node, 0);
- g_object_unref (node);
-
- node = gsk_render_node_new ();
- gsk_render_node_set_name (node, "Blue node");
- gsk_render_node_set_bounds (node, &(graphene_rect_t) {
- .origin.x = 0.f,
- .origin.y = 0.f,
- .size.width = BOX_SIZE,
- .size.height = BOX_SIZE
- });
- cr = gsk_render_node_get_draw_context (node);
- create_color_surface (cr, &(GdkRGBA) { .red = 0, .green = 0, .blue = 1, .alpha = 1 }, BOX_SIZE, BOX_SIZE);
- cairo_destroy (cr);
- graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) { .x = 0.5, .y = 0.5, .z = 0.f });
- gsk_render_node_set_transform (node, &ctm);
- gsk_render_node_insert_child_at_pos (root, node, 1);
- g_object_unref (node);
-}
-
-static void
-realize (GtkWidget *widget)
-{
- GskRenderer *renderer = get_renderer (widget);
-
- gsk_renderer_set_window (renderer, gtk_widget_get_window (widget));
- gsk_renderer_set_use_alpha (renderer, TRUE);
- gsk_renderer_realize (renderer);
-
- create_scene (renderer);
-}
-
-static void
-unrealize (GtkWidget *widget)
-{
- g_object_set_data (G_OBJECT (widget), "-gsk-renderer", NULL);
-}
-
-static void
-size_allocate (GtkWidget *widget, GtkAllocation *allocation)
-{
- GskRenderer *renderer = get_renderer (widget);
- GskRenderNode *root;
- graphene_matrix_t ctm;
-
- gsk_renderer_set_viewport (renderer, &(graphene_rect_t) {
- .origin.x = 0,
- .origin.y = 0,
- .size.width = allocation->width,
- .size.height = allocation->height
- });
-
- graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) {
- allocation->x,
- allocation->y,
- 0.f
- });
- gsk_renderer_set_modelview (renderer, &ctm);
-
- root = g_object_get_data (G_OBJECT (renderer), "-gsk-renderer-root-node");
- if (root == NULL)
- {
- create_scene (renderer);
- root = g_object_get_data (G_OBJECT (renderer), "-gsk-renderer-root-node");
- }
-
- graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) {
- .x = 0,
- .y = 0,
- .z = 0
- });
- gsk_render_node_set_transform (root, &ctm);
-}
-
-static gboolean
-draw (GtkWidget *widget, cairo_t *cr)
-{
- GskRenderer *renderer = get_renderer (widget);
-
- gsk_renderer_set_draw_context (renderer, cr);
- gsk_renderer_render (renderer);
-
- return TRUE;
-}
-
-static gboolean
-fade_out (GtkWidget *widget,
- GdkFrameClock *frame_clock,
- gpointer data)
-{
- static gint64 first_frame_time;
- static gboolean flip = FALSE;
- gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
-
- if (first_frame_time == 0)
- {
- first_frame_time = now;
-
- return G_SOURCE_CONTINUE;
- }
-
- double start = first_frame_time;
- double end = first_frame_time + (double) 1000000;
- double progress = (now - first_frame_time) / (end - start);
-
- if (flip)
- progress = 1 - progress;
-
- if (progress < 0 || progress >= 1)
- {
- first_frame_time = now;
- flip = !flip;
- return G_SOURCE_CONTINUE;
- }
-
- GskRenderer *renderer = get_renderer (widget);
- GskRenderNode *root = gsk_renderer_get_root_node (renderer);
-
- gsk_render_node_set_opacity (root, 1.0 - progress);
-
- gtk_widget_queue_draw (widget);
-
- return G_SOURCE_CONTINUE;
-}
-
-
-int
-main (int argc, char *argv[])
-{
- GtkWidget *window, *area;
-
- gtk_init (NULL, NULL);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
- gtk_window_set_title (GTK_WINDOW (window), "GSK Renderer");
- g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
-
- area = gtk_drawing_area_new ();
- gtk_widget_set_hexpand (area, TRUE);
- gtk_widget_set_vexpand (area, TRUE);
- gtk_widget_set_has_window (GTK_WIDGET (area), FALSE);
- gtk_widget_set_app_paintable (GTK_WIDGET (area), TRUE);
- gtk_container_add (GTK_CONTAINER (window), area);
-
- g_signal_connect (area, "realize", G_CALLBACK (realize), NULL);
- g_signal_connect (area, "unrealize", G_CALLBACK (unrealize), NULL);
- g_signal_connect (area, "size-allocate", G_CALLBACK (size_allocate), NULL);
- g_signal_connect (area, "draw", G_CALLBACK (draw), NULL);
-
- gtk_widget_add_tick_callback (area, fade_out, NULL, NULL);
-
- gtk_widget_show_all (window);
-
- gtk_main ();
-}