Compare commits
436 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dfefa884ad | |||
| 72b8c6cf74 | |||
| 501095452a | |||
| 2ede31b682 | |||
| 1355367360 | |||
| 761995ce3c | |||
| d164dd3146 | |||
| 4b9b55ab17 | |||
| 6e9767c7c1 | |||
| b2f783b70b | |||
| 5a68426c9a | |||
| 32d77fa874 | |||
| 8d00af6351 | |||
| a91a0720f5 | |||
| f01208ad94 | |||
| 56b955f819 | |||
| 0d7761269c | |||
| 9ebaafa2af | |||
| 25ea6beb39 | |||
| 905bb2c6fd | |||
| b4b7e9b040 | |||
| c3fcf0f7b0 | |||
| 60fc48e71f | |||
| 01d9886eea | |||
| a97231c8bf | |||
| 8ac8a027b2 | |||
| 070f3a61ac | |||
| 022347fa85 | |||
| ebb6076aca | |||
| 7b66bc45aa | |||
| 698aa7c0f3 | |||
| 70699efc71 | |||
| cebc95f253 | |||
| f9c6bd125b | |||
| 4733ca193b | |||
| c7b345f73e | |||
| 1fbc61f2cb | |||
| 565694ede5 | |||
| 0df03b054d | |||
| 73d01d3130 | |||
| 80f3357117 | |||
| d5b34aecdd | |||
| d16d2135e6 | |||
| 53b52abd30 | |||
| e55e9e3b36 | |||
| 9f9cea219f | |||
| dbee1a8160 | |||
| 133cd87bdf | |||
| 9f8e84cb60 | |||
| b8057b088e | |||
| cf8cca8724 | |||
| d97767014c | |||
| 2f974a1f5a | |||
| 4e2c7d5eb0 | |||
| a5d1cb93ef | |||
| 401b902cbf | |||
| 9f2778b97c | |||
| ed4eeb8adb | |||
| fb36d30685 | |||
| 385b9a7241 | |||
| c2abf30c46 | |||
| 50a47f55d9 | |||
| cd7fe772a7 | |||
| 317bba756e | |||
| 2212049e8f | |||
| 0f26a006ee | |||
| 3c451b3ec7 | |||
| 323adf9aa8 | |||
| 70f0cde730 | |||
| 14e78663ee | |||
| d8279209a2 | |||
| a0527ff0bd | |||
| 771ea81715 | |||
| f22a3f9ec6 | |||
| 246876a404 | |||
| 27a086b5f0 | |||
| 8158945de9 | |||
| 1c85141612 | |||
| 690381672b | |||
| 3d7ff44dc5 | |||
| a518c59098 | |||
| 1dd5e92499 | |||
| fbd3c5ebd0 | |||
| 48dc7df5b7 | |||
| 0c4c90d606 | |||
| da954d20f9 | |||
| ff262c081e | |||
| c6967234de | |||
| cdbfb35067 | |||
| 53e17ab14e | |||
| 550e98090a | |||
| 2771befdd9 | |||
| 911730493d | |||
| d05f47a695 | |||
| 11dc15207e | |||
| 4ea748a676 | |||
| b78d2a7f75 | |||
| 1fd9e1e916 | |||
| 24ceb47cbc | |||
| 8872e1cbb0 | |||
| c1e2ffac83 | |||
| 17df646663 | |||
| 6f8fae590f | |||
| 4146db0003 | |||
| 9c228cc634 | |||
| df2cdb6913 | |||
| 22a5447039 | |||
| a2475051fa | |||
| d41fb7c5a6 | |||
| 3b28c46595 | |||
| f57300b924 | |||
| c146f225ff | |||
| 9f4f65be4a | |||
| 93715b963e | |||
| c1407f2ca6 | |||
| 3b299f574d | |||
| a51c6aed47 | |||
| b552cf74dd | |||
| 0be0265751 | |||
| 207dd6fe0d | |||
| a87ff8d556 | |||
| 153cb8316e | |||
| 7ad7c0d8c1 | |||
| 61595af586 | |||
| d240c35850 | |||
| d276eb9e9a | |||
| afe4cbf26d | |||
| 76e5ef6937 | |||
| 0ed43f66a9 | |||
| 4882514234 | |||
| a15e87d2a6 | |||
| cc92b9b19f | |||
| bf0120f73d | |||
| 7f06eed8da | |||
| dc30044829 | |||
| 781fe2d7fa | |||
| b8a61f7899 | |||
| a44ca6756a | |||
| 490a9f193d | |||
| 754d364efd | |||
| 4939f0bb75 | |||
| 7537d80047 | |||
| c5bdf0a995 | |||
| 04870fc1a1 | |||
| 43e5bc795a | |||
| f3ec58d290 | |||
| 5b3d14e15b | |||
| 131ab11f5c | |||
| a2eb467663 | |||
| 06f85ee566 | |||
| aab40ad6a2 | |||
| 364eec24b1 | |||
| f1fe21e009 | |||
| 126cbccddf | |||
| 26cf74de5c | |||
| 2ecb8c08dc | |||
| ce7cc942e4 | |||
| a0e9d93b4c | |||
| 017aea1952 | |||
| 63d7b22924 | |||
| 3f3629154c | |||
| c3cfabfa96 | |||
| cd9525afc9 | |||
| 4d76beb59c | |||
| 59578c6d18 | |||
| 7bf8669d97 | |||
| e1156ea636 | |||
| 82f601253e | |||
| 96e710a76f | |||
| a45b66e1ca | |||
| 325b0010e4 | |||
| bf14a5f70b | |||
| 532e887c88 | |||
| 7830535c04 | |||
| 440c207146 | |||
| ed12c0cd5a | |||
| 543c7ae52a | |||
| 3ac50b81f2 | |||
| 6bac377fa5 | |||
| 3bb1c2298f | |||
| 637f6cc81b | |||
| 0ba8903fa5 | |||
| ee14b96c28 | |||
| cf86a01b65 | |||
| f57e211ba9 | |||
| e2c8b7fa6c | |||
| b486588883 | |||
| d0bf33339e | |||
| df09975753 | |||
| d21467e2e8 | |||
| c8529df309 | |||
| 5f03053569 | |||
| 1dbd74e181 | |||
| c8ae2d9002 | |||
| 03cd652063 | |||
| c0d49f296e | |||
| 1723ab34e1 | |||
| 55dbf0accb | |||
| b3d044a0b1 | |||
| 2fef71da5c | |||
| 48c1f5fd27 | |||
| 6e4a526ddf | |||
| d11886e7ac | |||
| 177b19a2da | |||
| f943469fc9 | |||
| 59d062cb3d | |||
| 8032e30a76 | |||
| 2e81e4d452 | |||
| d900407a18 | |||
| 64e5c76323 | |||
| b9651606d3 | |||
| 2a5f6fdde5 | |||
| 6dbbd65ef8 | |||
| 9947760d87 | |||
| 493b83ff24 | |||
| b65f6eef59 | |||
| f6ff0ee18c | |||
| b388c066dc | |||
| 9fe011b98f | |||
| 89ab3a8146 | |||
| 5dcaca9b3c | |||
| 69c8278558 | |||
| 0e9b967bf9 | |||
| 0c32a94d8e | |||
| 6d20f4bc60 | |||
| 8361949ba1 | |||
| 8372bc00bd | |||
| 5cf3c70db0 | |||
| a031011e5e | |||
| bd901896ee | |||
| cb5c994cd9 | |||
| 39a0e27513 | |||
| 832ddb31b7 | |||
| 8bdc7a3289 | |||
| 57521e6242 | |||
| 93d681ae77 | |||
| a9b27a7de0 | |||
| 41d80ac277 | |||
| cf9b8231bd | |||
| 3b6035a46d | |||
| c7a69882d3 | |||
| e5cd813a24 | |||
| 62d917eb08 | |||
| d4c4e4bbc5 | |||
| cfcc9658b2 | |||
| d8a0cd24d7 | |||
| 496ecd68f2 | |||
| 683878c733 | |||
| 38c0e2bdf6 | |||
| f0fc2709d6 | |||
| 1b38cbd410 | |||
| c2ec97e922 | |||
| 90a278ce46 | |||
| 2a5fe8cd0c | |||
| 42d89a0ff1 | |||
| 9f65cdf3aa | |||
| 35bc08da5e | |||
| 723c2493b2 | |||
| 245e51099f | |||
| a06cd6a821 | |||
| 1c509be875 | |||
| 9894417a09 | |||
| 51f218c877 | |||
| a8bb0a0ee1 | |||
| b7414dfbdd | |||
| 057479c284 | |||
| c5a01cd14b | |||
| 719ff9eca9 | |||
| d50e235753 | |||
| ae2020aca2 | |||
| 450524f6cf | |||
| be09cebb09 | |||
| 6230ff0fc4 | |||
| 1733671295 | |||
| 78a7127b96 | |||
| 94063cbe92 | |||
| 96e579501f | |||
| 98c88780bc | |||
| 7dcb7d7d0f | |||
| 95e36af46b | |||
| 47a13e601f | |||
| a301f18ebf | |||
| 6cbf4667a4 | |||
| ef20b706e2 | |||
| 979e4207f3 | |||
| c29237c75d | |||
| 99aa5f398b | |||
| 1858d955de | |||
| 3e5af3afce | |||
| b4a1ed2a70 | |||
| f05a8927f3 | |||
| a2368803fa | |||
| ee93f88268 | |||
| 32d35b1d01 | |||
| 528e246f1a | |||
| 03f820d26c | |||
| bf39fa3b3b | |||
| d2229e2aed | |||
| 9eac147426 | |||
| 1b1abba313 | |||
| 223d1343de | |||
| f0f6af1cf8 | |||
| 82eed5d672 | |||
| 38f64c2357 | |||
| daadaf8448 | |||
| e86fa6a072 | |||
| 1b3eb3ecd1 | |||
| 94539e6f08 | |||
| f5af3fe933 | |||
| bbad290518 | |||
| 334e380d31 | |||
| d8db673fb7 | |||
| 268ad54c6a | |||
| 64a67ac3a8 | |||
| 74ac95dc32 | |||
| 7f817fce0a | |||
| 5549a7ab5f | |||
| 53821da4d6 | |||
| f518d780ed | |||
| 9045431bde | |||
| 8271687ef6 | |||
| 8043d4d6e0 | |||
| e7a59d92ac | |||
| e3bac4063c | |||
| 48012a1ce4 | |||
| 63f6e75b38 | |||
| 23c1ec07e7 | |||
| 7431a58617 | |||
| 30e9d98f0d | |||
| 43d0b0fb3c | |||
| d47c8613b0 | |||
| e01311a565 | |||
| 0876089f8f | |||
| b7a8c2207e | |||
| 5ab8fde0bc | |||
| d1d1af1a62 | |||
| 88618952c5 | |||
| 92d1df94fa | |||
| 187db92a88 | |||
| a9b8551e70 | |||
| 0cac75aff1 | |||
| 6cf3f6ebff | |||
| 3efe1bef93 | |||
| 16c804c5e3 | |||
| 28f4666366 | |||
| 72a5927d38 | |||
| 7473617ffb | |||
| 7d43e4e56a | |||
| 8fd2a267ae | |||
| 3809e6efb9 | |||
| 9224efd95e | |||
| 4cbd384e39 | |||
| 12010a597b | |||
| 720ac700b3 | |||
| 373a6ab9f1 | |||
| 57c1c95e75 | |||
| ffc117564b | |||
| ee3367697d | |||
| c6e19f0384 | |||
| 9df265acdc | |||
| 461d9b4052 | |||
| 0ed45c5f40 | |||
| 73ac2d0a1c | |||
| 57ab670991 | |||
| e2b5e0d17d | |||
| 77e05a4240 | |||
| 97c5bb284b | |||
| 286b473f55 | |||
| 1152c93778 | |||
| 1a85d569e3 | |||
| bd114ab1a8 | |||
| 7a1f764910 | |||
| 10f934f782 | |||
| 97c60b84c8 | |||
| bf89431464 | |||
| 9ddae8aebc | |||
| e3c70645f9 | |||
| 1e54e838e0 | |||
| 40854f2ae9 | |||
| 5e8e877f95 | |||
| 99844c8ccf | |||
| 8418e4276a | |||
| 7693e7133d | |||
| e56f9dbeb8 | |||
| 282d66a604 | |||
| 3f513f3cc7 | |||
| 854910cc17 | |||
| 6bc7ec3d4d | |||
| bda6530fea | |||
| 6227592dfa | |||
| bc066de998 | |||
| 68980a5e3b | |||
| f200e8b132 | |||
| dde2d9b545 | |||
| ac64948efd | |||
| dfe2141227 | |||
| 1e1c973d71 | |||
| b69898228d | |||
| 9c71469c67 | |||
| a8b1c90303 | |||
| 69ffaab09f | |||
| 9730d44252 | |||
| f99e725391 | |||
| 8e4a42a214 | |||
| 603de8361c | |||
| 51fd7cf35a | |||
| ab1fba6fdc | |||
| cfa53de9af | |||
| 3ebbcc981a | |||
| 96a71d515b | |||
| b830ca8fab | |||
| 825c97be6c | |||
| 25f99f35f6 | |||
| b719f3bd60 | |||
| b16d01e018 | |||
| c56360f20b | |||
| 726d5b25e8 | |||
| 681aac7317 | |||
| 2cd550cdbc | |||
| 766048b8e4 | |||
| 63615c05bc | |||
| cdf5d08294 | |||
| 3e4d0b69d4 | |||
| 7742434dde | |||
| f0e6c03d94 | |||
| 09882701c2 | |||
| a19bc6620a | |||
| da5de1ba99 | |||
| e9d2f832a1 | |||
| 4fac0f713a | |||
| fff8198393 | |||
| df2cbb4e9f | |||
| 2990c1d8d8 | |||
| 4b5adcd374 | |||
| 0b861cf159 | |||
| 473881357c |
@@ -19,6 +19,7 @@ flatpak build ${builddir} meson \
|
||||
--buildtype=debugoptimized \
|
||||
-Dx11-backend=true \
|
||||
-Dwayland-backend=true \
|
||||
-Dvulkan=disabled \
|
||||
-Dbuild-tests=false \
|
||||
-Dbuild-testsuite=false \
|
||||
-Dbuild-examples=false \
|
||||
@@ -27,7 +28,7 @@ flatpak build ${builddir} meson \
|
||||
-Ddemo-profile=devel \
|
||||
_flatpak_build
|
||||
|
||||
flatpak build ${builddir} ninja -C _flatpak_build install
|
||||
flatpak build --env=CI_COMMIT_SHORT_SHA=$CI_COMMIT_SHORT_SHA ${builddir} ninja -C _flatpak_build install
|
||||
|
||||
flatpak-builder \
|
||||
--user --disable-rofiles-fuse \
|
||||
|
||||
@@ -6,7 +6,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
|
||||
|
||||
:: FIXME: make warnings fatal
|
||||
pip3 install --upgrade --user meson~=0.64 || goto :error
|
||||
meson setup -Dbackend_max_links=1 -Ddebug=false -Dmedia-gstreamer=disabled _build || goto :error
|
||||
meson setup -Dbackend_max_links=1 -Ddebug=false -Dmedia-gstreamer=disabled -Dvulkan=disabled _build || goto :error
|
||||
ninja -C _build || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
||||
@@ -33,7 +33,8 @@ pacman --noconfirm -S --needed \
|
||||
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \
|
||||
mingw-w64-$MSYS2_ARCH-shared-mime-info \
|
||||
mingw-w64-$MSYS2_ARCH-python-gobject \
|
||||
mingw-w64-$MSYS2_ARCH-shaderc
|
||||
mingw-w64-$MSYS2_ARCH-shaderc \
|
||||
mingw-w64-$MSYS2_ARCH-vulkan
|
||||
|
||||
mkdir -p _ccache
|
||||
export CCACHE_BASEDIR="$(pwd)"
|
||||
@@ -47,7 +48,6 @@ meson \
|
||||
-Dx11-backend=false \
|
||||
-Dwayland-backend=false \
|
||||
-Dwin32-backend=true \
|
||||
-Dvulkan=disabled \
|
||||
-Dintrospection=enabled \
|
||||
-Dgtk:werror=true \
|
||||
_build
|
||||
|
||||
+1
-1
@@ -213,7 +213,7 @@ Closes #1234
|
||||
`git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`.
|
||||
|
||||
- If your commit is addressing an issue, use the
|
||||
[GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html)
|
||||
[GitLab syntax](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
|
||||
to automatically close the issue when merging the commit with the upstream
|
||||
repository:
|
||||
|
||||
|
||||
@@ -1,3 +1,49 @@
|
||||
Overview of Changes in 4.13.6, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
Overview of Changes in 4.13.5, 07-01-2024
|
||||
=========================================
|
||||
|
||||
This release adds two new GSK renderers called vulkan and ngl,
|
||||
that are built from the same sources. The new renderers can
|
||||
handle many corner cases correctly that the current gl renderer
|
||||
does not handle, and they offer advantages such as antialiasing
|
||||
and supersampled gradients.
|
||||
|
||||
The new renderers are still considered experimental, and GTK
|
||||
will only use them if they are explicitly selected using the
|
||||
GSK_RENDERER environment variable.
|
||||
|
||||
As part of this work, the GSK include files have been rearranged.
|
||||
It is no longer necessary to include renderer-specific headers for
|
||||
ngl and vulkan (and doing so will trigger deprecation warnings),
|
||||
and their constructors are always available.
|
||||
|
||||
The previously available experimental GdkVulkanContext APIs and
|
||||
the old Vulkan renderer have been removed.
|
||||
|
||||
Vulkan is now enabled by default, and Linux distributions should
|
||||
build GTK with Vulkan support. This requires the glslc shader
|
||||
compiler as a new dependency.
|
||||
|
||||
Vulkan is now also used for dmabuf support.
|
||||
|
||||
* GtkDropdown:
|
||||
- Fix display of initial selection
|
||||
|
||||
* GtkShortcutsWindow:
|
||||
- Make the window adapt to smaller screen widths
|
||||
|
||||
* GtkTextView:
|
||||
- Fix a possible NULL dereference in history
|
||||
|
||||
* GDK:
|
||||
- Make the png loader safer against overflows
|
||||
|
||||
* GL:
|
||||
- Fix some errors in handling of texture formats and mipmaps
|
||||
|
||||
|
||||
Overview of Changes in 4.13.4, 30-12-2023
|
||||
=========================================
|
||||
|
||||
@@ -476,7 +522,7 @@ Overview of Changes in 4.11.4, 03-07-2023
|
||||
- Center newly created transient windows
|
||||
|
||||
* Vulkan:
|
||||
- Add antialising for gradients
|
||||
- Add antialiasing for gradients
|
||||
- Do less work on clipped away nodes
|
||||
- Redo image uploading
|
||||
- Support different image depths and formats
|
||||
@@ -1460,7 +1506,7 @@ Overview of Changes in 4.7.0, 07-05-2022
|
||||
- Event handling fixes
|
||||
- Fix keyboard input on popovers
|
||||
- Support OpenGL-based video playback
|
||||
- Suport fullscreen
|
||||
- Support fullscreen
|
||||
- Improve native filechoooser size allocation
|
||||
- Use CALayer and IOSurface for rendering
|
||||
- Use a per-monitor CVDisplayLink
|
||||
@@ -1857,7 +1903,7 @@ Overview of Changes in 4.4.0
|
||||
- Activate when moving focus
|
||||
|
||||
* GtkLabel:
|
||||
- Propertly ignore double underscores for mnemonics
|
||||
- Properly ignore double underscores for mnemonics
|
||||
|
||||
* GtkPopoverMenu:
|
||||
- Fix focus cycling
|
||||
@@ -2404,7 +2450,7 @@ Overview of Changes in 4.1.0
|
||||
- Set sort arrows in CSS
|
||||
- Set menu button arrows in CSS
|
||||
- Make scrollbars larger
|
||||
- Supprt circular menubuttons
|
||||
- Support circular menubuttons
|
||||
|
||||
* CSS:
|
||||
- Implement transform-origin
|
||||
|
||||
@@ -1586,7 +1586,7 @@ update_font_variations (void)
|
||||
}
|
||||
|
||||
gtk_grid_attach (GTK_GRID (demo->variations_grid), combo, 1, -1, 3, 1);
|
||||
g_signal_connect (combo, "notify::selecte", G_CALLBACK (instance_changed), NULL);
|
||||
g_signal_connect (combo, "notify::selected", G_CALLBACK (instance_changed), NULL);
|
||||
demo->instance_combo = combo;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "demos.h"
|
||||
#include "fontify.h"
|
||||
|
||||
#include "demo_conf.h"
|
||||
#include "profile_conf.h"
|
||||
|
||||
static GtkWidget *info_view;
|
||||
static GtkWidget *source_view;
|
||||
|
||||
@@ -236,7 +236,7 @@ foreach flag: common_cflags
|
||||
endif
|
||||
endforeach
|
||||
|
||||
gtkdemo_deps += [ demo_conf_h ]
|
||||
gtkdemo_deps += [ profile_conf_h ]
|
||||
|
||||
executable('gtk4-demo',
|
||||
sources: [demos, demos_h, extra_demo_sources, gtkdemo_resources],
|
||||
|
||||
+23
-16
@@ -53,7 +53,9 @@ gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
double rotation)
|
||||
{
|
||||
#define RADIUS 0.3
|
||||
cairo_t *cr;
|
||||
GskPathBuilder *builder;
|
||||
GskPath *path;
|
||||
GskStroke *stroke;
|
||||
double size;
|
||||
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
@@ -61,24 +63,29 @@ gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
size = MIN (width, height);
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT ((width - size) / 2.0,
|
||||
(height - size) / 2.0,
|
||||
size, size));
|
||||
gdk_cairo_set_source_rgba (cr, foreground);
|
||||
cairo_translate (cr, width / 2.0, height / 2.0);
|
||||
cairo_scale (cr, size, size);
|
||||
cairo_rotate (cr, rotation);
|
||||
|
||||
cairo_arc (cr, 0, 0, 0.1, - G_PI, G_PI);
|
||||
cairo_fill (cr);
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
cairo_set_line_width (cr, RADIUS);
|
||||
cairo_set_dash (cr, (double[1]) { RADIUS * G_PI / 3 }, 1, 0.0);
|
||||
cairo_arc (cr, 0, 0, RADIUS, - G_PI, G_PI);
|
||||
cairo_stroke (cr);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2.0, height / 2.0));
|
||||
gtk_snapshot_scale (snapshot, size, size);
|
||||
gtk_snapshot_rotate (snapshot, rotation);
|
||||
|
||||
cairo_destroy (cr);
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_circle (builder, graphene_point_zero (), 0.1);
|
||||
path = gsk_path_builder_free_to_path (builder);
|
||||
gtk_snapshot_append_fill (snapshot, path, GSK_FILL_RULE_WINDING, foreground);
|
||||
gsk_path_unref (path);
|
||||
|
||||
stroke = gsk_stroke_new (RADIUS);
|
||||
gsk_stroke_set_dash (stroke, (float[1]) { RADIUS * G_PI / 3 }, 1);
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_circle (builder, graphene_point_zero(), RADIUS);
|
||||
path = gsk_path_builder_free_to_path (builder);
|
||||
gtk_snapshot_append_stroke (snapshot, path, stroke, foreground);
|
||||
gsk_path_unref (path);
|
||||
gsk_stroke_free (stroke);
|
||||
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
|
||||
/* Here, we implement the functionality required by the GdkPaintable interface */
|
||||
|
||||
@@ -70,7 +70,7 @@ gtk_nuclear_animation_snapshot (GdkPaintable *paintable,
|
||||
? &(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 } /* yellow */
|
||||
: &(GdkRGBA) { 0, 0, 0, 0 }, /* transparent */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS);
|
||||
360 * nuclear->progress / MAX_PROGRESS);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
@@ -85,7 +85,7 @@ gtk_nuclear_animation_get_current_image (GdkPaintable *paintable)
|
||||
* Luckily we added the rotation property to the nuclear icon
|
||||
* object previously, so we can just return an instance of that one.
|
||||
*/
|
||||
return gtk_nuclear_icon_new (2 * G_PI * nuclear->progress / MAX_PROGRESS);
|
||||
return gtk_nuclear_icon_new (360 * nuclear->progress / MAX_PROGRESS);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
|
||||
@@ -76,7 +76,7 @@ gtk_nuclear_media_stream_snapshot (GdkPaintable *paintable,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / DURATION);
|
||||
360 * nuclear->progress / DURATION);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
@@ -85,7 +85,7 @@ gtk_nuclear_media_stream_get_current_image (GdkPaintable *paintable)
|
||||
GtkNuclearMediaStream *nuclear = GTK_NUCLEAR_MEDIA_STREAM (paintable);
|
||||
|
||||
/* Same thing as with the animation */
|
||||
return gtk_nuclear_icon_new (2 * G_PI * nuclear->progress / DURATION);
|
||||
return gtk_nuclear_icon_new (360 * nuclear->progress / DURATION);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "iconbrowserapp.h"
|
||||
#include "iconbrowserwin.h"
|
||||
|
||||
#include "demo_conf.h"
|
||||
#include "profile_conf.h"
|
||||
|
||||
struct _IconBrowserApp
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ iconbrowser_resources = gnome.compile_resources('iconbrowser_resources',
|
||||
executable('gtk4-icon-browser',
|
||||
sources: [iconbrowser_sources, iconbrowser_resources],
|
||||
c_args: common_cflags,
|
||||
dependencies: [ libgtk_dep, demo_conf_h ],
|
||||
dependencies: [ libgtk_dep, profile_conf_h ],
|
||||
include_directories: confinc,
|
||||
win_subsystem: 'windows',
|
||||
link_args: extra_demo_ldflags,
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
gen_demo_header = find_program('../build-aux/meson/gen-demo-header.py')
|
||||
demo_profile = get_option('demo-profile')
|
||||
|
||||
demo_conf_h = declare_dependency(
|
||||
sources: custom_target('demo-header',
|
||||
command: [gen_demo_header, meson.project_source_root(), demo_profile],
|
||||
capture: true,
|
||||
output: 'demo_conf.h',
|
||||
build_by_default: true,
|
||||
build_always_stale: true,
|
||||
)
|
||||
)
|
||||
|
||||
# appdata
|
||||
|
||||
appdata_config = configuration_data()
|
||||
|
||||
@@ -12,7 +12,7 @@ node_editor_resources = gnome.compile_resources('node_editor_resources',
|
||||
|
||||
executable('gtk4-node-editor',
|
||||
sources: [node_editor_sources, node_editor_resources],
|
||||
dependencies: [ libgtk_dep, demo_conf_h ],
|
||||
dependencies: [ libgtk_dep, profile_conf_h ],
|
||||
include_directories: confinc,
|
||||
c_args: common_cflags,
|
||||
win_subsystem: 'windows',
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "node-editor-application.h"
|
||||
|
||||
#include "node-editor-window.h"
|
||||
|
||||
#include "demo_conf.h"
|
||||
#include "profile_conf.h"
|
||||
|
||||
static const char *css =
|
||||
"textview.editor {"
|
||||
@@ -247,11 +249,63 @@ node_editor_application_class_init (NodeEditorApplicationClass *class)
|
||||
application_class->open = node_editor_application_open;
|
||||
}
|
||||
|
||||
static void
|
||||
print_version (void)
|
||||
{
|
||||
g_print ("gtk4-node-editor %s%s%s\n",
|
||||
PACKAGE_VERSION,
|
||||
g_strcmp0 (PROFILE, "devel") == 0 ? "-" : "",
|
||||
g_strcmp0 (PROFILE, "devel") == 0 ? VCS_TAG : "");
|
||||
}
|
||||
|
||||
static int
|
||||
local_options (GApplication *app,
|
||||
GVariantDict *options,
|
||||
gpointer data)
|
||||
{
|
||||
gboolean version = FALSE;
|
||||
gboolean reset = FALSE;
|
||||
|
||||
g_variant_dict_lookup (options, "version", "b", &version);
|
||||
|
||||
if (version)
|
||||
{
|
||||
print_version ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_variant_dict_lookup (options, "reset", "b", &reset);
|
||||
|
||||
if (reset)
|
||||
{
|
||||
char *path;
|
||||
|
||||
path = get_autosave_path ("-unsafe");
|
||||
g_remove (path);
|
||||
g_free (path);
|
||||
path = get_autosave_path (NULL);
|
||||
g_remove (path);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
NodeEditorApplication *
|
||||
node_editor_application_new (void)
|
||||
{
|
||||
return g_object_new (NODE_EDITOR_APPLICATION_TYPE,
|
||||
"application-id", "org.gtk.gtk4.NodeEditor",
|
||||
"flags", G_APPLICATION_HANDLES_OPEN,
|
||||
NULL);
|
||||
NodeEditorApplication *app;
|
||||
|
||||
app = g_object_new (NODE_EDITOR_APPLICATION_TYPE,
|
||||
"application-id", "org.gtk.gtk4.NodeEditor",
|
||||
"flags", G_APPLICATION_HANDLES_OPEN,
|
||||
NULL);
|
||||
|
||||
g_application_add_main_option (G_APPLICATION (app), "version", 0, 0,G_OPTION_ARG_NONE, "Show program version", NULL);
|
||||
g_application_add_main_option (G_APPLICATION (app), "reset", 0, 0,G_OPTION_ARG_NONE, "Remove autosave content", NULL);
|
||||
|
||||
g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,11 @@
|
||||
#include "gtkrendererpaintableprivate.h"
|
||||
|
||||
#include "gsk/gskrendernodeparserprivate.h"
|
||||
#include "gsk/gl/gskglrenderer.h"
|
||||
#ifdef GDK_WINDOWING_BROADWAY
|
||||
#include "gsk/broadway/gskbroadwayrenderer.h"
|
||||
#endif
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include "gsk/vulkan/gskvulkanrenderer.h"
|
||||
#endif
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include <cairo.h>
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
@@ -59,6 +57,7 @@ struct _NodeEditorWindow
|
||||
GtkWidget *testcase_name_entry;
|
||||
GtkWidget *testcase_save_button;
|
||||
GtkWidget *scale_scale;
|
||||
GtkWidget *crash_warning;
|
||||
|
||||
GtkWidget *renderer_listbox;
|
||||
GListStore *renderers;
|
||||
@@ -68,6 +67,9 @@ struct _NodeEditorWindow
|
||||
GFileMonitor *file_monitor;
|
||||
|
||||
GArray *errors;
|
||||
|
||||
guint update_timeout;
|
||||
gboolean auto_reload;
|
||||
};
|
||||
|
||||
struct _NodeEditorWindowClass
|
||||
@@ -75,6 +77,13 @@ struct _NodeEditorWindowClass
|
||||
GtkApplicationWindowClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_AUTO_RELOAD = 1,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
G_DEFINE_TYPE(NodeEditorWindow, node_editor_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||
|
||||
static void
|
||||
@@ -167,19 +176,84 @@ text_iter_skip_whitespace_backward (GtkTextIter *iter)
|
||||
}
|
||||
|
||||
static void
|
||||
text_changed (GtkTextBuffer *buffer,
|
||||
NodeEditorWindow *self)
|
||||
highlight_text (NodeEditorWindow *self)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextIter start, end;
|
||||
|
||||
gtk_text_buffer_get_start_iter (self->text_buffer, &iter);
|
||||
|
||||
while (!gtk_text_iter_is_end (&iter))
|
||||
{
|
||||
gunichar c = gtk_text_iter_get_char (&iter);
|
||||
|
||||
if (c == '{')
|
||||
{
|
||||
GtkTextIter word_end = iter;
|
||||
GtkTextIter word_start;
|
||||
|
||||
gtk_text_iter_backward_char (&word_end);
|
||||
text_iter_skip_whitespace_backward (&word_end);
|
||||
|
||||
word_start = word_end;
|
||||
gtk_text_iter_backward_word_start (&word_start);
|
||||
text_iter_skip_alpha_backward (&word_start);
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "nodename", &word_start, &word_end);
|
||||
}
|
||||
else if (c == ':')
|
||||
{
|
||||
GtkTextIter word_end = iter;
|
||||
GtkTextIter word_start;
|
||||
|
||||
gtk_text_iter_backward_char (&word_end);
|
||||
text_iter_skip_whitespace_backward (&word_end);
|
||||
|
||||
word_start = word_end;
|
||||
gtk_text_iter_backward_word_start (&word_start);
|
||||
text_iter_skip_alpha_backward (&word_start);
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "propname", &word_start, &word_end);
|
||||
}
|
||||
else if (c == '"')
|
||||
{
|
||||
GtkTextIter string_start = iter;
|
||||
GtkTextIter string_end = iter;
|
||||
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
while (!gtk_text_iter_is_end (&iter))
|
||||
{
|
||||
c = gtk_text_iter_get_char (&iter);
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
string_end = iter;
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
}
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "string", &string_start, &string_end);
|
||||
}
|
||||
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
}
|
||||
|
||||
gtk_text_buffer_get_bounds (self->text_buffer, &start, &end);
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "no-hyphens", &start, &end);
|
||||
}
|
||||
|
||||
static void
|
||||
reload (NodeEditorWindow *self)
|
||||
{
|
||||
char *text;
|
||||
GBytes *bytes;
|
||||
GtkTextIter iter;
|
||||
GtkTextIter start, end;
|
||||
float scale;
|
||||
GskRenderNode *big_node;
|
||||
|
||||
g_array_remove_range (self->errors, 0, self->errors->len);
|
||||
text = get_current_text (self->text_buffer);
|
||||
text_buffer_remove_all_tags (self->text_buffer);
|
||||
bytes = g_bytes_new_take (text, strlen (text));
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
@@ -240,73 +314,19 @@ text_changed (GtkTextBuffer *buffer,
|
||||
}
|
||||
|
||||
g_clear_pointer (&big_node, gsk_render_node_unref);
|
||||
}
|
||||
|
||||
gtk_text_buffer_get_start_iter (self->text_buffer, &iter);
|
||||
static void
|
||||
text_changed (GtkTextBuffer *buffer,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
g_array_remove_range (self->errors, 0, self->errors->len);
|
||||
text_buffer_remove_all_tags (self->text_buffer);
|
||||
|
||||
while (!gtk_text_iter_is_end (&iter))
|
||||
{
|
||||
gunichar c = gtk_text_iter_get_char (&iter);
|
||||
if (self->auto_reload)
|
||||
reload (self);
|
||||
|
||||
if (c == '{')
|
||||
{
|
||||
GtkTextIter word_end = iter;
|
||||
GtkTextIter word_start;
|
||||
|
||||
gtk_text_iter_backward_char (&word_end);
|
||||
text_iter_skip_whitespace_backward (&word_end);
|
||||
|
||||
word_start = word_end;
|
||||
gtk_text_iter_backward_word_start (&word_start);
|
||||
text_iter_skip_alpha_backward (&word_start);
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "nodename",
|
||||
&word_start, &word_end);
|
||||
}
|
||||
else if (c == ':')
|
||||
{
|
||||
GtkTextIter word_end = iter;
|
||||
GtkTextIter word_start;
|
||||
|
||||
gtk_text_iter_backward_char (&word_end);
|
||||
text_iter_skip_whitespace_backward (&word_end);
|
||||
|
||||
word_start = word_end;
|
||||
gtk_text_iter_backward_word_start (&word_start);
|
||||
text_iter_skip_alpha_backward (&word_start);
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "propname",
|
||||
&word_start, &word_end);
|
||||
}
|
||||
else if (c == '"')
|
||||
{
|
||||
GtkTextIter string_start = iter;
|
||||
GtkTextIter string_end = iter;
|
||||
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
while (!gtk_text_iter_is_end (&iter))
|
||||
{
|
||||
c = gtk_text_iter_get_char (&iter);
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
string_end = iter;
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
}
|
||||
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "string",
|
||||
&string_start, &string_end);
|
||||
}
|
||||
|
||||
gtk_text_iter_forward_char (&iter);
|
||||
}
|
||||
|
||||
gtk_text_buffer_get_bounds (self->text_buffer, &start, &end);
|
||||
gtk_text_buffer_apply_tag_by_name (self->text_buffer, "no-hyphens",
|
||||
&start, &end);
|
||||
highlight_text (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -794,7 +814,7 @@ create_cairo_texture (NodeEditorWindow *self)
|
||||
return NULL;
|
||||
|
||||
renderer = gsk_cairo_renderer_new ();
|
||||
gsk_renderer_realize (renderer, NULL, NULL);
|
||||
gsk_renderer_realize_for_display (renderer, gtk_widget_get_display (GTK_WIDGET (self)), NULL);
|
||||
|
||||
texture = gsk_renderer_render_texture (renderer, node, NULL);
|
||||
gsk_render_node_unref (node);
|
||||
@@ -866,11 +886,11 @@ export_image_response_cb (GObject *source,
|
||||
GskRenderer *renderer;
|
||||
|
||||
renderer = gsk_gl_renderer_new ();
|
||||
if (!gsk_renderer_realize (renderer, NULL, NULL))
|
||||
if (!gsk_renderer_realize_for_display (renderer, gdk_display_get_default (), NULL))
|
||||
{
|
||||
g_object_unref (renderer);
|
||||
renderer = gsk_cairo_renderer_new ();
|
||||
if (!gsk_renderer_realize (renderer, NULL, NULL))
|
||||
if (!gsk_renderer_realize_for_display (renderer, gdk_display_get_default (), NULL))
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
@@ -1105,6 +1125,9 @@ node_editor_window_finalize (GObject *object)
|
||||
{
|
||||
NodeEditorWindow *self = (NodeEditorWindow *)object;
|
||||
|
||||
if (self->update_timeout)
|
||||
g_source_remove (self->update_timeout);
|
||||
|
||||
g_array_free (self->errors, TRUE);
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
@@ -1121,8 +1144,11 @@ node_editor_window_add_renderer (NodeEditorWindow *self,
|
||||
const char *description)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
GdkDisplay *display;
|
||||
|
||||
if (!gsk_renderer_realize (renderer, NULL, NULL))
|
||||
display = gtk_widget_get_display (GTK_WIDGET (self));
|
||||
|
||||
if (!gsk_renderer_realize_for_display (renderer, display, NULL))
|
||||
{
|
||||
GdkSurface *surface = gtk_native_get_surface (GTK_NATIVE (self));
|
||||
g_assert (surface != NULL);
|
||||
@@ -1157,6 +1183,9 @@ node_editor_window_realize (GtkWidget *widget)
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_gl_renderer_new (),
|
||||
"OpenGL");
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_ngl_renderer_new (),
|
||||
"NGL");
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_vulkan_renderer_new (),
|
||||
@@ -1538,6 +1567,79 @@ edit_action_cb (GtkWidget *widget,
|
||||
node_editor_window_edit (self, &start);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_map (GtkWidget *widget)
|
||||
{
|
||||
char *path;
|
||||
|
||||
GTK_WIDGET_CLASS (node_editor_window_parent_class)->map (widget);
|
||||
|
||||
path = get_autosave_path (NULL);
|
||||
if (g_file_test (path, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
g_free (path);
|
||||
return;
|
||||
}
|
||||
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NodeEditorWindow *self = NODE_EDITOR_WINDOW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_AUTO_RELOAD:
|
||||
{
|
||||
gboolean auto_reload = g_value_get_boolean (value);
|
||||
if (self->auto_reload != auto_reload)
|
||||
{
|
||||
self->auto_reload = auto_reload;
|
||||
|
||||
if (self->auto_reload)
|
||||
reload (self);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
NodeEditorWindow *self = NODE_EDITOR_WINDOW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_AUTO_RELOAD:
|
||||
g_value_set_boolean (value, self->auto_reload);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
close_crash_warning (GtkButton *button,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->crash_warning), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
{
|
||||
@@ -1549,6 +1651,8 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
|
||||
object_class->dispose = node_editor_window_dispose;
|
||||
object_class->finalize = node_editor_window_finalize;
|
||||
object_class->set_property = node_editor_window_set_property;
|
||||
object_class->get_property = node_editor_window_get_property;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class,
|
||||
"/org/gtk/gtk4/node-editor/node-editor-window.ui");
|
||||
@@ -1556,6 +1660,14 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
widget_class->realize = node_editor_window_realize;
|
||||
widget_class->unrealize = node_editor_window_unrealize;
|
||||
|
||||
widget_class->map = node_editor_window_map;
|
||||
|
||||
properties[PROP_AUTO_RELOAD] = g_param_spec_boolean ("auto-reload", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME);
|
||||
|
||||
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
|
||||
|
||||
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, text_view);
|
||||
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, picture);
|
||||
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, renderer_listbox);
|
||||
@@ -1565,6 +1677,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_name_entry);
|
||||
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, testcase_save_button);
|
||||
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, scale_scale);
|
||||
gtk_widget_class_bind_template_child (widget_class, NodeEditorWindow, crash_warning);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, text_view_query_tooltip_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, open_cb);
|
||||
@@ -1577,6 +1690,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, click_gesture_pressed);
|
||||
gtk_widget_class_bind_template_callback (widget_class, close_crash_warning);
|
||||
|
||||
gtk_widget_class_install_action (widget_class, "smart-edit", NULL, edit_action_cb);
|
||||
|
||||
@@ -1628,11 +1742,133 @@ static GActionEntry win_entries[] = {
|
||||
{ "open", window_open, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
char *
|
||||
get_autosave_path (const char *suffix)
|
||||
{
|
||||
char *path;
|
||||
char *name;
|
||||
|
||||
name = g_strconcat ("autosave", suffix, NULL);
|
||||
path = g_build_filename (g_get_user_cache_dir (), "gtk4-node-editor", name, NULL);
|
||||
g_free (name);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static void
|
||||
set_initial_text (NodeEditorWindow *self)
|
||||
{
|
||||
char *path, *path1;
|
||||
char *initial_text;
|
||||
gsize len;
|
||||
|
||||
path = get_autosave_path (NULL);
|
||||
path1 = get_autosave_path ("-unsafe");
|
||||
|
||||
if (g_file_get_contents (path, &initial_text, &len, NULL))
|
||||
{
|
||||
gtk_text_buffer_set_text (self->text_buffer, initial_text, len);
|
||||
g_free (initial_text);
|
||||
}
|
||||
else if (g_file_get_contents (path1, &initial_text, &len, NULL))
|
||||
{
|
||||
self->auto_reload = FALSE;
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (self->crash_warning), TRUE);
|
||||
|
||||
gtk_text_buffer_set_text (self->text_buffer, initial_text, len);
|
||||
g_free (initial_text);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Default */
|
||||
gtk_text_buffer_set_text (self->text_buffer,
|
||||
"shadow {\n"
|
||||
" child: texture {\n"
|
||||
" bounds: 0 0 128 128;\n"
|
||||
" texture: url(\"resource:///org/gtk/gtk4/node-editor/icons/apps/org.gtk.gtk4.NodeEditor.svg\");\n"
|
||||
" }\n"
|
||||
" shadows: rgba(0,0,0,0.5) 0 1 12;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"transform {\n"
|
||||
" child: text {\n"
|
||||
" color: rgb(46,52,54);\n"
|
||||
" font: \"Cantarell Bold 11\";\n"
|
||||
" glyphs: \"GTK Node Editor\";\n"
|
||||
" offset: 8 14.418;\n"
|
||||
" }\n"
|
||||
" transform: translate(0, 140);\n"
|
||||
"}", -1);
|
||||
}
|
||||
|
||||
g_free (path);
|
||||
g_free (path1);
|
||||
}
|
||||
|
||||
static void
|
||||
autosave_contents (NodeEditorWindow *self)
|
||||
{
|
||||
char *path = NULL;
|
||||
char *dir = NULL;
|
||||
char *contents;
|
||||
GtkTextIter start, end;
|
||||
|
||||
gtk_text_buffer_get_bounds (self->text_buffer, &start, &end);
|
||||
contents = gtk_text_buffer_get_text (self->text_buffer, &start, &end, TRUE);
|
||||
path = get_autosave_path ("-unsafe");
|
||||
dir = g_path_get_dirname (path);
|
||||
g_mkdir_with_parents (dir, 0755);
|
||||
g_file_set_contents (path, contents, -1, NULL);
|
||||
|
||||
g_free (dir);
|
||||
g_free (path);
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
static void
|
||||
mark_autosave_as_safe (void)
|
||||
{
|
||||
char *path1 = NULL;
|
||||
char *path2 = NULL;
|
||||
|
||||
path1 = get_autosave_path ("-unsafe");
|
||||
path2 = get_autosave_path (NULL);
|
||||
|
||||
g_rename (path1, path2);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_timeout_cb (gpointer data)
|
||||
{
|
||||
NodeEditorWindow *self = data;
|
||||
|
||||
self->update_timeout = 0;
|
||||
|
||||
mark_autosave_as_safe ();
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
initiate_autosave (NodeEditorWindow *self)
|
||||
{
|
||||
autosave_contents (self);
|
||||
|
||||
if (self->update_timeout != 0)
|
||||
g_source_remove (self->update_timeout);
|
||||
|
||||
self->update_timeout = g_timeout_add (100, update_timeout_cb, self);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_init (NodeEditorWindow *self)
|
||||
{
|
||||
GAction *action;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
self->auto_reload = TRUE;
|
||||
|
||||
self->renderers = g_list_store_new (GDK_TYPE_PAINTABLE);
|
||||
gtk_list_box_bind_model (GTK_LIST_BOX (self->renderer_listbox),
|
||||
G_LIST_MODEL (self->renderers),
|
||||
@@ -1645,6 +1881,10 @@ node_editor_window_init (NodeEditorWindow *self)
|
||||
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (self), win_entries, G_N_ELEMENTS (win_entries), self);
|
||||
|
||||
action = G_ACTION (g_property_action_new ("auto-reload", self, "auto-reload"));
|
||||
g_action_map_add_action (G_ACTION_MAP (self), action);
|
||||
g_object_unref (action);
|
||||
|
||||
self->tag_table = gtk_text_tag_table_new ();
|
||||
gtk_text_tag_table_add (self->tag_table,
|
||||
g_object_new (GTK_TYPE_TEXT_TAG,
|
||||
@@ -1682,25 +1922,9 @@ node_editor_window_init (NodeEditorWindow *self)
|
||||
g_signal_connect (self->scale_scale, "notify::value", G_CALLBACK (scale_changed), self);
|
||||
gtk_text_view_set_buffer (GTK_TEXT_VIEW (self->text_view), self->text_buffer);
|
||||
|
||||
/* Default */
|
||||
gtk_text_buffer_set_text (self->text_buffer,
|
||||
"shadow {\n"
|
||||
" child: texture {\n"
|
||||
" bounds: 0 0 128 128;\n"
|
||||
" texture: url(\"resource:///org/gtk/gtk4/node-editor/icons/apps/org.gtk.gtk4.NodeEditor.svg\");\n"
|
||||
" }\n"
|
||||
" shadows: rgba(0,0,0,0.5) 0 1 12;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"transform {\n"
|
||||
" child: text {\n"
|
||||
" color: rgb(46,52,54);\n"
|
||||
" font: \"Cantarell Bold 11\";\n"
|
||||
" glyphs: \"GTK Node Editor\";\n"
|
||||
" offset: 8 14.418;\n"
|
||||
" }\n"
|
||||
" transform: translate(0, 140);\n"
|
||||
"}", -1);
|
||||
set_initial_text (self);
|
||||
|
||||
g_signal_connect_swapped (self->text_buffer, "changed", G_CALLBACK (initiate_autosave), self);
|
||||
|
||||
if (g_getenv ("GSK_RENDERER"))
|
||||
{
|
||||
|
||||
@@ -37,3 +37,5 @@ NodeEditorWindow * node_editor_window_new (NodeEditorApplication
|
||||
|
||||
gboolean node_editor_window_load (NodeEditorWindow *self,
|
||||
GFile *file);
|
||||
|
||||
char * get_autosave_path (const char *suffix);
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
<interface>
|
||||
<menu id="gear_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Reload automatically</attribute>
|
||||
<attribute name="action">win.auto-reload</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<attribute name="action">app.help</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<attribute name="action">app.help</attribute>
|
||||
@@ -24,7 +32,6 @@
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
|
||||
<object class="GtkPopover" id="testcase_popover">
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
@@ -39,7 +46,7 @@
|
||||
<object class="GtkEntry" id="testcase_name_entry">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="activates-default">1</property>
|
||||
<signal name="notify::text" handler="testcase_name_entry_changed_cb" />
|
||||
<signal name="notify::text" handler="testcase_name_entry_changed_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -52,7 +59,6 @@
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="wrap">1</property>
|
||||
@@ -66,7 +72,6 @@
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkLabel" id="testcase_error_label">
|
||||
<property name="wrap">1</property>
|
||||
@@ -78,7 +83,6 @@
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkButton" id="testcase_save_button">
|
||||
<property name="label">Save</property>
|
||||
@@ -86,9 +90,9 @@
|
||||
<property name="halign">end</property>
|
||||
<property name="receives-default">1</property>
|
||||
<property name="sensitive">0</property>
|
||||
<signal name="clicked" handler="testcase_save_clicked_cb" />
|
||||
<signal name="clicked" handler="testcase_save_clicked_cb"/>
|
||||
<style>
|
||||
<class name="suggested-action" />
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="row">4</property>
|
||||
@@ -100,7 +104,6 @@
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
<template class="NodeEditorWindow" parent="GtkApplicationWindow">
|
||||
<property name="title" translatable="yes">GTK Node Editor</property>
|
||||
<property name="default-width">1024</property>
|
||||
@@ -185,83 +188,128 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<property name="shrink-start-child">false</property>
|
||||
<property name="shrink-end-child">false</property>
|
||||
<property name="position">400</property>
|
||||
<property name="start-child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="text_view">
|
||||
<property name="wrap-mode">word</property>
|
||||
<property name="monospace">1</property>
|
||||
<property name="top-margin">6</property>
|
||||
<property name="left-margin">6</property>
|
||||
<property name="right-margin">6</property>
|
||||
<property name="bottom-margin">6</property>
|
||||
<property name="has-tooltip">1</property>
|
||||
<property name="extra-menu">extra_menu</property>
|
||||
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
|
||||
<object class="GtkOverlay">
|
||||
<child type="overlay">
|
||||
<object class="GtkRevealer" id="crash_warning">
|
||||
<property name="transition-type">slide-down</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="child">
|
||||
<object class="GtkFrame">
|
||||
<style>
|
||||
<class name="editor" />
|
||||
<class name="app-notification"/>
|
||||
</style>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">20</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="halign">1</property>
|
||||
<property name="label" translatable="1">The application may have crashed.
|
||||
As a precaution, auto-loading has been turned off.
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="valign">3</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="label" translatable="1">_Close</property>
|
||||
<signal name="clicked" handler="close_crash_warning"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<property name="child">
|
||||
<object class="GtkPaned">
|
||||
<property name="shrink-start-child">false</property>
|
||||
<property name="shrink-end-child">false</property>
|
||||
<property name="position">400</property>
|
||||
<property name="start-child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<property name="button">1</property>
|
||||
<signal name="pressed" handler="click_gesture_pressed"/>
|
||||
<object class="GtkTextView" id="text_view">
|
||||
<property name="wrap-mode">word</property>
|
||||
<property name="monospace">1</property>
|
||||
<property name="top-margin">6</property>
|
||||
<property name="left-margin">6</property>
|
||||
<property name="right-margin">6</property>
|
||||
<property name="bottom-margin">6</property>
|
||||
<property name="has-tooltip">1</property>
|
||||
<property name="extra-menu">extra_menu</property>
|
||||
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
|
||||
<style>
|
||||
<class name="editor"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<property name="button">1</property>
|
||||
<signal name="pressed" handler="click_gesture_pressed"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="end-child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="min-content-height">100</property>
|
||||
<property name="min-content-width">100</property>
|
||||
</property>
|
||||
<property name="end-child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="min-content-height">100</property>
|
||||
<property name="min-content-width">100</property>
|
||||
<child>
|
||||
<object class="GtkPicture" id="picture">
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<object class="GtkViewport">
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<object class="GtkPicture" id="picture">
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTargetAsync">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
|
||||
<property name="formats">application/x-gtk-render-node</property>
|
||||
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<child>
|
||||
<object class="GtkDropTargetAsync">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">application/x-gtk-render-node</property>
|
||||
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
|
||||
<object class="GtkListBox" id="renderer_listbox">
|
||||
<property name="selection-mode">none</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="renderer_listbox">
|
||||
<property name="selection-mode">none</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
@@ -322,27 +322,39 @@ stroke bounds of the path.
|
||||
|
||||
### text
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| color | `<color>` | black | non-default |
|
||||
| font | `<string>` | "Cantarell 11" | always |
|
||||
| glyphs | `<glyphs>` | "Hello" | always |
|
||||
| offset | `<point>` | 0 0 | non-default |
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ------------------- | ------------------- | ----------- |
|
||||
| color | `<color>` | black | non-default |
|
||||
| font | `<string>` `<url>`? | "Cantarell 11" | always |
|
||||
| glyphs | `<glyphs>` | "Hello" | always |
|
||||
| offset | `<point>` | 0 0 | non-default |
|
||||
|
||||
Creates a node like `gsk_text_node_new()` with the given properties.
|
||||
|
||||
If a url is specified for the font, it must point to a font file for the
|
||||
font that is specified in the string. It can be either a data url containing
|
||||
a base64-encoded font file, or a regular url that points to a font file.
|
||||
|
||||
Glyphs can be specified as an ASCII string, or as a comma-separated list of
|
||||
their glyph ID and advance width. Optionally, x and y offsets and flags can
|
||||
be specified as well, like this: 40 10 0 0 color.
|
||||
|
||||
If the given font does not exist or the given glyphs are invalid for the given
|
||||
font, an error node will be returned.
|
||||
|
||||
### texture
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| texture | `<url>` | *see below* | always |
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ------------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| texture | `<string>`?`<url>`? | *see below* | always |
|
||||
|
||||
Creates a node like `gsk_texture_node_new()` with the given properties.
|
||||
|
||||
If a string is specified for the texture, it will be used as a name for the text.
|
||||
Textures can be reused by specifying the name of a previously used texture. In
|
||||
that case, the url can be omitted.
|
||||
|
||||
The default texture is a 10x10 checkerboard with the top left and bottom right
|
||||
5x5 being in the color #FF00CC and the other part being transparent. A possible
|
||||
representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQXY0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
executable('gtk4-print-editor',
|
||||
sources: ['print-editor.c'],
|
||||
c_args: common_cflags,
|
||||
dependencies: [ libgtk_dep, demo_conf_h ],
|
||||
dependencies: [ libgtk_dep, profile_conf_h ],
|
||||
include_directories: confinc,
|
||||
win_subsystem: 'windows',
|
||||
link_args: extra_demo_ldflags,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "demo_conf.h"
|
||||
#include "profile_conf.h"
|
||||
|
||||
static GtkWidget *main_window;
|
||||
static GFile *filename = NULL;
|
||||
|
||||
@@ -66,7 +66,7 @@ endif
|
||||
executable('gtk4-widget-factory',
|
||||
sources: ['widget-factory.c', widgetfactory_resources],
|
||||
c_args: common_cflags,
|
||||
dependencies: [ libgtk_dep, demo_conf_h ],
|
||||
dependencies: [ libgtk_dep, profile_conf_h ],
|
||||
include_directories: confinc,
|
||||
win_subsystem: 'windows',
|
||||
link_args: extra_demo_ldflags,
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "demo_conf.h"
|
||||
#include "profile_conf.h"
|
||||
|
||||
static void
|
||||
change_dark_state (GSimpleAction *action,
|
||||
|
||||
@@ -75,7 +75,7 @@ define colors. Color expressions resemble functions, taking 1 or more colors
|
||||
and in some cases a number as arguments.
|
||||
|
||||
`lighter(Color)`
|
||||
: produces a brigher variant of Color
|
||||
: produces a brighter variant of Color
|
||||
|
||||
`darker(Color)`
|
||||
: produces a darker variant of Color
|
||||
|
||||
@@ -11,13 +11,17 @@ Editor render nodes
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
| **gtk4-node-editor** [OPTIONS...]
|
||||
| **gtk4-node-editor** [OPTIONS...] [FILE]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
``gtk4-node-editor`` is a utility to show and edit render node files.
|
||||
Such render node files can be obtained e.g. from the GTK inspector.
|
||||
Such render node files can be obtained e.g. from the GTK inspector or
|
||||
as part of the testsuite in the GTK sources.
|
||||
|
||||
``gtk4-node-editor`` is used by GTK developers for debugging and testing,
|
||||
and it has built-in support for saving testcases as part of the GTK testsuite.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
@@ -25,3 +29,21 @@ OPTIONS
|
||||
``-h, --help``
|
||||
|
||||
Show the application help.
|
||||
|
||||
``--version``
|
||||
|
||||
Show the program version.
|
||||
|
||||
``--reset``
|
||||
|
||||
Don't restore autosaved content and remove autosave files.
|
||||
|
||||
ENVIRONMENT
|
||||
-----------
|
||||
|
||||
``GTK_SOURCE_DIR``
|
||||
|
||||
can be set to point to the location where the GTK sources reside, so that
|
||||
testcases can be saved to the right location. If unsed, `gtk4-node-editor``
|
||||
checks if the current working directory looks like a GTK checkout, and failing
|
||||
that, saves testcase in the the current working directory.
|
||||
|
||||
@@ -12,9 +12,10 @@ SYNOPSIS
|
||||
--------
|
||||
| **gtk4-rendernode-tool** <COMMAND> [OPTIONS...] <FILE>
|
||||
|
|
||||
| **gtk4-rendernode-tool** benchmark [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** info [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** show [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** render [OPTIONS...] <FILE> [<FILE>]
|
||||
| **gtk4-rendernode-tool** show [OPTIONS...] <FILE>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -50,3 +51,31 @@ The name of the file to write can be specified as a second FILE argument.
|
||||
|
||||
Use the given renderer. Use ``--renderer=help`` to get a information
|
||||
about poassible values for the ``RENDERER``.
|
||||
|
||||
Benchmark
|
||||
^^^^^^^^^
|
||||
|
||||
The ``benchmark`` command benchmarks rendering of a node with the existing renderers
|
||||
and prints the runtimes.
|
||||
|
||||
``--renderer=RENDERER``
|
||||
|
||||
Add the given renderer. This argument can be passed multiple times to test multiple
|
||||
renderers. By default, all major GTK renderers are run.
|
||||
|
||||
``--runs=RUNS``
|
||||
|
||||
Number of times to render the node on each renderer. By default, this is 3 times.
|
||||
Keep in mind that the first run is often used to populate caches and might be
|
||||
significantly slower.
|
||||
|
||||
``--no-download``
|
||||
|
||||
Do not attempt to download the result. This may cause the measurement to not include
|
||||
the execution of the commands on the GPU. It can be useful to use this flag to test
|
||||
command submission performance.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ are only available when GTK has been configured with `-Ddebug=true`.
|
||||
`layout`
|
||||
: Layout managers
|
||||
|
||||
`acccessibility`
|
||||
`accessibility`
|
||||
: Accessibility state changs
|
||||
|
||||
A number of keys are influencing behavior instead of just logging:
|
||||
@@ -274,49 +274,46 @@ are only available when GTK has been configured with `-Ddebug=true`.
|
||||
`renderer`
|
||||
: General renderer information
|
||||
|
||||
`cairo`
|
||||
: cairo renderer information
|
||||
|
||||
`opengl`
|
||||
: OpenGL renderer information
|
||||
|
||||
`shaders`
|
||||
: Shaders
|
||||
|
||||
`surface`
|
||||
: Surfaces
|
||||
|
||||
`vulkan`
|
||||
: Vulkan renderer information
|
||||
|
||||
`shaders`
|
||||
: Information about shaders
|
||||
|
||||
`surface`
|
||||
: Information about surfaces
|
||||
|
||||
`fallback`
|
||||
: Information about fallbacks
|
||||
: Information about fallback usage in renderers
|
||||
|
||||
`glyphcache`
|
||||
: Information about glyph caching
|
||||
|
||||
`verbose`
|
||||
: Print verbose output while rendering
|
||||
|
||||
A number of options affect behavior instead of logging:
|
||||
|
||||
`diff`
|
||||
: Show differences
|
||||
|
||||
`geometry`
|
||||
: Show borders
|
||||
: Show borders (when using cairo)
|
||||
|
||||
`full-redraw`
|
||||
: Force full redraws for every frame
|
||||
: Force full redraws
|
||||
|
||||
`sync`
|
||||
: Sync after each frame
|
||||
|
||||
`staging`
|
||||
: Use a staging image for texture upload (Vulkan only)
|
||||
|
||||
`offload-disable`
|
||||
: Disable graphics offload to subsurfaces
|
||||
|
||||
`vulkan-staging-image`
|
||||
: Use a staging image for Vulkan texture upload
|
||||
|
||||
`vulkan-staging-buffer`
|
||||
: Use a staging buffer for Vulkan texture upload
|
||||
`cairo`
|
||||
: Overlay error pattern over cairo drawing (finds fallbacks)
|
||||
|
||||
The special value `all` can be used to turn on all debug options. The special
|
||||
value `help` can be used to obtain a list of all supported debug options.
|
||||
@@ -357,6 +354,40 @@ the default selection of the device that is used for Vulkan rendering.
|
||||
The special value `list` can be used to obtain a list of all Vulkan
|
||||
devices.
|
||||
|
||||
### `GDK_VULKAN_SKIP`
|
||||
|
||||
This variable can be set to a list of values, which cause GDK to
|
||||
disable features of the Vulkan support.
|
||||
Note that these features may already be disabled if the Vulkan driver
|
||||
does not support them.
|
||||
|
||||
`dmabuf`
|
||||
: Never import Dmabufs
|
||||
|
||||
`ycbr`
|
||||
: Do not support Ycbcr textures
|
||||
|
||||
`descriptor-indexing`
|
||||
: Force slow descriptor set layout codepath
|
||||
|
||||
`dynamic-indexing`
|
||||
: Hardcode small number of buffer and texture arrays
|
||||
|
||||
`nonuniform-indexing`
|
||||
: Split draw calls to ensure uniform texture accesses
|
||||
|
||||
`semaphore-export`
|
||||
: Disable sync of exported dmabufs
|
||||
|
||||
`semaphore-import`
|
||||
: Disable sync of imported dmabufs
|
||||
|
||||
`incremental-present`
|
||||
: Do not send damage regions
|
||||
|
||||
The special value `all` can be used to turn on all values. The special
|
||||
value `help` can be used to obtain a list of all supported values.
|
||||
|
||||
### `GSK_RENDERER`
|
||||
|
||||
If set, selects the GSK renderer to use. The following renderers can
|
||||
@@ -378,22 +409,56 @@ using and the GDK backend supports them:
|
||||
`gl`
|
||||
: Selects the "gl" OpenGL renderer
|
||||
|
||||
`ngl`
|
||||
: Selects the "ngl" OpenGL renderer
|
||||
|
||||
`vulkan`
|
||||
: Selects the Vulkan renderer
|
||||
|
||||
Note that on Windows, if one is running Nahimic 3 on a system with
|
||||
nVidia graphics, one needs to stop the "Nahimic service" or insert
|
||||
the GTK application into the Nahimic blacklist, as noted in
|
||||
https://www.nvidia.com/en-us/geforce/forums/game-ready-drivers/13/297952/nahimic-and-nvidia-drivers-conflict/2334568/, or use the cairo renderer (at the cost of being unable to use
|
||||
OpenGL features), or use GDK_DEBUG=gl-gles if you know that GLES
|
||||
support is enabled for the build.
|
||||
|
||||
This is a known issue, as the above link indicates, and affects quite
|
||||
a number of applications--sadly, since this issue lies within the
|
||||
nVidia graphics driver and/or the Nahimic 3 code, we are not able
|
||||
to rememdy this on the GTK side; the best bet before trying the above
|
||||
workarounds is to try to update your graphics drivers and Nahimic
|
||||
installation.
|
||||
::: note
|
||||
If you are running the Nahimic 3 service on a Windows system with
|
||||
nVidia graphics, you need to perform one of the following:
|
||||
|
||||
- stop the "Nahimic service"
|
||||
- insert the GTK application into the Nahimic blocklist, as noted in the
|
||||
[nVidia forums](https://www.nvidia.com/en-us/geforce/forums/game-ready-drivers/13/297952/nahimic-and-nvidia-drivers-conflict/2334568/)
|
||||
- use the cairo renderer (at the cost of being unable to use OpenGL features)
|
||||
- use `GDK_DEBUG=gl-gles`, if you know that GLES support is enabled for the build.
|
||||
|
||||
This is a known issue, as the above link indicates, and affects quite
|
||||
a number of applications—sadly, since this issue lies within the
|
||||
nVidia graphics driver and/or the Nahimic 3 code, we are not able
|
||||
to rememdy this on the GTK side; the best bet before trying the above
|
||||
workarounds is to try to update your graphics drivers and Nahimic
|
||||
installation.
|
||||
|
||||
|
||||
### `GSK_GPU_SKIP`
|
||||
|
||||
This variable can be set to a list of values, which cause GSK to
|
||||
disable certain optimizations of the "ngl" and "vulkan" renderer.
|
||||
|
||||
`uber`
|
||||
: Don't use the uber shader
|
||||
|
||||
`clear`
|
||||
: Use shaders instead of vkCmdClearAttachment()/glClear()
|
||||
|
||||
`blit`
|
||||
: Use shaders instead of vkCmdBlit()/glBlitFramebuffer()
|
||||
|
||||
`gradients`
|
||||
: Don't supersample gradients
|
||||
|
||||
`mipmap`
|
||||
: Avoid creating mipmaps
|
||||
|
||||
`gl-baseinstance`
|
||||
: Assume no ARB/EXT_base_instance support
|
||||
|
||||
The special value `all` can be used to turn on all values. The special
|
||||
value `help` can be used to obtain a list of all supported values.
|
||||
|
||||
### `GSK_MAX_TEXTURE_SIZE`
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ you should ensure that:
|
||||
GTK will try to fill in some information by using ancillary UI control properties,
|
||||
for instance the accessible name will be taken from the label used by the UI control,
|
||||
or from its tooltip, if the `GTK_ACCESSIBLE_PROPERTY_LABEL` property or the
|
||||
`GTK_ACCESSIBLE_RELATION_LABELLED_BY` relation are unset. Similary for the accessible
|
||||
`GTK_ACCESSIBLE_RELATION_LABELLED_BY` relation are unset. Similarly for the accessible
|
||||
description. Nevertheless, it is good practice and project hygiene to explicitly specify
|
||||
the accessible properties, just like it's good practice to specify tooltips and style classes.
|
||||
|
||||
|
||||
+3
-2
@@ -529,8 +529,9 @@ gdk_clipboard_get_content (GdkClipboard *clipboard)
|
||||
* exit. Depending on the platform, the functionality may not be available
|
||||
* unless a "clipboard manager" is running.
|
||||
*
|
||||
* This function is called automatically when a [class@Gtk.Application] is
|
||||
* shut down, so you likely don't need to call it.
|
||||
* This function is called automatically when a
|
||||
* [GtkApplication](../gtk4/class.Application.html)
|
||||
* is shut down, so you likely don't need to call it.
|
||||
*/
|
||||
void
|
||||
gdk_clipboard_store_async (GdkClipboard *clipboard,
|
||||
|
||||
+2
-1
@@ -47,7 +47,8 @@
|
||||
* Cursors by themselves are not very interesting: they must be bound to a
|
||||
* window for users to see them. This is done with [method@Gdk.Surface.set_cursor]
|
||||
* or [method@Gdk.Surface.set_device_cursor]. Applications will typically
|
||||
* use higher-level GTK functions such as [method@Gtk.Widget.set_cursor] instead.
|
||||
* use higher-level GTK functions such as [gtk_widget_set_cursor()](../gtk4/method.Widget.set_cursor.html)
|
||||
* instead.
|
||||
*
|
||||
* Cursors are not bound to a given [class@Gdk.Display], so they can be shared.
|
||||
* However, the appearance of cursors may vary when used on different
|
||||
|
||||
+2
-1
@@ -289,7 +289,8 @@ gdk_device_class_init (GdkDeviceClass *klass)
|
||||
*/
|
||||
device_props[PROP_MODIFIER_STATE] =
|
||||
g_param_spec_flags ("modifier-state", NULL, NULL,
|
||||
GDK_TYPE_MODIFIER_TYPE, 0,
|
||||
GDK_TYPE_MODIFIER_TYPE,
|
||||
GDK_NO_MODIFIER_MASK,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, device_props);
|
||||
|
||||
+54
-10
@@ -40,7 +40,7 @@
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdkrectangle.h"
|
||||
#include "gdkvulkancontext.h"
|
||||
#include "gdkvulkancontextprivate.h"
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
#include <epoxy/egl.h>
|
||||
@@ -253,6 +253,13 @@ gdk_display_class_init (GdkDisplayClass *class)
|
||||
TRUE,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDisplay:dmabuf-formats:
|
||||
*
|
||||
* The dma-buf formats that are supported on this display
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
props[PROP_DMABUF_FORMATS] =
|
||||
g_param_spec_boxed ("dmabuf-formats", NULL, NULL,
|
||||
GDK_TYPE_DMABUF_FORMATS,
|
||||
@@ -409,6 +416,13 @@ gdk_display_dispose (GObject *object)
|
||||
|
||||
g_clear_pointer (&display->egl_dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
g_clear_pointer (&display->egl_external_formats, gdk_dmabuf_formats_unref);
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
if (display->vk_dmabuf_formats)
|
||||
{
|
||||
gdk_display_unref_vulkan (display);
|
||||
g_assert (display->vk_dmabuf_formats == NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_clear_object (&priv->gl_context);
|
||||
#ifdef HAVE_EGL
|
||||
@@ -1182,9 +1196,9 @@ _gdk_display_get_next_serial (GdkDisplay *display)
|
||||
* Indicates to the GUI environment that the application has
|
||||
* finished loading, using a given identifier.
|
||||
*
|
||||
* GTK will call this function automatically for [class@Gtk.Window]
|
||||
* GTK will call this function automatically for [GtkWindow](../gtk4/class.Window.html)
|
||||
* with custom startup-notification identifier unless
|
||||
* [method@Gtk.Window.set_auto_startup_notification]
|
||||
* [gtk_window_set_auto_startup_notification()](../gtk4/method.Window.set_auto_startup_notification.html)
|
||||
* is called to disable that feature.
|
||||
*
|
||||
* Deprecated: 4.10: Using [method@Gdk.Toplevel.set_startup_id] is sufficient
|
||||
@@ -1253,12 +1267,14 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
/*<private>
|
||||
* gdk_display_create_vulkan_context:
|
||||
* @self: a `GdkDisplay`
|
||||
* @surface: (nullable): the `GdkSurface` to use or %NULL for a surfaceless
|
||||
* context
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Creates a new `GdkVulkanContext` for use with @display.
|
||||
*
|
||||
* The context can not be used to draw to surfaces, it can only be
|
||||
* used for custom rendering or compute.
|
||||
* If @surface is NULL, the context can not be used to draw to surfaces,
|
||||
* it can only be used for custom rendering or compute.
|
||||
*
|
||||
* If the creation of the `GdkVulkanContext` failed, @error will be set.
|
||||
*
|
||||
@@ -1267,9 +1283,11 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
*/
|
||||
GdkVulkanContext *
|
||||
gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), NULL);
|
||||
g_return_val_if_fail (surface == NULL || GDK_IS_SURFACE (surface), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (gdk_display_get_debug_flags (self) & GDK_DEBUG_VULKAN_DISABLE)
|
||||
@@ -1286,11 +1304,33 @@ gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_initable_new (GDK_DISPLAY_GET_CLASS (self)->vk_context_type,
|
||||
NULL,
|
||||
error,
|
||||
"display", self,
|
||||
NULL);
|
||||
if (surface)
|
||||
{
|
||||
return g_initable_new (GDK_DISPLAY_GET_CLASS (self)->vk_context_type,
|
||||
NULL,
|
||||
error,
|
||||
"surface", surface,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
return g_initable_new (GDK_DISPLAY_GET_CLASS (self)->vk_context_type,
|
||||
NULL,
|
||||
error,
|
||||
"display", self,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_display_has_vulkan_feature (GdkDisplay *self,
|
||||
GdkVulkanFeatures feature)
|
||||
{
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
return !!(self->vulkan_features & feature);
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1932,6 +1972,10 @@ gdk_display_init_dmabuf (GdkDisplay *self)
|
||||
#ifdef HAVE_DMABUF
|
||||
if (!GDK_DISPLAY_DEBUG_CHECK (self, DMABUF_DISABLE))
|
||||
{
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gdk_display_add_dmabuf_downloader (self, gdk_vulkan_get_dmabuf_downloader (self, builder));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
gdk_display_add_dmabuf_downloader (self, gdk_dmabuf_get_egl_downloader (self, builder));
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,17 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GdkDisplayClass GdkDisplayClass;
|
||||
|
||||
typedef enum {
|
||||
GDK_VULKAN_FEATURE_DMABUF = 1 << 0,
|
||||
GDK_VULKAN_FEATURE_YCBCR = 1 << 1,
|
||||
GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING = 1 << 2,
|
||||
GDK_VULKAN_FEATURE_DYNAMIC_INDEXING = 1 << 3,
|
||||
GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING = 1 << 4,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 5,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 6,
|
||||
GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 7,
|
||||
} GdkVulkanFeatures;
|
||||
|
||||
/* Tracks information about the device grab on this display */
|
||||
typedef struct
|
||||
{
|
||||
@@ -107,6 +118,8 @@ struct _GdkDisplay
|
||||
char *vk_pipeline_cache_etag;
|
||||
guint vk_save_pipeline_cache_source;
|
||||
GHashTable *vk_shader_modules;
|
||||
GdkDmabufFormats *vk_dmabuf_formats;
|
||||
GdkVulkanFeatures vulkan_features;
|
||||
|
||||
guint vulkan_refcount;
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
@@ -220,7 +233,10 @@ void _gdk_display_unpause_events (GdkDisplay *display
|
||||
|
||||
void gdk_display_init_dmabuf (GdkDisplay *self);
|
||||
|
||||
gboolean gdk_display_has_vulkan_feature (GdkDisplay *self,
|
||||
GdkVulkanFeatures feature);
|
||||
GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
|
||||
GdkSurface *surface,
|
||||
GError **error);
|
||||
|
||||
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
|
||||
|
||||
@@ -1919,6 +1919,19 @@ gdk_dmabuf_get_memory_format (guint32 fourcc,
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gboolean
|
||||
gdk_dmabuf_vk_get_nth (gsize n,
|
||||
guint32 *fourcc,
|
||||
VkFormat *vk_format)
|
||||
{
|
||||
if (n >= G_N_ELEMENTS (supported_formats))
|
||||
return FALSE;
|
||||
|
||||
*fourcc = supported_formats[n].fourcc;
|
||||
*vk_format = supported_formats[n].vk.format;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VkFormat
|
||||
gdk_dmabuf_get_vk_format (guint32 fourcc,
|
||||
VkComponentMapping *out_components)
|
||||
|
||||
+5
-5
@@ -140,10 +140,10 @@ gdk_dmabuf_egl_downloader_collect_formats (GdkDisplay *display,
|
||||
|
||||
typedef struct _GskRenderer GskRenderer;
|
||||
|
||||
extern GskRenderer * gsk_gl_renderer_new (void);
|
||||
extern gboolean gsk_renderer_realize (GskRenderer *renderer,
|
||||
GdkSurface *surface,
|
||||
GError **error);
|
||||
extern GskRenderer * gsk_gl_renderer_new (void);
|
||||
extern gboolean gsk_renderer_realize_for_display (GskRenderer *renderer,
|
||||
GdkDisplay *display,
|
||||
GError **error);
|
||||
|
||||
GdkDmabufDownloader *
|
||||
gdk_dmabuf_get_egl_downloader (GdkDisplay *display,
|
||||
@@ -176,7 +176,7 @@ gdk_dmabuf_get_egl_downloader (GdkDisplay *display,
|
||||
|
||||
renderer = gsk_gl_renderer_new ();
|
||||
|
||||
if (!gsk_renderer_realize (renderer, NULL, &error))
|
||||
if (!gsk_renderer_realize_for_display (renderer, display, &error))
|
||||
{
|
||||
g_warning ("Failed to realize GL renderer: %s", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
/**
|
||||
* GdkDmabufFormats:
|
||||
*
|
||||
* The `GdkDmabufFormats struct provides information about
|
||||
* The `GdkDmabufFormats` struct provides information about
|
||||
* supported DMA buffer formats.
|
||||
*
|
||||
* You can query whether a given format is supported with
|
||||
@@ -37,7 +37,7 @@
|
||||
* The list of supported formats is sorted by preference,
|
||||
* with the best formats coming first.
|
||||
*
|
||||
* The list may contains (format, modfier) pairs where the modifier
|
||||
* The list may contains (format, modifier) pairs where the modifier
|
||||
* is `DMA_FORMAT_MOD_INVALID`, indicating that **_implicit modifiers_**
|
||||
* may be used with this format.
|
||||
*
|
||||
@@ -152,10 +152,10 @@ gdk_dmabuf_formats_get_format (GdkDmabufFormats *formats,
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_format_contains:
|
||||
* gdk_dmabuf_formats_contains:
|
||||
* @formats: a `GdkDmabufFormats`
|
||||
* @fourcc: a format code
|
||||
* @modfier: a format modifier
|
||||
* @modifier: a format modifier
|
||||
*
|
||||
* Returns whether a given format is contained in @formats.
|
||||
*
|
||||
|
||||
@@ -54,6 +54,9 @@ gboolean gdk_dmabuf_get_memory_format (guint32
|
||||
gboolean premultiplied,
|
||||
GdkMemoryFormat *out_format);
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gboolean gdk_dmabuf_vk_get_nth (gsize n,
|
||||
guint32 *fourcc,
|
||||
VkFormat *vk_format);
|
||||
VkFormat gdk_dmabuf_get_vk_format (guint32 fourcc,
|
||||
VkComponentMapping *out_components);
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
* [class@Gdk.DmabufTextureBuilder] object.
|
||||
*
|
||||
* Dma-buf textures can only be created on Linux.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
|
||||
struct _GdkDmabufTexture
|
||||
|
||||
@@ -57,7 +57,7 @@ struct _GdkDmabufTextureBuilderClass
|
||||
*
|
||||
* DMA buffers are commonly called **_dma-bufs_**.
|
||||
*
|
||||
* DMA buffers a feature of the Linux kernel to enable efficient buffer and
|
||||
* DMA buffers are a feature of the Linux kernel to enable efficient buffer and
|
||||
* memory sharing between hardware such as codecs, GPUs, displays, cameras and the
|
||||
* kernel drivers controlling them. For example, a decoder may want its output to
|
||||
* be directly shared with the display server for rendering without a copy.
|
||||
@@ -67,7 +67,7 @@ struct _GdkDmabufTextureBuilderClass
|
||||
*
|
||||
* The memory that is shared via DMA buffers is usually stored in non-system memory
|
||||
* (maybe in device's local memory or something else not directly accessible by the
|
||||
* CPU), and accessing this memory from the CPU may have higher than usual overhead.
|
||||
* CPU), and accessing this memory from the CPU may have higher-than-usual overhead.
|
||||
*
|
||||
* In particular for graphics data, it is not uncommon that data consists of multiple
|
||||
* separate blocks of memory, for example one block for each of the red, green and
|
||||
@@ -87,7 +87,7 @@ struct _GdkDmabufTextureBuilderClass
|
||||
*
|
||||
* For historical reasons, some producers of dma-bufs don't provide an explicit modifier, but
|
||||
* instead return `DMA_FORMAT_MOD_INVALID` to indicate that their modifier is **_implicit_**.
|
||||
* GTK tries to accomodate this situation by accepting `DMA_FORMAT_MOD_INVALID` as modifier.
|
||||
* GTK tries to accommodate this situation by accepting `DMA_FORMAT_MOD_INVALID` as modifier.
|
||||
*
|
||||
* The operation of `GdkDmabufTextureBuilder` is quite simple: Create a texture builder,
|
||||
* set all the necessary properties, and then call [method@Gdk.DmabufTextureBuilder.build]
|
||||
|
||||
+4
-4
@@ -56,10 +56,10 @@ static struct {
|
||||
GdkCursor *cursor;
|
||||
} drag_cursors[] = {
|
||||
{ GDK_ACTION_ASK, "dnd-ask", NULL },
|
||||
{ GDK_ACTION_COPY, "dnd-copy", NULL },
|
||||
{ GDK_ACTION_MOVE, "dnd-move", NULL },
|
||||
{ GDK_ACTION_LINK, "dnd-link", NULL },
|
||||
{ 0, "dnd-none", NULL },
|
||||
{ GDK_ACTION_COPY, "copy", NULL },
|
||||
{ GDK_ACTION_MOVE, "move", NULL },
|
||||
{ GDK_ACTION_LINK, "alias", NULL },
|
||||
{ 0, "no-drop", NULL },
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
@@ -71,7 +71,7 @@ gdk_draw_context_default_surface_resized (GdkDrawContext *context)
|
||||
static void
|
||||
gdk_draw_context_default_empty_frame (GdkDrawContext *context)
|
||||
{
|
||||
g_warning ("FIXME: Implement");
|
||||
g_warning ("FIXME: Implement GdkDrawContext.empty_frame in %s", G_OBJECT_TYPE_NAME (context));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -305,8 +305,8 @@ gdk_draw_context_get_surface (GdkDrawContext *context)
|
||||
*
|
||||
* When using GTK, the widget system automatically places calls to
|
||||
* gdk_draw_context_begin_frame() and gdk_draw_context_end_frame() via the
|
||||
* use of [class@Gsk.Renderer]s, so application code does not need to call
|
||||
* these functions explicitly.
|
||||
* use of [GskRenderer](../gsk4/class.Renderer.html)s, so application code
|
||||
* does not need to call these functions explicitly.
|
||||
*/
|
||||
void
|
||||
gdk_draw_context_begin_frame (GdkDrawContext *context,
|
||||
@@ -331,7 +331,7 @@ gdk_draw_context_begin_frame (GdkDrawContext *context,
|
||||
*
|
||||
* This is only a request and if the GDK backend does not support HDR rendering
|
||||
* or does not consider it worthwhile, it may choose to not honor the request.
|
||||
* It may also choose to provide a differnet depth even if it was not requested.
|
||||
* It may also choose to provide a different depth even if it was not requested.
|
||||
* Typically the steps undertaken by a backend are:
|
||||
* 1. Check if high depth is supported by this drawing backend.
|
||||
* 2. Check if the compositor supports high depth.
|
||||
|
||||
@@ -160,6 +160,8 @@ typedef enum
|
||||
* reasons
|
||||
*
|
||||
* Error enumeration for `GdkDmabufTexture`.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_DMABUF_ERROR_NOT_AVAILABLE,
|
||||
|
||||
+4
-2
@@ -166,7 +166,8 @@ gdk_frame_clock_class_init (GdkFrameClockClass *klass)
|
||||
*
|
||||
* Animations should be updated using [method@Gdk.FrameClock.get_frame_time].
|
||||
* Applications can connect directly to this signal, or use
|
||||
* [method@Gtk.Widget.add_tick_callback] as a more convenient interface.
|
||||
* [gtk_widget_add_tick_callback()](../gtk4/method.Widget.add_tick_callback.html)
|
||||
* as a more convenient interface.
|
||||
*/
|
||||
signals[UPDATE] =
|
||||
g_signal_new (g_intern_static_string ("update"),
|
||||
@@ -203,7 +204,8 @@ gdk_frame_clock_class_init (GdkFrameClockClass *klass)
|
||||
*
|
||||
* The frame is repainted. GDK normally handles this internally and
|
||||
* emits [signal@Gdk.Surface::render] signals which are turned into
|
||||
* [signal@Gtk.Widget::snapshot] signals by GTK.
|
||||
* [GtkWidget::snapshot](../gtk4/signal.Widget.snapshot.html) signals
|
||||
* by GTK.
|
||||
*/
|
||||
signals[PAINT] =
|
||||
g_signal_new (g_intern_static_string ("paint"),
|
||||
|
||||
+13
-12
@@ -1569,10 +1569,10 @@ gdk_gl_context_init_memory_flags (GdkGLContext *self)
|
||||
priv->memory_flags[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R8G8B8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R8G8B8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= GDK_GL_FORMAT_USABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_USABLE;
|
||||
@@ -1583,12 +1583,12 @@ gdk_gl_context_init_memory_flags (GdkGLContext *self)
|
||||
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
|
||||
{
|
||||
/* GLES 3.2 spec, table 8.10 */
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1639,7 +1639,8 @@ gdk_gl_context_init_memory_flags (GdkGLContext *self)
|
||||
flags |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= flags;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= flags;
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= flags;
|
||||
/* disabled for now, see https://gitlab.freedesktop.org/mesa/mesa/-/issues/10378 */
|
||||
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= flags & ~GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= flags;
|
||||
}
|
||||
if (epoxy_has_gl_extension ("GL_OES_texture_float"))
|
||||
@@ -1651,7 +1652,7 @@ gdk_gl_context_init_memory_flags (GdkGLContext *self)
|
||||
flags |= GDK_GL_FORMAT_FILTERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= flags;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= flags;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= flags;
|
||||
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= flags & ~GDK_GL_FORMAT_RENDERABLE;
|
||||
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= flags;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-2
@@ -161,7 +161,12 @@ gdk_gl_texture_find_format (GdkGLContext *context,
|
||||
if (!(gdk_gl_context_get_format_flags (context, format) & GDK_GL_FORMAT_RENDERABLE))
|
||||
continue;
|
||||
|
||||
gdk_memory_format_gl_format (format, &q_internal_format, &q_format, &q_type, q_swizzle);
|
||||
gdk_memory_format_gl_format (format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&q_internal_format,
|
||||
&q_format,
|
||||
&q_type,
|
||||
q_swizzle);
|
||||
|
||||
if (q_format != gl_format || q_type != gl_type)
|
||||
continue;
|
||||
@@ -193,6 +198,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
((gdk_gl_context_get_format_flags (context, format) & GDK_GL_FORMAT_USABLE) == GDK_GL_FORMAT_USABLE))
|
||||
{
|
||||
gdk_memory_format_gl_format (format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&gl_internal_format,
|
||||
&gl_format, &gl_type, gl_swizzle);
|
||||
if (download->stride == expected_stride &&
|
||||
@@ -255,6 +261,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
actual_format = gdk_memory_format_get_straight (actual_format);
|
||||
|
||||
gdk_memory_format_gl_format (actual_format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&gl_internal_format,
|
||||
&gl_read_format, &gl_read_type, gl_swizzle);
|
||||
}
|
||||
@@ -266,6 +273,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
actual_format = gdk_memory_format_get_straight (actual_format);
|
||||
|
||||
gdk_memory_format_gl_format (actual_format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&gl_internal_format,
|
||||
&gl_read_format, &gl_read_type, gl_swizzle);
|
||||
}
|
||||
@@ -653,7 +661,7 @@ gdk_gl_texture_determine_format (GdkGLTexture *self)
|
||||
* Return value: (transfer full) (type GdkGLTexture): A newly-created
|
||||
* `GdkTexture`
|
||||
*
|
||||
* Deprecated: 4.12: [class@Gdk.GLTextureBuilder] supercedes this function
|
||||
* Deprecated: 4.12: [class@Gdk.GLTextureBuilder] supersedes this function
|
||||
* and provides extended functionality for creating GL textures.
|
||||
*/
|
||||
GdkTexture *
|
||||
|
||||
@@ -51,7 +51,7 @@ struct _GdkGLTextureBuilderClass
|
||||
/**
|
||||
* GdkGLTextureBuilder:
|
||||
*
|
||||
* `GdkGLTextureBuilder` is a buider used to construct [class@Gdk.Texture] objects from
|
||||
* `GdkGLTextureBuilder` is a builder used to construct [class@Gdk.Texture] objects from
|
||||
* GL textures.
|
||||
*
|
||||
* The operation is quite simple: Create a texture builder, set all the necessary
|
||||
|
||||
+80
-37
@@ -335,7 +335,8 @@ struct _GdkMemoryFormatDescription
|
||||
GdkMemoryDepth depth;
|
||||
const GdkMemoryFormat *fallbacks;
|
||||
struct {
|
||||
GLint internal_format;
|
||||
GLint internal_gl_format;
|
||||
GLint internal_gles_format;
|
||||
GLenum format;
|
||||
GLenum type;
|
||||
GLint swizzle[4];
|
||||
@@ -375,7 +376,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_BGRA,
|
||||
.format = GL_BGRA,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -402,7 +404,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_BGRA,
|
||||
.type = GDK_GL_UNSIGNED_BYTE_FLIPPED,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -429,7 +432,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -455,7 +459,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_RGBA,
|
||||
.type = GDK_GL_UNSIGNED_BYTE_FLIPPED,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -482,7 +487,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_BGRA,
|
||||
.format = GL_BGRA,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -509,7 +515,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_BGRA,
|
||||
.type = GDK_GL_UNSIGNED_BYTE_FLIPPED,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -536,7 +543,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -562,7 +570,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_RGBA,
|
||||
.type = GDK_GL_UNSIGNED_BYTE_FLIPPED,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -590,7 +599,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_BGRA,
|
||||
.format = GL_BGRA,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ONE },
|
||||
@@ -618,7 +628,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_BGRA,
|
||||
.type = GDK_GL_UNSIGNED_BYTE_FLIPPED,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ONE },
|
||||
@@ -646,7 +657,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ONE },
|
||||
@@ -673,7 +685,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA8,
|
||||
.internal_gl_format = GL_RGBA8,
|
||||
.internal_gles_format = GL_RGBA8,
|
||||
.format = GL_RGBA,
|
||||
.type = GDK_GL_UNSIGNED_BYTE_FLIPPED,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ONE },
|
||||
@@ -701,7 +714,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGB8,
|
||||
.internal_gl_format = GL_RGB8,
|
||||
.internal_gles_format = GL_RGB8,
|
||||
.format = GL_RGB,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -728,7 +742,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGB8,
|
||||
.internal_gl_format = GL_RGB8,
|
||||
.internal_gles_format = GL_RGB8,
|
||||
.format = GL_BGR,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -759,7 +774,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGB16,
|
||||
.internal_gl_format = GL_RGB16,
|
||||
.internal_gles_format = GL_RGB16,
|
||||
.format = GL_RGB,
|
||||
.type = GL_UNSIGNED_SHORT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -788,7 +804,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA16,
|
||||
.internal_gl_format = GL_RGBA16,
|
||||
.internal_gles_format = GL_RGBA16,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_UNSIGNED_SHORT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -817,7 +834,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA16,
|
||||
.internal_gl_format = GL_RGBA16,
|
||||
.internal_gles_format = GL_RGBA16,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_UNSIGNED_SHORT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -846,7 +864,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGB16F,
|
||||
.internal_gl_format = GL_RGB16F,
|
||||
.internal_gles_format = GL_RGB16F,
|
||||
.format = GL_RGB,
|
||||
.type = GL_HALF_FLOAT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -874,7 +893,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA16F,
|
||||
.internal_gl_format = GL_RGBA16F,
|
||||
.internal_gles_format = GL_RGBA16F,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_HALF_FLOAT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -902,7 +922,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA16F,
|
||||
.internal_gl_format = GL_RGBA16F,
|
||||
.internal_gles_format = GL_RGBA16F,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_HALF_FLOAT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -931,7 +952,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGB32F,
|
||||
.internal_gl_format = GL_RGB32F,
|
||||
.internal_gles_format = GL_RGB32F,
|
||||
.format = GL_RGB,
|
||||
.type = GL_FLOAT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -959,7 +981,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA32F,
|
||||
.internal_gl_format = GL_RGBA32F,
|
||||
.internal_gles_format = GL_RGBA32F,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_FLOAT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -987,7 +1010,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RGBA32F,
|
||||
.internal_gl_format = GL_RGBA32F,
|
||||
.internal_gles_format = GL_RGBA32F,
|
||||
.format = GL_RGBA,
|
||||
.type = GL_FLOAT,
|
||||
.swizzle = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA },
|
||||
@@ -1014,7 +1038,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RG8,
|
||||
.internal_gl_format = GL_RG8,
|
||||
.internal_gles_format = GL_RG8,
|
||||
.format = GL_RG,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_GREEN },
|
||||
@@ -1041,7 +1066,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RG8,
|
||||
.internal_gl_format = GL_RG8,
|
||||
.internal_gles_format = GL_RG8,
|
||||
.format = GL_RG,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_GREEN },
|
||||
@@ -1068,7 +1094,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_R8,
|
||||
.internal_gl_format = GL_R8,
|
||||
.internal_gles_format = GL_R8,
|
||||
.format = GL_RED,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_ONE },
|
||||
@@ -1098,7 +1125,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RG16,
|
||||
.internal_gl_format = GL_RG16,
|
||||
.internal_gles_format = GL_RG16,
|
||||
.format = GL_RG,
|
||||
.type = GL_UNSIGNED_SHORT,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_GREEN },
|
||||
@@ -1128,7 +1156,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_RG16,
|
||||
.internal_gl_format = GL_RG16,
|
||||
.internal_gles_format = GL_RG16,
|
||||
.format = GL_RG,
|
||||
.type = GL_UNSIGNED_SHORT,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_GREEN },
|
||||
@@ -1158,7 +1187,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_R16,
|
||||
.internal_gl_format = GL_R16,
|
||||
.internal_gles_format = GL_R16,
|
||||
.format = GL_RED,
|
||||
.type = GL_UNSIGNED_SHORT,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_ONE },
|
||||
@@ -1185,7 +1215,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_R8,
|
||||
.internal_gl_format = GL_R8,
|
||||
.internal_gles_format = GL_R8,
|
||||
.format = GL_RED,
|
||||
.type = GL_UNSIGNED_BYTE,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_RED },
|
||||
@@ -1215,7 +1246,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_R16,
|
||||
.internal_gl_format = GL_R16,
|
||||
.internal_gles_format = GL_R16,
|
||||
.format = GL_RED,
|
||||
.type = GL_UNSIGNED_SHORT,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_RED },
|
||||
@@ -1244,7 +1276,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_R16F,
|
||||
.internal_gl_format = GL_R16F,
|
||||
.internal_gles_format = GL_R16F,
|
||||
.format = GL_RED,
|
||||
.type = GL_HALF_FLOAT,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_RED },
|
||||
@@ -1273,7 +1306,8 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
-1,
|
||||
},
|
||||
.gl = {
|
||||
.internal_format = GL_R32F,
|
||||
.internal_gl_format = GL_R32F,
|
||||
.internal_gles_format = GL_R32F,
|
||||
.format = GL_RED,
|
||||
.type = GL_FLOAT,
|
||||
.swizzle = { GL_RED, GL_RED, GL_RED, GL_RED },
|
||||
@@ -1387,7 +1421,7 @@ gdk_memory_format_get_depth (GdkMemoryFormat format)
|
||||
* @depth1: the first depth
|
||||
* @depth2: the second depth
|
||||
*
|
||||
* Returns a depth that can accomodate both given depths
|
||||
* Returns a depth that can accommodate both given depths
|
||||
* without any loss of precision.
|
||||
*
|
||||
* Returns: The merged depth
|
||||
@@ -1473,12 +1507,16 @@ gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth)
|
||||
|
||||
void
|
||||
gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
GLint *out_internal_format,
|
||||
GLenum *out_format,
|
||||
GLenum *out_type,
|
||||
GLint out_swizzle[4])
|
||||
{
|
||||
*out_internal_format = memory_formats[format].gl.internal_format;
|
||||
if (gles)
|
||||
*out_internal_format = memory_formats[format].gl.internal_gles_format;
|
||||
else
|
||||
*out_internal_format = memory_formats[format].gl.internal_gl_format;
|
||||
*out_format = memory_formats[format].gl.format;
|
||||
*out_type = memory_formats[format].gl.type;
|
||||
memcpy (out_swizzle, memory_formats[format].gl.swizzle, sizeof(GLint) * 4);
|
||||
@@ -1487,6 +1525,7 @@ gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
/*
|
||||
* gdk_memory_format_gl_rgba_format:
|
||||
* @format: The format to query
|
||||
* @gles: TRUE for GLES, FALSE for GL
|
||||
* @out_actual_format: The actual RGBA format
|
||||
* @out_internal_format: the GL internal format
|
||||
* @out_format: the GL format
|
||||
@@ -1504,6 +1543,7 @@ gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
**/
|
||||
gboolean
|
||||
gdk_memory_format_gl_rgba_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
GdkMemoryFormat *out_actual_format,
|
||||
GLint *out_internal_format,
|
||||
GLenum *out_format,
|
||||
@@ -1516,7 +1556,10 @@ gdk_memory_format_gl_rgba_format (GdkMemoryFormat format,
|
||||
return FALSE;
|
||||
|
||||
*out_actual_format = actual;
|
||||
*out_internal_format = memory_formats[actual].gl.internal_format;
|
||||
if (gles)
|
||||
*out_internal_format = memory_formats[actual].gl.internal_gles_format;
|
||||
else
|
||||
*out_internal_format = memory_formats[actual].gl.internal_gl_format;
|
||||
*out_format = memory_formats[actual].gl.format;
|
||||
*out_type = memory_formats[actual].gl.type;
|
||||
memcpy (out_swizzle, memory_formats[format].gl.rgba_swizzle, sizeof(GLint) * 4);
|
||||
|
||||
@@ -55,11 +55,13 @@ GdkMemoryDepth gdk_memory_depth_merge (GdkMemoryDepth
|
||||
GdkMemoryFormat gdk_memory_depth_get_format (GdkMemoryDepth depth) G_GNUC_CONST;
|
||||
GdkMemoryFormat gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth) G_GNUC_CONST;
|
||||
void gdk_memory_format_gl_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
GLint *out_internal_format,
|
||||
GLenum *out_format,
|
||||
GLenum *out_type,
|
||||
GLint out_swizzle[4]);
|
||||
gboolean gdk_memory_format_gl_rgba_format (GdkMemoryFormat format,
|
||||
gboolean gles,
|
||||
GdkMemoryFormat *out_actual_format,
|
||||
GLint *out_internal_format,
|
||||
GLenum *out_format,
|
||||
|
||||
+2
-1
@@ -681,7 +681,8 @@ gdk_empty_paintable_init (GdkEmptyPaintable *self)
|
||||
* This is often useful for implementing the
|
||||
* [vfunc@Gdk.Paintable.get_current_image] virtual function
|
||||
* when the paintable is in an incomplete state (like a
|
||||
* [class@Gtk.MediaStream] before receiving the first frame).
|
||||
* [GtkMediaStream](../gtk4/class.MediaStream.html) before receiving
|
||||
* the first frame).
|
||||
*
|
||||
* Returns: (transfer full): a `GdkPaintable`
|
||||
*/
|
||||
|
||||
@@ -56,9 +56,9 @@
|
||||
* [method@Gdk.Popup.get_position_x], [method@Gdk.Popup.get_position_y],
|
||||
* [method@Gdk.Popup.get_rect_anchor] and [method@Gdk.Popup.get_surface_anchor]
|
||||
* after the popup has been presented. This can be used to adjust the rendering.
|
||||
* For example, [class@Gtk.Popover] changes its arrow position accordingly.
|
||||
* But you have to be careful avoid changing the size of the popover, or it
|
||||
* has to be presented again.
|
||||
* For example, [GtkPopover](../gtk4/class.Popover.html) changes its arrow position
|
||||
* accordingly. But you have to be careful avoid changing the size of the popover,
|
||||
* or it has to be presented again.
|
||||
*/
|
||||
|
||||
struct _GdkPopupLayout
|
||||
|
||||
+2
-2
@@ -45,12 +45,12 @@ void gdk_rectangle_union (const GdkRectangle *src1,
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_rectangle_equal (const GdkRectangle *rect1,
|
||||
const GdkRectangle *rect2);
|
||||
const GdkRectangle *rect2) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_rectangle_contains_point (const GdkRectangle *rect,
|
||||
int x,
|
||||
int y);
|
||||
int y) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_rectangle_get_type (void) G_GNUC_CONST;
|
||||
|
||||
+1
-1
@@ -642,7 +642,7 @@ gdk_rgba_parser_parse (GtkCssParser *parser,
|
||||
{
|
||||
if (gtk_css_token_is_ident (token, "transparent"))
|
||||
{
|
||||
*rgba = (GdkRGBA) { 0, 0, 0, 0 };
|
||||
*rgba = GDK_RGBA_TRANSPARENT;
|
||||
}
|
||||
else if (gdk_rgba_parse (rgba, gtk_css_token_get_string (token)))
|
||||
{
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
((_GDK_RGBA_SELECT_COLOR(str, 2, 4) << 4) | _GDK_RGBA_SELECT_COLOR(str, 2, 5)) / 255., \
|
||||
((sizeof(str) % 4 == 1) ? ((_GDK_RGBA_SELECT_COLOR(str, 3, 6) << 4) | _GDK_RGBA_SELECT_COLOR(str, 3, 7)) : 0xFF) / 255. })
|
||||
|
||||
#define GDK_RGBA_INIT_ALPHA(rgba,opacity) ((GdkRGBA) { (rgba)->red, (rgba)->green, (rgba)->blue, (rgba)->alpha * (opacity) })
|
||||
|
||||
#define GDK_RGBA_TRANSPARENT ((GdkRGBA) { 0, 0, 0, 0 })
|
||||
#define GDK_RGBA_BLACK ((GdkRGBA) { 0, 0, 0, 1 })
|
||||
#define GDK_RGBA_WHITE ((GdkRGBA) { 1, 1, 1, 1 })
|
||||
|
||||
gboolean gdk_rgba_parser_parse (GtkCssParser *parser,
|
||||
GdkRGBA *rgba);
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
*
|
||||
* Base type for snapshot operations.
|
||||
*
|
||||
* The subclass of `GdkSnapshot` used by GTK is [class@Gtk.Snapshot].
|
||||
* The subclass of `GdkSnapshot` used by GTK is [GtkSnapshot](../gtk4/class.Snapshot.html).
|
||||
*/
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (GdkSnapshot, gdk_snapshot, G_TYPE_OBJECT)
|
||||
|
||||
+10
-33
@@ -57,7 +57,7 @@
|
||||
* A `GdkSurface` is a rectangular region on the screen.
|
||||
*
|
||||
* It’s a low-level object, used to implement high-level objects
|
||||
* such as [class@Gtk.Window] or [class@Gtk.Dialog] in GTK.
|
||||
* such as [GtkWindow](../gtk4/class.Window.html).
|
||||
*
|
||||
* The surfaces you see in practice are either [iface@Gdk.Toplevel] or
|
||||
* [iface@Gdk.Popup], and those interfaces provide much of the required
|
||||
@@ -1246,43 +1246,20 @@ gdk_surface_create_cairo_context (GdkSurface *surface)
|
||||
* @surface: a `GdkSurface`
|
||||
* @error: return location for an error
|
||||
*
|
||||
* Creates a new `GdkVulkanContext` for rendering on @surface.
|
||||
* Sets an error and returns %NULL.
|
||||
*
|
||||
* If the creation of the `GdkVulkanContext` failed, @error will be set.
|
||||
* Returns: (transfer full): %NULL
|
||||
*
|
||||
* Returns: (transfer full): the newly created `GdkVulkanContext`, or
|
||||
* %NULL on error
|
||||
* Deprecated: 4.14: GTK does not expose any Vulkan internals. This
|
||||
* function is a leftover that was accidentally exposed.
|
||||
*/
|
||||
GdkVulkanContext *
|
||||
gdk_surface_create_vulkan_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (gdk_display_get_debug_flags (surface->display) & GDK_DEBUG_VULKAN_DISABLE)
|
||||
{
|
||||
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
|
||||
_("Vulkan support disabled via GDK_DEBUG"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display = surface->display;
|
||||
|
||||
if (GDK_DISPLAY_GET_CLASS (display)->vk_extension_name == NULL)
|
||||
{
|
||||
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
"The %s backend has no Vulkan support.", G_OBJECT_TYPE_NAME (display));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_initable_new (GDK_DISPLAY_GET_CLASS (display)->vk_context_type,
|
||||
NULL,
|
||||
error,
|
||||
"surface", surface,
|
||||
NULL);
|
||||
g_set_error (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_UNSUPPORTED,
|
||||
"GTK does not expose Vulkan internals.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1716,7 +1693,7 @@ gdk_surface_get_device_position (GdkSurface *surface,
|
||||
* For toplevel surfaces, withdraws them, so they will no longer be
|
||||
* known to the window manager; for all surfaces, unmaps them, so
|
||||
* they won’t be displayed. Normally done automatically as
|
||||
* part of [method@Gtk.Widget.hide].
|
||||
* part of [gtk_widget_hide()](../gtk4/method.Widget.hide.html).
|
||||
*/
|
||||
void
|
||||
gdk_surface_hide (GdkSurface *surface)
|
||||
@@ -2636,7 +2613,7 @@ gdk_surface_get_scale (GdkSurface *surface)
|
||||
* GTK will update this property automatically if the @surface background
|
||||
* is opaque, as we know where the opaque regions are. If your surface
|
||||
* background is not opaque, please update this property in your
|
||||
* [vfunc@Gtk.Widget.css_changed] handler.
|
||||
* [GtkWidgetClass.css_changed](../gtk4/vfunc.Widget.css_changed.html) handler.
|
||||
*/
|
||||
void
|
||||
gdk_surface_set_opaque_region (GdkSurface *surface,
|
||||
|
||||
+1
-1
@@ -134,7 +134,7 @@ GdkCairoContext *gdk_surface_create_cairo_context(GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkGLContext * gdk_surface_create_gl_context (GdkSurface *surface,
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_14
|
||||
GdkVulkanContext *
|
||||
gdk_surface_create_vulkan_context(GdkSurface *surface,
|
||||
GError **error);
|
||||
|
||||
+1
-1
@@ -870,7 +870,7 @@ gdk_texture_download_surface (GdkTexture *texture)
|
||||
* cairo_surface_mark_dirty (surface);
|
||||
* ```
|
||||
*
|
||||
* For more flexible download capabilites, see
|
||||
* For more flexible download capabilities, see
|
||||
* [struct@Gdk.TextureDownloader].
|
||||
*/
|
||||
void
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* [class@Gdk.Texture].
|
||||
*
|
||||
* It is intended to be created as a short-term object for a single download,
|
||||
* but can be used for multipe downloads of different textures or with different
|
||||
* but can be used for multiple downloads of different textures or with different
|
||||
* settings.
|
||||
*
|
||||
* `GdkTextureDownloader` can be used to convert data between different formats.
|
||||
|
||||
+7
-6
@@ -377,8 +377,9 @@ gdk_toplevel_lower (GdkToplevel *toplevel)
|
||||
*
|
||||
* Sets keyboard focus to @surface.
|
||||
*
|
||||
* In most cases, [method@Gtk.Window.present_with_time] should be
|
||||
* used on a [class@Gtk.Window], rather than calling this function.
|
||||
* In most cases, [gtk_window_present_with_time()](../gtk4/method.Window.present_with_time.html)
|
||||
* should be used on a [GtkWindow](../gtk4/class.Window.html), rather than
|
||||
* calling this function.
|
||||
*/
|
||||
void
|
||||
gdk_toplevel_focus (GdkToplevel *toplevel,
|
||||
@@ -437,8 +438,8 @@ gdk_toplevel_set_title (GdkToplevel *toplevel,
|
||||
* Sets the startup notification ID.
|
||||
*
|
||||
* When using GTK, typically you should use
|
||||
* [method@Gtk.Window.set_startup_id] instead of this
|
||||
* low-level function.
|
||||
* [gtk_window_set_startup_id()](../gtk4/method.Window.set_startup_id.html)
|
||||
* instead of this low-level function.
|
||||
*/
|
||||
void
|
||||
gdk_toplevel_set_startup_id (GdkToplevel *toplevel,
|
||||
@@ -461,8 +462,8 @@ gdk_toplevel_set_startup_id (GdkToplevel *toplevel,
|
||||
* allows the window manager to do things like center @surface
|
||||
* on @parent and keep @surface above @parent.
|
||||
*
|
||||
* See [method@Gtk.Window.set_transient_for] if you’re using
|
||||
* [class@Gtk.Window] or [class@Gtk.Dialog].
|
||||
* See [gtk_window_set_transient_for()](../gtk4/method.Window.set_transient_for.html)
|
||||
* if you’re using [GtkWindow](../gtk4/class.Window.html).
|
||||
*/
|
||||
void
|
||||
gdk_toplevel_set_transient_for (GdkToplevel *toplevel,
|
||||
|
||||
+296
-67
@@ -24,10 +24,27 @@
|
||||
|
||||
#include "gdkvulkancontextprivate.h"
|
||||
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkdmabufformatsbuilderprivate.h"
|
||||
#include "gdkdmabuffourccprivate.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
static const GdkDebugKey gsk_vulkan_feature_keys[] = {
|
||||
{ "dmabuf", GDK_VULKAN_FEATURE_DMABUF, "Never import Dmabufs" },
|
||||
{ "ycbcr", GDK_VULKAN_FEATURE_YCBCR, "Do not support Ycbcr textures" },
|
||||
{ "descriptor-indexing", GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING, "Force slow descriptor set layout codepath" },
|
||||
{ "dynamic-indexing", GDK_VULKAN_FEATURE_DYNAMIC_INDEXING, "Hardcode small number of buffer and texture arrays" },
|
||||
{ "nonuniform-indexing", GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING, "Split draw calls to ensure uniform texture accesses" },
|
||||
{ "semaphore-export", GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT, "Disable sync of exported dmabufs" },
|
||||
{ "semaphore-import", GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT, "Disable sync of imported dmabufs" },
|
||||
{ "incremental-present", GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT, "Do not send damage regions" },
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* GdkVulkanContext:
|
||||
*
|
||||
@@ -60,9 +77,6 @@ struct _GdkVulkanContextPrivate {
|
||||
guint n_images;
|
||||
VkImage *images;
|
||||
cairo_region_t **regions;
|
||||
|
||||
gboolean has_present_region;
|
||||
|
||||
#endif
|
||||
|
||||
guint32 draw_index;
|
||||
@@ -533,6 +547,74 @@ physical_device_supports_extension (VkPhysicalDevice device,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
physical_device_check_features (VkPhysicalDevice device,
|
||||
GdkVulkanFeatures *out_features)
|
||||
{
|
||||
VkPhysicalDeviceVulkan12Features v12_features = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
};
|
||||
VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcr_features = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
|
||||
.pNext = &v12_features
|
||||
};
|
||||
VkPhysicalDeviceFeatures2 features = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
||||
.pNext = &ycbcr_features
|
||||
};
|
||||
VkExternalSemaphoreProperties semaphore_props = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
|
||||
};
|
||||
|
||||
vkGetPhysicalDeviceFeatures2 (device, &features);
|
||||
vkGetPhysicalDeviceExternalSemaphoreProperties (device,
|
||||
&(VkPhysicalDeviceExternalSemaphoreInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
|
||||
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
|
||||
},
|
||||
&semaphore_props);
|
||||
|
||||
*out_features = 0;
|
||||
|
||||
if (features.features.shaderUniformBufferArrayDynamicIndexing &&
|
||||
features.features.shaderSampledImageArrayDynamicIndexing)
|
||||
*out_features |= GDK_VULKAN_FEATURE_DYNAMIC_INDEXING;
|
||||
|
||||
if (v12_features.descriptorIndexing &&
|
||||
v12_features.descriptorBindingPartiallyBound &&
|
||||
v12_features.descriptorBindingVariableDescriptorCount &&
|
||||
v12_features.descriptorBindingSampledImageUpdateAfterBind &&
|
||||
v12_features.descriptorBindingStorageBufferUpdateAfterBind)
|
||||
*out_features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
|
||||
else if (physical_device_supports_extension (device, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
*out_features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
|
||||
|
||||
if (v12_features.shaderSampledImageArrayNonUniformIndexing &&
|
||||
v12_features.shaderStorageBufferArrayNonUniformIndexing)
|
||||
*out_features |= GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING;
|
||||
|
||||
if (ycbcr_features.samplerYcbcrConversion)
|
||||
*out_features |= GDK_VULKAN_FEATURE_YCBCR;
|
||||
|
||||
if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME) &&
|
||||
physical_device_supports_extension (device, VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME))
|
||||
*out_features |= GDK_VULKAN_FEATURE_DMABUF;
|
||||
|
||||
if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME))
|
||||
{
|
||||
if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT)
|
||||
*out_features |= GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT;
|
||||
|
||||
if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)
|
||||
*out_features |= GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT;
|
||||
}
|
||||
|
||||
if (physical_device_supports_extension (device, VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME))
|
||||
*out_features |= GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
GdkMemoryDepth depth,
|
||||
@@ -578,42 +660,38 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context,
|
||||
GdkVulkanContext *context = GDK_VULKAN_CONTEXT (draw_context);
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (draw_context);
|
||||
VkPresentRegionsKHR *regionsptr = VK_NULL_HANDLE;
|
||||
VkPresentRegionsKHR regions;
|
||||
GdkDisplay *display = gdk_draw_context_get_display (draw_context);
|
||||
VkRectLayerKHR *rectangles;
|
||||
double scale;
|
||||
int n_regions;
|
||||
|
||||
scale = gdk_surface_get_scale (surface);
|
||||
n_regions = cairo_region_num_rectangles (painted);
|
||||
rectangles = g_alloca (sizeof (VkRectLayerKHR) * n_regions);
|
||||
|
||||
for (int i = 0; i < n_regions; i++)
|
||||
if (display->vulkan_features & GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT)
|
||||
{
|
||||
cairo_rectangle_int_t r;
|
||||
double scale;
|
||||
|
||||
cairo_region_get_rectangle (painted, i, &r);
|
||||
scale = gdk_surface_get_scale (surface);
|
||||
n_regions = cairo_region_num_rectangles (painted);
|
||||
rectangles = g_alloca (sizeof (VkRectLayerKHR) * n_regions);
|
||||
|
||||
rectangles[i] = (VkRectLayerKHR) {
|
||||
.layer = 0,
|
||||
.offset.x = (int) floor (r.x * scale),
|
||||
.offset.y = (int) floor (r.y * scale),
|
||||
.extent.width = (int) ceil (r.width * scale),
|
||||
.extent.height = (int) ceil (r.height * scale),
|
||||
};
|
||||
for (int i = 0; i < n_regions; i++)
|
||||
{
|
||||
cairo_rectangle_int_t r;
|
||||
|
||||
cairo_region_get_rectangle (painted, i, &r);
|
||||
|
||||
rectangles[i] = (VkRectLayerKHR) {
|
||||
.layer = 0,
|
||||
.offset.x = (int) floor (r.x * scale),
|
||||
.offset.y = (int) floor (r.y * scale),
|
||||
.extent.width = (int) ceil (r.width * scale),
|
||||
.extent.height = (int) ceil (r.height * scale),
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rectangles = NULL;
|
||||
n_regions = 0;
|
||||
}
|
||||
|
||||
regions = (VkPresentRegionsKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
|
||||
.swapchainCount = 1,
|
||||
.pRegions = &(VkPresentRegionKHR) {
|
||||
.rectangleCount = n_regions,
|
||||
.pRectangles = rectangles,
|
||||
},
|
||||
};
|
||||
|
||||
if (priv->has_present_region)
|
||||
regionsptr = ®ions;
|
||||
|
||||
GDK_VK_CHECK (vkQueuePresentKHR, gdk_vulkan_context_get_queue (context),
|
||||
&(VkPresentInfoKHR) {
|
||||
@@ -629,7 +707,14 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context,
|
||||
.pImageIndices = (uint32_t[]) {
|
||||
priv->draw_index
|
||||
},
|
||||
.pNext = regionsptr,
|
||||
.pNext = rectangles == NULL ? NULL : &(VkPresentRegionsKHR) {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
|
||||
.swapchainCount = 1,
|
||||
.pRegions = &(VkPresentRegionKHR) {
|
||||
.rectangleCount = n_regions,
|
||||
.pRectangles = rectangles,
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
cairo_region_destroy (priv->regions[priv->draw_index]);
|
||||
@@ -699,7 +784,7 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
VkBool32 supported;
|
||||
uint32_t i;
|
||||
|
||||
priv->vulkan_ref = gdk_display_ref_vulkan (display, error);
|
||||
priv->vulkan_ref = gdk_display_init_vulkan (display, error);
|
||||
if (!priv->vulkan_ref)
|
||||
return FALSE;
|
||||
|
||||
@@ -819,9 +904,6 @@ gdk_vulkan_context_real_init (GInitable *initable,
|
||||
if (priv->formats[GDK_MEMORY_U16].vk_format.format == VK_FORMAT_UNDEFINED)
|
||||
priv->formats[GDK_MEMORY_U16] = priv->formats[GDK_MEMORY_FLOAT32];
|
||||
|
||||
priv->has_present_region = physical_device_supports_extension (display->vk_physical_device,
|
||||
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
|
||||
if (!gdk_vulkan_context_check_swapchain (context, error))
|
||||
goto out_surface;
|
||||
|
||||
@@ -1122,10 +1204,8 @@ gdk_vulkan_save_pipeline_cache_cb (gpointer data)
|
||||
}
|
||||
|
||||
void
|
||||
gdk_vulkan_context_pipeline_cache_updated (GdkVulkanContext *self)
|
||||
gdk_display_vulkan_pipeline_cache_updated (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplay *display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self));
|
||||
|
||||
g_clear_handle_id (&display->vk_save_pipeline_cache_source, g_source_remove);
|
||||
display->vk_save_pipeline_cache_source = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE - 10,
|
||||
10, /* random choice that is not now */
|
||||
@@ -1150,14 +1230,6 @@ gdk_display_create_pipeline_cache (GdkDisplay *display)
|
||||
}
|
||||
}
|
||||
|
||||
VkPipelineCache
|
||||
gdk_vulkan_context_get_pipeline_cache (GdkVulkanContext *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (self), NULL);
|
||||
|
||||
return gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self))->vk_pipeline_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_vulkan_context_get_image_format:
|
||||
* @context: a `GdkVulkanContext`
|
||||
@@ -1268,6 +1340,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
const char *override;
|
||||
gboolean list_devices;
|
||||
int first, last;
|
||||
GdkVulkanFeatures skip_features;
|
||||
|
||||
uint32_t n_devices = 0;
|
||||
GDK_VK_CHECK(vkEnumeratePhysicalDevices, display->vk_instance, &n_devices, NULL);
|
||||
@@ -1287,6 +1360,10 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
first = 0;
|
||||
last = n_devices;
|
||||
|
||||
skip_features = gdk_parse_debug_var ("GDK_VULKAN_SKIP",
|
||||
gsk_vulkan_feature_keys,
|
||||
G_N_ELEMENTS (gsk_vulkan_feature_keys));
|
||||
|
||||
override = g_getenv ("GDK_VULKAN_DEVICE");
|
||||
list_devices = FALSE;
|
||||
if (override)
|
||||
@@ -1368,11 +1445,14 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
|
||||
for (i = first; i < last; i++)
|
||||
{
|
||||
GdkVulkanFeatures features, device_features;
|
||||
uint32_t n_queue_props;
|
||||
|
||||
if (!physical_device_supports_extension (devices[i], VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
if (!physical_device_check_features (devices[i], &device_features))
|
||||
continue;
|
||||
|
||||
features = device_features & ~skip_features;
|
||||
|
||||
vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, NULL);
|
||||
VkQueueFamilyProperties *queue_props = g_newa (VkQueueFamilyProperties, n_queue_props);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties (devices[i], &n_queue_props, queue_props);
|
||||
@@ -1381,18 +1461,22 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
if (queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
{
|
||||
GPtrArray *device_extensions;
|
||||
gboolean has_incremental_present;
|
||||
|
||||
has_incremental_present = physical_device_supports_extension (devices[i],
|
||||
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
|
||||
device_extensions = g_ptr_array_new ();
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
if (has_incremental_present)
|
||||
if (features & GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING)
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
|
||||
if (features & GDK_VULKAN_FEATURE_DMABUF)
|
||||
{
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME);
|
||||
}
|
||||
if (features & (GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT | GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT))
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
|
||||
if (features & GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT)
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
|
||||
|
||||
#define ENABLE_IF(flag) ((features & (flag)) ? VK_TRUE : VK_FALSE)
|
||||
GDK_DISPLAY_DEBUG (display, VULKAN, "Using Vulkan device %u, queue %u", i, j);
|
||||
if (GDK_VK_CHECK (vkCreateDevice, devices[i],
|
||||
&(VkDeviceCreateInfo) {
|
||||
@@ -1406,15 +1490,19 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
},
|
||||
.enabledExtensionCount = device_extensions->len,
|
||||
.ppEnabledExtensionNames = (const char * const *) device_extensions->pdata,
|
||||
.pNext = &(VkPhysicalDeviceVulkan12Features) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
|
||||
.shaderStorageBufferArrayNonUniformIndexing = VK_TRUE,
|
||||
.descriptorIndexing = VK_TRUE,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE,
|
||||
.pNext = &(VkPhysicalDeviceVulkan11Features) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
|
||||
.samplerYcbcrConversion = ENABLE_IF (GDK_VULKAN_FEATURE_YCBCR),
|
||||
.pNext = &(VkPhysicalDeviceVulkan12Features) {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.shaderSampledImageArrayNonUniformIndexing = ENABLE_IF (GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING),
|
||||
.shaderStorageBufferArrayNonUniformIndexing = ENABLE_IF (GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING),
|
||||
.descriptorIndexing = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingPartiallyBound = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingVariableDescriptorCount = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingSampledImageUpdateAfterBind = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
.descriptorBindingStorageBufferUpdateAfterBind = ENABLE_IF (GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING),
|
||||
}
|
||||
}
|
||||
},
|
||||
NULL,
|
||||
@@ -1423,12 +1511,26 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
g_ptr_array_unref (device_extensions);
|
||||
continue;
|
||||
}
|
||||
#undef ENABLE_IF
|
||||
|
||||
g_ptr_array_unref (device_extensions);
|
||||
|
||||
display->vk_physical_device = devices[i];
|
||||
vkGetDeviceQueue(display->vk_device, j, 0, &display->vk_queue);
|
||||
display->vk_queue_family_index = j;
|
||||
display->vulkan_features = features;
|
||||
|
||||
GDK_DISPLAY_DEBUG (display, VULKAN, "Enabled features (use GDK_VULKAN_SKIP env var to disable):");
|
||||
for (i = 0; i < G_N_ELEMENTS (gsk_vulkan_feature_keys); i++)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (display, VULKAN, " %s: %s",
|
||||
gsk_vulkan_feature_keys[i].key,
|
||||
(features & gsk_vulkan_feature_keys[i].value) ? "YES" :
|
||||
((skip_features & gsk_vulkan_feature_keys[i].value) ? "disabled via env var" :
|
||||
(((device_features & gsk_vulkan_feature_keys[i].value) == 0) ? "not supported" :
|
||||
"Hum, what? This should not happen.")));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1625,9 +1727,23 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_display_init_vulkan:
|
||||
* @display: a display
|
||||
* @error: A potential error message
|
||||
*
|
||||
* Initializes Vulkan and returns an error on failure.
|
||||
*
|
||||
* If Vulkan is already initialized, this function returns
|
||||
* %TRUE and increases the refcount of the existing instance.
|
||||
*
|
||||
* You need to gdk_display_unref_vulkan() to close it again.
|
||||
*
|
||||
* Returns: %TRUE if Vulkan is initialized.
|
||||
**/
|
||||
gboolean
|
||||
gdk_display_ref_vulkan (GdkDisplay *display,
|
||||
GError **error)
|
||||
gdk_display_init_vulkan (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
if (display->vulkan_refcount == 0)
|
||||
{
|
||||
@@ -1640,6 +1756,23 @@ gdk_display_ref_vulkan (GdkDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_display_ref_vulkan:
|
||||
* @display: a GdkDisplay
|
||||
*
|
||||
* Increases the refcount of an existing Vulkan instance.
|
||||
*
|
||||
* This function must not be called if Vulkan may not be initialized
|
||||
* yet, call gdk_display_init_vulkan() in that case.
|
||||
**/
|
||||
void
|
||||
gdk_display_ref_vulkan (GdkDisplay *display)
|
||||
{
|
||||
g_assert (display->vulkan_refcount > 0);
|
||||
|
||||
display->vulkan_refcount++;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_unref_vulkan (GdkDisplay *display)
|
||||
{
|
||||
@@ -1653,6 +1786,9 @@ gdk_display_unref_vulkan (GdkDisplay *display)
|
||||
if (display->vulkan_refcount > 0)
|
||||
return;
|
||||
|
||||
GDK_DEBUG (VULKAN, "Closing Vulkan instance");
|
||||
display->vulkan_features = 0;
|
||||
g_clear_pointer (&display->vk_dmabuf_formats, gdk_dmabuf_formats_unref);
|
||||
g_hash_table_iter_init (&iter, display->vk_shader_modules);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
@@ -1690,6 +1826,99 @@ gdk_display_unref_vulkan (GdkDisplay *display)
|
||||
display->vk_instance = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
|
||||
/* Hack. We don't include gsk/gsk.h here to avoid a build order problem
|
||||
* with the generated header gskenumtypes.h, so we need to hack around
|
||||
* a bit to access the gsk api we need.
|
||||
*/
|
||||
|
||||
typedef struct _GskRenderer GskRenderer;
|
||||
|
||||
extern GskRenderer * gsk_vulkan_renderer_new (void);
|
||||
extern gboolean gsk_renderer_realize_for_display (GskRenderer *renderer,
|
||||
GdkDisplay *display,
|
||||
GError **error);
|
||||
|
||||
GdkDmabufDownloader *
|
||||
gdk_vulkan_get_dmabuf_downloader (GdkDisplay *display,
|
||||
GdkDmabufFormatsBuilder *builder)
|
||||
{
|
||||
GdkDmabufFormatsBuilder *vulkan_builder;
|
||||
GskRenderer *renderer;
|
||||
VkDrmFormatModifierPropertiesEXT modifier_list[100];
|
||||
VkDrmFormatModifierPropertiesListEXT modifier_props = {
|
||||
.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
|
||||
.pNext = NULL,
|
||||
.pDrmFormatModifierProperties = modifier_list,
|
||||
};
|
||||
VkFormatProperties2 props = {
|
||||
.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
|
||||
.pNext = &modifier_props,
|
||||
};
|
||||
VkFormat vk_format;
|
||||
guint32 fourcc;
|
||||
GError *error = NULL;
|
||||
gsize i, j;
|
||||
|
||||
g_assert (display->vk_dmabuf_formats == NULL);
|
||||
|
||||
if (!gdk_display_init_vulkan (display, NULL))
|
||||
return NULL;
|
||||
|
||||
if ((display->vulkan_features & GDK_VULKAN_FEATURE_DMABUF) == 0)
|
||||
return NULL;
|
||||
|
||||
vulkan_builder = gdk_dmabuf_formats_builder_new ();
|
||||
|
||||
for (i = 0; gdk_dmabuf_vk_get_nth (i, &fourcc, &vk_format); i++)
|
||||
{
|
||||
if (vk_format == VK_FORMAT_UNDEFINED)
|
||||
continue;
|
||||
|
||||
modifier_props.drmFormatModifierCount = sizeof (modifier_list);
|
||||
vkGetPhysicalDeviceFormatProperties2 (display->vk_physical_device,
|
||||
vk_format,
|
||||
&props);
|
||||
g_warn_if_fail (modifier_props.drmFormatModifierCount < sizeof (modifier_list));
|
||||
for (j = 0; j < modifier_props.drmFormatModifierCount; j++)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (display, DMABUF,
|
||||
"Vulkan supports dmabuf format %.4s::%016llx with %u planes and features 0x%x",
|
||||
(char *) &fourcc,
|
||||
(long long unsigned) modifier_list[j].drmFormatModifier,
|
||||
modifier_list[j].drmFormatModifierPlaneCount,
|
||||
modifier_list[j].drmFormatModifierTilingFeatures);
|
||||
|
||||
if (modifier_list[j].drmFormatModifier == DRM_FORMAT_MOD_LINEAR)
|
||||
continue;
|
||||
|
||||
gdk_dmabuf_formats_builder_add_format (vulkan_builder,
|
||||
fourcc,
|
||||
modifier_list[j].drmFormatModifier);
|
||||
}
|
||||
}
|
||||
|
||||
display->vk_dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (vulkan_builder);
|
||||
|
||||
gdk_dmabuf_formats_builder_add_formats (builder, display->vk_dmabuf_formats);
|
||||
|
||||
renderer = gsk_vulkan_renderer_new ();
|
||||
|
||||
if (!gsk_renderer_realize_for_display (renderer, display, &error))
|
||||
{
|
||||
g_warning ("Failed to realize GL renderer: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (renderer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GDK_DMABUF_DOWNLOADER (renderer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
VkShaderModule
|
||||
gdk_display_get_vk_shader_module (GdkDisplay *self,
|
||||
const char *resource_name)
|
||||
|
||||
@@ -26,10 +26,6 @@
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_VULKAN_CONTEXT (gdk_vulkan_context_get_type ())
|
||||
@@ -44,37 +40,6 @@ GQuark gdk_vulkan_error_quark (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_vulkan_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#ifndef __GI_SCANNER__
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gdk_vulkan_strerror (VkResult result);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
VkInstance gdk_vulkan_context_get_instance (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
VkPhysicalDevice gdk_vulkan_context_get_physical_device (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
VkDevice gdk_vulkan_context_get_device (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
VkQueue gdk_vulkan_context_get_queue (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
uint32_t gdk_vulkan_context_get_queue_family_index (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
VkFormat gdk_vulkan_context_get_image_format (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
uint32_t gdk_vulkan_context_get_n_images (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
VkImage gdk_vulkan_context_get_image (GdkVulkanContext *context,
|
||||
guint id);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
uint32_t gdk_vulkan_context_get_draw_index (GdkVulkanContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
VkSemaphore gdk_vulkan_context_get_draw_semaphore (GdkVulkanContext *context);
|
||||
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
#endif /* __GI_SCANNER__ */
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkVulkanContext, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "gdkvulkancontext.h"
|
||||
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkdmabufprivate.h"
|
||||
#include "gdkdmabufdownloaderprivate.h"
|
||||
#include "gdkdrawcontextprivate.h"
|
||||
#include "gdkenums.h"
|
||||
|
||||
@@ -55,6 +57,8 @@ struct _GdkVulkanContextClass
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
|
||||
const char * gdk_vulkan_strerror (VkResult result);
|
||||
|
||||
static inline VkResult
|
||||
gdk_vulkan_handle_result (VkResult res,
|
||||
const char *called_function)
|
||||
@@ -69,15 +73,32 @@ gdk_vulkan_handle_result (VkResult res,
|
||||
|
||||
#define GDK_VK_CHECK(func, ...) gdk_vulkan_handle_result (func (__VA_ARGS__), G_STRINGIFY (func))
|
||||
|
||||
gboolean gdk_display_ref_vulkan (GdkDisplay *display,
|
||||
gboolean gdk_display_init_vulkan (GdkDisplay *display,
|
||||
GError **error);
|
||||
void gdk_display_ref_vulkan (GdkDisplay *display);
|
||||
void gdk_display_unref_vulkan (GdkDisplay *display);
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
GdkDmabufDownloader * gdk_vulkan_get_dmabuf_downloader (GdkDisplay *display,
|
||||
GdkDmabufFormatsBuilder *builder);
|
||||
#endif
|
||||
|
||||
VkShaderModule gdk_display_get_vk_shader_module (GdkDisplay *display,
|
||||
const char *resource_name);
|
||||
|
||||
VkPipelineCache gdk_vulkan_context_get_pipeline_cache (GdkVulkanContext *self);
|
||||
void gdk_vulkan_context_pipeline_cache_updated (GdkVulkanContext *self);
|
||||
void gdk_display_vulkan_pipeline_cache_updated (GdkDisplay *display);
|
||||
|
||||
VkInstance gdk_vulkan_context_get_instance (GdkVulkanContext *context);
|
||||
VkPhysicalDevice gdk_vulkan_context_get_physical_device (GdkVulkanContext *context);
|
||||
VkDevice gdk_vulkan_context_get_device (GdkVulkanContext *context);
|
||||
VkQueue gdk_vulkan_context_get_queue (GdkVulkanContext *context);
|
||||
uint32_t gdk_vulkan_context_get_queue_family_index (GdkVulkanContext *context);
|
||||
VkFormat gdk_vulkan_context_get_image_format (GdkVulkanContext *context);
|
||||
uint32_t gdk_vulkan_context_get_n_images (GdkVulkanContext *context);
|
||||
VkImage gdk_vulkan_context_get_image (GdkVulkanContext *context,
|
||||
guint id);
|
||||
uint32_t gdk_vulkan_context_get_draw_index (GdkVulkanContext *context);
|
||||
VkSemaphore gdk_vulkan_context_get_draw_semaphore (GdkVulkanContext *context);
|
||||
|
||||
GdkMemoryFormat gdk_vulkan_context_get_offscreen_format (GdkVulkanContext *context,
|
||||
GdkMemoryDepth depth);
|
||||
|
||||
+14
-5
@@ -137,8 +137,9 @@ gdk_load_png (GBytes *bytes,
|
||||
png_struct *png = NULL;
|
||||
png_info *info;
|
||||
guint width, height;
|
||||
gsize i, stride;
|
||||
int depth, color_type;
|
||||
int interlace, stride;
|
||||
int interlace;
|
||||
GdkMemoryFormat format;
|
||||
guchar *buffer = NULL;
|
||||
guchar **row_pointers = NULL;
|
||||
@@ -263,9 +264,14 @@ gdk_load_png (GBytes *bytes,
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
stride = width * bpp;
|
||||
if (stride % 8)
|
||||
stride += 8 - stride % 8;
|
||||
if (!g_size_checked_mul (&stride, width, bpp) ||
|
||||
!g_size_checked_add (&stride, stride, (8 - stride % 8) % 8))
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
_("Image stride too large for image size %ux%u"), width, height);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = g_try_malloc_n (height, stride);
|
||||
row_pointers = g_try_malloc_n (height, sizeof (char *));
|
||||
@@ -281,7 +287,7 @@ gdk_load_png (GBytes *bytes,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (i = 0; i < height; i++)
|
||||
row_pointers[i] = &buffer[i * stride];
|
||||
|
||||
png_read_image (png, row_pointers);
|
||||
@@ -413,6 +419,9 @@ gdk_save_png (GdkTexture *texture)
|
||||
if (!png)
|
||||
return NULL;
|
||||
|
||||
/* 2^31-1 is the maximum size for PNG files */
|
||||
png_set_user_limits (png, (1u << 31) - 1, (1u << 31) - 1);
|
||||
|
||||
info = png_create_info_struct (png);
|
||||
if (!info)
|
||||
{
|
||||
|
||||
@@ -188,7 +188,7 @@ _edge_snapping_motion (EdgeSnapping *self,
|
||||
edge_snapping_constrain_horizontal (self, change.x, &self->geometry, &new_window);
|
||||
}
|
||||
|
||||
/* Now constrain veritcally */
|
||||
/* Now constrain vertically */
|
||||
if (change.y)
|
||||
{
|
||||
edge_snapping_constrain_vertical (self, change.y, &self->workarea, &new_window, FALSE);
|
||||
|
||||
@@ -170,7 +170,7 @@ static int getting_events = 0;
|
||||
************************************************************/
|
||||
|
||||
/* The states in our state machine, see comments in select_thread_func()
|
||||
* for descriptiions of each state
|
||||
* for descriptions of each state
|
||||
*/
|
||||
typedef enum {
|
||||
BEFORE_START,
|
||||
|
||||
@@ -598,7 +598,7 @@ gdk_macos_gl_context_make_current (GdkGLContext *context,
|
||||
* are submitted.
|
||||
*
|
||||
* TODO: investigate if we need this because we may switch contexts
|
||||
* durring composition and only need it when returning to a
|
||||
* during composition and only need it when returning to a
|
||||
* previous context that uses the other context.
|
||||
*/
|
||||
if (current != NULL)
|
||||
|
||||
@@ -194,7 +194,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
|
||||
if ((image->width % cursor_scale != 0) ||
|
||||
(image->height % cursor_scale != 0))
|
||||
{
|
||||
g_warning (G_STRLOC " cursor image size (%dx%d) not an integer"
|
||||
g_warning (G_STRLOC " cursor image size (%dx%d) not an integer "
|
||||
"multiple of scale (%d)", image->width, image->height,
|
||||
cursor_scale);
|
||||
cursor_scale = 1;
|
||||
|
||||
@@ -1796,6 +1796,7 @@ static TranslationEntry translations[] = {
|
||||
{ FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } },
|
||||
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } },
|
||||
{ FALSE, "org.gnome.desktop.a11y.interface", "high-contrast", "high-contast", G_TYPE_NONE, { .b = FALSE } },
|
||||
{ FALSE, "org.gnome.desktop.a11y.interface", "show-status-shapes", "gtk-show-status-shapes", G_TYPE_BOOLEAN, { .b = FALSE } },
|
||||
/* Note, this setting doesn't exist, the portal and gsd fake it */
|
||||
{ FALSE, "org.gnome.fontconfig", "serial", "gtk-fontconfig-timestamp", G_TYPE_NONE, { .i = 0 } },
|
||||
};
|
||||
@@ -1845,13 +1846,6 @@ find_translation_entry_by_setting (const char *setting)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
high_contrast_changed (GdkDisplay *display)
|
||||
{
|
||||
gdk_display_setting_changed (display, "gtk-theme-name");
|
||||
gdk_display_setting_changed (display, "gtk-icon-theme-name");
|
||||
}
|
||||
|
||||
static void
|
||||
settings_changed (GSettings *settings,
|
||||
const char *key,
|
||||
@@ -1866,7 +1860,7 @@ settings_changed (GSettings *settings,
|
||||
if (entry->type != G_TYPE_NONE)
|
||||
gdk_display_setting_changed (display, entry->setting);
|
||||
else if (strcmp (key, "high-contrast") == 0)
|
||||
high_contrast_changed (display);
|
||||
gdk_display_setting_changed (display, "gtk-theme-name");
|
||||
else
|
||||
update_xft_settings (display);
|
||||
}
|
||||
|
||||
@@ -2859,6 +2859,7 @@ tablet_tool_handle_proximity_out (void *data,
|
||||
|
||||
gdk_device_update_tool (tablet->stylus_device, NULL);
|
||||
g_clear_object (&tablet->pointer_info.cursor);
|
||||
tablet->pointer_info.cursor_is_default = FALSE;
|
||||
}
|
||||
|
||||
static double *
|
||||
|
||||
@@ -1973,8 +1973,10 @@ gdk_wayland_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
return FALSE;
|
||||
|
||||
seat = gdk_display_get_default_seat (surface->display);
|
||||
wl_seat = gdk_wayland_seat_get_wl_seat (seat);
|
||||
if (!seat)
|
||||
return FALSE;
|
||||
|
||||
wl_seat = gdk_wayland_seat_get_wl_seat (seat);
|
||||
serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (seat), NULL);
|
||||
|
||||
gtk_surface1_titlebar_gesture (wayland_toplevel->display_server.gtk_surface,
|
||||
@@ -2155,15 +2157,14 @@ gdk_wayland_toplevel_focus (GdkToplevel *toplevel,
|
||||
GdkWaylandSurface *wayland_surface = GDK_WAYLAND_SURFACE (toplevel);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandSeat *seat =
|
||||
GDK_WAYLAND_SEAT (gdk_display_get_default_seat (display));
|
||||
gchar *startup_id = NULL;
|
||||
|
||||
startup_id = g_steal_pointer (&display_wayland->startup_notification_id);
|
||||
|
||||
if (display_wayland->xdg_activation)
|
||||
if (seat && display_wayland->xdg_activation)
|
||||
{
|
||||
GdkWaylandSeat *seat =
|
||||
GDK_WAYLAND_SEAT (gdk_display_get_default_seat (display));
|
||||
|
||||
/* If the focus request does not have a startup ID associated, get a
|
||||
* new token to activate the window.
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,7 @@ GTK has two clipboards - normal clipboard and primary clipboard
|
||||
Primary clipboard is only handled
|
||||
internally by GTK (it's not portable to Windows).
|
||||
|
||||
("C:" means clipboard client (requestor), "S:" means clipboard server (provider))
|
||||
("C:" means clipboard client (requester), "S:" means clipboard server (provider))
|
||||
("transmute" here means "change the format of some data"; this term is used here
|
||||
instead of "convert" to avoid clashing with the old g(t|d)k_selection_convert() APIs,
|
||||
which are completely unrelated)
|
||||
@@ -1356,7 +1356,7 @@ inner_clipboard_window_procedure (HWND hwnd,
|
||||
else if (returned_render->main_thread_data_handle)
|
||||
{
|
||||
BOOL set_data_succeeded;
|
||||
/* The requestor is holding the clipboard, no
|
||||
/* The requester is holding the clipboard, no
|
||||
* OpenClipboard() is required/possible
|
||||
*/
|
||||
GDK_NOTE (DND,
|
||||
|
||||
@@ -3029,7 +3029,7 @@ gdk_event_translate (MSG *msg,
|
||||
unset_bits |= GDK_TOPLEVEL_STATE_MAXIMIZED;
|
||||
|
||||
/*
|
||||
* If we are minizing, pause all surface layout computations, and re-start the
|
||||
* If we are minimizing, pause all surface layout computations, and re-start the
|
||||
* computation once we are coming out of a minimized state
|
||||
*/
|
||||
if (!(old_state & GDK_TOPLEVEL_STATE_MINIMIZED) && set_bits & GDK_TOPLEVEL_STATE_MINIMIZED)
|
||||
@@ -3045,7 +3045,7 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
/* Whenever one window changes iconified state we need to also
|
||||
* change the iconified state in all transient related windows,
|
||||
* as windows doesn't give icons for transient childrens.
|
||||
* as windows doesn't give icons for transient children.
|
||||
*/
|
||||
if ((old_state & GDK_TOPLEVEL_STATE_MINIMIZED) !=
|
||||
(new_state & GDK_TOPLEVEL_STATE_MINIMIZED))
|
||||
|
||||
@@ -211,7 +211,7 @@ struct _GdkW32DragMoveResizeContext
|
||||
gboolean revealed;
|
||||
|
||||
/* Arrays of GdkRectangle pairs, describing the areas of the virtual
|
||||
* desktop that trigger various AeroSnap window transofrmations
|
||||
* desktop that trigger various AeroSnap window transformations
|
||||
* Coordinates are GDK screen coordinates.
|
||||
*/
|
||||
GArray *halfleft_regions;
|
||||
|
||||
@@ -39,9 +39,17 @@
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (GdkX11GLContext, gdk_x11_gl_context, GDK_TYPE_GL_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_x11_gl_context_empty_frame (GdkDrawContext *draw_context)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
|
||||
{
|
||||
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
|
||||
|
||||
draw_context_class->empty_frame = gdk_x11_gl_context_empty_frame;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -39,6 +39,7 @@ static const struct {
|
||||
{"Gtk/CursorThemeSize", "gtk-cursor-theme-size"},
|
||||
{"Gtk/ColorScheme", "gtk-color-scheme"},
|
||||
{"Gtk/EnableAnimations", "gtk-enable-animations"},
|
||||
{"Gtk/ShowStatusStates", "gtk-show-status-shapes"},
|
||||
{"Xft/Antialias", "gtk-xft-antialias"},
|
||||
{"Xft/Hinting", "gtk-xft-hinting"},
|
||||
{"Xft/HintStyle", "gtk-xft-hintstyle"},
|
||||
|
||||
@@ -35,6 +35,7 @@ G_DEFINE_TYPE (GskBroadwayRenderer, gsk_broadway_renderer, GSK_TYPE_RENDERER)
|
||||
|
||||
static gboolean
|
||||
gsk_broadway_renderer_realize (GskRenderer *renderer,
|
||||
GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
|
||||
@@ -23,20 +23,24 @@ def replace_if_changed(new, old):
|
||||
gl_source_shaders = []
|
||||
ngl_source_shaders = []
|
||||
vulkan_compiled_shaders = []
|
||||
gpu_vulkan_compiled_shaders = []
|
||||
vulkan_shaders = []
|
||||
|
||||
for f in sys.argv[2:]:
|
||||
if f.endswith('.glsl'):
|
||||
if f.startswith('ngl'):
|
||||
ngl_source_shaders.append(f);
|
||||
if f.find('gsk/gpu') > -1:
|
||||
ngl_source_shaders.append(f)
|
||||
else:
|
||||
gl_source_shaders.append(f)
|
||||
elif f.endswith('.spv'):
|
||||
vulkan_compiled_shaders.append(f)
|
||||
if f.find('gsk/gpu') > -1:
|
||||
gpu_vulkan_compiled_shaders.append(f)
|
||||
else:
|
||||
vulkan_compiled_shaders.append(f)
|
||||
elif f.endswith('.frag') or f.endswith('.vert'):
|
||||
vulkan_shaders.append(f)
|
||||
else:
|
||||
sys.exit(-1) # FIXME: error message
|
||||
raise Exception(f"No idea what XML to generate for {f}")
|
||||
|
||||
xml = '''<?xml version='1.0' encoding='UTF-8'?>
|
||||
<gresources>
|
||||
@@ -50,7 +54,7 @@ for f in gl_source_shaders:
|
||||
xml += '\n'
|
||||
|
||||
for f in ngl_source_shaders:
|
||||
xml += ' <file alias=\'ngl/{0}\'>ngl/resources/{0}</file>\n'.format(os.path.basename(f))
|
||||
xml += ' <file alias=\'shaders/gl/{0}\'>gpu/shaders/{0}</file>\n'.format(os.path.basename(f))
|
||||
|
||||
xml += '\n'
|
||||
|
||||
@@ -59,6 +63,11 @@ for f in vulkan_compiled_shaders:
|
||||
|
||||
xml += '\n'
|
||||
|
||||
for f in gpu_vulkan_compiled_shaders:
|
||||
xml += ' <file alias=\'shaders/vulkan/{0}\'>gpu/shaders/{0}</file>\n'.format(os.path.basename(f))
|
||||
|
||||
xml += '\n'
|
||||
|
||||
for f in vulkan_shaders:
|
||||
xml += ' <file alias=\'vulkan/{0}\'>vulkan/resources/{0}</file>\n'.format(os.path.basename(f))
|
||||
|
||||
|
||||
+42
-23
@@ -1435,6 +1435,8 @@ gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case GL_RGBA8:
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
break;
|
||||
@@ -1477,12 +1479,14 @@ gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self)
|
||||
static GdkMemoryFormat
|
||||
memory_format_gl_format (GskGLCommandQueue *self,
|
||||
GdkMemoryFormat data_format,
|
||||
gboolean ensure_mipmap,
|
||||
gboolean *out_can_mipmap,
|
||||
GLint *gl_internalformat,
|
||||
GLenum *gl_format,
|
||||
GLenum *gl_type,
|
||||
GLint gl_swizzle[4])
|
||||
{
|
||||
GdkGLMemoryFlags flags;
|
||||
GdkGLMemoryFlags flags, required_flags;
|
||||
GdkMemoryFormat alt_format;
|
||||
const GdkMemoryFormat *fallbacks;
|
||||
gsize i;
|
||||
@@ -1491,20 +1495,27 @@ memory_format_gl_format (GskGLCommandQueue *self,
|
||||
if (gdk_memory_format_alpha (data_format) == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
data_format = gdk_memory_format_get_premultiplied (data_format);
|
||||
|
||||
required_flags = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
|
||||
if (ensure_mipmap)
|
||||
required_flags |= GDK_GL_FORMAT_RENDERABLE;
|
||||
|
||||
/* First, try the format itself */
|
||||
flags = gdk_gl_context_get_format_flags (self->context, data_format);
|
||||
if ((flags & (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)) == (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE))
|
||||
if ((flags & required_flags) == required_flags)
|
||||
{
|
||||
gdk_memory_format_gl_format (data_format,
|
||||
gdk_gl_context_get_use_es (self->context),
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
gl_swizzle);
|
||||
*out_can_mipmap = (flags & GDK_GL_FORMAT_RENDERABLE) ? TRUE : FALSE;
|
||||
return data_format;
|
||||
}
|
||||
|
||||
/* Second, try the potential RGBA format */
|
||||
if (gdk_memory_format_gl_rgba_format (data_format,
|
||||
gdk_gl_context_get_use_es (self->context),
|
||||
&alt_format,
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
@@ -1512,12 +1523,15 @@ memory_format_gl_format (GskGLCommandQueue *self,
|
||||
gl_swizzle))
|
||||
{
|
||||
flags = gdk_gl_context_get_format_flags (self->context, alt_format);
|
||||
if ((flags & (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)) == (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE))
|
||||
if ((flags & required_flags) == required_flags)
|
||||
{
|
||||
*out_can_mipmap = (flags & GDK_GL_FORMAT_RENDERABLE) ? TRUE : FALSE;
|
||||
|
||||
if (self->can_swizzle)
|
||||
return data_format;
|
||||
|
||||
gdk_memory_format_gl_format (alt_format,
|
||||
gdk_gl_context_get_use_es (self->context),
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
@@ -1532,13 +1546,16 @@ memory_format_gl_format (GskGLCommandQueue *self,
|
||||
for (i = 0; fallbacks[i] != -1; i++)
|
||||
{
|
||||
flags = gdk_gl_context_get_format_flags (self->context, fallbacks[i]);
|
||||
if (((flags & (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)) == (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)))
|
||||
if (((flags & required_flags) == required_flags))
|
||||
{
|
||||
gdk_memory_format_gl_format (fallbacks[i],
|
||||
gdk_gl_context_get_use_es (self->context),
|
||||
gl_internalformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
gl_swizzle);
|
||||
|
||||
*out_can_mipmap = (flags & GDK_GL_FORMAT_RENDERABLE) ? TRUE : FALSE;
|
||||
return fallbacks[i];
|
||||
}
|
||||
}
|
||||
@@ -1552,32 +1569,24 @@ static void
|
||||
gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
|
||||
GdkTexture *texture,
|
||||
int x,
|
||||
int y)
|
||||
int y,
|
||||
GdkMemoryFormat data_format,
|
||||
GLenum gl_format,
|
||||
GLenum gl_type,
|
||||
GLint gl_swizzle[4])
|
||||
|
||||
{
|
||||
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
|
||||
const guchar *data;
|
||||
gsize stride;
|
||||
GBytes *bytes;
|
||||
GdkTextureDownloader downloader;
|
||||
GdkMemoryFormat data_format;
|
||||
int width, height;
|
||||
GLint gl_internalformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
GLint gl_swizzle[4];
|
||||
gsize bpp;
|
||||
|
||||
data_format = gdk_texture_get_format (texture);
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
data_format = memory_format_gl_format (self,
|
||||
data_format,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type,
|
||||
gl_swizzle);
|
||||
|
||||
if (GSK_DEBUG_CHECK (FALLBACK) &&
|
||||
data_format != gdk_texture_get_format (texture))
|
||||
{
|
||||
@@ -1652,8 +1661,10 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
|
||||
|
||||
int
|
||||
gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
|
||||
gboolean ensure_mipmap,
|
||||
unsigned int n_chunks,
|
||||
GskGLTextureChunk *chunks)
|
||||
GskGLTextureChunk *chunks,
|
||||
gboolean *out_can_mipmap)
|
||||
{
|
||||
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
|
||||
int width, height;
|
||||
@@ -1684,7 +1695,7 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
|
||||
height = MIN (height, self->max_texture_size);
|
||||
}
|
||||
|
||||
texture_id = gsk_gl_command_queue_create_texture (self, width, height, GL_RGBA8);
|
||||
texture_id = gsk_gl_command_queue_create_texture (self, width, height, 0);
|
||||
if (texture_id == -1)
|
||||
return texture_id;
|
||||
|
||||
@@ -1698,6 +1709,8 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
|
||||
data_format = gdk_texture_get_format (chunks[0].texture);
|
||||
data_format = memory_format_gl_format (self,
|
||||
data_format,
|
||||
ensure_mipmap,
|
||||
out_can_mipmap,
|
||||
&gl_internalformat,
|
||||
&gl_format,
|
||||
&gl_type,
|
||||
@@ -1708,7 +1721,7 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
|
||||
for (unsigned int i = 0; i < n_chunks; i++)
|
||||
{
|
||||
GskGLTextureChunk *c = &chunks[i];
|
||||
gsk_gl_command_queue_do_upload_texture_chunk (self, c->texture, c->x, c->y);
|
||||
gsk_gl_command_queue_do_upload_texture_chunk (self, c->texture, c->x, c->y, data_format, gl_format, gl_type, gl_swizzle);
|
||||
}
|
||||
|
||||
/* Restore previous texture state if any */
|
||||
@@ -1726,9 +1739,15 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
|
||||
|
||||
int
|
||||
gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
|
||||
GdkTexture *texture)
|
||||
GdkTexture *texture,
|
||||
gboolean ensure_mipmap,
|
||||
gboolean *out_can_mipmap)
|
||||
{
|
||||
return gsk_gl_command_queue_upload_texture_chunks (self, 1, &(GskGLTextureChunk){ texture, 0, 0});
|
||||
return gsk_gl_command_queue_upload_texture_chunks (self,
|
||||
ensure_mipmap,
|
||||
1,
|
||||
&(GskGLTextureChunk){ texture, 0, 0},
|
||||
out_can_mipmap);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -313,7 +313,9 @@ void gsk_gl_command_queue_execute (GskGLCommandQueue
|
||||
const cairo_region_t *scissor,
|
||||
guint default_framebuffer);
|
||||
int gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
|
||||
GdkTexture *texture);
|
||||
GdkTexture *texture,
|
||||
gboolean ensure_mipmap,
|
||||
gboolean *out_can_mipmap);
|
||||
int gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
|
||||
int width,
|
||||
int height,
|
||||
@@ -327,8 +329,10 @@ typedef struct {
|
||||
} GskGLTextureChunk;
|
||||
|
||||
int gsk_gl_command_queue_upload_texture_chunks(GskGLCommandQueue *self,
|
||||
gboolean ensure_mipmap,
|
||||
unsigned int n_chunks,
|
||||
GskGLTextureChunk *chunks);
|
||||
GskGLTextureChunk *chunks,
|
||||
gboolean *out_can_mipmap);
|
||||
|
||||
guint gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self);
|
||||
gboolean gsk_gl_command_queue_create_render_target (GskGLCommandQueue *self,
|
||||
|
||||
+17
-7
@@ -925,6 +925,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
guint texture_id;
|
||||
int height;
|
||||
int width;
|
||||
gboolean can_mipmap = FALSE;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
|
||||
@@ -938,17 +939,20 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
t = gdk_texture_get_render_data (texture, self);
|
||||
if (t && t->texture_id)
|
||||
{
|
||||
if (ensure_mipmap && !t->has_mipmap)
|
||||
if (ensure_mipmap && t->can_mipmap && !t->has_mipmap)
|
||||
{
|
||||
glBindTexture (GL_TEXTURE_2D, t->texture_id);
|
||||
glGenerateMipmap (GL_TEXTURE_2D);
|
||||
t->has_mipmap = TRUE;
|
||||
}
|
||||
|
||||
return t->texture_id;
|
||||
if (!ensure_mipmap || t->has_mipmap)
|
||||
return t->texture_id;
|
||||
|
||||
gdk_texture_clear_render_data (texture);
|
||||
}
|
||||
|
||||
if (GDK_IS_DMABUF_TEXTURE (texture))
|
||||
if (GDK_IS_DMABUF_TEXTURE (texture) && !ensure_mipmap)
|
||||
{
|
||||
texture_id = gsk_gl_driver_import_dmabuf_texture (self, GDK_DMABUF_TEXTURE (texture));
|
||||
}
|
||||
@@ -975,7 +979,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
*/
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, GDK_TEXTURE (downloaded_texture));
|
||||
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, GDK_TEXTURE (downloaded_texture), ensure_mipmap, &can_mipmap);
|
||||
}
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
@@ -984,8 +988,10 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
t = gsk_gl_texture_new (texture_id,
|
||||
width, height,
|
||||
self->current_frame_id);
|
||||
t->can_mipmap = can_mipmap;
|
||||
if (ensure_mipmap)
|
||||
{
|
||||
g_assert (can_mipmap);
|
||||
glBindTexture (GL_TEXTURE_2D, t->texture_id);
|
||||
glGenerateMipmap (GL_TEXTURE_2D);
|
||||
t->has_mipmap = TRUE;
|
||||
@@ -1230,7 +1236,7 @@ gsk_gl_driver_release_render_target (GskGLDriver *self,
|
||||
* @shader: the shader to lookup or load
|
||||
* @error: a location for a `GError`
|
||||
*
|
||||
* Attepts to load @shader from the shader cache.
|
||||
* Attempts to load @shader from the shader cache.
|
||||
*
|
||||
* If it has not been loaded, then it will compile the shader on demand.
|
||||
*
|
||||
@@ -1433,6 +1439,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
GdkMemoryTexture *memtex2 = NULL;
|
||||
GdkMemoryTexture *memtex3 = NULL;
|
||||
GdkMemoryTexture *memtex4 = NULL;
|
||||
gboolean can_mipmap = TRUE, slice_can_mipmap;
|
||||
|
||||
g_assert (GSK_IS_GL_DRIVER (self));
|
||||
g_assert (GDK_IS_TEXTURE (texture));
|
||||
@@ -1694,7 +1701,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
n_chunks++;
|
||||
}
|
||||
|
||||
texture_id = gsk_gl_command_queue_upload_texture_chunks (self->command_queue, n_chunks, chunks);
|
||||
texture_id = gsk_gl_command_queue_upload_texture_chunks (self->command_queue, TRUE, n_chunks, chunks, &slice_can_mipmap);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, texture_id);
|
||||
glGenerateMipmap (GL_TEXTURE_2D);
|
||||
@@ -1707,10 +1714,12 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
GdkTexture *subtex;
|
||||
|
||||
subtex = gdk_memory_texture_new_subtexture (memtex, x, y, slice_width, slice_height);
|
||||
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, subtex);
|
||||
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, subtex, FALSE, &slice_can_mipmap);
|
||||
g_object_unref (subtex);
|
||||
}
|
||||
|
||||
can_mipmap &= slice_can_mipmap;
|
||||
|
||||
slices[slice_index].rect.x = x;
|
||||
slices[slice_index].rect.y = y;
|
||||
slices[slice_index].rect.width = slice_width;
|
||||
@@ -1737,6 +1746,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
t = gsk_gl_texture_new (0,
|
||||
tex_width, tex_height,
|
||||
self->current_frame_id);
|
||||
t->can_mipmap = can_mipmap;
|
||||
t->has_mipmap = ensure_mipmap;
|
||||
|
||||
/* Use gsk_gl_texture_free() as destroy notify here since we are
|
||||
|
||||
@@ -202,6 +202,7 @@ gsk_gl_driver_get_texture_by_id (GskGLDriver *self,
|
||||
* gsk_gl_driver_lookup_texture:
|
||||
* @self: a `GskGLDriver`
|
||||
* @key: the key for the texture
|
||||
* @has_mipmap: (out): Return location for whether the texture has a mipmap
|
||||
*
|
||||
* Looks up a texture in the texture cache by @key.
|
||||
*
|
||||
@@ -211,7 +212,8 @@ gsk_gl_driver_get_texture_by_id (GskGLDriver *self,
|
||||
*/
|
||||
static inline guint
|
||||
gsk_gl_driver_lookup_texture (GskGLDriver *self,
|
||||
const GskTextureKey *key)
|
||||
const GskTextureKey *key,
|
||||
gboolean *has_mipmap)
|
||||
{
|
||||
gpointer id;
|
||||
|
||||
@@ -222,6 +224,9 @@ gsk_gl_driver_lookup_texture (GskGLDriver *self,
|
||||
if (texture != NULL)
|
||||
texture->last_used_in_frame = self->current_frame_id;
|
||||
|
||||
if (has_mipmap)
|
||||
*has_mipmap = texture ? texture->has_mipmap : FALSE;
|
||||
|
||||
return GPOINTER_TO_UINT (id);
|
||||
}
|
||||
|
||||
|
||||
+3
-57
@@ -162,6 +162,7 @@ gsk_gl_renderer_new (void)
|
||||
|
||||
static gboolean
|
||||
gsk_gl_renderer_realize (GskRenderer *renderer,
|
||||
GdkDisplay *display,
|
||||
GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
@@ -169,7 +170,6 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
|
||||
GskGLRenderer *self = (GskGLRenderer *)renderer;
|
||||
GdkGLContext *context = NULL;
|
||||
GskGLDriver *driver = NULL;
|
||||
GdkDisplay *display;
|
||||
gboolean ret = FALSE;
|
||||
gboolean debug_shaders = FALSE;
|
||||
GdkGLAPI api;
|
||||
@@ -182,15 +182,9 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
|
||||
g_assert (self->command_queue == NULL);
|
||||
|
||||
if (surface == NULL)
|
||||
{
|
||||
display = gdk_display_get_default (); /* FIXME: allow different displays somehow ? */
|
||||
context = gdk_display_create_gl_context (display, error);
|
||||
}
|
||||
context = gdk_display_create_gl_context (display, error);
|
||||
else
|
||||
{
|
||||
display = gdk_surface_get_display (surface);
|
||||
context = gdk_surface_create_gl_context (surface, error);
|
||||
}
|
||||
context = gdk_surface_create_gl_context (surface, error);
|
||||
|
||||
if (!context || !gdk_gl_context_realize (context, error))
|
||||
goto failure;
|
||||
@@ -537,51 +531,3 @@ gsk_gl_renderer_try_compile_gl_shader (GskGLRenderer *renderer,
|
||||
return program != NULL;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GskRenderer parent_instance;
|
||||
} GskNglRenderer;
|
||||
|
||||
typedef struct {
|
||||
GskRendererClass parent_class;
|
||||
} GskNglRendererClass;
|
||||
|
||||
G_DEFINE_TYPE (GskNglRenderer, gsk_ngl_renderer, GSK_TYPE_RENDERER)
|
||||
|
||||
static void
|
||||
gsk_ngl_renderer_init (GskNglRenderer *renderer)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_ngl_renderer_realize (GskRenderer *renderer,
|
||||
GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"please use the GL renderer instead");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_ngl_renderer_class_init (GskNglRendererClass *class)
|
||||
{
|
||||
GSK_RENDERER_CLASS (class)->realize = gsk_ngl_renderer_realize;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_ngl_renderer_new:
|
||||
*
|
||||
* Same as gsk_gl_renderer_new().
|
||||
*
|
||||
* Returns: (transfer full): a new GL renderer
|
||||
*
|
||||
* Deprecated: 4.4: Use gsk_gl_renderer_new()
|
||||
*/
|
||||
GskRenderer *
|
||||
gsk_ngl_renderer_new (void)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
return g_object_new (gsk_ngl_renderer_get_type (), NULL);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
}
|
||||
|
||||
+10
-4
@@ -20,7 +20,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GSK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#include <gsk/gsk.h>
|
||||
#define GSK_INCLUDE_WARNING(x) GDK_DEPRECATED_IN_4_14_FOR("#include <gsk/gsk.h> instead of <gsk/gl/gskglrenderer.h> to avoid this warning")
|
||||
#else
|
||||
#include <gsk/gsktypes.h>
|
||||
#define GSK_INCLUDE_WARNING(x) x
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -35,14 +41,14 @@ G_BEGIN_DECLS
|
||||
typedef struct _GskGLRenderer GskGLRenderer;
|
||||
typedef struct _GskGLRendererClass GskGLRendererClass;
|
||||
|
||||
GDK_AVAILABLE_IN_4_2
|
||||
GSK_INCLUDE_WARNING(GDK_AVAILABLE_IN_4_2)
|
||||
GType gsk_gl_renderer_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_4_2
|
||||
GSK_INCLUDE_WARNING(GDK_AVAILABLE_IN_4_2)
|
||||
GskRenderer *gsk_gl_renderer_new (void);
|
||||
|
||||
GDK_DEPRECATED_IN_4_4_FOR (gsk_gl_renderer_get_type)
|
||||
GSK_INCLUDE_WARNING(GDK_AVAILABLE_IN_ALL)
|
||||
GType gsk_ngl_renderer_get_type (void) G_GNUC_CONST;
|
||||
GDK_DEPRECATED_IN_4_4_FOR (gsk_gl_renderer_new)
|
||||
GSK_INCLUDE_WARNING(GDK_AVAILABLE_IN_ALL)
|
||||
GskRenderer *gsk_ngl_renderer_new (void);
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "gskglrenderer.h"
|
||||
|
||||
#include "gskglshader.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean gsk_gl_renderer_try_compile_gl_shader (GskGLRenderer *renderer,
|
||||
|
||||
+42
-38
@@ -830,8 +830,8 @@ rounded_rect_scale_corners (const GskRoundedRect *rect,
|
||||
{
|
||||
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);
|
||||
out_rect->corner[i].width = rect->corner[i].width * fabsf (scale_x);
|
||||
out_rect->corner[i].height = rect->corner[i].height * fabsf (scale_y);
|
||||
}
|
||||
|
||||
if (scale_x < 0)
|
||||
@@ -1173,8 +1173,8 @@ 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 * fabsf (scale_x));
|
||||
int surface_height = ceilf (node->bounds.size.height * fabsf (scale_y));
|
||||
GdkTexture *texture;
|
||||
cairo_surface_t *surface;
|
||||
cairo_surface_t *rendered_surface;
|
||||
@@ -1190,7 +1190,7 @@ 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);
|
||||
texture_id = gsk_gl_driver_lookup_texture (job->driver, &key, NULL);
|
||||
|
||||
if (texture_id != 0)
|
||||
goto done;
|
||||
@@ -1203,11 +1203,11 @@ 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, fabsf (scale_x), fabsf (scale_y));
|
||||
cr = cairo_create (rendered_surface);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_translate (cr, - floorf (node->bounds.origin.x), - floorf (node->bounds.origin.y));
|
||||
cairo_translate (cr, - node->bounds.origin.x, - node->bounds.origin.y);
|
||||
/* Render nodes don't modify state, so casting away the const is fine here */
|
||||
gsk_render_node_draw_fallback ((GskRenderNode *)node, cr);
|
||||
cairo_restore (cr);
|
||||
@@ -1217,16 +1217,16 @@ 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, fabsf (scale_x), fabsf (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_translate (cr, scale_x < 0 ? - surface_width / fabsf (scale_x) : 0,
|
||||
scale_y < 0 ? 0 : - surface_height / fabsf (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 / fabsf (scale_x), surface_height / fabsf (scale_y));
|
||||
cairo_fill (cr);
|
||||
cairo_restore (cr);
|
||||
cairo_destroy (cr);
|
||||
@@ -1432,10 +1432,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 * fabsf (scale_x),
|
||||
texture_height * fabsf (scale_y),
|
||||
blur_radius * fabsf (scale_x),
|
||||
blur_radius * fabsf (scale_y));
|
||||
init_full_texture_region (offscreen);
|
||||
}
|
||||
|
||||
@@ -2019,9 +2019,9 @@ result_is_axis_aligned (GskTransform *transform,
|
||||
for (guint i = 0; i < 4; i++)
|
||||
{
|
||||
p = graphene_quad_get_point (&q, i);
|
||||
if (fabs (p->x - b1.x) > FLT_EPSILON && fabs (p->x - b2.x) > FLT_EPSILON)
|
||||
if (fabsf (p->x - b1.x) > FLT_EPSILON && fabsf (p->x - b2.x) > FLT_EPSILON)
|
||||
return FALSE;
|
||||
if (fabs (p->y - b1.y) > FLT_EPSILON && fabs (p->y - b2.y) > FLT_EPSILON)
|
||||
if (fabsf (p->y - b1.y) > FLT_EPSILON && fabsf (p->y - b2.y) > FLT_EPSILON)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -2216,7 +2216,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
|
||||
key.scale_x = scale_x;
|
||||
key.scale_y = scale_y;
|
||||
|
||||
blurred_texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
|
||||
blurred_texture_id = gsk_gl_driver_lookup_texture (job->driver, &key, NULL);
|
||||
|
||||
if (blurred_texture_id == 0)
|
||||
{
|
||||
@@ -2304,8 +2304,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 * fabsf (scale_x),
|
||||
blur_radius * fabsf (scale_y));
|
||||
|
||||
gsk_gl_driver_release_render_target (job->driver, render_target, TRUE);
|
||||
|
||||
@@ -2501,8 +2501,8 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
|
||||
do_slicing = TRUE;
|
||||
}
|
||||
|
||||
texture_width = (int)ceil ((scaled_outline.bounds.size.width + blur_extra) * scale_x);
|
||||
texture_height = (int)ceil ((scaled_outline.bounds.size.height + blur_extra) * scale_y);
|
||||
texture_width = (int)ceilf ((scaled_outline.bounds.size.width + blur_extra) * scale_x);
|
||||
texture_height = (int)ceilf ((scaled_outline.bounds.size.height + blur_extra) * scale_y);
|
||||
|
||||
scaled_outline.bounds.origin.x = extra_blur_pixels_x;
|
||||
scaled_outline.bounds.origin.y = extra_blur_pixels_y;
|
||||
@@ -2577,8 +2577,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 * fabsf (scale_x),
|
||||
blur_radius * fabsf (scale_y));
|
||||
|
||||
gsk_gl_shadow_library_insert (job->driver->shadows_library,
|
||||
&scaled_outline,
|
||||
@@ -2834,7 +2834,7 @@ 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)));
|
||||
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabsf (job->scale_x), fabsf (job->scale_y)));
|
||||
|
||||
if (!gsk_gl_render_job_visit_node_with_offscreen (job, start_node, &offscreen_start))
|
||||
{
|
||||
@@ -2964,7 +2964,7 @@ gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
|
||||
const PangoFont *font = gsk_text_node_get_font (node);
|
||||
const PangoGlyphInfo *glyphs = gsk_text_node_get_glyphs (node, NULL);
|
||||
const graphene_point_t *offset = gsk_text_node_get_offset (node);
|
||||
float text_scale = MAX (fabs (job->scale_x), fabs (job->scale_y)); /* TODO: Fix for uneven scales? */
|
||||
float text_scale = MAX (fabsf (job->scale_x), fabsf (job->scale_y)); /* TODO: Fix for uneven scales? */
|
||||
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
|
||||
float x = offset->x + job->offset_x;
|
||||
float y = offset->y + job->offset_y;
|
||||
@@ -3216,7 +3216,7 @@ gsk_gl_render_job_visit_blur_node (GskGLRenderJob *job,
|
||||
key.scale_x = job->scale_x;
|
||||
key.scale_y = job->scale_y;
|
||||
|
||||
offscreen.texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
|
||||
offscreen.texture_id = gsk_gl_driver_lookup_texture (job->driver, &key, NULL);
|
||||
cache_texture = offscreen.texture_id == 0;
|
||||
|
||||
blur_node (job,
|
||||
@@ -3263,7 +3263,7 @@ 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)));
|
||||
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabsf (job->scale_x), fabsf (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. */
|
||||
@@ -3344,8 +3344,8 @@ gsk_gl_render_job_texture_mask_for_color (GskGLRenderJob *job,
|
||||
gboolean use_mipmap;
|
||||
guint16 cc[4];
|
||||
|
||||
use_mipmap = (scale_x * fabs (job->scale_x)) < 0.5 ||
|
||||
(scale_y * fabs (job->scale_y)) < 0.5;
|
||||
use_mipmap = (scale_x * fabsf (job->scale_x)) < 0.5 ||
|
||||
(scale_y * fabsf (job->scale_y)) < 0.5;
|
||||
|
||||
rgba_to_half (rgba, cc);
|
||||
gsk_gl_render_job_upload_texture (job, texture, use_mipmap, &offscreen);
|
||||
@@ -3396,7 +3396,7 @@ 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)));
|
||||
gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, fabsf (job->scale_x), fabsf (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.
|
||||
@@ -3664,8 +3664,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 * fabsf (job->scale_x)) < 0.5 ||
|
||||
(scale_y * fabsf (job->scale_y)) < 0.5;
|
||||
|
||||
if G_LIKELY (texture->width <= max_texture_size &&
|
||||
texture->height <= max_texture_size)
|
||||
@@ -3771,6 +3771,8 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
float u0, u1, v0, v1;
|
||||
GskTextureKey key;
|
||||
guint texture_id;
|
||||
gboolean need_mipmap;
|
||||
gboolean has_mipmap;
|
||||
|
||||
gsk_gl_render_job_untransform_bounds (job, &job->current_clip->rect.bounds, &clip_rect);
|
||||
|
||||
@@ -3783,9 +3785,11 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
key.scale_x = 1.;
|
||||
key.scale_y = 1.;
|
||||
|
||||
texture_id = gsk_gl_driver_lookup_texture (job->driver, &key);
|
||||
need_mipmap = (filter == GSK_SCALING_FILTER_TRILINEAR);
|
||||
|
||||
if (texture_id != 0)
|
||||
texture_id = gsk_gl_driver_lookup_texture (job->driver, &key, &has_mipmap);
|
||||
|
||||
if (texture_id != 0 && (!need_mipmap || has_mipmap))
|
||||
goto render_texture;
|
||||
|
||||
viewport = GRAPHENE_RECT_INIT (0, 0,
|
||||
@@ -3816,7 +3820,7 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
{
|
||||
gpointer sync;
|
||||
|
||||
texture_id = gsk_gl_driver_load_texture (job->driver, texture, filter == GSK_SCALING_FILTER_TRILINEAR);
|
||||
texture_id = gsk_gl_driver_load_texture (job->driver, texture, need_mipmap);
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture) && texture_id == gdk_gl_texture_get_id (GDK_GL_TEXTURE (texture)))
|
||||
sync = gdk_gl_texture_get_sync (GDK_GL_TEXTURE (texture));
|
||||
@@ -3853,7 +3857,7 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
|
||||
GskGLTextureSlice *slices = NULL;
|
||||
guint n_slices = 0;
|
||||
|
||||
gsk_gl_driver_slice_texture (job->driver, texture, filter == GSK_SCALING_FILTER_TRILINEAR, &slices, &n_slices);
|
||||
gsk_gl_driver_slice_texture (job->driver, texture, need_mipmap, &slices, &n_slices);
|
||||
|
||||
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit)))
|
||||
{
|
||||
@@ -4352,7 +4356,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
}
|
||||
|
||||
/* Check if we've already cached the drawn texture. */
|
||||
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key);
|
||||
cached_id = gsk_gl_driver_lookup_texture (job->driver, &key, NULL);
|
||||
|
||||
if (cached_id != 0)
|
||||
{
|
||||
|
||||
@@ -117,9 +117,8 @@ gsk_gl_texture_library_real_compact (GskGLTextureLibrary *self,
|
||||
g_hash_table_iter_remove (&iter);
|
||||
dropped++;
|
||||
}
|
||||
|
||||
if (periodic_scan)
|
||||
entry->accessed = FALSE;
|
||||
else if (periodic_scan)
|
||||
entry->accessed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +439,6 @@ gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
|
||||
|
||||
entry->texture = texture;
|
||||
entry->is_atlased = FALSE;
|
||||
entry->accessed = TRUE;
|
||||
entry->area.x = padding / (float) (padding + width + padding);
|
||||
entry->area.y = padding / (float) (padding + height + padding);
|
||||
entry->area.x2 = (padding + width) / (float) (padding + width + padding);
|
||||
|
||||
@@ -73,6 +73,8 @@ struct _GskGLTexture
|
||||
|
||||
/* Set when used by an atlas so we don't drop the texture */
|
||||
guint permanent : 1;
|
||||
/* we are allowed to call glGenerateMipmap() for this texture */
|
||||
guint can_mipmap : 1;
|
||||
/* we called glGenerateMipmap() for this texture */
|
||||
guint has_mipmap : 1;
|
||||
};
|
||||
|
||||
@@ -10,8 +10,8 @@ void main() {
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
|
||||
// We use this shader for both plain glyphs (used as mask)
|
||||
// and color glpyhs (used as source). The renderer sets
|
||||
// aColor to vec4(-1) for color glyhs.
|
||||
// and color glyphs (used as source). The renderer sets
|
||||
// aColor to vec4(-1) for color glyphs.
|
||||
if (distance(aColor,vec4(-1)) < 0.1)
|
||||
use_color = 0.0;
|
||||
else
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskglbufferprivate.h"
|
||||
|
||||
struct _GskGLBuffer
|
||||
{
|
||||
GskGpuBuffer parent_instance;
|
||||
|
||||
GLenum target;
|
||||
GLuint buffer_id;
|
||||
GLenum access;
|
||||
guchar *data;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLBuffer, gsk_gl_buffer, GSK_TYPE_GPU_BUFFER)
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_finalize (GObject *object)
|
||||
{
|
||||
GskGLBuffer *self = GSK_GL_BUFFER (object);
|
||||
|
||||
g_free (self->data);
|
||||
glDeleteBuffers (1, &self->buffer_id);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_buffer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static guchar *
|
||||
gsk_gl_buffer_map (GskGpuBuffer *buffer)
|
||||
{
|
||||
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
|
||||
|
||||
return self->data;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_unmap (GskGpuBuffer *buffer)
|
||||
{
|
||||
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
|
||||
|
||||
gsk_gl_buffer_bind (self);
|
||||
|
||||
glBufferSubData (self->target, 0, gsk_gpu_buffer_get_size (buffer), self->data);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_class_init (GskGLBufferClass *klass)
|
||||
{
|
||||
GskGpuBufferClass *buffer_class = GSK_GPU_BUFFER_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
buffer_class->map = gsk_gl_buffer_map;
|
||||
buffer_class->unmap = gsk_gl_buffer_unmap;
|
||||
|
||||
gobject_class->finalize = gsk_gl_buffer_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_init (GskGLBuffer *self)
|
||||
{
|
||||
}
|
||||
|
||||
GskGpuBuffer *
|
||||
gsk_gl_buffer_new (GLenum target,
|
||||
gsize size,
|
||||
GLenum access)
|
||||
{
|
||||
GskGLBuffer *self;
|
||||
|
||||
self = g_object_new (GSK_TYPE_GL_BUFFER, NULL);
|
||||
|
||||
gsk_gpu_buffer_setup (GSK_GPU_BUFFER (self), size);
|
||||
|
||||
self->target = target;
|
||||
self->access = access;
|
||||
|
||||
glGenBuffers (1, &self->buffer_id);
|
||||
glBindBuffer (target, self->buffer_id);
|
||||
glBufferData (target, size, NULL, GL_STATIC_DRAW);
|
||||
self->data = malloc (size);
|
||||
|
||||
return GSK_GPU_BUFFER (self);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_buffer_bind (GskGLBuffer *self)
|
||||
{
|
||||
glBindBuffer (self->target, self->buffer_id);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_buffer_bind_base (GskGLBuffer *self,
|
||||
GLuint index)
|
||||
{
|
||||
glBindBufferBase (self->target, index, self->buffer_id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpubufferprivate.h"
|
||||
|
||||
#include "gskgldeviceprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_BUFFER (gsk_gl_buffer_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLBuffer, gsk_gl_buffer, GSK, GL_BUFFER, GskGpuBuffer)
|
||||
|
||||
GskGpuBuffer * gsk_gl_buffer_new (GLenum target,
|
||||
gsize size,
|
||||
GLenum access);
|
||||
|
||||
void gsk_gl_buffer_bind (GskGLBuffer *self);
|
||||
void gsk_gl_buffer_bind_base (GskGLBuffer *self,
|
||||
GLuint index);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgldescriptorsprivate.h"
|
||||
|
||||
#include "gskglbufferprivate.h"
|
||||
#include "gskglimageprivate.h"
|
||||
|
||||
struct _GskGLDescriptors
|
||||
{
|
||||
GskGpuDescriptors parent_instance;
|
||||
|
||||
GskGLDevice *device;
|
||||
guint n_external;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK_TYPE_GPU_DESCRIPTORS)
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_finalize (GObject *object)
|
||||
{
|
||||
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (object);
|
||||
|
||||
g_object_unref (self->device);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_descriptors_add_image (GskGpuDescriptors *desc,
|
||||
GskGpuImage *image,
|
||||
GskGpuSampler sampler,
|
||||
guint32 *out_descriptor)
|
||||
{
|
||||
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (desc);
|
||||
gsize used_texture_units;
|
||||
|
||||
used_texture_units = gsk_gpu_descriptors_get_n_images (desc) + 2 * self->n_external;
|
||||
|
||||
if (gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_EXTERNAL)
|
||||
{
|
||||
if (16 - used_texture_units < 3)
|
||||
return FALSE;
|
||||
|
||||
*out_descriptor = (self->n_external << 1) | 1;
|
||||
self->n_external++;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (used_texture_units >= 16)
|
||||
return FALSE;
|
||||
|
||||
*out_descriptor = (gsk_gpu_descriptors_get_n_images (desc) - self->n_external) << 1;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
GskGpuBuffer *buffer,
|
||||
guint32 *out_descriptor)
|
||||
{
|
||||
gsize used_buffers;
|
||||
|
||||
used_buffers = gsk_gpu_descriptors_get_n_buffers (desc);
|
||||
|
||||
if (used_buffers >= 11)
|
||||
return FALSE;
|
||||
|
||||
*out_descriptor = used_buffers;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_class_init (GskGLDescriptorsClass *klass)
|
||||
{
|
||||
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gsk_gl_descriptors_finalize;
|
||||
|
||||
descriptors_class->add_image = gsk_gl_descriptors_add_image;
|
||||
descriptors_class->add_buffer = gsk_gl_descriptors_add_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_init (GskGLDescriptors *self)
|
||||
{
|
||||
}
|
||||
|
||||
GskGpuDescriptors *
|
||||
gsk_gl_descriptors_new (GskGLDevice *device)
|
||||
{
|
||||
GskGLDescriptors *self;
|
||||
|
||||
self = g_object_new (GSK_TYPE_GL_DESCRIPTORS, NULL);
|
||||
|
||||
self->device = g_object_ref (device);
|
||||
|
||||
return GSK_GPU_DESCRIPTORS (self);
|
||||
}
|
||||
|
||||
guint
|
||||
gsk_gl_descriptors_get_n_external (GskGLDescriptors *self)
|
||||
{
|
||||
return self->n_external;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_descriptors_use (GskGLDescriptors *self)
|
||||
{
|
||||
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
|
||||
gsize i, ext, n_textures;
|
||||
|
||||
n_textures = 16 - 3 * self->n_external;
|
||||
ext = 0;
|
||||
|
||||
for (i = 0; i < gsk_gpu_descriptors_get_n_images (desc); i++)
|
||||
{
|
||||
GskGLImage *image = GSK_GL_IMAGE (gsk_gpu_descriptors_get_image (desc, i));
|
||||
|
||||
if (gsk_gpu_image_get_flags (GSK_GPU_IMAGE (image)) & GSK_GPU_IMAGE_EXTERNAL)
|
||||
{
|
||||
glActiveTexture (GL_TEXTURE0 + n_textures + 3 * ext);
|
||||
gsk_gl_image_bind_texture (image);
|
||||
ext++;
|
||||
}
|
||||
else
|
||||
{
|
||||
glActiveTexture (GL_TEXTURE0 + i - ext);
|
||||
gsk_gl_image_bind_texture (image);
|
||||
glBindSampler (i - ext, gsk_gl_device_get_sampler_id (self->device, gsk_gpu_descriptors_get_sampler (desc, i)));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < gsk_gpu_descriptors_get_n_buffers (desc); i++)
|
||||
{
|
||||
GskGLBuffer *buffer = GSK_GL_BUFFER (gsk_gpu_descriptors_get_buffer (desc, i));
|
||||
|
||||
/* index 0 are the globals, we start at 1 */
|
||||
gsk_gl_buffer_bind_base (buffer, i + 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpudescriptorsprivate.h"
|
||||
|
||||
#include "gskgldeviceprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_DESCRIPTORS (gsk_gl_descriptors_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK, GL_DESCRIPTORS, GskGpuDescriptors)
|
||||
|
||||
GskGpuDescriptors * gsk_gl_descriptors_new (GskGLDevice *device);
|
||||
|
||||
guint gsk_gl_descriptors_get_n_external (GskGLDescriptors *self);
|
||||
void gsk_gl_descriptors_use (GskGLDescriptors *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -0,0 +1,687 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgldeviceprivate.h"
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskgpushaderopprivate.h"
|
||||
#include "gskglbufferprivate.h"
|
||||
#include "gskglimageprivate.h"
|
||||
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
struct _GskGLDevice
|
||||
{
|
||||
GskGpuDevice parent_instance;
|
||||
|
||||
GHashTable *gl_programs;
|
||||
const char *version_string;
|
||||
GdkGLAPI api;
|
||||
|
||||
guint sampler_ids[GSK_GPU_SAMPLER_N_SAMPLERS];
|
||||
};
|
||||
|
||||
struct _GskGLDeviceClass
|
||||
{
|
||||
GskGpuDeviceClass parent_class;
|
||||
};
|
||||
|
||||
typedef struct _GLProgramKey GLProgramKey;
|
||||
|
||||
struct _GLProgramKey
|
||||
{
|
||||
const GskGpuShaderOpClass *op_class;
|
||||
guint32 variation;
|
||||
GskGpuShaderClip clip;
|
||||
guint n_external_textures;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLDevice, gsk_gl_device, GSK_TYPE_GPU_DEVICE)
|
||||
|
||||
static guint
|
||||
gl_program_key_hash (gconstpointer data)
|
||||
{
|
||||
const GLProgramKey *key = data;
|
||||
|
||||
return GPOINTER_TO_UINT (key->op_class) ^
|
||||
key->clip ^
|
||||
(key->variation << 2) ^
|
||||
(key->n_external_textures << 24);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gl_program_key_equal (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const GLProgramKey *keya = a;
|
||||
const GLProgramKey *keyb = b;
|
||||
|
||||
return keya->op_class == keyb->op_class &&
|
||||
keya->variation == keyb->variation &&
|
||||
keya->clip == keyb->clip &&
|
||||
keya->n_external_textures == keyb->n_external_textures;
|
||||
}
|
||||
|
||||
static GskGpuImage *
|
||||
gsk_gl_device_create_offscreen_image (GskGpuDevice *device,
|
||||
gboolean with_mipmap,
|
||||
GdkMemoryDepth depth,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskGLDevice *self = GSK_GL_DEVICE (device);
|
||||
|
||||
return gsk_gl_image_new (self,
|
||||
gdk_memory_depth_get_format (depth),
|
||||
GSK_GPU_IMAGE_RENDERABLE | GSK_GPU_IMAGE_FILTERABLE,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
static GskGpuImage *
|
||||
gsk_gl_device_create_upload_image (GskGpuDevice *device,
|
||||
gboolean with_mipmap,
|
||||
GdkMemoryFormat format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskGLDevice *self = GSK_GL_DEVICE (device);
|
||||
|
||||
return gsk_gl_image_new (self,
|
||||
format,
|
||||
0,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
static GskGpuImage *
|
||||
gsk_gl_device_create_download_image (GskGpuDevice *device,
|
||||
GdkMemoryDepth depth,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskGLDevice *self = GSK_GL_DEVICE (device);
|
||||
|
||||
return gsk_gl_image_new (self,
|
||||
gdk_memory_depth_get_format (depth),
|
||||
GSK_GPU_IMAGE_RENDERABLE,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
static GskGpuImage *
|
||||
gsk_gl_device_create_atlas_image (GskGpuDevice *device,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskGLDevice *self = GSK_GL_DEVICE (device);
|
||||
|
||||
return gsk_gl_image_new (self,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
GSK_GPU_IMAGE_RENDERABLE,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_device_finalize (GObject *object)
|
||||
{
|
||||
GskGLDevice *self = GSK_GL_DEVICE (object);
|
||||
GskGpuDevice *device = GSK_GPU_DEVICE (self);
|
||||
|
||||
g_object_steal_data (G_OBJECT (gsk_gpu_device_get_display (device)), "-gsk-gl-device");
|
||||
|
||||
gdk_gl_context_make_current (gdk_display_get_gl_context (gsk_gpu_device_get_display (device)));
|
||||
|
||||
g_hash_table_unref (self->gl_programs);
|
||||
glDeleteSamplers (G_N_ELEMENTS (self->sampler_ids), self->sampler_ids);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_device_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_device_class_init (GskGLDeviceClass *klass)
|
||||
{
|
||||
GskGpuDeviceClass *gpu_device_class = GSK_GPU_DEVICE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gpu_device_class->create_offscreen_image = gsk_gl_device_create_offscreen_image;
|
||||
gpu_device_class->create_atlas_image = gsk_gl_device_create_atlas_image;
|
||||
gpu_device_class->create_upload_image = gsk_gl_device_create_upload_image;
|
||||
gpu_device_class->create_download_image = gsk_gl_device_create_download_image;
|
||||
|
||||
object_class->finalize = gsk_gl_device_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
free_gl_program (gpointer program)
|
||||
{
|
||||
glDeleteProgram (GPOINTER_TO_UINT (program));
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_device_init (GskGLDevice *self)
|
||||
{
|
||||
self->gl_programs = g_hash_table_new_full (gl_program_key_hash, gl_program_key_equal, g_free, free_gl_program);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_device_setup_samplers (GskGLDevice *self)
|
||||
{
|
||||
struct {
|
||||
GLuint min_filter;
|
||||
GLuint mag_filter;
|
||||
GLuint wrap;
|
||||
} sampler_flags[GSK_GPU_SAMPLER_N_SAMPLERS] = {
|
||||
[GSK_GPU_SAMPLER_DEFAULT] = {
|
||||
.min_filter = GL_LINEAR,
|
||||
.mag_filter = GL_LINEAR,
|
||||
.wrap = GL_CLAMP_TO_EDGE,
|
||||
},
|
||||
[GSK_GPU_SAMPLER_TRANSPARENT] = {
|
||||
.min_filter = GL_LINEAR,
|
||||
.mag_filter = GL_LINEAR,
|
||||
.wrap = GL_CLAMP_TO_BORDER,
|
||||
},
|
||||
[GSK_GPU_SAMPLER_REPEAT] = {
|
||||
.min_filter = GL_LINEAR,
|
||||
.mag_filter = GL_LINEAR,
|
||||
.wrap = GL_REPEAT,
|
||||
},
|
||||
[GSK_GPU_SAMPLER_NEAREST] = {
|
||||
.min_filter = GL_NEAREST,
|
||||
.mag_filter = GL_NEAREST,
|
||||
.wrap = GL_CLAMP_TO_EDGE,
|
||||
},
|
||||
[GSK_GPU_SAMPLER_MIPMAP_DEFAULT] = {
|
||||
.min_filter = GL_LINEAR_MIPMAP_LINEAR,
|
||||
.mag_filter = GL_LINEAR,
|
||||
.wrap = GL_CLAMP_TO_EDGE,
|
||||
}
|
||||
};
|
||||
guint i;
|
||||
|
||||
glGenSamplers (G_N_ELEMENTS (self->sampler_ids), self->sampler_ids);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (self->sampler_ids); i++)
|
||||
{
|
||||
glSamplerParameteri (self->sampler_ids[i], GL_TEXTURE_MIN_FILTER, sampler_flags[i].min_filter);
|
||||
glSamplerParameteri (self->sampler_ids[i], GL_TEXTURE_MAG_FILTER, sampler_flags[i].mag_filter);
|
||||
glSamplerParameteri (self->sampler_ids[i], GL_TEXTURE_WRAP_S, sampler_flags[i].wrap);
|
||||
glSamplerParameteri (self->sampler_ids[i], GL_TEXTURE_WRAP_T, sampler_flags[i].wrap);
|
||||
}
|
||||
}
|
||||
|
||||
GskGpuDevice *
|
||||
gsk_gl_device_get_for_display (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
GskGLDevice *self;
|
||||
GdkGLContext *context;
|
||||
GLint max_texture_size;
|
||||
|
||||
self = g_object_get_data (G_OBJECT (display), "-gsk-gl-device");
|
||||
if (self)
|
||||
return GSK_GPU_DEVICE (g_object_ref (self));
|
||||
|
||||
if (!gdk_display_prepare_gl (display, error))
|
||||
return NULL;
|
||||
|
||||
context = gdk_display_get_gl_context (display);
|
||||
|
||||
/* GLES 2 is not supported */
|
||||
if (!gdk_gl_context_check_version (context, "3.0", "3.0"))
|
||||
{
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("OpenGL ES 2.0 is not supported by this renderer."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = g_object_new (GSK_TYPE_GL_DEVICE, NULL);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
|
||||
gsk_gpu_device_setup (GSK_GPU_DEVICE (self), display, max_texture_size);
|
||||
|
||||
self->version_string = gdk_gl_context_get_glsl_version_string (context);
|
||||
self->api = gdk_gl_context_get_api (context);
|
||||
gsk_gl_device_setup_samplers (self);
|
||||
|
||||
g_object_set_data (G_OBJECT (display), "-gsk-gl-device", self);
|
||||
|
||||
return GSK_GPU_DEVICE (self);
|
||||
}
|
||||
|
||||
static char *
|
||||
prepend_line_numbers (char *code)
|
||||
{
|
||||
GString *s;
|
||||
char *p;
|
||||
int line;
|
||||
|
||||
s = g_string_new ("");
|
||||
p = code;
|
||||
line = 1;
|
||||
while (*p)
|
||||
{
|
||||
char *end = strchr (p, '\n');
|
||||
if (end)
|
||||
end = end + 1; /* Include newline */
|
||||
else
|
||||
end = p + strlen (p);
|
||||
|
||||
g_string_append_printf (s, "%3d| ", line++);
|
||||
g_string_append_len (s, p, end - p);
|
||||
|
||||
p = end;
|
||||
}
|
||||
|
||||
g_free (code);
|
||||
|
||||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_device_check_shader_error (int shader_id,
|
||||
GError **error)
|
||||
{
|
||||
GLint status;
|
||||
GLint log_len;
|
||||
GLint code_len;
|
||||
char *log;
|
||||
char *code;
|
||||
|
||||
glGetShaderiv (shader_id, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if G_LIKELY (status == GL_TRUE)
|
||||
return TRUE;
|
||||
|
||||
glGetShaderiv (shader_id, GL_INFO_LOG_LENGTH, &log_len);
|
||||
log = g_malloc0 (log_len + 1);
|
||||
glGetShaderInfoLog (shader_id, log_len, NULL, log);
|
||||
|
||||
glGetShaderiv (shader_id, GL_SHADER_SOURCE_LENGTH, &code_len);
|
||||
code = g_malloc0 (code_len + 1);
|
||||
glGetShaderSource (shader_id, code_len, NULL, code);
|
||||
|
||||
code = prepend_line_numbers (code);
|
||||
|
||||
g_set_error (error,
|
||||
GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_COMPILATION_FAILED,
|
||||
"Compilation failure in shader.\n"
|
||||
"Source Code:\n"
|
||||
"%s\n"
|
||||
"\n"
|
||||
"Error Message:\n"
|
||||
"%s\n"
|
||||
"\n",
|
||||
code,
|
||||
log);
|
||||
|
||||
g_free (code);
|
||||
g_free (log);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
print_shader_info (const char *prefix,
|
||||
GLuint shader_id,
|
||||
const char *name)
|
||||
{
|
||||
if (GSK_DEBUG_CHECK (SHADERS))
|
||||
{
|
||||
int code_len;
|
||||
|
||||
glGetShaderiv (shader_id, GL_SHADER_SOURCE_LENGTH, &code_len);
|
||||
|
||||
if (code_len > 0)
|
||||
{
|
||||
char *code;
|
||||
|
||||
code = g_malloc0 (code_len + 1);
|
||||
glGetShaderSource (shader_id, code_len, NULL, code);
|
||||
|
||||
code = prepend_line_numbers (code);
|
||||
|
||||
g_message ("%s %d, %s:\n%s",
|
||||
prefix, shader_id,
|
||||
name ? name : "unnamed",
|
||||
code);
|
||||
g_free (code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint
|
||||
gsk_gl_device_load_shader (GskGLDevice *self,
|
||||
const char *program_name,
|
||||
GLenum shader_type,
|
||||
guint32 variation,
|
||||
GskGpuShaderClip clip,
|
||||
guint n_external_textures,
|
||||
GError **error)
|
||||
{
|
||||
GString *preamble;
|
||||
char *resource_name;
|
||||
GBytes *bytes;
|
||||
GLuint shader_id;
|
||||
|
||||
preamble = g_string_new (NULL);
|
||||
|
||||
g_string_append (preamble, self->version_string);
|
||||
g_string_append (preamble, "\n");
|
||||
if (self->api == GDK_GL_API_GLES)
|
||||
{
|
||||
if (n_external_textures > 0)
|
||||
{
|
||||
g_string_append (preamble, "#extension GL_OES_EGL_image_external_essl3 : require\n");
|
||||
g_string_append (preamble, "#extension GL_OES_EGL_image_external : require\n");
|
||||
}
|
||||
g_string_append (preamble, "#define GSK_GLES 1\n");
|
||||
g_assert (3 * n_external_textures <= 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (n_external_textures == 0);
|
||||
}
|
||||
|
||||
g_string_append_printf (preamble, "#define N_TEXTURES %u\n", 16 - 3 * n_external_textures);
|
||||
g_string_append_printf (preamble, "#define N_EXTERNAL_TEXTURES %u\n", n_external_textures);
|
||||
|
||||
switch (shader_type)
|
||||
{
|
||||
case GL_VERTEX_SHADER:
|
||||
g_string_append (preamble, "#define GSK_VERTEX_SHADER 1\n");
|
||||
break;
|
||||
|
||||
case GL_FRAGMENT_SHADER:
|
||||
g_string_append (preamble, "#define GSK_FRAGMENT_SHADER 1\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_string_append_printf (preamble, "#define GSK_VARIATION %uu\n", variation);
|
||||
|
||||
switch (clip)
|
||||
{
|
||||
case GSK_GPU_SHADER_CLIP_NONE:
|
||||
g_string_append (preamble, "#define GSK_SHADER_CLIP GSK_GPU_SHADER_CLIP_NONE\n");
|
||||
break;
|
||||
case GSK_GPU_SHADER_CLIP_RECT:
|
||||
g_string_append (preamble, "#define GSK_SHADER_CLIP GSK_GPU_SHADER_CLIP_RECT\n");
|
||||
break;
|
||||
case GSK_GPU_SHADER_CLIP_ROUNDED:
|
||||
g_string_append (preamble, "#define GSK_SHADER_CLIP GSK_GPU_SHADER_CLIP_ROUNDED\n");
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
resource_name = g_strconcat ("/org/gtk/libgsk/shaders/gl/", program_name, ".glsl", NULL);
|
||||
bytes = g_resources_lookup_data (resource_name, 0, error);
|
||||
g_free (resource_name);
|
||||
if (bytes == NULL)
|
||||
return 0;
|
||||
|
||||
shader_id = glCreateShader (shader_type);
|
||||
|
||||
glShaderSource (shader_id,
|
||||
2,
|
||||
(const char *[]) {
|
||||
preamble->str,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
},
|
||||
NULL);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
g_string_free (preamble, TRUE);
|
||||
|
||||
glCompileShader (shader_id);
|
||||
|
||||
print_shader_info (shader_type == GL_FRAGMENT_SHADER ? "fragment" : "vertex", shader_id, program_name);
|
||||
|
||||
if (!gsk_gl_device_check_shader_error (shader_id, error))
|
||||
{
|
||||
glDeleteShader (shader_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shader_id;
|
||||
}
|
||||
|
||||
static GLuint
|
||||
gsk_gl_device_load_program (GskGLDevice *self,
|
||||
const GskGpuShaderOpClass *op_class,
|
||||
guint32 variation,
|
||||
GskGpuShaderClip clip,
|
||||
guint n_external_textures,
|
||||
GError **error)
|
||||
{
|
||||
GLuint vertex_shader_id, fragment_shader_id, program_id;
|
||||
GLint link_status;
|
||||
|
||||
vertex_shader_id = gsk_gl_device_load_shader (self, op_class->shader_name, GL_VERTEX_SHADER, variation, clip, n_external_textures, error);
|
||||
if (vertex_shader_id == 0)
|
||||
return 0;
|
||||
|
||||
fragment_shader_id = gsk_gl_device_load_shader (self, op_class->shader_name, GL_FRAGMENT_SHADER, variation, clip, n_external_textures, error);
|
||||
if (fragment_shader_id == 0)
|
||||
return 0;
|
||||
|
||||
program_id = glCreateProgram ();
|
||||
|
||||
glAttachShader (program_id, vertex_shader_id);
|
||||
glAttachShader (program_id, fragment_shader_id);
|
||||
|
||||
op_class->setup_attrib_locations (program_id);
|
||||
|
||||
glLinkProgram (program_id);
|
||||
|
||||
glGetProgramiv (program_id, GL_LINK_STATUS, &link_status);
|
||||
|
||||
glDetachShader (program_id, vertex_shader_id);
|
||||
glDeleteShader (vertex_shader_id);
|
||||
glDetachShader (program_id, fragment_shader_id);
|
||||
glDeleteShader (fragment_shader_id);
|
||||
|
||||
if (link_status == GL_FALSE)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
int log_len = 0;
|
||||
|
||||
glGetProgramiv (program_id, GL_INFO_LOG_LENGTH, &log_len);
|
||||
|
||||
if (log_len > 0)
|
||||
{
|
||||
/* log_len includes NULL */
|
||||
buffer = g_malloc0 (log_len);
|
||||
glGetProgramInfoLog (program_id, log_len, NULL, buffer);
|
||||
}
|
||||
|
||||
g_set_error (error,
|
||||
GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_LINK_FAILED,
|
||||
"Linking failure in shader: %s",
|
||||
buffer ? buffer : "");
|
||||
|
||||
g_free (buffer);
|
||||
|
||||
glDeleteProgram (program_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return program_id;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_device_use_program (GskGLDevice *self,
|
||||
const GskGpuShaderOpClass *op_class,
|
||||
guint32 variation,
|
||||
GskGpuShaderClip clip,
|
||||
guint n_external_textures)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GLuint program_id;
|
||||
GLProgramKey key = {
|
||||
.op_class = op_class,
|
||||
.variation = variation,
|
||||
.clip = clip,
|
||||
.n_external_textures = n_external_textures
|
||||
};
|
||||
guint i, n_textures;
|
||||
|
||||
program_id = GPOINTER_TO_UINT (g_hash_table_lookup (self->gl_programs, &key));
|
||||
if (program_id)
|
||||
{
|
||||
glUseProgram (program_id);
|
||||
return;
|
||||
}
|
||||
|
||||
program_id = gsk_gl_device_load_program (self, op_class, variation, clip, n_external_textures, &error);
|
||||
if (program_id == 0)
|
||||
{
|
||||
g_critical ("Failed to load shader program: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_hash_table_insert (self->gl_programs, g_memdup (&key, sizeof (GLProgramKey)), GUINT_TO_POINTER (program_id));
|
||||
|
||||
glUseProgram (program_id);
|
||||
|
||||
n_textures = 16 - 3 * n_external_textures;
|
||||
|
||||
for (i = 0; i < n_external_textures; i++)
|
||||
{
|
||||
char *name = g_strdup_printf ("external_textures[%u]", i);
|
||||
glUniform1i (glGetUniformLocation (program_id, name), n_textures + 3 * i);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_textures; i++)
|
||||
{
|
||||
char *name = g_strdup_printf ("textures[%u]", i);
|
||||
glUniform1i (glGetUniformLocation (program_id, name), i);
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint
|
||||
gsk_gl_device_get_sampler_id (GskGLDevice *self,
|
||||
GskGpuSampler sampler)
|
||||
{
|
||||
g_return_val_if_fail (sampler < G_N_ELEMENTS (self->sampler_ids), 0);
|
||||
|
||||
return self->sampler_ids[sampler];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_gl_device_get_format_flags (GskGLDevice *self,
|
||||
GdkGLContext *context,
|
||||
GdkMemoryFormat format,
|
||||
GskGpuImageFlags *out_flags)
|
||||
{
|
||||
GdkGLMemoryFlags gl_flags;
|
||||
|
||||
*out_flags = 0;
|
||||
gl_flags = gdk_gl_context_get_format_flags (context, format);
|
||||
|
||||
if (!(gl_flags & GDK_GL_FORMAT_USABLE))
|
||||
return FALSE;
|
||||
|
||||
if (gl_flags & GDK_GL_FORMAT_RENDERABLE)
|
||||
*out_flags |= GSK_GPU_IMAGE_RENDERABLE;
|
||||
else if (gdk_gl_context_get_use_es (context))
|
||||
*out_flags |= GSK_GPU_IMAGE_NO_BLIT;
|
||||
if (gl_flags & GDK_GL_FORMAT_FILTERABLE)
|
||||
*out_flags |= GSK_GPU_IMAGE_FILTERABLE;
|
||||
if ((gl_flags & (GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE)) == (GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE))
|
||||
*out_flags |= GSK_GPU_IMAGE_CAN_MIPMAP;
|
||||
|
||||
if (gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
*out_flags |= GSK_GPU_IMAGE_STRAIGHT_ALPHA;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_device_find_gl_format (GskGLDevice *self,
|
||||
GdkMemoryFormat format,
|
||||
GskGpuImageFlags required_flags,
|
||||
GdkMemoryFormat *out_format,
|
||||
GskGpuImageFlags *out_flags,
|
||||
GLint *out_gl_internal_format,
|
||||
GLenum *out_gl_format,
|
||||
GLenum *out_gl_type,
|
||||
GLint out_swizzle[4])
|
||||
{
|
||||
GdkGLContext *context = gdk_gl_context_get_current ();
|
||||
GskGpuImageFlags flags;
|
||||
GdkMemoryFormat alt_format;
|
||||
const GdkMemoryFormat *fallbacks;
|
||||
gsize i;
|
||||
|
||||
/* First, try the actual format */
|
||||
if (gsk_gl_device_get_format_flags (self, context, format, &flags) &&
|
||||
((flags & required_flags) == required_flags))
|
||||
{
|
||||
*out_format = format;
|
||||
*out_flags = flags;
|
||||
gdk_memory_format_gl_format (format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
out_gl_internal_format,
|
||||
out_gl_format,
|
||||
out_gl_type,
|
||||
out_swizzle);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Second, try the potential RGBA format */
|
||||
if (gdk_memory_format_gl_rgba_format (format,
|
||||
gdk_gl_context_get_use_es (context),
|
||||
&alt_format,
|
||||
out_gl_internal_format,
|
||||
out_gl_format,
|
||||
out_gl_type,
|
||||
out_swizzle) &&
|
||||
gsk_gl_device_get_format_flags (self, context, alt_format, &flags) &&
|
||||
((flags & required_flags) == required_flags))
|
||||
{
|
||||
*out_format = format;
|
||||
*out_flags = flags;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Next, try the fallbacks */
|
||||
fallbacks = gdk_memory_format_get_fallbacks (format);
|
||||
for (i = 0; fallbacks[i] != -1; i++)
|
||||
{
|
||||
if (gsk_gl_device_get_format_flags (self, context, fallbacks[i], &flags) &&
|
||||
((flags & required_flags) == required_flags))
|
||||
{
|
||||
*out_format = fallbacks[i];
|
||||
*out_flags = flags;
|
||||
gdk_memory_format_gl_format (fallbacks[i],
|
||||
gdk_gl_context_get_use_es (context),
|
||||
out_gl_internal_format,
|
||||
out_gl_format,
|
||||
out_gl_type,
|
||||
out_swizzle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* fallbacks will always fallback to a supported format */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpudeviceprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_DEVICE (gsk_gl_device_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLDevice, gsk_gl_device, GSK, GL_DEVICE, GskGpuDevice)
|
||||
|
||||
GskGpuDevice * gsk_gl_device_get_for_display (GdkDisplay *display,
|
||||
GError **error);
|
||||
|
||||
void gsk_gl_device_use_program (GskGLDevice *self,
|
||||
const GskGpuShaderOpClass *op_class,
|
||||
guint32 variation,
|
||||
GskGpuShaderClip clip,
|
||||
guint n_external_textures);
|
||||
|
||||
GLuint gsk_gl_device_get_sampler_id (GskGLDevice *self,
|
||||
GskGpuSampler sampler);
|
||||
|
||||
void gsk_gl_device_find_gl_format (GskGLDevice *self,
|
||||
GdkMemoryFormat format,
|
||||
GskGpuImageFlags required_flags,
|
||||
GdkMemoryFormat *out_format,
|
||||
GskGpuImageFlags *out_flags,
|
||||
GLint *out_gl_internal_format,
|
||||
GLenum *out_gl_format,
|
||||
GLenum *out_gl_type,
|
||||
GLint out_swizzle[4]);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -0,0 +1,240 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskglframeprivate.h"
|
||||
|
||||
#include "gskgpuglobalsopprivate.h"
|
||||
#include "gskgpuopprivate.h"
|
||||
#include "gskgpushaderopprivate.h"
|
||||
#include "gskglbufferprivate.h"
|
||||
#include "gskgldescriptorsprivate.h"
|
||||
#include "gskgldeviceprivate.h"
|
||||
#include "gskglimageprivate.h"
|
||||
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
struct _GskGLFrame
|
||||
{
|
||||
GskGpuFrame parent_instance;
|
||||
|
||||
GLuint globals_buffer_id;
|
||||
guint next_texture_slot;
|
||||
|
||||
GHashTable *vaos;
|
||||
};
|
||||
|
||||
struct _GskGLFrameClass
|
||||
{
|
||||
GskGpuFrameClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLFrame, gsk_gl_frame, GSK_TYPE_GPU_FRAME)
|
||||
|
||||
static gboolean
|
||||
gsk_gl_frame_is_busy (GskGpuFrame *frame)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_setup (GskGpuFrame *frame)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
|
||||
glGenBuffers (1, &self->globals_buffer_id);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_cleanup (GskGpuFrame *frame)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
|
||||
self->next_texture_slot = 0;
|
||||
|
||||
GSK_GPU_FRAME_CLASS (gsk_gl_frame_parent_class)->cleanup (frame);
|
||||
}
|
||||
|
||||
static GskGpuImage *
|
||||
gsk_gl_frame_upload_texture (GskGpuFrame *frame,
|
||||
gboolean with_mipmap,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
GdkGLTexture *gl_texture = GDK_GL_TEXTURE (texture);
|
||||
|
||||
if (gdk_gl_context_is_shared (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
|
||||
gdk_gl_texture_get_context (gl_texture)))
|
||||
{
|
||||
GskGpuImage *image;
|
||||
GLsync sync;
|
||||
|
||||
image = gsk_gl_image_new_for_texture (GSK_GL_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
texture,
|
||||
gdk_gl_texture_get_id (gl_texture),
|
||||
FALSE,
|
||||
gdk_gl_texture_has_mipmap (gl_texture) ? (GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP) : 0);
|
||||
|
||||
/* This is a hack, but it works */
|
||||
sync = gdk_gl_texture_get_sync (gl_texture);
|
||||
if (sync)
|
||||
glWaitSync (sync, 0, GL_TIMEOUT_IGNORED);
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
else if (GDK_IS_DMABUF_TEXTURE (texture))
|
||||
{
|
||||
gboolean external;
|
||||
GLuint tex_id;
|
||||
|
||||
tex_id = gdk_gl_context_import_dmabuf (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture)),
|
||||
&external);
|
||||
if (tex_id)
|
||||
{
|
||||
return gsk_gl_image_new_for_texture (GSK_GL_DEVICE (gsk_gpu_frame_get_device (frame)),
|
||||
texture,
|
||||
tex_id,
|
||||
TRUE,
|
||||
(external ? GSK_GPU_IMAGE_EXTERNAL | GSK_GPU_IMAGE_NO_BLIT : 0));
|
||||
}
|
||||
}
|
||||
|
||||
return GSK_GPU_FRAME_CLASS (gsk_gl_frame_parent_class)->upload_texture (frame, with_mipmap, texture);
|
||||
}
|
||||
|
||||
static GskGpuDescriptors *
|
||||
gsk_gl_frame_create_descriptors (GskGpuFrame *frame)
|
||||
{
|
||||
return GSK_GPU_DESCRIPTORS (gsk_gl_descriptors_new (GSK_GL_DEVICE (gsk_gpu_frame_get_device (frame))));
|
||||
}
|
||||
|
||||
static GskGpuBuffer *
|
||||
gsk_gl_frame_create_vertex_buffer (GskGpuFrame *frame,
|
||||
gsize size)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
|
||||
/* We could also reassign them all to the new buffer here?
|
||||
* Is that faster?
|
||||
*/
|
||||
g_hash_table_remove_all (self->vaos);
|
||||
|
||||
return gsk_gl_buffer_new (GL_ARRAY_BUFFER, size, GL_WRITE_ONLY);
|
||||
}
|
||||
|
||||
static GskGpuBuffer *
|
||||
gsk_gl_frame_create_storage_buffer (GskGpuFrame *frame,
|
||||
gsize size)
|
||||
{
|
||||
return gsk_gl_buffer_new (GL_UNIFORM_BUFFER, size, GL_WRITE_ONLY);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_submit (GskGpuFrame *frame,
|
||||
GskGpuBuffer *vertex_buffer,
|
||||
GskGpuOp *op)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (frame);
|
||||
GskGLCommandState state = { 0, };
|
||||
|
||||
glEnable (GL_SCISSOR_TEST);
|
||||
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
glDepthFunc (GL_LEQUAL);
|
||||
glEnable (GL_BLEND);
|
||||
|
||||
if (vertex_buffer)
|
||||
gsk_gl_buffer_bind (GSK_GL_BUFFER (vertex_buffer));
|
||||
|
||||
gsk_gl_frame_bind_globals (self);
|
||||
glBufferData (GL_UNIFORM_BUFFER,
|
||||
sizeof (GskGpuGlobalsInstance),
|
||||
NULL,
|
||||
GL_STREAM_DRAW);
|
||||
|
||||
while (op)
|
||||
{
|
||||
op = gsk_gpu_op_gl_command (op, frame, &state);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_finalize (GObject *object)
|
||||
{
|
||||
GskGLFrame *self = GSK_GL_FRAME (object);
|
||||
|
||||
g_hash_table_unref (self->vaos);
|
||||
glDeleteBuffers (1, &self->globals_buffer_id);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_frame_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_class_init (GskGLFrameClass *klass)
|
||||
{
|
||||
GskGpuFrameClass *gpu_frame_class = GSK_GPU_FRAME_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gpu_frame_class->is_busy = gsk_gl_frame_is_busy;
|
||||
gpu_frame_class->setup = gsk_gl_frame_setup;
|
||||
gpu_frame_class->cleanup = gsk_gl_frame_cleanup;
|
||||
gpu_frame_class->upload_texture = gsk_gl_frame_upload_texture;
|
||||
gpu_frame_class->create_descriptors = gsk_gl_frame_create_descriptors;
|
||||
gpu_frame_class->create_vertex_buffer = gsk_gl_frame_create_vertex_buffer;
|
||||
gpu_frame_class->create_storage_buffer = gsk_gl_frame_create_storage_buffer;
|
||||
gpu_frame_class->submit = gsk_gl_frame_submit;
|
||||
|
||||
object_class->finalize = gsk_gl_frame_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
free_vao (gpointer vao)
|
||||
{
|
||||
glDeleteVertexArrays (1, (GLuint[1]) { GPOINTER_TO_UINT (vao) });
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_frame_init (GskGLFrame *self)
|
||||
{
|
||||
self->vaos = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_vao);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_frame_use_program (GskGLFrame *self,
|
||||
const GskGpuShaderOpClass *op_class,
|
||||
guint32 variation,
|
||||
GskGpuShaderClip clip,
|
||||
guint n_external_textures)
|
||||
{
|
||||
GLuint vao;
|
||||
|
||||
gsk_gl_device_use_program (GSK_GL_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self))),
|
||||
op_class,
|
||||
variation,
|
||||
clip,
|
||||
n_external_textures);
|
||||
|
||||
vao = GPOINTER_TO_UINT (g_hash_table_lookup (self->vaos, op_class));
|
||||
if (vao)
|
||||
{
|
||||
glBindVertexArray (vao);
|
||||
return;
|
||||
}
|
||||
glGenVertexArrays (1, &vao);
|
||||
glBindVertexArray (vao);
|
||||
op_class->setup_vao (0);
|
||||
|
||||
g_hash_table_insert (self->vaos, (gpointer) op_class, GUINT_TO_POINTER (vao));
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_frame_bind_globals (GskGLFrame *self)
|
||||
{
|
||||
glBindBufferBase (GL_UNIFORM_BUFFER, 0, self->globals_buffer_id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpuframeprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_FRAME (gsk_gl_frame_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLFrame, gsk_gl_frame, GSK, GL_FRAME, GskGpuFrame)
|
||||
|
||||
void gsk_gl_frame_use_program (GskGLFrame *self,
|
||||
const GskGpuShaderOpClass *op_class,
|
||||
guint32 variation,
|
||||
GskGpuShaderClip clip,
|
||||
guint n_external_textures);
|
||||
|
||||
void gsk_gl_frame_bind_globals (GskGLFrame *self);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -0,0 +1,308 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskglimageprivate.h"
|
||||
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
|
||||
struct _GskGLImage
|
||||
{
|
||||
GskGpuImage parent_instance;
|
||||
|
||||
guint texture_id;
|
||||
guint framebuffer_id;
|
||||
|
||||
GLint gl_internal_format;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
guint owns_texture : 1;
|
||||
};
|
||||
|
||||
struct _GskGLImageClass
|
||||
{
|
||||
GskGpuImageClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLImage, gsk_gl_image, GSK_TYPE_GPU_IMAGE)
|
||||
|
||||
static void
|
||||
gsk_gl_image_get_projection_matrix (GskGpuImage *image,
|
||||
graphene_matrix_t *out_projection)
|
||||
{
|
||||
GskGLImage *self = GSK_GL_IMAGE (image);
|
||||
|
||||
GSK_GPU_IMAGE_CLASS (gsk_gl_image_parent_class)->get_projection_matrix (image, out_projection);
|
||||
|
||||
if (self->texture_id == 0)
|
||||
graphene_matrix_scale (out_projection, 1.f, -1.f, 1.f);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_image_finalize (GObject *object)
|
||||
{
|
||||
GskGLImage *self = GSK_GL_IMAGE (object);
|
||||
|
||||
if (self->framebuffer_id)
|
||||
glDeleteFramebuffers (1, &self->framebuffer_id);
|
||||
|
||||
if (self->owns_texture)
|
||||
glDeleteTextures (1, &self->texture_id);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_image_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_image_class_init (GskGLImageClass *klass)
|
||||
{
|
||||
GskGpuImageClass *image_class = GSK_GPU_IMAGE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
image_class->get_projection_matrix = gsk_gl_image_get_projection_matrix;
|
||||
|
||||
object_class->finalize = gsk_gl_image_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_image_init (GskGLImage *self)
|
||||
{
|
||||
}
|
||||
|
||||
GskGpuImage *
|
||||
gsk_gl_image_new_backbuffer (GskGLDevice *device,
|
||||
GdkMemoryFormat format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskGLImage *self;
|
||||
GskGpuImageFlags flags;
|
||||
GLint swizzle[4];
|
||||
|
||||
self = g_object_new (GSK_TYPE_GL_IMAGE, NULL);
|
||||
|
||||
/* We only do this so these variables get initialized */
|
||||
gsk_gl_device_find_gl_format (device,
|
||||
format,
|
||||
0,
|
||||
&format,
|
||||
&flags,
|
||||
&self->gl_internal_format,
|
||||
&self->gl_format,
|
||||
&self->gl_type,
|
||||
swizzle);
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self), flags, format, width, height);
|
||||
|
||||
/* texture_id == 0 means backbuffer */
|
||||
|
||||
return GSK_GPU_IMAGE (self);
|
||||
}
|
||||
|
||||
GskGpuImage *
|
||||
gsk_gl_image_new (GskGLDevice *device,
|
||||
GdkMemoryFormat format,
|
||||
GskGpuImageFlags required_flags,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
GskGLImage *self;
|
||||
GLint swizzle[4];
|
||||
GskGpuImageFlags flags;
|
||||
gsize max_size;
|
||||
|
||||
max_size = gsk_gpu_device_get_max_image_size (GSK_GPU_DEVICE (device));
|
||||
if (width > max_size || height > max_size)
|
||||
return NULL;
|
||||
|
||||
self = g_object_new (GSK_TYPE_GL_IMAGE, NULL);
|
||||
|
||||
gsk_gl_device_find_gl_format (device,
|
||||
format,
|
||||
required_flags,
|
||||
&format,
|
||||
&flags,
|
||||
&self->gl_internal_format,
|
||||
&self->gl_format,
|
||||
&self->gl_type,
|
||||
swizzle);
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
|
||||
flags,
|
||||
format,
|
||||
width, height);
|
||||
|
||||
glGenTextures (1, &self->texture_id);
|
||||
self->owns_texture = TRUE;
|
||||
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, self->texture_id);
|
||||
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, self->gl_internal_format, width, height, 0, self->gl_format, self->gl_type, NULL);
|
||||
|
||||
/* Only apply swizzle if really needed, might not even be
|
||||
* supported if default values are set
|
||||
*/
|
||||
if (swizzle[0] != GL_RED || swizzle[1] != GL_GREEN || swizzle[2] != GL_BLUE || swizzle[3] != GL_ALPHA)
|
||||
{
|
||||
/* Set each channel independently since GLES 3.0 doesn't support the iv method */
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, swizzle[0]);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, swizzle[1]);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, swizzle[2]);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, swizzle[3]);
|
||||
}
|
||||
|
||||
return GSK_GPU_IMAGE (self);
|
||||
}
|
||||
|
||||
GskGpuImage *
|
||||
gsk_gl_image_new_for_texture (GskGLDevice *device,
|
||||
GdkTexture *owner,
|
||||
GLuint tex_id,
|
||||
gboolean take_ownership,
|
||||
GskGpuImageFlags extra_flags)
|
||||
{
|
||||
GdkMemoryFormat format, real_format;
|
||||
GskGpuImageFlags flags;
|
||||
GskGLImage *self;
|
||||
GLint swizzle[4];
|
||||
|
||||
format = gdk_texture_get_format (owner);
|
||||
|
||||
self = g_object_new (GSK_TYPE_GL_IMAGE, NULL);
|
||||
|
||||
gsk_gl_device_find_gl_format (device,
|
||||
format,
|
||||
0,
|
||||
&real_format,
|
||||
&flags,
|
||||
&self->gl_internal_format,
|
||||
&self->gl_format,
|
||||
&self->gl_type,
|
||||
swizzle);
|
||||
if (format != real_format)
|
||||
flags = GSK_GPU_IMAGE_NO_BLIT |
|
||||
(gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT ? GSK_GPU_IMAGE_STRAIGHT_ALPHA : 0);
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
|
||||
flags | extra_flags,
|
||||
format,
|
||||
gdk_texture_get_width (owner),
|
||||
gdk_texture_get_height (owner));
|
||||
gsk_gpu_image_toggle_ref_texture (GSK_GPU_IMAGE (self), owner);
|
||||
|
||||
self->texture_id = tex_id;
|
||||
self->owns_texture = take_ownership;
|
||||
|
||||
return GSK_GPU_IMAGE (self);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_image_bind_texture (GskGLImage *self)
|
||||
{
|
||||
if (gsk_gpu_image_get_flags (GSK_GPU_IMAGE (self)) & GSK_GPU_IMAGE_EXTERNAL)
|
||||
glBindTexture (GL_TEXTURE_EXTERNAL_OES, self->texture_id);
|
||||
else
|
||||
glBindTexture (GL_TEXTURE_2D, self->texture_id);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_image_bind_framebuffer_target (GskGLImage *self,
|
||||
GLenum target)
|
||||
{
|
||||
GLenum status;
|
||||
|
||||
if (self->framebuffer_id)
|
||||
{
|
||||
glBindFramebuffer (target, self->framebuffer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're the renderbuffer */
|
||||
if (self->texture_id == 0)
|
||||
{
|
||||
glBindFramebuffer (target, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
glGenFramebuffers (1, &self->framebuffer_id);
|
||||
glBindFramebuffer (target, self->framebuffer_id);
|
||||
glFramebufferTexture2D (target, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->texture_id, 0);
|
||||
status = glCheckFramebufferStatus (target);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE:
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
|
||||
g_critical ("glCheckFramebufferStatus() returned GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT. Expect broken rendering.");
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
|
||||
g_critical ("glCheckFramebufferStatus() returned GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS. Expect broken rendering.");
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
|
||||
g_critical ("glCheckFramebufferStatus() returned GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT. Expect broken rendering.");
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED:
|
||||
g_critical ("glCheckFramebufferStatus() returned GL_FRAMEBUFFER_UNSUPPORTED. Expect broken rendering.");
|
||||
break;
|
||||
|
||||
default:
|
||||
g_critical ("glCheckFramebufferStatus() returned %u (0x%x). Expect broken rendering.", status, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_image_bind_framebuffer (GskGLImage *self)
|
||||
{
|
||||
gsk_gl_image_bind_framebuffer_target (self, GL_FRAMEBUFFER);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_gl_image_is_flipped (GskGLImage *self)
|
||||
{
|
||||
return self->texture_id == 0;
|
||||
}
|
||||
|
||||
GLint
|
||||
gsk_gl_image_get_gl_internal_format (GskGLImage *self)
|
||||
{
|
||||
return self->gl_internal_format;
|
||||
}
|
||||
|
||||
GLenum
|
||||
gsk_gl_image_get_gl_format (GskGLImage *self)
|
||||
{
|
||||
return self->gl_format;
|
||||
}
|
||||
|
||||
GLenum
|
||||
gsk_gl_image_get_gl_type (GskGLImage *self)
|
||||
{
|
||||
return self->gl_type;
|
||||
}
|
||||
|
||||
GLuint
|
||||
gsk_gl_image_steal_texture (GskGLImage *self)
|
||||
{
|
||||
g_assert (self->owns_texture);
|
||||
|
||||
if (self->framebuffer_id)
|
||||
{
|
||||
glDeleteFramebuffers (1, &self->framebuffer_id);
|
||||
self->framebuffer_id = 0;
|
||||
}
|
||||
|
||||
self->owns_texture = FALSE;
|
||||
|
||||
return self->texture_id;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpuimageprivate.h"
|
||||
|
||||
#include "gskgldeviceprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_IMAGE (gsk_gl_image_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLImage, gsk_gl_image, GSK, GL_IMAGE, GskGpuImage)
|
||||
|
||||
GskGpuImage * gsk_gl_image_new_backbuffer (GskGLDevice *device,
|
||||
GdkMemoryFormat format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
GskGpuImage * gsk_gl_image_new (GskGLDevice *device,
|
||||
GdkMemoryFormat format,
|
||||
GskGpuImageFlags required_flags,
|
||||
gsize width,
|
||||
gsize height);
|
||||
GskGpuImage * gsk_gl_image_new_for_texture (GskGLDevice *device,
|
||||
GdkTexture *owner,
|
||||
GLuint tex_id,
|
||||
gboolean take_ownership,
|
||||
GskGpuImageFlags extra_flags);
|
||||
|
||||
|
||||
void gsk_gl_image_bind_texture (GskGLImage *self);
|
||||
void gsk_gl_image_bind_framebuffer (GskGLImage *self);
|
||||
void gsk_gl_image_bind_framebuffer_target (GskGLImage *self,
|
||||
GLenum target);
|
||||
|
||||
gboolean gsk_gl_image_is_flipped (GskGLImage *self);
|
||||
GLint gsk_gl_image_get_gl_internal_format (GskGLImage *self);
|
||||
GLenum gsk_gl_image_get_gl_format (GskGLImage *self);
|
||||
GLenum gsk_gl_image_get_gl_type (GskGLImage *self);
|
||||
|
||||
GLuint gsk_gl_image_steal_texture (GskGLImage *self);
|
||||
|
||||
G_END_DECLS
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user