[gtk+/wip/ebassi/gsk-renderer: 430/545] gtk: Use GskRenderNode to render widgets



commit 4203e5235d6bfec66c70178249d3c4532efc19ab
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu Jun 23 17:35:42 2016 +0100

    gtk: Use GskRenderNode to render widgets
    
    We need a virtual function to retrieve the GskRenderNode for each
    widget, which is supposed to attach its own children's GskRenderNodes.
    Additionally, we want to maintain the existing GtkWidget::draw mechanism
    for widgets that do not implement get_render_node() — as well as widgets
    that have handlers connected to the ::draw signal.

 gtk/gtkwidget.c        |  105 ++++++++++++++++++++++++++++++++++++++++++++----
 gtk/gtkwidget.h        |    5 ++-
 gtk/gtkwidgetprivate.h |    3 +
 gtk/gtkwindow.c        |    6 +++
 4 files changed, 110 insertions(+), 9 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index ca6be0c..7416d77 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -16052,27 +16052,116 @@ gtk_widget_reset_controllers (GtkWidget *widget)
     }
 }
 
+GskRenderer *
+gtk_widget_get_renderer (GtkWidget *widget)
+{
+  GtkWidget *toplevel;
+
+  toplevel = _gtk_widget_get_toplevel (widget);
+  if (_gtk_widget_is_toplevel (toplevel))
+    return gtk_window_get_renderer (GTK_WINDOW (toplevel));
+
+  return NULL;
+}
+
+GskRenderNode *
+gtk_widget_get_render_node (GtkWidget   *widget,
+                            GskRenderer *renderer)
+{
+  GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (widget);
+  GskRenderNode *node;
+
+  if (klass->get_render_node == NULL)
+    {
+      GskRenderNode *tmp;
+      graphene_rect_t bounds;
+      GtkAllocation clip;
+      cairo_t *cr;
+
+      gtk_widget_get_clip (widget, &clip);
+      graphene_rect_init (&bounds, clip.x, clip.y, clip.width, clip.height);
+
+      tmp = gsk_render_node_new ();
+      gsk_render_node_set_bounds (tmp, &bounds);
+      cr = gsk_render_node_get_draw_context (tmp);
+
+      gtk_widget_draw (widget, cr);
+
+      cairo_destroy (cr);
+
+      node = tmp;
+    }
+  else
+    {
+      node = klass->get_render_node (widget, renderer);
+
+      if (klass->draw != NULL ||
+          g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
+        {
+          GskRenderNode *tmp;
+          graphene_rect_t bounds;
+          GtkAllocation clip;
+          gboolean result;
+          cairo_t *cr;
+
+          gtk_widget_get_clip (widget, &clip);
+          graphene_rect_init (&bounds, clip.x, clip.y, clip.width, clip.height);
+
+          tmp = gsk_render_node_new ();
+          gsk_render_node_set_bounds (tmp, &bounds);
+          cr = gsk_render_node_get_draw_context (tmp);
+
+          if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
+            {
+              g_signal_emit (widget, widget_signals[DRAW], 0, cr, &result);
+            }
+          else if (klass->draw != NULL)
+            {
+              klass->draw (widget, cr);
+            }
+
+          cairo_destroy (cr);
+
+          if (node != NULL)
+            {
+              gsk_render_node_append_child (node, tmp);
+              gsk_render_node_unref (tmp);
+            }
+          else
+            {
+              node = tmp;
+            }
+        }
+    }
+
+  return node;
+}
+
 void
 gtk_widget_render (GtkWidget            *widget,
                    GdkWindow            *window,
                    const cairo_region_t *region)
 {
   GdkDrawingContext *context;
-  gboolean do_clip;
-  cairo_t *cr;
-  int x, y;
+  GskRenderer *renderer;
+  GskRenderNode *root;
 
   /* We only render double buffered on native windows */
   if (!gdk_window_has_native (window))
     return;
 
-  context = gdk_window_begin_draw_frame (window, region);
-  cr = gdk_drawing_context_get_cairo_context (context);
+  renderer = gtk_widget_get_renderer (widget);
+  if (renderer == NULL)
+    return;
 
-  do_clip = _gtk_widget_get_translation_to_window (widget, window, &x, &y);
-  cairo_translate (cr, -x, -y);
+  root = gtk_widget_get_render_node (widget, renderer);
+  if (root == NULL)
+    return;
+
+  context = gdk_window_begin_draw_frame (window, region);
 
-  gtk_widget_draw_internal (widget, cr, do_clip);
+  gsk_renderer_render (renderer, root, context);
+  gsk_render_node_unref (root);
 
   gdk_window_end_draw_frame (window, context);
 }
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 4c5ac48..65327f7 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -30,6 +30,7 @@
 #endif
 
 #include <gdk/gdk.h>
+#include <gsk/gsk.h>
 #include <gtk/gtkaccelgroup.h>
 #include <gtk/gtkborder.h>
 #include <gtk/gtktypes.h>
@@ -595,12 +596,14 @@ struct _GtkWidgetClass
   void         (*queue_draw_region)           (GtkWidget         *widget,
                                               const cairo_region_t *region);
 
+  GskRenderNode *(* get_render_node) (GtkWidget *widget,
+                                      GskRenderer *renderer);
+
   /*< private >*/
 
   GtkWidgetClassPrivate *priv;
 
   /* Padding for future expansion */
-  void (*_gtk_reserved6) (void);
   void (*_gtk_reserved7) (void);
 };
 
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 1fe2c03..65f2bc8 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -297,6 +297,9 @@ void              gtk_widget_render                        (GtkWidget
                                                             const cairo_region_t *region);
 
 
+GskRenderNode *   gtk_widget_get_render_node               (GtkWidget   *widget,
+                                                            GskRenderer *renderer);
+
 /* inline getters */
 
 static inline gboolean
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index b790c4a..923aa2c 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -7328,6 +7328,8 @@ _gtk_window_set_allocation (GtkWindow           *window,
     {
       graphene_rect_t viewport;
       graphene_matrix_t projection;
+      graphene_matrix_t modelview;
+      graphene_point3d_t tmp;
 
       graphene_rect_init (&viewport, 0, 0, allocation->width, allocation->height);
       gsk_renderer_set_viewport (priv->renderer, &viewport);
@@ -7337,6 +7339,10 @@ _gtk_window_set_allocation (GtkWindow           *window,
                                   0, allocation->height,
                                   -1, 1);
       gsk_renderer_set_projection (priv->renderer, &projection);
+
+      graphene_matrix_init_translate (&modelview,
+                                      graphene_point3d_init (&tmp, 0.f, 0.f, 0.f));
+      gsk_renderer_set_modelview (priv->renderer, &modelview);
     }
 
   get_shadow_width (window, &window_border);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]