[gtk+/wip/ebassi/frame-marker: 3/3] Add GdkDrawingContext
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/ebassi/frame-marker: 3/3] Add GdkDrawingContext
- Date: Fri, 3 Jun 2016 15:19:51 +0000 (UTC)
commit e4fd3fbb5581a61e7781b78d98dd9d688cd6399e
Author: Emmanuele Bassi <ebassi gnome org>
Date: Mon May 30 09:44:30 2016 +0100
Add GdkDrawingContext
Instead of giving out Cairo contexts, GdkWindow should provide a
"drawing context", which can then create Cairo contexts on demand; this
allows us to future proof the API for when we're going to use a
different rendering pipeline, like OpenGL.
https://bugzilla.gnome.org/show_bug.cgi?id=766675
gdk/Makefile.am | 3 ++
gdk/gdk.h | 1 +
gdk/gdkdrawingcontext.c | 71 ++++++++++++++++++++++++++++++++++++++++
gdk/gdkdrawingcontext.h | 44 ++++++++++++++++++++++++
gdk/gdkdrawingcontextprivate.h | 31 +++++++++++++++++
gdk/gdkwindow.c | 49 ++++++++++++++++++---------
gdk/gdkwindow.h | 7 ++--
gdk/gdkwindowimpl.h | 5 +++
gtk/gtkwidget.c | 6 ++-
9 files changed, 195 insertions(+), 22 deletions(-)
---
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index 16230cb..91da7bd 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -75,6 +75,7 @@ gdk_public_h_sources = \
gdkdisplay.h \
gdkdisplaymanager.h \
gdkdnd.h \
+ gdkdrawingcontext.h \
gdkevents.h \
gdkframetimings.h \
gdkglcontext.h \
@@ -116,6 +117,7 @@ gdk_private_headers = \
gdkdisplaymanagerprivate.h \
gdkdisplayprivate.h \
gdkdndprivate.h \
+ gdkdrawingcontextprivate.h \
gdkframeclockidle.h \
gdkframeclockprivate.h \
gdkglcontextprivate.h \
@@ -146,6 +148,7 @@ gdk_c_sources = \
gdkdisplay.c \
gdkdisplaymanager.c \
gdkdnd.c \
+ gdkdrawingcontext.c \
gdkevents.c \
gdkframetimings.c \
gdkgl.c \
diff --git a/gdk/gdk.h b/gdk/gdk.h
index 4631c52..92bafe1 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -38,6 +38,7 @@
#include <gdk/gdkdisplay.h>
#include <gdk/gdkdisplaymanager.h>
#include <gdk/gdkdnd.h>
+#include <gdk/gdkdrawingcontext.h>
#include <gdk/gdkenumtypes.h>
#include <gdk/gdkevents.h>
#include <gdk/gdkframeclock.h>
diff --git a/gdk/gdkdrawingcontext.c b/gdk/gdkdrawingcontext.c
new file mode 100644
index 0000000..32adc62
--- /dev/null
+++ b/gdk/gdkdrawingcontext.c
@@ -0,0 +1,71 @@
+#include "config.h"
+
+#include <cairo-gobject.h>
+
+#include "gdkdrawingcontextprivate.h"
+
+#include "gdkrectangle.h"
+#include "gdkinternals.h"
+#include "gdkintl.h"
+#include "gdkframeclockidle.h"
+#include "gdkwindowimpl.h"
+#include "gdkglcontextprivate.h"
+#include "gdk-private.h"
+
+G_DEFINE_TYPE (GdkDrawingContext, gdk_drawing_context, G_TYPE_OBJECT)
+
+static void
+gdk_drawing_context_dispose (GObject *gobject)
+{
+ GdkDrawingContext *self = GDK_DRAWING_CONTEXT (gobject);
+
+ g_clear_object (&self->window);
+ g_clear_pointer (&self->clip, cairo_region_destroy);
+ g_clear_pointer (&self->cr, cairo_destroy);
+
+ G_OBJECT_CLASS (gdk_drawing_context_parent_class)->dispose (gobject);
+}
+
+static void
+gdk_drawing_context_class_init (GdkDrawingContextClass *klass)
+{
+ G_OBJECT_CLASS (klass)->dispose = gdk_drawing_context_dispose;
+}
+
+static void
+gdk_drawing_context_init (GdkDrawingContext *self)
+{
+}
+
+/**
+ * gdk_drawing_context_get_cairo_context:
+ * @context:
+ *
+ * Retrieves a Cairo context to be used to draw on the #GdkWindow
+ * that created the #GdkDrawingContext.
+ *
+ * The returned context is guaranteed to be valid as long as the
+ * #GdkDrawingContext is valid, that is between a call to
+ * gdk_window_begin_draw_frame() and gdk_window_end_draw_frame().
+ *
+ * Returns: (transfer none): a Cairo context to be used to draw
+ * the contents of the #GdkWindow. The context is owned by the
+ * #GdkDrawingContext and should not be destroyed
+ *
+ * Since: 3.22
+ */
+cairo_t *
+gdk_drawing_context_get_cairo_context (GdkDrawingContext *context)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (GDK_WINDOW (context->window), NULL);
+
+ if (context->cr == NULL)
+ {
+ context->cr = gdk_cairo_create (context->window);
+ gdk_cairo_region (context->cr, context->clip);
+ cairo_clip (context->cr);
+ }
+
+ return context->cr;
+}
diff --git a/gdk/gdkdrawingcontext.h b/gdk/gdkdrawingcontext.h
new file mode 100644
index 0000000..21e2095
--- /dev/null
+++ b/gdk/gdkdrawingcontext.h
@@ -0,0 +1,44 @@
+/* GDK - The GIMP Drawing Kit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_DRAWING_CONTEXT_H__
+#define __GDK_DRAWING_CONTEXT_H__
+
+#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>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_DRAWING_CONTEXT (gdk_drawing_context_get_type ())
+
+#define GDK_DRAWING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_DRAWING_CONTEXT,
GdkDrawingContext))
+#define GDK_IS_DRAWING_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_DRAWING_CONTEXT))
+
+typedef struct _GdkDrawingContext GdkDrawingContext;
+
+GDK_AVAILABLE_IN_3_22
+GType gdk_drawing_context_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_22
+cairo_t * gdk_drawing_context_get_cairo_context (GdkDrawingContext *context);
+
+G_END_DECLS
+
+#endif /* __GDK_DRAWING_CONTEXT_H__ */
diff --git a/gdk/gdkdrawingcontextprivate.h b/gdk/gdkdrawingcontextprivate.h
new file mode 100644
index 0000000..e8663c9
--- /dev/null
+++ b/gdk/gdkdrawingcontextprivate.h
@@ -0,0 +1,31 @@
+#ifndef __GDK_DRAWING_CONTEXT_PRIVATE_H__
+#define __GDK_DRAWING_CONTEXT_PRIVATE_H__
+
+#include "gdkdrawingcontext.h"
+
+G_BEGIN_DECLS
+
+#define GDK_DRAWING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAWING_CONTEXT,
GdkDrawingContextClass))
+#define GDK_IS_DRAWING_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAWING_CONTEXT))
+#define GDK_DRAWING_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAWING_CONTEXT,
GdkDrawingContextClass))
+
+typedef struct _GdkDrawingContextClass GdkDrawingContextClass;
+
+struct _GdkDrawingContext
+{
+ GObject parent_instance;
+
+ GdkWindow *window;
+
+ cairo_region_t *clip;
+ cairo_t *cr;
+};
+
+struct _GdkDrawingContextClass
+{
+ GObjectClass parent_instance;
+};
+
+G_END_DECLS
+
+#endif /* __GDK_DRAWING_CONTEXT_PRIVATE_H__ */
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 81862c5..48cba0e 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -40,6 +40,7 @@
#include "gdkframeclockidle.h"
#include "gdkwindowimpl.h"
#include "gdkglcontextprivate.h"
+#include "gdkdrawingcontextprivate.h"
#include "gdk-private.h"
#include <math.h>
@@ -3174,7 +3175,7 @@ gdk_window_should_draw (GdkWindow *window,
* @region: a Cairo region
*
* Indicates that you are beginning the process of redrawing @region
- * on @window, and provides you with a Cairo context for drawing.
+ * on @window, and provides you with a #GdkDrawingContext.
*
* If @window is a top level #GdkWindow, backed by a native window
* implementation, a backing store (offscreen buffer) large enough to
@@ -3201,40 +3202,46 @@ gdk_window_should_draw (GdkWindow *window,
* code in GTK does not need to call gdk_window_begin_draw_frame()
* explicitly.
*
- * Returns: (transfer none): a Cairo context that should be used to
- * draw the contents of the window; the returned context is owned
- * by GDK and should not be destroyed directly
+ * Returns: (transfer none): a #GdkDrawingContext context that should be
+ * used to draw the contents of the window; the returned context is owned
+ * by GDK.
*
* Since: 3.22
*/
-cairo_t *
+GdkDrawingContext *
gdk_window_begin_draw_frame (GdkWindow *window,
const cairo_region_t *region)
{
- cairo_t *retval;
+ GdkDrawingContext *context;
+ GdkWindowImplClass *impl_class;
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
if (gdk_window_has_native (window) && gdk_window_is_toplevel (window))
gdk_window_begin_paint_internal (window, region);
- retval = gdk_cairo_create (window);
-
- gdk_cairo_region (retval, region);
- cairo_clip (retval);
+ impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+ if (impl_class->create_draw_context != NULL)
+ context = impl_class->create_draw_context (window, region);
+ else
+ {
+ context = g_object_new (GDK_TYPE_DRAWING_CONTEXT, NULL);
+ context->window = g_object_ref (window);
+ context->clip = cairo_region_copy (region);
+ }
- return retval;
+ return context;
}
/**
* gdk_window_end_draw_frame:
* @window: a #GdkWindow
- * @cr: the Cairo context created by gdk_window_begin_draw_frame()
+ * @context: the #GdkDrawingContext created by gdk_window_begin_draw_frame()
*
* Indicates that the drawing of the contents of @window started with
* gdk_window_begin_frame() has been completed.
*
- * This function will take care of destroying the Cairo context.
+ * This function will take care of destroying the #GdkDrawingContext.
*
* It is an error to call this function without a matching
* gdk_window_begin_frame() first.
@@ -3242,14 +3249,22 @@ gdk_window_begin_draw_frame (GdkWindow *window,
* Since: 3.22
*/
void
-gdk_window_end_draw_frame (GdkWindow *window,
- cairo_t *cr)
+gdk_window_end_draw_frame (GdkWindow *window,
+ GdkDrawingContext *context)
{
+ GdkWindowImplClass *impl_class;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
+
if (gdk_window_has_native (window) && gdk_window_is_toplevel (window))
gdk_window_end_paint_internal (window);
- gdk_cairo_set_window (cr, NULL);
- cairo_destroy (cr);
+ impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+ if (impl_class->destroy_draw_context != NULL)
+ impl_class->destroy_draw_context (window, context);
+ else
+ g_object_unref (context);
}
/**
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 6930f9b..1ff6977 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -31,6 +31,7 @@
#include <gdk/gdkversionmacros.h>
#include <gdk/gdktypes.h>
+#include <gdk/gdkdrawingcontext.h>
#include <gdk/gdkevents.h>
#include <gdk/gdkframeclock.h>
@@ -706,11 +707,11 @@ GDK_AVAILABLE_IN_ALL
void gdk_window_end_paint (GdkWindow *window);
GDK_AVAILABLE_IN_3_22
-cairo_t * gdk_window_begin_draw_frame (GdkWindow *window,
- const cairo_region_t *region);
+GdkDrawingContext *gdk_window_begin_draw_frame (GdkWindow *window,
+ const cairo_region_t *region);
GDK_AVAILABLE_IN_3_22
void gdk_window_end_draw_frame (GdkWindow *window,
- cairo_t *cr);
+ GdkDrawingContext *cr);
GDK_AVAILABLE_IN_3_22
gboolean gdk_window_should_draw (GdkWindow *window,
cairo_t *cr);
diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h
index f074343..4ccdc67 100644
--- a/gdk/gdkwindowimpl.h
+++ b/gdk/gdkwindowimpl.h
@@ -303,6 +303,11 @@ struct _GdkWindowImplClass
GError **error);
void (*invalidate_for_new_frame)(GdkWindow *window,
cairo_region_t *update_area);
+
+ GdkDrawingContext *(* create_draw_context) (GdkWindow *window,
+ const cairo_region_t *region);
+ void (* destroy_draw_context) (GdkWindow *window,
+ GdkDrawingContext *context);
};
/* Interface Functions */
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 35cedb3..57475ca 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -17431,6 +17431,7 @@ gtk_widget_render (GtkWidget *widget,
const cairo_region_t *region)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+ GdkDrawingContext *context;
gboolean do_clip;
cairo_t *cr;
int x, y;
@@ -17442,12 +17443,13 @@ gtk_widget_render (GtkWidget *widget,
return;
}
- cr = gdk_window_begin_draw_frame (window, region);
+ context = gdk_window_begin_draw_frame (window, region);
+ cr = gdk_drawing_context_get_cairo_context (context);
do_clip = _gtk_widget_get_translation_to_window (widget, window, &x, &y);
cairo_translate (cr, -x, -y);
gtk_widget_draw_internal (widget, cr, do_clip);
- gdk_window_end_draw_frame (window, cr);
+ gdk_window_end_draw_frame (window, context);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]