[gtk] gdk: Add GdkCairoContext



commit f3967860519981b30a01268d6fb459ba1a79d624
Author: Benjamin Otte <otte redhat com>
Date:   Thu Apr 12 00:16:43 2018 +0200

    gdk: Add GdkCairoContext
    
    This does nothing but disallow passing NULL to gdk_surface_begin_paint()
    and instead require this context.
    
    The ultimate goal is to split out Cairo drawing into its own source file
    so it doesn't clutter up the generic rendering path.

 docs/reference/gdk/gdk4-sections.txt |   8 +++
 gdk/gdk.h                            |   1 +
 gdk/gdkcairocontext.c                | 102 +++++++++++++++++++++++++++++++++++
 gdk/gdkcairocontext.h                |  47 ++++++++++++++++
 gdk/gdkcairocontextprivate.h         |  50 +++++++++++++++++
 gdk/gdkdrawingcontext.c              |   2 +-
 gdk/gdksurface.c                     |  40 ++++++++------
 gdk/gdksurface.h                     |   6 ++-
 gdk/gdktypes.h                       |   1 +
 gdk/meson.build                      |   2 +
 gsk/gskcairorenderer.c               |  15 +++++-
 11 files changed, 252 insertions(+), 22 deletions(-)
---
diff --git a/docs/reference/gdk/gdk4-sections.txt b/docs/reference/gdk/gdk4-sections.txt
index a6bcd8b82a..2cc4563ce8 100644
--- a/docs/reference/gdk/gdk4-sections.txt
+++ b/docs/reference/gdk/gdk4-sections.txt
@@ -1201,6 +1201,14 @@ GDK_DRAWING_CONTEXT
 GDK_IS_DRAWING_CONTEXT
 </SECTION>
 
+<SECTION>
+<FILE>gdkcairocontext</FILE>
+GdkCairoContext
+
+<SUBSECTION Standard>
+gdk_cairo_context_get_type
+</SECTION>
+
 <SECTION>
 <FILE>gdkvulkancontext</FILE>
 GdkVulkanContext
diff --git a/gdk/gdk.h b/gdk/gdk.h
index 921e93690d..8311ef23bd 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -31,6 +31,7 @@
 #include <gdk/gdkversionmacros.h>
 #include <gdk/gdkapplaunchcontext.h>
 #include <gdk/gdkcairo.h>
+#include <gdk/gdkcairocontext.h>
 #include <gdk/gdkclipboard.h>
 #include <gdk/gdkcontentdeserializer.h>
 #include <gdk/gdkcontentformats.h>
diff --git a/gdk/gdkcairocontext.c b/gdk/gdkcairocontext.c
new file mode 100644
index 0000000000..281ef501e2
--- /dev/null
+++ b/gdk/gdkcairocontext.c
@@ -0,0 +1,102 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * gdkcairocontext.c: Cairo wrappers
+ *
+ * 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 "gdkcairocontext.h"
+
+#include "gdkcairocontextprivate.h"
+
+#include "gdkdisplayprivate.h"
+#include "gdkinternals.h"
+#include "gdkintl.h"
+
+/**
+ * SECTION:gdkcairocontext
+ * @Title: GdkCairoContext
+ * @Short_description: Cairo draw context
+ *
+ * #GdkCairoContext is an object representing the platform-specific
+ * draw context.
+ *
+ * #GdkCairoContexts are created for a #GdkDisplay using
+ * gdk_surface_create_cairo_context(), and the context can then be used
+ * to draw on that #GdkSurface.
+ */
+
+/**
+ * GdkCairoContext:
+ *
+ * The GdkCairoContext struct contains only private fields and should not
+ * be accessed directly.
+ */
+
+typedef struct _GdkCairoContextPrivate GdkCairoContextPrivate;
+
+struct _GdkCairoContextPrivate {
+  gpointer unused;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GdkCairoContext, gdk_cairo_context, GDK_TYPE_DRAW_CONTEXT,
+                         G_ADD_PRIVATE (GdkCairoContext))
+
+void
+gdk_surface_begin_paint_internal (GdkSurface            *surface,
+                                  const cairo_region_t *region);
+
+static void
+gdk_cairo_context_begin_frame (GdkDrawContext *draw_context,
+                               cairo_region_t *region)
+{
+  gdk_surface_begin_paint_internal (gdk_draw_context_get_surface (draw_context),
+                                    region);
+}
+
+void
+gdk_surface_end_paint_internal (GdkSurface *surface);
+
+static void
+gdk_cairo_context_end_frame (GdkDrawContext *draw_context,
+                             cairo_region_t *painted,
+                             cairo_region_t *damage)
+{
+  gdk_surface_end_paint_internal (gdk_draw_context_get_surface (draw_context));
+}
+
+static void
+gdk_cairo_context_surface_resized (GdkDrawContext *draw_context)
+{
+}
+
+static void
+gdk_cairo_context_class_init (GdkCairoContextClass *klass)
+{
+  GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
+
+  draw_context_class->begin_frame = gdk_cairo_context_begin_frame;
+  draw_context_class->end_frame = gdk_cairo_context_end_frame;
+  draw_context_class->surface_resized = gdk_cairo_context_surface_resized;
+}
+
+static void
+gdk_cairo_context_init (GdkCairoContext *self)
+{
+}
+
diff --git a/gdk/gdkcairocontext.h b/gdk/gdkcairocontext.h
new file mode 100644
index 0000000000..0d2948a262
--- /dev/null
+++ b/gdk/gdkcairocontext.h
@@ -0,0 +1,47 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * gdkcairocontext.h:  specific Cairo wrappers
+ *
+ * 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_CAIRO_CONTEXT__
+#define __GDK_CAIRO_CONTEXT__
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#include <gdk/gdkversionmacros.h>
+#include <gdk/gdktypes.h>
+
+#include <cairo/cairo.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_CAIRO_CONTEXT             (gdk_cairo_context_get_type ())
+#define GDK_CAIRO_CONTEXT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CAIRO_CONTEXT, 
GdkCairoContext))
+#define GDK_IS_CAIRO_CONTEXT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CAIRO_CONTEXT))
+
+#define GDK_CAIRO_ERROR                    (gdk_cairo_error_quark ())
+
+GDK_AVAILABLE_IN_ALL
+GType                   gdk_cairo_context_get_type                      (void) G_GNUC_CONST;
+
+
+G_END_DECLS
+
+#endif /* __GDK_CAIRO_CONTEXT__ */
diff --git a/gdk/gdkcairocontextprivate.h b/gdk/gdkcairocontextprivate.h
new file mode 100644
index 0000000000..66cc3223eb
--- /dev/null
+++ b/gdk/gdkcairocontextprivate.h
@@ -0,0 +1,50 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * gdkcairocontextprivate.h: specific Cairo wrappers
+ *
+ * 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_CAIRO_CONTEXT_PRIVATE__
+#define __GDK_CAIRO_CONTEXT_PRIVATE__
+
+#include "gdkcairocontext.h"
+
+#include "gdkdrawcontextprivate.h"
+
+#include <cairo/cairo.h>
+
+G_BEGIN_DECLS
+
+#define GDK_CAIRO_CONTEXT_CLASS(klass)                 (G_TYPE_CHECK_CLASS_CAST ((klass), 
GDK_TYPE_CAIRO_CONTEXT, GdkCairoContextClass))
+#define GDK_IS_CAIRO_CONTEXT_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CAIRO_CONTEXT))
+#define GDK_CAIRO_CONTEXT_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CAIRO_CONTEXT, 
GdkCairoContextClass))
+
+typedef struct _GdkCairoContextClass GdkCairoContextClass;
+
+struct _GdkCairoContext
+{
+  GdkDrawContext parent_instance;
+};
+
+struct _GdkCairoContextClass
+{
+  GdkDrawContextClass parent_class;
+};
+
+G_END_DECLS
+
+#endif /* __GDK__CAIRO_CONTEXT_PRIVATE__ */
diff --git a/gdk/gdkdrawingcontext.c b/gdk/gdkdrawingcontext.c
index 57740eeb34..70569ba9cf 100644
--- a/gdk/gdkdrawingcontext.c
+++ b/gdk/gdkdrawingcontext.c
@@ -232,7 +232,7 @@ gdk_drawing_context_get_cairo_context (GdkDrawingContext *context)
   g_return_val_if_fail (GDK_IS_DRAWING_CONTEXT (context), NULL);
   g_return_val_if_fail (GDK_IS_SURFACE (priv->surface), NULL);
 
-  if (priv->paint_context != NULL)
+  if (!GDK_IS_CAIRO_CONTEXT (priv->paint_context))
     return NULL;
 
   if (priv->cr == NULL)
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index ed769e215e..a818fb2d7d 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -1496,7 +1496,7 @@ gdk_surface_get_paint_gl_context (GdkSurface  *surface,
  * %NULL on error
  **/
 GdkGLContext *
-gdk_surface_create_gl_context (GdkSurface    *surface,
+gdk_surface_create_gl_context (GdkSurface   *surface,
                                GError      **error)
 {
   GdkGLContext *paint_context;
@@ -1509,9 +1509,17 @@ gdk_surface_create_gl_context (GdkSurface    *surface,
     return NULL;
 
   return GDK_SURFACE_IMPL_GET_CLASS (surface->impl)->create_gl_context (surface->impl_surface,
-                                                                      FALSE,
-                                                                      paint_context,
-                                                                      error);
+                                                                        FALSE,
+                                                                        paint_context,
+                                                                        error);
+}
+
+GdkCairoContext *
+gdk_surface_create_cairo_context (GdkSurface *surface)
+{
+  return g_object_new (GDK_TYPE_CAIRO_CONTEXT,
+                       "surface", surface,
+                       NULL);
 }
 
 /**
@@ -1558,7 +1566,10 @@ gdk_surface_create_vulkan_context (GdkSurface  *surface,
                          NULL);
 }
 
-static void
+void
+gdk_surface_begin_paint_internal (GdkSurface            *surface,
+                                  const cairo_region_t *region);
+void
 gdk_surface_begin_paint_internal (GdkSurface            *surface,
                                   const cairo_region_t *region)
 {
@@ -1609,7 +1620,9 @@ gdk_surface_begin_paint_internal (GdkSurface            *surface,
     gdk_surface_clear_backing_region (surface);
 }
 
-static void
+void
+gdk_surface_end_paint_internal (GdkSurface *surface);
+void
 gdk_surface_end_paint_internal (GdkSurface *surface)
 {
   GdkSurfaceImplClass *impl_class;
@@ -1688,7 +1701,7 @@ gdk_surface_end_paint_internal (GdkSurface *surface)
  *   by GDK.
  */
 GdkDrawingContext *
-gdk_surface_begin_draw_frame (GdkSurface            *surface,
+gdk_surface_begin_draw_frame (GdkSurface           *surface,
                               GdkDrawContext       *draw_context,
                               const cairo_region_t *region)
 {
@@ -1698,12 +1711,9 @@ gdk_surface_begin_draw_frame (GdkSurface            *surface,
   g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
   g_return_val_if_fail (gdk_surface_has_native (surface), NULL);
   g_return_val_if_fail (gdk_surface_is_toplevel (surface), NULL);
+  g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (draw_context), NULL);
+  g_return_val_if_fail (gdk_draw_context_get_surface (draw_context) == surface, NULL);
   g_return_val_if_fail (region != NULL, NULL);
-  if (draw_context != NULL)
-    {
-      g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (draw_context), NULL);
-      g_return_val_if_fail (gdk_draw_context_get_surface (draw_context) == surface, NULL);
-    }
 
   if (GDK_SURFACE_DESTROYED (surface))
     return NULL;
@@ -1718,10 +1728,7 @@ gdk_surface_begin_draw_frame (GdkSurface            *surface,
 
   real_region = cairo_region_copy (region);
 
-  if (draw_context)
-    gdk_draw_context_begin_frame (draw_context, real_region);
-  else
-    gdk_surface_begin_paint_internal (surface, real_region);
+  gdk_draw_context_begin_frame (draw_context, real_region);
 
   context = g_object_new (GDK_TYPE_DRAWING_CONTEXT,
                           "surface", surface,
@@ -1784,7 +1791,6 @@ gdk_surface_end_draw_frame (GdkSurface         *surface,
     }
   else
     {
-      gdk_surface_end_paint_internal (surface);
     }
 
   surface->drawing_context = NULL;
diff --git a/gdk/gdksurface.h b/gdk/gdksurface.h
index e333608a99..3775f20d5d 100644
--- a/gdk/gdksurface.h
+++ b/gdk/gdksurface.h
@@ -843,11 +843,13 @@ gboolean  gdk_surface_show_window_menu          (GdkSurface      *surface,
                                                  GdkEvent       *event);
 
 GDK_AVAILABLE_IN_ALL
-GdkGLContext * gdk_surface_create_gl_context    (GdkSurface      *surface,
+GdkCairoContext *gdk_surface_create_cairo_context(GdkSurface    *surface);
+GDK_AVAILABLE_IN_ALL
+GdkGLContext * gdk_surface_create_gl_context    (GdkSurface     *surface,
                                                  GError        **error);
 GDK_AVAILABLE_IN_ALL
 GdkVulkanContext *
-               gdk_surface_create_vulkan_context(GdkSurface      *surface,
+               gdk_surface_create_vulkan_context(GdkSurface     *surface,
                                                  GError        **error);
 
 G_END_DECLS
diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h
index d4e3623309..f2081c1536 100644
--- a/gdk/gdktypes.h
+++ b/gdk/gdktypes.h
@@ -136,6 +136,7 @@ typedef struct _GdkSnapshot           GdkSnapshot;
 
 typedef struct _GdkDrawingContext     GdkDrawingContext;
 typedef struct _GdkDrawContext        GdkDrawContext;
+typedef struct _GdkCairoContext       GdkCairoContext;
 typedef struct _GdkGLContext          GdkGLContext;
 typedef struct _GdkVulkanContext      GdkVulkanContext;
 
diff --git a/gdk/meson.build b/gdk/meson.build
index d801d7592a..0f22b2fe39 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -2,6 +2,7 @@ gdk_public_sources = files([
   'gdk.c',
   'gdkapplaunchcontext.c',
   'gdkcairo.c',
+  'gdkcairocontext.c',
   'gdkclipboard.c',
   'gdkcontentdeserializer.c',
   'gdkcontentformats.c',
@@ -51,6 +52,7 @@ gdk_public_headers = files([
   'gdk.h',
   'gdkapplaunchcontext.h',
   'gdkcairo.h',
+  'gdkcairocontext.h',
   'gdkclipboard.h',
   'gdkcontentdeserializer.h',
   'gdkcontentformats.h',
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
index 5cf3d7822d..f5871e49a8 100644
--- a/gsk/gskcairorenderer.c
+++ b/gsk/gskcairorenderer.c
@@ -18,6 +18,8 @@ struct _GskCairoRenderer
 {
   GskRenderer parent_instance;
 
+  GdkCairoContext *cairo_context;
+
 #ifdef G_ENABLE_DEBUG
   ProfileTimers profile_timers;
 #endif
@@ -32,16 +34,22 @@ G_DEFINE_TYPE (GskCairoRenderer, gsk_cairo_renderer, GSK_TYPE_RENDERER)
 
 static gboolean
 gsk_cairo_renderer_realize (GskRenderer  *renderer,
-                            GdkSurface    *surface,
+                            GdkSurface   *surface,
                             GError      **error)
 {
+  GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
+
+  self->cairo_context = gdk_surface_create_cairo_context (surface);
+
   return TRUE;
 }
 
 static void
 gsk_cairo_renderer_unrealize (GskRenderer *renderer)
 {
+  GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
 
+  g_clear_object (&self->cairo_context);
 }
 
 static void
@@ -99,11 +107,14 @@ gsk_cairo_renderer_render (GskRenderer          *renderer,
                            GskRenderNode        *root,
                            const cairo_region_t *region)
 {
+  GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
   GdkSurface *surface = gsk_renderer_get_surface (renderer);
   GdkDrawingContext *context;
   cairo_t *cr;
 
-  context = gdk_surface_begin_draw_frame (surface, NULL, region);
+  context = gdk_surface_begin_draw_frame (surface,
+                                          GDK_DRAW_CONTEXT (self->cairo_context),
+                                          region);
   cr = gdk_drawing_context_get_cairo_context (context);
 
   g_return_if_fail (cr != NULL);


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