From f3967860519981b30a01268d6fb459ba1a79d624 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 12 Apr 2018 00:16:43 +0200 Subject: [PATCH] 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(-) create mode 100644 gdk/gdkcairocontext.c create mode 100644 gdk/gdkcairocontext.h create mode 100644 gdk/gdkcairocontextprivate.h 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 +
+gdkcairocontext +GdkCairoContext + + +gdk_cairo_context_get_type +
+
gdkvulkancontext 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 #include #include +#include #include #include #include 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 . + */ + +#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 . + */ + +#ifndef __GDK_CAIRO_CONTEXT__ +#define __GDK_CAIRO_CONTEXT__ + +#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only can be included directly." +#endif + +#include +#include + +#include + +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 . + */ + +#ifndef __GDK_CAIRO_CONTEXT_PRIVATE__ +#define __GDK_CAIRO_CONTEXT_PRIVATE__ + +#include "gdkcairocontext.h" + +#include "gdkdrawcontextprivate.h" + +#include + +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);