[gtk/wip/chergert/glproto: 673/920] stub out fallback drawing




commit c438912e3a8c4c17355c2fa64a9740cfb6bda861
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jan 11 10:03:20 2021 -0800

    stub out fallback drawing

 gsk/next/gskglrenderjob.c        | 217 +++++++++++++++++++++++++++++++--------
 gsk/next/gskglrenderjobprivate.h |  22 ++--
 2 files changed, 184 insertions(+), 55 deletions(-)
---
diff --git a/gsk/next/gskglrenderjob.c b/gsk/next/gskglrenderjob.c
index 10ad22d074..f0a6903e69 100644
--- a/gsk/next/gskglrenderjob.c
+++ b/gsk/next/gskglrenderjob.c
@@ -24,6 +24,7 @@
 #include "config.h"
 
 #include <gdk/gdkglcontextprivate.h>
+#include <gdk/gdktextureprivate.h>
 #include <gsk/gskrendernodeprivate.h>
 #include <math.h>
 #include <string.h>
@@ -79,6 +80,7 @@ struct _GskGLRenderJob
   float              offset_y;
   float              scale_x;
   float              scale_y;
+  guint              debug_fallback : 1;
 };
 
 typedef struct _GskGLRenderClip
@@ -654,16 +656,13 @@ gsk_gl_render_job_node_overlaps_clip (GskGLRenderJob *job,
 }
 
 static void
-gsk_gl_render_job_draw_rect (GskGLRenderJob        *job,
-                             const graphene_rect_t *rect)
+gsk_gl_render_job_draw_coords (GskGLRenderJob *job,
+                               float           min_x,
+                               float           min_y,
+                               float           max_x,
+                               float           max_y)
 {
-  GskGLDrawVertex *vertices;
-  const float min_x = job->offset_x + rect->origin.x;
-  const float min_y = job->offset_y + rect->origin.y;
-  const float max_x = min_x + rect->size.width;
-  const float max_y = min_y + rect->size.height;
-
-  vertices = gsk_gl_command_queue_add_vertices (job->command_queue, NULL);
+  GskGLDrawVertex *vertices = gsk_gl_command_queue_add_vertices (job->command_queue, NULL);
 
   vertices[0].position[0] = min_x;
   vertices[0].position[1] = min_y;
@@ -696,6 +695,18 @@ gsk_gl_render_job_draw_rect (GskGLRenderJob        *job,
   vertices[5].uv[1] = 0;
 }
 
+static void
+gsk_gl_render_job_draw_rect (GskGLRenderJob        *job,
+                             const graphene_rect_t *rect)
+{
+  float min_x = job->offset_x + rect->origin.x;
+  float min_y = job->offset_y + rect->origin.y;
+  float max_x = min_x + rect->size.width;
+  float max_y = min_y + rect->size.height;
+
+  gsk_gl_render_job_draw_coords (job, min_x, min_y, max_x, max_y);
+}
+
 static void
 gsk_gl_render_job_draw (GskGLRenderJob *job,
                         float           x,
@@ -703,43 +714,12 @@ gsk_gl_render_job_draw (GskGLRenderJob *job,
                         float           width,
                         float           height)
 {
-  GskGLDrawVertex *vertices;
-  const float min_x = job->offset_x + x;
-  const float min_y = job->offset_y + y;
-  const float max_x = min_x + width;
-  const float max_y = min_y + height;
-
-  vertices = gsk_gl_command_queue_add_vertices (job->command_queue, NULL);
-
-  vertices[0].position[0] = min_x;
-  vertices[0].position[1] = min_y;
-  vertices[0].uv[0] = 0;
-  vertices[0].uv[1] = 0;
-
-  vertices[1].position[0] = min_x;
-  vertices[1].position[1] = max_y;
-  vertices[1].uv[0] = 0;
-  vertices[1].uv[1] = 1;
+  float min_x = job->offset_x + x;
+  float min_y = job->offset_y + y;
+  float max_x = min_x + width;
+  float max_y = min_y + height;
 
-  vertices[2].position[0] = max_x;
-  vertices[2].position[1] = min_y;
-  vertices[2].uv[0] = 1;
-  vertices[2].uv[1] = 0;
-
-  vertices[3].position[0] = max_x;
-  vertices[3].position[1] = max_y;
-  vertices[3].uv[0] = 1;
-  vertices[3].uv[1] = 1;
-
-  vertices[4].position[0] = min_x;
-  vertices[4].position[1] = max_y;
-  vertices[4].uv[0] = 0;
-  vertices[4].uv[1] = 1;
-
-  vertices[5].position[0] = max_x;
-  vertices[5].position[1] = min_y;
-  vertices[5].uv[0] = 1;
-  vertices[5].uv[1] = 0;
+  gsk_gl_render_job_draw_coords (job, min_x, min_y, max_x, max_y);
 }
 
 static void
@@ -788,10 +768,138 @@ gsk_gl_render_job_draw_from_offscreen (GskGLRenderJob        *job,
   vertices[5].uv[1] = y1;
 }
 
+static void
+gsk_gl_render_job_draw_offscren_rect (GskGLRenderJob        *job,
+                                      const graphene_rect_t *bounds)
+{
+  float min_x = job->offset_x + bounds->origin.x;
+  float min_y = job->offset_y + bounds->origin.y;
+  float max_x = min_x + bounds->size.width;
+  float max_y = min_y + bounds->size.height;
+
+  gsk_gl_render_job_draw_coords (job, min_x, min_y, max_x, max_y);
+}
+
 static void
 gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
                                      GskRenderNode  *node)
 {
+  float scale_x = job->scale_x;
+  float scale_y = job->scale_y;
+  int surface_width = ceilf (node->bounds.size.width * scale_x);
+  int surface_height = ceilf (node->bounds.size.height * scale_y);
+  GdkTexture *texture;
+  cairo_surface_t *surface;
+  cairo_surface_t *rendered_surface;
+  cairo_t *cr;
+  graphene_rect_t area;
+  int cached_id;
+  int texture_id;
+  GskTextureKey key;
+
+  if (surface_width <= 0 || surface_height <= 0)
+    return;
+
+  key.pointer = node;
+  key.pointer_is_child = FALSE;
+  key.scale_x = scale_x;
+  key.scale_y = scale_y;
+  key.filter = GL_NEAREST;
+
+  cached_id = gsk_next_driver_lookup_texture (job->driver, &key);
+
+  if (cached_id != 0)
+    {
+      gsk_gl_program_begin_draw (job->driver->blit,
+                                 &job->viewport,
+                                 &job->projection,
+                                 gsk_gl_render_job_get_modelview_matrix (job),
+                                 gsk_gl_render_job_get_clip (job),
+                                 job->alpha);
+      gsk_gl_program_set_uniform_texture (job->driver->blit,
+                                          UNIFORM_SHARED_SOURCE,
+                                          GL_TEXTURE_2D, GL_TEXTURE0, cached_id);
+      gsk_gl_render_job_draw_offscren_rect (job, &node->bounds);
+      gsk_gl_program_end_draw (job->driver->blit);
+      return;
+    }
+
+  /* We first draw the recording surface on an image surface,
+   * just because the scaleY(-1) later otherwise screws up the
+   * rendering... */
+  {
+    rendered_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                                   surface_width,
+                                                   surface_height);
+
+    cairo_surface_set_device_scale (rendered_surface, scale_x, scale_y);
+    cr = cairo_create (rendered_surface);
+
+    cairo_save (cr);
+    cairo_translate (cr, - floorf (node->bounds.origin.x), - floorf (node->bounds.origin.y));
+    gsk_render_node_draw (node, cr);
+    cairo_restore (cr);
+    cairo_destroy (cr);
+  }
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        surface_width,
+                                        surface_height);
+  cairo_surface_set_device_scale (surface, scale_x, scale_y);
+  cr = cairo_create (surface);
+
+  /* We draw upside down here, so it matches what GL does. */
+  cairo_save (cr);
+  cairo_scale (cr, 1, -1);
+  cairo_translate (cr, 0, - surface_height / scale_y);
+  cairo_set_source_surface (cr, rendered_surface, 0, 0);
+  cairo_rectangle (cr, 0, 0, surface_width / scale_x, surface_height / scale_y);
+  cairo_fill (cr);
+  cairo_restore (cr);
+
+#ifdef G_ENABLE_DEBUG
+  if (job->debug_fallback)
+    {
+      cairo_move_to (cr, 0, 0);
+      cairo_rectangle (cr, 0, 0, node->bounds.size.width, node->bounds.size.height);
+      if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
+        cairo_set_source_rgba (cr, 0.3, 0, 1, 0.25);
+      else
+        cairo_set_source_rgba (cr, 1, 0, 0, 0.25);
+      cairo_fill_preserve (cr);
+      if (gsk_render_node_get_node_type (node) == GSK_CAIRO_NODE)
+        cairo_set_source_rgba (cr, 0.3, 0, 1, 1);
+      else
+        cairo_set_source_rgba (cr, 1, 0, 0, 1);
+      cairo_stroke (cr);
+    }
+#endif
+  cairo_destroy (cr);
+
+  /* Create texture to upload */
+  texture = gdk_texture_new_for_surface (surface);
+  texture_id = gsk_next_driver_load_texture (job->driver, texture, GL_NEAREST, GL_NEAREST, &area);
+
+  if (gdk_gl_context_has_debug (job->command_queue->context))
+    gdk_gl_context_label_object_printf (job->command_queue->context, GL_TEXTURE, texture_id,
+                                        "Fallback %s %d",
+                                        g_type_name_from_instance ((GTypeInstance *) node),
+                                        texture_id);
+
+  g_object_unref (texture);
+  cairo_surface_destroy (surface);
+  cairo_surface_destroy (rendered_surface);
+
+  gsk_next_driver_cache_texture (job->driver, &key, texture_id);
+
+  gsk_gl_program_begin_draw (job->driver->blit,
+                             &job->viewport,
+                             &job->projection,
+                             gsk_gl_render_job_get_modelview_matrix (job),
+                             gsk_gl_render_job_get_clip (job),
+                             job->alpha);
+  gsk_gl_render_job_draw_offscren_rect (job, &area);
+  gsk_gl_program_end_draw (job->driver->blit);
 }
 
 static void
@@ -1412,6 +1520,7 @@ static void
 gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
                                                    GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
@@ -1497,6 +1606,7 @@ static void
 gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
                                                     GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static inline bool G_GNUC_PURE
@@ -1624,48 +1734,56 @@ gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
                                    const GdkRGBA  *color,
                                    gboolean        force_color)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
 gsk_gl_render_job_visit_shadow_node (GskGLRenderJob *job,
                                      GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
 gsk_gl_render_job_visit_blur_node (GskGLRenderJob *job,
                                    GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
 gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
                                     GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
 gsk_gl_render_job_visit_cairo_node (GskGLRenderJob *job,
                                     GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
 gsk_gl_render_job_visit_color_matrix_node (GskGLRenderJob *job,
                                            GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
 gsk_gl_render_job_visit_gl_shader_node (GskGLRenderJob *job,
                                         GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
 gsk_gl_render_job_visit_texture_node (GskGLRenderJob *job,
                                       GskRenderNode  *node)
 {
+  gsk_gl_render_job_visit_as_fallback (job, node);
 }
 
 static void
@@ -2007,3 +2125,12 @@ gsk_gl_render_job_render (GskGLRenderJob *job,
 
   gsk_next_driver_end_frame (job->driver);
 }
+
+void
+gsk_gl_render_job_set_debug_falllback (GskGLRenderJob *job,
+                                       gboolean        debug_fallback)
+{
+  g_return_if_fail (job != NULL);
+
+  job->debug_fallback = !!debug_fallback;
+}
diff --git a/gsk/next/gskglrenderjobprivate.h b/gsk/next/gskglrenderjobprivate.h
index 448dbb731d..108f823529 100644
--- a/gsk/next/gskglrenderjobprivate.h
+++ b/gsk/next/gskglrenderjobprivate.h
@@ -23,15 +23,17 @@
 
 #include "gskgltypes.h"
 
-GskGLRenderJob *gsk_gl_render_job_new            (GskNextDriver         *driver,
-                                                  const graphene_rect_t *viewport,
-                                                  float                  scale_factor,
-                                                  const cairo_region_t  *region,
-                                                  guint                  framebuffer);
-void            gsk_gl_render_job_free           (GskGLRenderJob        *job);
-void            gsk_gl_render_job_render         (GskGLRenderJob        *job,
-                                                  GskRenderNode         *root);
-void            gsk_gl_render_job_render_flipped (GskGLRenderJob        *job,
-                                                  GskRenderNode         *root);
+GskGLRenderJob *gsk_gl_render_job_new                 (GskNextDriver         *driver,
+                                                       const graphene_rect_t *viewport,
+                                                       float                  scale_factor,
+                                                       const cairo_region_t  *region,
+                                                       guint                  framebuffer);
+void            gsk_gl_render_job_free                (GskGLRenderJob        *job);
+void            gsk_gl_render_job_render              (GskGLRenderJob        *job,
+                                                       GskRenderNode         *root);
+void            gsk_gl_render_job_render_flipped      (GskGLRenderJob        *job,
+                                                       GskRenderNode         *root);
+void            gsk_gl_render_job_set_debug_falllback (GskGLRenderJob        *job,
+                                                       gboolean               debug_fallback);
 
 #endif /* __GSK_GL_RENDER_JOB_H__ */


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