diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2016-08-25 11:31:56 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2016-10-18 11:49:16 +0100 |
commit | dace0791a9bab4a5d1a69e4bde87973814ca217a (patch) | |
tree | bcf8e20b5813fdf1ed613ec1d3a13682a20786d5 /gsk/gskrenderer.c | |
parent | a9bbb020aac9f20d7366b29219ada2e77349642a (diff) | |
download | gtk+-dace0791a9bab4a5d1a69e4bde87973814ca217a.tar.gz |
gsk: Add the ability to create fallback renderers
While porting GTK to GskRenderer we noticed that the current fallback
code for widgets using Cairo to draw is not enough to cover all the
possible cases.
For instance, if a container widget still uses GtkWidget::draw to render
its children, and at least one of them has been ported to using render
nodes instead, the container won't know how to draw it.
For this reason we want to provide to layers above GSK the ability to
create a "fallback" renderer instance, created using a "parent"
GskRenderer instance, but using a Cairo context as the rendering target
instead of a GdkDrawingContext.
GTK will use this inside the gtk_widget_draw() implementation, if a
widget implements GtkWidgetClass.get_render_node().
Diffstat (limited to 'gsk/gskrenderer.c')
-rw-r--r-- | gsk/gskrenderer.c | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c index ebdb1a4b28..d77bfe1ed3 100644 --- a/gsk/gskrenderer.c +++ b/gsk/gskrenderer.c @@ -37,6 +37,7 @@ #include "gskrendererprivate.h" +#include "gskcairorendererprivate.h" #include "gskdebugprivate.h" #include "gskglrendererprivate.h" #include "gskprofilerprivate.h" @@ -68,6 +69,7 @@ typedef struct GdkDrawingContext *drawing_context; GskRenderNode *root_node; GdkDisplay *display; + cairo_t *cairo_context; GskProfiler *profiler; @@ -121,6 +123,7 @@ gsk_renderer_dispose (GObject *gobject) gsk_renderer_unrealize (self); + g_clear_pointer (&priv->cairo_context, cairo_destroy); g_clear_object (&priv->window); g_clear_object (&priv->display); @@ -603,6 +606,16 @@ gsk_renderer_render (GskRenderer *renderer, if (context != NULL) priv->drawing_context = g_object_ref (context); + else + { + if (priv->cairo_context == NULL) + { + g_critical ("The given GskRenderer instance was not created using " + "gsk_renderer_create_fallback(), but you forgot to pass " + "a GdkDrawingContext."); + return; + } + } priv->root_node = gsk_render_node_ref (root); gsk_render_node_make_immutable (priv->root_node); @@ -695,7 +708,7 @@ gsk_renderer_get_for_display (GdkDisplay *display) } if (use_software[0] != '0') - return NULL; + return g_object_new (GSK_TYPE_CAIRO_RENDERER, "display", display, NULL); #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_DISPLAY (display)) @@ -707,7 +720,7 @@ gsk_renderer_get_for_display (GdkDisplay *display) renderer_type = GSK_TYPE_GL_RENDERER; else #endif - return NULL; + renderer_type = GSK_TYPE_CAIRO_RENDERER; GSK_NOTE (RENDERER, g_print ("Creating renderer of type '%s' for display '%s'\n", g_type_name (renderer_type), @@ -717,3 +730,65 @@ gsk_renderer_get_for_display (GdkDisplay *display) return g_object_new (renderer_type, "display", display, NULL); } + +static void +gsk_renderer_set_cairo_context (GskRenderer *renderer, + cairo_t *cr) +{ + GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer); + + g_clear_pointer (&priv->cairo_context, cairo_destroy); + + if (cr != NULL) + priv->cairo_context = cairo_reference (cr); +} + +cairo_t * +gsk_renderer_get_cairo_context (GskRenderer *renderer) +{ + GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer); + + return priv->cairo_context; +} + +/** + * gsk_renderer_create_fallback: + * @renderer: a #GskRenderer + * @viewport: the viewport for the fallback renderer + * @cr: a Cairo context + * + * Creates a fallback #GskRenderer using the same display and window of + * the given @renderer, and instructs it to render to a given Cairo + * context. + * + * Typically, you'll use this function to implement fallback rendering + * of #GskRenderNodes on an intermediate Cairo context, instead of using + * the drawing context associated to a #GdkWindow's rendering buffer. + * + * Returns: (transfer full): a newly created fallback #GskRenderer instance + * + * Since: 3.22 + */ +GskRenderer * +gsk_renderer_create_fallback (GskRenderer *renderer, + const graphene_rect_t *viewport, + cairo_t *cr) +{ + GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer); + GskRenderer *res; + + g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL); + g_return_val_if_fail (cr != NULL, NULL); + + res = g_object_new (GSK_TYPE_CAIRO_RENDERER, + "display", priv->display, + "window", priv->window, + "scale-factor", priv->scale_factor, + "viewport", viewport, + NULL); + + gsk_renderer_set_cairo_context (res, cr); + gsk_renderer_realize (res); + + return res; +} |