gtk/gdk/gdkdrawcontext.c
Matthias Clasen 4c150d8eb5 The big versioning cleanup
Remove all the old 2.x and 3.x version annotations.
GTK+ 4 is a new start, and from the perspective of a
GTK+ 4 developer all these APIs have been around since
the beginning.
2018-02-06 01:16:32 -05:00

281 lines
7.8 KiB
C

/* GDK - The GIMP Drawing Kit
*
* gdkdrawcontext.c: base class for rendering system support
*
* Copyright © 2016 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 "gdkdrawcontextprivate.h"
#include "gdkinternals.h"
#include "gdkintl.h"
/**
* SECTION:gdkdrawcontext
* @Title: GdkDrawContext
* @Short_description: Base class for draw contexts
*
* #GdkDrawContext is the base object used by contexts implementing different
* rendering methods, such as #GdkGLContext or #GdkVulkanContext. It provides
* shared functionality between those contexts.
*
* You will always interact with one of those s.ubclasses.
*
* A GdkDrawContext is always associated with a single toplevel window.
*/
/**
* GdkDrawContext:
*
* The GdkDrawContext struct contains only private fields and should not
* be accessed directly.
*/
typedef struct _GdkDrawContextPrivate GdkDrawContextPrivate;
struct _GdkDrawContextPrivate {
GdkWindow *window;
guint is_drawing : 1;
};
enum {
PROP_0,
PROP_DISPLAY,
PROP_WINDOW,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP] = { NULL, };
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkDrawContext, gdk_draw_context, G_TYPE_OBJECT)
static void
gdk_draw_context_dispose (GObject *gobject)
{
GdkDrawContext *context = GDK_DRAW_CONTEXT (gobject);
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
g_clear_object (&priv->window);
G_OBJECT_CLASS (gdk_draw_context_parent_class)->dispose (gobject);
}
static void
gdk_draw_context_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkDrawContext *context = GDK_DRAW_CONTEXT (gobject);
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
switch (prop_id)
{
case PROP_WINDOW:
priv->window = g_value_dup_object (value);
g_assert (priv->window != NULL);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
gdk_draw_context_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkDrawContext *context = GDK_DRAW_CONTEXT (gobject);
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, gdk_draw_context_get_display (context));
break;
case PROP_WINDOW:
g_value_set_object (value, priv->window);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
gdk_draw_context_class_init (GdkDrawContextClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gdk_draw_context_set_property;
gobject_class->get_property = gdk_draw_context_get_property;
gobject_class->dispose = gdk_draw_context_dispose;
/**
* GdkDrawContext:display:
*
* The #GdkDisplay used to create the #GdkDrawContext.
*/
pspecs[PROP_DISPLAY] =
g_param_spec_object ("display",
P_("Display"),
P_("The GDK display used to create the context"),
GDK_TYPE_DISPLAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
/**
* GdkDrawContext:window:
*
* The #GdkWindow the gl context is bound to.
*/
pspecs[PROP_WINDOW] =
g_param_spec_object ("window",
P_("Window"),
P_("The GDK window bound to the context"),
GDK_TYPE_WINDOW,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, LAST_PROP, pspecs);
}
static void
gdk_draw_context_init (GdkDrawContext *self)
{
}
/*< private >
* gdk_draw_context_is_drawing:
* @context: a #GdkDrawContext
*
* Returns %TRUE if @context is in the process of drawing to its window. In such
* cases, it will have access to the window's backbuffer to render the new frame
* onto it.
*
* Returns: %TRUE if the context is between begin_frame() and end_frame() calls.
*/
gboolean
gdk_draw_context_is_drawing (GdkDrawContext *context)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
return priv->is_drawing;
}
/*< private >
* gdk_draw_context_begin_frame:
* @context: a #GdkDrawContext
* @region: (inout): The clip region that needs to be repainted
*
* Sets up @context and @drawing for a new drawing.
*
* The @context is free to update @region to the size that actually needs to
* be repainted. Contexts that do not support partial blits for example may
* want to invalidate the whole window instead.
*
* The function does not clear the background. Clearing the backgroud is the
* job of the renderer. The contents of the backbuffer are undefined after this
* function call.
*/
void
gdk_draw_context_begin_frame (GdkDrawContext *context,
cairo_region_t *region)
{
GdkDrawContextPrivate *priv;
g_return_if_fail (GDK_IS_DRAW_CONTEXT (context));
g_return_if_fail (region != NULL);
priv = gdk_draw_context_get_instance_private (context);
priv->is_drawing = TRUE;
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, region);
}
/*< private >
* gdk_draw_context_end_frame:
* @context: a #GdkDrawContext
* @painted: The area that has been redrawn this frame
* @damage: The area that we know is actually different from the last frame
*
* Copies the back buffer to the front buffer.
*
* This function may call `glFlush()` implicitly before returning; it
* is not recommended to call `glFlush()` explicitly before calling
* this function.
*/
void
gdk_draw_context_end_frame (GdkDrawContext *context,
cairo_region_t *painted,
cairo_region_t *damage)
{
GdkDrawContextPrivate *priv;
g_return_if_fail (GDK_IS_DRAW_CONTEXT (context));
GDK_DRAW_CONTEXT_GET_CLASS (context)->end_frame (context, painted, damage);
priv = gdk_draw_context_get_instance_private (context);
priv->is_drawing = FALSE;
}
/**
* gdk_draw_context_get_display:
* @context: a #GdkDrawContext
*
* Retrieves the #GdkDisplay the @context is created for
*
* Returns: (nullable) (transfer none): a #GdkDisplay or %NULL
*/
GdkDisplay *
gdk_draw_context_get_display (GdkDrawContext *context)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (context), NULL);
return priv->window ? gdk_window_get_display (priv->window) : NULL;
}
/**
* gdk_draw_context_get_window:
* @context: a #GdkDrawContext
*
* Retrieves the #GdkWindow used by the @context.
*
* Returns: (nullable) (transfer none): a #GdkWindow or %NULL
*/
GdkWindow *
gdk_draw_context_get_window (GdkDrawContext *context)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (context), NULL);
return priv->window;
}