[gtk/glshader-paintable: 1/3] Work around linker issues
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/glshader-paintable: 1/3] Work around linker issues
- Date: Fri, 25 Sep 2020 02:27:12 +0000 (UTC)
commit 2bb196b2367a373f141f3576c4c82f66e886c35b
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Sep 24 22:19:57 2020 -0400
Work around linker issues
I've wasted some time trying to figure out why GskShaderPaintable
api does not appear in libgtk-4.so. It turns out that I have to
use a symbol from that .o file in libgtk or the file will get
dropped.
gsk/gsk.h | 1 +
gsk/gskshaderpaintable.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++
gsk/gskshaderpaintable.h | 59 +++++++++
gsk/meson.build | 2 +
gtk/gtkwidget.c | 2 +
5 files changed, 380 insertions(+)
---
diff --git a/gsk/gsk.h b/gsk/gsk.h
index 523b24c81a..2953358aad 100644
--- a/gsk/gsk.h
+++ b/gsk/gsk.h
@@ -24,6 +24,7 @@
#include <gsk/gskrenderer.h>
#include <gsk/gskrendernode.h>
#include <gsk/gskroundedrect.h>
+#include <gsk/gskshaderpaintable.h>
#include <gsk/gsktransform.h>
#include <gsk/gskcairorenderer.h>
diff --git a/gsk/gskshaderpaintable.c b/gsk/gskshaderpaintable.c
new file mode 100644
index 0000000000..fa8b588697
--- /dev/null
+++ b/gsk/gskshaderpaintable.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright © 2020 Red Hat, Inc
+ *
+ * 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.1 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/>.
+ *
+ * Authors: Matthias Clasen <mclasen redhat com>
+ */
+
+#include "config.h"
+
+#include "gskshaderpaintable.h"
+
+/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
+
+void gtk_snapshot_push_gl_shader (GdkSnapshot *snapshot,
+ GskGLShader *shader,
+ const graphene_rect_t *bounds,
+ GBytes *uniform_data,
+ int n_children);
+void gtk_snapshot_append_color (GdkSnapshot *snapshot,
+ const GdkRGBA *color,
+ const graphene_rect_t *bounds);
+void gtk_snapshot_pop (GdkSnapshot *snapshot);
+
+
+
+struct _GskShaderPaintable
+{
+ GObject parent_instance;
+
+ GskGLShader *shader;
+ GBytes *uniform_data;
+
+ GdkFrameClock *frame_clock;
+ guint clock_tick_id;
+ int time_idx;
+ gint64 first_frame_time;
+ gint64 frame_time;
+};
+
+struct _GskShaderPaintableClass
+{
+ GObjectClass parent_class;
+};
+
+enum {
+ PROP_0,
+ PROP_SHADER,
+ PROP_UNIFORM_DATA,
+
+ N_PROPS,
+};
+
+static GParamSpec *properties[N_PROPS] = { NULL, };
+
+static void
+gsk_shader_paintable_paintable_snapshot (GdkPaintable *paintable,
+ GdkSnapshot *snapshot,
+ double width,
+ double height)
+{
+ GskShaderPaintable *self = GSK_SHADER_PAINTABLE (paintable);
+ graphene_rect_t bounds;
+ GBytes *uniform_data;
+ gsize size;
+
+ size = gsk_gl_shader_get_uniforms_size (self->shader);
+
+ if (self->time_idx > -1)
+ {
+ int offset = gsk_gl_shader_get_uniform_offset (self->shader, self->time_idx);
+ guchar *data;
+
+ data = g_new0 (guchar, size);
+ memcpy (data, g_bytes_get_data (self->uniform_data, NULL), size);
+
+ *(float*)(data + offset) = (self->frame_time - self->first_frame_time) / (float)G_TIME_SPAN_SECOND;
+
+ uniform_data = g_bytes_new_take (data, size);
+ }
+ else
+ uniform_data = g_bytes_ref (self->uniform_data);
+
+ graphene_rect_init (&bounds, 0, 0, width, height);
+
+ gtk_snapshot_push_gl_shader (snapshot, self->shader, &GRAPHENE_RECT_INIT(0, 0, width, height),
uniform_data, 0);
+ gtk_snapshot_append_color (snapshot, &(GdkRGBA){1.0, 0.5, 0.6, 1.0}, &GRAPHENE_RECT_INIT(0, 0, width,
height));
+ gtk_snapshot_pop (snapshot);
+
+ g_bytes_unref (uniform_data);
+}
+
+static void
+gsk_shader_paintable_paintable_init (GdkPaintableInterface *iface)
+{
+ iface->snapshot = gsk_shader_paintable_paintable_snapshot;
+}
+
+G_DEFINE_TYPE_EXTENDED (GskShaderPaintable, gsk_shader_paintable, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
+ gsk_shader_paintable_paintable_init))
+
+static void
+gsk_shader_paintable_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_SHADER:
+ gsk_shader_paintable_set_shader (self, g_value_get_object (value));
+ break;
+
+ case PROP_UNIFORM_DATA:
+ gsk_shader_paintable_set_uniform_data (self, g_value_get_boxed (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsk_shader_paintable_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_SHADER:
+ g_value_set_object (value, self->shader);
+ break;
+
+ case PROP_UNIFORM_DATA:
+ g_value_set_boxed (value, self->uniform_data);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gsk_shader_paintable_finalize (GObject *object)
+{
+ GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
+
+ if (self->clock_tick_id)
+ {
+ g_signal_handler_disconnect (self->frame_clock, self->clock_tick_id);
+ gdk_frame_clock_end_updating (self->frame_clock);
+ g_object_unref (self->frame_clock);
+ }
+
+ g_clear_pointer (&self->uniform_data, g_bytes_unref);
+ g_clear_object (&self->shader);
+
+ G_OBJECT_CLASS (gsk_shader_paintable_parent_class)->finalize (object);
+}
+
+static void
+gsk_shader_paintable_class_init (GskShaderPaintableClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = gsk_shader_paintable_get_property;
+ gobject_class->set_property = gsk_shader_paintable_set_property;
+ gobject_class->finalize = gsk_shader_paintable_finalize;
+
+ properties[PROP_SHADER] =
+ g_param_spec_object ("shader", "Shader", "The shader",
+ GSK_TYPE_GLSHADER,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_UNIFORM_DATA] =
+ g_param_spec_boxed ("uniform-data", "Uniform data", "The uniform data",
+ G_TYPE_BYTES,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class, N_PROPS, properties);
+}
+
+static void
+gsk_shader_paintable_init (GskShaderPaintable *self)
+{
+ self->time_idx = -1;
+}
+
+GdkPaintable *
+gsk_shader_paintable_new (GskGLShader *shader,
+ GBytes *data)
+{
+ GdkPaintable *ret;
+
+ g_return_val_if_fail (shader == NULL || GSK_IS_GL_SHADER (shader), NULL);
+
+ ret = g_object_new (GSK_TYPE_SHADER_PAINTABLE,
+ "shader", shader,
+ "uniform-data", data,
+ NULL);
+
+ g_clear_object (&shader);
+ g_clear_pointer (&data, g_bytes_unref);
+
+ return ret;
+}
+
+void
+gsk_shader_paintable_set_shader (GskShaderPaintable *self,
+ GskGLShader *shader)
+{
+ g_return_if_fail (GSK_IS_SHADER_PAINTABLE (self));
+ g_return_if_fail (shader == NULL || GSK_IS_GL_SHADER (shader));
+
+ if (!g_set_object (&self->shader, shader))
+ return;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHADER]);
+ gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
+ gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
+
+ g_clear_pointer (&self->uniform_data, g_bytes_unref);
+}
+
+GskGLShader *
+gsk_shader_paintable_get_shader (GskShaderPaintable *self)
+{
+ g_return_val_if_fail (GSK_IS_SHADER_PAINTABLE (self), NULL);
+
+ return self->shader;
+}
+
+void
+gsk_shader_paintable_set_uniform_data (GskShaderPaintable *self,
+ GBytes *data)
+{
+ g_return_if_fail (GSK_IS_SHADER_PAINTABLE (self));
+
+ g_clear_pointer (&self->uniform_data, g_bytes_unref);
+ if (data)
+ self->uniform_data = g_bytes_ref (data);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UNIFORM_DATA]);
+ gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
+ gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
+}
+
+GBytes *
+gsk_shader_paintable_get_uniform_data (GskShaderPaintable *self)
+{
+ g_return_val_if_fail (GSK_IS_SHADER_PAINTABLE (self), NULL);
+
+ return self->uniform_data;
+}
+
+static void
+on_frame_clock_update (GdkFrameClock *frame_clock,
+ GskShaderPaintable *self)
+{
+ gint64 frame_time;
+
+ frame_time = gdk_frame_clock_get_frame_time (frame_clock);
+
+ if (self->first_frame_time == 0)
+ self->first_frame_time = frame_time;
+
+ self->frame_time = frame_time;
+
+ gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
+ gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
+}
+
+void
+gsk_shader_paintable_set_frame_clock (GskShaderPaintable *self,
+ GdkFrameClock *frame_clock,
+ int uniform_idx)
+{
+ self->time_idx = uniform_idx;
+ self->first_frame_time = 0;
+
+ if (self->clock_tick_id)
+ {
+ g_signal_handler_disconnect (self->frame_clock, self->clock_tick_id);
+ self->clock_tick_id = 0;
+ gdk_frame_clock_end_updating (self->frame_clock);
+ }
+
+ g_set_object (&self->frame_clock, frame_clock);
+
+ if (frame_clock)
+ {
+ self->clock_tick_id = g_signal_connect (frame_clock, "update",
+ G_CALLBACK (on_frame_clock_update), self);
+ gdk_frame_clock_begin_updating (frame_clock);
+ }
+}
diff --git a/gsk/gskshaderpaintable.h b/gsk/gskshaderpaintable.h
new file mode 100644
index 0000000000..4f812a99f4
--- /dev/null
+++ b/gsk/gskshaderpaintable.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * 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.1 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/>.
+ *
+ * Authors: Matthias Clasen <mclasen redhat com>
+ */
+
+#ifndef __GSK_SHADER_PAINTABLE_H__
+#define __GSK_SHADER_PAINTABLE_H__
+
+#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gsk/gsk.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+#include <gsk/gskglshader.h>
+
+G_BEGIN_DECLS
+
+#define GSK_TYPE_SHADER_PAINTABLE (gsk_shader_paintable_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (GskShaderPaintable, gsk_shader_paintable, GSK, SHADER_PAINTABLE, GObject)
+
+GDK_AVAILABLE_IN_ALL
+GdkPaintable * gsk_shader_paintable_new (GskGLShader *shader,
+ GBytes *data);
+
+GDK_AVAILABLE_IN_ALL
+GskGLShader * gsk_shader_paintable_get_shader (GskShaderPaintable *self);
+GDK_AVAILABLE_IN_ALL
+void gsk_shader_paintable_set_shader (GskShaderPaintable *self,
+ GskGLShader *shader);
+GDK_AVAILABLE_IN_ALL
+GBytes * gsk_shader_paintable_get_uniform_data (GskShaderPaintable *self);
+GDK_AVAILABLE_IN_ALL
+void gsk_shader_paintable_set_uniform_data (GskShaderPaintable *self,
+ GBytes *data);
+
+GDK_AVAILABLE_IN_ALL
+void gsk_shader_paintable_set_frame_clock (GskShaderPaintable *self,
+ GdkFrameClock *frame_clock,
+ int uniform_idx);
+
+G_END_DECLS
+
+#endif /* __GSK_SHADER_PAINTABLE_H__ */
diff --git a/gsk/meson.build b/gsk/meson.build
index e71ac50c78..69f74d2264 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -28,6 +28,7 @@ gsk_public_sources = files([
'gskrendernodeimpl.c',
'gskrendernodeparser.c',
'gskroundedrect.c',
+ 'gskshaderpaintable.c',
'gsktransform.c',
'gl/gskglrenderer.c',
])
@@ -58,6 +59,7 @@ gsk_public_headers = files([
'gskrenderer.h',
'gskrendernode.h',
'gskroundedrect.h',
+ 'gskshaderpaintable.h',
'gsktransform.h',
'gsktypes.h',
'gsk-autocleanup.h',
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index f9d5f079f9..bf0b814097 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -736,6 +736,8 @@ gtk_widget_base_class_init (gpointer g_class)
GtkWidgetClass *klass = g_class;
GtkWidgetClassPrivate *priv;
+ g_type_ensure (GSK_TYPE_SHADER_PAINTABLE);
+
priv = klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
priv->template = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]