mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 13:41:07 +00:00
b8a92dfa0e
Using GObject as the base type for a transient tree may prove to be too intensive, especially when creating a lot of node instances. Since we don't need properties or signals, and we don't need complex destruction semantics, we can use GTypeInstance directly as the base type for GskRenderNode.
1075 lines
28 KiB
C
1075 lines
28 KiB
C
/* GSK - The GTK Scene Kit
|
|
*
|
|
* Copyright 2016 Endless
|
|
*
|
|
* 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/>.
|
|
*/
|
|
|
|
/**
|
|
* SECTION:GskRenderer
|
|
* @title: GskRenderer
|
|
* @Short_desc: Renders a scene with a simplified graph
|
|
*
|
|
* TODO
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gskrendererprivate.h"
|
|
|
|
#include "gskdebugprivate.h"
|
|
#include "gskglrendererprivate.h"
|
|
#include "gskrendernodeprivate.h"
|
|
|
|
#include "gskenumtypes.h"
|
|
|
|
#include <graphene-gobject.h>
|
|
#include <cairo-gobject.h>
|
|
#include <gdk/gdk.h>
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
#include <gdk/x11/gdkx.h>
|
|
#endif
|
|
#ifdef GDK_WINDOWING_WAYLAND
|
|
#include <gdk/wayland/gdkwayland.h>
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
GObject parent_instance;
|
|
|
|
graphene_rect_t viewport;
|
|
graphene_matrix_t modelview;
|
|
graphene_matrix_t projection;
|
|
|
|
GskScalingFilter min_filter;
|
|
GskScalingFilter mag_filter;
|
|
|
|
GdkWindow *window;
|
|
GdkDrawingContext *drawing_context;
|
|
GskRenderNode *root_node;
|
|
GdkDisplay *display;
|
|
|
|
int scale_factor;
|
|
|
|
gboolean is_realized : 1;
|
|
gboolean auto_clear : 1;
|
|
gboolean use_alpha : 1;
|
|
} GskRendererPrivate;
|
|
|
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GskRenderer, gsk_renderer, G_TYPE_OBJECT)
|
|
|
|
enum {
|
|
PROP_VIEWPORT = 1,
|
|
PROP_MODELVIEW,
|
|
PROP_PROJECTION,
|
|
PROP_MINIFICATION_FILTER,
|
|
PROP_MAGNIFICATION_FILTER,
|
|
PROP_AUTO_CLEAR,
|
|
PROP_USE_ALPHA,
|
|
PROP_SCALE_FACTOR,
|
|
PROP_WINDOW,
|
|
PROP_DISPLAY,
|
|
PROP_DRAWING_CONTEXT,
|
|
|
|
N_PROPS
|
|
};
|
|
|
|
static GParamSpec *gsk_renderer_properties[N_PROPS];
|
|
|
|
#define GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \
|
|
g_critical ("Renderer of type '%s' does not implement GskRenderer::" # method, G_OBJECT_TYPE_NAME (obj))
|
|
|
|
static gboolean
|
|
gsk_renderer_real_realize (GskRenderer *self)
|
|
{
|
|
GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, realize);
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_real_unrealize (GskRenderer *self)
|
|
{
|
|
GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, unrealize);
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_real_render (GskRenderer *self,
|
|
GskRenderNode *root,
|
|
GdkDrawingContext *context)
|
|
{
|
|
GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, render);
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_dispose (GObject *gobject)
|
|
{
|
|
GskRenderer *self = GSK_RENDERER (gobject);
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
|
|
|
|
gsk_renderer_unrealize (self);
|
|
|
|
g_clear_object (&priv->window);
|
|
g_clear_object (&priv->display);
|
|
|
|
G_OBJECT_CLASS (gsk_renderer_parent_class)->dispose (gobject);
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_set_property (GObject *gobject,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GskRenderer *self = GSK_RENDERER (gobject);
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_VIEWPORT:
|
|
gsk_renderer_set_viewport (self, g_value_get_boxed (value));
|
|
break;
|
|
|
|
case PROP_MODELVIEW:
|
|
gsk_renderer_set_modelview (self, g_value_get_boxed (value));
|
|
break;
|
|
|
|
case PROP_PROJECTION:
|
|
gsk_renderer_set_projection (self, g_value_get_boxed (value));
|
|
break;
|
|
|
|
case PROP_MINIFICATION_FILTER:
|
|
gsk_renderer_set_scaling_filters (self, g_value_get_enum (value), priv->mag_filter);
|
|
break;
|
|
|
|
case PROP_MAGNIFICATION_FILTER:
|
|
gsk_renderer_set_scaling_filters (self, priv->min_filter, g_value_get_enum (value));
|
|
break;
|
|
|
|
case PROP_AUTO_CLEAR:
|
|
gsk_renderer_set_auto_clear (self, g_value_get_boolean (value));
|
|
break;
|
|
|
|
case PROP_USE_ALPHA:
|
|
gsk_renderer_set_use_alpha (self, g_value_get_boolean (value));
|
|
break;
|
|
|
|
case PROP_SCALE_FACTOR:
|
|
gsk_renderer_set_scale_factor (self, g_value_get_int (value));
|
|
break;
|
|
|
|
case PROP_WINDOW:
|
|
gsk_renderer_set_window (self, g_value_get_object (value));
|
|
break;
|
|
|
|
case PROP_DISPLAY:
|
|
/* Construct-only */
|
|
priv->display = g_value_dup_object (value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_get_property (GObject *gobject,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GskRenderer *self = GSK_RENDERER (gobject);
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_VIEWPORT:
|
|
g_value_set_boxed (value, &priv->viewport);
|
|
break;
|
|
|
|
case PROP_MODELVIEW:
|
|
g_value_set_boxed (value, &priv->modelview);
|
|
break;
|
|
|
|
case PROP_PROJECTION:
|
|
g_value_set_boxed (value, &priv->projection);
|
|
break;
|
|
|
|
case PROP_MINIFICATION_FILTER:
|
|
g_value_set_enum (value, priv->min_filter);
|
|
break;
|
|
|
|
case PROP_MAGNIFICATION_FILTER:
|
|
g_value_set_enum (value, priv->mag_filter);
|
|
break;
|
|
|
|
case PROP_AUTO_CLEAR:
|
|
g_value_set_boolean (value, priv->auto_clear);
|
|
break;
|
|
|
|
case PROP_USE_ALPHA:
|
|
g_value_set_boolean (value, priv->use_alpha);
|
|
break;
|
|
|
|
case PROP_SCALE_FACTOR:
|
|
g_value_set_int (value, priv->scale_factor);
|
|
break;
|
|
|
|
case PROP_WINDOW:
|
|
g_value_set_object (value, priv->window);
|
|
break;
|
|
|
|
case PROP_DRAWING_CONTEXT:
|
|
g_value_set_object (value, priv->drawing_context);
|
|
break;
|
|
|
|
case PROP_DISPLAY:
|
|
g_value_set_object (value, priv->display);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_constructed (GObject *gobject)
|
|
{
|
|
GskRenderer *self = GSK_RENDERER (gobject);
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
|
|
|
|
if (priv->display == NULL)
|
|
{
|
|
GdkDisplayManager *manager = gdk_display_manager_get ();
|
|
|
|
priv->display = gdk_display_manager_get_default_display (manager);
|
|
g_assert (priv->display != NULL);
|
|
}
|
|
|
|
G_OBJECT_CLASS (gsk_renderer_parent_class)->constructed (gobject);
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_class_init (GskRendererClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
klass->realize = gsk_renderer_real_realize;
|
|
klass->unrealize = gsk_renderer_real_unrealize;
|
|
klass->render = gsk_renderer_real_render;
|
|
|
|
gobject_class->constructed = gsk_renderer_constructed;
|
|
gobject_class->set_property = gsk_renderer_set_property;
|
|
gobject_class->get_property = gsk_renderer_get_property;
|
|
gobject_class->dispose = gsk_renderer_dispose;
|
|
|
|
/**
|
|
* GskRenderer:viewport:
|
|
*
|
|
* The visible area used by the #GskRenderer to render its contents.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_VIEWPORT] =
|
|
g_param_spec_boxed ("viewport",
|
|
"Viewport",
|
|
"The visible area used by the renderer",
|
|
GRAPHENE_TYPE_RECT,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GskRenderer:modelview:
|
|
*
|
|
* The initial modelview matrix used by the #GskRenderer.
|
|
*
|
|
* If set to %NULL, the identity matrix:
|
|
*
|
|
* |[<!-- language="plain"
|
|
* | 1.0, 0.0, 0.0, 0.0 |
|
|
* | 0.0, 1.0, 0.0, 0.0 |
|
|
* | 0.0, 0.0, 1.0, 0.0 |
|
|
* | 0.0, 0.0, 0.0, 1.0 |
|
|
* ]|
|
|
*
|
|
* Is used instead.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_MODELVIEW] =
|
|
g_param_spec_boxed ("modelview",
|
|
"Modelview",
|
|
"The modelview matrix used by the renderer",
|
|
GRAPHENE_TYPE_MATRIX,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GskRenderer:projection:
|
|
*
|
|
* The projection matrix used by the #GskRenderer.
|
|
*
|
|
* If set to %NULL, the identity matrix:
|
|
*
|
|
* |[<!-- language="plain"
|
|
* | 1.0, 0.0, 0.0, 0.0 |
|
|
* | 0.0, 1.0, 0.0, 0.0 |
|
|
* | 0.0, 0.0, 1.0, 0.0 |
|
|
* | 0.0, 0.0, 0.0, 1.0 |
|
|
* ]|
|
|
*
|
|
* Is used instead.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_PROJECTION] =
|
|
g_param_spec_boxed ("projection",
|
|
"Projection",
|
|
"The projection matrix used by the renderer",
|
|
GRAPHENE_TYPE_MATRIX,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GskRenderer:minification-filter:
|
|
*
|
|
* The filter to be used when scaling textures down.
|
|
*
|
|
* See also: gsk_renderer_set_scaling_filters()
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_MINIFICATION_FILTER] =
|
|
g_param_spec_enum ("minification-filter",
|
|
"Minification Filter",
|
|
"The minification filter used by the renderer for texture targets",
|
|
GSK_TYPE_SCALING_FILTER,
|
|
GSK_SCALING_FILTER_LINEAR,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GskRenderer:magnification-filter:
|
|
*
|
|
* The filter to be used when scaling textures up.
|
|
*
|
|
* See also: gsk_renderer_set_scaling_filters()
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_MAGNIFICATION_FILTER] =
|
|
g_param_spec_enum ("magnification-filter",
|
|
"Magnification Filter",
|
|
"The magnification filter used by the renderer for texture targets",
|
|
GSK_TYPE_SCALING_FILTER,
|
|
GSK_SCALING_FILTER_LINEAR,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GskRenderer:auto-clear:
|
|
*
|
|
* Automatically clear the rendering surface when rendering.
|
|
*
|
|
* Setting this property to %FALSE assumes that the owner of the
|
|
* rendering surface will have cleared it prior to calling
|
|
* gsk_renderer_render().
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_AUTO_CLEAR] =
|
|
g_param_spec_boolean ("auto-clear",
|
|
"Auto Clear",
|
|
"Automatically clears the rendering target on render",
|
|
TRUE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GskRenderer:display:
|
|
*
|
|
* The #GdkDisplay used by the #GskRenderer.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_DISPLAY] =
|
|
g_param_spec_object ("display",
|
|
"Display",
|
|
"The GdkDisplay object used by the renderer",
|
|
GDK_TYPE_DISPLAY,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
gsk_renderer_properties[PROP_WINDOW] =
|
|
g_param_spec_object ("window",
|
|
"Window",
|
|
"The window associated to the renderer",
|
|
GDK_TYPE_WINDOW,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
/**
|
|
* GskRenderer:scale-factor:
|
|
*
|
|
* The scale factor used when rendering.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_SCALE_FACTOR] =
|
|
g_param_spec_int ("scale-factor",
|
|
"Scale Factor",
|
|
"The scaling factor of the renderer",
|
|
1, G_MAXINT,
|
|
1,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GskRenderer:drawing-context:
|
|
*
|
|
* The drawing context used when rendering.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_DRAWING_CONTEXT] =
|
|
g_param_spec_object ("drawing-context",
|
|
"Drawing Context",
|
|
"The drawing context used by the renderer",
|
|
GDK_TYPE_DRAWING_CONTEXT,
|
|
G_PARAM_READABLE |
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
/**
|
|
* GskRenderer:use-alpha:
|
|
*
|
|
* Whether the #GskRenderer should use the alpha channel when rendering.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gsk_renderer_properties[PROP_USE_ALPHA] =
|
|
g_param_spec_boolean ("use-alpha",
|
|
"Use Alpha",
|
|
"Whether the renderer should use the alpha channel when rendering",
|
|
FALSE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
g_object_class_install_properties (gobject_class, N_PROPS, gsk_renderer_properties);
|
|
}
|
|
|
|
static void
|
|
gsk_renderer_init (GskRenderer *self)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
|
|
|
|
graphene_matrix_init_identity (&priv->modelview);
|
|
graphene_matrix_init_identity (&priv->projection);
|
|
|
|
priv->auto_clear = TRUE;
|
|
priv->scale_factor = 1;
|
|
|
|
priv->min_filter = GSK_SCALING_FILTER_LINEAR;
|
|
priv->mag_filter = GSK_SCALING_FILTER_LINEAR;
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_set_viewport:
|
|
* @renderer: a #GskRenderer
|
|
* @viewport: (nullable): the viewport rectangle used by the @renderer
|
|
*
|
|
* Sets the visible rectangle to be used as the viewport for
|
|
* the rendering.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_set_viewport (GskRenderer *renderer,
|
|
const graphene_rect_t *viewport)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
if (viewport == NULL)
|
|
{
|
|
graphene_rect_init (&priv->viewport, 0.f, 0.f, 0.f, 0.f);
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_VIEWPORT]);
|
|
return;
|
|
}
|
|
|
|
if (graphene_rect_equal (viewport, &priv->viewport))
|
|
return;
|
|
|
|
graphene_rect_init_from_rect (&priv->viewport, viewport);
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_VIEWPORT]);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_viewport:
|
|
* @renderer: a #GskRenderer
|
|
* @viewport: (out caller-allocates): return location for the viewport rectangle
|
|
*
|
|
* Retrieves the viewport of the #GskRenderer.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_get_viewport (GskRenderer *renderer,
|
|
graphene_rect_t *viewport)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
g_return_if_fail (viewport != NULL);
|
|
|
|
graphene_rect_init_from_rect (viewport, &priv->viewport);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_set_modelview:
|
|
* @renderer: a #GskRenderer
|
|
* @modelview: the modelview matrix used by the @renderer
|
|
*
|
|
* Sets the initial modelview matrix used by the #GskRenderer.
|
|
*
|
|
* A modelview matrix defines the initial transformation imposed
|
|
* on the scene graph.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_set_modelview (GskRenderer *renderer,
|
|
const graphene_matrix_t *modelview)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
if (modelview == NULL)
|
|
graphene_matrix_init_identity (&priv->modelview);
|
|
else
|
|
graphene_matrix_init_from_matrix (&priv->modelview, modelview);
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_MODELVIEW]);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_modelview:
|
|
* @renderer: a #GskRenderer
|
|
* @modelview: (out caller-allocates): return location for the modelview matrix
|
|
*
|
|
* Retrieves the modelview matrix used by the #GskRenderer.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_get_modelview (GskRenderer *renderer,
|
|
graphene_matrix_t *modelview)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
g_return_if_fail (modelview != NULL);
|
|
|
|
graphene_matrix_init_from_matrix (modelview, &priv->modelview);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_set_projection:
|
|
* @renderer: a #GskRenderer
|
|
* @projection: the projection matrix used by the @renderer
|
|
*
|
|
* Sets the projection matrix used by the #GskRenderer.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_set_projection (GskRenderer *renderer,
|
|
const graphene_matrix_t *projection)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
if (projection == NULL)
|
|
graphene_matrix_init_identity (&priv->projection);
|
|
else
|
|
graphene_matrix_init_from_matrix (&priv->projection, projection);
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_PROJECTION]);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_projection:
|
|
* @renderer: a #GskRenderer
|
|
* @projection: (out caller-allocates): return location for the projection matrix
|
|
*
|
|
* Retrieves the projection matrix used by the #GskRenderer.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_get_projection (GskRenderer *renderer,
|
|
graphene_matrix_t *projection)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
g_return_if_fail (projection != NULL);
|
|
|
|
graphene_matrix_init_from_matrix (projection, &priv->projection);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_set_scaling_filters:
|
|
* @renderer: a #GskRenderer
|
|
* @min_filter: the minification scaling filter
|
|
* @mag_filter: the magnification scaling filter
|
|
*
|
|
* Sets the scaling filters to be applied when scaling textures
|
|
* up and down.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_set_scaling_filters (GskRenderer *renderer,
|
|
GskScalingFilter min_filter,
|
|
GskScalingFilter mag_filter)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
GObject *gobject;
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
gobject = G_OBJECT (renderer);
|
|
|
|
g_object_freeze_notify (gobject);
|
|
|
|
if (priv->min_filter != min_filter)
|
|
{
|
|
priv->min_filter = min_filter;
|
|
g_object_notify_by_pspec (gobject, gsk_renderer_properties[PROP_MINIFICATION_FILTER]);
|
|
}
|
|
|
|
if (priv->mag_filter != mag_filter)
|
|
{
|
|
priv->mag_filter = mag_filter;
|
|
g_object_notify_by_pspec (gobject, gsk_renderer_properties[PROP_MAGNIFICATION_FILTER]);
|
|
}
|
|
|
|
g_object_thaw_notify (gobject);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_scaling_filters:
|
|
* @renderer: a #GskRenderer
|
|
* @min_filter: (out) (nullable): return location for the minification filter
|
|
* @mag_filter: (out) (nullable): return location for the magnification filter
|
|
*
|
|
* Retrieves the minification and magnification filters used by the #GskRenderer.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_get_scaling_filters (GskRenderer *renderer,
|
|
GskScalingFilter *min_filter,
|
|
GskScalingFilter *mag_filter)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
if (min_filter != NULL)
|
|
*min_filter = priv->min_filter;
|
|
|
|
if (mag_filter != NULL)
|
|
*mag_filter = priv->mag_filter;
|
|
}
|
|
|
|
void
|
|
gsk_renderer_set_scale_factor (GskRenderer *renderer,
|
|
int scale_factor)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
if (priv->scale_factor != scale_factor)
|
|
{
|
|
priv->scale_factor = scale_factor;
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_SCALE_FACTOR]);
|
|
}
|
|
}
|
|
|
|
int
|
|
gsk_renderer_get_scale_factor (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), 1);
|
|
|
|
return priv->scale_factor;
|
|
}
|
|
|
|
void
|
|
gsk_renderer_set_window (GskRenderer *renderer,
|
|
GdkWindow *window)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
g_return_if_fail (!priv->is_realized);
|
|
g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
|
|
|
|
if (g_set_object (&priv->window, window))
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_WINDOW]);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_window:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Retrieves the #GdkWindow set using gsk_renderer_set_window().
|
|
*
|
|
* Returns: (transfer none) (nullable): a #GdkWindow
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
GdkWindow *
|
|
gsk_renderer_get_window (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
|
|
|
return priv->window;
|
|
}
|
|
|
|
/*< private >
|
|
* gsk_renderer_get_root_node:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Retrieves the #GskRenderNode used by @renderer.
|
|
*
|
|
* Returns: (transfer none) (nullable): a #GskRenderNode
|
|
*/
|
|
GskRenderNode *
|
|
gsk_renderer_get_root_node (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
|
|
|
return priv->root_node;
|
|
}
|
|
|
|
/*< private >
|
|
* gsk_renderer_get_drawing_context:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Retrieves the #GdkDrawingContext used by @renderer.
|
|
*
|
|
* Returns: (transfer none) (nullable): a #GdkDrawingContext
|
|
*/
|
|
GdkDrawingContext *
|
|
gsk_renderer_get_drawing_context (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
|
|
|
return priv->drawing_context;
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_display:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Retrieves the #GdkDisplay used when creating the #GskRenderer.
|
|
*
|
|
* Returns: (transfer none): a #GdkDisplay
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
GdkDisplay *
|
|
gsk_renderer_get_display (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
|
|
|
return priv->display;
|
|
}
|
|
|
|
/*< private >
|
|
* gsk_renderer_is_realized:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Checks whether the @renderer is realized or not.
|
|
*
|
|
* Returns: %TRUE if the #GskRenderer was realized, and %FALSE otherwise
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gboolean
|
|
gsk_renderer_is_realized (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), FALSE);
|
|
|
|
return priv->is_realized;
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_realize:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Creates the resources needed by the @renderer to render the scene
|
|
* graph.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gboolean
|
|
gsk_renderer_realize (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), FALSE);
|
|
|
|
if (priv->is_realized)
|
|
return TRUE;
|
|
|
|
priv->is_realized = GSK_RENDERER_GET_CLASS (renderer)->realize (renderer);
|
|
|
|
return priv->is_realized;
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_unrealize:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Releases all the resources created by gsk_renderer_realize().
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_unrealize (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
if (!priv->is_realized)
|
|
return;
|
|
|
|
GSK_RENDERER_GET_CLASS (renderer)->unrealize (renderer);
|
|
|
|
priv->is_realized = FALSE;
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_render:
|
|
* @renderer: a #GskRenderer
|
|
* @root: a #GskRenderNode
|
|
* @context: a #GdkDrawingContext
|
|
*
|
|
* Renders the scene graph, described by a tree of #GskRenderNode instances,
|
|
* using the given #GdkDrawingContext.
|
|
*
|
|
* The @renderer will acquire a reference on the #GskRenderNode tree while
|
|
* the rendering is in progress, and will make the tree immutable.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_render (GskRenderer *renderer,
|
|
GskRenderNode *root,
|
|
GdkDrawingContext *context)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
g_return_if_fail (priv->is_realized);
|
|
g_return_if_fail (GSK_IS_RENDER_NODE (root));
|
|
g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
|
|
g_return_if_fail (priv->drawing_context == NULL);
|
|
g_return_if_fail (priv->root_node == NULL);
|
|
|
|
priv->drawing_context = g_object_ref (context);
|
|
priv->root_node = gsk_render_node_ref (root);
|
|
gsk_render_node_make_immutable (priv->root_node);
|
|
|
|
GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, context);
|
|
|
|
g_clear_object (&priv->drawing_context);
|
|
g_clear_pointer (&priv->root_node, gsk_render_node_unref);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_set_auto_clear:
|
|
* @renderer: a #GskRenderer
|
|
* @clear: whether the target surface should be cleared prior
|
|
* to rendering to it
|
|
*
|
|
* Sets whether the target surface used by @renderer should be cleared
|
|
* before rendering.
|
|
*
|
|
* If you pass a custom surface to gsk_renderer_set_surface(), you may
|
|
* want to manage the clearing manually; this is possible by passing
|
|
* %FALSE to this function.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_set_auto_clear (GskRenderer *renderer,
|
|
gboolean clear)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
|
|
clear = !!clear;
|
|
|
|
if (clear == priv->auto_clear)
|
|
return;
|
|
|
|
priv->auto_clear = clear;
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_AUTO_CLEAR]);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_auto_clear:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Retrieves the value set using gsk_renderer_set_auto_clear().
|
|
*
|
|
* Returns: %TRUE if the target surface should be cleared prior to rendering
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gboolean
|
|
gsk_renderer_get_auto_clear (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), FALSE);
|
|
|
|
return priv->auto_clear;
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_set_use_alpha:
|
|
* @renderer: a #GskRenderer
|
|
* @use_alpha: whether to use the alpha channel of the target surface or not
|
|
*
|
|
* Sets whether the @renderer should use the alpha channel of the target surface
|
|
* or not.
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
void
|
|
gsk_renderer_set_use_alpha (GskRenderer *renderer,
|
|
gboolean use_alpha)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_if_fail (GSK_IS_RENDERER (renderer));
|
|
g_return_if_fail (!priv->is_realized);
|
|
|
|
use_alpha = !!use_alpha;
|
|
|
|
if (use_alpha == priv->use_alpha)
|
|
return;
|
|
|
|
priv->use_alpha = use_alpha;
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (renderer), gsk_renderer_properties[PROP_USE_ALPHA]);
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_use_alpha:
|
|
* @renderer: a #GskRenderer
|
|
*
|
|
* Retrieves the value set using gsk_renderer_set_use_alpha().
|
|
*
|
|
* Returns: %TRUE if the target surface should use an alpha channel
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
gboolean
|
|
gsk_renderer_get_use_alpha (GskRenderer *renderer)
|
|
{
|
|
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
|
|
|
g_return_val_if_fail (GSK_IS_RENDERER (renderer), FALSE);
|
|
|
|
return priv->use_alpha;
|
|
}
|
|
|
|
/**
|
|
* gsk_renderer_get_for_display:
|
|
* @display: a #GdkDisplay
|
|
*
|
|
* Creates an appropriate #GskRenderer instance for the given @display.
|
|
*
|
|
* Returns: (transfer full) (nullable): a #GskRenderer
|
|
*
|
|
* Since: 3.22
|
|
*/
|
|
GskRenderer *
|
|
gsk_renderer_get_for_display (GdkDisplay *display)
|
|
{
|
|
static const char *use_software;
|
|
|
|
GType renderer_type = G_TYPE_INVALID;
|
|
|
|
if (use_software == NULL)
|
|
{
|
|
use_software = g_getenv ("GSK_USE_SOFTWARE");
|
|
if (use_software == NULL)
|
|
use_software = "0";
|
|
}
|
|
|
|
if (use_software[0] != '0')
|
|
return NULL;
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
if (GDK_IS_X11_DISPLAY (display))
|
|
renderer_type = GSK_TYPE_GL_RENDERER;
|
|
else
|
|
#endif
|
|
#ifdef GDK_WINDOWING_WAYLAND
|
|
if (GDK_IS_WAYLAND_DISPLAY (display))
|
|
renderer_type = GSK_TYPE_GL_RENDERER;
|
|
#endif
|
|
else
|
|
return NULL;
|
|
|
|
GSK_NOTE (RENDERER, g_print ("Creating renderer of type '%s' for display '%s'\n",
|
|
g_type_name (renderer_type),
|
|
G_OBJECT_TYPE_NAME (display)));
|
|
|
|
g_assert (renderer_type != G_TYPE_INVALID);
|
|
|
|
return g_object_new (renderer_type, "display", display, NULL);
|
|
}
|