Compare commits

..

2 Commits

Author SHA1 Message Date
Matthias Clasen
865cab3cc6 Add a test for changing content
This is meant to produce lots of widget that all share the
same CSS and size, and frequently change content.
2023-04-30 08:08:31 -04:00
Matthias Clasen
bc47cc5970 docs: Migration guide updates
Mention various widget size apis going away.
2023-04-29 16:17:51 -04:00
145 changed files with 1158 additions and 2728 deletions

View File

@@ -26,7 +26,7 @@ variables:
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Ddemos=false -Dbuild-examples=false -Dbuild-tests=false -Dbuild-testsuite=true"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v46"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v42"
workflow:
rules:
@@ -57,9 +57,15 @@ style-check-diff:
reports:
junit:
- "${CI_PROJECT_DIR}/_build/report-x11.xml"
- "${CI_PROJECT_DIR}/_build/report-x11_unstable.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_unstable.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_gles.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_gles_unstable.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_smalltexture.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_smalltexture_unstable.xml"
- "${CI_PROJECT_DIR}/_build/report-broadway.xml"
- "${CI_PROJECT_DIR}/_build/report-broadway_unstable.xml"
name: "gtk-${CI_COMMIT_REF_NAME}"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
@@ -70,7 +76,6 @@ style-check-diff:
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
- "${CI_PROJECT_DIR}/_build/testsuite/headless/*/*.log"
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
cache:
key: "$CI_JOB_NAME"
@@ -86,6 +91,7 @@ fedora-x86_64:
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=0.64
- meson subprojects download
- meson subprojects update --reset
- mkdir _install
@@ -103,6 +109,7 @@ fedora-x86_64:
- .gitlab-ci/run-tests.sh _build x11
- .gitlab-ci/run-tests.sh _build wayland
- .gitlab-ci/run-tests.sh _build wayland_gles
- .gitlab-ci/run-tests.sh _build wayland_smalltexture
- .gitlab-ci/run-tests.sh _build broadway
release-build:
@@ -114,6 +121,7 @@ release-build:
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=0.64
- meson subprojects download
- meson subprojects update --reset
- meson setup
@@ -144,11 +152,23 @@ fedora-mingw64:
script:
- .gitlab-ci/show-info-linux.sh
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=1.0
- pip3 install --user meson~=0.64
- meson subprojects download
- meson subprojects update --reset
- meson -Dintrospection=disabled -Dgraphene:introspection=disabled _build
- meson compile -C _build
# Test that mingw64-meson still fails. If it has stopped failing, the CI
# will fail and now you should remove the hack that follows this.
- FAILED=false
- mingw64-meson --version || FAILED=true
- test $FAILED = false && echo "mingw64-meson works now, remove the hack" && exit 1
# HACK: Running mingw64-meson directly fails on the CI with:
# /usr/bin/mingw64-meson: line 92: fg: no job control
# Because rpm is not evaluating %__meson and it gets interpreted as a job
# specifier. So we fix that and run it ourselves.
- rpm --eval "%{mingw64_meson}" > mingw64-meson.sh
- sed -i -e 's/%__meson/meson/' mingw64-meson.sh
- chmod +x mingw64-meson.sh
- ./mingw64-meson.sh -Dintrospection=disabled -Dgraphene:introspection=disabled _build
- ninja -C _build
.mingw-defaults:
stage: build
@@ -190,7 +210,7 @@ macos:
needs: []
before_script:
- bash .gitlab-ci/show-info-osx.sh
- pip3 install --user meson~=1.0
- pip3 install --user meson~=0.64
- pip3 install --user ninja
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
- export MESON_FORCE_BACKTRACE=1
@@ -348,6 +368,7 @@ static-scan:
EXTRA_MESON_FLAGS: "--buildtype=debug"
script:
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=0.64
- meson setup
${COMMON_MESON_FLAGS}
${EXTRA_MESON_FLAGS}
@@ -369,6 +390,7 @@ asan-build:
variables:
script:
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=0.64
- CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled -Df16c=disabled _build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build wayland
@@ -383,6 +405,7 @@ reference:
needs: []
script:
- export PATH="$HOME/.local/bin:$PATH"
- pip3 install --user meson~=0.64
- meson setup
${COMMON_MESON_FLAGS}
--buildtype=release

View File

@@ -32,6 +32,7 @@ RUN dnf -y install \
glib2-static \
glibc-devel \
glibc-headers \
gnome-desktop-testing \
gnupg2 \
gobject-introspection-devel \
graphene-devel \
@@ -72,14 +73,10 @@ RUN dnf -y install \
mesa-dri-drivers \
mesa-libEGL-devel \
mesa-libGLES-devel \
meson \
mutter \
ninja-build \
pango-devel \
pcre-devel \
pcre-static \
pipewire \
pipewire-gstreamer \
python3 \
python3-docutils \
python3-gobject \
@@ -87,7 +84,6 @@ RUN dnf -y install \
python3-markdown \
python3-packaging \
python3-pip \
python3-pydbus \
python3-pygments \
python3-typogrify \
python3-wheel \
@@ -99,7 +95,6 @@ RUN dnf -y install \
weston \
weston-libs \
which \
wireplumber \
xorg-x11-server-Xvfb \
&& dnf clean all

View File

@@ -138,8 +138,7 @@ if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
${CMD} run \
--rm \
--userns=keep-id \
--volume "$(pwd)/..:/home/user/app:rw,z" \
--volume "$(pwd)/..:/home/user/app" \
--workdir "/home/user/app" \
--tty \
--interactive "${TAG}" \

View File

@@ -6,7 +6,6 @@ set +e
srcdir=$( pwd )
builddir=$1
backend=$2
multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:verbosity=1:log_threads=1
@@ -16,8 +15,7 @@ case "${backend}" in
x11)
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
@@ -28,6 +26,14 @@ case "${backend}" in
# Store the exit code for the CI run, but always
# generate the reports
exit_code=$?
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend}_unstable \
--suite=flaky \
--suite=failing || true
;;
wayland*)
@@ -38,17 +44,22 @@ case "${backend}" in
export WAYLAND_DISPLAY=wayland-5
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
--no-suite=failing \
--no-suite=flaky \
--no-suite=${backend}_failing \
--no-suite=gsk-compare-broadway
exit_code=$?
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend}_unstable \
--suite=flaky \
--suite=failing || true
kill ${compositor}
;;
@@ -60,8 +71,7 @@ case "${backend}" in
export BROADWAY_DISPLAY=:5
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend} \
--suite=gtk \
@@ -72,6 +82,13 @@ case "${backend}" in
# don't let Broadway failures fail the run, for now
exit_code=0
meson test -C ${builddir} \
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
--print-errorlogs \
--setup=${backend}_unstable \
--suite=flaky \
--suite=failing || true
kill ${server}
;;
@@ -84,19 +101,20 @@ esac
cd ${builddir}
$srcdir/.gitlab-ci/meson-junit-report.py \
for suffix in "" "_unstable"; do
$srcdir/.gitlab-ci/meson-junit-report.py \
--project-name=gtk \
--backend="${backend}" \
--backend="${backend}${suffix}" \
--job-id="${CI_JOB_NAME}" \
--output="report-${backend}.xml" \
"meson-logs/testlog-${backend}.json"
$srcdir/.gitlab-ci/meson-html-report.py \
--output="report-${backend}${suffix}.xml" \
"meson-logs/testlog-${backend}${suffix}.json"
$srcdir/.gitlab-ci/meson-html-report.py \
--project-name=gtk \
--backend="${backend}" \
--backend="${backend}${suffix}" \
--job-id="${CI_JOB_NAME}" \
--reftest-output-dir="testsuite/reftests/output/${backend}" \
--output="report-${backend}.html" \
"meson-logs/testlog-${backend}.json"
--reftest-output-dir="testsuite/reftests/output/${backend}${suffix}" \
--output="report-${backend}${suffix}.html" \
"meson-logs/testlog-${backend}${suffix}.json"
done
exit $exit_code

View File

@@ -64,8 +64,6 @@
</child>
<child>
<object class="GtkLabel" id="short_time_label">
<property name="hexpand">1</property>
<property name="xalign">1</property>
<property name="valign">baseline</property>
<property name="label" translatable="yes">38m</property>
<style>

View File

@@ -64,7 +64,6 @@ struct _NodeEditorWindow
GListStore *renderers;
GskRenderNode *node;
GFile *file;
GFileMonitor *file_monitor;
GArray *errors;
@@ -545,14 +544,12 @@ node_editor_window_load (NodeEditorWindow *self,
{
GError *error = NULL;
g_clear_object (&self->file);
g_clear_object (&self->file_monitor);
if (!load_file_contents (self, file))
return FALSE;
self->file = g_object_ref (file);
self->file_monitor = g_file_monitor_file (self->file, G_FILE_MONITOR_NONE, NULL, &error);
self->file_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
if (error)
{
@@ -589,21 +586,13 @@ static void
show_open_filechooser (NodeEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Open node file");
if (self->file)
{
gtk_file_dialog_set_initial_file (dialog, self->file);
}
else
{
GFile *cwd;
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
g_object_unref (cwd);
}
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
g_object_unref (cwd);
gtk_file_dialog_open (dialog, GTK_WINDOW (self),
NULL, open_response_cb, self);
g_object_unref (dialog);
@@ -661,21 +650,14 @@ save_cb (GtkWidget *button,
NodeEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Save node");
if (self->file)
{
gtk_file_dialog_set_initial_file (dialog, self->file);
}
else
{
GFile *cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
gtk_file_dialog_set_initial_name (dialog, "demo.node");
g_object_unref (cwd);
}
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
gtk_file_dialog_set_initial_name (dialog, "demo.node");
g_object_unref (cwd);
gtk_file_dialog_save (dialog,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
NULL,
@@ -1109,8 +1091,6 @@ node_editor_window_finalize (GObject *object)
g_clear_pointer (&self->node, gsk_render_node_unref);
g_clear_object (&self->renderers);
g_clear_object (&self->file_monitor);
g_clear_object (&self->file);
G_OBJECT_CLASS (node_editor_window_parent_class)->finalize (object);
}

View File

@@ -68,7 +68,6 @@ ui_files = [
'stackswitcher.ui',
'statusbar.ui',
'switch.ui',
'switch-state.ui',
'toggle-button.ui',
'video.ui',
'volumebutton.ui',

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow">
<property name="decorated">0</property>
<property name="resizable">0</property>
<property name="default-width">280</property>
<property name="default-height">120</property>
<style>
<class name="nobackground"/>
</style>
<child>
<object class="GtkBox">
<style>
<class name="shadow"/>
<class name="background"/>
<class name="frame"/>
</style>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="halign">center</property>
<property name="valign">center</property>
<child>
<object class="GtkSwitch">
<property name="active">1</property>
<property name="state">0</property>
</object>
</child>
<child>
<object class="GtkSwitch">
<property name="active">0</property>
<property name="state">1</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -875,10 +875,10 @@ reference.
### Adapt to coordinate API changes
A number of APIs that are accepting or returning coordinates have
been changed from `int`s to `double`s: `gtk_widget_translate_coordinates()`,
been changed from ints to doubles: `gtk_widget_translate_coordinates()`,
`gtk_fixed_put()`, `gtk_fixed_move()`. This change is mostly transparent,
except for cases where out parameters are involved: you need to
pass `double*` now, instead of `int*`.
pass double* now, instead of int*.
### Adapt to GtkStyleContext API changes

View File

@@ -132,4 +132,6 @@ use `gtk_widget_compute_bounds (widget, widget, &bounds)` instead.
The function gtk_widget_get_allocation() is also going away. It does not have a direct
replacement, but the previously mentioned alternatives can be used for it too.
gtk_widget_translate_coordinates90 has been replaced by [method@Gtk.Widget.compute_point].
The function gtk_widget_get_allocated_baseline() has been renamed to [method@Gtk.Widget.get_baseline].

View File

@@ -437,7 +437,7 @@ gdk_display_manager_open_display (GdkDisplayManager *manager,
}
}
if (!found && !any && !display)
if (!found && !display)
g_warning ("No such backend: %s", backend);
}

View File

@@ -338,7 +338,6 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
gpointer data)
{
GdkGLTexture *self;
GdkTexture *update_texture;
self = g_object_new (GDK_TYPE_GL_TEXTURE,
"width", gdk_gl_texture_builder_get_width (builder),
@@ -354,22 +353,6 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
self->destroy = destroy;
self->data = data;
update_texture = gdk_gl_texture_builder_get_update_texture (builder);
if (update_texture)
{
cairo_region_t *update_region = gdk_gl_texture_builder_get_update_region (builder);
if (update_region)
{
update_region = cairo_region_copy (update_region);
cairo_region_intersect_rectangle (update_region,
&(cairo_rectangle_int_t) {
0, 0,
update_texture->width, update_texture->height
});
gdk_texture_set_diff (GDK_TEXTURE (self), update_texture, update_region);
}
}
return GDK_TEXTURE (self);
}

View File

@@ -25,8 +25,6 @@
#include "gdkglcontext.h"
#include "gdkgltextureprivate.h"
#include <cairo-gobject.h>
struct _GdkGLTextureBuilder
{
GObject parent_instance;
@@ -38,9 +36,6 @@ struct _GdkGLTextureBuilder
GdkMemoryFormat format;
gboolean has_mipmap;
gpointer sync;
GdkTexture *update_texture;
cairo_region_t *update_region;
};
struct _GdkGLTextureBuilderClass
@@ -75,8 +70,6 @@ enum
PROP_HEIGHT,
PROP_ID,
PROP_SYNC,
PROP_UPDATE_REGION,
PROP_UPDATE_TEXTURE,
PROP_WIDTH,
N_PROPS
@@ -93,9 +86,6 @@ gdk_gl_texture_builder_dispose (GObject *object)
g_clear_object (&self->context);
g_clear_object (&self->update_texture);
g_clear_pointer (&self->update_region, cairo_region_destroy);
G_OBJECT_CLASS (gdk_gl_texture_builder_parent_class)->dispose (object);
}
@@ -133,14 +123,6 @@ gdk_gl_texture_builder_get_property (GObject *object,
g_value_set_pointer (value, self->sync);
break;
case PROP_UPDATE_REGION:
g_value_set_boxed (value, self->update_region);
break;
case PROP_UPDATE_TEXTURE:
g_value_set_object (value, self->update_texture);
break;
case PROP_WIDTH:
g_value_set_int (value, self->width);
break;
@@ -185,14 +167,6 @@ gdk_gl_texture_builder_set_property (GObject *object,
gdk_gl_texture_builder_set_sync (self, g_value_get_pointer (value));
break;
case PROP_UPDATE_REGION:
gdk_gl_texture_builder_set_update_region (self, g_value_get_boxed (value));
break;
case PROP_UPDATE_TEXTURE:
gdk_gl_texture_builder_set_update_texture (self, g_value_get_object (value));
break;
case PROP_WIDTH:
gdk_gl_texture_builder_set_width (self, g_value_get_int (value));
break;
@@ -286,30 +260,6 @@ gdk_gl_texture_builder_class_init (GdkGLTextureBuilderClass *klass)
g_param_spec_pointer ("sync", NULL, NULL,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkGLTextureBuilder:update-region: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_update_region org.gdk.Property.set=gdk_gl_texture_builder_set_update_region)
*
* The update region for [property@Gdk.GLTextureBuilder:update-texture].
*
* Since: 4.12
*/
properties[PROP_UPDATE_REGION] =
g_param_spec_boxed ("update-region", NULL, NULL,
CAIRO_GOBJECT_TYPE_REGION,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkGLTextureBuilder:update-texture: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_update_texture org.gdk.Property.set=gdk_gl_texture_builder_set_update_texture)
*
* The texture [property@Gdk.GLTextureBuilder:update-region] is an update for.
*
* Since: 4.12
*/
properties[PROP_UPDATE_TEXTURE] =
g_param_spec_object ("update-texture", NULL, NULL,
GDK_TYPE_TEXTURE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GdkGLTextureBuilder:width: (attributes org.gdk.Property.get=gdk_gl_texture_builder_get_width org.gdk.Property.set=gdk_gl_texture_builder_set_width)
*
@@ -321,7 +271,6 @@ gdk_gl_texture_builder_class_init (GdkGLTextureBuilderClass *klass)
g_param_spec_int ("width", NULL, NULL,
G_MININT, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
@@ -664,102 +613,6 @@ gdk_gl_texture_builder_set_format (GdkGLTextureBuilder *self,
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FORMAT]);
}
/**
* gdk_gl_texture_builder_get_update_texture: (attributes org.gdk.Method.get_property=update_texture)
* @self: a `GdkGLTextureBuilder`
*
* Gets the texture previously set via gdk_gl_texture_builder_set_update_texture() or
* %NULL if none was set.
*
* Returns: (transfer none) (nullable): The texture
*
* Since: 4.12
*/
GdkTexture *
gdk_gl_texture_builder_get_update_texture (GdkGLTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self), NULL);
return self->update_texture;
}
/**
* gdk_gl_texture_builder_set_update_texture: (attributes org.gdk.Method.set_property=update_texture)
* @self: a `GdkGLTextureBuilder`
* @texture: (nullable): the texture to update
*
* Sets the texture to be updated by this texture. See
* [method@Gdk.GLTextureBuilder.set_update_region] for an explanation.
*
* Since: 4.12
*/
void
gdk_gl_texture_builder_set_update_texture (GdkGLTextureBuilder *self,
GdkTexture *texture)
{
g_return_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self));
g_return_if_fail (texture == NULL || GDK_IS_TEXTURE (texture));
if (!g_set_object (&self->update_texture, texture))
return;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_TEXTURE]);
}
/**
* gdk_gl_texture_builder_get_update_region: (attributes org.gdk.Method.get_property=update_region)
* @self: a `GdkGLTextureBuilder`
*
* Gets the region previously set via gdk_gl_texture_builder_set_update_region() or
* %NULL if none was set.
*
* Returns: (transfer none) (nullable): The region
*
* Since: 4.12
*/
cairo_region_t *
gdk_gl_texture_builder_get_update_region (GdkGLTextureBuilder *self)
{
g_return_val_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self), NULL);
return self->update_region;
}
/**
* gdk_gl_texture_builder_set_update_region: (attributes org.gdk.Method.set_property=update_region)
* @self: a `GdkGLTextureBuilder`
* @region: (nullable): the region to update
*
* Sets the region to be updated by this texture. Together with
* [property@Gdk.GLTextureBuilder:update-texture] this describes an
* update of a previous texture.
*
* When rendering animations of large textures, it is possible that
* consecutive textures are only updating contents in parts of the texture.
* It is then possible to describe this update via these two properties,
* so that GTK can avoid rerendering parts that did not change.
*
* An example would be a screen recording where only the mouse pointer moves.
*
* Since: 4.12
*/
void
gdk_gl_texture_builder_set_update_region (GdkGLTextureBuilder *self,
cairo_region_t *region)
{
g_return_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self));
if (self->update_region == region)
return;
g_clear_pointer (&self->update_region, cairo_region_destroy);
if (region)
self->update_region = cairo_region_reference (region);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UPDATE_REGION]);
}
/**
* gdk_gl_texture_builder_build:
* @self: a `GdkGLTextureBuilder`

View File

@@ -78,18 +78,6 @@ GDK_AVAILABLE_IN_4_12
void gdk_gl_texture_builder_set_sync (GdkGLTextureBuilder *self,
gpointer sync);
GDK_AVAILABLE_IN_4_12
GdkTexture * gdk_gl_texture_builder_get_update_texture (GdkGLTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_12
void gdk_gl_texture_builder_set_update_texture (GdkGLTextureBuilder *self,
GdkTexture *texture);
GDK_AVAILABLE_IN_4_12
cairo_region_t * gdk_gl_texture_builder_get_update_region (GdkGLTextureBuilder *self) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_12
void gdk_gl_texture_builder_set_update_region (GdkGLTextureBuilder *self,
cairo_region_t *region);
GDK_AVAILABLE_IN_4_12
GdkTexture * gdk_gl_texture_builder_build (GdkGLTextureBuilder *self,
GDestroyNotify destroy,

View File

@@ -282,8 +282,6 @@ gdk_texture_dispose (GObject *object)
{
GdkTexture *self = GDK_TEXTURE (object);
g_clear_pointer (&self->diff_to_previous, cairo_region_destroy);
gdk_texture_clear_render_data (self);
G_OBJECT_CLASS (gdk_texture_parent_class)->dispose (object);
@@ -673,47 +671,7 @@ gdk_texture_do_download (GdkTexture *texture,
guchar *data,
gsize stride)
{
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data, stride);
}
void
gdk_texture_diff (GdkTexture *self,
GdkTexture *other,
cairo_region_t *region)
{
if (self == other)
return;
if (self->previous_texture == other &&
g_atomic_pointer_get (&other->next_texture) == self)
{
cairo_region_union (region, self->diff_to_previous);
}
else if (other->previous_texture == self &&
g_atomic_pointer_get (&self->next_texture) == other)
{
cairo_region_union (region, other->diff_to_previous);
}
else
{
cairo_region_union_rectangle (region,
&(cairo_rectangle_int_t) {
0,
0,
MAX (self->width, other->width),
MAX (self->height, other->height)
});
}
}
void
gdk_texture_set_diff (GdkTexture *self,
GdkTexture *previous,
cairo_region_t *diff)
{
self->previous_texture = previous;
self->diff_to_previous = diff;
g_atomic_pointer_set (&previous->next_texture, self);
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data,stride);
}
cairo_surface_t *

View File

@@ -21,12 +21,6 @@ struct _GdkTexture
gpointer render_key;
gpointer render_data;
GDestroyNotify render_notify;
/* for diffing swapchain-like textures.
* Links are only valid if both textures agree on them */
gpointer next_texture; /* atomic, no reference, may be invalid pointer */
gpointer previous_texture; /* no reference, may be invalid pointer */
cairo_region_t *diff_to_previous;
};
struct _GdkTextureClass {
@@ -48,14 +42,6 @@ void gdk_texture_do_download (GdkTexture
GdkMemoryFormat format,
guchar *data,
gsize stride);
void gdk_texture_diff (GdkTexture *self,
GdkTexture *other,
cairo_region_t *region);
void gdk_texture_set_diff (GdkTexture *self,
GdkTexture *previous,
cairo_region_t *diff);
gboolean gdk_texture_set_render_data (GdkTexture *self,
gpointer key,
gpointer data,

View File

@@ -223,7 +223,7 @@ gdk_vulkan_strerror (VkResult result)
#if VK_HEADER_VERSION < 140
case VK_RESULT_RANGE_SIZE:
#endif
#if VK_HEADER_VERSION >= 238
#if VK_HEADER_VERSION >= 218
case VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR:
return "The requested VkImageUsageFlags are not supported. (VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR)";
case VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR:

View File

@@ -78,7 +78,6 @@ gsk_gl_attachment_state_bind_texture (GskGLAttachmentState *self,
target == GL_TEXTURE_2D ||
target == GL_TEXTURE_3D);
g_assert (texture >= GL_TEXTURE0 && texture <= GL_TEXTURE16);
g_assert (texture - GL_TEXTURE0 < G_N_ELEMENTS (self->textures));
attach = &self->textures[texture - GL_TEXTURE0];

View File

@@ -73,13 +73,11 @@ struct _GskGLBindFramebuffer
G_STATIC_ASSERT (sizeof (GskGLBindFramebuffer) == 4);
/* Increase if shaders add more textures */
#define GSK_GL_MAX_TEXTURES_PER_PROGRAM 4
struct _GskGLAttachmentState
{
GskGLBindFramebuffer fbo;
GskGLBindTexture textures[GSK_GL_MAX_TEXTURES_PER_PROGRAM];
/* Increase if shaders add more textures */
GskGLBindTexture textures[4];
guint n_changed;
};

View File

@@ -1028,8 +1028,8 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
G_GNUC_UNUSED unsigned int n_programs = 0;
guint vao_id;
guint vbo_id;
int textures[GSK_GL_MAX_TEXTURES_PER_PROGRAM];
int samplers[GSK_GL_MAX_TEXTURES_PER_PROGRAM];
int textures[4];
int samplers[4];
int framebuffer = -1;
int next_batch_index;
int active = -1;
@@ -1161,8 +1161,6 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
if G_UNLIKELY (batch->draw.bind_count > 0)
{
const GskGLCommandBind *bind = &self->batch_binds.items[batch->draw.bind_offset];
g_assert (bind->texture < G_N_ELEMENTS (textures));
for (guint i = 0; i < batch->draw.bind_count; i++)
{
if (textures[bind->texture] != bind->id)

View File

@@ -1121,21 +1121,19 @@ gsk_gl_driver_lookup_shader (GskGLDriver *self,
}
#ifdef G_ENABLE_DEBUG
void
gsk_gl_driver_save_texture_to_png (GskGLDriver *driver,
int texture_id,
int width,
int height,
const char *filename)
static void
write_atlas_to_png (GskGLDriver *driver,
GskGLTextureAtlas *atlas,
const char *filename)
{
GdkGLTextureBuilder *builder;
GdkTexture *texture;
builder = gdk_gl_texture_builder_new ();
gdk_gl_texture_builder_set_context (builder, gsk_gl_driver_get_context (driver));
gdk_gl_texture_builder_set_id (builder, texture_id);
gdk_gl_texture_builder_set_width (builder, width);
gdk_gl_texture_builder_set_height (builder, height);
gdk_gl_texture_builder_set_id (builder, atlas->texture_id);
gdk_gl_texture_builder_set_width (builder, atlas->width);
gdk_gl_texture_builder_set_height (builder, atlas->height);
texture = gdk_gl_texture_builder_build (builder, NULL, NULL);
gdk_texture_save_to_png (texture, filename);
@@ -1170,7 +1168,7 @@ gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
G_DIR_SEPARATOR_S,
(int)self->current_frame_id,
atlas->texture_id);
gsk_gl_driver_save_texture_to_png (self, atlas->texture_id, atlas->width, atlas->height, filename);
write_atlas_to_png (self, atlas, filename);
g_free (filename);
}

View File

@@ -176,13 +176,8 @@ GskGLProgram * gsk_gl_driver_lookup_shader (GskGLDriver *s
GError **error);
#ifdef G_ENABLE_DEBUG
void gsk_gl_driver_save_texture_to_png (GskGLDriver *self,
int texture_id,
int width,
int height,
const char *filename);
void gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
const char *filename);
const char *directory);
#endif
static inline GskGLTexture *

View File

@@ -356,8 +356,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
for (x = 0; x < width; x += max_size)
{
texture = gsk_gl_renderer_render_texture (renderer, root,
&GRAPHENE_RECT_INIT (viewport->origin.x + x,
viewport->origin.y + y,
&GRAPHENE_RECT_INIT (x, y,
MIN (max_size, viewport->size.width - x),
MIN (max_size, viewport->size.height - y)));
gdk_texture_download (texture,

View File

@@ -54,6 +54,27 @@
/* Make sure gradient stops fits in packed array_count */
G_STATIC_ASSERT ((MAX_GRADIENT_STOPS * 5) < (1 << GSK_GL_UNIFORM_ARRAY_BITS));
#define rounded_rect_top_left(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x, \
r->bounds.origin.y, \
r->corner[0].width, r->corner[0].height))
#define rounded_rect_top_right(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[1].width, \
r->bounds.origin.y, \
r->corner[1].width, r->corner[1].height))
#define rounded_rect_bottom_right(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x + r->bounds.size.width - r->corner[2].width, \
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
r->corner[2].width, r->corner[2].height))
#define rounded_rect_bottom_left(r) \
(GRAPHENE_RECT_INIT(r->bounds.origin.x, \
r->bounds.origin.y + r->bounds.size.height - r->corner[2].height, \
r->corner[3].width, r->corner[3].height))
#define rounded_rect_corner0(r) rounded_rect_top_left(r)
#define rounded_rect_corner1(r) rounded_rect_top_right(r)
#define rounded_rect_corner2(r) rounded_rect_bottom_right(r)
#define rounded_rect_corner3(r) rounded_rect_bottom_left(r)
#define rounded_rect_corner(r, i) (rounded_rect_corner##i(r))
#define ALPHA_IS_CLEAR(alpha) ((alpha) < ((float) 0x00ff / (float) 0xffff))
#define RGBA_IS_CLEAR(rgba) ALPHA_IS_CLEAR((rgba)->alpha)
@@ -408,6 +429,70 @@ rect_intersects (const graphene_rect_t *r1,
return TRUE;
}
static inline gboolean
rounded_rect_has_corner (const GskRoundedRect *r,
guint i)
{
return r->corner[i].width > 0 && r->corner[i].height > 0;
}
/* Current clip is NOT rounded but new one is definitely! */
static inline gboolean
intersect_rounded_rectilinear (const graphene_rect_t *non_rounded,
const GskRoundedRect *rounded,
GskRoundedRect *result)
{
gboolean corners[4];
/* Intersects with top left corner? */
corners[0] = rounded_rect_has_corner (rounded, 0) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 0));
if (corners[0] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 0)))
return FALSE;
/* top right ? */
corners[1] = rounded_rect_has_corner (rounded, 1) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 1));
if (corners[1] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 1)))
return FALSE;
/* bottom right ? */
corners[2] = rounded_rect_has_corner (rounded, 2) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 2));
if (corners[2] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 2)))
return FALSE;
/* bottom left ? */
corners[3] = rounded_rect_has_corner (rounded, 3) &&
rect_intersects (non_rounded,
&rounded_rect_corner (rounded, 3));
if (corners[3] && !rect_contains_rect (non_rounded,
&rounded_rect_corner (rounded, 3)))
return FALSE;
/* We do intersect with at least one of the corners, but in such a way that the
* intersection between the two clips can still be represented by a single rounded
* rect in a trivial way. do that.
*/
graphene_rect_intersection (non_rounded, &rounded->bounds, &result->bounds);
for (guint i = 0; i < 4; i++)
{
if (corners[i])
result->corner[i] = rounded->corner[i];
else
result->corner[i].width = result->corner[i].height = 0;
}
return TRUE;
}
static inline void
init_projection_matrix (graphene_matrix_t *projection,
const graphene_rect_t *viewport)
@@ -466,14 +551,13 @@ extract_matrix_metadata (GskGLRenderModelview *modelview)
case GSK_TRANSFORM_CATEGORY_2D:
{
float skew_x, skew_y, angle, dx, dy;
float xx, xy, yx, yy, dx, dy;
gsk_transform_to_2d_components (modelview->transform,
&skew_x, &skew_y,
&modelview->scale_x, &modelview->scale_y,
&angle, &dx, &dy);
modelview->dx = 0;
modelview->dy = 0;
gsk_transform_to_2d (modelview->transform,
&xx, &xy, &yx, &yy, &dx, &dy);
modelview->scale_x = sqrtf (xx * xx + xy * xy);
modelview->scale_y = sqrtf (yx * yx + yy * yy);
}
break;
@@ -834,10 +918,10 @@ gsk_gl_render_job_untransform_bounds (GskGLRenderJob *job,
}
static inline void
gsk_gl_render_job_translate_rounded_rect (GskGLRenderJob *job,
gsk_gl_render_job_transform_rounded_rect (GskGLRenderJob *job,
const GskRoundedRect *rect,
GskRoundedRect *out_rect)
{
{
out_rect->bounds.origin.x = job->offset_x + rect->bounds.origin.x;
out_rect->bounds.origin.y = job->offset_y + rect->bounds.origin.y;
out_rect->bounds.size.width = rect->bounds.size.width;
@@ -845,52 +929,6 @@ gsk_gl_render_job_translate_rounded_rect (GskGLRenderJob *job,
memcpy (out_rect->corner, rect->corner, sizeof rect->corner);
}
static inline void
rounded_rect_scale_corners (const GskRoundedRect *rect,
GskRoundedRect *out_rect,
float scale_x,
float scale_y)
{
for (guint i = 0; i < G_N_ELEMENTS (out_rect->corner); i++)
{
out_rect->corner[i].width = rect->corner[i].width * fabs (scale_x);
out_rect->corner[i].height = rect->corner[i].height * fabs (scale_y);
}
if (scale_x < 0)
{
graphene_size_t p;
p = out_rect->corner[GSK_CORNER_TOP_LEFT];
out_rect->corner[GSK_CORNER_TOP_LEFT] = out_rect->corner[GSK_CORNER_TOP_RIGHT];
out_rect->corner[GSK_CORNER_TOP_RIGHT] = p;
p = out_rect->corner[GSK_CORNER_BOTTOM_LEFT];
out_rect->corner[GSK_CORNER_BOTTOM_LEFT] = out_rect->corner[GSK_CORNER_BOTTOM_RIGHT];
out_rect->corner[GSK_CORNER_BOTTOM_RIGHT] = p;
}
if (scale_y < 0)
{
graphene_size_t p;
p = out_rect->corner[GSK_CORNER_TOP_LEFT];
out_rect->corner[GSK_CORNER_TOP_LEFT] = out_rect->corner[GSK_CORNER_BOTTOM_LEFT];
out_rect->corner[GSK_CORNER_BOTTOM_LEFT] = p;
p = out_rect->corner[GSK_CORNER_TOP_RIGHT];
out_rect->corner[GSK_CORNER_TOP_RIGHT] = out_rect->corner[GSK_CORNER_BOTTOM_RIGHT];
out_rect->corner[GSK_CORNER_BOTTOM_RIGHT] = p;
}
}
static inline void
gsk_gl_render_job_transform_rounded_rect (GskGLRenderJob *job,
const GskRoundedRect *rect,
GskRoundedRect *out_rect)
{
gsk_gl_render_job_transform_bounds (job, &rect->bounds, &out_rect->bounds);
rounded_rect_scale_corners (rect, out_rect, job->scale_x, job->scale_y);
}
static inline void
rounded_rect_get_inner (const GskRoundedRect *rect,
graphene_rect_t *inner)
@@ -1193,12 +1231,13 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
{
float scale_x = job->scale_x;
float scale_y = job->scale_y;
int surface_width = ceilf (node->bounds.size.width * fabs (scale_x));
int surface_height = ceilf (node->bounds.size.height * fabs (scale_y));
int surface_width = ceilf (node->bounds.size.width * scale_x);
int surface_height = ceilf (node->bounds.size.height * scale_y);
GdkTexture *texture;
cairo_surface_t *surface;
cairo_surface_t *rendered_surface;
cairo_t *cr;
int cached_id;
int texture_id;
GskTextureKey key;
@@ -1210,10 +1249,18 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
key.scale_x = scale_x;
key.scale_y = scale_y;
texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key);
if (texture_id != 0)
goto done;
if (cached_id != 0)
{
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
GL_TEXTURE_2D, GL_TEXTURE0, cached_id);
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
gsk_gl_render_job_end_draw (job);
return;
}
/* We first draw the recording surface on an image surface,
* just because the scaleY(-1) later otherwise screws up the
@@ -1223,7 +1270,7 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
surface_width,
surface_height);
cairo_surface_set_device_scale (rendered_surface, fabs (scale_x), fabs (scale_y));
cairo_surface_set_device_scale (rendered_surface, scale_x, scale_y);
cr = cairo_create (rendered_surface);
cairo_save (cr);
@@ -1237,16 +1284,15 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
surface_width,
surface_height);
cairo_surface_set_device_scale (surface, fabs (scale_x), fabs (scale_y));
cairo_surface_set_device_scale (surface, scale_x, scale_y);
cr = cairo_create (surface);
/* We draw upside down here, so it matches what GL does. */
cairo_save (cr);
cairo_scale (cr, scale_x < 0 ? -1 : 1, scale_y < 0 ? 1 : -1);
cairo_translate (cr, scale_x < 0 ? - surface_width / fabs (scale_x) : 0,
scale_y < 0 ? 0 : - surface_height / fabs (scale_y));
cairo_scale (cr, 1, -1);
cairo_translate (cr, 0, - surface_height / scale_y);
cairo_set_source_surface (cr, rendered_surface, 0, 0);
cairo_rectangle (cr, 0, 0, surface_width / fabs (scale_x), surface_height / fabs (scale_y));
cairo_rectangle (cr, 0, 0, surface_width / scale_x, surface_height / scale_y);
cairo_fill (cr);
cairo_restore (cr);
@@ -1285,16 +1331,6 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
gsk_gl_driver_cache_texture (job->driver, &key, texture_id);
done:
if (scale_x < 0 || scale_y < 0)
{
GskTransform *transform = gsk_transform_translate (NULL,
&GRAPHENE_POINT_INIT (scale_x < 0 ? - surface_width : 0,
scale_y < 0 ? - surface_height : 0));
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
}
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -1303,9 +1339,6 @@ done:
texture_id);
gsk_gl_render_job_draw_offscreen_rect (job, &node->bounds);
gsk_gl_render_job_end_draw (job);
if (scale_x < 0 || scale_y < 0)
gsk_gl_render_job_pop_modelview (job);
}
static guint
@@ -1460,10 +1493,10 @@ blur_node (GskGLRenderJob *job,
offscreen->texture_id = blur_offscreen (job,
offscreen,
texture_width * fabs (scale_x),
texture_height * fabs (scale_y),
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
texture_width * scale_x,
texture_height * scale_y,
blur_radius * scale_x,
blur_radius * scale_y);
init_full_texture_region (offscreen);
}
@@ -1645,7 +1678,6 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job,
{
graphene_rect_t transformed_clip;
GskRoundedRect intersection;
GskRoundedRectIntersection result;
gsk_gl_render_job_transform_bounds (job, clip, &transformed_clip);
@@ -1659,17 +1691,10 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job,
gsk_gl_render_job_push_clip (job, &intersection);
gsk_gl_render_job_visit_node (job, child);
gsk_gl_render_job_pop_clip (job);
return;
}
result = gsk_rounded_rect_intersect_with_rect (&job->current_clip->rect,
&transformed_clip,
&intersection);
if (result == GSK_INTERSECTION_EMPTY)
return;
if (result == GSK_INTERSECTION_NONEMPTY)
else if (intersect_rounded_rectilinear (&transformed_clip,
&job->current_clip->rect,
&intersection))
{
gsk_gl_render_job_push_clip (job, &intersection);
gsk_gl_render_job_visit_node (job, child);
@@ -1716,26 +1741,28 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
const GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
const GskRoundedRect *clip = gsk_rounded_clip_node_get_clip (node);
GskRoundedRect transformed_clip;
float scale_x = job->scale_x;
float scale_y = job->scale_y;
gboolean need_offscreen;
if (node_is_invisible (child))
return;
gsk_gl_render_job_transform_rounded_rect (job, clip, &transformed_clip);
gsk_gl_render_job_transform_bounds (job, &clip->bounds, &transformed_clip.bounds);
for (guint i = 0; i < G_N_ELEMENTS (transformed_clip.corner); i++)
{
transformed_clip.corner[i].width = clip->corner[i].width * scale_x;
transformed_clip.corner[i].height = clip->corner[i].height * scale_y;
}
if (job->current_clip->is_rectilinear)
{
GskRoundedRect intersected_clip;
GskRoundedRectIntersection result;
result = gsk_rounded_rect_intersect_with_rect (&transformed_clip,
&job->current_clip->rect.bounds,
&intersected_clip);
if (result == GSK_INTERSECTION_EMPTY)
return;
if (result == GSK_INTERSECTION_NONEMPTY)
if (intersect_rounded_rectilinear (&job->current_clip->rect.bounds,
&transformed_clip,
&intersected_clip))
{
gsk_gl_render_job_push_clip (job, &intersected_clip);
gsk_gl_render_job_visit_node (job, child);
@@ -1750,13 +1777,22 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
if (job->clip->len <= 1)
need_offscreen = FALSE;
else if (gsk_rounded_rect_contains_rect (&job->current_clip->rect, &transformed_clip.bounds))
else if (rounded_inner_rect_contains_rect (&job->current_clip->rect, &transformed_clip.bounds))
need_offscreen = FALSE;
else
need_offscreen = TRUE;
if (!need_offscreen)
{
/* If the new clip entirely contains the current clip, the intersection is simply
* the current clip, so we can ignore the new one.
*/
if (rounded_inner_rect_contains_rect (&transformed_clip, &job->current_clip->rect.bounds))
{
gsk_gl_render_job_visit_node (job, child);
return;
}
gsk_gl_render_job_push_clip (job, &transformed_clip);
gsk_gl_render_job_visit_node (job, child);
gsk_gl_render_job_pop_clip (job);
@@ -1878,7 +1914,7 @@ gsk_gl_render_job_visit_border_node (GskGLRenderJob *job,
sizes[3].w = MAX (widths[3], rounded_outline->corner[3].width);
}
gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, border));
@@ -1982,7 +2018,7 @@ gsk_gl_render_job_visit_css_background (GskGLRenderJob *job,
rgba_to_half (&gsk_border_node_get_colors (node2)[0], color);
rgba_to_half (gsk_color_node_get_color (child), color2);
gsk_gl_render_job_translate_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_transform_rounded_rect (job, rounded_outline, &outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, filled_border));
@@ -2123,7 +2159,6 @@ gsk_gl_render_job_visit_transform_node (GskGLRenderJob *job,
scale = gsk_transform_translate (gsk_transform_scale (NULL, sx, sy), &GRAPHENE_POINT_INIT (tx, ty));
gsk_gl_render_job_push_modelview (job, scale);
transform = gsk_transform_transform (gsk_transform_invert (scale), transform);
gsk_transform_unref (scale);
}
}
@@ -2174,7 +2209,7 @@ gsk_gl_render_job_visit_unblurred_inset_shadow_node (GskGLRenderJob *job,
GskRoundedRect transformed_outline;
guint16 color[4];
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
@@ -2274,7 +2309,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
prev_fbo = gsk_gl_command_queue_bind_framebuffer (job->command_queue, render_target->framebuffer_id);
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
gsk_gl_render_job_translate_rounded_rect (job, &outline_to_blur, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, &outline_to_blur, &transformed_outline);
/* Actual inset shadow outline drawing */
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow));
@@ -2307,8 +2342,8 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
&offscreen,
texture_width,
texture_height,
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
blur_radius * scale_x,
blur_radius * scale_y);
gsk_gl_driver_release_render_target (job->driver, render_target, TRUE);
@@ -2330,7 +2365,14 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
{
GskRoundedRect node_clip;
gsk_gl_render_job_translate_rounded_rect (job, node_outline, &node_clip);
gsk_gl_render_job_transform_bounds (job, &node_outline->bounds, &node_clip.bounds);
for (guint i = 0; i < 4; i ++)
{
node_clip.corner[i].width = node_outline->corner[i].width * scale_x;
node_clip.corner[i].height = node_outline->corner[i].height * scale_y;
}
gsk_gl_render_job_push_clip (job, &node_clip);
}
@@ -2380,7 +2422,7 @@ gsk_gl_render_job_visit_unblurred_outset_shadow_node (GskGLRenderJob *job,
rgba_to_half (gsk_outset_shadow_node_get_color (node), color);
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, unblurred_outset_shadow));
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
@@ -2573,8 +2615,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
&offscreen,
texture_width,
texture_height,
blur_radius * fabs (scale_x),
blur_radius * fabs (scale_y));
blur_radius * scale_x,
blur_radius * scale_y);
gsk_gl_shadow_library_insert (job->driver->shadows_library,
&scaled_outline,
@@ -2588,7 +2630,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
blurred_texture_id = cached_tid;
}
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
gsk_gl_render_job_transform_rounded_rect (job, outline, &transformed_outline);
if (!do_slicing)
{
@@ -2824,12 +2866,8 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
offscreen_end.reset_clip = TRUE;
offscreen_end.bounds = &node->bounds;
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabs (job->scale_x), fabs (job->scale_y)));
if (!gsk_gl_render_job_visit_node_with_offscreen (job, start_node, &offscreen_start))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_visit_node (job, end_node);
return;
}
@@ -2838,18 +2876,12 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_visit_node_with_offscreen (job, end_node, &offscreen_end))
{
float prev_alpha;
gsk_gl_render_job_pop_modelview (job);
prev_alpha = gsk_gl_render_job_set_alpha (job, job->alpha * progress);
float prev_alpha = gsk_gl_render_job_set_alpha (job, job->alpha * progress);
gsk_gl_render_job_visit_node (job, start_node);
gsk_gl_render_job_set_alpha (job, prev_alpha);
return;
}
gsk_gl_render_job_pop_modelview (job);
g_assert (offscreen_end.texture_id);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, cross_fade));
@@ -3243,14 +3275,10 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
bottom_offscreen.force_offscreen = TRUE;
bottom_offscreen.reset_clip = TRUE;
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabs (job->scale_x), fabs (job->scale_y)));
/* TODO: We create 2 textures here as big as the blend node, but both the
* start and the end node might be a lot smaller than that. */
if (!gsk_gl_render_job_visit_node_with_offscreen (job, bottom_child, &bottom_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_visit_node (job, top_child);
return;
}
@@ -3259,8 +3287,6 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_visit_node_with_offscreen (job, top_child, &top_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -3274,8 +3300,6 @@ gsk_gl_render_job_visit_blend_node (GskGLRenderJob *job,
g_assert (top_offscreen.was_offscreen);
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blend));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -3312,14 +3336,11 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
mask_offscreen.reset_clip = TRUE;
mask_offscreen.do_not_cache = TRUE;
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabs (job->scale_x), fabs (job->scale_y)));
/* TODO: We create 2 textures here as big as the mask node, but both
* nodes might be a lot smaller than that.
*/
if (!gsk_gl_render_job_visit_node_with_offscreen (job, source, &source_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_visit_node (job, source);
return;
}
@@ -3328,14 +3349,11 @@ gsk_gl_render_job_visit_mask_node (GskGLRenderJob *job,
if (!gsk_gl_render_job_visit_node_with_offscreen (job, mask, &mask_offscreen))
{
gsk_gl_render_job_pop_modelview (job);
return;
}
g_assert (mask_offscreen.was_offscreen);
gsk_gl_render_job_pop_modelview (job);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, mask));
gsk_gl_program_set_uniform_texture (job->current_program,
UNIFORM_SHARED_SOURCE, 0,
@@ -3569,8 +3587,8 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
float scale_y = bounds->size.height / texture->height;
gboolean use_mipmap;
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
(scale_y * fabs (job->scale_y)) < 0.5;
use_mipmap = (scale_x * job->scale_x) < 0.5 ||
(scale_y * job->scale_y) < 0.5;
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size)
@@ -4102,7 +4120,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
}
if (gsk_render_node_get_node_type (node) == GSK_TEXTURE_NODE &&
!offscreen->force_offscreen)
offscreen->force_offscreen == FALSE)
{
GdkTexture *texture = gsk_texture_node_get_texture (node);
gsk_gl_render_job_upload_texture (job, texture, FALSE, offscreen);
@@ -4120,7 +4138,6 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
gboolean flipped_x = job->scale_x < 0;
gboolean flipped_y = job->scale_y < 0;
graphene_rect_t viewport;
gboolean reset_clip = FALSE;
if (flipped_x || flipped_y)
{
@@ -4128,7 +4145,6 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
flipped_x ? -1 : 1,
flipped_y ? -1 : 1);
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
}
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
@@ -4166,9 +4182,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
{
GskTransform *transform = gsk_transform_scale (NULL, downscale_x, downscale_y);
gsk_gl_render_job_push_modelview (job, transform);
gsk_transform_unref (transform);
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
graphene_rect_scale (&viewport, downscale_x, downscale_y, &viewport);
}
if (downscale_x == 1)
@@ -4252,25 +4266,11 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
if (offscreen->reset_clip)
{
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (job->viewport));
reset_clip = TRUE;
}
else if (flipped_x || flipped_y || downscale_x != 1 || downscale_y != 1)
{
GskRoundedRect new_clip;
float scale_x = flipped_x ? - downscale_x : downscale_x;
float scale_y = flipped_y ? - downscale_y : downscale_y;
graphene_rect_scale (&job->current_clip->rect.bounds, scale_x, scale_y, &new_clip.bounds);
rounded_rect_scale_corners (&job->current_clip->rect, &new_clip, scale_x, scale_y);
gsk_gl_render_job_push_clip (job, &new_clip);
reset_clip = TRUE;
}
gsk_gl_render_job_push_clip (job, &GSK_ROUNDED_RECT_INIT_FROM_RECT (job->viewport));
gsk_gl_render_job_visit_node (job, node);
if (reset_clip)
if (offscreen->reset_clip)
gsk_gl_render_job_pop_clip (job);
if (downscale_x != 1 || downscale_y != 1)

View File

@@ -19,9 +19,6 @@ void main() {
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_normalize(outside);
gsk_rounded_rect_normalize(inside);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}
@@ -37,9 +34,10 @@ _IN_ _GSK_ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
void main() {
vec2 frag = gsk_get_frag_coord();
float outer_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag);
float inner_coverage = gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag);
float alpha = clamp(outer_coverage - inner_coverage, 0.0, 1.0);
float alpha = clamp(gsk_rounded_rect_coverage(gsk_decode_rect(transformed_outside_outline), frag) -
gsk_rounded_rect_coverage(gsk_decode_rect(transformed_inside_outline), frag),
0.0, 1.0);
gskSetScaledOutputColor(final_color, alpha);
}

View File

@@ -21,9 +21,6 @@ void main() {
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_normalize(outside);
gsk_rounded_rect_normalize(inside);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}

View File

@@ -22,9 +22,6 @@ void main() {
gsk_rounded_rect_transform(outside, u_modelview);
gsk_rounded_rect_transform(inside, u_modelview);
gsk_rounded_rect_normalize(outside);
gsk_rounded_rect_normalize(inside);
gsk_rounded_rect_encode(outside, transformed_outside_outline);
gsk_rounded_rect_encode(inside, transformed_inside_outline);
}

View File

@@ -15,7 +15,6 @@ void main() {
GskRoundedRect outline = gsk_create_rect(u_outline_rect);
gsk_rounded_rect_transform(outline, u_modelview);
gsk_rounded_rect_normalize(outline);
gsk_rounded_rect_encode(outline, transformed_outline);
}

View File

@@ -16,15 +16,11 @@ _IN_ vec2 vUv;
GskRoundedRect gsk_decode_rect(_GSK_ROUNDED_RECT_UNIFORM_ r)
{
GskRoundedRect rect;
#if defined(GSK_GLES) || defined(GSK_LEGACY)
rect = GskRoundedRect(r[0], r[1], r[2]);
return GskRoundedRect(r[0], r[1], r[2]);
#else
rect = r;
return r;
#endif
gsk_rounded_rect_normalize (rect);
return rect;
}
float

View File

@@ -22,55 +22,6 @@ struct GskRoundedRect
vec4 corner_points2; // xy = bottom right, zw = bottom left
};
void gsk_rounded_rect_normalize(inout GskRoundedRect r)
{
if (r.bounds.x > r.bounds.z)
{
float t = r.bounds.x;
r.bounds.x = r.bounds.z;
r.bounds.z = t;
vec2 c = r.corner_points1.xy;
r.corner_points1.xy = r.corner_points1.zw;
r.corner_points1.zw = c;
c = r.corner_points2.xy;
r.corner_points2.xy = r.corner_points2.zw;
r.corner_points2.zw = c;
}
if (r.bounds.y > r.bounds.w)
{
float t = r.bounds.y;
r.bounds.y = r.bounds.w;
r.bounds.w = t;
vec2 c = r.corner_points1.xy;
r.corner_points1.xy = r.corner_points2.xy;
r.corner_points2.xy = c;
c = r.corner_points1.zw;
r.corner_points1.zw = r.corner_points2.zw;
r.corner_points2.zw = c;
}
}
void gsk_bounds_normalize (inout vec4 bounds)
{
if (bounds.x > bounds.z)
{
float t = bounds.x;
bounds.x = bounds.z;
bounds.z = t;
}
if (bounds.y > bounds.w)
{
float t = bounds.y;
bounds.y = bounds.w;
bounds.w = t;
}
}
// Transform from a C GskRoundedRect to what we need.
GskRoundedRect
gsk_create_rect(vec4[3] data)
@@ -82,21 +33,13 @@ gsk_create_rect(vec4[3] data)
vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
bounds.xw + vec2(data[2].zw * vec2(1, -1)));
GskRoundedRect rect = GskRoundedRect(bounds, corner_points1, corner_points2);
gsk_rounded_rect_normalize (rect);
return rect;
return GskRoundedRect(bounds, corner_points1, corner_points2);
}
vec4
gsk_get_bounds(vec4[3] data)
{
vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
gsk_bounds_normalize (bounds);
return bounds;
return vec4(data[0].xy, data[0].xy + data[0].zw);
}
vec4 gsk_premultiply(vec4 c) {

View File

@@ -1650,28 +1650,12 @@ gsk_texture_node_diff (GskRenderNode *node1,
{
GskTextureNode *self1 = (GskTextureNode *) node1;
GskTextureNode *self2 = (GskTextureNode *) node2;
cairo_region_t *sub;
if (!graphene_rect_equal (&node1->bounds, &node2->bounds) ||
gdk_texture_get_width (self1->texture) != gdk_texture_get_width (self2->texture) ||
gdk_texture_get_height (self1->texture) != gdk_texture_get_height (self2->texture))
{
gsk_render_node_diff_impossible (node1, node2, region);
return;
}
if (self1->texture == self2->texture)
if (graphene_rect_equal (&node1->bounds, &node2->bounds) &&
self1->texture == self2->texture)
return;
sub = cairo_region_create ();
gdk_texture_diff (self1->texture, self2->texture, sub);
region_union_region_affine (region,
sub,
node1->bounds.size.width / gdk_texture_get_width (self1->texture),
node1->bounds.size.height / gdk_texture_get_height (self1->texture),
node1->bounds.origin.x,
node1->bounds.origin.y);
cairo_region_destroy (sub);
gsk_render_node_diff_impossible (node1, node2, region);
}
static void
@@ -1844,29 +1828,13 @@ gsk_texture_scale_node_diff (GskRenderNode *node1,
{
GskTextureScaleNode *self1 = (GskTextureScaleNode *) node1;
GskTextureScaleNode *self2 = (GskTextureScaleNode *) node2;
cairo_region_t *sub;
if (!graphene_rect_equal (&node1->bounds, &node2->bounds) ||
self1->filter != self2->filter ||
gdk_texture_get_width (self1->texture) != gdk_texture_get_width (self2->texture) ||
gdk_texture_get_height (self1->texture) != gdk_texture_get_height (self2->texture))
{
gsk_render_node_diff_impossible (node1, node2, region);
return;
}
if (self1->texture == self2->texture)
if (graphene_rect_equal (&node1->bounds, &node2->bounds) &&
self1->texture == self2->texture &&
self1->filter == self2->filter)
return;
sub = cairo_region_create ();
gdk_texture_diff (self1->texture, self2->texture, sub);
region_union_region_affine (region,
sub,
node1->bounds.size.width / gdk_texture_get_width (self1->texture),
node1->bounds.size.height / gdk_texture_get_height (self1->texture),
node1->bounds.origin.x,
node1->bounds.origin.y);
cairo_region_destroy (sub);
gsk_render_node_diff_impossible (node1, node2, region);
}
static void

View File

@@ -871,7 +871,7 @@ create_ascii_glyphs (PangoFont *font)
if (!pango_coverage_get (coverage, i))
break;
}
g_object_unref (coverage);
pango_coverage_unref (coverage);
if (i < MAX_ASCII_GLYPH)
return NULL;
@@ -1371,10 +1371,7 @@ parse_shader (GtkCssParser *parser,
GskGLShader *shader;
if (!parse_string (parser, context, &sourcecode))
{
gtk_css_parser_error_value (parser, "Not a string");
return FALSE;
}
return FALSE;
bytes = g_bytes_new_take (sourcecode, strlen (sourcecode));
shader = gsk_gl_shader_new_from_bytes (bytes);
@@ -1503,29 +1500,6 @@ parse_shader_args (GtkCssParser *parser,
return TRUE;
}
static const char default_glsl[] =
"void\n"
"mainImage(out vec4 fragColor,\n"
" in vec2 fragCoord,\n"
" in vec2 resolution,\n"
" in vec2 uv)\n"
"{\n"
" fragColor = vec4(1.0, 105.0/255.0, 180.0/255.0, 1.0);\n"
"}";
static GskGLShader *
get_default_glshader (void)
{
GBytes *bytes;
GskGLShader *shader;
bytes = g_bytes_new (default_glsl, strlen (default_glsl) + 1);
shader = gsk_gl_shader_new_from_bytes (bytes);
g_bytes_unref (bytes);
return shader;
}
static GskRenderNode *
parse_glshader_node (GtkCssParser *parser,
Context *context)
@@ -1546,7 +1520,6 @@ parse_glshader_node (GtkCssParser *parser,
{ "child4", parse_node, clear_node, &child[3] },
};
GskGLShader *shader;
GskShaderArgsBuilder *builder;
GskRenderNode *node;
GBytes *args = NULL;
int len, i;
@@ -1559,17 +1532,8 @@ parse_glshader_node (GtkCssParser *parser,
break;
}
if (shader_info.shader)
shader = shader_info.shader;
else
shader = get_default_glshader ();
if (shader_info.args)
builder = shader_info.args;
else
builder = gsk_shader_args_builder_new (shader, NULL);
args = gsk_shader_args_builder_free_to_args (builder);
shader = shader_info.shader;
args = gsk_shader_args_builder_free_to_args (shader_info.args);
node = gsk_gl_shader_node_new (shader, &bounds, args, child, len);

View File

@@ -519,174 +519,8 @@ gsk_rounded_rect_intersects_rect (const GskRoundedRect *self,
gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x, rect->origin.y + rect->size.height)) == OUTSIDE_TOP_RIGHT ||
gsk_rounded_rect_locate_point (self, &GRAPHENE_POINT_INIT (rect->origin.x + rect->size.width, rect->origin.y + rect->size.height)) == OUTSIDE_TOP_LEFT)
return FALSE;
return TRUE;
}
#define rect_point0(r) ((r)->origin)
#define rect_point1(r) (GRAPHENE_POINT_INIT ((r)->origin.x + (r)->size.width, (r)->origin.y))
#define rect_point2(r) (GRAPHENE_POINT_INIT ((r)->origin.x + (r)->size.width, (r)->origin.y + (r)->size.height))
#define rect_point3(r) (GRAPHENE_POINT_INIT ((r)->origin.x, (r)->origin.y + (r)->size.height))
#define rounded_rect_corner0(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x, \
(r)->bounds.origin.y, \
(r)->corner[0].width, (r)->corner[0].height))
#define rounded_rect_corner1(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x + (r)->bounds.size.width - (r)->corner[1].width, \
(r)->bounds.origin.y, \
(r)->corner[1].width, (r)->corner[1].height))
#define rounded_rect_corner2(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x + (r)->bounds.size.width - (r)->corner[2].width, \
(r)->bounds.origin.y + (r)->bounds.size.height - (r)->corner[2].height, \
(r)->corner[2].width, (r)->corner[2].height))
#define rounded_rect_corner3(r) \
(GRAPHENE_RECT_INIT((r)->bounds.origin.x, \
(r)->bounds.origin.y + (r)->bounds.size.height - (r)->corner[3].height, \
(r)->corner[3].width, (r)->corner[3].height))
enum {
BELOW,
INNER,
ABOVE
};
static inline void
classify_point (const graphene_point_t *p, const graphene_rect_t *rect, int *px, int *py)
{
if (p->x <= rect->origin.x)
*px = BELOW;
else if (p->x >= rect->origin.x + rect->size.width)
*px = ABOVE;
else
*px = INNER;
if (p->y <= rect->origin.y)
*py = BELOW;
else if (p->y >= rect->origin.y + rect->size.height)
*py = ABOVE;
else
*py = INNER;
}
GskRoundedRectIntersection
gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
const graphene_rect_t *rect,
GskRoundedRect *result)
{
int px, py, qx, qy;
if (!graphene_rect_intersection (&self->bounds, rect, &result->bounds))
return GSK_INTERSECTION_EMPTY;
classify_point (&rect_point0 (rect), &rounded_rect_corner0 (self), &px, &py);
if (px == BELOW && py == BELOW)
{
classify_point (&rect_point2 (rect), &rounded_rect_corner0 (self), &qx, &qy);
if (qx == BELOW || qy == BELOW)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == ABOVE && qy == ABOVE)
result->corner[0] = self->corner[0];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) == OUTSIDE_TOP_LEFT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[0].width = result->corner[0].height = 0;
classify_point (&rect_point1 (rect), &rounded_rect_corner1 (self), &px, &py);
if (px == ABOVE && py == BELOW)
{
classify_point (&rect_point3 (rect), &rounded_rect_corner1 (self), &qx, &qy);
if (qx == ABOVE || qy == BELOW)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == BELOW && qy == ABOVE)
result->corner[1] = self->corner[1];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) == OUTSIDE_TOP_RIGHT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[1].width = result->corner[1].height = 0;
classify_point (&rect_point2 (rect), &rounded_rect_corner2 (self), &px, &py);
if (px == ABOVE && py == ABOVE)
{
classify_point (&rect_point0 (rect), &rounded_rect_corner2 (self), &qx, &qy);
if (qx == ABOVE || qy == ABOVE)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == BELOW && qy == BELOW)
result->corner[2] = self->corner[2];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) == OUTSIDE_BOTTOM_RIGHT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[2].width = result->corner[2].height = 0;
classify_point (&rect_point3 (rect), &rounded_rect_corner3 (self), &px, &py);
if (px == BELOW && py == ABOVE)
{
classify_point (&rect_point1 (rect), &rounded_rect_corner3 (self), &qx, &qy);
if (qx == BELOW || qy == ABOVE)
return GSK_INTERSECTION_EMPTY;
else if (qx == INNER && qy == INNER &&
gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) != INSIDE)
return GSK_INTERSECTION_EMPTY;
else if (qx == ABOVE && qy == BELOW)
result->corner[3] = self->corner[3];
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else if ((px == INNER || py == INNER) &&
gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) != INSIDE)
{
if (gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) == OUTSIDE_BOTTOM_LEFT)
return GSK_INTERSECTION_EMPTY;
else
return GSK_INTERSECTION_NOT_REPRESENTABLE;
}
else
result->corner[3].width = result->corner[3].height = 0;
return GSK_INTERSECTION_NONEMPTY;
return TRUE;
}
static void
@@ -731,7 +565,7 @@ gsk_rounded_rect_path (const GskRoundedRect *self,
self->corner[GSK_CORNER_TOP_LEFT].width,
self->corner[GSK_CORNER_TOP_LEFT].height,
G_PI, 3 * G_PI_2);
_cairo_ellipsis (cr,
_cairo_ellipsis (cr,
self->bounds.origin.x + self->bounds.size.width - self->corner[GSK_CORNER_TOP_RIGHT].width,
self->bounds.origin.y + self->corner[GSK_CORNER_TOP_RIGHT].height,
self->corner[GSK_CORNER_TOP_RIGHT].width,
@@ -815,4 +649,5 @@ gsk_rounded_rect_to_string (const GskRoundedRect *self)
self->corner[2].height,
self->corner[3].width,
self->corner[3].height);
}

View File

@@ -34,16 +34,6 @@ gboolean gsk_rounded_rect_equal (gconstpointer
gconstpointer rect2) G_GNUC_PURE;
char * gsk_rounded_rect_to_string (const GskRoundedRect *self) G_GNUC_MALLOC;
typedef enum {
GSK_INTERSECTION_EMPTY,
GSK_INTERSECTION_NONEMPTY,
GSK_INTERSECTION_NOT_REPRESENTABLE
} GskRoundedRectIntersection;
GskRoundedRectIntersection gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
const graphene_rect_t *rect,
GskRoundedRect *result) G_GNUC_PURE;
G_END_DECLS

View File

@@ -164,7 +164,7 @@ gskenum_h = gsk_enums[1]
gskresources = gnome.compile_resources('gskresources',
gsk_resources_xml,
dependencies: gsk_private_vulkan_compiled_shaders_deps,
source_dir: [meson.current_build_dir(), meson.current_source_dir()],
source_dir: meson.current_source_dir(),
c_name: '_gsk',
extra_args: [ '--manual-register', ],
)

View File

@@ -1012,8 +1012,9 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskVulkanUploader *uploader,
GskRenderNode *node,
const graphene_rect_t *bounds,
GskVulkanClip *current_clip,
graphene_rect_t *tex_bounds)
graphene_rect_t *tex_rect)
{
GskVulkanImage *result;
cairo_surface_t *surface;
@@ -1022,12 +1023,16 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
switch ((guint) gsk_render_node_get_node_type (node))
{
case GSK_TEXTURE_NODE:
result = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
gsk_texture_node_get_texture (node),
uploader);
gsk_vulkan_render_add_cleanup_image (render, result);
*tex_bounds = node->bounds;
return result;
if (graphene_rect_equal (bounds, &node->bounds))
{
result = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
gsk_texture_node_get_texture (node),
uploader);
gsk_vulkan_render_add_cleanup_image (render, result);
*tex_rect = GRAPHENE_RECT_INIT(0, 0, 1, 1);
return result;
}
break;
case GSK_CAIRO_NODE:
/* We're using recording surfaces, so drawing them to an image
@@ -1045,9 +1050,9 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
graphene_rect_t clipped;
if (current_clip)
graphene_rect_intersection (&current_clip->rect.bounds, &node->bounds, &clipped);
graphene_rect_intersection (&current_clip->rect.bounds, bounds, &clipped);
else
clipped = node->bounds;
clipped = *bounds;
if (clipped.size.width == 0 || clipped.size.height == 0)
return NULL;
@@ -1106,30 +1111,33 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
/* assuming the unclipped bounds should go to texture coordinates 0..1,
* calculate the coordinates for the clipped texture size
*/
*tex_bounds = clipped;
tex_rect->origin.x = (bounds->origin.x - clipped.origin.x)/clipped.size.width;
tex_rect->origin.y = (bounds->origin.y - clipped.origin.y)/clipped.size.height;
tex_rect->size.width = bounds->size.width/clipped.size.width;
tex_rect->size.height = bounds->size.height/clipped.size.height;
return result;
}
}
GSK_RENDERER_DEBUG (gsk_vulkan_render_get_renderer (render), FALLBACK, "Node as texture not implemented for this case. Using %gx%g fallback surface",
ceil (node->bounds.size.width),
ceil (node->bounds.size.height));
ceil (bounds->size.width),
ceil (bounds->size.height));
#ifdef G_ENABLE_DEBUG
{
GskProfiler *profiler = gsk_renderer_get_profiler (gsk_vulkan_render_get_renderer (render));
gsk_profiler_counter_add (profiler,
self->fallback_pixels,
ceil (node->bounds.size.width) * ceil (node->bounds.size.height));
ceil (bounds->size.width) * ceil (bounds->size.height));
}
#endif
/* XXX: We could intersect bounds with clip bounds here */
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
ceil (node->bounds.size.width),
ceil (node->bounds.size.height));
ceil (bounds->size.width),
ceil (bounds->size.height));
cr = cairo_create (surface);
cairo_translate (cr, -node->bounds.origin.x, -node->bounds.origin.y);
cairo_translate (cr, -bounds->origin.x, -bounds->origin.y);
gsk_render_node_draw (node, cr);
@@ -1145,7 +1153,10 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
gsk_vulkan_render_add_cleanup_image (render, result);
*tex_bounds = node->bounds;
tex_rect->origin.x = (node->bounds.origin.x - bounds->origin.x)/bounds->size.width;
tex_rect->origin.y = (node->bounds.origin.y - bounds->origin.y)/bounds->size.height;
tex_rect->size.width = node->bounds.size.width/bounds->size.width;
tex_rect->size.height = node->bounds.size.height/bounds->size.height;
return result;
}
@@ -1239,18 +1250,6 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
gsk_vulkan_render_add_cleanup_image (render, op->source);
}
static void
get_tex_rect (graphene_rect_t *tex_coords,
const graphene_rect_t *rect,
const graphene_rect_t *tex)
{
graphene_rect_init (tex_coords,
(rect->origin.x - tex->origin.x) / tex->size.width,
(rect->origin.y - tex->origin.y) / tex->size.height,
rect->size.width / tex->size.width,
rect->size.height / tex->size.height);
}
void
gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
GskVulkanRender *render,
@@ -1295,61 +1294,63 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
case GSK_VULKAN_OP_OPACITY:
{
GskRenderNode *child = gsk_opacity_node_get_child (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
&child->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
}
break;
case GSK_VULKAN_OP_REPEAT:
{
GskRenderNode *child = gsk_repeat_node_get_child (op->render.node);
const graphene_rect_t *bounds = &op->render.node->bounds;
const graphene_rect_t *child_bounds = gsk_repeat_node_get_child_bounds (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
child_bounds,
NULL,
&tex_bounds);
get_tex_rect (&op->render.source_rect, child_bounds, &tex_bounds);
&op->render.source_rect);
op->render.source_rect.origin.x = (bounds->origin.x - child_bounds->origin.x)/child_bounds->size.width;
op->render.source_rect.origin.y = (bounds->origin.y - child_bounds->origin.y)/child_bounds->size.height;
op->render.source_rect.size.width = bounds->size.width / child_bounds->size.width;
op->render.source_rect.size.height = bounds->size.height / child_bounds->size.height;
}
break;
case GSK_VULKAN_OP_BLUR:
{
GskRenderNode *child = gsk_blur_node_get_child (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
&child->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
}
break;
case GSK_VULKAN_OP_COLOR_MATRIX:
{
GskRenderNode *child = gsk_color_matrix_node_get_child (op->render.node);
graphene_rect_t tex_bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
child,
&child->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
}
break;
@@ -1357,23 +1358,31 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
{
GskRenderNode *start = gsk_cross_fade_node_get_start_child (op->render.node);
GskRenderNode *end = gsk_cross_fade_node_get_end_child (op->render.node);
graphene_rect_t tex_bounds;
const graphene_rect_t *bounds = &op->render.node->bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
start,
&start->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
op->render.source_rect.origin.x = (bounds->origin.x - start->bounds.origin.x)/start->bounds.size.width;
op->render.source_rect.origin.y = (bounds->origin.y - start->bounds.origin.y)/start->bounds.size.height;
op->render.source_rect.size.width = bounds->size.width / start->bounds.size.width;
op->render.source_rect.size.height = bounds->size.height / start->bounds.size.height;
op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
end,
&end->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source2_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source2_rect);
op->render.source2_rect.origin.x = (bounds->origin.x - end->bounds.origin.x)/end->bounds.size.width;
op->render.source2_rect.origin.y = (bounds->origin.y - end->bounds.origin.y)/end->bounds.size.height;
op->render.source2_rect.size.width = bounds->size.width / end->bounds.size.width;
op->render.source2_rect.size.height = bounds->size.height / end->bounds.size.height;
}
break;
@@ -1381,23 +1390,31 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
{
GskRenderNode *top = gsk_blend_node_get_top_child (op->render.node);
GskRenderNode *bottom = gsk_blend_node_get_bottom_child (op->render.node);
graphene_rect_t tex_bounds;
const graphene_rect_t *bounds = &op->render.node->bounds;
op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
top,
&top->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source_rect);
op->render.source_rect.origin.x = (bounds->origin.x - top->bounds.origin.x)/top->bounds.size.width;
op->render.source_rect.origin.y = (bounds->origin.y - top->bounds.origin.y)/top->bounds.size.height;
op->render.source_rect.size.width = bounds->size.width / top->bounds.size.width;
op->render.source_rect.size.height = bounds->size.height / top->bounds.size.height;
op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
render,
uploader,
bottom,
&bottom->bounds,
clip,
&tex_bounds);
get_tex_rect (&op->render.source2_rect, &op->render.node->bounds, &tex_bounds);
&op->render.source2_rect);
op->render.source2_rect.origin.x = (bounds->origin.x - bottom->bounds.origin.x)/bottom->bounds.size.width;
op->render.source2_rect.origin.y = (bounds->origin.y - bottom->bounds.origin.y)/bottom->bounds.size.height;
op->render.source2_rect.size.width = bounds->size.width / bottom->bounds.size.width;
op->render.source2_rect.size.height = bounds->size.height / bottom->bounds.size.height;
}
break;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More