forked from AuroraMiddleware/gtk
gsk: Rework GskRenderer and GskRenderNode semantics
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.
This commit is contained in:
parent
d99f91f5fd
commit
074c77e7ac
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
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;
|
||||
return FALSE;
|
||||
|
||||
n_children = gsk_render_node_get_n_children (root);
|
||||
if (n_children == 0)
|
||||
return FALSE;
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
if (!clear_items)
|
||||
{
|
||||
GSK_NOTE (OPENGL, g_print ("Tree is still valid\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
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_gl_renderer_add_render_item (self, root);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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,36 +106,13 @@ 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)
|
||||
{
|
||||
@ -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);
|
||||
case PROP_USE_ALPHA:
|
||||
g_value_set_boolean (value, priv->use_alpha);
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
g_value_set_boxed (value, priv->surface);
|
||||
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,23 +432,47 @@ 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_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,112 +722,100 @@ 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);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_SURFACE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (priv->window != NULL)
|
||||
if (priv->scale_factor != scale_factor)
|
||||
{
|
||||
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;
|
||||
priv->scale_factor = scale_factor;
|
||||
|
||||
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);
|
||||
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_SCALE_FACTOR]);
|
||||
}
|
||||
}
|
||||
|
||||
return priv->surface;
|
||||
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), 1);
|
||||
|
||||
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;
|
||||
if (g_set_object (&priv->window, window))
|
||||
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_WINDOW]);
|
||||
}
|
||||
|
||||
cairo_t *
|
||||
gsk_renderer_get_draw_context (GskRenderer *renderer)
|
||||
/**
|
||||
* gsk_renderer_get_window:
|
||||
* @renderer: a #GskRenderer
|
||||
*
|
||||
* Retrieves the #GdkWindow set using gsk_renderer_set_window().
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GdkWindow
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
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);
|
||||
|
||||
if (priv->draw_context != NULL)
|
||||
return priv->draw_context;
|
||||
return priv->window;
|
||||
}
|
||||
|
||||
return cairo_create (gsk_renderer_get_surface (renderer));
|
||||
/*< private >
|
||||
* gsk_renderer_get_root_node:
|
||||
* @renderer: a #GskRenderer
|
||||
*
|
||||
* Retrieves the #GskRenderNode used by @renderer.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GskRenderNode
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_renderer_get_root_node (GskRenderer *renderer)
|
||||
{
|
||||
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
||||
|
||||
return priv->root_node;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gsk_renderer_get_drawing_context:
|
||||
* @renderer: a #GskRenderer
|
||||
*
|
||||
* Retrieves the #GdkDrawingContext used by @renderer.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GdkDrawingContext
|
||||
*/
|
||||
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), NULL);
|
||||
|
||||
return priv->drawing_context;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -947,26 +838,6 @@ gsk_renderer_get_display (GskRenderer *renderer)
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_renderer_get_root_node:
|
||||
* @renderer: a #GskRenderer
|
||||
*
|
||||
* Retrieves the root node of the scene graph.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GskRenderNode
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
GskRenderNode *
|
||||
gsk_renderer_get_root_node (GskRenderer *renderer)
|
||||
{
|
||||
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
||||
|
||||
return priv->root_node;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gsk_renderer_is_realized:
|
||||
* @renderer: a #GskRenderer
|
||||
@ -987,51 +858,6 @@ gsk_renderer_is_realized (GskRenderer *renderer)
|
||||
return priv->is_realized;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_renderer_set_window:
|
||||
* @renderer: a #GskRenderer
|
||||
* @window: (nullable): a #GdkWindow
|
||||
*
|
||||
* Sets the #GdkWindow used to create the target rendering surface.
|
||||
*
|
||||
* See also: gsk_renderer_set_surface()
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
void
|
||||
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 (window == NULL || GDK_IS_WINDOW (window));
|
||||
g_return_if_fail (!priv->is_realized);
|
||||
|
||||
if (g_set_object (&priv->window, window))
|
||||
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_WINDOW]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_renderer_get_window:
|
||||
* @renderer: a #GskRenderer
|
||||
*
|
||||
* Retrieves the #GdkWindow set with gsk_renderer_set_window().
|
||||
*
|
||||
* Returns: (transfer none) (nullable): a #GdkWindow
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
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->window;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_renderer_realize:
|
||||
* @renderer: a #GskRenderer
|
||||
@ -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 associated to @renderer, using the
|
||||
* given target surface.
|
||||
* Renders the scene graph, described by a tree of #GskRenderNode instances,
|
||||
* using the given #GdkDrawingContext.
|
||||
*
|
||||
* 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);
|
||||
g_return_if_fail (GSK_IS_RENDER_NODE (root));
|
||||
g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
|
||||
|
||||
/* 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_set_object (&priv->root_node, root);
|
||||
g_set_object (&priv->drawing_context, context);
|
||||
|
||||
gsk_renderer_maybe_update (renderer);
|
||||
gsk_render_node_make_immutable (root);
|
||||
|
||||
gsk_renderer_maybe_validate_tree (renderer);
|
||||
GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, context);
|
||||
|
||||
/* Clear the output surface */
|
||||
gsk_renderer_maybe_clear (renderer);
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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);
|
||||
void gsk_renderer_set_use_alpha (GskRenderer *renderer,
|
||||
gboolean use_alpha);
|
||||
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);
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
@ -50,19 +48,12 @@ gsk_render_node_dispose (GObject *gobject)
|
||||
G_OBJECT_CLASS (gsk_render_node_parent_class)->dispose (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)
|
||||
@ -296,6 +281,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
|
||||
@ -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);
|
||||
}
|
||||
|
@ -52,6 +52,12 @@ GskRenderNode * gsk_render_node_get_next_sibling (GskRenderNode *
|
||||
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,
|
||||
@ -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
|
||||
|
@ -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__ */
|
||||
|
@ -163,7 +163,6 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
||||
testpopup \
|
||||
testpopupat \
|
||||
testgaction \
|
||||
testgskrenderer \
|
||||
$(NULL)
|
||||
|
||||
if USE_X11
|
||||
@ -281,7 +280,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 \
|
||||
@ -490,8 +488,6 @@ listmodel_SOURCES = listmodel.c
|
||||
|
||||
foreigndrawing_SOURCES = foreigndrawing.c
|
||||
|
||||
testgskrenderer_SOURCES = testgskrenderer.c
|
||||
|
||||
EXTRA_DIST += \
|
||||
gradient1.png \
|
||||
testgtk.1 \
|
||||
|
@ -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 ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user