Compare commits
32 Commits
wip/matthi
...
wip/ebassi
Author | SHA1 | Date | |
---|---|---|---|
|
1d859a45ef | ||
|
d810989cfd | ||
|
ac9517c0aa | ||
|
7acc254d51 | ||
|
c672682668 | ||
|
5aaf111862 | ||
|
dee52aec7c | ||
|
4dd866c08f | ||
|
8d2df67388 | ||
|
d7a5c2ccf6 | ||
|
b5db5fb601 | ||
|
c9420c4b3b | ||
|
0634f221e3 | ||
|
0de191ca62 | ||
|
6e9988cb8b | ||
|
88f575d611 | ||
|
20848c5eea | ||
|
545a8892ce | ||
|
1319ded55e | ||
|
120e8454c3 | ||
|
4e07f8234d | ||
|
119654155e | ||
|
bb785ad689 | ||
|
7c64170a13 | ||
|
c6a83f1ba4 | ||
|
e7309b1474 | ||
|
9e50de3a56 | ||
|
c0c7cf46d6 | ||
|
b35b32f5dd | ||
|
c4262644ea | ||
|
a3c32b738a | ||
|
ad8b82f8bd |
@@ -1,7 +1,7 @@
|
||||
## Makefile.am for GTK+
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
SRC_SUBDIRS = gdk gtk libgail-util modules demos tests testsuite examples
|
||||
SRC_SUBDIRS = gdk gsk gtk libgail-util modules demos tests testsuite examples
|
||||
SUBDIRS = po po-properties $(SRC_SUBDIRS) docs m4macros build
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
@@ -46,7 +46,7 @@ gdk-x11-3.0.pc gdk-win32-3.0.pc gdk-quartz-3.0.pc gdk-broadway-3.0.pc gdk-waylan
|
||||
cp gdk-3.0.pc $@
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = gdk-3.0.pc gtk+-3.0.pc gail-3.0.pc
|
||||
pkgconfig_DATA = gdk-3.0.pc gsk-3.0.pc gtk+-3.0.pc gail-3.0.pc
|
||||
pkgconfig_DATA += ${GDK_BACKENDS:%=gtk+-%-3.0.pc}
|
||||
pkgconfig_DATA += ${GDK_BACKENDS:%=gdk-%-3.0.pc}
|
||||
|
||||
@@ -63,6 +63,7 @@ DISTCLEANFILES = \
|
||||
gtk+-broadway-3.0.pc \
|
||||
gtk+-wayland-3.0.pc \
|
||||
gtk+-mir-3.0.pc \
|
||||
gsk-3.0.pc \
|
||||
gdk-3.0.pc \
|
||||
gdk-x11-3.0.pc \
|
||||
gdk-win32-3.0.pc \
|
||||
|
26
configure.ac
26
configure.ac
@@ -64,6 +64,7 @@ m4_define([wayland_protocols_required_version], [1.3])
|
||||
m4_define([mirclient_required_version], [0.11.0])
|
||||
m4_define([mircookie_required_version], [0.17.0])
|
||||
m4_define([epoxy_required_version], [1.0])
|
||||
m4_define([graphene_required_version], [1.2])
|
||||
GLIB_REQUIRED_VERSION=glib_required_version
|
||||
PANGO_REQUIRED_VERSION=pango_required_version
|
||||
ATK_REQUIRED_VERSION=atk_required_version
|
||||
@@ -1365,6 +1366,26 @@ AC_SUBST(GDK_EXTRA_CFLAGS)
|
||||
AC_SUBST(GDK_DEP_LIBS)
|
||||
AC_SUBST(GDK_DEP_CFLAGS)
|
||||
|
||||
########################################
|
||||
# Check for GSK flags
|
||||
########################################
|
||||
|
||||
GSK_EXTRA_LIBS=
|
||||
GSK_EXTRA_CFLAGS=
|
||||
|
||||
GSK_PACKAGES="gdk-pixbuf-2.0 >= gdk_pixbuf_required_version cairo >= cairo_required_version cairo-gobject >= cairo_required_version graphene-1.0 >= graphene_required_version"
|
||||
GSK_PRIVATE_PACKAGES="epoxy >= epoxy_required_version"
|
||||
|
||||
PKG_CHECK_MODULES(GSK_DEP, $PANGO_PACKAGES $GSK_PACKAGES $GSK_PRIVATE_PACKAGES)
|
||||
GSK_DEP_LIBS="$GSK_EXTRA_LIBS $GSK_DEP_LIBS $MATH_LIB"
|
||||
GSK_DEP_CFLAGS="$GSK_DEP_CFLAGS $GSK_EXTRA_CFLAGS"
|
||||
|
||||
AC_SUBST(GSK_PACKAGES)
|
||||
AC_SUBST(GSK_PRIVATE_PACKAGES)
|
||||
AC_SUBST(GSK_EXTRA_LIBS)
|
||||
AC_SUBST(GSK_EXTRA_CFLAGS)
|
||||
AC_SUBST(GSK_DEP_LIBS)
|
||||
AC_SUBST(GSK_DEP_CFLAGS)
|
||||
|
||||
########################################
|
||||
# Check for Accessibility Toolkit flags
|
||||
@@ -1379,7 +1400,7 @@ fi
|
||||
PKG_CHECK_MODULES(ATK, $ATK_PACKAGES)
|
||||
|
||||
GTK_PACKAGES="atk >= atk_required_version cairo >= cairo_required_version cairo-gobject >= cairo_required_version gdk-pixbuf-2.0 >= gdk_pixbuf_required_version gio-2.0 >= glib_required_version"
|
||||
GTK_PRIVATE_PACKAGES="$ATK_PACKAGES $WAYLAND_PACKAGES $MIR_PACKAGES epoxy >= epoxy_required_version"
|
||||
GTK_PRIVATE_PACKAGES="$ATK_PACKAGES $WAYLAND_PACKAGES $MIR_PACKAGES epoxy >= epoxy_required_version graphene-1.0 >= graphene_required_version"
|
||||
if test "x$enable_x11_backend" = xyes -o "x$enable_wayland_backend" = xyes; then
|
||||
GTK_PRIVATE_PACKAGES="$GTK_PRIVATE_PACKAGES pangoft2"
|
||||
fi
|
||||
@@ -1892,6 +1913,7 @@ config.h.win32
|
||||
gtk-zip.sh
|
||||
Makefile
|
||||
gdk-3.0.pc
|
||||
gsk-3.0.pc
|
||||
gtk+-3.0.pc
|
||||
gtk+-unix-print-3.0.pc
|
||||
gail-3.0.pc
|
||||
@@ -1925,6 +1947,7 @@ testsuite/css/parser/Makefile
|
||||
testsuite/css/nodes/Makefile
|
||||
testsuite/css/style/Makefile
|
||||
testsuite/gdk/Makefile
|
||||
testsuite/gsk/Makefile
|
||||
testsuite/gtk/Makefile
|
||||
testsuite/reftests/Makefile
|
||||
testsuite/tools/Makefile
|
||||
@@ -1957,6 +1980,7 @@ gdk/quartz/Makefile
|
||||
gdk/wayland/Makefile
|
||||
gdk/mir/Makefile
|
||||
gdk/gdkversionmacros.h
|
||||
gsk/Makefile
|
||||
gtk/Makefile
|
||||
gtk/makefile.msc
|
||||
gtk/gtkversion.h
|
||||
|
@@ -86,6 +86,13 @@ void gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GdkDrawingContext * gdk_cairo_get_drawing_context (cairo_t *cr);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gdk_cairo_surface_upload_to_gl (cairo_surface_t *surface,
|
||||
int target,
|
||||
int width,
|
||||
int height,
|
||||
GdkGLContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_CAIRO_H__ */
|
||||
|
48
gdk/gdkgl.c
48
gdk/gdkgl.c
@@ -814,3 +814,51 @@ gdk_gl_texture_from_surface (cairo_surface_t *surface,
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
glDeleteTextures (1, &texture_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cairo_surface_upload_to_gl:
|
||||
* @surface: a Cairo surface
|
||||
* @target: a GL texture target
|
||||
* @width: the width of the texture @target
|
||||
* @height: the height of the texture @target
|
||||
* @context: (nullable): a #GdkGLContext, or %NULL to use the currently
|
||||
* bound context
|
||||
*
|
||||
* Uploads the contents of a Cairo @surface to a GL texture @target.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
void
|
||||
gdk_cairo_surface_upload_to_gl (cairo_surface_t *surface,
|
||||
int target,
|
||||
int width,
|
||||
int height,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_surface_t *tmp;
|
||||
double sx, sy;
|
||||
double device_x_offset, device_y_offset;
|
||||
|
||||
g_return_if_fail (surface != NULL);
|
||||
g_return_if_fail (context == NULL || GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
if (context == NULL)
|
||||
context = gdk_gl_context_get_current ();
|
||||
|
||||
cairo_surface_flush (surface);
|
||||
|
||||
sx = sy = 1;
|
||||
cairo_surface_get_device_scale (surface, &sx, &sy);
|
||||
cairo_surface_get_device_offset (surface, &device_x_offset, &device_y_offset);
|
||||
|
||||
rect.x = (int) device_x_offset;
|
||||
rect.y = (int) device_y_offset;
|
||||
rect.width = width * sx;
|
||||
rect.height = height * sx;
|
||||
tmp = cairo_surface_map_to_image (surface, &rect);
|
||||
|
||||
gdk_gl_context_upload_texture (context, tmp, rect.width, rect.height, target);
|
||||
|
||||
cairo_surface_unmap_image (surface, tmp);
|
||||
}
|
||||
|
@@ -470,6 +470,8 @@ struct _GdkPoint
|
||||
* @GDK_GL_ERROR_NOT_AVAILABLE: OpenGL support is not available
|
||||
* @GDK_GL_ERROR_UNSUPPORTED_FORMAT: The requested visual format is not supported
|
||||
* @GDK_GL_ERROR_UNSUPPORTED_PROFILE: The requested profile is not supported
|
||||
* @GDK_GL_ERROR_COMPILATION_FAILED: The shader compilation failed (available since 3.22)
|
||||
* @GDK_GL_ERROR_LINK_FAILED: The shader linking failed (available since 3.22)
|
||||
*
|
||||
* Error enumeration for #GdkGLContext.
|
||||
*
|
||||
@@ -478,7 +480,9 @@ struct _GdkPoint
|
||||
typedef enum {
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
GDK_GL_ERROR_UNSUPPORTED_PROFILE
|
||||
GDK_GL_ERROR_UNSUPPORTED_PROFILE,
|
||||
GDK_GL_ERROR_COMPILATION_FAILED,
|
||||
GDK_GL_ERROR_LINK_FAILED
|
||||
} GdkGLError;
|
||||
|
||||
/**
|
||||
|
13
gsk-3.0.pc.in
Normal file
13
gsk-3.0.pc.in
Normal file
@@ -0,0 +1,13 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
targets=@GDK_BACKENDS@
|
||||
|
||||
Name: GSK
|
||||
Description: GTK+ Scene Graph Kit
|
||||
Version: @VERSION@
|
||||
Requires: gdk-@GTK_API_VERSION@ @GSK_PACKAGES@
|
||||
Requires.private: @GSK_PRIVATE_PACKAGES@
|
||||
Libs: -L${libdir} -lgsk-3 @GSK_EXTRA_LIBS@
|
||||
Cflags: -I${includedir}/gsk-@GTK_API_VERSION@ @GSK_EXTRA_CFLAGS@
|
159
gsk/Makefile.am
Normal file
159
gsk/Makefile.am
Normal file
@@ -0,0 +1,159 @@
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DG_LOG_DOMAIN=\"Gsk\" \
|
||||
-DGSK_COMPILATION \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/gdk \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_builddir)/gsk \
|
||||
$(GTK_DEBUG_FLAGS) \
|
||||
$(GSK_DEP_CFLAGS)
|
||||
|
||||
# libtool stuff: set version and export symbols for resolving
|
||||
# since automake doesn't support conditionalized libsomething_la_LDFLAGS
|
||||
# we use the general approach here
|
||||
LDADD = \
|
||||
$(GTK_LINK_FLAGS) \
|
||||
-version-info $(LT_VERSION_INFO) \
|
||||
-export-dynamic \
|
||||
-rpath $(libdir) \
|
||||
$(no_undefined)
|
||||
|
||||
BUILT_SOURCES =
|
||||
|
||||
CLEANFILES =
|
||||
DISTCLEANFILES =
|
||||
|
||||
lib_LTLIBRARIES =
|
||||
|
||||
gsk_public_source_h = \
|
||||
gskenums.h \
|
||||
gsklayer.h \
|
||||
gskrenderer.h \
|
||||
gskrendernode.h \
|
||||
gskrendernodeiter.h \
|
||||
gsktypes.h
|
||||
gsk_private_source_h = \
|
||||
gskcairorendererprivate.h \
|
||||
gskdebugprivate.h \
|
||||
gskglrendererprivate.h \
|
||||
gskprivate.h \
|
||||
gskrendererprivate.h \
|
||||
gskrendernodeprivate.h \
|
||||
gskshaderbuilderprivate.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 \
|
||||
gsklayer.c \
|
||||
gskrenderer.c \
|
||||
gskrendernode.c \
|
||||
gskrendernodeiter.c \
|
||||
gskshaderbuilder.c
|
||||
|
||||
all_sources = \
|
||||
$(gsk_public_source_h) \
|
||||
$(gsk_private_source_h) \
|
||||
$(gsk_built_source_h) \
|
||||
$(gsk_private_source_c) \
|
||||
$(gsk_source_c)
|
||||
|
||||
BUILT_SOURCES += $(gsk_built_source_h) $(gsk_built_source_c) gsk.resources.xml
|
||||
|
||||
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_3_la_SOURCES = $(all_sources)
|
||||
nodist_libgsk_3_la_SOURCES = $(gsk_built_source_h) $(gsk_built_source_c)
|
||||
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)
|
||||
|
||||
lib_LTLIBRARIES += libgsk-3.la
|
||||
|
||||
gskincludedir = $(includedir)/gtk-3.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 = $(filter-out $(wildcard *private.h),$(all_sources))
|
||||
|
||||
Gsk-3.0.gir: libgsk-3.la Makefile
|
||||
Gsk_3_0_gir_SCANNERFLAGS = \
|
||||
--add-include-path=$(top_builddir)/gdk \
|
||||
--include-uninstalled=$(top_builddir)/gdk/Gdk-3.0.gir \
|
||||
--c-include="gsk/gsk.h"
|
||||
Gsk_3_0_gir_LIBS = libgsk-3.la $(top_builddir)/gdk/libgdk-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
|
||||
|
||||
girdir = $(datadir)/gir-1.0
|
||||
gir_DATA = $(INTROSPECTION_GIRS)
|
||||
|
||||
typelibsdir = $(libdir)/girepository-1.0
|
||||
typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
|
||||
|
||||
CLEANFILES += $(gir_DATA) $(typelibs_DATA)
|
||||
|
||||
endif
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
35
gsk/gsk.h
Normal file
35
gsk/gsk.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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/gsktypes.h>
|
||||
#include <gsk/gskenums.h>
|
||||
#include <gsk/gskenumtypes.h>
|
||||
|
||||
#include <gsk/gskrenderer.h>
|
||||
#include <gsk/gskrendernode.h>
|
||||
#include <gsk/gskrendernodeiter.h>
|
||||
|
||||
#include <gsk/gsklayer.h>
|
||||
|
||||
#undef __GSK_H_INSIDE__
|
||||
|
||||
#endif /* __GSK_H__ */
|
180
gsk/gskcairorenderer.c
Normal file
180
gsk/gskcairorenderer.c
Normal file
@@ -0,0 +1,180 @@
|
||||
#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_render (GskRenderer *renderer,
|
||||
GskRenderNode *root,
|
||||
GdkDrawingContext *context)
|
||||
{
|
||||
GskCairoRenderer *self = GSK_CAIRO_RENDERER (renderer);
|
||||
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
|
||||
|
||||
gsk_renderer_get_viewport (renderer, &self->viewport);
|
||||
|
||||
if (gsk_renderer_get_auto_clear (renderer))
|
||||
{
|
||||
cairo_save (cr);
|
||||
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_restore (cr);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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->render = gsk_cairo_renderer_render;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cairo_renderer_init (GskCairoRenderer *self)
|
||||
{
|
||||
|
||||
}
|
26
gsk/gskcairorendererprivate.h
Normal file
26
gsk/gskcairorendererprivate.h
Normal 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__ */
|
59
gsk/gskdebug.c
Normal file
59
gsk/gskdebug.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#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 },
|
||||
{ "shaders", GSK_RENDERING_MODE_SHADERS },
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
44
gsk/gskdebugprivate.h
Normal file
44
gsk/gskdebugprivate.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#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,
|
||||
GSK_RENDERING_MODE_SHADERS = 1 << 1
|
||||
} 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__ */
|
85
gsk/gskenums.h
Normal file
85
gsk/gskenums.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* 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;
|
||||
|
||||
/**
|
||||
* GskBlendMode:
|
||||
* @GSK_BLEND_MODE_DEFAULT: The default blend mode, which specifies no blending
|
||||
* @GSK_BLEND_MODE_MULTIPLY: The source color is multiplied by the destination
|
||||
* and replaces the destination
|
||||
* @GSK_BLEND_MODE_SCREEN:
|
||||
* @GSK_BLEND_MODE_OVERLAY: ...
|
||||
* @GSK_BLEND_MODE_DARKEN: ...
|
||||
* @GSK_BLEND_MODE_LIGHTEN: ...
|
||||
* @GSK_BLEND_MODE_COLOR_DODGE: ...
|
||||
* @GSK_BLEND_MODE_COLOR_BURN: ...
|
||||
* @GSK_BLEND_MODE_HARD_LIGHT: ...
|
||||
* @GSK_BLEND_MODE_SOFT_LIGHT: ...
|
||||
* @GSK_BLEND_MODE_DIFFERENCE: ...
|
||||
* @GSK_BLEND_MODE_EXCLUSION: ...
|
||||
*
|
||||
* The blend modes available for render nodes.
|
||||
*
|
||||
* The implementation of each blend mode is deferred to the
|
||||
* rendering pipeline.
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
typedef enum {
|
||||
GSK_BLEND_MODE_DEFAULT = 0,
|
||||
|
||||
GSK_BLEND_MODE_MULTIPLY,
|
||||
GSK_BLEND_MODE_SCREEN,
|
||||
GSK_BLEND_MODE_OVERLAY,
|
||||
GSK_BLEND_MODE_DARKEN,
|
||||
GSK_BLEND_MODE_LIGHTEN,
|
||||
GSK_BLEND_MODE_COLOR_DODGE,
|
||||
GSK_BLEND_MODE_COLOR_BURN,
|
||||
GSK_BLEND_MODE_HARD_LIGHT,
|
||||
GSK_BLEND_MODE_SOFT_LIGHT,
|
||||
GSK_BLEND_MODE_DIFFERENCE,
|
||||
GSK_BLEND_MODE_EXCLUSION
|
||||
} GskBlendMode;
|
||||
|
||||
#endif /* __GSK_TYPES_H__ */
|
38
gsk/gskenumtypes.c.template
Normal file
38
gsk/gskenumtypes.c.template
Normal 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 ***/
|
24
gsk/gskenumtypes.h.template
Normal file
24
gsk/gskenumtypes.h.template
Normal 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 ***/
|
978
gsk/gskglrenderer.c
Normal file
978
gsk/gskglrenderer.c
Normal file
@@ -0,0 +1,978 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskglrendererprivate.h"
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskenums.h"
|
||||
#include "gskrendererprivate.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
#include "gskrendernodeiter.h"
|
||||
#include "gskshaderbuilderprivate.h"
|
||||
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
#define SHADER_VERSION_GLES 110
|
||||
#define SHADER_VERSION_GL_LEGACY 120
|
||||
#define SHADER_VERSION_GL3 150
|
||||
|
||||
typedef struct {
|
||||
guint vao_id;
|
||||
guint buffer_id;
|
||||
guint texture_id;
|
||||
guint program_id;
|
||||
|
||||
guint mvp_location;
|
||||
guint map_location;
|
||||
guint parentMap_location;
|
||||
guint uv_location;
|
||||
guint position_location;
|
||||
guint alpha_location;
|
||||
guint blendMode_location;
|
||||
} RenderData;
|
||||
|
||||
typedef struct {
|
||||
/* Back pointer to the node, only meant for comparison */
|
||||
GskRenderNode *node;
|
||||
|
||||
graphene_point3d_t min;
|
||||
graphene_point3d_t max;
|
||||
|
||||
graphene_size_t size;
|
||||
|
||||
graphene_matrix_t mvp;
|
||||
|
||||
gboolean opaque : 1;
|
||||
float opacity;
|
||||
float z;
|
||||
|
||||
const char *name;
|
||||
|
||||
GskBlendMode blend_mode;
|
||||
|
||||
RenderData render_data;
|
||||
RenderData *parent_data;
|
||||
} RenderItem;
|
||||
|
||||
enum {
|
||||
MVP,
|
||||
MAP,
|
||||
PARENT_MAP,
|
||||
ALPHA,
|
||||
BLEND_MODE,
|
||||
N_UNIFORMS
|
||||
};
|
||||
|
||||
enum {
|
||||
POSITION,
|
||||
UV,
|
||||
N_ATTRIBUTES
|
||||
};
|
||||
|
||||
struct _GskGLRenderer
|
||||
{
|
||||
GskRenderer parent_instance;
|
||||
|
||||
GdkGLContext *context;
|
||||
|
||||
graphene_matrix_t mvp;
|
||||
graphene_frustum_t frustum;
|
||||
|
||||
guint frame_buffer;
|
||||
guint render_buffer;
|
||||
guint depth_stencil_buffer;
|
||||
guint texture_id;
|
||||
|
||||
GQuark uniforms[N_UNIFORMS];
|
||||
GQuark attributes[N_ATTRIBUTES];
|
||||
|
||||
GskShaderBuilder *shader_builder;
|
||||
|
||||
int blend_program_id;
|
||||
int blit_program_id;
|
||||
|
||||
guint vao_id;
|
||||
|
||||
GArray *opaque_render_items;
|
||||
GArray *transparent_render_items;
|
||||
|
||||
gboolean has_buffers : 1;
|
||||
gboolean has_alpha : 1;
|
||||
gboolean has_stencil_buffer : 1;
|
||||
gboolean has_depth_buffer : 1;
|
||||
};
|
||||
|
||||
struct _GskGLRendererClass
|
||||
{
|
||||
GskRendererClass parent_class;
|
||||
};
|
||||
|
||||
static void render_item_clear (gpointer data_);
|
||||
|
||||
G_DEFINE_TYPE (GskGLRenderer, gsk_gl_renderer, GSK_TYPE_RENDERER)
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_dispose (GObject *gobject)
|
||||
{
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (gobject);
|
||||
|
||||
g_clear_object (&self->context);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_renderer_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_create_buffers (GskGLRenderer *self)
|
||||
{
|
||||
if (self->has_buffers)
|
||||
return;
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Creating buffers\n"));
|
||||
|
||||
glGenFramebuffersEXT (1, &self->frame_buffer);
|
||||
|
||||
if (gsk_renderer_get_use_alpha (GSK_RENDERER (self)))
|
||||
{
|
||||
if (self->texture_id == 0)
|
||||
glGenTextures (1, &self->texture_id);
|
||||
|
||||
if (self->render_buffer != 0)
|
||||
{
|
||||
glDeleteRenderbuffersEXT (1, &self->render_buffer);
|
||||
self->render_buffer = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->render_buffer == 0)
|
||||
glGenRenderbuffersEXT (1, &self->render_buffer);
|
||||
|
||||
if (self->texture_id != 0)
|
||||
{
|
||||
glDeleteTextures (1, &self->texture_id);
|
||||
self->texture_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->has_depth_buffer || self->has_stencil_buffer)
|
||||
{
|
||||
if (self->depth_stencil_buffer == 0)
|
||||
glGenRenderbuffersEXT (1, &self->depth_stencil_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->depth_stencil_buffer != 0)
|
||||
{
|
||||
glDeleteRenderbuffersEXT (1, &self->depth_stencil_buffer);
|
||||
self->depth_stencil_buffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We only have one VAO at the moment */
|
||||
glGenVertexArrays (1, &self->vao_id);
|
||||
glBindVertexArray (self->vao_id);
|
||||
|
||||
self->has_buffers = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_allocate_buffers (GskGLRenderer *self,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (self->context == NULL)
|
||||
return;
|
||||
|
||||
if (self->texture_id != 0)
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, self->texture_id);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->context))
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
else
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||
}
|
||||
|
||||
if (self->render_buffer != 0)
|
||||
{
|
||||
glBindRenderbuffer (GL_RENDERBUFFER, self->render_buffer);
|
||||
glRenderbufferStorage (GL_RENDERBUFFER, GL_RGB8, width, height);
|
||||
}
|
||||
|
||||
if (self->has_depth_buffer || self->has_stencil_buffer)
|
||||
{
|
||||
glBindRenderbuffer (GL_RENDERBUFFER, self->depth_stencil_buffer);
|
||||
|
||||
if (self->has_stencil_buffer)
|
||||
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
else
|
||||
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_attach_buffers (GskGLRenderer *self)
|
||||
{
|
||||
gsk_gl_renderer_create_buffers (self);
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Attaching buffers\n"));
|
||||
|
||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, self->frame_buffer);
|
||||
|
||||
if (self->texture_id != 0)
|
||||
{
|
||||
glFramebufferTexture2D (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D, self->texture_id, 0);
|
||||
}
|
||||
else if (self->render_buffer != 0)
|
||||
{
|
||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_RENDERBUFFER_EXT, self->render_buffer);
|
||||
}
|
||||
|
||||
if (self->depth_stencil_buffer != 0)
|
||||
{
|
||||
if (self->has_depth_buffer)
|
||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, self->depth_stencil_buffer);
|
||||
|
||||
if (self->has_stencil_buffer)
|
||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, self->depth_stencil_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_destroy_buffers (GskGLRenderer *self)
|
||||
{
|
||||
if (self->context == NULL)
|
||||
return;
|
||||
|
||||
if (!self->has_buffers)
|
||||
return;
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Destroying buffers\n"));
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
if (self->vao_id != 0)
|
||||
{
|
||||
glDeleteVertexArrays (1, &self->vao_id);
|
||||
self->vao_id = 0;
|
||||
}
|
||||
|
||||
if (self->depth_stencil_buffer != 0)
|
||||
{
|
||||
glDeleteRenderbuffersEXT (1, &self->depth_stencil_buffer);
|
||||
self->depth_stencil_buffer = 0;
|
||||
}
|
||||
|
||||
if (self->render_buffer != 0)
|
||||
{
|
||||
glDeleteRenderbuffersEXT (1, &self->render_buffer);
|
||||
self->render_buffer = 0;
|
||||
}
|
||||
|
||||
if (self->texture_id != 0)
|
||||
{
|
||||
glDeleteTextures (1, &self->texture_id);
|
||||
self->texture_id = 0;
|
||||
}
|
||||
|
||||
if (self->frame_buffer != 0)
|
||||
{
|
||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
|
||||
glDeleteFramebuffersEXT (1, &self->frame_buffer);
|
||||
self->frame_buffer = 0;
|
||||
}
|
||||
|
||||
self->has_buffers = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_renderer_create_programs (GskGLRenderer *self)
|
||||
{
|
||||
GskShaderBuilder *builder;
|
||||
GError *error = NULL;
|
||||
gboolean res = FALSE;
|
||||
|
||||
builder = gsk_shader_builder_new ();
|
||||
|
||||
gsk_shader_builder_set_resource_base_path (builder, "/org/gtk/libgsk/glsl");
|
||||
|
||||
self->uniforms[MVP] = gsk_shader_builder_add_uniform (builder, "mvp");
|
||||
self->uniforms[MAP] = gsk_shader_builder_add_uniform (builder, "map");
|
||||
self->uniforms[PARENT_MAP] = gsk_shader_builder_add_uniform (builder, "parentMap");
|
||||
self->uniforms[ALPHA] = gsk_shader_builder_add_uniform (builder, "alpha");
|
||||
self->uniforms[BLEND_MODE] = gsk_shader_builder_add_uniform (builder, "blendMode");
|
||||
|
||||
self->attributes[POSITION] = gsk_shader_builder_add_attribute (builder, "position");
|
||||
self->attributes[UV] = gsk_shader_builder_add_attribute (builder, "uv");
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->context))
|
||||
{
|
||||
gsk_shader_builder_set_version (builder, SHADER_VERSION_GLES);
|
||||
gsk_shader_builder_set_vertex_preamble (builder, "es2_common.vs.glsl");
|
||||
gsk_shader_builder_set_fragment_preamble (builder, "es2_common.fs.glsl");
|
||||
gsk_shader_builder_add_define (builder, "GSK_GLES", "1");
|
||||
}
|
||||
else if (gdk_gl_context_is_legacy (self->context))
|
||||
{
|
||||
gsk_shader_builder_set_version (builder, SHADER_VERSION_GL_LEGACY);
|
||||
gsk_shader_builder_set_vertex_preamble (builder, "gl_common.vs.glsl");
|
||||
gsk_shader_builder_set_fragment_preamble (builder, "gl_common.fs.glsl");
|
||||
gsk_shader_builder_add_define (builder, "GSK_LEGACY", "1");
|
||||
}
|
||||
else
|
||||
{
|
||||
gsk_shader_builder_set_version (builder, SHADER_VERSION_GL3);
|
||||
gsk_shader_builder_set_vertex_preamble (builder, "gl3_common.vs.glsl");
|
||||
gsk_shader_builder_set_fragment_preamble (builder, "gl3_common.fs.glsl");
|
||||
gsk_shader_builder_add_define (builder, "GSK_GL3", "1");
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_RENDER_MODE_CHECK (SHADERS))
|
||||
gsk_shader_builder_add_define (builder, "GSK_DEBUG", "1");
|
||||
#endif
|
||||
|
||||
self->blend_program_id =
|
||||
gsk_shader_builder_create_program (builder, "blend.vs.glsl", "blend.fs.glsl", &error);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_critical ("Unable to create 'blend' program: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (builder);
|
||||
goto out;
|
||||
}
|
||||
|
||||
self->blit_program_id =
|
||||
gsk_shader_builder_create_program (builder, "blit.vs.glsl", "blit.fs.glsl", &error);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_critical ("Unable to create 'blit' program: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (builder);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Keep a pointer to query for the uniform and attribute locations
|
||||
* when rendering the scene
|
||||
*/
|
||||
self->shader_builder = builder;
|
||||
|
||||
res = TRUE;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_destroy_programs (GskGLRenderer *self)
|
||||
{
|
||||
g_clear_object (&self->shader_builder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_renderer_realize (GskRenderer *renderer)
|
||||
{
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
|
||||
GError *error = NULL;
|
||||
|
||||
/* If we didn't get a GdkGLContext before realization, try creating
|
||||
* one now, for our exclusive use.
|
||||
*/
|
||||
if (self->context == NULL)
|
||||
{
|
||||
GdkWindow *window = gsk_renderer_get_window (renderer);
|
||||
|
||||
if (window == NULL)
|
||||
return FALSE;
|
||||
|
||||
self->context = gdk_window_create_gl_context (window, &error);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_critical ("Unable to create GL context for renderer: %s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gdk_gl_context_realize (self->context, &error);
|
||||
if (error != NULL)
|
||||
{
|
||||
g_critical ("Unable to realize GL renderer: %s", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Creating buffers and programs\n"));
|
||||
if (!gsk_gl_renderer_create_programs (self))
|
||||
return FALSE;
|
||||
|
||||
gsk_gl_renderer_create_buffers (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_unrealize (GskRenderer *renderer)
|
||||
{
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
|
||||
|
||||
if (self->context == NULL)
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
g_clear_pointer (&self->opaque_render_items, g_array_unref);
|
||||
g_clear_pointer (&self->transparent_render_items, g_array_unref);
|
||||
|
||||
gsk_gl_renderer_destroy_buffers (self);
|
||||
gsk_gl_renderer_destroy_programs (self);
|
||||
|
||||
if (self->context == gdk_gl_context_get_current ())
|
||||
gdk_gl_context_clear_current ();
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_resize_viewport (GskGLRenderer *self,
|
||||
const graphene_rect_t *viewport)
|
||||
{
|
||||
GSK_NOTE (OPENGL, g_print ("glViewport(0, 0, %g, %g)\n",
|
||||
viewport->size.width,
|
||||
viewport->size.height));
|
||||
|
||||
glViewport (viewport->origin.x, viewport->origin.y,
|
||||
viewport->size.width, viewport->size.height);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_update_frustum (GskGLRenderer *self,
|
||||
const graphene_matrix_t *modelview,
|
||||
const graphene_matrix_t *projection)
|
||||
{
|
||||
GSK_NOTE (OPENGL, g_print ("Updating the modelview/projection\n"));
|
||||
|
||||
graphene_matrix_multiply (projection, modelview, &self->mvp);
|
||||
|
||||
graphene_frustum_init_from_matrix (&self->frustum, &self->mvp);
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Renderer MVP:\n"));
|
||||
GSK_NOTE (OPENGL, graphene_matrix_print (&self->mvp));
|
||||
}
|
||||
|
||||
static void
|
||||
render_item_clear (gpointer data_)
|
||||
{
|
||||
RenderItem *item = data_;
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Destroying render item [%p] buffer %u\n",
|
||||
item,
|
||||
item->render_data.buffer_id));
|
||||
glDeleteBuffers (1, &item->render_data.buffer_id);
|
||||
item->render_data.buffer_id = 0;
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Destroying render item [%p] texture %u\n",
|
||||
item,
|
||||
item->render_data.texture_id));
|
||||
glDeleteTextures (1, &item->render_data.texture_id);
|
||||
item->render_data.texture_id = 0;
|
||||
|
||||
graphene_matrix_init_identity (&item->mvp);
|
||||
|
||||
item->opacity = 1;
|
||||
}
|
||||
|
||||
#define N_VERTICES 6
|
||||
|
||||
static void
|
||||
render_item (RenderItem *item)
|
||||
{
|
||||
struct vertex_info {
|
||||
float position[2];
|
||||
float uv[2];
|
||||
};
|
||||
float mvp[16];
|
||||
|
||||
glBindVertexArray (item->render_data.vao_id);
|
||||
|
||||
/* Generate the vertex buffer for the texture quad */
|
||||
if (item->render_data.buffer_id == 0)
|
||||
{
|
||||
struct vertex_info vertex_data[] = {
|
||||
{ { item->min.x, item->min.y }, { 0, 0 }, },
|
||||
{ { item->min.x, item->max.y }, { 0, 1 }, },
|
||||
{ { item->max.x, item->min.y }, { 1, 0 }, },
|
||||
|
||||
{ { item->max.x, item->max.y }, { 1, 1 }, },
|
||||
{ { item->min.x, item->max.y }, { 0, 1 }, },
|
||||
{ { item->max.x, item->min.y }, { 1, 0 }, },
|
||||
};
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Creating quad for render item [%p]\n", item));
|
||||
|
||||
glGenBuffers (1, &(item->render_data.buffer_id));
|
||||
glBindBuffer (GL_ARRAY_BUFFER, item->render_data.buffer_id);
|
||||
|
||||
/* The data won't change */
|
||||
glBufferData (GL_ARRAY_BUFFER, sizeof (vertex_data), vertex_data, GL_STATIC_DRAW);
|
||||
|
||||
/* Set up the buffers with the computed position and texels */
|
||||
glEnableVertexAttribArray (item->render_data.position_location);
|
||||
glVertexAttribPointer (item->render_data.position_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof (struct vertex_info),
|
||||
(void *) G_STRUCT_OFFSET (struct vertex_info, position));
|
||||
glEnableVertexAttribArray (item->render_data.uv_location);
|
||||
glVertexAttribPointer (item->render_data.uv_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof (struct vertex_info),
|
||||
(void *) G_STRUCT_OFFSET (struct vertex_info, uv));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already set up the vertex buffer, so we just need to reuse it */
|
||||
glBindBuffer (GL_ARRAY_BUFFER, item->render_data.buffer_id);
|
||||
glEnableVertexAttribArray (item->render_data.position_location);
|
||||
glEnableVertexAttribArray (item->render_data.uv_location);
|
||||
}
|
||||
|
||||
glUseProgram (item->render_data.program_id);
|
||||
|
||||
/* Use texture unit 0 for the sampler */
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, item->render_data.texture_id);
|
||||
glUniform1i (item->render_data.map_location, 0);
|
||||
|
||||
if (item->parent_data != NULL)
|
||||
{
|
||||
if (item->parent_data->texture_id != 0)
|
||||
{
|
||||
glActiveTexture (GL_TEXTURE1);
|
||||
glBindTexture (GL_TEXTURE_2D, item->parent_data->texture_id);
|
||||
glUniform1i (item->render_data.parentMap_location, 1);
|
||||
}
|
||||
|
||||
glUniform1i (item->render_data.blendMode_location, item->blend_mode);
|
||||
}
|
||||
|
||||
/* Pass the opacity component */
|
||||
glUniform1f (item->render_data.alpha_location, item->opaque ? 1 : item->opacity);
|
||||
|
||||
/* Pass the mvp to the vertex shader */
|
||||
GSK_NOTE (OPENGL, graphene_matrix_print (&item->mvp));
|
||||
graphene_matrix_to_float (&item->mvp, mvp);
|
||||
glUniformMatrix4fv (item->render_data.mvp_location, 1, GL_FALSE, mvp);
|
||||
|
||||
/* Draw the quad */
|
||||
GSK_NOTE (OPENGL, g_print ("Drawing item <%s>[%p] with opacity: %g\n",
|
||||
item->name,
|
||||
item,
|
||||
item->opaque ? 1 : item->opacity));
|
||||
|
||||
glDrawArrays (GL_TRIANGLES, 0, N_VERTICES);
|
||||
|
||||
/* Reset the state */
|
||||
glBindTexture (GL_TEXTURE_2D, 0);
|
||||
glDisableVertexAttribArray (item->render_data.position_location);
|
||||
glDisableVertexAttribArray (item->render_data.uv_location);
|
||||
glUseProgram (0);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_to_texture (cairo_surface_t *surface,
|
||||
graphene_rect_t *clip,
|
||||
int min_filter,
|
||||
int mag_filter,
|
||||
guint *texture_out)
|
||||
{
|
||||
guint texture_id;
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Uploading surface[%p] { w:%g, h:%g } to texid:%d\n",
|
||||
surface,
|
||||
clip->size.width,
|
||||
clip->size.height,
|
||||
texture_id));
|
||||
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||
|
||||
gdk_cairo_surface_upload_to_gl (surface, GL_TEXTURE_2D, clip->size.width, clip->size.height, NULL);
|
||||
|
||||
if (min_filter != GL_NEAREST)
|
||||
glGenerateMipmap (GL_TEXTURE_2D);
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("New texture id %d from surface %p\n", texture_id, surface));
|
||||
|
||||
*texture_out = texture_id;
|
||||
}
|
||||
|
||||
static void
|
||||
get_gl_scaling_filters (GskRenderer *renderer,
|
||||
int *min_filter_r,
|
||||
int *mag_filter_r)
|
||||
{
|
||||
GskScalingFilter min_filter, mag_filter;
|
||||
|
||||
gsk_renderer_get_scaling_filters (renderer, &min_filter, &mag_filter);
|
||||
|
||||
switch (min_filter)
|
||||
{
|
||||
case GSK_SCALING_FILTER_NEAREST:
|
||||
*min_filter_r = GL_NEAREST;
|
||||
break;
|
||||
|
||||
case GSK_SCALING_FILTER_LINEAR:
|
||||
*min_filter_r = GL_LINEAR;
|
||||
break;
|
||||
|
||||
case GSK_SCALING_FILTER_TRILINEAR:
|
||||
*min_filter_r = GL_LINEAR_MIPMAP_LINEAR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (mag_filter)
|
||||
{
|
||||
case GSK_SCALING_FILTER_NEAREST:
|
||||
*mag_filter_r = GL_NEAREST;
|
||||
break;
|
||||
|
||||
/* There's no point in using anything above GL_LINEAR for
|
||||
* magnification filters
|
||||
*/
|
||||
case GSK_SCALING_FILTER_LINEAR:
|
||||
case GSK_SCALING_FILTER_TRILINEAR:
|
||||
*mag_filter_r = GL_LINEAR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static gboolean
|
||||
check_in_frustum (const graphene_frustum_t *frustum,
|
||||
RenderItem *item)
|
||||
{
|
||||
graphene_box_t aabb;
|
||||
|
||||
graphene_box_init (&aabb, &item->min, &item->max);
|
||||
graphene_matrix_transform_box (&item->mvp, &aabb, &aabb);
|
||||
|
||||
return graphene_frustum_intersects_box (frustum, &aabb);
|
||||
}
|
||||
#endif
|
||||
|
||||
static float
|
||||
project_item (const graphene_matrix_t *projection,
|
||||
const graphene_matrix_t *modelview)
|
||||
{
|
||||
graphene_vec4_t vec;
|
||||
|
||||
graphene_matrix_get_row (modelview, 3, &vec);
|
||||
graphene_matrix_transform_vec4 (projection, &vec, &vec);
|
||||
|
||||
return graphene_vec4_get_z (&vec) / graphene_vec4_get_w (&vec);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_add_render_item (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderItem *parent)
|
||||
{
|
||||
graphene_rect_t viewport;
|
||||
int gl_min_filter, gl_mag_filter;
|
||||
cairo_surface_t *surface;
|
||||
GskRenderNodeIter iter;
|
||||
graphene_matrix_t mv, projection;
|
||||
graphene_rect_t bounds;
|
||||
GskRenderNode *child;
|
||||
RenderItem item;
|
||||
int program_id;
|
||||
|
||||
if (gsk_render_node_is_hidden (node))
|
||||
{
|
||||
GSK_NOTE (OPENGL, g_print ("Skipping hidden node <%s>[%p]\n",
|
||||
node->name != NULL ? node->name : "unnamed",
|
||||
node));
|
||||
return;
|
||||
}
|
||||
|
||||
memset (&item, 0, sizeof (RenderItem));
|
||||
|
||||
gsk_renderer_get_viewport (GSK_RENDERER (self), &viewport);
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
|
||||
item.node = node;
|
||||
item.name = node->name != NULL ? node->name : "unnamed";
|
||||
|
||||
/* The texture size */
|
||||
item.size = bounds.size;
|
||||
|
||||
/* Each render item is an axis-aligned bounding box that we
|
||||
* transform using the given transformation matrix
|
||||
*/
|
||||
item.min.x = bounds.origin.x;
|
||||
item.min.y = bounds.origin.y;
|
||||
item.min.z = 0.f;
|
||||
|
||||
item.max.x = bounds.origin.x + bounds.size.width;
|
||||
item.max.y = bounds.origin.y + bounds.size.height;
|
||||
item.max.z = 0.f;
|
||||
|
||||
/* The location of the item, in normalized world coordinates */
|
||||
gsk_render_node_get_world_matrix (node, &mv);
|
||||
graphene_matrix_multiply (&mv, &self->mvp, &item.mvp);
|
||||
|
||||
item.opaque = gsk_render_node_is_opaque (node);
|
||||
item.opacity = gsk_render_node_get_opacity (node);
|
||||
|
||||
item.blend_mode = gsk_render_node_get_blend_mode (node);
|
||||
|
||||
/* GL objects */
|
||||
item.render_data.vao_id = self->vao_id;
|
||||
item.render_data.buffer_id = 0;
|
||||
|
||||
/* Select the program to use */
|
||||
if (parent != NULL)
|
||||
program_id = self->blend_program_id;
|
||||
else
|
||||
program_id = self->blit_program_id;
|
||||
|
||||
item.render_data.map_location =
|
||||
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[MAP]);
|
||||
item.render_data.parentMap_location =
|
||||
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[PARENT_MAP]);
|
||||
item.render_data.mvp_location =
|
||||
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[MVP]);
|
||||
item.render_data.alpha_location =
|
||||
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[ALPHA]);
|
||||
item.render_data.blendMode_location =
|
||||
gsk_shader_builder_get_uniform_location (self->shader_builder, program_id, self->uniforms[BLEND_MODE]);
|
||||
|
||||
item.render_data.position_location =
|
||||
gsk_shader_builder_get_attribute_location (self->shader_builder, program_id, self->attributes[POSITION]);
|
||||
item.render_data.uv_location =
|
||||
gsk_shader_builder_get_attribute_location (self->shader_builder, program_id, self->attributes[UV]);
|
||||
|
||||
item.render_data.program_id = program_id;
|
||||
|
||||
if (parent != NULL)
|
||||
item.parent_data = &(parent->render_data);
|
||||
else
|
||||
item.parent_data = NULL;
|
||||
|
||||
gsk_renderer_get_projection (GSK_RENDERER (self), &projection);
|
||||
item.z = project_item (&projection, &mv);
|
||||
|
||||
/* TODO: This should really be an asset atlas, to avoid uploading a ton
|
||||
* of textures. Ideally we could use a single Cairo surface to get around
|
||||
* the GL texture limits and reorder the texture data on the CPU side and
|
||||
* do a single upload; alternatively, we could use a separate FBO and
|
||||
* render each texture into it
|
||||
*/
|
||||
get_gl_scaling_filters (GSK_RENDERER (self), &gl_min_filter, &gl_mag_filter);
|
||||
surface = gsk_render_node_get_surface (node);
|
||||
|
||||
/* If the node does not have any surface we skip drawing it, but we still
|
||||
* recurse.
|
||||
*
|
||||
* XXX: This needs to be re-done if the opacity is != 0, in which case we
|
||||
* need to composite the opacity level of the children
|
||||
*/
|
||||
if (surface == NULL)
|
||||
goto recurse_children;
|
||||
|
||||
surface_to_texture (surface, &bounds, gl_min_filter, gl_mag_filter, &(item.render_data.texture_id));
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Adding node <%s>[%p] to render items\n",
|
||||
node->name != NULL ? node->name : "unnamed",
|
||||
node));
|
||||
if (gsk_render_node_is_opaque (node) && gsk_render_node_get_opacity (node) == 1.f)
|
||||
g_array_append_val (self->opaque_render_items, item);
|
||||
else
|
||||
g_array_prepend_val (self->transparent_render_items, item);
|
||||
|
||||
recurse_children:
|
||||
gsk_render_node_iter_init (&iter, node);
|
||||
while (gsk_render_node_iter_next (&iter, &child))
|
||||
gsk_gl_renderer_add_render_item (self, child, &item);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_renderer_validate_tree (GskGLRenderer *self,
|
||||
GskRenderNode *root)
|
||||
{
|
||||
int n_nodes;
|
||||
|
||||
if (self->context == NULL)
|
||||
{
|
||||
GSK_NOTE (OPENGL, g_print ("No valid GL context associated to the renderer"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
n_nodes = gsk_render_node_get_size (root);
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
self->opaque_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), n_nodes);
|
||||
self->transparent_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), n_nodes);
|
||||
|
||||
g_array_set_clear_func (self->opaque_render_items, render_item_clear);
|
||||
g_array_set_clear_func (self->transparent_render_items, render_item_clear);
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("RenderNode -> RenderItem\n"));
|
||||
gsk_gl_renderer_add_render_item (self, root, NULL);
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Total render items: %d of %d (opaque:%d, transparent:%d)\n",
|
||||
self->opaque_render_items->len + self->transparent_render_items->len,
|
||||
n_nodes,
|
||||
self->opaque_render_items->len,
|
||||
self->transparent_render_items->len));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_clear_tree (GskGLRenderer *self)
|
||||
{
|
||||
if (self->context == NULL)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->opaque_render_items, g_array_unref);
|
||||
g_clear_pointer (&self->transparent_render_items, g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_clear (GskGLRenderer *self)
|
||||
{
|
||||
int clear_bits = GL_COLOR_BUFFER_BIT;
|
||||
|
||||
if (self->has_depth_buffer)
|
||||
clear_bits |= GL_DEPTH_BUFFER_BIT;
|
||||
if (self->has_stencil_buffer)
|
||||
clear_bits |= GL_STENCIL_BUFFER_BIT;
|
||||
|
||||
GSK_NOTE (OPENGL, g_print ("Clearing viewport\n"));
|
||||
glClearColor (0, 0, 0, 0);
|
||||
glClear (clear_bits);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_render (GskRenderer *renderer,
|
||||
GskRenderNode *root,
|
||||
GdkDrawingContext *context)
|
||||
{
|
||||
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
|
||||
graphene_matrix_t modelview, projection;
|
||||
graphene_rect_t viewport;
|
||||
gboolean use_alpha;
|
||||
int status;
|
||||
guint i;
|
||||
|
||||
if (self->context == NULL)
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
gsk_renderer_get_viewport (renderer, &viewport);
|
||||
|
||||
gsk_gl_renderer_create_buffers (self);
|
||||
gsk_gl_renderer_allocate_buffers (self, viewport.size.width, viewport.size.height);
|
||||
gsk_gl_renderer_attach_buffers (self);
|
||||
|
||||
if (self->has_depth_buffer)
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
else
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
|
||||
/* Ensure that the viewport is up to date */
|
||||
status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
|
||||
if (status == GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
gsk_gl_renderer_resize_viewport (self, &viewport);
|
||||
|
||||
gsk_gl_renderer_clear (self);
|
||||
|
||||
gsk_renderer_get_modelview (renderer, &modelview);
|
||||
gsk_renderer_get_projection (renderer, &projection);
|
||||
gsk_gl_renderer_update_frustum (self, &modelview, &projection);
|
||||
|
||||
if (!gsk_gl_renderer_validate_tree (self, root))
|
||||
goto out;
|
||||
|
||||
/* Opaque pass: front-to-back */
|
||||
GSK_NOTE (OPENGL, g_print ("Rendering %u opaque items\n", self->opaque_render_items->len));
|
||||
for (i = 0; i < self->opaque_render_items->len; i++)
|
||||
{
|
||||
RenderItem *item = &g_array_index (self->opaque_render_items, RenderItem, i);
|
||||
|
||||
render_item (item);
|
||||
}
|
||||
|
||||
glEnable (GL_BLEND);
|
||||
|
||||
/* Transparent pass: back-to-front */
|
||||
GSK_NOTE (OPENGL, g_print ("Rendering %u transparent items\n", self->transparent_render_items->len));
|
||||
for (i = 0; i < self->transparent_render_items->len; i++)
|
||||
{
|
||||
RenderItem *item = &g_array_index (self->transparent_render_items, RenderItem, i);
|
||||
|
||||
render_item (item);
|
||||
}
|
||||
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
/* Draw the output of the GL rendering to the window */
|
||||
GSK_NOTE (OPENGL, g_print ("Drawing GL content on Cairo surface using a %s\n",
|
||||
self->texture_id != 0 ? "texture" : "renderbuffer"));
|
||||
|
||||
out:
|
||||
use_alpha = gsk_renderer_get_use_alpha (renderer);
|
||||
|
||||
gdk_cairo_draw_from_gl (gdk_drawing_context_get_cairo_context (context),
|
||||
gdk_drawing_context_get_window (context),
|
||||
use_alpha ? self->texture_id : self->render_buffer,
|
||||
use_alpha ? GL_TEXTURE : GL_RENDERBUFFER,
|
||||
gsk_renderer_get_scale_factor (renderer),
|
||||
0, 0, viewport.size.width, viewport.size.height);
|
||||
|
||||
gdk_gl_context_make_current (self->context);
|
||||
|
||||
gsk_gl_renderer_clear_tree (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_class_init (GskGLRendererClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GskRendererClass *renderer_class = GSK_RENDERER_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = gsk_gl_renderer_dispose;
|
||||
|
||||
renderer_class->realize = gsk_gl_renderer_realize;
|
||||
renderer_class->unrealize = gsk_gl_renderer_unrealize;
|
||||
renderer_class->render = gsk_gl_renderer_render;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_renderer_init (GskGLRenderer *self)
|
||||
{
|
||||
gsk_ensure_resources ();
|
||||
|
||||
graphene_matrix_init_identity (&self->mvp);
|
||||
|
||||
self->has_depth_buffer = TRUE;
|
||||
self->has_stencil_buffer = TRUE;
|
||||
}
|
23
gsk/gskglrendererprivate.h
Normal file
23
gsk/gskglrendererprivate.h
Normal 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__ */
|
59
gsk/gsklayer.c
Normal file
59
gsk/gsklayer.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gsklayer.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gskenumtypes.h"
|
||||
#include "gskdebugprivate.h"
|
||||
|
||||
typedef struct {
|
||||
GskLayer *parent;
|
||||
|
||||
GskLayer *first_child;
|
||||
GskLayer *last_child;
|
||||
GskLayer *prev_sibling;
|
||||
GskLayer *next_sibling;
|
||||
|
||||
int n_children;
|
||||
|
||||
gint64 age;
|
||||
|
||||
graphene_rect_t bounds;
|
||||
graphene_point_t anchor;
|
||||
|
||||
graphene_matrix_t transform;
|
||||
graphene_matrix_t child_transform;
|
||||
|
||||
gboolean transform_set : 1;
|
||||
gboolean child_transform_set : 1;
|
||||
gboolean is_hidden : 1;
|
||||
gboolean is_opaque : 1;
|
||||
} GskLayerPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GskLayer, gsk_layer, G_TYPE_INITIALLY_UNOWNED)
|
||||
|
||||
static void
|
||||
gsk_layer_class_init (GskLayerClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_layer_init (GskLayer *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_layer_new:
|
||||
*
|
||||
* Creates a new #GskLayer.
|
||||
*
|
||||
* Returns: (transfer full): the newly created #GskLayer
|
||||
*
|
||||
* Since: 3.22
|
||||
*/
|
||||
GskLayer *
|
||||
gsk_layer_new (void)
|
||||
{
|
||||
return g_object_new (GSK_TYPE_LAYER, NULL);
|
||||
}
|
68
gsk/gsklayer.h
Normal file
68
gsk/gsklayer.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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_LAYER_H__
|
||||
#define __GSK_LAYER_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/gskrenderer.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_LAYER gsk_layer_get_type()
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
G_DECLARE_DERIVABLE_TYPE (GskLayer, gsk_layer, GSK, LAYER, GInitiallyUnowned)
|
||||
|
||||
struct _GskLayerClass
|
||||
{
|
||||
/*< private >*/
|
||||
GInitiallyUnowned parent_instance;
|
||||
|
||||
/*< public >*/
|
||||
|
||||
/* vfuncs */
|
||||
GskRenderNode *(* get_render_node) (GskLayer *layer,
|
||||
GskRenderer *renderer);
|
||||
|
||||
void (* queue_resize) (GskLayer *layer,
|
||||
GskLayer *origin);
|
||||
void (* queue_redraw) (GskLayer *layer,
|
||||
GskLayer *origin);
|
||||
|
||||
/* signals */
|
||||
void (* child_added) (GskLayer *layer,
|
||||
GskLayer *child);
|
||||
void (* child_removed) (GskLayer *layer,
|
||||
GskLayer *child);
|
||||
void (* destroy) (GskLayer *layer);
|
||||
|
||||
|
||||
/*< private >*/
|
||||
gpointer _padding[16];
|
||||
};
|
||||
|
||||
GskLayer * gsk_layer_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_LAYER_H__ */
|
16
gsk/gskprivate.c
Normal file
16
gsk/gskprivate.c
Normal 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 (®ister_resources_once, register_resources, NULL);
|
||||
}
|
12
gsk/gskprivate.h
Normal file
12
gsk/gskprivate.h
Normal 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__ */
|
1083
gsk/gskrenderer.c
Normal file
1083
gsk/gskrenderer.c
Normal file
File diff suppressed because it is too large
Load Diff
106
gsk/gskrenderer.h
Normal file
106
gsk/gskrenderer.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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_scale_factor (GskRenderer *renderer,
|
||||
int scale_factor);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
int gsk_renderer_get_scale_factor (GskRenderer *renderer);
|
||||
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_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
|
||||
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
|
||||
GdkDisplay * gsk_renderer_get_display (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,
|
||||
GskRenderNode *root,
|
||||
GdkDrawingContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_RENDERER_H__ */
|
54
gsk/gskrendererprivate.h
Normal file
54
gsk/gskrendererprivate.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 (* render) (GskRenderer *renderer,
|
||||
GskRenderNode *root,
|
||||
GdkDrawingContext *context);
|
||||
};
|
||||
|
||||
gboolean gsk_renderer_is_realized (GskRenderer *renderer);
|
||||
|
||||
GskRenderNode * gsk_renderer_get_root_node (GskRenderer *renderer);
|
||||
GdkDrawingContext * gsk_renderer_get_drawing_context (GskRenderer *renderer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_RENDERER_PRIVATE_H__ */
|
1483
gsk/gskrendernode.c
Normal file
1483
gsk/gskrendernode.c
Normal file
File diff suppressed because it is too large
Load Diff
143
gsk/gskrendernode.h
Normal file
143
gsk/gskrendernode.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/* 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_ref (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_render_node_unref (GskRenderNode *node);
|
||||
|
||||
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_append_child (GskRenderNode *node,
|
||||
GskRenderNode *child);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_render_node_prepend_child (GskRenderNode *node,
|
||||
GskRenderNode *child);
|
||||
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
|
||||
cairo_t * gsk_render_node_get_draw_context (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_render_node_set_blend_mode (GskRenderNode *node,
|
||||
GskBlendMode blend_mode);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskBlendMode gsk_render_node_get_blend_mode (GskRenderNode *node);
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_render_node_set_name (GskRenderNode *node,
|
||||
const char *name);
|
||||
|
||||
#define GSK_VALUE_HOLDS_RENDER_NODE(value) (G_VALUE_HOLDS (value, GSK_TYPE_RENDER_NODE))
|
||||
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_value_set_render_node (GValue *value,
|
||||
GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
void gsk_value_take_render_node (GValue *value,
|
||||
GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_value_get_render_node (const GValue *value);
|
||||
GDK_AVAILABLE_IN_3_22
|
||||
GskRenderNode * gsk_value_dup_render_node (const GValue *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_RENDER_NODE_H__ */
|
254
gsk/gskrendernodeiter.c
Normal file
254
gsk/gskrendernodeiter.c
Normal 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
45
gsk/gskrendernodeiter.h
Normal 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 */
|
93
gsk/gskrendernodeprivate.h
Normal file
93
gsk/gskrendernodeprivate.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#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))
|
||||
|
||||
struct _GskRenderNode
|
||||
{
|
||||
GTypeInstance parent_instance;
|
||||
|
||||
volatile int ref_count;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Blend mode */
|
||||
GskBlendMode blend_mode;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Bit fields; leave at the end */
|
||||
gboolean is_mutable : 1;
|
||||
gboolean hidden : 1;
|
||||
gboolean opaque : 1;
|
||||
gboolean transform_set : 1;
|
||||
gboolean child_transform_set : 1;
|
||||
gboolean needs_world_matrix_update : 1;
|
||||
};
|
||||
|
||||
struct _GskRenderNodeClass
|
||||
{
|
||||
GTypeClass parent_class;
|
||||
|
||||
void (* finalize) (GskRenderNode *node);
|
||||
};
|
||||
|
||||
void gsk_render_node_make_immutable (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);
|
||||
|
||||
int gsk_render_node_get_size (GskRenderNode *root);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_RENDER_NODE_PRIVATE_H__ */
|
483
gsk/gskshaderbuilder.c
Normal file
483
gsk/gskshaderbuilder.c
Normal file
@@ -0,0 +1,483 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskshaderbuilderprivate.h"
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
typedef struct {
|
||||
int program_id;
|
||||
|
||||
GHashTable *uniform_locations;
|
||||
GHashTable *attribute_locations;
|
||||
} ShaderProgram;
|
||||
|
||||
struct _GskShaderBuilder
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *resource_base_path;
|
||||
char *vertex_preamble;
|
||||
char *fragment_preamble;
|
||||
|
||||
int version;
|
||||
|
||||
GPtrArray *defines;
|
||||
GPtrArray *uniforms;
|
||||
GPtrArray *attributes;
|
||||
|
||||
GHashTable *programs;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskShaderBuilder, gsk_shader_builder, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
shader_program_free (gpointer data)
|
||||
{
|
||||
ShaderProgram *p = data;
|
||||
|
||||
g_clear_pointer (&p->uniform_locations, g_hash_table_unref);
|
||||
g_clear_pointer (&p->attribute_locations, g_hash_table_unref);
|
||||
|
||||
glDeleteProgram (p->program_id);
|
||||
|
||||
g_slice_free (ShaderProgram, data);
|
||||
}
|
||||
|
||||
static ShaderProgram *
|
||||
shader_program_new (int program_id)
|
||||
{
|
||||
ShaderProgram *p = g_slice_new (ShaderProgram);
|
||||
|
||||
p->program_id = program_id;
|
||||
|
||||
p->uniform_locations = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
p->attribute_locations = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_builder_finalize (GObject *gobject)
|
||||
{
|
||||
GskShaderBuilder *self = GSK_SHADER_BUILDER (gobject);
|
||||
|
||||
g_free (self->resource_base_path);
|
||||
|
||||
g_clear_pointer (&self->defines, g_ptr_array_unref);
|
||||
g_clear_pointer (&self->uniforms, g_ptr_array_unref);
|
||||
g_clear_pointer (&self->attributes, g_ptr_array_unref);
|
||||
|
||||
g_clear_pointer (&self->programs, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (gsk_shader_builder_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_builder_class_init (GskShaderBuilderClass *klass)
|
||||
{
|
||||
G_OBJECT_CLASS (klass)->finalize = gsk_shader_builder_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_builder_init (GskShaderBuilder *self)
|
||||
{
|
||||
self->defines = g_ptr_array_new_with_free_func (g_free);
|
||||
self->uniforms = g_ptr_array_new_with_free_func (g_free);
|
||||
self->attributes = g_ptr_array_new_with_free_func (g_free);
|
||||
|
||||
self->programs = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
NULL,
|
||||
shader_program_free);
|
||||
}
|
||||
|
||||
GskShaderBuilder *
|
||||
gsk_shader_builder_new (void)
|
||||
{
|
||||
return g_object_new (GSK_TYPE_SHADER_BUILDER, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_shader_builder_set_resource_base_path (GskShaderBuilder *builder,
|
||||
const char *base_path)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
|
||||
|
||||
g_free (builder->resource_base_path);
|
||||
builder->resource_base_path = g_strdup (base_path);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_shader_builder_set_vertex_preamble (GskShaderBuilder *builder,
|
||||
const char *vertex_preamble)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
|
||||
|
||||
g_free (builder->vertex_preamble);
|
||||
builder->vertex_preamble = g_strdup (vertex_preamble);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_shader_builder_set_fragment_preamble (GskShaderBuilder *builder,
|
||||
const char *fragment_preamble)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
|
||||
|
||||
g_free (builder->fragment_preamble);
|
||||
builder->fragment_preamble = g_strdup (fragment_preamble);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_shader_builder_set_version (GskShaderBuilder *builder,
|
||||
int version)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
|
||||
|
||||
builder->version = version;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_shader_builder_add_define (GskShaderBuilder *builder,
|
||||
const char *define_name,
|
||||
const char *define_value)
|
||||
{
|
||||
g_return_if_fail (GSK_IS_SHADER_BUILDER (builder));
|
||||
g_return_if_fail (define_name != NULL && *define_name != '\0');
|
||||
g_return_if_fail (define_value != NULL && *define_name != '\0');
|
||||
|
||||
g_ptr_array_add (builder->defines, g_strdup (define_name));
|
||||
g_ptr_array_add (builder->defines, g_strdup (define_value));
|
||||
}
|
||||
|
||||
GQuark
|
||||
gsk_shader_builder_add_uniform (GskShaderBuilder *builder,
|
||||
const char *uniform_name)
|
||||
{
|
||||
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), 0);
|
||||
g_return_val_if_fail (uniform_name != NULL, 0);
|
||||
|
||||
g_ptr_array_add (builder->uniforms, g_strdup (uniform_name));
|
||||
|
||||
return g_quark_from_string (uniform_name);
|
||||
}
|
||||
|
||||
GQuark
|
||||
gsk_shader_builder_add_attribute (GskShaderBuilder *builder,
|
||||
const char *attribute_name)
|
||||
{
|
||||
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), 0);
|
||||
g_return_val_if_fail (attribute_name != NULL, 0);
|
||||
|
||||
g_ptr_array_add (builder->attributes, g_strdup (attribute_name));
|
||||
|
||||
return g_quark_from_string (attribute_name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lookup_shader_code (GString *code,
|
||||
const char *base_path,
|
||||
const char *shader_file,
|
||||
GError **error)
|
||||
{
|
||||
GBytes *source;
|
||||
char *path;
|
||||
|
||||
if (base_path != NULL)
|
||||
path = g_build_filename (base_path, shader_file, NULL);
|
||||
else
|
||||
path = g_strdup (shader_file);
|
||||
|
||||
source = g_resources_lookup_data (path, 0, error);
|
||||
g_free (path);
|
||||
|
||||
if (source == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_string_append (code, g_bytes_get_data (source, NULL));
|
||||
|
||||
g_bytes_unref (source);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
|
||||
int shader_type,
|
||||
const char *shader_preamble,
|
||||
const char *shader_source,
|
||||
GError **error)
|
||||
{
|
||||
GString *code;
|
||||
char *source;
|
||||
int shader_id;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
code = g_string_new (NULL);
|
||||
|
||||
if (builder->version > 0)
|
||||
{
|
||||
g_string_append_printf (code, "#version %d\n", builder->version);
|
||||
g_string_append_c (code, '\n');
|
||||
}
|
||||
|
||||
for (i = 0; i < builder->defines->len; i += 2)
|
||||
{
|
||||
const char *name = g_ptr_array_index (builder->defines, i);
|
||||
const char *value = g_ptr_array_index (builder->defines, i + 1);
|
||||
|
||||
g_string_append (code, "#define");
|
||||
g_string_append_c (code, ' ');
|
||||
g_string_append (code, name);
|
||||
g_string_append_c (code, ' ');
|
||||
g_string_append (code, value);
|
||||
g_string_append_c (code, '\n');
|
||||
|
||||
if (i == builder->defines->len - 2)
|
||||
g_string_append_c (code, '\n');
|
||||
}
|
||||
|
||||
if (!lookup_shader_code (code, builder->resource_base_path, shader_preamble, error))
|
||||
{
|
||||
g_string_free (code, TRUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_string_append_c (code, '\n');
|
||||
|
||||
if (!lookup_shader_code (code, builder->resource_base_path, shader_source, error))
|
||||
{
|
||||
g_string_free (code, TRUE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
source = g_string_free (code, FALSE);
|
||||
|
||||
shader_id = glCreateShader (shader_type);
|
||||
glShaderSource (shader_id, 1, (const GLchar **) &source, NULL);
|
||||
glCompileShader (shader_id);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_DEBUG_CHECK (OPENGL))
|
||||
{
|
||||
g_print ("*** Compiling %s shader ***\n"
|
||||
"%s\n",
|
||||
shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
|
||||
source);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_free (source);
|
||||
|
||||
glGetShaderiv (shader_id, GL_COMPILE_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
int log_len;
|
||||
char *buffer;
|
||||
|
||||
glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &log_len);
|
||||
|
||||
buffer = g_malloc0 (log_len + 1);
|
||||
glGetShaderInfoLog (shader_id, log_len, NULL, buffer);
|
||||
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
|
||||
"Compilation failure in %s shader:\n%s",
|
||||
shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
|
||||
buffer);
|
||||
g_free (buffer);
|
||||
|
||||
glDeleteShader (shader_id);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return shader_id;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_builder_cache_uniforms (GskShaderBuilder *builder,
|
||||
ShaderProgram *program)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < builder->uniforms->len; i++)
|
||||
{
|
||||
const char *uniform = g_ptr_array_index (builder->uniforms, i);
|
||||
int loc = glGetUniformLocation (program->program_id, uniform);
|
||||
|
||||
g_hash_table_insert (program->uniform_locations,
|
||||
GINT_TO_POINTER (g_quark_from_string (uniform)),
|
||||
GINT_TO_POINTER (loc));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shader_builder_cache_attributes (GskShaderBuilder *builder,
|
||||
ShaderProgram *program)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < builder->attributes->len; i++)
|
||||
{
|
||||
const char *attribute = g_ptr_array_index (builder->attributes, i);
|
||||
int loc = glGetAttribLocation (program->program_id, attribute);
|
||||
|
||||
g_hash_table_insert (program->attribute_locations,
|
||||
GINT_TO_POINTER (g_quark_from_string (attribute)),
|
||||
GINT_TO_POINTER (loc));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *vertex_shader,
|
||||
const char *fragment_shader,
|
||||
GError **error)
|
||||
{
|
||||
ShaderProgram *program;
|
||||
int vertex_id, fragment_id;
|
||||
int program_id;
|
||||
int status;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
|
||||
g_return_val_if_fail (vertex_shader != NULL, -1);
|
||||
g_return_val_if_fail (fragment_shader != NULL, -1);
|
||||
|
||||
vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
|
||||
builder->vertex_preamble,
|
||||
vertex_shader,
|
||||
error);
|
||||
if (vertex_id < 0)
|
||||
return -1;
|
||||
|
||||
fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
|
||||
builder->fragment_preamble,
|
||||
fragment_shader,
|
||||
error);
|
||||
if (fragment_id < 0)
|
||||
{
|
||||
glDeleteShader (vertex_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
program_id = glCreateProgram ();
|
||||
glAttachShader (program_id, vertex_id);
|
||||
glAttachShader (program_id, fragment_id);
|
||||
glLinkProgram (program_id);
|
||||
|
||||
glGetProgramiv (program_id, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
int log_len = 0;
|
||||
|
||||
glGetProgramiv (program_id, GL_INFO_LOG_LENGTH, &log_len);
|
||||
|
||||
buffer = g_malloc0 (log_len + 1);
|
||||
glGetProgramInfoLog (program_id, log_len, NULL, buffer);
|
||||
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED,
|
||||
"Linking failure in shader:\n%s", buffer);
|
||||
g_free (buffer);
|
||||
|
||||
glDeleteProgram (program_id);
|
||||
program_id = -1;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
program = shader_program_new (program_id);
|
||||
gsk_shader_builder_cache_uniforms (builder, program);
|
||||
gsk_shader_builder_cache_attributes (builder, program);
|
||||
|
||||
g_hash_table_insert (builder->programs, GINT_TO_POINTER (program_id), program);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_DEBUG_CHECK (OPENGL))
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer name_p, location_p;
|
||||
|
||||
g_hash_table_iter_init (&iter, program->uniform_locations);
|
||||
while (g_hash_table_iter_next (&iter, &name_p, &location_p))
|
||||
{
|
||||
g_print ("Uniform '%s' - location: %d\n",
|
||||
g_quark_to_string (GPOINTER_TO_INT (name_p)),
|
||||
GPOINTER_TO_INT (location_p));
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, program->attribute_locations);
|
||||
while (g_hash_table_iter_next (&iter, &name_p, &location_p))
|
||||
{
|
||||
g_print ("Attribute '%s' - location: %d\n",
|
||||
g_quark_to_string (GPOINTER_TO_INT (name_p)),
|
||||
GPOINTER_TO_INT (location_p));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
if (vertex_id > 0)
|
||||
{
|
||||
glDetachShader (program_id, vertex_id);
|
||||
glDeleteShader (vertex_id);
|
||||
}
|
||||
|
||||
if (fragment_id > 0)
|
||||
{
|
||||
glDetachShader (program_id, fragment_id);
|
||||
glDeleteShader (fragment_id);
|
||||
}
|
||||
|
||||
return program_id;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_shader_builder_get_uniform_location (GskShaderBuilder *builder,
|
||||
int program_id,
|
||||
GQuark uniform_quark)
|
||||
{
|
||||
ShaderProgram *p = NULL;
|
||||
gpointer loc_p = NULL;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
|
||||
g_return_val_if_fail (program_id >= 0, -1);
|
||||
|
||||
if (builder->uniforms->len == 0)
|
||||
return -1;
|
||||
|
||||
p = g_hash_table_lookup (builder->programs, GINT_TO_POINTER (program_id));
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
||||
if (g_hash_table_lookup_extended (p->uniform_locations, GINT_TO_POINTER (uniform_quark), NULL, &loc_p))
|
||||
return GPOINTER_TO_INT (loc_p);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_shader_builder_get_attribute_location (GskShaderBuilder *builder,
|
||||
int program_id,
|
||||
GQuark attribute_quark)
|
||||
{
|
||||
ShaderProgram *p = NULL;
|
||||
gpointer loc_p = NULL;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
|
||||
g_return_val_if_fail (program_id >= 0, -1);
|
||||
|
||||
if (builder->attributes->len == 0)
|
||||
return -1;
|
||||
|
||||
p = g_hash_table_lookup (builder->programs, GINT_TO_POINTER (program_id));
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
||||
if (g_hash_table_lookup_extended (p->attribute_locations, GINT_TO_POINTER (attribute_quark), NULL, &loc_p))
|
||||
return GPOINTER_TO_INT (loc_p);
|
||||
|
||||
return -1;
|
||||
}
|
46
gsk/gskshaderbuilderprivate.h
Normal file
46
gsk/gskshaderbuilderprivate.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef __GSK_SHADER_BUILDER_PRIVATE_H__
|
||||
#define __GSK_SHADER_BUILDER_PRIVATE_H__
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_SHADER_BUILDER (gsk_shader_builder_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskShaderBuilder, gsk_shader_builder, GSK, SHADER_BUILDER, GObject)
|
||||
|
||||
GskShaderBuilder * gsk_shader_builder_new (void);
|
||||
|
||||
void gsk_shader_builder_set_version (GskShaderBuilder *builder,
|
||||
int version);
|
||||
void gsk_shader_builder_set_resource_base_path (GskShaderBuilder *builder,
|
||||
const char *base_path);
|
||||
void gsk_shader_builder_set_vertex_preamble (GskShaderBuilder *builder,
|
||||
const char *shader_preamble);
|
||||
void gsk_shader_builder_set_fragment_preamble (GskShaderBuilder *builder,
|
||||
const char *shader_preamble);
|
||||
|
||||
GQuark gsk_shader_builder_add_uniform (GskShaderBuilder *builder,
|
||||
const char *uniform_name);
|
||||
GQuark gsk_shader_builder_add_attribute (GskShaderBuilder *builder,
|
||||
const char *attribute_name);
|
||||
void gsk_shader_builder_add_define (GskShaderBuilder *builder,
|
||||
const char *define_name,
|
||||
const char *define_value);
|
||||
|
||||
int gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *vertex_shader,
|
||||
const char *fragment_shader,
|
||||
GError **error);
|
||||
|
||||
int gsk_shader_builder_get_uniform_location (GskShaderBuilder *builder,
|
||||
int program_id,
|
||||
GQuark uniform_quark);
|
||||
int gsk_shader_builder_get_attribute_location (GskShaderBuilder *builder,
|
||||
int program_id,
|
||||
GQuark attribute_quark);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_SHADER_BUILDER_PRIVATE_H__ */
|
29
gsk/gsktypes.h
Normal file
29
gsk/gsktypes.h
Normal 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__ */
|
62
gsk/resources/glsl/blend.fs.glsl
Normal file
62
gsk/resources/glsl/blend.fs.glsl
Normal file
@@ -0,0 +1,62 @@
|
||||
vec3 BlendMultiply(vec3 Cb, vec3 Cs) {
|
||||
return Cb * Cs;
|
||||
}
|
||||
|
||||
vec3 BlendScreen(vec3 Cb, vec3 Cs) {
|
||||
return Cb + Cs - (Cb * Cs);
|
||||
}
|
||||
|
||||
vec3 BlendHardLight(vec3 Cb, vec3 Cs) {
|
||||
vec3 m = BlendMultiply(Cb, 2.0 * Cs);
|
||||
vec3 s = BlendScreen(Cb, 2.0 * Cs - 1.0);
|
||||
vec3 edge = vec3(0.5, 0.5, 0.5);
|
||||
|
||||
/* Use mix() and step() to avoid a branch */
|
||||
return mix(m, s, step(edge, Cs));
|
||||
}
|
||||
|
||||
vec3 BlendOverlay(vec3 Cb, vec3 Cs) {
|
||||
return BlendHardLight(Cs, Cb);
|
||||
}
|
||||
|
||||
vec3 BlendDarken(vec3 Cb, vec3 Cs) {
|
||||
return min(Cb, Cs);
|
||||
}
|
||||
|
||||
vec3 BlendLighten(vec3 Cb, vec3 Cs) {
|
||||
return max(Cb, Cs);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 mask = Texture(parentMap, vUv);
|
||||
vec4 diffuse = Texture(map, vUv);
|
||||
vec3 res;
|
||||
|
||||
if (blendMode == 0) {
|
||||
res = diffuse.xyz;
|
||||
}
|
||||
else if (blendMode == 1) {
|
||||
res = BlendMultiply(mask.xyz, diffuse.xyz);
|
||||
}
|
||||
else if (blendMode == 2) {
|
||||
res = BlendScreen(mask.xyz, diffuse.xyz);
|
||||
}
|
||||
else if (blendMode == 3) {
|
||||
res = BlendOverlay(mask.xyz, diffuse.xyz);
|
||||
}
|
||||
else if (blendMode == 4) {
|
||||
res = BlendDarken(mask.xyz, diffuse.xyz);
|
||||
}
|
||||
else if (blendMode == 5) {
|
||||
res = BlendLighten(mask.xyz, diffuse.xyz);
|
||||
}
|
||||
else if (blendMode == 8) {
|
||||
res = BlendHardLight(mask.xyz, diffuse.xyz);
|
||||
}
|
||||
else {
|
||||
// Use red for debugging missing blend modes
|
||||
res = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
setOutputColor(vec4(res, diffuse.a * alpha));
|
||||
}
|
6
gsk/resources/glsl/blend.vs.glsl
Normal file
6
gsk/resources/glsl/blend.vs.glsl
Normal file
@@ -0,0 +1,6 @@
|
||||
void main() {
|
||||
gl_Position = mvp * vec4(position, 0.0, 1.0);
|
||||
|
||||
// Flip the sampling
|
||||
vUv = vec2(uv.x, 1.0 - uv.y);
|
||||
}
|
5
gsk/resources/glsl/blit.fs.glsl
Normal file
5
gsk/resources/glsl/blit.fs.glsl
Normal file
@@ -0,0 +1,5 @@
|
||||
void main() {
|
||||
vec4 diffuse = Texture(map, vUv);
|
||||
|
||||
setOutputColor(vec4(diffuse.xyz, diffuse.a * alpha));
|
||||
}
|
6
gsk/resources/glsl/blit.vs.glsl
Normal file
6
gsk/resources/glsl/blit.vs.glsl
Normal file
@@ -0,0 +1,6 @@
|
||||
void main() {
|
||||
gl_Position = mvp * vec4(position, 0.0, 1.0);
|
||||
|
||||
// Flip the sampling
|
||||
vUv = vec2(uv.x, 1.0 - uv.y);
|
||||
}
|
16
gsk/resources/glsl/es2_common.fs.glsl
Normal file
16
gsk/resources/glsl/es2_common.fs.glsl
Normal file
@@ -0,0 +1,16 @@
|
||||
precision mediump float;
|
||||
|
||||
uniform mat4 mvp;
|
||||
uniform sampler2D map;
|
||||
uniform sampler2D parentMap;
|
||||
uniform float alpha;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
vec4 Texture(sampler2D sampler, vec2 texCoords) {
|
||||
return texture2D(sampler, texCoords);
|
||||
}
|
||||
|
||||
void setOutputColor(vec4 color) {
|
||||
gl_FragColor = color;
|
||||
}
|
7
gsk/resources/glsl/es2_common.vs.glsl
Normal file
7
gsk/resources/glsl/es2_common.vs.glsl
Normal file
@@ -0,0 +1,7 @@
|
||||
uniform mat4 mvp;
|
||||
uniform float alpha;
|
||||
|
||||
attribute vec2 position;
|
||||
attribute vec2 uv;
|
||||
|
||||
varying vec2 vUv;
|
19
gsk/resources/glsl/gl3_common.fs.glsl
Normal file
19
gsk/resources/glsl/gl3_common.fs.glsl
Normal file
@@ -0,0 +1,19 @@
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D map;
|
||||
uniform sampler2D parentMap;
|
||||
uniform mat4 mvp;
|
||||
uniform float alpha;
|
||||
uniform int blendMode;
|
||||
|
||||
in vec2 vUv;
|
||||
|
||||
out vec4 outputColor;
|
||||
|
||||
vec4 Texture(sampler2D sampler, vec2 texCoords) {
|
||||
return texture(sampler, texCoords);
|
||||
}
|
||||
|
||||
void setOutputColor(vec4 color) {
|
||||
outputColor = color;
|
||||
}
|
7
gsk/resources/glsl/gl3_common.vs.glsl
Normal file
7
gsk/resources/glsl/gl3_common.vs.glsl
Normal file
@@ -0,0 +1,7 @@
|
||||
uniform mat4 mvp;
|
||||
uniform float alpha;
|
||||
|
||||
in vec2 position;
|
||||
in vec2 uv;
|
||||
|
||||
out vec2 vUv;
|
14
gsk/resources/glsl/gl_common.fs.glsl
Normal file
14
gsk/resources/glsl/gl_common.fs.glsl
Normal file
@@ -0,0 +1,14 @@
|
||||
uniform mat4 mvp;
|
||||
uniform sampler2D map;
|
||||
uniform sampler2D parentMap;
|
||||
uniform float alpha;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
vec4 Texture(sampler2D sampler, vec2 texCoords) {
|
||||
return texture2D(sampler, texCoords);
|
||||
}
|
||||
|
||||
void setOutputColor(vec4 color) {
|
||||
gl_FragColor = color;
|
||||
}
|
7
gsk/resources/glsl/gl_common.vs.glsl
Normal file
7
gsk/resources/glsl/gl_common.vs.glsl
Normal file
@@ -0,0 +1,7 @@
|
||||
uniform mat4 mvp;
|
||||
uniform float alpha;
|
||||
|
||||
attribute vec2 position;
|
||||
attribute vec2 uv;
|
||||
|
||||
varying vec2 vUv;
|
@@ -26,6 +26,8 @@ AM_CPPFLAGS = \
|
||||
-I$(top_builddir)/gtk \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/gdk \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/gsk \
|
||||
$(GMODULE_CFLAGS) \
|
||||
$(GTK_DEBUG_FLAGS) \
|
||||
$(GDK_HIDDEN_VISIBILITY_CFLAGS) \
|
||||
@@ -79,10 +81,12 @@ endif
|
||||
|
||||
libadd = \
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la \
|
||||
$(GMODULE_LIBS) \
|
||||
$(GTK_DEP_LIBS)
|
||||
deps = \
|
||||
$(top_builddir)/gdk/libgdk-3.la
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la
|
||||
|
||||
# libtool stuff: set version and export symbols for resolving
|
||||
# since automake doesn't support conditionalized libsomething_la_LDFLAGS
|
||||
@@ -1553,7 +1557,7 @@ Gtk_3_0_gir_CFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-DGTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
|
||||
Gtk_3_0_gir_FILES = $(introspection_files)
|
||||
Gtk_3_0_gir_LIBS = libgtk-3.la $(top_builddir)/gdk/libgdk-3.la
|
||||
Gtk_3_0_gir_LIBS = libgtk-3.la $(top_builddir)/gdk/libgdk-3.la $(top_builddir)/gsk/libgsk-3.la
|
||||
Gtk_3_0_gir_EXPORT_PACKAGES = gtk+-3.0
|
||||
INTROSPECTION_GIRS = Gtk-3.0.gir
|
||||
|
||||
@@ -1581,6 +1585,7 @@ gtk_query_immodules_3_0_SOURCES = queryimmodules.c gtkutils.c
|
||||
gtk_query_immodules_3_0_LDADD = \
|
||||
libgtk-3.la \
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la \
|
||||
$(GMODULE_LIBS) \
|
||||
$(GTK_DEP_LIBS)
|
||||
|
||||
@@ -1591,24 +1596,28 @@ gtk_encode_symbolic_svg_SOURCES = encodesymbolic.c
|
||||
gtk_encode_symbolic_svg_LDADD = \
|
||||
$(GDK_PIXBUF_LIBS) \
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la \
|
||||
$(GTK_DEP_LIBS)
|
||||
|
||||
gtk_builder_tool_SOURCES = gtk-builder-tool.c
|
||||
gtk_builder_tool_LDADD = \
|
||||
libgtk-3.la \
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la \
|
||||
$(GTK_DEP_LIBS)
|
||||
|
||||
gtk_query_settings_SOURCES = gtk-query-settings.c
|
||||
gtk_query_settings_LDADD= \
|
||||
libgtk-3.la \
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la \
|
||||
$(GTK_DEP_LIBS)
|
||||
|
||||
gtk_launch_SOURCES = gtk-launch.c
|
||||
gtk_launch_LDADD = \
|
||||
libgtk-3.la \
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la \
|
||||
$(GTK_DEP_LIBS)
|
||||
|
||||
if OS_WIN32
|
||||
|
127
gtk/gtkwidget.c
127
gtk/gtkwidget.c
@@ -17447,28 +17447,128 @@ gtk_widget_reset_controllers (GtkWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
GskRenderer *
|
||||
gtk_widget_get_renderer (GtkWidget *widget)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
|
||||
toplevel = _gtk_widget_get_toplevel (widget);
|
||||
if (_gtk_widget_is_toplevel (toplevel))
|
||||
return gtk_window_get_renderer (GTK_WINDOW (toplevel));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GskRenderNode *
|
||||
gtk_widget_get_render_node (GtkWidget *widget,
|
||||
GskRenderer *renderer)
|
||||
{
|
||||
GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (widget);
|
||||
GskRenderNode *node;
|
||||
|
||||
if (klass->get_render_node == NULL)
|
||||
{
|
||||
GskRenderNode *tmp;
|
||||
graphene_rect_t bounds;
|
||||
GtkAllocation clip;
|
||||
cairo_t *cr;
|
||||
|
||||
gtk_widget_get_clip (widget, &clip);
|
||||
graphene_rect_init (&bounds, clip.x, clip.y, clip.width, clip.height);
|
||||
|
||||
tmp = gsk_render_node_new ();
|
||||
gsk_render_node_set_bounds (tmp, &bounds);
|
||||
cr = gsk_render_node_get_draw_context (tmp);
|
||||
|
||||
gtk_widget_draw (widget, cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
node = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = klass->get_render_node (widget, renderer);
|
||||
|
||||
if (klass->draw != NULL ||
|
||||
g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
|
||||
{
|
||||
GskRenderNode *tmp;
|
||||
graphene_rect_t bounds;
|
||||
GtkAllocation clip;
|
||||
gboolean result;
|
||||
cairo_t *cr;
|
||||
|
||||
gtk_widget_get_clip (widget, &clip);
|
||||
graphene_rect_init (&bounds, clip.x, clip.y, clip.width, clip.height);
|
||||
|
||||
tmp = gsk_render_node_new ();
|
||||
gsk_render_node_set_bounds (tmp, &bounds);
|
||||
cr = gsk_render_node_get_draw_context (tmp);
|
||||
|
||||
if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
|
||||
{
|
||||
g_signal_emit (widget, widget_signals[DRAW], 0, cr, &result);
|
||||
}
|
||||
else if (klass->draw != NULL)
|
||||
{
|
||||
klass->draw (widget, cr);
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
gsk_render_node_append_child (node, tmp);
|
||||
gsk_render_node_unref (tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_widget_render (GtkWidget *widget,
|
||||
GdkWindow *window,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GdkDrawingContext *context;
|
||||
gboolean do_clip;
|
||||
cairo_t *cr;
|
||||
int x, y;
|
||||
|
||||
if (priv->double_buffered)
|
||||
{
|
||||
GdkDrawingContext *context;
|
||||
GskRenderer *renderer;
|
||||
GskRenderNode *root;
|
||||
|
||||
/* We only render double buffered on native windows */
|
||||
if (!gdk_window_has_native (window))
|
||||
return;
|
||||
|
||||
renderer = gtk_widget_get_renderer (widget);
|
||||
if (renderer == NULL)
|
||||
return;
|
||||
|
||||
root = gtk_widget_get_render_node (widget, renderer);
|
||||
if (root == NULL)
|
||||
return;
|
||||
|
||||
context = gdk_window_begin_draw_frame (window, region);
|
||||
cr = gdk_drawing_context_get_cairo_context (context);
|
||||
gsk_renderer_render (renderer, root, context);
|
||||
gdk_window_end_draw_frame (window, context);
|
||||
|
||||
gsk_render_node_unref (root);
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean do_clip;
|
||||
cairo_t *cr;
|
||||
int x, y;
|
||||
|
||||
/* This is annoying, but it has to stay because Firefox
|
||||
* disables double buffering on a top-level GdkWindow,
|
||||
* which breaks the drawing context.
|
||||
@@ -17478,15 +17578,12 @@ gtk_widget_render (GtkWidget *widget,
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
cr = gdk_cairo_create (window);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
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);
|
||||
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (priv->double_buffered)
|
||||
gdk_window_end_draw_frame (window, context);
|
||||
else
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gsk/gsk.h>
|
||||
#include <gtk/gtkaccelgroup.h>
|
||||
#include <gtk/gtkborder.h>
|
||||
#include <gtk/gtktypes.h>
|
||||
@@ -599,12 +600,14 @@ struct _GtkWidgetClass
|
||||
void (*queue_draw_region) (GtkWidget *widget,
|
||||
const cairo_region_t *region);
|
||||
|
||||
GskRenderNode *(* get_render_node) (GtkWidget *widget,
|
||||
GskRenderer *renderer);
|
||||
|
||||
/*< private >*/
|
||||
|
||||
GtkWidgetClassPrivate *priv;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved6) (void);
|
||||
void (*_gtk_reserved7) (void);
|
||||
};
|
||||
|
||||
|
@@ -302,6 +302,9 @@ void gtk_widget_render (GtkWidget
|
||||
const cairo_region_t *region);
|
||||
|
||||
|
||||
GskRenderNode * gtk_widget_get_render_node (GtkWidget *widget,
|
||||
GskRenderer *renderer);
|
||||
|
||||
/* inline getters */
|
||||
|
||||
static inline gboolean
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <graphene.h>
|
||||
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkwindowprivate.h"
|
||||
@@ -271,6 +272,8 @@ struct _GtkWindowPrivate
|
||||
GdkWindow *hardcoded_window;
|
||||
|
||||
GtkCssNode *decoration_node;
|
||||
|
||||
GskRenderer *renderer;
|
||||
};
|
||||
|
||||
static const GtkTargetEntry dnd_dest_targets [] = {
|
||||
@@ -7159,6 +7162,16 @@ gtk_window_realize (GtkWidget *widget)
|
||||
|
||||
_gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (priv->renderer == NULL)
|
||||
{
|
||||
graphene_rect_t viewport;
|
||||
|
||||
priv->renderer = gsk_renderer_get_for_display (gtk_widget_get_display (widget));
|
||||
|
||||
graphene_rect_init (&viewport, 0, 0, allocation.width, allocation.height);
|
||||
gsk_renderer_set_viewport (priv->renderer, &viewport);
|
||||
}
|
||||
|
||||
if (gtk_widget_get_parent_window (widget))
|
||||
{
|
||||
gtk_container_set_default_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT);
|
||||
@@ -7182,6 +7195,9 @@ gtk_window_realize (GtkWidget *widget)
|
||||
gtk_widget_register_window (widget, gdk_window);
|
||||
gtk_widget_set_realized (widget, TRUE);
|
||||
|
||||
gsk_renderer_set_window (priv->renderer, gdk_window);
|
||||
gsk_renderer_realize (priv->renderer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7275,6 +7291,10 @@ gtk_window_realize (GtkWidget *widget)
|
||||
gtk_widget_register_window (widget, gdk_window);
|
||||
gtk_widget_set_realized (widget, TRUE);
|
||||
|
||||
gsk_renderer_set_window (priv->renderer, gdk_window);
|
||||
gsk_renderer_set_use_alpha (priv->renderer, TRUE);
|
||||
gsk_renderer_realize (priv->renderer);
|
||||
|
||||
attributes.x = allocation.x;
|
||||
attributes.y = allocation.y;
|
||||
attributes.width = allocation.width;
|
||||
@@ -7395,6 +7415,9 @@ gtk_window_realize (GtkWidget *widget)
|
||||
}
|
||||
|
||||
check_scale_changed (window);
|
||||
|
||||
/* Renderer */
|
||||
gsk_renderer_realize (priv->renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -7422,6 +7445,9 @@ gtk_window_unrealize (GtkWidget *widget)
|
||||
GList *link;
|
||||
gint i;
|
||||
|
||||
if (priv->renderer != NULL)
|
||||
gsk_renderer_unrealize (priv->renderer);
|
||||
|
||||
/* On unrealize, we reset the size of the window such
|
||||
* that we will re-apply the default sizing stuff
|
||||
* next time we show the window.
|
||||
@@ -7569,6 +7595,27 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
child_allocation.width = allocation->width;
|
||||
child_allocation.height = allocation->height;
|
||||
|
||||
if (priv->renderer != NULL)
|
||||
{
|
||||
graphene_rect_t viewport;
|
||||
graphene_matrix_t projection;
|
||||
graphene_matrix_t modelview;
|
||||
graphene_point3d_t tmp;
|
||||
|
||||
graphene_rect_init (&viewport, 0, 0, allocation->width, allocation->height);
|
||||
gsk_renderer_set_viewport (priv->renderer, &viewport);
|
||||
|
||||
graphene_matrix_init_ortho (&projection,
|
||||
0, allocation->width,
|
||||
0, allocation->height,
|
||||
-1, 1);
|
||||
gsk_renderer_set_projection (priv->renderer, &projection);
|
||||
|
||||
graphene_matrix_init_translate (&modelview,
|
||||
graphene_point3d_init (&tmp, 0.f, 0.f, 0.f));
|
||||
gsk_renderer_set_modelview (priv->renderer, &modelview);
|
||||
}
|
||||
|
||||
get_shadow_width (window, &window_border);
|
||||
|
||||
if (_gtk_widget_get_realized (widget))
|
||||
@@ -12631,3 +12678,11 @@ gtk_window_set_hardcoded_window (GtkWindow *window,
|
||||
|
||||
g_set_object (&priv->hardcoded_window, gdk_window);
|
||||
}
|
||||
|
||||
GskRenderer *
|
||||
gtk_window_get_renderer (GtkWindow *window)
|
||||
{
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
|
||||
return priv->renderer;
|
||||
}
|
||||
|
@@ -135,6 +135,8 @@ void gtk_window_set_hardcoded_window (GtkWindow *window,
|
||||
|
||||
GdkScreen *_gtk_window_get_screen (GtkWindow *window);
|
||||
|
||||
GskRenderer *gtk_window_get_renderer (GtkWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_WINDOW_PRIVATE_H__ */
|
||||
|
@@ -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-3.la \
|
||||
$(top_builddir)/gsk/libgsk-3.la \
|
||||
$(top_builddir)/gdk/libgdk-3.la \
|
||||
$(GTK_DEP_LIBS) \
|
||||
$(GDK_DEP_LIBS) \
|
||||
|
@@ -1,6 +1,6 @@
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
SUBDIRS = gdk gtk a11y css reftests tools
|
||||
SUBDIRS = gdk gsk gtk a11y css reftests tools
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
||||
|
||||
|
39
testsuite/gsk/Makefile.am
Normal file
39
testsuite/gsk/Makefile.am
Normal file
@@ -0,0 +1,39 @@
|
||||
include $(top_srcdir)/Makefile.decl
|
||||
|
||||
NULL=
|
||||
|
||||
noinst_PROGRAMS = $(TEST_PROGS)
|
||||
|
||||
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)
|
||||
|
||||
LDADD = $(GTK_DEP_LIBS) $(top_builddir)/gsk/libgsk-3.la
|
||||
|
||||
TEST_PROGS += \
|
||||
$(NULL)
|
||||
|
||||
if BUILDOPT_INSTALL_TESTS
|
||||
insttestdir=$(pkglibexecdir)/installed-tests
|
||||
insttest_PROGRAMS = $(TEST_PROGS)
|
||||
|
||||
%.test: %$(EXEEXT) Makefile
|
||||
$(AM_V_GEN) (echo '[Test]' > $@.tmp; \
|
||||
echo 'Type=session' >> $@.tmp; \
|
||||
echo 'Exec=$(insttestdir)/$<' >> $@.tmp; \
|
||||
mv $@.tmp $@)
|
||||
|
||||
test_files = $(TEST_PROGRS:=.test)
|
||||
|
||||
DISTCLEANFILES = $(test_files)
|
||||
|
||||
testmetadir = $(datadir)/installed-tests/$(PACKAGE)
|
||||
testmeta_DATA = $(test_files)
|
||||
endif
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
Reference in New Issue
Block a user