Initial implementation of GSK rendering pipeline

GSK is conceptually split into two scene graphs:

 * a simple rendering tree of operations
 * a complex set of logical layers

The latter is built on the former, and adds convenience and high level
API for application developers.

The lower layer, though, is what gets transformed into the rendering
pipeline, as it's simple and thus can be transformed into appropriate
rendering commands with minimal state changes.

The lower layer is also suitable for reuse from more complex higher
layers, like the CSS machinery in GTK, without necessarily port those
layers to the GSK high level API.

This lower layer is based on GskRenderNode instances, which represent
the tree of rendering operations; and a GskRenderer instance, which
takes the render nodes and submits them (after potentially reordering
and transforming them to a more appropriate representation) to the
underlying graphic system.
This commit is contained in:
Emmanuele Bassi
2016-03-17 13:48:19 +00:00
parent 2378965e92
commit a422f45544
26 changed files with 5346 additions and 34 deletions

View File

@@ -1,23 +1,12 @@
include $(top_srcdir)/Makefile.decl
-include $(INTROSPECTION_MAKEFILE)
# Preamble
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ARGS = \
--add-include-path=../gdk \
--warn-all
INTROSPECTION_COMPILER_ARGS = \
--includedir=$(srcdir) \
--includedir=. \
--includedir=../gdk
AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\"Gsk\" \
-DGSK_COMPILATION \
-I$(top_builddir) \
-I$(top_builddir)/gsk \
-I$(top_srcdir) \
-I$(top_srcdir)/gdk \
-I$(top_builddir) \
-I$(top_builddir)/gsk \
$(GTK_DEBUG_FLAGS) \
$(GTK_WARN_FLAGS) \
$(GSK_DEP_CFLAGS)
@@ -35,39 +24,124 @@ LDADD = \
BUILT_SOURCES =
CLEANFILES =
DISTCLEANFILES =
lib_LTLIBRARIES =
gsk_public_source_h =
gsk_private_source_h =
gsk_private_source_c =
gsk_source_c =
gsk_public_source_h = \
gskenums.h \
gskrenderer.h \
gskrendernode.h \
gskrendernodeiter.h \
gsktypes.h
gsk_private_source_h = \
gskcairorendererprivate.h \
gskdebugprivate.h \
gskglrendererprivate.h \
gskrendererprivate.h \
gskrendernodeprivate.h \
gskprivate.h
gsk_private_source_c = \
gskprivate.c
gsk_built_source_h = \
gskenumtypes.h \
gskresources.h
gsk_built_source_c = \
gskenumtypes.c \
gskresources.c
gsk_source_c = \
gskcairorenderer.c \
gskdebug.c \
gskglrenderer.c \
gskrenderer.c \
gskrendernode.c \
gskrendernodeiter.c
libgsk_3_la_SOURCES = $(all_sources)
libgsk_3_la_CFLAGS = $(AM_CFLAGS) $(GDK_HIDDEN_VISIBILITY_CFLAGS)
libgsk_3_la_LIBADD = $(GSK_DEP_LIBS) $(top_builddir)/gdk/libgdk-3.la
libgsk_3_la_LDFLAGS = $(LDADD)
all_sources = \
$(gsk_public_source_h) \
$(gsk_private_source_h) \
$(gsk_built_source_h) \
$(gsk_private_source_c) \
$(gsk_source_c)
lib_LTLIBRARIES += libgsk-3.la
BUILT_SOURCES += $(gsk_built_source_h) $(gsk_built_source_c) gsk.resources.xml
gskincludedir = $(includedir)/gtk-3.0/gsk
gskinclude_HEADERS = $(gsk_public_source_h) gsk.h
gskenumtypes.h: $(gsk_public_source_h) gskenumtypes.h.template
$(AM_V_GEN) $(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \
gskenumtypes.h.tmp && \
mv gskenumtypes.h.tmp gskenumtypes.h
gskenumtypes.c: $(gsk_public_source_h) gskenumtypes.c.template
$(AM_V_GEN) $(GLIB_MKENUMS) --template $(filter %.template,$^) $(filter-out %.template,$^) > \
gskenumtypes.c.tmp && \
mv gskenumtypes.c.tmp gskenumtypes.c
EXTRA_DIST += gskenumtypes.h.template gskenumtypes.c.template
DISTCLEANFILES += gskenumtypes.h gskenumtypes.c
resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(builddir)/gsk.resources.xml)
gsk.resources.xml: Makefile.am
$(AM_V_GEN) echo "<?xml version='1.0' encoding='UTF-8'?>" > $@; \
echo "<gresources>" >> $@; \
echo " <gresource prefix='/org/gtk/libgsk'>" >> $@; \
for f in $(top_srcdir)/gsk/resources/glsl/*; do \
n=`basename $$f`; \
echo " <file alias='glsl/$$n'>resources/glsl/$$n</file>" >> $@; \
done; \
echo " </gresource>" >> $@; \
echo "</gresources>" >> $@
gskresources.h: gsk.resources.xml
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< \
--target=$@ --sourcedir=$(srcdir) --c-name _gsk --generate-header --manual-register
gskresources.c: gsk.resources.xml $(resource_files)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< \
--target=$@ --sourcedir=$(srcdir) --c-name _gsk --generate-source --manual-register
EXTRA_DIST += $(resource_files)
CLEANFILES += gsk.resources.xml
DISTCLEANFILES += gskresources.h gskresources.c
libgsk_4_la_SOURCES = $(all_sources)
nodist_libgsk_4_la_SOURCES = $(gsk_built_source_h) $(gsk_built_source_c)
libgsk_4_la_CFLAGS = $(AM_CFLAGS) $(GDK_HIDDEN_VISIBILITY_CFLAGS)
libgsk_4_la_LIBADD = $(GSK_DEP_LIBS) $(top_builddir)/gdk/libgdk-4.la
libgsk_4_la_LDFLAGS = $(LDADD)
lib_LTLIBRARIES += libgsk-4.la
gskincludedir = $(includedir)/gtk-4.0/gsk
gskinclude_HEADERS = $(gsk_public_source_h) gskenumtypes.h gsk.h
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_GIRS =
INTROSPECTION_SCANNER_ENV = \
CC="$(CC)"
INTROSPECTION_SCANNER_ARGS = \
--add-include-path=../gdk \
--warn-all
INTROSPECTION_COMPILER_ARGS = \
--includedir=$(srcdir) \
--includedir=. \
--includedir=../gdk
if HAVE_INTROSPECTION
introspection_files = $(gsk_source_c) $(gsk_public_source_h)
introspection_files = $(filter-out $(wildcard *private.h),$(all_sources))
Gsk-3.0.gir: libgsk-3.la Makefile
Gsk_3_0_gir_SCANNERFLAGS = \
Gsk-4.0.gir: libgsk-4.la Makefile
Gsk_4_0_gir_SCANNERFLAGS = \
--add-include-path=$(top_builddir)/gdk \
--include-uninstalled=$(top_builddir)/gdk/Gdk-3.0.gir \
--include-uninstalled=$(top_builddir)/gdk/Gdk-4.0.gir \
--c-include="gsk/gsk.h"
Gsk_3_0_gir_LIBS = libgsk-3.la
Gsk_3_0_gir_FILES = $(introspection_files)
Gsk_3_0_gir_CFLAGS = $(AM_CPPFLAGS)
Gsk_3_0_gir_EXPORT_PACKAGES = gsk-3.0
Gsk_3_0_gir_INCLUDES = GObject-2.0 cairo-1.0 Graphene-1.0
INTROSPECTION_GIRS += Gsk-3.0.gir
Gsk_4_0_gir_LIBS = libgsk-4.la $(top_builddir)/gdk/libgdk-4.la
Gsk_4_0_gir_FILES = $(introspection_files)
Gsk_4_0_gir_CFLAGS = $(AM_CPPFLAGS)
Gsk_4_0_gir_EXPORT_PACKAGES = gsk-4.0
Gsk_4_0_gir_INCLUDES = GObject-2.0 cairo-1.0 Graphene-1.0
INTROSPECTION_GIRS += Gsk-4.0.gir
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)

33
gsk/gsk.h Normal file
View File

@@ -0,0 +1,33 @@
/* 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/>.
*/
#ifndef __GSK_H__
#define __GSK_H__
#define __GSK_H_INSIDE__
#include <gsk/gskenums.h>
#include <gsk/gskrenderer.h>
#include <gsk/gskrendernode.h>
#include <gsk/gskrendernodeiter.h>
#include <gsk/gsktypes.h>
#include <gsk/gskenumtypes.h>
#undef __GSK_H_INSIDE__
#endif /* __GSK_H__ */

195
gsk/gskcairorenderer.c Normal file
View File

@@ -0,0 +1,195 @@
#include "config.h"
#include "gskcairorendererprivate.h"
#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
#include "gskrendernodeiter.h"
#include "gskrendernodeprivate.h"
struct _GskCairoRenderer
{
GskRenderer parent_instance;
graphene_rect_t viewport;
};
struct _GskCairoRendererClass
{
GskRendererClass parent_class;
};
G_DEFINE_TYPE (GskCairoRenderer, gsk_cairo_renderer, GSK_TYPE_RENDERER)
static gboolean
gsk_cairo_renderer_realize (GskRenderer *renderer)
{
return TRUE;
}
static void
gsk_cairo_renderer_unrealize (GskRenderer *renderer)
{
}
static void
gsk_cairo_renderer_render_node (GskCairoRenderer *self,
GskRenderNode *node,
cairo_t *cr)
{
GskRenderNodeIter iter;
GskRenderNode *child;
gboolean pop_group = FALSE;
graphene_matrix_t mvp;
cairo_matrix_t ctm;
graphene_rect_t frame;
if (gsk_render_node_is_hidden (node))
return;
cairo_save (cr);
gsk_render_node_get_world_matrix (node, &mvp);
if (graphene_matrix_to_2d (&mvp, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
{
GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
ctm.xx, ctm.yx,
ctm.xy, ctm.yy,
ctm.x0, ctm.y0));
cairo_transform (cr, &ctm);
}
else
g_critical ("Invalid non-affine transformation for node %p", node);
gsk_render_node_get_bounds (node, &frame);
GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
frame.origin.x, frame.origin.y,
frame.size.width, frame.size.height));
if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
{
cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
cairo_clip (cr);
}
if (!gsk_render_node_is_opaque (node) && gsk_render_node_get_opacity (node) != 1.0)
{
GSK_NOTE (CAIRO, g_print ("Pushing opacity group (opacity:%g)\n",
gsk_render_node_get_opacity (node)));
cairo_push_group (cr);
pop_group = TRUE;
}
GSK_NOTE (CAIRO, g_print ("Rendering surface %p for node %p at %g, %g\n",
gsk_render_node_get_surface (node),
node,
frame.origin.x, frame.origin.y));
cairo_set_source_surface (cr, gsk_render_node_get_surface (node), frame.origin.x, frame.origin.y);
cairo_paint (cr);
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
{
cairo_save (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
cairo_set_line_width (cr, 2);
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
cairo_stroke (cr);
cairo_restore (cr);
}
cairo_matrix_invert (&ctm);
cairo_transform (cr, &ctm);
if (gsk_render_node_get_n_children (node) != 0)
{
GSK_NOTE (CAIRO, g_print ("Drawing %d children of node [%p]\n",
gsk_render_node_get_n_children (node),
node));
gsk_render_node_iter_init (&iter, node);
while (gsk_render_node_iter_next (&iter, &child))
gsk_cairo_renderer_render_node (self, child, cr);
}
if (pop_group)
{
cairo_pop_group_to_source (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_paint_with_alpha (cr, gsk_render_node_get_opacity (node));
}
cairo_restore (cr);
}
static void
gsk_cairo_renderer_resize_viewport (GskRenderer *renderer,
const graphene_rect_t *viewport)
{
GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
self->viewport = *viewport;
}
static void
gsk_cairo_renderer_render (GskRenderer *renderer)
{
GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
cairo_surface_t *target = gsk_renderer_get_surface (renderer);
GskRenderNode *root = gsk_renderer_get_root_node (renderer);
cairo_t *cr = cairo_create (target);
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
{
cairo_save (cr);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_rectangle (cr,
self->viewport.origin.x,
self->viewport.origin.y,
self->viewport.size.width,
self->viewport.size.height);
cairo_set_source_rgba (cr, 0, 0, 0.85, 0.5);
cairo_stroke (cr);
cairo_restore (cr);
}
gsk_cairo_renderer_render_node (self, root, cr);
cairo_destroy (cr);
}
static void
gsk_cairo_renderer_clear (GskRenderer *renderer)
{
cairo_surface_t *surface = gsk_renderer_get_surface (renderer);
cairo_t *cr = cairo_create (surface);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
if (gsk_renderer_get_use_alpha (renderer))
cairo_set_source_rgba (cr, 0, 0, 0, 0);
else
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
}
static void
gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
{
GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);
renderer_class->realize = gsk_cairo_renderer_realize;
renderer_class->unrealize = gsk_cairo_renderer_unrealize;
renderer_class->resize_viewport = gsk_cairo_renderer_resize_viewport;
renderer_class->clear = gsk_cairo_renderer_clear;
renderer_class->render = gsk_cairo_renderer_render;
}
static void
gsk_cairo_renderer_init (GskCairoRenderer *self)
{
}

View File

@@ -0,0 +1,26 @@
#ifndef __GSK_CAIRO_RENDERER_PRIVATE_H__
#define __GSK_CAIRO_RENDERER_PRIVATE_H__
#include <cairo.h>
#include <gsk/gskrenderer.h>
G_BEGIN_DECLS
#define GSK_TYPE_CAIRO_RENDERER (gsk_cairo_renderer_get_type ())
#define GSK_CAIRO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_CAIRO_RENDERER, GskCairoRenderer))
#define GSK_IS_CAIRO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_CAIRO_RENDERER))
#define GSK_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_CAIRO_RENDERER, GskCairoRendererClass))
#define GSK_IS_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_CAIRO_RENDERER))
#define GSK_CAIRO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_CAIRO_RENDERER, GskCairoRendererClass))
typedef struct _GskCairoRenderer GskCairoRenderer;
typedef struct _GskCairoRendererClass GskCairoRendererClass;
GType gsk_cairo_renderer_get_type (void) G_GNUC_CONST;
GskRenderer *gsk_cairo_renderer_new (void);
G_END_DECLS
#endif /* __GSK_CAIRO_RENDERER_PRIVATE_H__ */

58
gsk/gskdebug.c Normal file
View File

@@ -0,0 +1,58 @@
#include "gskdebugprivate.h"
#ifdef G_ENABLE_DEBUG
static const GDebugKey gsk_debug_keys[] = {
{ "rendernode", GSK_DEBUG_RENDER_NODE },
{ "renderer", GSK_DEBUG_RENDERER },
{ "cairo", GSK_DEBUG_CAIRO },
{ "opengl", GSK_DEBUG_OPENGL },
};
#endif
static const GDebugKey gsk_rendering_keys[] = {
{ "geometry", GSK_RENDERING_MODE_GEOMETRY },
};
gboolean
gsk_check_debug_flags (GskDebugFlags flags)
{
#ifdef G_ENABLE_DEBUG
static volatile gsize gsk_debug_flags__set;
static guint gsk_debug_flags;
if (g_once_init_enter (&gsk_debug_flags__set))
{
const char *env = g_getenv ("GSK_DEBUG");
gsk_debug_flags = g_parse_debug_string (env,
(GDebugKey *) gsk_debug_keys,
G_N_ELEMENTS (gsk_debug_keys));
g_once_init_leave (&gsk_debug_flags__set, TRUE);
}
return (gsk_debug_flags & flags) != 0;
#else
return FALSE;
#endif
}
gboolean
gsk_check_rendering_flags (GskRenderingMode flags)
{
static volatile gsize gsk_rendering_flags__set;
static guint gsk_rendering_flags;
if (g_once_init_enter (&gsk_rendering_flags__set))
{
const char *env = g_getenv ("GSK_RENDERING_MODE");
gsk_rendering_flags = g_parse_debug_string (env,
(GDebugKey *) gsk_rendering_keys,
G_N_ELEMENTS (gsk_rendering_keys));
g_once_init_leave (&gsk_rendering_flags__set, TRUE);
}
return (gsk_rendering_flags & flags) != 0;
}

43
gsk/gskdebugprivate.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef __GSK_DEBUG_PRIVATE_H__
#define __GSK_DEBUG_PRIVATE_H__
#include <glib.h>
G_BEGIN_DECLS
typedef enum {
GSK_DEBUG_RENDER_NODE = 1 << 0,
GSK_DEBUG_RENDERER = 1 << 1,
GSK_DEBUG_CAIRO = 1 << 2,
GSK_DEBUG_OPENGL = 1 << 3
} GskDebugFlags;
typedef enum {
GSK_RENDERING_MODE_GEOMETRY = 1 << 0
} GskRenderingMode;
gboolean gsk_check_debug_flags (GskDebugFlags flags);
gboolean gsk_check_rendering_flags (GskRenderingMode flags);
#ifdef G_ENABLE_DEBUG
#define GSK_DEBUG_CHECK(type) G_UNLIKELY (gsk_check_debug_flags (GSK_DEBUG_ ## type))
#define GSK_RENDER_MODE_CHECK(type) G_UNLIKELY (gsk_check_rendering_flags (GSK_RENDERING_MODE_ ## type))
#define GSK_NOTE(type,action) G_STMT_START { \
if (GSK_DEBUG_CHECK (type)) { \
action; \
} } G_STMT_END
#else
#define GSK_RENDER_MODE_CHECK(type) 0
#define GSK_DEBUG_CHECK(type) 0
#define GSK_NOTE(type,action)
#endif
G_END_DECLS
#endif /* __GSK_DEBUG_PRIVATE_H__ */

46
gsk/gskenums.h Normal file
View File

@@ -0,0 +1,46 @@
/* 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/>.
*/
#ifndef __GSK_ENUMS_H__
#define __GSK_ENUMS_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
/**
* GskScalingFilter:
* @GSK_SCALING_FILTER_LINEAR: linear interpolation filter
* @GSK_SCALING_FILTER_NEAREST: nearest neighbor interpolation filter
* @GSK_SCALING_FILTER_TRILINEAR: linear interpolation along each axis,
* plus mipmap generation, with linear interpolation along the mipmap
* levels
*
* The filters used when scaling texture data.
*
* The actual implementation of each filter is deferred to the
* rendering pipeline.
*
* Since: 3.22
*/
typedef enum {
GSK_SCALING_FILTER_LINEAR,
GSK_SCALING_FILTER_NEAREST,
GSK_SCALING_FILTER_TRILINEAR
} GskScalingFilter;
#endif /* __GSK_TYPES_H__ */

View File

@@ -0,0 +1,38 @@
/*** BEGIN file-header ***/
#include "config.h"
#include "gskenumtypes.h"
#include <gsk.h>
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter (&g_define_type_id__volatile))
{
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
GType g_define_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
/*** END value-tail ***/

View File

@@ -0,0 +1,24 @@
/*** BEGIN file-header ***/
#ifndef __GSK_ENUM_TYPES_H__
#define __GSK_ENUM_TYPES_H__
#include <gdk/gdk.h>
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GDK_AVAILABLE_IN_ALL GType @enum_name@_get_type (void) G_GNUC_CONST;
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
/*** END value-header ***/
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* __GSK_ENUM_TYPES_H__ */
/*** END file-tail ***/

1092
gsk/gskglrenderer.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
#ifndef __GSK_GL_RENDERER_PRIVATE_H__
#define __GSK_GL_RENDERER_PRIVATE_H__
#include <gsk/gskrenderer.h>
G_BEGIN_DECLS
#define GSK_TYPE_GL_RENDERER (gsk_gl_renderer_get_type ())
#define GSK_GL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_GL_RENDERER, GskGLRenderer))
#define GSK_IS_GL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_GL_RENDERER))
#define GSK_GL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_GL_RENDERER, GskGLRendererClass))
#define GSK_IS_GL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_GL_RENDERER))
#define GSK_GL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_GL_RENDERER, GskGLRendererClass))
typedef struct _GskGLRenderer GskGLRenderer;
typedef struct _GskGLRendererClass GskGLRendererClass;
GType gsk_gl_renderer_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GSK_GL_RENDERER_PRIVATE_H__ */

16
gsk/gskprivate.c Normal file
View File

@@ -0,0 +1,16 @@
#include "gskresources.h"
static gpointer
register_resources (gpointer data)
{
_gsk_register_resource ();
return NULL;
}
void
gsk_ensure_resources (void)
{
static GOnce register_resources_once = G_ONCE_INIT;
g_once (&register_resources_once, register_resources, NULL);
}

12
gsk/gskprivate.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef __GSK_PRIVATE_H__
#define __GSK_PRIVATE_H__
#include <glib.h>
G_BEGIN_DECLS
void gsk_ensure_resources (void);
G_END_DECLS
#endif /* __GSK_PRIVATE_H__ */

1377
gsk/gskrenderer.c Normal file

File diff suppressed because it is too large Load Diff

113
gsk/gskrenderer.h Normal file
View File

@@ -0,0 +1,113 @@
/* 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/>.
*/
#ifndef __GSK_RENDERER_H__
#define __GSK_RENDERER_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
#include <gsk/gskrendernode.h>
G_BEGIN_DECLS
#define GSK_TYPE_RENDERER (gsk_renderer_get_type ())
#define GSK_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_RENDERER, GskRenderer))
#define GSK_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_RENDERER))
typedef struct _GskRenderer GskRenderer;
typedef struct _GskRendererClass GskRendererClass;
GDK_AVAILABLE_IN_3_22
GType gsk_renderer_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_22
GskRenderer * gsk_renderer_get_for_display (GdkDisplay *display);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_viewport (GskRenderer *renderer,
const graphene_rect_t *viewport);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_get_viewport (GskRenderer *renderer,
graphene_rect_t *viewport);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_projection (GskRenderer *renderer,
const graphene_matrix_t *projection);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_get_projection (GskRenderer *renderer,
graphene_matrix_t *projection);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_modelview (GskRenderer *renderer,
const graphene_matrix_t *modelview);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_get_modelview (GskRenderer *renderer,
graphene_matrix_t *modelview);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_scaling_filters (GskRenderer *renderer,
GskScalingFilter min_filter,
GskScalingFilter mag_filter);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_get_scaling_filters (GskRenderer *renderer,
GskScalingFilter *min_filter,
GskScalingFilter *mag_filter);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_auto_clear (GskRenderer *renderer,
gboolean clear);
GDK_AVAILABLE_IN_3_22
gboolean gsk_renderer_get_auto_clear (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_root_node (GskRenderer *renderer,
GskRenderNode *root);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_renderer_get_root_node (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_surface (GskRenderer *renderer,
cairo_surface_t *surface);
GDK_AVAILABLE_IN_3_22
cairo_surface_t * gsk_renderer_get_surface (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_window (GskRenderer *renderer,
GdkWindow *window);
GDK_AVAILABLE_IN_3_22
GdkWindow * gsk_renderer_get_window (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_draw_context (GskRenderer *renderer,
cairo_t *cr);
GDK_AVAILABLE_IN_3_22
cairo_t * gsk_renderer_get_draw_context (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
GdkDisplay * gsk_renderer_get_display (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_set_use_alpha (GskRenderer *renderer,
gboolean use_alpha);
GDK_AVAILABLE_IN_3_22
gboolean gsk_renderer_get_use_alpha (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
gboolean gsk_renderer_realize (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_unrealize (GskRenderer *renderer);
GDK_AVAILABLE_IN_3_22
void gsk_renderer_render (GskRenderer *renderer);
G_END_DECLS
#endif /* __GSK_RENDERER_H__ */

62
gsk/gskrendererprivate.h Normal file
View File

@@ -0,0 +1,62 @@
/* 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/>.
*/
#ifndef __GSK_RENDERER_PRIVATE_H__
#define __GSK_RENDERER_PRIVATE_H__
#include "gskrenderer.h"
G_BEGIN_DECLS
#define GSK_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_RENDERER, GskRendererClass))
#define GSK_IS_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_RENDERER))
#define GSK_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_RENDERER, GskRendererClass))
struct _GskRenderer
{
GObject parent_instance;
};
struct _GskRendererClass
{
GObjectClass parent_class;
gboolean (* realize) (GskRenderer *renderer);
void (* unrealize) (GskRenderer *renderer);
void (* resize_viewport) (GskRenderer *renderer,
const graphene_rect_t *viewport);
void (* update) (GskRenderer *renderer,
const graphene_matrix_t *modelview,
const graphene_matrix_t *projection);
void (* validate_tree) (GskRenderer *renderer,
GskRenderNode *root);
void (* clear) (GskRenderer *renderer);
void (* render) (GskRenderer *renderer);
};
gboolean gsk_renderer_is_realized (GskRenderer *renderer);
void gsk_renderer_maybe_resize_viewport (GskRenderer *renderer);
void gsk_renderer_maybe_update (GskRenderer *renderer);
void gsk_renderer_maybe_validate_tree (GskRenderer *renderer);
void gsk_renderer_maybe_clear (GskRenderer *renderer);
G_END_DECLS
#endif /* __GSK_RENDERER_PRIVATE_H__ */

1246
gsk/gskrendernode.c Normal file

File diff suppressed because it is too large Load Diff

117
gsk/gskrendernode.h Normal file
View File

@@ -0,0 +1,117 @@
/* 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/>.
*/
#ifndef __GSK_RENDER_NODE_H__
#define __GSK_RENDER_NODE_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_RENDER_NODE (gsk_render_node_get_type ())
#define GSK_RENDER_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_RENDER_NODE, GskRenderNode))
#define GSK_IS_RENDER_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_RENDER_NODE))
typedef struct _GskRenderNode GskRenderNode;
typedef struct _GskRenderNodeClass GskRenderNodeClass;
GDK_AVAILABLE_IN_3_22
GType gsk_render_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_new (void);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_get_parent (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_get_first_child (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_get_last_child (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_get_next_sibling (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_get_previous_sibling (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_insert_child_at_pos (GskRenderNode *node,
GskRenderNode *child,
int index_);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_insert_child_before (GskRenderNode *node,
GskRenderNode *child,
GskRenderNode *sibling);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_insert_child_after (GskRenderNode *node,
GskRenderNode *child,
GskRenderNode *sibling);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_remove_child (GskRenderNode *node,
GskRenderNode *child);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_replace_child (GskRenderNode *node,
GskRenderNode *new_child,
GskRenderNode *old_child);
GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_remove_all_children (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
guint gsk_render_node_get_n_children (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
gboolean gsk_render_node_contains (GskRenderNode *node,
GskRenderNode *descendant);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_bounds (GskRenderNode *node,
const graphene_rect_t *bounds);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_transform (GskRenderNode *node,
const graphene_matrix_t *transform);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_child_transform (GskRenderNode *node,
const graphene_matrix_t *transform);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_opacity (GskRenderNode *node,
double opacity);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_hidden (GskRenderNode *node,
gboolean hidden);
GDK_AVAILABLE_IN_3_22
gboolean gsk_render_node_is_hidden (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_opaque (GskRenderNode *node,
gboolean opaque);
GDK_AVAILABLE_IN_3_22
gboolean gsk_render_node_is_opaque (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_surface (GskRenderNode *node,
cairo_surface_t *surface);
GDK_AVAILABLE_IN_3_22
cairo_t * gsk_render_node_get_draw_context (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_set_name (GskRenderNode *node,
const char *name);
G_END_DECLS
#endif /* __GSK_RENDER_NODE_H__ */

254
gsk/gskrendernodeiter.c Normal file
View File

@@ -0,0 +1,254 @@
/* 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:GskRenderNodeIter
* @title: GskRenderNodeIter
* @Short_desc: Iterator helper for render nodes
*
* TODO
*/
#include "config.h"
#include "gskrendernodeiter.h"
#include "gskrendernodeprivate.h"
typedef struct {
GskRenderNode *root;
GskRenderNode *current;
gint64 age;
gpointer reserved1;
gpointer reserved2;
} RealIter;
#define REAL_ITER(iter) ((RealIter *) (iter))
/**
* gsk_render_node_iter_new: (constructor)
*
* Allocates a new #GskRenderNodeIter.
*
* Returns: (transfer full): the newly allocated #GskRenderNodeIter
*
* Since: 3.22
*/
GskRenderNodeIter *
gsk_render_node_iter_new (void)
{
return g_slice_new (GskRenderNodeIter);
}
/*< private >
* gsk_render_node_iter_copy:
* @src: a #GskRenderNodeIter
*
* Copies a #GskRenderNodeIter.
*
* Returns: (transfer full): a #GskRenderNodeIter
*/
static GskRenderNodeIter *
gsk_render_node_iter_copy (GskRenderNodeIter *src)
{
return g_slice_dup (GskRenderNodeIter, src);
}
/**
* gsk_render_node_iter_free:
* @iter: a #GskRenderNodeIter
*
* Frees the resources allocated by gsk_render_node_iter_new().
*
* Since: 3.22
*/
void
gsk_render_node_iter_free (GskRenderNodeIter *iter)
{
g_slice_free (GskRenderNodeIter, iter);
}
G_DEFINE_BOXED_TYPE (GskRenderNodeIter, gsk_render_node_iter,
gsk_render_node_iter_copy,
gsk_render_node_iter_free)
/**
* gsk_render_node_iter_init:
* @iter: a #GskRenderNodeIter
* @node: a #GskRenderNode
*
* Initializes a #GskRenderNodeIter for iterating over the
* children of @node.
*
* It's safe to call this function multiple times on the same
* #GskRenderNodeIter instance.
*
* Since: 3.22
*/
void
gsk_render_node_iter_init (GskRenderNodeIter *iter,
GskRenderNode *node)
{
RealIter *riter = REAL_ITER (iter);
g_return_if_fail (iter != NULL);
g_return_if_fail (GSK_IS_RENDER_NODE (node));
riter->root = node;
riter->age = node->age;
riter->current = NULL;
}
/**
* gsk_render_node_iter_is_valid:
* @iter: a #GskRenderNodeIter
*
* Checks whether a #GskRenderNodeIter is associated to a #GskRenderNode,
* or whether the associated node was modified while iterating.
*
* Returns: %TRUE if the iterator is still valid.
*
* Since: 3.22
*/
gboolean
gsk_render_node_iter_is_valid (GskRenderNodeIter *iter)
{
RealIter *riter = REAL_ITER (iter);
g_return_val_if_fail (iter != NULL, FALSE);
if (riter->root == NULL)
return FALSE;
return riter->root->age == riter->age;
}
/**
* gsk_render_node_iter_next:
* @iter: a #GskRenderNodeIter
* @child: (out) (transfer none): return location for a #GskRenderNode
*
* Advances the @iter and retrieves the next child of the root #GskRenderNode
* used to initialize the #GskRenderNodeIter.
*
* If the iterator could advance, this function returns %TRUE and sets the
* @child argument with the child #GskRenderNode.
*
* If the iterator could not advance, this function returns %FALSE and the
* contents of the @child argument are undefined.
*
* Returns: %TRUE if the iterator could advance, and %FALSE otherwise
*
* Since: 3.22
*/
gboolean
gsk_render_node_iter_next (GskRenderNodeIter *iter,
GskRenderNode **child)
{
RealIter *riter = REAL_ITER (iter);
g_return_val_if_fail (riter != NULL, FALSE);
g_return_val_if_fail (riter->root != NULL, FALSE);
g_return_val_if_fail (riter->root->age == riter->age, FALSE);
if (riter->current == NULL)
riter->current = riter->root->first_child;
else
riter->current = riter->current->next_sibling;
if (child != NULL)
*child = riter->current;
return riter->current != NULL;
}
/**
* gsk_render_node_iter_prev:
* @iter: a #GskRenderNodeIter
* @child: (out) (transfer none): return location for a #GskRenderNode
*
* Advances the @iter and retrieves the previous child of the root
* #GskRenderNode used to initialize the #GskRenderNodeIter.
*
* If the iterator could advance, this function returns %TRUE and sets the
* @child argument with the child #GskRenderNode.
*
* If the iterator could not advance, this function returns %FALSE and the
* contents of the @child argument are undefined.
*
* Returns: %TRUE if the iterator could advance, and %FALSE otherwise
*
* Since: 3.22
*/
gboolean
gsk_render_node_iter_prev (GskRenderNodeIter *iter,
GskRenderNode **child)
{
RealIter *riter = REAL_ITER (iter);
g_return_val_if_fail (riter != NULL, FALSE);
g_return_val_if_fail (riter->root != NULL, FALSE);
g_return_val_if_fail (riter->root->age == riter->age, FALSE);
if (riter->current == NULL)
riter->current = riter->root->last_child;
else
riter->current = riter->current->prev_sibling;
if (child != NULL)
*child = riter->current;
return riter->current != NULL;
}
/**
* gsk_render_node_iter_remove:
* @iter: a #GskRenderNodeIter
*
* Removes the child #GskRenderNode currently being visited by
* the iterator.
*
* Calling this function on an invalid #GskRenderNodeIter results
* in undefined behavior.
*
* Since: 3.22
*/
void
gsk_render_node_iter_remove (GskRenderNodeIter *iter)
{
RealIter *riter = REAL_ITER (iter);
GskRenderNode *tmp;
g_return_if_fail (riter != NULL);
g_return_if_fail (riter->root != NULL);
g_return_if_fail (riter->root->age == riter->age);
g_return_if_fail (riter->current != NULL);
tmp = riter->current;
if (tmp != NULL)
{
riter->current = tmp->prev_sibling;
gsk_render_node_remove_child (riter->root, tmp);
riter->age += 1;
/* Safety net */
g_assert (riter->age == riter->root->age);
}
}

45
gsk/gskrendernodeiter.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __GSK_RENDER_NODE_ITER_H__
#define __GSK_RENDER_NODE_ITER_H__
#include <gsk/gskrendernode.h>
G_BEGIN_DECLS
#define GSK_TYPE_RENDER_NODE_ITER (gsk_render_node_iter_get_type())
typedef struct _GskRenderNodeIter GskRenderNodeIter;
struct _GskRenderNodeIter
{
/*< private >*/
gpointer dummy1;
gpointer dummy2;
gint64 dummy3;
gpointer dummy4;
gpointer dummy5;
};
GDK_AVAILABLE_IN_3_22
GType gsk_render_node_iter_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_22
GskRenderNodeIter * gsk_render_node_iter_new (void);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_iter_free (GskRenderNodeIter *iter);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_iter_init (GskRenderNodeIter *iter,
GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
gboolean gsk_render_node_iter_is_valid (GskRenderNodeIter *iter);
GDK_AVAILABLE_IN_3_22
gboolean gsk_render_node_iter_prev (GskRenderNodeIter *iter,
GskRenderNode **child);
GDK_AVAILABLE_IN_3_22
gboolean gsk_render_node_iter_next (GskRenderNodeIter *iter,
GskRenderNode **child);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_iter_remove (GskRenderNodeIter *iter);
G_END_DECLS
#endif /* GSK_RENDER_NODE_ITER_H */

124
gsk/gskrendernodeprivate.h Normal file
View File

@@ -0,0 +1,124 @@
#ifndef __GSK_RENDER_NODE_PRIVATE_H__
#define __GSK_RENDER_NODE_PRIVATE_H__
#include "gskrendernode.h"
#include <cairo.h>
G_BEGIN_DECLS
#define GSK_RENDER_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_RENDER_NODE, GskRenderNodeClass))
#define GSK_IS_RENDER_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_RENDER_NODE))
#define GSK_RENDER_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_RENDER_NODE, GskRenderNodeClass))
typedef enum {
GSK_RENDER_NODE_CHANGES_UPDATE_BOUNDS = 1 << 0,
GSK_RENDER_NODE_CHANGES_UPDATE_TRANSFORM = 1 << 1,
GSK_RENDER_NODE_CHANGES_UPDATE_SURFACE = 1 << 2,
GSK_RENDER_NODE_CHANGES_UPDATE_OPACITY = 1 << 3,
GSK_RENDER_NODE_CHANGES_UPDATE_VISIBILITY = 1 << 4,
GSK_RENDER_NODE_CHANEGS_UPDATE_HIERARCHY = 1 << 5
} GskRenderNodeChanges;
typedef void (* GskRenderNodeInvalidateFunc) (GskRenderNode *node,
gpointer data);
struct _GskRenderNode
{
GObject parent_instance;
/* The graph */
GskRenderNode *parent;
GskRenderNode *first_child;
GskRenderNode *last_child;
GskRenderNode *prev_sibling;
GskRenderNode *next_sibling;
int n_children;
/* Use for debugging */
char *name;
/* Tag updated when adding/removing children */
gint64 age;
/* The contents of the node */
cairo_surface_t *surface;
/* Paint opacity */
double opacity;
/* Clip rectangle */
graphene_rect_t bounds;
/* Transformations relative to the root of the scene */
graphene_matrix_t world_matrix;
/* Transformations applied to the node */
graphene_matrix_t transform;
/* Transformations applied to the children of the node */
graphene_matrix_t child_transform;
/* Invalidation function for root node */
GskRenderNodeInvalidateFunc invalidate_func;
gpointer func_data;
GDestroyNotify destroy_func_data;
/* Descendants that need to be validated; only for root node */
GPtrArray *invalidated_descendants;
GskRenderNodeChanges last_state_change;
/* Bit fields; leave at the end */
gboolean hidden : 1;
gboolean opaque : 1;
gboolean transform_set : 1;
gboolean child_transform_set : 1;
gboolean needs_resize : 1;
gboolean needs_world_matrix_update : 1;
gboolean needs_content_update : 1;
gboolean needs_opacity_update : 1;
gboolean needs_visibility_update : 1;
};
struct _GskRenderNodeClass
{
GObjectClass parent_class;
void (* resize) (GskRenderNode *node);
};
void gsk_render_node_get_bounds (GskRenderNode *node,
graphene_rect_t *frame);
void gsk_render_node_get_transform (GskRenderNode *node,
graphene_matrix_t *mv);
double gsk_render_node_get_opacity (GskRenderNode *node);
cairo_surface_t *gsk_render_node_get_surface (GskRenderNode *node);
GskRenderNode *gsk_render_node_get_toplevel (GskRenderNode *node);
void gsk_render_node_update_world_matrix (GskRenderNode *node,
gboolean force);
void gsk_render_node_get_world_matrix (GskRenderNode *node,
graphene_matrix_t *mv);
void gsk_render_node_queue_invalidate (GskRenderNode *node,
GskRenderNodeChanges changes);
void gsk_render_node_set_invalidate_func (GskRenderNode *root,
GskRenderNodeInvalidateFunc validate_func,
gpointer data,
GDestroyNotify notify);
void gsk_render_node_validate (GskRenderNode *node);
void gsk_render_node_maybe_resize (GskRenderNode *node);
GskRenderNodeChanges gsk_render_node_get_current_state (GskRenderNode *node);
GskRenderNodeChanges gsk_render_node_get_last_state (GskRenderNode *node);
G_END_DECLS
#endif /* __GSK_RENDER_NODE_PRIVATE_H__ */

29
gsk/gsktypes.h Normal file
View File

@@ -0,0 +1,29 @@
/* 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/>.
*/
#ifndef __GSK_TYPES_H__
#define __GSK_TYPES_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <graphene.h>
#include <gdk/gdk.h>
#include <gsk/gskenums.h>
#endif /* __GSK_TYPES_H__ */

View File

@@ -0,0 +1,13 @@
#version 150
smooth in vec2 vUv;
out vec4 outputColor;
uniform mat4 mvp;
uniform sampler2D map;
uniform float alpha;
void main() {
outputColor = texture2D(map, vUv) * vec4(alpha);
}

View File

@@ -0,0 +1,16 @@
#version 150
uniform mat4 mvp;
uniform sampler2D map;
uniform float alpha;
in vec2 position;
in vec2 uv;
smooth out vec2 vUv;
void main() {
gl_Position = mvp * vec4(position, 0.0, 1.0);
vUv = vec2(uv.x, 1 - uv.y);
}

View File

@@ -7,6 +7,8 @@ AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_builddir)/gdk \
-I$(top_srcdir)/gdk \
-I$(top_builddir)/gsk \
-I$(top_srcdir)/gsk \
$(GTK_DEBUG_FLAGS) \
$(GTK_DEP_CFLAGS) \
$(GDK_DEP_CFLAGS)
@@ -16,6 +18,7 @@ DEPS = \
LDADD = \
$(top_builddir)/gtk/libgtk-4.la \
$(top_builddir)/gsk/libgsk-4.la \
$(top_builddir)/gdk/libgdk-4.la \
$(GTK_DEP_LIBS) \
$(GDK_DEP_LIBS) \
@@ -161,6 +164,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
listmodel \
testpopup \
testpopupat \
testgskrenderer \
$(NULL)
if USE_X11
@@ -280,6 +284,7 @@ testtitlebar_DEPENDENCIES = $(TEST_DEPS)
testwindowsize_DEPENDENCIES = $(TEST_DEPS)
listmodel_DEPENDENCIES = $(TEST_DEPS)
foreigndrawing_DEPENDENCIES = $(TEST_DEPS)
testgskrenderer_DEPENDENCIES = $(TEST_DEPS)
animated_resizing_SOURCES = \
animated-resizing.c \
@@ -494,6 +499,8 @@ listmodel_SOURCES = listmodel.c
foreigndrawing_SOURCES = foreigndrawing.c
testgskrenderer_SOURCES = testgskrenderer.c
EXTRA_DIST += \
gradient1.png \
testgtk.1 \

229
tests/testgskrenderer.c Normal file
View File

@@ -0,0 +1,229 @@
#include "config.h"
#include <graphene.h>
#include <cairo.h>
#include <gsk/gsk.h>
#include <gtk/gtk.h>
#define BOX_SIZE 50.f
#define PADDING 10.f
#define ROOT_SIZE BOX_SIZE * 2 + PADDING * 2
static void
create_color_surface (cairo_t *cr, GdkRGBA *color, int w, int h)
{
cairo_set_source_rgba (cr, color->red, color->green, color->blue, color->alpha);
cairo_rectangle (cr, 0, 0, w, h);
cairo_fill (cr);
}
static GskRenderer *
get_renderer (GtkWidget *widget)
{
GskRenderer *res;
res = g_object_get_data (G_OBJECT (widget), "-gsk-renderer");
if (res == NULL)
{
res = gsk_renderer_get_for_display (gtk_widget_get_display (widget));
g_object_set_data_full (G_OBJECT (widget), "-gsk-renderer",
res,
(GDestroyNotify) g_object_unref);
}
return res;
}
static void
create_scene (GskRenderer *renderer)
{
GskRenderNode *root, *node;
graphene_matrix_t ctm;
cairo_t *cr;
root = gsk_render_node_new ();
gsk_render_node_set_name (root, "Root node");
gsk_render_node_set_bounds (root, &(graphene_rect_t) {
.origin.x = 0.f,
.origin.y = 0.f,
.size.width = ROOT_SIZE,
.size.height = ROOT_SIZE
});
cr = gsk_render_node_get_draw_context (root);
create_color_surface (cr, &(GdkRGBA) { .red = 1, .green = 0, .blue = 0, .alpha = 1 }, ROOT_SIZE, ROOT_SIZE);
cairo_destroy (cr);
gsk_renderer_set_root_node (renderer, root);
g_object_set_data (G_OBJECT (renderer), "-gsk-renderer-root-node", root);
g_object_unref (root);
node = gsk_render_node_new ();
gsk_render_node_set_name (node, "Green node");
gsk_render_node_set_bounds (node, &(graphene_rect_t) {
.origin.x = 0.f,
.origin.y = 0.f,
.size.width = BOX_SIZE,
.size.height = BOX_SIZE
});
cr = gsk_render_node_get_draw_context (node);
create_color_surface (cr, &(GdkRGBA) { .red = 0, .green = 1, .blue = 0, .alpha = 1 }, BOX_SIZE, BOX_SIZE);
cairo_destroy (cr);
graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) { .x = -0.5, .y = -0.5, .z = 0.f });
gsk_render_node_set_transform (node, &ctm);
gsk_render_node_insert_child_at_pos (root, node, 0);
g_object_unref (node);
node = gsk_render_node_new ();
gsk_render_node_set_name (node, "Blue node");
gsk_render_node_set_bounds (node, &(graphene_rect_t) {
.origin.x = 0.f,
.origin.y = 0.f,
.size.width = BOX_SIZE,
.size.height = BOX_SIZE
});
cr = gsk_render_node_get_draw_context (node);
create_color_surface (cr, &(GdkRGBA) { .red = 0, .green = 0, .blue = 1, .alpha = 1 }, BOX_SIZE, BOX_SIZE);
cairo_destroy (cr);
graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) { .x = 0.5, .y = 0.5, .z = 0.f });
gsk_render_node_set_transform (node, &ctm);
gsk_render_node_insert_child_at_pos (root, node, 1);
g_object_unref (node);
}
static void
realize (GtkWidget *widget)
{
GskRenderer *renderer = get_renderer (widget);
gsk_renderer_set_window (renderer, gtk_widget_get_window (widget));
gsk_renderer_set_use_alpha (renderer, TRUE);
gsk_renderer_realize (renderer);
create_scene (renderer);
}
static void
unrealize (GtkWidget *widget)
{
g_object_set_data (G_OBJECT (widget), "-gsk-renderer", NULL);
}
static void
size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
GskRenderer *renderer = get_renderer (widget);
GskRenderNode *root;
graphene_matrix_t ctm;
gsk_renderer_set_viewport (renderer, &(graphene_rect_t) {
.origin.x = 0,
.origin.y = 0,
.size.width = allocation->width,
.size.height = allocation->height
});
graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) {
allocation->x,
allocation->y,
0.f
});
gsk_renderer_set_modelview (renderer, &ctm);
root = g_object_get_data (G_OBJECT (renderer), "-gsk-renderer-root-node");
if (root == NULL)
{
create_scene (renderer);
root = g_object_get_data (G_OBJECT (renderer), "-gsk-renderer-root-node");
}
graphene_matrix_init_translate (&ctm, &(graphene_point3d_t) {
.x = 0,
.y = 0,
.z = 0
});
gsk_render_node_set_transform (root, &ctm);
}
static gboolean
draw (GtkWidget *widget, cairo_t *cr)
{
GskRenderer *renderer = get_renderer (widget);
gsk_renderer_set_draw_context (renderer, cr);
gsk_renderer_render (renderer);
return TRUE;
}
static gboolean
fade_out (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer data)
{
static gint64 first_frame_time;
static gboolean flip = FALSE;
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
if (first_frame_time == 0)
{
first_frame_time = now;
return G_SOURCE_CONTINUE;
}
double start = first_frame_time;
double end = first_frame_time + (double) 1000000;
double progress = (now - first_frame_time) / (end - start);
if (flip)
progress = 1 - progress;
if (progress < 0 || progress >= 1)
{
first_frame_time = now;
flip = !flip;
return G_SOURCE_CONTINUE;
}
GskRenderer *renderer = get_renderer (widget);
GskRenderNode *root = gsk_renderer_get_root_node (renderer);
gsk_render_node_set_opacity (root, 1.0 - progress);
gtk_widget_queue_draw (widget);
return G_SOURCE_CONTINUE;
}
int
main (int argc, char *argv[])
{
GtkWidget *window, *area;
gtk_init (NULL, NULL);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
gtk_window_set_title (GTK_WINDOW (window), "GSK Renderer");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
area = gtk_drawing_area_new ();
gtk_widget_set_hexpand (area, TRUE);
gtk_widget_set_vexpand (area, TRUE);
gtk_widget_set_has_window (GTK_WIDGET (area), FALSE);
gtk_widget_set_app_paintable (GTK_WIDGET (area), TRUE);
gtk_container_add (GTK_CONTAINER (window), area);
g_signal_connect (area, "realize", G_CALLBACK (realize), NULL);
g_signal_connect (area, "unrealize", G_CALLBACK (unrealize), NULL);
g_signal_connect (area, "size-allocate", G_CALLBACK (size_allocate), NULL);
g_signal_connect (area, "draw", G_CALLBACK (draw), NULL);
gtk_widget_add_tick_callback (area, fade_out, NULL, NULL);
gtk_widget_show_all (window);
gtk_main ();
}