broadway: Add and use GdkBroadwayDrawContext
authorAlexander Larsson <alexl@redhat.com>
Tue, 24 Apr 2018 13:39:53 +0000 (15:39 +0200)
committerBenjamin Otte <otte@redhat.com>
Tue, 24 Apr 2018 21:24:55 +0000 (23:24 +0200)
gdk/broadway/gdkdisplay-broadway.c
gdk/broadway/gdkdrawcontext-broadway.c [new file with mode: 0644]
gdk/broadway/gdkdrawcontext-broadway.h [new file with mode: 0644]
gdk/broadway/gdkprivate-broadway.h
gdk/broadway/meson.build
gsk/gskbroadwayrenderer.c

index 254e0a2bc794f1648eaa1690fac304f7c209121d..f27af0b3ef32faba150c94b8d4471ba67dd8b07a 100644 (file)
 #endif
 #include <sys/types.h>
 
-static gboolean
-compare_surface (cairo_surface_t *a,
-                 cairo_surface_t *b,
-                 int width,
-                 int height)
-{
-  unsigned char *data_a, *data_b;
-  int stride_a, stride_b;
-  int y;
-
-  data_a = cairo_image_surface_get_data (a);
-  stride_a = cairo_image_surface_get_stride (a);
-
-  data_b = cairo_image_surface_get_data (b);
-  stride_b = cairo_image_surface_get_stride (b);
-
-  for (y = 0; y < height; y++)
-    {
-      if (memcmp (data_a, data_b, 4 * width) != 0)
-        return FALSE;
-      data_a += stride_a;
-      data_b += stride_b;
-    }
-
-  return TRUE;
-}
-
-static gboolean
-gdk_texture_equal (GdkTexture *a,
-                   GdkTexture *b)
-{
-  cairo_surface_t *surface_a;
-  cairo_surface_t *surface_b;
-  gboolean res;
-
-  if (a == b)
-    return TRUE;
-
-  if (a->width != b->width ||
-      a->height != b->height)
-    return FALSE;
-
-  surface_a = gdk_texture_download_surface (a);
-  surface_b = gdk_texture_download_surface (b);
-
-  res = compare_surface (surface_a, surface_b, a->width, a->height);
-
-  cairo_surface_destroy (surface_a);
-  cairo_surface_destroy (surface_b);
-
-  return res;
-}
-
-static guint
-gdk_texture_hash (GdkTexture *self)
-{
-  cairo_surface_t *surface;
-  unsigned char *data;
-  int stride;
-  guint32 *row;
-  guint64 sum;
-  int x, y, width, height;
-  guint h;
-
-  surface = gdk_texture_download_surface (self);
-  data = cairo_image_surface_get_data (surface);
-  stride = cairo_image_surface_get_stride (surface);
-
-  width = MIN (self->width, 4);
-  height = MIN (self->height, 4);
-
-  sum = 0;
-  for (y = 0; y < height; y++, data += stride)
-    {
-      row = (guint32 *)data;
-      for (x = 0; x < width; x++)
-        sum += row[x];
-    }
-
-  cairo_surface_destroy (surface);
-
-  h = sum / (width * height);
-
-  return h ^ self->width ^ (self->height << 16);
-}
-
 static void   gdk_broadway_display_dispose            (GObject            *object);
 static void   gdk_broadway_display_finalize           (GObject            *object);
 
@@ -149,7 +63,6 @@ gdk_broadway_display_init (GdkBroadwayDisplay *display)
                                    NULL);
   gdk_monitor_set_manufacturer (display->monitor, "browser");
   gdk_monitor_set_model (display->monitor, "0");
-  display->texture_cache = g_hash_table_new ((GHashFunc)gdk_texture_hash, (GEqualFunc)gdk_texture_equal);
 }
 
 static void
@@ -439,39 +352,17 @@ gdk_broadway_display_get_last_seen_time (GdkDisplay *display)
 typedef struct {
   int id;
   GdkDisplay *display;
-  GdkTexture *in_cache;
   GList *textures;
 } BroadwayTextureData;
 
 static void
-broadway_texture_data_notify (BroadwayTextureData *data,
-                             GdkTexture *disposed_texture)
+broadway_texture_data_free (BroadwayTextureData *data)
 {
   GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (data->display);
 
-  if (data->in_cache == disposed_texture)
-    {
-      g_hash_table_remove (broadway_display->texture_cache, disposed_texture);
-      data->in_cache = NULL;
-    }
-
-  g_object_set_data (G_OBJECT (disposed_texture), "broadway-data", NULL);
-
-  data->textures = g_list_remove (data->textures, disposed_texture);
-  if (data->textures == NULL)
-    {
-      gdk_broadway_server_release_texture (broadway_display->server, data->id);
-      g_object_unref (data->display);
-      g_free (data);
-    }
-  else if (data->in_cache == NULL)
-    {
-      GdkTexture *first = data->textures->data;
-
-      data->in_cache = first;
-      g_hash_table_replace (broadway_display->texture_cache,
-                           data->in_cache, data->in_cache);
-    }
+  gdk_broadway_server_release_texture (broadway_display->server, data->id);
+  g_object_unref (data->display);
+  g_free (data);
 }
 
 guint32
@@ -480,35 +371,18 @@ gdk_broadway_display_ensure_texture (GdkDisplay *display,
 {
   GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
   BroadwayTextureData *data;
-  guint32 id;
-  GdkTexture *cached;
 
   data = g_object_get_data (G_OBJECT (texture), "broadway-data");
-  if (data != NULL)
-    return data->id;
-
-  cached = g_hash_table_lookup (broadway_display->texture_cache, texture);
-  if (cached)
-    data = g_object_get_data (G_OBJECT (cached), "broadway-data");
-
   if (data == NULL)
     {
-      id = gdk_broadway_server_upload_texture (broadway_display->server, texture);
+      guint32 id = gdk_broadway_server_upload_texture (broadway_display->server, texture);
 
       data = g_new0 (BroadwayTextureData, 1);
       data->id = id;
       data->display = g_object_ref (display);
-
-      data->in_cache = texture;
-      g_hash_table_replace (broadway_display->texture_cache,
-                           data->in_cache, data->in_cache);
+      g_object_set_data_full (G_OBJECT (texture), "broadway-data", data, (GDestroyNotify)broadway_texture_data_free);
     }
 
-  data->textures = g_list_prepend (data->textures, texture);
-
-  g_object_weak_ref (G_OBJECT (texture), (GWeakNotify)broadway_texture_data_notify, data);
-  g_object_set_data (G_OBJECT (texture), "broadway-data", data);
-
   return data->id;
 }
 
diff --git a/gdk/broadway/gdkdrawcontext-broadway.c b/gdk/broadway/gdkdrawcontext-broadway.c
new file mode 100644 (file)
index 0000000..889b52f
--- /dev/null
@@ -0,0 +1,100 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * Copyright © 2018  Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gdkconfig.h"
+
+#include "gdkdrawcontext-broadway.h"
+#include "gdktextureprivate.h"
+#include "gdkprivate-broadway.h"
+
+G_DEFINE_TYPE (GdkBroadwayDrawContext, gdk_broadway_draw_context, GDK_TYPE_DRAW_CONTEXT)
+
+static void
+gdk_broadway_draw_context_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (gdk_broadway_draw_context_parent_class)->dispose (object);
+}
+
+static void
+gdk_broadway_draw_context_begin_frame (GdkDrawContext *draw_context,
+                                       cairo_region_t *region)
+{
+  GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
+  GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self));
+
+  cairo_region_union_rectangle (region,
+                                &(cairo_rectangle_int_t) {
+                                    0, 0,
+                                    gdk_surface_get_width (surface),
+                                    gdk_surface_get_height (surface)
+                                 });
+
+  g_assert (self->nodes == NULL);
+  g_assert (self->node_textures == NULL);
+
+  self->nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
+  self->node_textures = g_ptr_array_new_with_free_func (g_object_unref);
+}
+
+static void
+gdk_broadway_draw_context_end_frame (GdkDrawContext *draw_context,
+                                     cairo_region_t *painted)
+{
+  GdkBroadwayDrawContext *self = GDK_BROADWAY_DRAW_CONTEXT (draw_context);
+  GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
+
+  gdk_broadway_surface_set_nodes (surface, self->nodes, self->node_textures);
+
+  g_array_unref (self->nodes);
+  self->nodes = NULL;
+  g_ptr_array_unref (self->node_textures);
+  self->node_textures = NULL;
+}
+
+static void
+gdk_broadway_draw_context_surface_resized (GdkDrawContext *draw_context)
+{
+}
+
+static void
+gdk_broadway_draw_context_class_init (GdkBroadwayDrawContextClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
+
+  gobject_class->dispose = gdk_broadway_draw_context_dispose;
+
+  draw_context_class->begin_frame = gdk_broadway_draw_context_begin_frame;
+  draw_context_class->end_frame = gdk_broadway_draw_context_end_frame;
+  draw_context_class->surface_resized = gdk_broadway_draw_context_surface_resized;
+}
+
+static void
+gdk_broadway_draw_context_init (GdkBroadwayDrawContext *self)
+{
+}
+
+GdkBroadwayDrawContext *
+gdk_broadway_draw_context_context (GdkSurface *surface)
+{
+  return g_object_new (GDK_TYPE_BROADWAY_DRAW_CONTEXT,
+                       "surface", surface,
+                       NULL);
+}
diff --git a/gdk/broadway/gdkdrawcontext-broadway.h b/gdk/broadway/gdkdrawcontext-broadway.h
new file mode 100644 (file)
index 0000000..ccb0e09
--- /dev/null
@@ -0,0 +1,58 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * Copyright © 2018  Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_BROADWAY_DRAW_CONTEXT__
+#define __GDK_BROADWAY_DRAW_CONTEXT__
+
+#include "gdkconfig.h"
+
+#include "gdkdrawcontextprivate.h"
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_BROADWAY_DRAW_CONTEXT                  (gdk_broadway_draw_context_get_type ())
+#define GDK_BROADWAY_DRAW_CONTEXT(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_BROADWAY_DRAW_CONTEXT, GdkBroadwayDrawContext))
+#define GDK_IS_BROADWAY_DRAW_CONTEXT(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_BROADWAY_DRAW_CONTEXT))
+#define GDK_BROADWAY_DRAW_CONTEXT_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_BROADWAY_DRAW_CONTEXT, GdkBroadwayDrawContextClass))
+#define GDK_IS_BROADWAY_DRAW_CONTEXT_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_DRAW_CONTEXT))
+#define GDK_BROADWAY_DRAW_CONTEXT_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_DRAW_CONTEXT, GdkBroadwayDrawContextClass))
+
+typedef struct _GdkBroadwayDrawContext GdkBroadwayDrawContext;
+typedef struct _GdkBroadwayDrawContextClass GdkBroadwayDrawContextClass;
+
+struct _GdkBroadwayDrawContext
+{
+  GdkDrawContext parent_instance;
+
+  GPtrArray *node_textures;
+  GArray *nodes;
+};
+
+struct _GdkBroadwayDrawContextClass
+{
+  GdkDrawContextClass parent_class;
+};
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_broadway_draw_context_get_type (void) G_GNUC_CONST;
+
+GdkBroadwayDrawContext *gdk_broadway_draw_context_context (GdkSurface *surface);
+
+G_END_DECLS
+
+#endif /* __GDK_BROADWAY_DRAW_CONTEXT__ */
index db4ce7619bc88c40b3b7dc44bd96440ad8b136db..bfca42173aa6a2b1d7dbea508ee0202e14c13ab6 100644 (file)
@@ -33,6 +33,7 @@
 #include <gdk/gdkinternals.h>
 #include "gdksurface-broadway.h"
 #include "gdkdisplay-broadway.h"
+#include "gdkdrawcontext-broadway.h"
 
 #include "gdkbroadwaycursor.h"
 #include "gdkbroadwaysurface.h"
index aaa517ee6f0c3e391a824cf2958358bc2a864172..0306770f3fa6c3d874a056a324d7981a3360119f 100644 (file)
@@ -4,6 +4,7 @@ gdk_broadway_sources = files([
   'broadwayd.c',
   'gdkbroadway-server.c',
   'gdkcairocontext-broadway.c',
+  'gdkdrawcontext-broadway.c',
   'gdkcursor-broadway.c',
   'gdkdevice-broadway.c',
   'gdkdisplay-broadway.c',
index 0c118859cc3770f0b08d922108e5ba947262c1ba..9eeec7ce463483d42645485f06d59e3e5e317f7e 100644 (file)
@@ -8,11 +8,10 @@
 #include "gskrendernodeprivate.h"
 #include "gdk/gdktextureprivate.h"
 
-
 struct _GskBroadwayRenderer
 {
   GskRenderer parent_instance;
-
+  GdkBroadwayDrawContext *draw_context;
 };
 
 struct _GskBroadwayRendererClass
@@ -23,21 +22,33 @@ struct _GskBroadwayRendererClass
 G_DEFINE_TYPE (GskBroadwayRenderer, gsk_broadway_renderer, GSK_TYPE_RENDERER)
 
 static gboolean
-gsk_broadway_renderer_realize (GskRenderer  *self,
-                               GdkSurface    *surface,
+gsk_broadway_renderer_realize (GskRenderer  *renderer,
+                               GdkSurface   *surface,
                                GError      **error)
 {
+  GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
+
+  if (!GDK_IS_BROADWAY_SURFACE (surface))
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                   "Broadway renderer only works for broadway surfaces");
+      return FALSE;
+    }
+
+  self->draw_context = gdk_broadway_draw_context_context (surface);
+
   return TRUE;
 }
 
 static void
-gsk_broadway_renderer_unrealize (GskRenderer *self)
+gsk_broadway_renderer_unrealize (GskRenderer *renderer)
 {
-
+  GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
+  g_clear_object (&self->draw_context);
 }
 
 static GdkTexture *
-gsk_broadway_renderer_render_texture (GskRenderer           *self,
+gsk_broadway_renderer_render_texture (GskRenderer           *renderer,
                                       GskRenderNode         *root,
                                       const graphene_rect_t *viewport)
 {
@@ -443,14 +454,14 @@ node_texture_fallback (GskRenderNode *node,
    parent-relative which is what the dom uses, and
    which is good for re-using subtrees. */
 static void
-gsk_broadway_renderer_add_node (GskRenderer *self,
+gsk_broadway_renderer_add_node (GskRenderer *renderer,
                                 GArray *nodes,
                                 GPtrArray *node_textures,
                                 GskRenderNode *node,
                                 float offset_x,
                                 float offset_y)
 {
-  GdkDisplay *display = gsk_renderer_get_display (self);
+  GdkDisplay *display = gsk_renderer_get_display (renderer);
 
   switch (gsk_render_node_get_node_type (node))
     {
@@ -564,7 +575,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
             add_float (nodes, shadow->dy);
             add_float (nodes, shadow->radius);
           }
-        gsk_broadway_renderer_add_node (self, nodes, node_textures,
+        gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
                                         gsk_shadow_node_get_child (node),
                                         offset_x, offset_y);
       }
@@ -574,7 +585,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
       {
         add_uint32 (nodes, BROADWAY_NODE_OPACITY);
         add_float (nodes, gsk_opacity_node_get_opacity (node));
-        gsk_broadway_renderer_add_node (self, nodes, node_textures,
+        gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
                                         gsk_opacity_node_get_child (node),
                                         offset_x, offset_y);
       }
@@ -585,7 +596,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
         const GskRoundedRect *rclip = gsk_rounded_clip_node_peek_clip (node);
         add_uint32 (nodes, BROADWAY_NODE_ROUNDED_CLIP);
         add_rounded_rect (nodes, rclip, offset_x, offset_y);
-        gsk_broadway_renderer_add_node (self, nodes, node_textures,
+        gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
                                         gsk_rounded_clip_node_get_child (node),
                                         rclip->bounds.origin.x,
                                         rclip->bounds.origin.y);
@@ -597,7 +608,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
         const graphene_rect_t *clip = gsk_clip_node_peek_clip (node);
         add_uint32 (nodes, BROADWAY_NODE_CLIP);
         add_rect (nodes, clip, offset_x, offset_y);
-        gsk_broadway_renderer_add_node (self, nodes, node_textures,
+        gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
                                         gsk_clip_node_get_child (node),
                                         clip->origin.x,
                                         clip->origin.y);
@@ -614,13 +625,13 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
         add_uint32 (nodes, gsk_container_node_get_n_children (node));
 
         for (i = 0; i < gsk_container_node_get_n_children (node); i++)
-          gsk_broadway_renderer_add_node (self, nodes, node_textures,
+          gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
                                           gsk_container_node_get_child (node, i), offset_x, offset_y);
       }
       return;
 
     case GSK_DEBUG_NODE:
-      gsk_broadway_renderer_add_node (self, nodes, node_textures,
+      gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
                                       gsk_debug_node_get_child (node), offset_x, offset_y);
       return;
 
@@ -666,32 +677,15 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
 }
 
 static void
-gsk_broadway_renderer_render (GskRenderer          *self,
+gsk_broadway_renderer_render (GskRenderer          *renderer,
                               GskRenderNode        *root,
                               const cairo_region_t *update_area)
 {
-  GArray *nodes;
-  GPtrArray *node_textures;
-  cairo_region_t *whole;
-  GdkSurface *surface;
-
-  surface = gsk_renderer_get_surface (self);
-  whole = cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
-                                           0, 0,
-                                           gdk_surface_get_width (surface),
-                                           gdk_surface_get_height (surface)
-                                         });
-  gdk_draw_context_begin_frame (NULL, whole);
-  cairo_region_destroy (whole);
-
-  nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
-  node_textures = g_ptr_array_new_with_free_func (g_object_unref);
-  gsk_broadway_renderer_add_node (self, nodes, node_textures, root, 0, 0);
-  gdk_broadway_surface_set_nodes (surface, nodes, node_textures);
-  g_array_unref (nodes);
-  g_ptr_array_unref (node_textures);
-
-  gdk_draw_context_end_frame (NULL);
+  GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
+
+  gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->draw_context), update_area);
+  gsk_broadway_renderer_add_node (renderer, self->draw_context->nodes, self->draw_context->node_textures, root, 0, 0);
+  gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->draw_context));
 }
 
 static void