Compare commits

...

89 Commits

Author SHA1 Message Date
Matthias Clasen
4c5fc2db89 Add a test for CSS variables 2024-04-21 14:35:26 -04:00
Alice Mikhaylenko
9faeea801e tmp tests 2024-03-20 23:11:36 +04:00
Alice Mikhaylenko
26aecbb006 tmp: Add libadwaita styles 2024-03-20 23:11:36 +04:00
Alice Mikhaylenko
17ccb849b3 csskeyframes: Support variables 2024-03-20 23:11:36 +04:00
Alice Mikhaylenko
4a3894e820 cssanimation: Recompute values while playing
This will be necessary for supporting variables in animations.
2024-03-20 23:11:36 +04:00
Alice Mikhaylenko
156a7450be cssvalue: Pass an extra GtkCssVariableSet to compute()
This will be useful for supporting variables in @keyframes.
2024-03-20 23:11:35 +04:00
Alice Mikhaylenko
b7988d133d Implement basic support for CSS variables 2024-03-20 22:46:32 +04:00
Alice Mikhaylenko
1baaeeb048 cssvalue: Add contains_variables()
We'll need this to know which values to recompute for animations.
2024-03-20 22:46:32 +04:00
Alice Mikhaylenko
63f489dc64 csstokenizer: Add save() and restore()
We'll need that to check if property values contain variables.
2024-03-20 22:46:32 +04:00
Alice Mikhaylenko
3323f08c75 cssselector: Support :root
This is useful for defining global variables.
2024-03-20 22:46:32 +04:00
Alice Mikhaylenko
35060aae8d cssprovider: Copy bytes when loading
We'll need to keep accessing them later to compute values with variables,
so we can't avoid this anymore.
2024-03-20 22:46:32 +04:00
Alice Mikhaylenko
c6c13ded6a csstokenizer: Fix an out of bounds when reading an ident followed by EOG
TODO: Split this into a separate MR, it's a preexisting bug.
2024-03-20 22:46:32 +04:00
Matthias Clasen
e1406d2e95 Merge branch 'matthiasc/for-main' into 'main'
gsk: Avoid some allocations

See merge request GNOME/gtk!7047
2024-03-18 12:26:37 +00:00
Daniel Rusek
2fe467983c Update Czech translation 2024-03-18 11:30:47 +00:00
Matthias Clasen
ee4a56ed4a settings: Mention the macOS implementation 2024-03-17 21:44:02 -04:00
Matthias Clasen
2408e227aa Add another xfail for clipped compare tests
These just keep happening.
2024-03-17 21:30:36 -04:00
Matthias Clasen
144cd2d91c gsk: Avoid some allocations
We can use a static font options object and allocate it only once.
2024-03-17 21:30:36 -04:00
Matthias Clasen
6abd9def55 Merge branch 'macos-popover-focus' into 'main'
macos: Fix IMContext for popovers

See merge request GNOME/gtk!7041
2024-03-17 16:55:52 +00:00
Martin
f5685cc0ae Update Slovenian translation 2024-03-17 10:28:21 +00:00
Martin
54bd03573e Update Slovenian translation 2024-03-17 10:26:36 +00:00
Matthias Clasen
bc81b33990 Merge branch 'matthiasc/for-main' into 'main'
Forgotten file

See merge request GNOME/gtk!7046
2024-03-17 03:05:56 +00:00
Matthias Clasen
de764d61ef Forgotten file 2024-03-16 22:26:22 -04:00
Matthias Clasen
68fa9bcf2e Merge branch 'matthiasc/for-main' into 'main'
4.14.1

See merge request GNOME/gtk!7045
2024-03-17 02:11:30 +00:00
Matthias Clasen
2f124bc712 Post-release version bump 2024-03-16 22:10:26 -04:00
Matthias Clasen
c648bb7b19 NEWS: Updates 2024-03-16 20:52:15 -04:00
Matthias Clasen
90956b15d9 docs: Small tweaks 2024-03-16 20:52:15 -04:00
Benjamin Otte
195ebf6848 Merge branch 'wip/otte/gl-map-buffer' into 'main'
Add GLBuffer implementation w/ persistent mapping

See merge request GNOME/gtk!7042
2024-03-17 00:27:51 +00:00
Benjamin Otte
0615b48318 Merge branch 'wip/otte/VYycQTm2HrM' into 'main'
gpu: Sort passes correctly

Closes #6318

See merge request GNOME/gtk!7044
2024-03-16 23:08:05 +00:00
Benjamin Otte
aff34e8d1b gpu: Sort passes correctly
In a very particular situation, it could happen that our renderpass
reordering did not work out.
Consider this nesting of renderpasses (indentation indicates subpasses):

pass A
  subpass of A
pass B
  subpass of B

Out reordering code would reorder this as:

subpass of B
subpass of A
pass A
pass B

Which doesn't sound too bad, the subpasses happen before the passes
after all.

However, a subpass might be a pass that converts the image for a texture
stored in the texture cache and then updates the cached image.
If "subpass of A" is such a pass *and* if "subpass of B" then renders
with exactly this texture, then "subpass of B" will use the result of
"subpass of A" as a source.

The fix is to ensure that subpasses stay ordered, too.

The new order moves subpasses right before their parent pass, so the
order of the example now looks like:

subpass of A
pass A
subpass of B
pass B

The place where this would happen most common was when drawing thumbnail
images in Nautilus, the GTK filechooser or Fractal.
Those images are usually PNG files, which are straight alpha. They are then
drawn with a drop shadow, which requires an offscreen for drawing as
well as those images as premultipled sources, so lots of subpasses happen.
If there is then a redraw with a somewhat tricky subregion, then the
slicing of the region code could end up generating 2 passes that each draw
half of the thumbnail image - the first pass drawing the top half and the
second pass drawing the bottom half.
And due to the bug the bottom half would then be drawn from the
offscreen before the actual contents of the offscreen would be drawn,
leading to a corrupt bottom part of the image.

Test included.

Fixes: #6318
2024-03-16 23:44:59 +01:00
Matthias Clasen
c05bb504ff Merge branch 'accessible-leaks' into 'main'
Fix leaks of GtkAccessible and GtkATContext

See merge request GNOME/gtk!7031
2024-03-16 21:39:43 +00:00
Benjamin Otte
47307dc7c1 vulkan: Prefer cached buffer memory
We write the buffers in small chunks, and we even sometimes read it. So
prefer it when it's cached.

Speeds up the text benchmarks by a factor of 3x on my dedicated GPU.
2024-03-16 22:32:49 +01:00
Matthias Clasen
16ea91c1fe Merge branch 'macos-fullscreen-resize' into 'main'
macos: Cleanup fullscreen state

See merge request GNOME/gtk!7043
2024-03-16 21:27:29 +00:00
Benjamin Otte
96b800fa0c gl: Add buffer implementation using persistent mapping
If glBufferStorage() is available, we can replace our usage of
glBufferSubData() with persistently mapped storage via
glMappedBufferRange().

This has 1 disadvantage:

1. It's not supported everywhere, it requires GL 4.4 or
   GL_EXT_buffer_storage. But every GPU of the last 10 years should
   implement it. So we check for it and keep the old code.
   The old code can also be forced via GDK_GL_DISABLE=buffer-storage.

But it has 2 advantages:

1. It is what Vulkan does, so it unifies the two renderers' buffer
   handling.

2. It is a significant performance boost in use cases with large vertex
   buffers. Those are pretty rare, but do happen with lots of text at a
   small font size. An example would be a small font in a maximized VTE
   terminal or the overview in gnome-text-editor.

A custom benchmark tailored for this problem can be created with:

  tests/rendernode-create-tests 1000000 text.node

This creates a node file called "text.node" that draws 1 million text
nodes.
(Creating that test takes a minute or so. A smaller number may be useful
on less powerful hardware than my Intel Tigerlake laptop.)
The difference can then be compared via:

  tools/gtk4-rendernode-tool benchmark --runs=20 text.node
and
  GDK_GL_DISABLE=buffer-storage tools/gtk4-rendernode-tool benchmark --runs=20 text.node

For my laptop, the difference is:
before: 1.1s
after:  0.8s

Related: !7021
2024-03-16 20:55:26 +01:00
Benjamin Otte
e7a2baf78c gpu: Remove unused arguments
It's not just unused, it's also wrong.

We are reading from the buffer when reallocating the vertex buffer
and memcpy()ing the old into the new buffer - at that point we read from
it.
2024-03-16 19:46:37 +01:00
Matthias Clasen
438d86fcf5 gsk: Move the buffer upload counter
Move the sysprof counter for buffer uploads to the generic
code, so it works for both ngl and Vulkan. This partially
reverts commit ecf1b7c18a.
2024-03-16 19:39:16 +01:00
Arjan Molenaar
4fd848c9de macos: Retrieve NSEvents based on event properties
We cannot depend on the exact event, since some events (e.g. for popups)
are rewritten. Therefore we need to determine the NSEvent based on
heuristics. The usual suspects are event type, device and timestamp.

This allows us to fix IMContext for popups.
2024-03-16 17:25:38 +01:00
Matthias Clasen
a23a7d4149 Merge branch 'maze-demo' into 'main'
demos: Make the maze demo non-resizable

Closes #6549

See merge request GNOME/gtk!7040
2024-03-16 14:41:27 +00:00
Matthias Clasen
1cbdf88b0f Merge branch 'debug-cleanup' into 'main'
gsk: Fix a typo

See merge request GNOME/gtk!7039
2024-03-16 14:41:16 +00:00
Benjamin Otte
0a0feef57d Merge branch 'wip/otte/gdk-gl-disable' into 'main'
Rework GL feature handling

See merge request GNOME/gtk!7038
2024-03-16 14:25:11 +00:00
Matthias Clasen
2701a2bfdd demos: Make the maze demo non-resizable
It isn't playable if the entrance/exit don't reach the edge
of the window.

Fixes: #6549
2024-03-16 10:08:37 -04:00
Benjamin Otte
2aea75f426 testsuite: Run the plain test without any args
Never do nothing.
2024-03-16 14:53:22 +01:00
Matthias Clasen
b1fb7cd4ae gsk: Drop unused debug flags
The 'surface', 'sync' and 'opengl' flags are not used anywhere.
2024-03-16 09:44:57 -04:00
Matthias Clasen
33ffe28236 docs: Clarify GSK_DEBUG=vulkan
Make it clearer what this debug flag does.
2024-03-16 09:44:57 -04:00
Matthias Clasen
fd90b56df6 gsk: Move and clarify a debug message
Move the only error message in the OPENGL category to RENDERER,
and make it clearer what and how.
2024-03-16 09:44:57 -04:00
Benjamin Otte
43373e6350 gpu: Rename env var GSK_GPU_SKIP to GSK_GPU_DISABLE
See previous commits.
2024-03-16 14:11:08 +01:00
Benjamin Otte
afd5ea53d8 vulkan: Rename env var from GDK_VULKAN_SKIP to GDK_VULKAN_DISABLE
It's a better name.
2024-03-16 14:03:36 +01:00
Benjamin Otte
f725bdad25 gl: Move GL_ARB_base_instance check
It's a GLContext feature check, not a GpuRenderer thing.

So put it there.
2024-03-16 13:52:28 +01:00
Benjamin Otte
cfbe3709bf gpu: Respect the GDK_GL_DISABLE flag
It's now possible to disable sync support.
2024-03-16 13:52:21 +01:00
Benjamin Otte
4e453acd4f gl: Remove the BGRA feature
Nobody is using it anymore now that we have format tracking for all
formats.
2024-03-16 13:44:02 +01:00
Benjamin Otte
3a04542146 gl: Add GDK_GL_DISABLE env var
This allows disabling certain GL features for testing, same as with
Vulkan.
2024-03-16 13:44:02 +01:00
Benjamin Otte
d6a1eb1b2f gl: Split out function
This splits feature checks into its own function.

Which in turn allows splitting the check from the actual reaction to the
flags.
2024-03-16 13:44:02 +01:00
Benjamin Otte
802110bfe5 vulkan: Change function prototype
The function cannot return an error, so don't make that possible.
2024-03-16 13:44:02 +01:00
Benjamin Otte
141769fb46 gl: Turn has_foo flags into GdkGLFeatures
The goal is to have it mirror GdkVulkanFeatures, and in particular
having an environment variable to turn individual flags off.
2024-03-16 13:44:02 +01:00
Benjamin Otte
0fdb6a9243 gl: Remove an unnecessary make_current()
This function is called only from make_current() after all, so the
context is already current.
2024-03-16 13:44:02 +01:00
Benjamin Otte
d007d136c5 Merge branch 'wip/otte/merge-ops' into 'main'
Speed up stuff

See merge request GNOME/gtk!7036
2024-03-16 09:43:06 +00:00
Matthias Clasen
cb374efb9a Merge branch 'matthiasc/for-main' into 'main'
gdk: Describe egl formats more precisely

See merge request GNOME/gtk!7037
2024-03-16 02:12:16 +00:00
Matthias Clasen
8334d21c87 gdk: Describe egl formats more precisely
Mention the presence of a depth of stencil buffer.

Related: #6542
2024-03-15 21:52:23 -04:00
Matthias Clasen
6e132463f1 Merge branch 'matthiasc/for-main' into 'main'
glcontext: Don't call get_instance_private (NULL)

See merge request GNOME/gtk!7035
2024-03-15 21:59:49 +00:00
Arjan Molenaar
3f8f6f6792 macos: Let host determine window sizes
Clean up lastUnfullscreenFrame attribute, as we do not really
need it. The application knows what to resize to.
2024-03-15 21:55:44 +01:00
Benjamin Otte
93cdcc5e88 gpu: Merge multiple ops into one ShaderOp
When ops get allocated that use the same stats as the last op, put them
into the same ShaderOp. This reduces the number of ShaderOps we need to
record, which has 3 benefits:

1. It's less work when iterating over all the ops.
   This isn't a big win, but it makes submit() and print() run a bit
   faster.
2. We don't need to manage data per-op.
   This is a large win because we don't need to ref/unref descriptors
   as much anymore, and refcounting is visible on profiles.
3. We save memory.
   This is a pretty big win because we iterate over ops a lot, and when
   the array is large enough (I've managed to write testcases that makes
   it grow to over 4GB) it kills all the caches and that's bad.

The main benefit of all this are glyphs, which used to emit 1 ShaderOp
per glyph and can now end up with 1 ShaderOp for multiple text nodes,
even if those text nodes use different fonts or colors - because they
can all share the same ColorizeOp.
2024-03-15 20:25:02 +01:00
Matthias Clasen
d51912c0b4 gsk: Add gsk_gpu_frame_get_last_op
This function will be used in the future to find the previous
op during node processing, so we can make optimization decisions
based on that.
2024-03-15 20:25:02 +01:00
Benjamin Otte
bad6e1e102 gpu: Change the way we merge draw calls
With potentially multiple ops per ShaderOp, we may encounter situations
where 1 ShaderOp contains more ops than we want to merge. (With
GSK_GPU_SKIP=merge, we don't want to merge at all.)

So we still merge the ShaderOps (now unconditionally), but we then run
a loop that potentially splits the merged ops again - exactly at the
point we want to.

This way we can merge ops inside of ShaderOps and merge ShaderOps, but
still have the draw calls contain the exact number of ops we want.
2024-03-15 20:25:02 +01:00
Benjamin Otte
28a8dc5a14 gpu: Add GskGpuShaderOp.n_ops
This just introduces the variable and sets it to 1 everywhere.

The ultimate goal is to allow one ShaderOp to collect multiple ops into
one, thereby saving memory in the ops array and leading to faster
performance.
2024-03-15 19:49:17 +01:00
Benjamin Otte
975cdd8c30 gpu: Remove unused return value from function
Technically, an alloc() function should return what it allocated. But
the return value is never used.

Maybe we should rename the function?
2024-03-15 19:49:17 +01:00
Benjamin Otte
153b78e2bc gpu: Add a ShaderOp.print_instance vfunc
... and add gsk_shader_op_print() to do the generic stuff.
2024-03-15 19:49:17 +01:00
Benjamin Otte
de2b10e46c gpu: Set variable to NULL after freeing
Saw this while reviewing code.
2024-03-15 19:49:17 +01:00
Matthias Clasen
7cf4414f4a ci: Drop some unnecessary packages
We don't use at, at-spi or the docbook stylesheets.
2024-03-15 13:06:54 -04:00
Matthias Clasen
a9dfec8478 glcontext: Don't call get_instance_private (NULL)
ubsan does not like this.

See a9175e0c03 for a detailed explanation.
2024-03-15 13:06:34 -04:00
Matthias Clasen
60ddf7c421 Merge branch 'wip/smcv/no-zink-when-screen-scraping' into 'main'
testsuite: Force Mesa to use software GL when asserting about stderr

Closes #6478

See merge request GNOME/gtk!6949
2024-03-15 17:05:12 +00:00
Tim Sabsch
1922174c9f Update German translation 2024-03-14 20:36:56 +00:00
Changwoo Ryu
3c39c5259e Update Korean translation 2024-03-14 10:57:06 +00:00
Matthias Clasen
f5a6d93939 Merge branch 'wip/otte/who-framed-roger-rabbit' into 'main'
Don't reuse frames while they're in use

See merge request GNOME/gtk!7030
2024-03-14 10:21:34 +00:00
Benjamin Otte
30dddf2412 gpu: Refactor waiting for frames
Instead of having renderer API to wait for any number of frames, just
have gsk_gpu_frame_wait() to wait for a single frame.

This unifies behavior on Vulkan and GL, because unlike Vulkan, GL does
not allow waiting for multiple fences.

To make up for it, we replace waiting for multiple frames with finding
the frame with the earliest timestamp and waiting for that one.

Also implement wait() for GL.
2024-03-14 06:06:33 +01:00
Elliott Sales de Andrade
19a9215e4f Fix leaks of GtkAccessible and GtkATContext
These variables are all assigned from function calls that are transfer
full, so they need an unref.
2024-03-14 00:50:17 -04:00
Benjamin Otte
b43950d0f7 gpu: Don't reuse frames while they're in use
This copies the Vulkan idea of using a fence at the end of command
submission and waiting until it gets signaled before reusing the frame.

This frees up the GL driver from doing the work of making buffers etc
reusable and instead allocates new ones when they're still in use and is
a pretty massive performance win.
2024-03-14 04:53:12 +01:00
Matthias Clasen
6e5a183c98 Merge branch 'matthiasc/for-main' into 'main'
gtk-demo: Skip gl shader when necessary

Closes #6538

See merge request GNOME/gtk!7029
2024-03-14 01:29:32 +00:00
Matthias Clasen
d224110b48 gtk-demo: Skip the transitions demo when necessary
This demo uses GL shader nodes which only work with the GL renderer,
therefore skip the demo unless the GL renderer is in use.

Fixes: #6538
2024-03-13 21:02:17 -04:00
Matthias Clasen
8f356c2e8c gtk-demo: Skip gl shader when necessary
GL shader nodes only work with the GL renderer, therefore skip
the Shader in the list unless the GL renderer is in use.

Fixes: #6538
2024-03-13 21:02:10 -04:00
Matthias Clasen
139ed2c900 Merge branch 'textview-cursor-anchor' into 'main'
textview: Fix cursor/anchor mixup when retrieving surrounding text

Closes #6460

See merge request GNOME/gtk!6929
2024-03-14 00:07:41 +00:00
Matthias Clasen
32e21d5402 Merge branch 'speedup-inner-loop' into 'main'
Simplify our inner loop

See merge request GNOME/gtk!7026
2024-03-13 12:41:43 +00:00
Marek Kasik
fb3d8b8523 printing: Avoid accessing freed printers
Print backend can be disposed together with all its printers
as a reaction to user stopping enumeration of printers.
Adding a weak pointer help us to detect that the backend
was disposed and hence the backend and its printers should not
be used anymore.

Fixes #6265
2024-03-13 11:17:42 +01:00
Matthias Clasen
380523b41b gsk: Eschew more divisions
Pull out a pango_scale_inv constant, and use it.
2024-03-13 01:26:14 -04:00
Matthias Clasen
2fda256bb0 gsk: Avoid some unnecessary calls
Most of the time, the image we get for the glyphs will be the
same (the atlas), so avoid adding it to the descriptor set over
and over, and check first if have to. This matches what the
pattern variant of this function already does.
2024-03-13 01:03:32 -04:00
Matthias Clasen
c71a66b6f6 gsk: Simplify our inner loop
Pull out the if-else and precompute things before the loop.
2024-03-13 01:03:31 -04:00
Matthias Clasen
cb92778478 gsk: Drop the glyph-align flag
It wasn't doing anymore what it was designed for, and we are not
sure that we need it.
2024-03-13 01:00:49 -04:00
Matthias Clasen
ab67936a64 Merge branch 'matthiasc/for-main' into 'main'
Drop an unused header

See merge request GNOME/gtk!7025
2024-03-13 04:44:07 +00:00
Matthias Clasen
0ae2c1a8a7 Drop an unused header
This came in with a GskPath-related merge, but it isn't used
anywhere. So drop it for now.
2024-03-12 22:14:31 -04:00
Simon McVittie
85cf995af7 testsuite: Force Mesa to use software GL when asserting about stderr
In an autobuilder environment, there will typically be no hardware GPU
available, so Mesa will fall back from hardware to Zink to software
rendering. Unfortunately, Zink logs to stderr during loading if no
hardware GPUs are available. This particular test asserts that stderr
has desired contents, which means Zink's extra output causes the test
to fail. We can bypass this by disabling use of Zink.

Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/6478
Signed-off-by: Simon McVittie <smcv@debian.org>
2024-02-26 13:23:11 +00:00
Sebastian Keller
575bd64698 textview: Fix cursor/anchor mixup when retrieving surrounding text
Previously the code for calculating the cursor and anchor for the
flipped case was mixed up with the logic for the non-flipped case.

Additionally make the code more readable by making the anchor/selection
bound the start and the cursor/insert the end of a selection. Thus a
selection made from left to right goes from start to end. Selections
from right to left, i.e. end to start are considered flipped.

Also update the test to use the correct cursor/anchor and change some
variable names to make it more readable.

Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/6460
2024-02-22 20:49:10 +01:00
230 changed files with 14018 additions and 5192 deletions

View File

@@ -2,8 +2,6 @@ FROM fedora:39
RUN dnf -y install \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
@@ -18,7 +16,6 @@ RUN dnf -y install \
dejavu-sans-mono-fonts \
desktop-file-utils \
diffutils \
docbook-style-xsl \
elfutils-libelf-devel \
expat-devel \
fribidi-devel \

41
NEWS
View File

@@ -1,6 +1,45 @@
Overview of Changes in 4.14.1, xx-xx-xxxx
Overview of Changes in 4.14.2, xx-xx-xxxx
=========================================
Overview of Changes in 4.14.1, 16-03-2024
=========================================
* GtkTextView:
- Fix a mixup of cursor and anchor when retrieving surrounding text
in input methods
* Printing:
- Avoid accessing freed printers
* Accessibility:
- Fix memory leaks
* GDK:
- Rename the GDK_VULKAN_SKIP environment variable to GDK_VULKAN_DISABLE
- Add a GDK_GL_DISABLE environment variable
* GSK:
- Rename the GSK_GPU_SKIP environment variable to GSK_GPU_DISABLE
- Speed up handling of repeated ops, which should help for text
- Speed up the inner loop of text node conversion
- Drop the glyph-align optimization flag
- ngl: Avoid reusing frames while they are in use
- Fix flickering thumbnails in nautilus
- Speed up buffer handling in both ngl and Vulkan
* Demos:
- Skip demos using gl shaders when we're not using the gl renderer
* Build:
- Fix some ubsan warnings
- Avoid zink in ci since it spams stderr
* Translation updates:
Czech
German
Korean
Russian
Overview of Changes in 4.14.0, 12-03-2024
=========================================

View File

@@ -184,6 +184,12 @@ create_cogs (void)
return picture;
}
static gboolean
check_cogs (GtkFishbowl *fb)
{
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (gtk_widget_get_native (GTK_WIDGET (fb))));
}
static void
mapped (GtkWidget *w)
{
@@ -218,36 +224,41 @@ create_graph (void)
static const struct {
const char *name;
GtkWidget * (*create_func) (void);
GtkWidget * (* create_func) (void);
gboolean (* check) (GtkFishbowl *fb);
} widget_types[] = {
{ "Icon", create_icon },
{ "Button", create_button },
{ "Blurbutton", create_blurred_button },
{ "Fontbutton", create_font_button },
{ "Levelbar", create_level_bar },
{ "Label", create_label },
{ "Spinner", create_spinner },
{ "Spinbutton", create_spinbutton },
{ "Video", create_video },
{ "Gears", create_gears },
{ "Switch", create_switch },
{ "Menubutton", create_menu_button },
{ "Shader", create_cogs },
{ "Tiger", create_tiger },
{ "Graph", create_graph },
{ "Icon", create_icon, NULL },
{ "Button", create_button, NULL },
{ "Blurbutton", create_blurred_button, NULL },
{ "Fontbutton", create_font_button, NULL },
{ "Levelbar", create_level_bar, NULL },
{ "Label", create_label, NULL },
{ "Spinner", create_spinner, NULL },
{ "Spinbutton", create_spinbutton, NULL },
{ "Video", create_video, NULL },
{ "Gears", create_gears, NULL },
{ "Switch", create_switch, NULL },
{ "Menubutton", create_menu_button, NULL },
{ "Shader", create_cogs, check_cogs },
{ "Tiger", create_tiger, NULL },
{ "Graph", create_graph, NULL },
};
static int selected_widget_type = -1;
static const int N_WIDGET_TYPES = G_N_ELEMENTS (widget_types);
static void
static gboolean
set_widget_type (GtkFishbowl *fishbowl,
int widget_type_index)
{
GtkWidget *window;
if (widget_type_index == selected_widget_type)
return;
return TRUE;
if (widget_types[widget_type_index].check != NULL &&
!widget_types[widget_type_index].check (fishbowl))
return FALSE;
selected_widget_type = widget_type_index;
@@ -257,6 +268,8 @@ set_widget_type (GtkFishbowl *fishbowl,
window = GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (fishbowl)));
gtk_window_set_title (GTK_WINDOW (window),
widget_types[selected_widget_type].name);
return TRUE;
}
G_MODULE_EXPORT void
@@ -264,14 +277,17 @@ fishbowl_next_button_clicked_cb (GtkButton *source,
gpointer user_data)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
int new_index = selected_widget_type;
if (selected_widget_type + 1 >= N_WIDGET_TYPES)
new_index = 0;
else
new_index = selected_widget_type + 1;
do
{
if (new_index + 1 >= N_WIDGET_TYPES)
new_index = 0;
else
new_index = new_index + 1;
set_widget_type (fishbowl, new_index);
}
while (!set_widget_type (fishbowl, new_index));
}
G_MODULE_EXPORT void
@@ -279,14 +295,18 @@ fishbowl_prev_button_clicked_cb (GtkButton *source,
gpointer user_data)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
int new_index = selected_widget_type;
if (selected_widget_type - 1 < 0)
new_index = N_WIDGET_TYPES - 1;
else
new_index = selected_widget_type - 1;
do
{
if (new_index - 1 < 0)
new_index = N_WIDGET_TYPES - 1;
else
new_index = new_index - 1;
set_widget_type (fishbowl, new_index);
}
while (!set_widget_type (fishbowl, new_index));
}
G_MODULE_EXPORT void

View File

@@ -827,13 +827,25 @@ demo_search_changed_cb (GtkSearchEntry *entry,
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static gboolean
demo_can_run (GtkWidget *window,
const char *name)
{
if (name != NULL && strcmp (name, "gltransition") == 0)
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (GTK_NATIVE (window)));
return TRUE;
}
static GListModel *
create_demo_model (void)
create_demo_model (GtkWidget *window)
{
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
DemoData *demo = gtk_demos;
GtkDemo *d;
gtk_widget_realize (window);
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
d->name = "main";
d->title = "GTK Demo";
@@ -845,16 +857,20 @@ create_demo_model (void)
while (demo->title)
{
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
DemoData *children = demo->children;
DemoData *children = demo->children;
d->name = demo->name;
d->title = demo->title;
d->keywords = demo->keywords;
d->filename = demo->filename;
d->func = demo->func;
if (demo_can_run (window, demo->name))
{
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
g_list_store_append (store, d);
d->name = demo->name;
d->title = demo->title;
d->keywords = demo->keywords;
d->filename = demo->filename;
d->func = demo->func;
g_list_store_append (store, d);
}
if (children)
{
@@ -862,15 +878,19 @@ create_demo_model (void)
while (children->title)
{
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
if (demo_can_run (window, children->name))
{
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
child->name = children->name;
child->title = children->title;
child->keywords = children->keywords;
child->filename = children->filename;
child->func = children->func;
child->name = children->name;
child->title = children->title;
child->keywords = children->keywords;
child->filename = children->filename;
child->func = children->func;
g_list_store_append (G_LIST_STORE (d->children_model), child);
}
g_list_store_append (G_LIST_STORE (d->children_model), child);
children++;
}
}
@@ -936,7 +956,7 @@ activate (GApplication *app)
search_bar = GTK_WIDGET (gtk_builder_get_object (builder, "searchbar"));
g_signal_connect (search_bar, "notify::search-mode-enabled", G_CALLBACK (clear_search), NULL);
listmodel = create_demo_model ();
listmodel = create_demo_model (window);
treemodel = gtk_tree_list_model_new (G_LIST_MODEL (listmodel),
FALSE,
TRUE,

View File

@@ -338,7 +338,7 @@ do_path_maze (GtkWidget *do_widget)
GskPath *path;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_title (GTK_WINDOW (window), "Follow the maze with the mouse");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);

View File

@@ -38,13 +38,13 @@ can run the build, using Ninja:
```
cd builddir
ninja
ninja install
meson compile
meson install
```
If you don't have permission to write to the directory you are
installing in, you may have to change to root temporarily before
running `ninja install`.
running `meson install`.
Several environment variables are useful to pass to set before
running *meson*. `CPPFLAGS` contains options to pass to the C
@@ -112,10 +112,10 @@ responsible for controlling the debugging features of GTK with
## Dependencies
Before you can compile the GTK widget toolkit, you need to have
various other tools and libraries installed on your
system. Dependencies of GTK have their own build systems, so
you will need to refer to their own installation instructions.
Before you can compile GTK, you need to have various other tools and
libraries installed on your system. Dependencies of GTK have their own
build systems, so you will need to refer to their own installation
instructions.
A particular important tool used by GTK to find its dependencies
is `pkg-config`.
@@ -156,8 +156,8 @@ Other libraries are maintained separately.
the development environment for these libraries that your
operating system vendor provides.
- The [fontconfig](https://www.freedesktop.org/wiki/Software/fontconfig/)
library provides Pango with a standard way of locating
fonts and matching them against font names.
library provides Pango with a standard way of locating fonts and matching
them against font names.
- [Cairo](https://www.cairographics.org) is a graphics library that
supports vector graphics and image compositing. Both Pango and GTK
use Cairo for drawing. Note that we also need the auxiliary cairo-gobject
@@ -220,13 +220,12 @@ meson configure builddir
### `x11-backend`, `win32-backend`, `broadway-backend`, `wayland-backend` and `macos-backend`
Enable specific backends for GDK. If none of these options
are given, the Wayland backend will be enabled by default,
if the platform is Linux; the X11 backend will also be enabled
by default, unless the platform is Windows, in which case the
default is win32, or the platform is macOS, in which case the
default is macOS. If any backend is explicitly enabled or disabled,
no other platform will be enabled automatically.
Enable specific backends for GDK. If none of these options are given, the
Wayland backend will be enabled by default, if the platform is Linux; the
X11 backend will also be enabled by default, unless the platform is Windows,
in which case the default is win32, or the platform is macOS, in which case
the default is macOS. If any backend is explicitly enabled or disabled, no
other platform will be enabled automatically.
### `vulkan`

View File

@@ -1,7 +1,7 @@
Title: CSS in GTK
Slug: css
This chapter describes how GTK uses CSS for styling and layout.
This chapter describes how GTK uses CSS for styling and layout.
It is not meant to be an explanation of CSS from first principles,
but focuses on listing supported CSS features and differences
between Web CSS and GTK.

View File

@@ -28,6 +28,9 @@ GTK depends on the following libraries:
- **OpenGL**: OpenGL is the premier environment for developing portable,
interactive 2D and 3D graphics applications. More information available
on the [Khronos website][opengl].
- **Vulkan**: Vulkan is the a newer graphics API, that can be considered
the successor of OpenGL. More information available on the
[Khronos website][vulkan].
- **Pango**: Pango is a library for internationalized text handling. It
centers around the `PangoLayout` object, representing a paragraph of
text. Pango provides the engine for `GtkTextView`, `GtkLabel`,
@@ -60,6 +63,7 @@ GTK is divided into three parts:
[gio]: https://developer.gnome.org/gio/stable/
[cairo]: https://www.cairographics.org/manual/
[opengl]: https://www.opengl.org/about/
[vulkan]: https://www.vulkan.org/
[pango]: https://pango.gnome.org/
[gdkpixbuf]: https://developer.gnome.org/gdk-pixbuf/stable/
[graphene]: https://ebassi.github.io/graphene/

View File

@@ -278,14 +278,11 @@ are only available when GTK has been configured with `-Ddebug=true`.
: OpenGL renderer information
`vulkan`
: Vulkan renderer information
: Check Vulkan errors
`shaders`
: Information about shaders
`surface`
: Information about surfaces
`fallback`
: Information about fallback usage in renderers
@@ -303,9 +300,6 @@ A number of options affect behavior instead of logging:
`full-redraw`
: Force full redraws
`sync`
: Sync after each frame
`staging`
: Use a staging image for texture upload (Vulkan only)
@@ -347,6 +341,28 @@ a `*`, which means: try all remaining backends. The special value
backends. For more information about selecting backends,
see the [func@Gdk.DisplayManager.get] function.
### `GDK_GL_DISABLE`
This variable can be set to a list of values, which cause GDK to
disable extension features of the OpenGL support.
Note that these features may already be disabled if the GL driver
does not support them.
`debug`
: GL_KHR_debug
`unpack-subimage`
:GL_EXT_unpack_subimage
`half-float`
:GL_OES_vertex_half_float
`sync`
:GL_ARB_sync
`base-instance`
:GL_EXT_base_instance
### `GDK_VULKAN_DEVICE`
This variable can be set to the index of a Vulkan device to override
@@ -354,7 +370,7 @@ 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`
### `GDK_VULKAN_DISABLE`
This variable can be set to a list of values, which cause GDK to
disable features of the Vulkan support.
@@ -434,7 +450,7 @@ using and the GDK backend supports them:
installation.
### `GSK_GPU_SKIP`
### `GSK_GPU_DISABLE`
This variable can be set to a list of values, which cause GSK to
disable certain optimizations of the "ngl" and "vulkan" renderer.
@@ -454,9 +470,6 @@ disable certain optimizations of the "ngl" and "vulkan" renderer.
`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.
@@ -469,10 +482,10 @@ n seconds. The default timeout is 15 seconds.
### `GSK_MAX_TEXTURE_SIZE`
Limit texture size to the minimum of this value and the OpenGL limit
for texture sizes. This can be used to debug issues with texture slicing
on systems where the OpenGL texture size limit would otherwise make
texture slicing difficult to test.
Limit texture size to the minimum of this value and the OpenGL limit for
texture sizes in the "gl" renderer. This can be used to debug issues with
texture slicing on systems where the OpenGL texture size limit would
otherwise make texture slicing difficult to test.
### `GTK_CSD`

View File

@@ -1538,6 +1538,7 @@ describe_egl_config (EGLDisplay egl_display,
EGLConfig egl_config)
{
EGLint red, green, blue, alpha, type;
EGLint depth, stencil;
if (egl_config == NULL)
return g_strdup ("-");
@@ -1556,7 +1557,15 @@ describe_egl_config (EGLDisplay egl_display,
else
type = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
return g_strdup_printf ("R%dG%dB%dA%d%s", red, green, blue, alpha, type == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float");
if (!eglGetConfigAttrib (egl_display, egl_config, EGL_DEPTH_SIZE, &depth))
depth = 0;
if (!eglGetConfigAttrib (egl_display, egl_config, EGL_STENCIL_SIZE, &stencil))
stencil = 0;
return g_strdup_printf ("R%dG%dB%dA%d%s%s%s", red, green, blue, alpha,
type == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT ? "" : " float",
depth > 0 ? ", depth buffer" : "",
stencil > 0 ? ", stencil buffer" : "");
}
gpointer

View File

@@ -125,7 +125,7 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
* the GL_UNPACK_ROW_LENGTH support
*/
if (gdk_gl_context_get_use_es (paint_context) &&
!(version >= 300 || gdk_gl_context_has_unpack_subimage (paint_context)))
!(version >= 300 || gdk_gl_context_has_feature (paint_context, GDK_GL_FEATURE_UNPACK_SUBIMAGE)))
return;
/* TODO: avoid reading back non-required data due to dest clip */

View File

@@ -103,6 +103,15 @@
#define DEFAULT_ALLOWED_APIS GDK_GL_API_GL | GDK_GL_API_GLES
static const GdkDebugKey gdk_gl_feature_keys[] = {
{ "debug", GDK_GL_FEATURE_DEBUG, "GL_KHR_debug" },
{ "unpack-subimage", GDK_GL_FEATURE_UNPACK_SUBIMAGE, "GL_EXT_unpack_subimage" },
{ "half-float", GDK_GL_FEATURE_VERTEX_HALF_FLOAT, "GL_OES_vertex_half_float" },
{ "sync", GDK_GL_FEATURE_SYNC, "GL_ARB_sync" },
{ "base-instance", GDK_GL_FEATURE_BASE_INSTANCE, "GL_ARB_base_instance" },
{ "buffer-storage", GDK_GL_FEATURE_BUFFER_STORAGE, "GL_EXT_buffer_storage" },
};
typedef struct _GdkGLContextPrivate GdkGLContextPrivate;
struct _GdkGLContextPrivate
@@ -112,13 +121,9 @@ struct _GdkGLContextPrivate
GdkGLMemoryFlags memory_flags[GDK_MEMORY_N_FORMATS];
guint has_khr_debug : 1;
GdkGLFeatures features;
guint use_khr_debug : 1;
guint has_half_float : 1;
guint has_sync : 1;
guint has_unpack_subimage : 1;
guint has_debug_output : 1;
guint has_bgra : 1;
guint extensions_checked : 1;
guint debug_enabled : 1;
guint forward_compatible : 1;
@@ -290,7 +295,7 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
GdkDisplay *display = gdk_gl_context_get_display (context);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
GdkGLContext *share = gdk_display_get_gl_context (display);
GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share);
GdkGLContextPrivate *share_priv = share ? gdk_gl_context_get_instance_private (share) : NULL;
EGLConfig egl_config;
EGLContext ctx;
EGLint context_attribs[N_EGL_ATTRS], i = 0, flags = 0;
@@ -898,11 +903,12 @@ gdk_gl_context_label_object_printf (GdkGLContext *context,
gboolean
gdk_gl_context_has_unpack_subimage (GdkGLContext *context)
gdk_gl_context_has_feature (GdkGLContext *self,
GdkGLFeatures feature)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_unpack_subimage;
return (priv->features & feature) == feature;
}
static gboolean
@@ -1664,10 +1670,53 @@ gdk_gl_version_init_epoxy (GdkGLVersion *version)
*version = GDK_GL_VERSION_INIT (epoxy_version / 10, epoxy_version % 10);
}
static GdkGLFeatures
gdk_gl_context_check_features (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLFeatures features = 0;
if (gdk_gl_context_get_use_es (context))
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage"))
features |= GDK_GL_FEATURE_UNPACK_SUBIMAGE;
}
else
{
features |= GDK_GL_FEATURE_UNPACK_SUBIMAGE;
}
if (epoxy_has_gl_extension ("GL_KHR_debug"))
features |= GDK_GL_FEATURE_DEBUG;
if (gdk_gl_context_check_version (context, "3.0", "3.0") ||
epoxy_has_gl_extension ("GL_OES_vertex_half_float"))
features |= GDK_GL_FEATURE_VERTEX_HALF_FLOAT;
if (gdk_gl_context_check_version (context, "3.2", "3.0") ||
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync"))
features |= GDK_GL_FEATURE_SYNC;
if (gdk_gl_context_check_version (context, "4.2", "9.9") ||
epoxy_has_gl_extension ("GL_EXT_base_instance") ||
epoxy_has_gl_extension ("GL_ARB_base_instance"))
features |= GDK_GL_FEATURE_BASE_INSTANCE;
if (gdk_gl_context_check_version (context, "4.4", "9.9") ||
epoxy_has_gl_extension ("GL_EXT_buffer_storage") ||
epoxy_has_gl_extension ("GL_ARB_buffer_storage"))
features |= GDK_GL_FEATURE_BUFFER_STORAGE;
return features;
}
static void
gdk_gl_context_check_extensions (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLFeatures supported_features, disabled_features;
gboolean gl_debug = FALSE;
GdkDisplay *display;
@@ -1685,69 +1734,54 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
if (priv->has_debug_output && gl_debug)
{
gdk_gl_context_make_current (context);
glEnable (GL_DEBUG_OUTPUT);
glEnable (GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback (gl_debug_message_callback, NULL);
}
if (gdk_gl_context_get_use_es (context))
{
priv->has_unpack_subimage = gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage");
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
priv->has_bgra = epoxy_has_gl_extension ("GL_EXT_texture_format_BGRA8888");
}
else
{
priv->has_unpack_subimage = TRUE;
priv->has_khr_debug = epoxy_has_gl_extension ("GL_KHR_debug");
priv->has_bgra = TRUE;
/* If we asked for a core profile, but didn't get one, we're in legacy mode */
if (!gdk_gl_context_get_use_es (context) &&
!gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
priv->is_legacy = TRUE;
/* We asked for a core profile, but we didn't get one, so we're in legacy mode */
if (!gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
priv->is_legacy = TRUE;
}
supported_features = gdk_gl_context_check_features (context);
disabled_features = gdk_parse_debug_var ("GDK_GL_DISABLE",
gdk_gl_feature_keys,
G_N_ELEMENTS (gdk_gl_feature_keys));
if (priv->has_khr_debug && gl_debug)
priv->features = supported_features & ~disabled_features;
gdk_gl_context_init_memory_flags (context);
if ((priv->features & GDK_GL_FEATURE_DEBUG) && gl_debug)
{
priv->use_khr_debug = TRUE;
glGetIntegerv (GL_MAX_LABEL_LENGTH, &priv->max_debug_label_length);
}
priv->has_half_float = gdk_gl_context_check_version (context, "3.0", "3.0") ||
epoxy_has_gl_extension ("GL_OES_vertex_half_float");
priv->has_sync = gdk_gl_context_check_version (context, "3.2", "3.0") ||
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync");
gdk_gl_context_init_memory_flags (context);
{
int max_texture_size;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
GDK_DISPLAY_DEBUG (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), OPENGL,
"%s version: %d.%d (%s)\n"
"* GLSL version: %s\n"
"* Max texture size: %d\n"
"* Extensions checked:\n"
" - GL_KHR_debug: %s\n"
" - GL_EXT_unpack_subimage: %s\n"
" - half float: %s\n"
" - sync: %s\n"
" - bgra: %s",
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
gdk_gl_version_get_major (&priv->gl_version), gdk_gl_version_get_minor (&priv->gl_version),
priv->is_legacy ? "legacy" : "core",
glGetString (GL_SHADING_LANGUAGE_VERSION),
max_texture_size,
priv->has_khr_debug ? "yes" : "no",
priv->has_unpack_subimage ? "yes" : "no",
priv->has_half_float ? "yes" : "no",
priv->has_sync ? "yes" : "no",
priv->has_bgra ? "yes" : "no");
}
if (GDK_DISPLAY_DEBUG_CHECK (display, OPENGL))
{
int i, max_texture_size;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
gdk_debug_message ("%s version: %d.%d (%s)\n"
"* GLSL version: %s\n"
"* Max texture size: %d\n",
gdk_gl_context_get_use_es (context) ? "OpenGL ES" : "OpenGL",
gdk_gl_version_get_major (&priv->gl_version), gdk_gl_version_get_minor (&priv->gl_version),
priv->is_legacy ? "legacy" : "core",
glGetString (GL_SHADING_LANGUAGE_VERSION),
max_texture_size);
gdk_debug_message ("Enabled features (use GDK_GL_DISABLE env var to disable):");
for (i = 0; i < G_N_ELEMENTS (gdk_gl_feature_keys); i++)
{
gdk_debug_message (" %s: %s",
gdk_gl_feature_keys[i].key,
(priv->features & gdk_gl_feature_keys[i].value) ? "YES" :
((disabled_features & gdk_gl_feature_keys[i].value) ? "disabled via env var" :
(((supported_features & gdk_gl_feature_keys[i].value) == 0) ? "not supported" :
"Hum, what? This should not happen.")));
}
}
priv->extensions_checked = TRUE;
}
@@ -2016,30 +2050,6 @@ gdk_gl_context_get_format_flags (GdkGLContext *self,
return priv->memory_flags[format];
}
gboolean
gdk_gl_context_has_debug (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->debug_enabled || priv->use_khr_debug;
}
gboolean
gdk_gl_context_has_vertex_half_float (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_half_float;
}
gboolean
gdk_gl_context_has_sync (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->has_sync;
}
/* Return if glGenVertexArrays, glBindVertexArray and glDeleteVertexArrays
* can be used
*/

View File

@@ -27,6 +27,15 @@
G_BEGIN_DECLS
typedef enum {
GDK_GL_FEATURE_DEBUG = 1 << 0,
GDK_GL_FEATURE_UNPACK_SUBIMAGE = 1 << 1,
GDK_GL_FEATURE_VERTEX_HALF_FLOAT = 1 << 2,
GDK_GL_FEATURE_SYNC = 1 << 3,
GDK_GL_FEATURE_BASE_INSTANCE = 1 << 4,
GDK_GL_FEATURE_BUFFER_STORAGE = 1 << 5,
} GdkGLFeatures;
typedef enum {
GDK_GL_NONE = 0,
GDK_GL_EGL,
@@ -142,7 +151,6 @@ void gdk_gl_context_get_matching_version (GdkGLContext
gboolean legacy,
GdkGLVersion *out_version);
gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context);
void gdk_gl_context_push_debug_group (GdkGLContext *context,
const char *message);
void gdk_gl_context_push_debug_group_printf (GdkGLContext *context,
@@ -163,14 +171,11 @@ const char * gdk_gl_context_get_glsl_version_string (GdkGLContext
GdkGLMemoryFlags gdk_gl_context_get_format_flags (GdkGLContext *self,
GdkMemoryFormat format) G_GNUC_PURE;
gboolean gdk_gl_context_has_debug (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_feature (GdkGLContext *self,
GdkGLFeatures feature) G_GNUC_PURE;
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);
gboolean gdk_gl_context_has_vertex_half_float (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_sync (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_has_vertex_arrays (GdkGLContext *self) G_GNUC_PURE;
double gdk_gl_context_get_scale (GdkGLContext *self);

View File

@@ -494,7 +494,7 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
self->id = gdk_gl_texture_builder_get_id (builder);
GDK_TEXTURE (self)->format = gdk_gl_texture_builder_get_format (builder);
self->has_mipmap = gdk_gl_texture_builder_get_has_mipmap (builder);
if (gdk_gl_context_has_sync (self->context))
if (gdk_gl_context_has_feature (self->context, GDK_GL_FEATURE_SYNC))
self->sync = gdk_gl_texture_builder_get_sync (builder);
self->destroy = destroy;
self->data = data;

View File

@@ -552,9 +552,8 @@ physical_device_supports_extension (VkPhysicalDevice device,
return FALSE;
}
static gboolean
physical_device_check_features (VkPhysicalDevice device,
GdkVulkanFeatures *out_features)
static GdkVulkanFeatures
physical_device_check_features (VkPhysicalDevice device)
{
VkPhysicalDeviceVulkan12Features v12_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
@@ -563,15 +562,16 @@ physical_device_check_features (VkPhysicalDevice device,
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
.pNext = &v12_features
};
VkPhysicalDeviceFeatures2 features = {
VkPhysicalDeviceFeatures2 v10_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = &ycbcr_features
};
VkExternalSemaphoreProperties semaphore_props = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
};
GdkVulkanFeatures features;
vkGetPhysicalDeviceFeatures2 (device, &features);
vkGetPhysicalDeviceFeatures2 (device, &v10_features);
vkGetPhysicalDeviceExternalSemaphoreProperties (device,
&(VkPhysicalDeviceExternalSemaphoreInfo) {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
@@ -579,46 +579,46 @@ physical_device_check_features (VkPhysicalDevice device,
},
&semaphore_props);
*out_features = 0;
features = 0;
if (features.features.shaderUniformBufferArrayDynamicIndexing &&
features.features.shaderSampledImageArrayDynamicIndexing)
*out_features |= GDK_VULKAN_FEATURE_DYNAMIC_INDEXING;
if (v10_features.features.shaderUniformBufferArrayDynamicIndexing &&
v10_features.features.shaderSampledImageArrayDynamicIndexing)
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;
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;
features |= GDK_VULKAN_FEATURE_DESCRIPTOR_INDEXING;
if (v12_features.shaderSampledImageArrayNonUniformIndexing &&
v12_features.shaderStorageBufferArrayNonUniformIndexing)
*out_features |= GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING;
features |= GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING;
if (ycbcr_features.samplerYcbcrConversion ||
physical_device_supports_extension (device, VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME))
*out_features |= GDK_VULKAN_FEATURE_YCBCR;
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;
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;
features |= GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT;
if (semaphore_props.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT)
*out_features |= GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT;
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;
features |= GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT;
return TRUE;
return features;
}
static void
@@ -1366,7 +1366,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
first = 0;
last = n_devices;
skip_features = gdk_parse_debug_var ("GDK_VULKAN_SKIP",
skip_features = gdk_parse_debug_var ("GDK_VULKAN_DISABLE",
gsk_vulkan_feature_keys,
G_N_ELEMENTS (gsk_vulkan_feature_keys));
@@ -1454,8 +1454,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
GdkVulkanFeatures features, device_features;
uint32_t n_queue_props;
if (!physical_device_check_features (devices[i], &device_features))
continue;
device_features = physical_device_check_features (devices[i]);
features = device_features & ~skip_features;
@@ -1540,7 +1539,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
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):");
GDK_DISPLAY_DEBUG (display, VULKAN, "Enabled features (use GDK_VULKAN_DISABLE env var to disable):");
for (i = 0; i < G_N_ELEMENTS (gsk_vulkan_feature_keys); i++)
{
GDK_DISPLAY_DEBUG (display, VULKAN, " %s: %s",

View File

@@ -715,26 +715,16 @@ typedef NSString *CALayerContentsGravity;
-(void)setStyleMask:(NSWindowStyleMask)styleMask
{
gboolean was_fullscreen;
gboolean is_fullscreen;
gboolean was_opaque;
gboolean is_opaque;
was_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
was_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
[super setStyleMask:styleMask];
is_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
is_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
if (was_fullscreen != is_fullscreen)
{
if (was_fullscreen)
[self setFrame:lastUnfullscreenFrame display:NO];
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
}
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
if (was_opaque != is_opaque)
{
@@ -777,7 +767,6 @@ typedef NSString *CALayerContentsGravity;
-(void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
inFullscreenTransition = YES;
lastUnfullscreenFrame = [self frame];
}
-(void)windowDidEnterFullScreen:(NSNotification *)aNotification

View File

@@ -49,7 +49,6 @@
EdgeSnapping snapping;
NSRect lastUnfullscreenFrame;
BOOL inFullscreenTransition;
}

View File

@@ -998,7 +998,9 @@ _gdk_macos_display_get_nsevent (GdkEvent *event)
{
const GdkToNSEventMap *map = iter->data;
if (map->gdk_event == event)
if (map->gdk_event->event_type == event->event_type &&
map->gdk_event->device == event->device &&
map->gdk_event->time == event->time)
return map->nsevent;
}

View File

@@ -56,14 +56,6 @@ enum {
static GParamSpec *properties [LAST_PROP];
static gboolean
window_is_fullscreen (GdkMacosSurface *self)
{
g_assert (GDK_IS_MACOS_SURFACE (self));
return ([self->window styleMask] & NSWindowStyleMaskFullScreen) != 0;
}
void
_gdk_macos_surface_request_frame (GdkMacosSurface *self)
{
@@ -758,7 +750,7 @@ _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self)
g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
state = GDK_SURFACE (self)->state;
is_fullscreen = window_is_fullscreen (self);
is_fullscreen = ([self->window styleMask] & NSWindowStyleMaskFullScreen) != 0;
was_fullscreen = (state & GDK_TOPLEVEL_STATE_FULLSCREEN) != 0;
if (is_fullscreen != was_fullscreen)

View File

@@ -488,12 +488,14 @@ gsk_gl_command_queue_new (GdkGLContext *context,
int max_texture_size = atoi (g_getenv ("GSK_MAX_TEXTURE_SIZE"));
if (max_texture_size == 0)
{
g_warning ("Failed to parse GSK_MAX_TEXTURE_SIZE");
g_warning ("Failed to parse %s", "GSK_MAX_TEXTURE_SIZE");
}
else
{
max_texture_size = MAX (max_texture_size, 512);
GSK_DEBUG(OPENGL, "Limiting max texture size to %d", max_texture_size);
GSK_DEBUG (RENDERER,
"Limiting texture size in the GL renderer to %d (via %s)",
max_texture_size, "GSK_MAX_TEXTURE_SIZE");
self->max_texture_size = MIN (self->max_texture_size, max_texture_size);
}
}
@@ -1622,7 +1624,7 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
{
glTexSubImage2D (GL_TEXTURE_2D, 0, x, y, width, height, gl_format, gl_type, data);
}
else if (stride % bpp == 0 && gdk_gl_context_has_unpack_subimage (self->context))
else if (stride % bpp == 0 && gdk_gl_context_has_feature (self->context, GDK_GL_FEATURE_UNPACK_SUBIMAGE))
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);

View File

@@ -1835,7 +1835,7 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
state = g_new0 (GskGLTextureState, 1);
state->texture_id = texture_id;
state->context = g_object_ref (self->command_queue->context);
if (gdk_gl_context_has_sync (self->command_queue->context))
if (gdk_gl_context_has_feature (self->command_queue->context, GDK_GL_FEATURE_SYNC))
state->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
g_hash_table_steal (self->textures, GUINT_TO_POINTER (texture_id));

View File

@@ -194,7 +194,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
{
gdk_gl_context_make_current (context);
if (!gdk_gl_context_has_vertex_half_float (context))
if (!gdk_gl_context_has_feature (context, GDK_GL_FEATURE_VERTEX_HALF_FLOAT))
{
int major, minor;

View File

@@ -1235,7 +1235,7 @@ gsk_gl_render_job_visit_as_fallback (GskGLRenderJob *job,
texture = gdk_texture_new_for_surface (surface);
texture_id = gsk_gl_driver_load_texture (job->driver, texture, FALSE);
if (gdk_gl_context_has_debug (job->command_queue->context))
if (gdk_gl_context_has_feature (job->command_queue->context, GDK_GL_FEATURE_DEBUG))
gdk_gl_context_label_object_printf (job->command_queue->context, GL_TEXTURE, texture_id,
"Fallback %s %d",
g_type_name_from_instance ((GTypeInstance *) node),
@@ -2532,7 +2532,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
get_target_format (job, node),
&render_target);
if (gdk_gl_context_has_debug (context))
if (gdk_gl_context_has_feature (context, GDK_GL_FEATURE_DEBUG))
{
gdk_gl_context_label_object_printf (context,
GL_TEXTURE,
@@ -4382,7 +4382,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
&render_target))
g_assert_not_reached ();
if (gdk_gl_context_has_debug (job->command_queue->context))
if (gdk_gl_context_has_feature (job->command_queue->context, GDK_GL_FEATURE_DEBUG))
{
gdk_gl_context_label_object_printf (job->command_queue->context,
GL_TEXTURE,

View File

@@ -1,30 +1,25 @@
#include "config.h"
#include <gdk/gdkprofilerprivate.h>
#include "gskglbufferprivate.h"
/* {{{ GskGLBuffer */
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 guint profiler_buffer_uploads_id;
static gint64 profiler_buffer_uploads;
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);
@@ -42,16 +37,6 @@ static void
gsk_gl_buffer_unmap (GskGpuBuffer *buffer,
gsize used)
{
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
if (used == 0)
return;
gsk_gl_buffer_bind (self);
profiler_buffer_uploads += used;
glBufferSubData (self->target, 0, used, self->data);
gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads);
}
static void
@@ -64,8 +49,6 @@ gsk_gl_buffer_class_init (GskGLBufferClass *klass)
buffer_class->unmap = gsk_gl_buffer_unmap;
gobject_class->finalize = gsk_gl_buffer_finalize;
profiler_buffer_uploads_id = gdk_profiler_define_int_counter ("ngl-buffer-uploads", "Number of bytes uploaded to GPU");
}
static void
@@ -73,28 +56,6 @@ 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)
{
@@ -108,3 +69,140 @@ gsk_gl_buffer_bind_base (GskGLBuffer *self,
glBindBufferBase (self->target, index, self->buffer_id);
}
static void
gsk_gl_buffer_setup (GskGLBuffer *self,
GLenum target,
gsize size)
{
gsk_gpu_buffer_setup (GSK_GPU_BUFFER (self), size);
self->target = target;
glGenBuffers (1, &self->buffer_id);
}
/* }}} */
/* {{{ GskGLMappedBuffer */
struct _GskGLMappedBuffer
{
GskGLBuffer parent_instance;
};
G_DEFINE_TYPE (GskGLMappedBuffer, gsk_gl_mapped_buffer, GSK_TYPE_GL_BUFFER)
static void
gsk_gl_mapped_buffer_finalize (GObject *object)
{
GskGLBuffer *self = GSK_GL_BUFFER (object);
gsk_gl_buffer_bind (self);
glUnmapBuffer (self->target);
G_OBJECT_CLASS (gsk_gl_mapped_buffer_parent_class)->finalize (object);
}
static void
gsk_gl_mapped_buffer_class_init (GskGLMappedBufferClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gsk_gl_mapped_buffer_finalize;
}
static void
gsk_gl_mapped_buffer_init (GskGLMappedBuffer *self)
{
}
GskGpuBuffer *
gsk_gl_mapped_buffer_new (GLenum target,
gsize size)
{
GskGLBuffer *self;
self = g_object_new (GSK_TYPE_GL_MAPPED_BUFFER, NULL);
gsk_gl_buffer_setup (self, target, size);
gsk_gl_buffer_bind (self);
glBufferStorage (target,
size,
NULL,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
self->data = glMapBufferRange (target,
0,
size,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
return GSK_GPU_BUFFER (self);
}
/* }}} */
/* {{{ GskGLCopiedBuffer */
struct _GskGLCopiedBuffer
{
GskGLBuffer parent_instance;
};
G_DEFINE_TYPE (GskGLCopiedBuffer, gsk_gl_copied_buffer, GSK_TYPE_GL_BUFFER)
static void
gsk_gl_copied_buffer_finalize (GObject *object)
{
GskGLBuffer *self = GSK_GL_BUFFER (object);
g_free (self->data);
G_OBJECT_CLASS (gsk_gl_copied_buffer_parent_class)->finalize (object);
}
static void
gsk_gl_copied_buffer_unmap (GskGpuBuffer *buffer,
gsize used)
{
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
if (used == 0)
return;
gsk_gl_buffer_bind (self);
glBufferSubData (self->target, 0, used, self->data);
}
static void
gsk_gl_copied_buffer_class_init (GskGLCopiedBufferClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GskGpuBufferClass *buffer_class = GSK_GPU_BUFFER_CLASS (klass);
gobject_class->finalize = gsk_gl_copied_buffer_finalize;
buffer_class->unmap = gsk_gl_copied_buffer_unmap;
}
static void
gsk_gl_copied_buffer_init (GskGLCopiedBuffer *self)
{
}
GskGpuBuffer *
gsk_gl_copied_buffer_new (GLenum target,
gsize size)
{
GskGLBuffer *self;
self = g_object_new (GSK_TYPE_GL_COPIED_BUFFER, NULL);
gsk_gl_buffer_setup (self, target, size);
gsk_gl_buffer_bind (self);
glBufferData (target, size, NULL, GL_STATIC_DRAW);
self->data = malloc (size);
return GSK_GPU_BUFFER (self);
}
/* }}} */

View File

@@ -7,12 +7,17 @@
G_BEGIN_DECLS
#define GSK_TYPE_GL_BUFFER (gsk_gl_buffer_get_type ())
#define GSK_TYPE_GL_MAPPED_BUFFER (gsk_gl_mapped_buffer_get_type ())
#define GSK_TYPE_GL_COPIED_BUFFER (gsk_gl_copied_buffer_get_type ())
G_DECLARE_FINAL_TYPE (GskGLBuffer, gsk_gl_buffer, GSK, GL_BUFFER, GskGpuBuffer)
G_DECLARE_FINAL_TYPE (GskGLMappedBuffer, gsk_gl_mapped_buffer, GSK, GL_MAPPED_BUFFER, GskGLBuffer)
G_DECLARE_FINAL_TYPE (GskGLCopiedBuffer, gsk_gl_copied_buffer, GSK, GL_COPIED_BUFFER, GskGLBuffer)
GskGpuBuffer * gsk_gl_buffer_new (GLenum target,
gsize size,
GLenum access);
GskGpuBuffer * gsk_gl_mapped_buffer_new (GLenum target,
gsize size);
GskGpuBuffer * gsk_gl_copied_buffer_new (GLenum target,
gsize size);
void gsk_gl_buffer_bind (GskGLBuffer *self);
void gsk_gl_buffer_bind_base (GskGLBuffer *self,

View File

@@ -20,6 +20,7 @@ struct _GskGLFrame
GLuint globals_buffer_id;
guint next_texture_slot;
GLsync sync;
GHashTable *vaos;
};
@@ -34,7 +35,23 @@ G_DEFINE_TYPE (GskGLFrame, gsk_gl_frame, GSK_TYPE_GPU_FRAME)
static gboolean
gsk_gl_frame_is_busy (GskGpuFrame *frame)
{
return FALSE;
GskGLFrame *self = GSK_GL_FRAME (frame);
if (!self->sync)
return FALSE;
return glClientWaitSync (self->sync, 0, 0) == GL_TIMEOUT_EXPIRED;
}
static void
gsk_gl_frame_wait (GskGpuFrame *frame)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
if (!self->sync)
return;
glClientWaitSync (self->sync, 0, G_MAXINT64);
}
static void
@@ -50,6 +67,12 @@ gsk_gl_frame_cleanup (GskGpuFrame *frame)
{
GskGLFrame *self = GSK_GL_FRAME (frame);
if (self->sync)
{
glClientWaitSync (self->sync, 0, -1);
g_clear_pointer (&self->sync, glDeleteSync);
}
self->next_texture_slot = 0;
GSK_GPU_FRAME_CLASS (gsk_gl_frame_parent_class)->cleanup (frame);
@@ -124,14 +147,22 @@ gsk_gl_frame_create_vertex_buffer (GskGpuFrame *frame,
*/
g_hash_table_remove_all (self->vaos);
return gsk_gl_buffer_new (GL_ARRAY_BUFFER, size, GL_WRITE_ONLY);
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_BUFFER_STORAGE))
return gsk_gl_mapped_buffer_new (GL_ARRAY_BUFFER, size);
else
return gsk_gl_copied_buffer_new (GL_ARRAY_BUFFER, size);
}
static GskGpuBuffer *
gsk_gl_frame_create_storage_buffer (GskGpuFrame *frame,
gsize size)
{
return gsk_gl_buffer_new (GL_UNIFORM_BUFFER, size, GL_WRITE_ONLY);
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_BUFFER_STORAGE))
return gsk_gl_mapped_buffer_new (GL_UNIFORM_BUFFER, size);
else
return gsk_gl_copied_buffer_new (GL_UNIFORM_BUFFER, size);
}
static void
@@ -160,6 +191,10 @@ gsk_gl_frame_submit (GskGpuFrame *frame,
{
op = gsk_gpu_op_gl_command (op, frame, &state);
}
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_SYNC))
self->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
static void
@@ -180,6 +215,7 @@ gsk_gl_frame_class_init (GskGLFrameClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
gpu_frame_class->is_busy = gsk_gl_frame_is_busy;
gpu_frame_class->wait = gsk_gl_frame_wait;
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;

View File

@@ -17,23 +17,16 @@ struct _GskGpuBlendModeOp
};
static void
gsk_gpu_blend_mode_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_blend_mode_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBlendmodeInstance *instance;
GskGpuBlendmodeInstance *instance = (GskGpuBlendmodeInstance *) instance_;
instance = (GskGpuBlendmodeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "blend-mode");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->bottom_id);
gsk_gpu_print_enum (string, GSK_TYPE_BLEND_MODE, shader->variation);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->top_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
@@ -41,7 +34,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBlendModeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_blend_mode_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -52,6 +45,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_blendmode_info,
#endif
gsk_gpu_blend_mode_op_print_instance,
gsk_gpu_blendmode_setup_attrib_locations,
gsk_gpu_blendmode_setup_vao
};

View File

@@ -20,22 +20,15 @@ struct _GskGpuBlurOp
};
static void
gsk_gpu_blur_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_blur_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBlurInstance *instance;
GskGpuBlurInstance *instance = (GskGpuBlurInstance *) instance_;
instance = (GskGpuBlurInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "blur");
gsk_gpu_print_shader_info (string, shader->clip);
g_string_append_printf (string, "%g,%g ", instance->blur_direction[0], instance->blur_direction[1]);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_BLUR_OP_CLASS = {
@@ -43,7 +36,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLUR_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBlurOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_blur_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -54,6 +47,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLUR_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_blur_info,
#endif
gsk_gpu_blur_op_print_instance,
gsk_gpu_blur_setup_attrib_locations,
gsk_gpu_blur_setup_vao
};

View File

@@ -25,18 +25,12 @@ color_equal (const float *color1,
}
static void
gsk_gpu_border_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_border_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBorderInstance *instance;
GskGpuBorderInstance *instance = (GskGpuBorderInstance *) instance_;
instance = (GskGpuBorderInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "border");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rounded_rect (string, instance->outline);
gsk_gpu_print_rgba (string, (const float *) &instance->border_colors[0]);
@@ -58,8 +52,6 @@ gsk_gpu_border_op_print (GskGpuOp *op,
instance->border_widths[2],
instance->border_widths[3]);
}
gsk_gpu_print_newline (string);
}
#ifdef GDK_RENDERING_VULKAN
@@ -85,7 +77,7 @@ static const GskGpuShaderOpClass GSK_GPU_BORDER_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBorderOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_border_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_border_op_vk_command,
#endif
@@ -96,6 +88,7 @@ static const GskGpuShaderOpClass GSK_GPU_BORDER_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_border_info,
#endif
gsk_gpu_border_op_print_instance,
gsk_gpu_border_setup_attrib_locations,
gsk_gpu_border_setup_vao
};

View File

@@ -20,24 +20,17 @@ struct _GskGpuBoxShadowOp
};
static void
gsk_gpu_box_shadow_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_box_shadow_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuBoxshadowInstance *instance;
GskGpuBoxshadowInstance *instance = (GskGpuBoxshadowInstance *) instance_;
instance = (GskGpuBoxshadowInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, shader->variation & VARIATION_INSET ? "inset-shadow" : "outset-shadow");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rounded_rect (string, instance->outline);
gsk_gpu_print_rgba (string, instance->color);
g_string_append_printf (string, "%g %g %g %g ",
instance->shadow_offset[0], instance->shadow_offset[1],
instance->blur_radius, instance->shadow_spread);
gsk_gpu_print_newline (string);
}
#ifdef GDK_RENDERING_VULKAN
@@ -63,7 +56,7 @@ static const GskGpuShaderOpClass GSK_GPU_BOX_SHADOW_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuBoxShadowOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_box_shadow_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_box_shadow_op_vk_command,
#endif
@@ -74,6 +67,7 @@ static const GskGpuShaderOpClass GSK_GPU_BOX_SHADOW_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_boxshadow_info,
#endif
gsk_gpu_box_shadow_op_print_instance,
gsk_gpu_boxshadow_setup_attrib_locations,
gsk_gpu_boxshadow_setup_vao
};

View File

@@ -2,6 +2,8 @@
#include "gskgpubufferprivate.h"
#include <gdk/gdkprofilerprivate.h>
typedef struct _GskGpuBufferPrivate GskGpuBufferPrivate;
struct _GskGpuBufferPrivate
@@ -11,9 +13,13 @@ struct _GskGpuBufferPrivate
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuBuffer, gsk_gpu_buffer, G_TYPE_OBJECT)
static guint profiler_buffer_uploads_id;
static gint64 profiler_buffer_uploads;
static void
gsk_gpu_buffer_class_init (GskGpuBufferClass *klass)
{
profiler_buffer_uploads_id = gdk_profiler_define_int_counter ("ngl-buffer-uploads", "Number of bytes uploaded to GPU");
}
static void
@@ -29,7 +35,7 @@ gsk_gpu_buffer_setup (GskGpuBuffer *self,
priv->size = size;
}
gsize
gsk_gpu_buffer_get_size (GskGpuBuffer *self)
{
@@ -49,5 +55,8 @@ gsk_gpu_buffer_unmap (GskGpuBuffer *self,
gsize size)
{
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self, size);
profiler_buffer_uploads += size;
gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads);
}

View File

@@ -16,22 +16,15 @@ struct _GskGpuColorizeOp
};
static void
gsk_gpu_colorize_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_colorize_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuColorizeInstance *instance;
GskGpuColorizeInstance *instance = (GskGpuColorizeInstance *) instance_;
instance = (GskGpuColorizeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "colorize");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_rgba (string, instance->color);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_COLORIZE_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLORIZE_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuColorizeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_colorize_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLORIZE_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_colorize_info,
#endif
gsk_gpu_colorize_op_print_instance,
gsk_gpu_colorize_setup_attrib_locations,
gsk_gpu_colorize_setup_vao
};

View File

@@ -16,21 +16,14 @@ struct _GskGpuColorMatrixOp
};
static void
gsk_gpu_color_matrix_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_color_matrix_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuColormatrixInstance *instance;
GskGpuColormatrixInstance *instance = (GskGpuColormatrixInstance *) instance_;
instance = (GskGpuColormatrixInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "color-matrix");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_COLOR_MATRIX_OP_CLASS = {
@@ -38,7 +31,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_MATRIX_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuColorMatrixOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_color_matrix_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -49,6 +42,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_MATRIX_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_colormatrix_info,
#endif
gsk_gpu_color_matrix_op_print_instance,
gsk_gpu_colormatrix_setup_attrib_locations,
gsk_gpu_colormatrix_setup_vao
};

View File

@@ -17,21 +17,14 @@ struct _GskGpuColorOp
};
static void
gsk_gpu_color_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_color_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuColorInstance *instance;
GskGpuColorInstance *instance = (GskGpuColorInstance *) instance_;
instance = (GskGpuColorInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "color");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_rgba (string, instance->color);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_COLOR_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuColorOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_color_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_COLOR_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_color_info,
#endif
gsk_gpu_color_op_print_instance,
gsk_gpu_color_setup_attrib_locations,
gsk_gpu_color_setup_vao
};

View File

@@ -18,20 +18,13 @@ struct _GskGpuConicGradientOp
};
static void
gsk_gpu_conic_gradient_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_conic_gradient_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuConicgradientInstance *instance;
GskGpuConicgradientInstance *instance = (GskGpuConicgradientInstance *) instance_;
instance = (GskGpuConicgradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "conic-gradient");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_CONIC_GRADIENT_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_CONIC_GRADIENT_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuConicGradientOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_conic_gradient_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_CONIC_GRADIENT_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_conicgradient_info,
#endif
gsk_gpu_conic_gradient_op_print_instance,
gsk_gpu_conicgradient_setup_attrib_locations,
gsk_gpu_conicgradient_setup_vao
};

View File

@@ -16,23 +16,16 @@ struct _GskGpuCrossFadeOp
};
static void
gsk_gpu_cross_fade_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_cross_fade_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuCrossfadeInstance *instance;
GskGpuCrossfadeInstance *instance = (GskGpuCrossfadeInstance *) instance_;
instance = (GskGpuCrossfadeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "cross-fade");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->start_id);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->end_id);
g_string_append_printf (string, "%g%%", 100 * instance->opacity_progress[1]);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_CROSS_FADE_OP_CLASS = {
@@ -40,7 +33,7 @@ static const GskGpuShaderOpClass GSK_GPU_CROSS_FADE_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuCrossFadeOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_cross_fade_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -51,6 +44,7 @@ static const GskGpuShaderOpClass GSK_GPU_CROSS_FADE_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_crossfade_info,
#endif
gsk_gpu_cross_fade_op_print_instance,
gsk_gpu_crossfade_setup_attrib_locations,
gsk_gpu_crossfade_setup_vao
};

View File

@@ -272,7 +272,7 @@ gsk_gpu_download_op_gl_command (GskGpuOp *op,
data->context = g_object_ref (context);
data->texture_id = gsk_gl_image_steal_texture (GSK_GL_IMAGE (self->image));
if (gdk_gl_context_has_sync (context))
if (gdk_gl_context_has_feature (context, GDK_GL_FEATURE_SYNC))
data->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
builder = gdk_gl_texture_builder_new ();

View File

@@ -40,6 +40,7 @@ struct _GskGpuFramePrivate
GskGpuOps ops;
GskGpuOp *first_op;
GskGpuOp *last_op;
GskGpuBuffer *vertex_buffer;
guchar *vertex_buffer_data;
@@ -70,6 +71,8 @@ gsk_gpu_frame_default_cleanup (GskGpuFrame *self)
gsk_gpu_op_finish (op);
}
gsk_gpu_ops_set_size (&priv->ops, 0);
priv->last_op = NULL;
}
static void
@@ -248,27 +251,35 @@ gsk_gpu_frame_sort_render_pass (GskGpuFrame *self,
SortData *sort_data)
{
SortData subpasses = { { NULL, NULL }, { NULL, NULL } };
SortData pass = { { NULL, NULL }, { NULL, NULL } };
if (op->op_class->stage == GSK_GPU_STAGE_BEGIN_PASS)
{
pass.command.first = op;
pass.command.last = op;
op = op->next;
}
while (op)
{
switch (op->op_class->stage)
{
case GSK_GPU_STAGE_UPLOAD:
if (sort_data->upload.first == NULL)
sort_data->upload.first = op;
if (pass.upload.first == NULL)
pass.upload.first = op;
else
sort_data->upload.last->next = op;
sort_data->upload.last = op;
pass.upload.last->next = op;
pass.upload.last = op;
op = op->next;
break;
case GSK_GPU_STAGE_COMMAND:
case GSK_GPU_STAGE_SHADER:
if (sort_data->command.first == NULL)
sort_data->command.first = op;
if (pass.command.first == NULL)
pass.command.first = op;
else
sort_data->command.last->next = op;
sort_data->command.last = op;
pass.command.last->next = op;
pass.command.last = op;
op = op->next;
break;
@@ -282,19 +293,13 @@ gsk_gpu_frame_sort_render_pass (GskGpuFrame *self,
break;
case GSK_GPU_STAGE_BEGIN_PASS:
if (subpasses.command.first == NULL)
subpasses.command.first = op;
else
subpasses.command.last->next = op;
subpasses.command.last = op;
/* append subpass to existing subpasses */
op = gsk_gpu_frame_sort_render_pass (self, op->next, &subpasses);
op = gsk_gpu_frame_sort_render_pass (self, op, &subpasses);
break;
case GSK_GPU_STAGE_END_PASS:
sort_data->command.last->next = op;
sort_data->command.last = op;
pass.command.last->next = op;
pass.command.last = op;
op = op->next;
goto out;
@@ -305,22 +310,38 @@ gsk_gpu_frame_sort_render_pass (GskGpuFrame *self,
}
out:
/* prepend subpasses to the current pass */
/* append to the sort data, first the subpasses, then the current pass */
if (subpasses.upload.first)
{
if (sort_data->upload.first != NULL)
subpasses.upload.last->next = sort_data->upload.first;
sort_data->upload.last->next = subpasses.upload.first;
else
sort_data->upload.last = subpasses.upload.last;
sort_data->upload.first = subpasses.upload.first;
sort_data->upload.first = subpasses.upload.first;
sort_data->upload.last = subpasses.upload.last;
}
if (pass.upload.first)
{
if (sort_data->upload.first != NULL)
sort_data->upload.last->next = pass.upload.first;
else
sort_data->upload.first = pass.upload.first;
sort_data->upload.last = pass.upload.last;
}
if (subpasses.command.first)
{
if (sort_data->command.first != NULL)
subpasses.command.last->next = sort_data->command.first;
sort_data->command.last->next = subpasses.command.first;
else
sort_data->command.last = subpasses.command.last;
sort_data->command.first = subpasses.command.first;
sort_data->command.first = subpasses.command.first;
sort_data->command.last = subpasses.command.last;
}
if (pass.command.first)
{
if (sort_data->command.first != NULL)
sort_data->command.last->next = pass.command.first;
else
sort_data->command.first = pass.command.first;
sort_data->command.last = pass.command.last;
}
return op;
@@ -331,8 +352,13 @@ gsk_gpu_frame_sort_ops (GskGpuFrame *self)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
SortData sort_data = { { NULL, }, };
gsk_gpu_frame_sort_render_pass (self, priv->first_op, &sort_data);
GskGpuOp *op;
op = priv->first_op;
while (op)
{
op = gsk_gpu_frame_sort_render_pass (self, op, &sort_data);
}
if (sort_data.upload.first)
{
@@ -343,6 +369,8 @@ gsk_gpu_frame_sort_ops (GskGpuFrame *self)
priv->first_op = sort_data.command.first;
if (sort_data.command.last)
sort_data.command.last->next = NULL;
priv->last_op = NULL;
}
gpointer
@@ -360,7 +388,17 @@ gsk_gpu_frame_alloc_op (GskGpuFrame *self,
NULL,
size);
return gsk_gpu_ops_index (&priv->ops, pos);
priv->last_op = (GskGpuOp *) gsk_gpu_ops_index (&priv->ops, pos);
return priv->last_op;
}
GskGpuOp *
gsk_gpu_frame_get_last_op (GskGpuFrame *self)
{
GskGpuFramePrivate *priv = gsk_gpu_frame_get_instance_private (self);
return priv->last_op;
}
GskGpuImage *
@@ -505,6 +543,12 @@ gsk_gpu_frame_is_busy (GskGpuFrame *self)
return GSK_GPU_FRAME_GET_CLASS (self)->is_busy (self);
}
void
gsk_gpu_frame_wait (GskGpuFrame *self)
{
GSK_GPU_FRAME_GET_CLASS (self)->wait (self);
}
static void
copy_texture (gpointer user_data,
GdkTexture *texture)

View File

@@ -24,6 +24,7 @@ struct _GskGpuFrameClass
GObjectClass parent_class;
gboolean (* is_busy) (GskGpuFrame *self);
void (* wait) (GskGpuFrame *self);
void (* setup) (GskGpuFrame *self);
void (* cleanup) (GskGpuFrame *self);
GskGpuImage * (* upload_texture) (GskGpuFrame *self,
@@ -69,6 +70,7 @@ GskGpuBuffer * gsk_gpu_frame_write_storage_buffer (GskGpuF
gsize *out_offset);
gboolean gsk_gpu_frame_is_busy (GskGpuFrame *self);
void gsk_gpu_frame_wait (GskGpuFrame *self);
void gsk_gpu_frame_render (GskGpuFrame *self,
gint64 timestamp,
@@ -83,6 +85,7 @@ void gsk_gpu_frame_download_texture (GskGpuF
GdkMemoryFormat format,
guchar *data,
gsize stride);
GskGpuOp *gsk_gpu_frame_get_last_op (GskGpuFrame *self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuFrame, g_object_unref)

View File

@@ -19,23 +19,15 @@ struct _GskGpuLinearGradientOp
};
static void
gsk_gpu_linear_gradient_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_linear_gradient_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuLineargradientInstance *instance;
instance = (GskGpuLineargradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
GskGpuLineargradientInstance *instance = (GskGpuLineargradientInstance *) instance_;
if (shader->variation & VARIATION_REPEATING)
gsk_gpu_print_op (string, indent, "repeating-linear-gradient");
else
gsk_gpu_print_op (string, indent, "linear-gradient");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_string (string, "repeating");
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_LINEAR_GRADIENT_OP_CLASS = {
@@ -43,7 +35,7 @@ static const GskGpuShaderOpClass GSK_GPU_LINEAR_GRADIENT_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuLinearGradientOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_linear_gradient_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -54,6 +46,7 @@ static const GskGpuShaderOpClass GSK_GPU_LINEAR_GRADIENT_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_lineargradient_info,
#endif
gsk_gpu_linear_gradient_op_print_instance,
gsk_gpu_lineargradient_setup_attrib_locations,
gsk_gpu_lineargradient_setup_vao
};

View File

@@ -16,22 +16,15 @@ struct _GskGpuMaskOp
};
static void
gsk_gpu_mask_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_mask_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuMaskInstance *instance;
GskGpuMaskInstance *instance = (GskGpuMaskInstance *) instance_;
instance = (GskGpuMaskInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "mask");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->source_id);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->mask_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_MASK_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_MASK_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuMaskOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_mask_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_MASK_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_mask_info,
#endif
gsk_gpu_mask_op_print_instance,
gsk_gpu_mask_setup_attrib_locations,
gsk_gpu_mask_setup_vao
};

View File

@@ -3000,8 +3000,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
guint i, num_glyphs;
float scale, inv_scale;
GdkRGBA color;
gboolean glyph_align;
gboolean hinting;
float align_scale_x, align_scale_y;
float inv_align_scale_x, inv_align_scale_y;
unsigned int flags_mask;
GskGpuImage *last_image;
guint32 descriptor;
const float inv_pango_scale = 1.f / PANGO_SCALE;
if (self->opacity < 1.0 &&
gsk_text_node_has_color_glyphs (node))
@@ -3024,45 +3028,38 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
inv_scale = 1.f / scale;
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
{
align_scale_x = scale * 4;
align_scale_y = scale;
flags_mask = 3;
}
else
{
align_scale_x = align_scale_y = scale * 4;
flags_mask = 15;
}
inv_align_scale_x = 1 / align_scale_x;
inv_align_scale_y = 1 / align_scale_y;
last_image = NULL;
descriptor = 0;
for (i = 0; i < num_glyphs; i++)
{
GskGpuImage *image;
graphene_rect_t glyph_bounds, glyph_tex_rect;
graphene_point_t glyph_offset, glyph_origin;
guint32 descriptor;
GskGpuGlyphLookupFlags flags;
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
if (hinting && glyph_align)
{
/* Force glyph_origin.y to be device pixel aligned.
* The hinter expects that.
*/
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
flags = ((int) glyph_origin.x & 3);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
}
else if (glyph_align)
{
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
glyph_origin.y = floor (glyph_origin.y * scale * 4 + .5);
flags = ((int) glyph_origin.x & 3) |
(((int) glyph_origin.y & 3) << 2);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
}
else
{
glyph_origin.x = floor (glyph_origin.x * scale + .5) * inv_scale;
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
flags = 0;
}
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
glyph_origin.x *= inv_align_scale_x;
glyph_origin.y *= inv_align_scale_y;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
@@ -3084,7 +3081,11 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
glyph_origin.y - glyph_offset.y * inv_scale);
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
if (image != last_image)
{
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
last_image = image;
}
if (glyphs[i].attr.is_color)
gsk_gpu_texture_op (self->frame,
@@ -3104,7 +3105,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
&glyph_tex_rect,
&color);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset.x += glyphs[i].geometry.width * inv_pango_scale;
}
}
@@ -3121,8 +3122,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
guint32 tex_id;
GskGpuImage *last_image;
graphene_point_t offset;
gboolean glyph_align;
gboolean hinting;
float align_scale_x, align_scale_y;
float inv_align_scale_x, inv_align_scale_y;
unsigned int flags_mask;
const float inv_pango_scale = 1.f / PANGO_SCALE;
if (gsk_text_node_has_color_glyphs (node))
return FALSE;
@@ -3142,8 +3145,20 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
{
align_scale_x = scale * 4;
align_scale_y = scale;
flags_mask = 3;
}
else
{
align_scale_x = align_scale_y = scale * 4;
flags_mask = 15;
}
inv_align_scale_x = 1 / align_scale_x;
inv_align_scale_y = 1 / align_scale_y;
last_image = NULL;
for (i = 0; i < num_glyphs; i++)
@@ -3153,34 +3168,14 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
graphene_point_t glyph_offset, glyph_origin;
GskGpuGlyphLookupFlags flags;
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
if (hinting && glyph_align)
{
/* Force glyph_origin.y to be device pixel aligned.
* The hinter expects that.
*/
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
flags = ((int) glyph_origin.x & 3);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
}
else if (glyph_align)
{
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
flags = ((int) glyph_origin.x & 3) |
(((int) glyph_origin.y & 3) << 2);
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
}
else
{
glyph_origin.x = roundf (glyph_origin.x * scale) * inv_scale;
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
flags = 0;
}
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
glyph_origin.x *= inv_align_scale_x;
glyph_origin.y *= inv_align_scale_y;
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
@@ -3220,7 +3215,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
),
&glyph_origin);
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
offset.x += glyphs[i].geometry.width * inv_pango_scale;
}
return TRUE;

View File

@@ -19,23 +19,15 @@ struct _GskGpuRadialGradientOp
};
static void
gsk_gpu_radial_gradient_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_radial_gradient_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuRadialgradientInstance *instance;
instance = (GskGpuRadialgradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
GskGpuRadialgradientInstance *instance = (GskGpuRadialgradientInstance *) instance_;
if (shader->variation & VARIATION_REPEATING)
gsk_gpu_print_op (string, indent, "repeating-radial-gradient");
else
gsk_gpu_print_op (string, indent, "radial-gradient");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_string (string, "repeating");
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_RADIAL_GRADIENT_OP_CLASS = {
@@ -43,7 +35,7 @@ static const GskGpuShaderOpClass GSK_GPU_RADIAL_GRADIENT_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuRadialGradientOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_radial_gradient_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -54,6 +46,7 @@ static const GskGpuShaderOpClass GSK_GPU_RADIAL_GRADIENT_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_radialgradient_info,
#endif
gsk_gpu_radial_gradient_op_print_instance,
gsk_gpu_radialgradient_setup_attrib_locations,
gsk_gpu_radialgradient_setup_vao
};

View File

@@ -30,9 +30,6 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
{ "blit", GSK_GPU_OPTIMIZE_BLIT, "Use shaders instead of vkCmdBlit()/glBlitFramebuffer()" },
{ "gradients", GSK_GPU_OPTIMIZE_GRADIENTS, "Don't supersample gradients" },
{ "mipmap", GSK_GPU_OPTIMIZE_MIPMAP, "Avoid creating mipmaps" },
{ "glyph-align", GSK_GPU_OPTIMIZE_GLYPH_ALIGN, "Never align glyphs to the subpixel grid" },
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
};
typedef struct _GskGpuRendererPrivate GskGpuRendererPrivate;
@@ -167,24 +164,36 @@ static GskGpuFrame *
gsk_gpu_renderer_get_frame (GskGpuRenderer *self)
{
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
GskGpuFrame *earliest_frame = NULL;
gint64 earliest_time = G_MAXINT64;
guint i;
while (TRUE)
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
gint64 timestamp;
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
if (priv->frames[i] == NULL)
{
priv->frames[i] = gsk_gpu_renderer_create_frame (self);
return priv->frames[i];
}
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, GSK_GPU_MAX_FRAMES);
if (!gsk_gpu_frame_is_busy (priv->frames[i]))
return priv->frames[i];
timestamp = gsk_gpu_frame_get_timestamp (priv->frames[i]);
if (timestamp < earliest_time)
{
earliest_time = timestamp;
earliest_frame = priv->frames[i];
}
}
g_assert (earliest_frame);
gsk_gpu_frame_wait (earliest_frame);
return earliest_frame;
}
static gboolean
@@ -218,31 +227,17 @@ gsk_gpu_renderer_unrealize (GskRenderer *renderer)
{
GskGpuRenderer *self = GSK_GPU_RENDERER (renderer);
GskGpuRendererPrivate *priv = gsk_gpu_renderer_get_instance_private (self);
gsize i, j;
gsize i;
gsk_gpu_renderer_make_current (self);
while (TRUE)
for (i = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
for (i = 0, j = 0; i < G_N_ELEMENTS (priv->frames); i++)
{
if (priv->frames[i] == NULL)
break;
if (gsk_gpu_frame_is_busy (priv->frames[i]))
{
if (i > j)
{
priv->frames[j] = priv->frames[i];
priv->frames[i] = NULL;
}
j++;
continue;
}
g_clear_object (&priv->frames[i]);
}
if (j == 0)
if (priv->frames[i] == NULL)
break;
GSK_GPU_RENDERER_GET_CLASS (self)->wait (self, priv->frames, j);
if (gsk_gpu_frame_is_busy (priv->frames[i]))
gsk_gpu_frame_wait (priv->frames[i]);
g_clear_object (&priv->frames[i]);
}
g_clear_object (&priv->context);
@@ -458,7 +453,7 @@ gsk_gpu_renderer_class_init (GskGpuRendererClass *klass)
gsk_ensure_resources ();
klass->optimizations = -1;
klass->optimizations &= ~gdk_parse_debug_var ("GSK_GPU_SKIP",
klass->optimizations &= ~gdk_parse_debug_var ("GSK_GPU_DISABLE",
gsk_gpu_optimization_keys,
G_N_ELEMENTS (gsk_gpu_optimization_keys));
klass->get_scale = gsk_gpu_renderer_real_get_scale;

View File

@@ -35,9 +35,6 @@ struct _GskGpuRendererClass
void (* make_current) (GskGpuRenderer *self);
GskGpuImage * (* get_backbuffer) (GskGpuRenderer *self);
void (* wait) (GskGpuRenderer *self,
GskGpuFrame **frame,
gsize n_frames);
double (* get_scale) (GskGpuRenderer *self);
GdkDmabufFormats * (* get_dmabuf_formats) (GskGpuRenderer *self);

View File

@@ -17,21 +17,14 @@ struct _GskGpuRoundedColorOp
};
static void
gsk_gpu_rounded_color_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_rounded_color_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuRoundedcolorInstance *instance;
GskGpuRoundedcolorInstance *instance = (GskGpuRoundedcolorInstance *) instance_;
instance = (GskGpuRoundedcolorInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "rounded-color");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rounded_rect (string, instance->outline);
gsk_gpu_print_rgba (string, instance->color);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_ROUNDED_COLOR_OP_CLASS = {
@@ -39,7 +32,7 @@ static const GskGpuShaderOpClass GSK_GPU_ROUNDED_COLOR_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuRoundedColorOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_rounded_color_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -50,6 +43,7 @@ static const GskGpuShaderOpClass GSK_GPU_ROUNDED_COLOR_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_roundedcolor_info,
#endif
gsk_gpu_rounded_color_op_print_instance,
gsk_gpu_roundedcolor_setup_attrib_locations,
gsk_gpu_roundedcolor_setup_vao
};

View File

@@ -3,6 +3,7 @@
#include "gskgpushaderopprivate.h"
#include "gskgpuframeprivate.h"
#include "gskgpuprintprivate.h"
#include "gskgldescriptorsprivate.h"
#include "gskgldeviceprivate.h"
#include "gskglframeprivate.h"
@@ -12,6 +13,8 @@
#include "gskvulkandeviceprivate.h"
#endif
#include "gdkglcontextprivate.h"
/* maximum number of ops to merge into one call
* If this number is too high, the command may take too long
* causing the driver to kill us.
@@ -26,6 +29,36 @@ gsk_gpu_shader_op_finish (GskGpuOp *op)
g_clear_object (&self->desc);
}
void
gsk_gpu_shader_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
{
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
const GskGpuShaderOpClass *shader_class = (const GskGpuShaderOpClass *) op->op_class;
const char *shader_name;
guchar *instance;
gsize i;
if (g_str_has_prefix (shader_class->shader_name, "gskgpu"))
shader_name = shader_class->shader_name + 6;
else
shader_name = shader_class->shader_name;
instance = gsk_gpu_frame_get_vertex_data (frame, self->vertex_offset);
for (i = 0; i < self->n_ops; i++)
{
gsk_gpu_print_op (string, indent, shader_name);
gsk_gpu_print_shader_info (string, self->clip);
shader_class->print_instance (self,
instance + i * shader_class->vertex_size,
string);
gsk_gpu_print_newline (string);
}
}
#ifdef GDK_RENDERING_VULKAN
GskGpuOp *
gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
@@ -37,15 +70,15 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
GskGpuShaderOpClass *shader_op_class = (GskGpuShaderOpClass *) op->op_class;
GskVulkanDescriptors *desc;
GskGpuOp *next;
gsize i, n;
gsize i, n_ops, max_ops_per_draw;
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_MERGE) &&
gsk_vulkan_device_has_feature (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)),
GDK_VULKAN_FEATURE_NONUNIFORM_INDEXING))
n = MAX_MERGE_OPS;
max_ops_per_draw = MAX_MERGE_OPS;
else
n = 1;
i = 1;
max_ops_per_draw = 1;
desc = GSK_VULKAN_DESCRIPTORS (self->desc);
if (desc && state->desc != desc)
{
@@ -53,7 +86,8 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
state->desc = desc;
}
for (next = op->next; next && i < n; next = next->next)
n_ops = self->n_ops;
for (next = op->next; next; next = next->next)
{
GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next;
@@ -61,10 +95,10 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
next_shader->desc != self->desc ||
next_shader->variation != self->variation ||
next_shader->clip != self->clip ||
next_shader->vertex_offset != self->vertex_offset + i * shader_op_class->vertex_size)
next_shader->vertex_offset != self->vertex_offset + n_ops * shader_op_class->vertex_size)
break;
i++;
n_ops += next_shader->n_ops;
}
vkCmdBindPipeline (state->vk_command_buffer,
@@ -78,10 +112,13 @@ gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
state->vk_format,
state->vk_render_pass));
vkCmdDraw (state->vk_command_buffer,
6 * instance_scale, i,
0, self->vertex_offset / shader_op_class->vertex_size);
for (i = 0; i < n_ops; i += max_ops_per_draw)
{
vkCmdDraw (state->vk_command_buffer,
6 * instance_scale, MIN (max_ops_per_draw, n_ops - i),
0, self->vertex_offset / shader_op_class->vertex_size + i);
}
return next;
}
@@ -104,7 +141,7 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op,
GskGpuShaderOpClass *shader_op_class = (GskGpuShaderOpClass *) op->op_class;
GskGLDescriptors *desc;
GskGpuOp *next;
gsize i, n, n_external;
gsize i, n_ops, n_external, max_ops_per_draw;
desc = GSK_GL_DESCRIPTORS (self->desc);
if (desc)
@@ -135,11 +172,12 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op,
}
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_MERGE))
n = MAX_MERGE_OPS;
max_ops_per_draw = MAX_MERGE_OPS;
else
n = 1;
i = 1;
for (next = op->next; next && i < n; next = next->next)
max_ops_per_draw = 1;
n_ops = self->n_ops;
for (next = op->next; next; next = next->next)
{
GskGpuShaderOp *next_shader = (GskGpuShaderOp *) next;
@@ -147,28 +185,32 @@ gsk_gpu_shader_op_gl_command_n (GskGpuOp *op,
next_shader->desc != self->desc ||
next_shader->variation != self->variation ||
next_shader->clip != self->clip ||
next_shader->vertex_offset != self->vertex_offset + i * shader_op_class->vertex_size)
next_shader->vertex_offset != self->vertex_offset + n_ops * shader_op_class->vertex_size)
break;
i++;
n_ops += next_shader->n_ops;
}
if (gsk_gpu_frame_should_optimize (frame, GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE))
for (i = 0; i < n_ops; i += max_ops_per_draw)
{
glDrawArraysInstancedBaseInstance (GL_TRIANGLES,
0,
6 * instance_scale,
i,
self->vertex_offset / shader_op_class->vertex_size);
}
else
{
shader_op_class->setup_vao (self->vertex_offset);
if (gdk_gl_context_has_feature (GDK_GL_CONTEXT (gsk_gpu_frame_get_context (frame)),
GDK_GL_FEATURE_BASE_INSTANCE))
{
glDrawArraysInstancedBaseInstance (GL_TRIANGLES,
0,
6 * instance_scale,
MIN (max_ops_per_draw, n_ops - i),
self->vertex_offset / shader_op_class->vertex_size + i);
}
else
{
shader_op_class->setup_vao (self->vertex_offset + i * shader_op_class->vertex_size);
glDrawArraysInstanced (GL_TRIANGLES,
0,
6 * instance_scale,
i);
glDrawArraysInstanced (GL_TRIANGLES,
0,
6 * instance_scale,
MIN (max_ops_per_draw, n_ops - i));
}
}
return next;
@@ -182,7 +224,7 @@ gsk_gpu_shader_op_gl_command (GskGpuOp *op,
return gsk_gpu_shader_op_gl_command_n (op, frame, state, 1);
}
GskGpuShaderOp *
void
gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
const GskGpuShaderOpClass *op_class,
guint32 variation,
@@ -190,20 +232,39 @@ gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
GskGpuDescriptors *desc,
gpointer out_vertex_data)
{
GskGpuShaderOp *self;
GskGpuOp *last;
GskGpuShaderOp *last_shader;
gsize vertex_offset;
self = (GskGpuShaderOp *) gsk_gpu_op_alloc (frame, &op_class->parent_class);
vertex_offset = gsk_gpu_frame_reserve_vertex_data (frame, op_class->vertex_size);
self->variation = variation;
self->clip = clip;
if (desc)
self->desc = g_object_ref (desc);
last = gsk_gpu_frame_get_last_op (frame);
/* careful: We're casting without checking, but the if() does the check */
last_shader = (GskGpuShaderOp *) last;
if (last &&
last->op_class == (const GskGpuOpClass *) op_class &&
last_shader->desc == desc &&
last_shader->variation == variation &&
last_shader->clip == clip &&
last_shader->vertex_offset + last_shader->n_ops * op_class->vertex_size == vertex_offset)
{
last_shader->n_ops++;
}
else
self->desc = NULL;
self->vertex_offset = gsk_gpu_frame_reserve_vertex_data (frame, op_class->vertex_size);
{
GskGpuShaderOp *self;
self = (GskGpuShaderOp *) gsk_gpu_op_alloc (frame, &op_class->parent_class);
*((gpointer *) out_vertex_data) = gsk_gpu_frame_get_vertex_data (frame, self->vertex_offset);
self->variation = variation;
self->clip = clip;
self->vertex_offset = vertex_offset;
if (desc)
self->desc = g_object_ref (desc);
else
self->desc = NULL;
self->n_ops = 1;
}
return self;
*((gpointer *) out_vertex_data) = gsk_gpu_frame_get_vertex_data (frame, vertex_offset);
}

View File

@@ -14,6 +14,7 @@ struct _GskGpuShaderOp
guint32 variation;
GskGpuShaderClip clip;
gsize vertex_offset;
gsize n_ops;
};
struct _GskGpuShaderOpClass
@@ -25,11 +26,14 @@ struct _GskGpuShaderOpClass
#ifdef GDK_RENDERING_VULKAN
const VkPipelineVertexInputStateCreateInfo *vertex_input_state;
#endif
void (* print_instance) (GskGpuShaderOp *shader,
gpointer instance,
GString *string);
void (* setup_attrib_locations) (GLuint program);
void (* setup_vao) (gsize offset);
};
GskGpuShaderOp * gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
void gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
const GskGpuShaderOpClass *op_class,
guint32 variation,
GskGpuShaderClip clip,
@@ -38,6 +42,10 @@ GskGpuShaderOp * gsk_gpu_shader_op_alloc (GskGpuF
void gsk_gpu_shader_op_finish (GskGpuOp *op);
void gsk_gpu_shader_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent);
#ifdef GDK_RENDERING_VULKAN
GskGpuOp * gsk_gpu_shader_op_vk_command_n (GskGpuOp *op,
GskGpuFrame *frame,

View File

@@ -19,21 +19,14 @@ struct _GskGpuStraightAlphaOp
};
static void
gsk_gpu_straight_alpha_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_straight_alpha_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuStraightalphaInstance *instance;
GskGpuStraightalphaInstance *instance = (GskGpuStraightalphaInstance *) instance_;
instance = (GskGpuStraightalphaInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "straight-alpha");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_STRAIGHT_ALPHA_OP_CLASS = {
@@ -41,7 +34,7 @@ static const GskGpuShaderOpClass GSK_GPU_STRAIGHT_ALPHA_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuStraightAlphaOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_straight_alpha_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -52,6 +45,7 @@ static const GskGpuShaderOpClass GSK_GPU_STRAIGHT_ALPHA_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_straightalpha_info,
#endif
gsk_gpu_straight_alpha_op_print_instance,
gsk_gpu_straightalpha_setup_attrib_locations,
gsk_gpu_straightalpha_setup_vao
};

View File

@@ -16,21 +16,14 @@ struct _GskGpuTextureOp
};
static void
gsk_gpu_texture_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_texture_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuTextureInstance *instance;
GskGpuTextureInstance *instance = (GskGpuTextureInstance *) instance_;
instance = (GskGpuTextureInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "texture");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_TEXTURE_OP_CLASS = {
@@ -38,7 +31,7 @@ static const GskGpuShaderOpClass GSK_GPU_TEXTURE_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuTextureOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_texture_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -49,6 +42,7 @@ static const GskGpuShaderOpClass GSK_GPU_TEXTURE_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_texture_info,
#endif
gsk_gpu_texture_op_print_instance,
gsk_gpu_texture_setup_attrib_locations,
gsk_gpu_texture_setup_vao
};

View File

@@ -118,8 +118,5 @@ typedef enum {
GSK_GPU_OPTIMIZE_BLIT = 1 << 3,
GSK_GPU_OPTIMIZE_GRADIENTS = 1 << 4,
GSK_GPU_OPTIMIZE_MIPMAP = 1 << 5,
GSK_GPU_OPTIMIZE_GLYPH_ALIGN = 1 << 6,
/* These require hardware support */
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 7,
} GskGpuOptimizations;

View File

@@ -17,20 +17,13 @@ struct _GskGpuUberOp
};
static void
gsk_gpu_uber_op_print (GskGpuOp *op,
GskGpuFrame *frame,
GString *string,
guint indent)
gsk_gpu_uber_op_print_instance (GskGpuShaderOp *shader,
gpointer instance_,
GString *string)
{
GskGpuShaderOp *shader = (GskGpuShaderOp *) op;
GskGpuUberInstance *instance;
GskGpuUberInstance *instance = instance_;
instance = (GskGpuUberInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
gsk_gpu_print_op (string, indent, "uber");
gsk_gpu_print_shader_info (string, shader->clip);
gsk_gpu_print_rect (string, instance->rect);
gsk_gpu_print_newline (string);
}
static const GskGpuShaderOpClass GSK_GPU_UBER_OP_CLASS = {
@@ -38,7 +31,7 @@ static const GskGpuShaderOpClass GSK_GPU_UBER_OP_CLASS = {
GSK_GPU_OP_SIZE (GskGpuUberOp),
GSK_GPU_STAGE_SHADER,
gsk_gpu_shader_op_finish,
gsk_gpu_uber_op_print,
gsk_gpu_shader_op_print,
#ifdef GDK_RENDERING_VULKAN
gsk_gpu_shader_op_vk_command,
#endif
@@ -49,8 +42,9 @@ static const GskGpuShaderOpClass GSK_GPU_UBER_OP_CLASS = {
#ifdef GDK_RENDERING_VULKAN
&gsk_gpu_uber_info,
#endif
gsk_gpu_uber_op_print_instance,
gsk_gpu_uber_setup_attrib_locations,
gsk_gpu_uber_setup_vao
gsk_gpu_uber_setup_vao,
};
void

View File

@@ -52,7 +52,7 @@ gsk_gpu_upload_op_gl_command_with_area (GskGpuOp *op,
{
glTexSubImage2D (GL_TEXTURE_2D, 0, area->x, area->y, area->width, area->height, gl_format, gl_type, data);
}
else if (stride % bpp == 0 && gdk_gl_context_has_unpack_subimage (context))
else if (stride % bpp == 0 && gdk_gl_context_has_feature (context, GDK_GL_FEATURE_UNPACK_SUBIMAGE))
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);

View File

@@ -72,11 +72,6 @@ gsk_ngl_renderer_create_context (GskGpuRenderer *renderer,
*/
*supported &= ~GSK_GPU_OPTIMIZE_UBER;
if (!gdk_gl_context_check_version (context, "4.2", "9.9") &&
!epoxy_has_gl_extension ("GL_EXT_base_instance") &&
!epoxy_has_gl_extension ("GL_ARB_base_instance"))
*supported &= ~GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE;
return GDK_DRAW_CONTEXT (context);
}
@@ -119,13 +114,6 @@ gsk_ngl_renderer_get_backbuffer (GskGpuRenderer *renderer)
return self->backbuffer;
}
static void
gsk_ngl_renderer_wait (GskGpuRenderer *self,
GskGpuFrame **frame,
gsize n_frames)
{
}
static double
gsk_ngl_renderer_get_scale (GskGpuRenderer *self)
{
@@ -164,7 +152,6 @@ gsk_ngl_renderer_class_init (GskNglRendererClass *klass)
gpu_renderer_class->create_context = gsk_ngl_renderer_create_context;
gpu_renderer_class->make_current = gsk_ngl_renderer_make_current;
gpu_renderer_class->get_backbuffer = gsk_ngl_renderer_get_backbuffer;
gpu_renderer_class->wait = gsk_ngl_renderer_wait;
gpu_renderer_class->get_scale = gsk_ngl_renderer_get_scale;
gpu_renderer_class->get_dmabuf_formats = gsk_ngl_renderer_get_dmabuf_formats;

View File

@@ -97,7 +97,8 @@ gsk_vulkan_buffer_new_internal (GskVulkanDevice *device,
self->allocator = gsk_vulkan_device_find_allocator (device,
requirements.memoryTypeBits,
GSK_VULKAN_MEMORY_MAPPABLE,
GSK_VULKAN_MEMORY_MAPPABLE);
GSK_VULKAN_MEMORY_MAPPABLE |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
gsk_vulkan_alloc (self->allocator,
requirements.size,
requirements.alignment,

View File

@@ -74,6 +74,21 @@ gsk_vulkan_frame_is_busy (GskGpuFrame *frame)
return vkGetFenceStatus (device, self->vk_fence) == VK_NOT_READY;
}
static void
gsk_vulkan_frame_wait (GskGpuFrame *frame)
{
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
VkDevice vk_device;
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)));
GSK_VK_CHECK (vkWaitForFences, vk_device,
1,
&self->vk_fence,
VK_FALSE,
INT64_MAX);
}
static void
gsk_vulkan_frame_setup (GskGpuFrame *frame)
{
@@ -387,6 +402,7 @@ gsk_vulkan_frame_class_init (GskVulkanFrameClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
gpu_frame_class->is_busy = gsk_vulkan_frame_is_busy;
gpu_frame_class->wait = gsk_vulkan_frame_wait;
gpu_frame_class->setup = gsk_vulkan_frame_setup;
gpu_frame_class->cleanup = gsk_vulkan_frame_cleanup;
gpu_frame_class->upload_texture = gsk_vulkan_frame_upload_texture;

View File

@@ -129,31 +129,6 @@ gsk_vulkan_renderer_get_backbuffer (GskGpuRenderer *renderer)
return self->targets[gdk_vulkan_context_get_draw_index (context)];
}
static void
gsk_vulkan_renderer_wait (GskGpuRenderer *renderer,
GskGpuFrame **frames,
gsize n_frames)
{
VkFence *fences;
VkDevice vk_device;
gsize i;
vk_device = gsk_vulkan_device_get_vk_device (GSK_VULKAN_DEVICE (gsk_gpu_renderer_get_device (renderer)));
fences = g_alloca (sizeof (VkFence) * n_frames);
for (i = 0; i < n_frames; i++)
{
fences[i] = gsk_vulkan_frame_get_vk_fence (GSK_VULKAN_FRAME (frames[i]));
}
GSK_VK_CHECK (vkWaitForFences, vk_device,
n_frames,
fences,
VK_FALSE,
INT64_MAX);
}
static GdkDmabufFormats *
gsk_vulkan_renderer_get_dmabuf_formats (GskGpuRenderer *renderer)
{
@@ -189,7 +164,6 @@ gsk_vulkan_renderer_class_init (GskVulkanRendererClass *klass)
gpu_renderer_class->create_context = gsk_vulkan_renderer_create_context;
gpu_renderer_class->make_current = gsk_vulkan_renderer_make_current;
gpu_renderer_class->get_backbuffer = gsk_vulkan_renderer_get_backbuffer;
gpu_renderer_class->wait = gsk_vulkan_renderer_wait;
gpu_renderer_class->get_dmabuf_formats = gsk_vulkan_renderer_get_dmabuf_formats;
renderer_class->unrealize = gsk_vulkan_renderer_unrealize;

View File

@@ -5,16 +5,13 @@
static const GdkDebugKey gsk_debug_keys[] = {
{ "renderer", GSK_DEBUG_RENDERER, "General renderer information" },
{ "opengl", GSK_DEBUG_OPENGL, "OpenGL renderer information" },
{ "vulkan", GSK_DEBUG_VULKAN, "Vulkan renderer information" },
{ "shaders", GSK_DEBUG_SHADERS, "Information about shaders" },
{ "surface", GSK_DEBUG_SURFACE, "Information about surfaces" },
{ "fallback", GSK_DEBUG_FALLBACK, "Information about fallback usage in renderers" },
{ "glyphcache", GSK_DEBUG_GLYPH_CACHE, "Information about glyph caching" },
{ "verbose", GSK_DEBUG_VERBOSE, "Print verbose output while rendering" },
{ "geometry", GSK_DEBUG_GEOMETRY, "Show borders (when using cairo)" },
{ "full-redraw", GSK_DEBUG_FULL_REDRAW, "Force full redraws" },
{ "sync", GSK_DEBUG_SYNC, "Sync after each frame" },
{ "staging", GSK_DEBUG_STAGING, "Use a staging image for texture upload (Vulkan only)" },
{ "offload-disable", GSK_DEBUG_OFFLOAD_DISABLE, "Disable graphics offload" },
{ "cairo", GSK_DEBUG_CAIRO, "Overlay error pattern over Cairo drawing (finds fallbacks)" },

View File

@@ -7,20 +7,17 @@ G_BEGIN_DECLS
typedef enum {
GSK_DEBUG_RENDERER = 1 << 0,
GSK_DEBUG_OPENGL = 1 << 1,
GSK_DEBUG_SHADERS = 1 << 2,
GSK_DEBUG_SURFACE = 1 << 3,
GSK_DEBUG_VULKAN = 1 << 4,
GSK_DEBUG_FALLBACK = 1 << 5,
GSK_DEBUG_GLYPH_CACHE = 1 << 6,
GSK_DEBUG_VERBOSE = 1 << 7,
GSK_DEBUG_VULKAN = 1 << 3,
GSK_DEBUG_FALLBACK = 1 << 4,
GSK_DEBUG_GLYPH_CACHE = 1 << 5,
GSK_DEBUG_VERBOSE = 1 << 6,
/* flags below may affect behavior */
GSK_DEBUG_GEOMETRY = 1 << 8,
GSK_DEBUG_FULL_REDRAW = 1 << 9,
GSK_DEBUG_SYNC = 1 << 10,
GSK_DEBUG_STAGING = 1 << 11,
GSK_DEBUG_OFFLOAD_DISABLE = 1 << 12,
GSK_DEBUG_CAIRO = 1 << 13,
GSK_DEBUG_GEOMETRY = 1 << 7,
GSK_DEBUG_FULL_REDRAW = 1 << 8,
GSK_DEBUG_STAGING = 1 << 10,
GSK_DEBUG_OFFLOAD_DISABLE = 1 << 11,
GSK_DEBUG_CAIRO = 1 << 12,
} GskDebugFlags;
#define GSK_DEBUG_ANY ((1 << 13) - 1)

View File

@@ -1,20 +0,0 @@
#pragma once
#include <graphene.h>
static inline void G_GNUC_PURE
gsk_point_interpolate (const graphene_point_t *p1,
const graphene_point_t *p2,
float t,
graphene_point_t *p)
{
p->x = p1->x * (1 - t) + p2->x * t;
p->Y = p1->y * (1 - t) + p2->y * t;
}
static inline float G_GNUC_PURE
gsk_point_distance (const graphene_point_t *p1,
const graphene_point_t *p2)
{
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
}

View File

@@ -44,9 +44,9 @@ gsk_reload_font (PangoFont *font,
cairo_hint_style_t hint_style,
cairo_antialias_t antialias)
{
cairo_font_options_t *options;
cairo_scaled_font_t *sf;
static cairo_font_options_t *options = NULL;
static PangoContext *context = NULL;
cairo_scaled_font_t *sf;
#if !PANGO_VERSION_CHECK (1, 52, 0)
PangoFontDescription *desc;
FcPattern *pattern;
@@ -80,7 +80,9 @@ gsk_reload_font (PangoFont *font,
g_set_object (&last_font, font);
g_clear_object (&last_result);
options = cairo_font_options_create ();
if (G_UNLIKELY (options == NULL))
options = cairo_font_options_create ();
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
cairo_scaled_font_get_font_options (sf, options);
@@ -100,7 +102,6 @@ gsk_reload_font (PangoFont *font,
cairo_font_options_get_subpixel_order (options) == CAIRO_SUBPIXEL_ORDER_DEFAULT)
{
last_result = g_object_ref (font);
cairo_font_options_destroy (options);
return g_object_ref (font);
}
@@ -109,11 +110,10 @@ gsk_reload_font (PangoFont *font,
cairo_font_options_set_antialias (options, antialias);
cairo_font_options_set_subpixel_order (options, CAIRO_SUBPIXEL_ORDER_DEFAULT);
if (!context)
if (G_UNLIKELY (context == NULL))
context = pango_context_new ();
pango_cairo_context_set_font_options (context, options);
cairo_font_options_destroy (options);
#if PANGO_VERSION_CHECK (1, 52, 0)
last_result = pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, context, NULL);
@@ -123,14 +123,9 @@ gsk_reload_font (PangoFont *font,
if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultMatch)
pango_cairo_context_set_resolution (context, dpi);
desc = pango_font_describe (font);
desc = pango_font_describe_with_absolute_size (font);
size = pango_font_description_get_size (desc);
if (pango_font_description_get_size_is_absolute (desc))
pango_font_description_set_absolute_size (desc, size * scale);
else
pango_font_description_set_size (desc, (int) floor (size * scale + .5));
pango_font_description_set_absolute_size (desc, size * scale);
last_result = pango_font_map_load_font (pango_font_get_font_map (font), context, desc);
pango_font_description_free (desc);
#endif
@@ -178,15 +173,16 @@ gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
cairo_hint_style_t
gsk_font_get_hint_style (PangoFont *font)
{
static cairo_font_options_t *options = NULL;
cairo_scaled_font_t *sf;
cairo_font_options_t *options;
cairo_hint_style_t style;
if (G_UNLIKELY (options == NULL))
options = cairo_font_options_create ();
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
options = cairo_font_options_create ();
cairo_scaled_font_get_font_options (sf, options);
style = cairo_font_options_get_hint_style (options);
cairo_font_options_destroy (options);
return style;
}

View File

@@ -86,6 +86,8 @@ translate_coordinates_to_accessible (GtkAccessible *accessible,
parent = gtk_accessible_get_accessible_parent (accessible);
while (parent != NULL)
{
g_object_unref (parent);
if (gtk_accessible_get_bounds (parent, &x, &y, &width, &height))
{
*xo = *xo - x;
@@ -138,6 +140,8 @@ translate_coordinates_from_accessible (GtkAccessible *accessible,
parent = gtk_accessible_get_accessible_parent (accessible);
while (parent != NULL)
{
g_object_unref (parent);
if (gtk_accessible_get_bounds (parent, &x, &y, &width, &height))
{
*xo = *xo + x;
@@ -172,6 +176,7 @@ accessible_at_point (GtkAccessible *parent,
child = gtk_accessible_get_next_accessible_sibling (child))
{
GtkAccessible *found = accessible_at_point (child, x - px, y - py, FALSE);
g_object_unref (child);
if (found)
result = found;
}

View File

@@ -183,6 +183,7 @@ gtk_at_spi_socket_get_bounds (GtkAccessible *accessible,
int *height)
{
GtkAccessible *accessible_parent;
gboolean res = FALSE;
g_assert (GTK_IS_AT_SPI_SOCKET (accessible));
@@ -190,7 +191,11 @@ gtk_at_spi_socket_get_bounds (GtkAccessible *accessible,
if (accessible_parent == NULL)
return FALSE;
return gtk_accessible_get_bounds (accessible_parent, x, y, width, height);
res = gtk_accessible_get_bounds (accessible_parent, x, y, width, height);
g_object_unref (accessible_parent);
return res;
}
static void

View File

@@ -27,12 +27,13 @@
#include "gtkcsslocationprivate.h"
typedef struct _GtkCssParserBlock GtkCssParserBlock;
typedef struct _GtkCssParserTokenStreamData GtkCssParserTokenStreamData;
struct _GtkCssParser
{
volatile int ref_count;
GtkCssTokenizer *tokenizer;
GPtrArray *tokenizers;
GFile *file;
GFile *directory;
GtkCssParserErrorFunc error_func;
@@ -42,6 +43,11 @@ struct _GtkCssParser
GArray *blocks;
GtkCssLocation location;
GtkCssToken token;
GtkCssVariableValue **refs;
gsize n_refs;
gsize next_ref;
gboolean var_fallback;
};
struct _GtkCssParserBlock
@@ -52,6 +58,12 @@ struct _GtkCssParserBlock
GtkCssTokenType alternative_token;
};
static inline GtkCssTokenizer *
get_tokenizer (GtkCssParser *self)
{
return g_ptr_array_index (self->tokenizers, self->tokenizers->len - 1);
}
static GtkCssParser *
gtk_css_parser_new (GtkCssTokenizer *tokenizer,
GFile *file,
@@ -64,7 +76,11 @@ gtk_css_parser_new (GtkCssTokenizer *tokenizer,
self = g_new0 (GtkCssParser, 1);
self->ref_count = 1;
self->tokenizer = gtk_css_tokenizer_ref (tokenizer);
self->tokenizers = g_ptr_array_new ();
g_ptr_array_add (self->tokenizers, gtk_css_tokenizer_ref (tokenizer));
g_ptr_array_set_free_func (self->tokenizers, (GDestroyNotify) gtk_css_tokenizer_unref);
if (file)
{
self->file = g_object_ref (file);
@@ -117,19 +133,46 @@ gtk_css_parser_new_for_bytes (GBytes *bytes,
return result;
}
GtkCssParser *
gtk_css_parser_new_for_token_stream (GtkCssVariableValue *value,
GFile *file,
GtkCssVariableValue **refs,
gsize n_refs,
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy)
{
GtkCssTokenizer *tokenizer;
GtkCssParser *result;
tokenizer = gtk_css_tokenizer_new_for_range (value->bytes, value->offset,
value->end_offset - value->offset);
result = gtk_css_parser_new (tokenizer, file, error_func, user_data, user_destroy);
gtk_css_tokenizer_unref (tokenizer);
result->refs = refs;
result->n_refs = n_refs;
result->next_ref = 0;
return result;
}
static void
gtk_css_parser_finalize (GtkCssParser *self)
{
if (self->user_destroy)
self->user_destroy (self->user_data);
g_clear_pointer (&self->tokenizer, gtk_css_tokenizer_unref);
g_clear_pointer (&self->tokenizers, g_ptr_array_unref);
g_clear_object (&self->file);
g_clear_object (&self->directory);
if (self->blocks->len)
g_critical ("Finalizing CSS parser with %u remaining blocks", self->blocks->len);
g_array_free (self->blocks, TRUE);
if (self->refs)
g_free (self->refs);
g_free (self);
}
@@ -239,7 +282,7 @@ gtk_css_parser_get_start_location (GtkCssParser *self)
const GtkCssLocation *
gtk_css_parser_get_end_location (GtkCssParser *self)
{
return gtk_css_tokenizer_get_location (self->tokenizer);
return gtk_css_tokenizer_get_location (get_tokenizer (self));
}
/**
@@ -273,12 +316,14 @@ static void
gtk_css_parser_ensure_token (GtkCssParser *self)
{
GError *error = NULL;
GtkCssTokenizer *tokenizer;
if (!gtk_css_token_is (&self->token, GTK_CSS_TOKEN_EOF))
return;
self->location = *gtk_css_tokenizer_get_location (self->tokenizer);
if (!gtk_css_tokenizer_read_token (self->tokenizer, &self->token, &error))
tokenizer = get_tokenizer (self);
self->location = *gtk_css_tokenizer_get_location (tokenizer);
if (!gtk_css_tokenizer_read_token (tokenizer, &self->token, &error))
{
/* We ignore the error here, because the resulting token will
* likely already trigger an error in the parsing code and
@@ -286,6 +331,64 @@ gtk_css_parser_ensure_token (GtkCssParser *self)
*/
g_clear_error (&error);
}
if (self->tokenizers->len > 1 && gtk_css_token_is (&self->token, GTK_CSS_TOKEN_EOF))
{
g_ptr_array_remove_index_fast (self->tokenizers, self->tokenizers->len - 1);
gtk_css_parser_ensure_token (self);
return;
}
/* Resolve var(--name): skip it and insert the resolved reference instead */
if (self->n_refs > 0 && gtk_css_token_is_function (&self->token, "var") && self->var_fallback == 0)
{
GtkCssVariableValue *ref;
GtkCssTokenizer *ref_tokenizer;
gtk_css_parser_start_block (self);
if (gtk_css_parser_has_token (self, GTK_CSS_TOKEN_IDENT))
{
char *var_name = gtk_css_parser_consume_ident (self);
if (var_name[0] != '-' || var_name[1] != '-')
{
g_free (var_name);
self->var_fallback++;
gtk_css_parser_skip (self);
gtk_css_parser_end_block (self);
self->var_fallback--;
return;
}
g_free (var_name);
}
else
{
self->var_fallback++;
gtk_css_parser_skip (self);
gtk_css_parser_end_block (self);
self->var_fallback--;
return;
}
/* If we encounter var() in a fallback when we can already resolve the
* actual variable, skip it */
self->var_fallback++;
gtk_css_parser_skip (self);
gtk_css_parser_end_block (self);
self->var_fallback--;
g_assert (self->next_ref < self->n_refs);
ref = self->refs[self->next_ref++];
ref_tokenizer = gtk_css_tokenizer_new_for_range (ref->bytes, ref->offset,
ref->end_offset - ref->offset);
g_ptr_array_add (self->tokenizers, ref_tokenizer);
gtk_css_parser_ensure_token (self);
}
}
const GtkCssToken *
@@ -1112,3 +1215,274 @@ gtk_css_parser_consume_any (GtkCssParser *parser,
return result;
}
gboolean
gtk_css_parser_has_references (GtkCssParser *self)
{
GtkCssTokenizer *tokenizer = get_tokenizer (self);
gboolean ret = FALSE;
int inner_blocks = 0, i;
gtk_css_tokenizer_save (tokenizer);
do {
const GtkCssToken *token;
token = gtk_css_parser_get_token (self);
if (inner_blocks == 0)
{
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
break;
if (gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_SQUARE))
{
goto error;
}
}
if (gtk_css_token_is_preserved (token, NULL))
{
if (inner_blocks > 0 && gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
gtk_css_parser_end_block (self);
inner_blocks--;
}
else
{
gtk_css_parser_consume_token (self);
}
}
else
{
gboolean is_var = gtk_css_token_is_function (token, "var");
inner_blocks++;
gtk_css_parser_start_block (self);
if (!ret && is_var)
{
token = gtk_css_parser_get_token (self);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
const char *var_name = gtk_css_token_get_string (token);
if (var_name[0] != '-' || var_name[1] != '-')
goto error;
gtk_css_parser_consume_token (self);
if (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_EOF) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_COMMA))
{
goto error;
}
ret = TRUE;
}
}
}
}
while (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SEMICOLON) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_CLOSE_CURLY));
if (inner_blocks > 0)
goto error;
gtk_css_tokenizer_restore (tokenizer);
self->location = *gtk_css_tokenizer_get_location (tokenizer);
gtk_css_tokenizer_read_token (tokenizer, &self->token, NULL);
return ret;
error:
for (i = 0; i < inner_blocks; i++)
gtk_css_parser_end_block (self);
gtk_css_tokenizer_restore (tokenizer);
self->location = *gtk_css_tokenizer_get_location (tokenizer);
gtk_css_tokenizer_read_token (tokenizer, &self->token, NULL);
return FALSE;
}
static void
clear_ref (GtkCssVariableValueReference *ref)
{
g_free (ref->name);
if (ref->fallback)
gtk_css_variable_value_unref (ref->fallback);
}
GtkCssVariableValue *
gtk_css_parser_parse_value_into_token_stream (GtkCssParser *self)
{
GBytes *bytes = gtk_css_tokenizer_get_bytes (get_tokenizer (self));
const GtkCssToken *token;
gsize offset;
gsize length = 0;
GArray *refs;
GtkCssVariableValueReference *out_refs;
gsize n_refs;
int inner_blocks = 0, i;
gboolean is_initial = FALSE;
refs = g_array_new (FALSE, TRUE, sizeof (GtkCssVariableValueReference));
g_array_set_clear_func (refs, (GDestroyNotify) clear_ref);
for (token = gtk_css_parser_peek_token (self);
gtk_css_token_is (token, GTK_CSS_TOKEN_WHITESPACE);
token = gtk_css_parser_peek_token (self))
{
gtk_css_parser_consume_token (self);
}
offset = self->location.bytes;
do {
token = gtk_css_parser_get_token (self);
if (length == 0 && gtk_css_token_is_ident (token, "initial"))
is_initial = TRUE;
if (gtk_css_token_is (token, GTK_CSS_TOKEN_BAD_STRING) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_BAD_URL))
{
gtk_css_parser_error_syntax (self, "Invalid property value");
goto error;
}
if (inner_blocks == 0)
{
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
break;
if (gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS) ||
gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_SQUARE))
{
gtk_css_parser_error_syntax (self, "Invalid property value");
goto error;
}
}
if (gtk_css_token_is_preserved (token, NULL))
{
if (inner_blocks > 0 && gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
length++;
gtk_css_parser_end_block (self);
inner_blocks--;
}
else
{
length++;
gtk_css_parser_consume_token (self);
}
}
else
{
gboolean is_var = gtk_css_token_is_function (token, "var");
length++;
inner_blocks++;
gtk_css_parser_start_block (self);
if (is_var)
{
token = gtk_css_parser_get_token (self);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
{
GtkCssVariableValueReference ref;
char *var_name = g_strdup (gtk_css_token_get_string (token));
if (var_name[0] != '-' || var_name[1] != '-')
{
gtk_css_parser_error_value (self, "Invalid variable name: %s", var_name);
g_free (var_name);
goto error;
}
length++;
gtk_css_parser_consume_token (self);
if (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_EOF) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_COMMA))
{
gtk_css_parser_error_syntax (self, "Invalid property value");
g_free (var_name);
goto error;
}
ref.name = var_name;
if (gtk_css_parser_has_token (self, GTK_CSS_TOKEN_EOF))
{
ref.length = 3;
ref.fallback = NULL;
}
else
{
length++;
gtk_css_parser_consume_token (self);
ref.fallback = gtk_css_parser_parse_value_into_token_stream (self);
if (ref.fallback == NULL)
{
gtk_css_parser_error_value (self, "Invalid fallback for: %s", var_name);
g_free (var_name);
goto error;
}
ref.length = 4 + ref.fallback->length;
length += ref.fallback->length;
}
g_array_append_val (refs, ref);
}
}
}
}
while (!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_SEMICOLON) &&
!gtk_css_parser_has_token (self, GTK_CSS_TOKEN_CLOSE_CURLY));
if (inner_blocks > 0)
{
gtk_css_parser_error_syntax (self, "Invalid property value");
goto error;
}
if (is_initial && length == 1)
{
g_array_unref (refs);
return gtk_css_variable_value_new_initial (bytes,
offset,
self->location.bytes);
}
else
{
out_refs = g_array_steal (refs, &n_refs);
return gtk_css_variable_value_new (bytes,
offset,
self->location.bytes,
length,
out_refs,
n_refs);
}
error:
for (i = 0; i < inner_blocks; i++)
gtk_css_parser_end_block (self);
g_array_unref (refs);
return NULL;
}

View File

@@ -22,6 +22,7 @@
#include "gtkcssenums.h"
#include "gtkcsstokenizerprivate.h"
#include "gtkcssvariablevalueprivate.h"
#include <gio/gio.h>
@@ -58,6 +59,13 @@ GtkCssParser * gtk_css_parser_new_for_bytes (GBytes
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy);
GtkCssParser * gtk_css_parser_new_for_token_stream (GtkCssVariableValue *value,
GFile *file,
GtkCssVariableValue **refs,
gsize n_refs,
GtkCssParserErrorFunc error_func,
gpointer user_data,
GDestroyNotify user_destroy);
GtkCssParser * gtk_css_parser_ref (GtkCssParser *self);
void gtk_css_parser_unref (GtkCssParser *self);
@@ -150,5 +158,9 @@ gsize gtk_css_parser_consume_any (GtkCssParser
gsize n_options,
gpointer user_data);
gboolean gtk_css_parser_has_references (GtkCssParser *parser);
GtkCssVariableValue * gtk_css_parser_parse_value_into_token_stream (GtkCssParser *parser);
G_END_DECLS

View File

@@ -36,8 +36,15 @@ struct _GtkCssTokenizer
const char *end;
GtkCssLocation position;
GArray *saved_states;
};
typedef struct
{
GtkCssLocation position;
const char *data;
} GtkCssTokenizerSavedState;
void
gtk_css_token_clear (GtkCssToken *token)
{
@@ -568,6 +575,14 @@ gtk_css_token_init_dimension (GtkCssToken *token,
GtkCssTokenizer *
gtk_css_tokenizer_new (GBytes *bytes)
{
return gtk_css_tokenizer_new_for_range (bytes, 0, g_bytes_get_size (bytes));
}
GtkCssTokenizer *
gtk_css_tokenizer_new_for_range (GBytes *bytes,
gsize offset,
gsize length)
{
GtkCssTokenizer *tokenizer;
@@ -576,10 +591,11 @@ gtk_css_tokenizer_new (GBytes *bytes)
tokenizer->bytes = g_bytes_ref (bytes);
tokenizer->name_buffer = g_string_new (NULL);
tokenizer->data = g_bytes_get_data (bytes, NULL);
tokenizer->end = tokenizer->data + g_bytes_get_size (bytes);
tokenizer->data = g_bytes_get_region (bytes, 1, offset, length);
tokenizer->end = tokenizer->data + length;
gtk_css_location_init (&tokenizer->position);
tokenizer->saved_states = g_array_new (FALSE, FALSE, sizeof (GtkCssTokenizerSavedState));
return tokenizer;
}
@@ -601,9 +617,16 @@ gtk_css_tokenizer_unref (GtkCssTokenizer *tokenizer)
g_string_free (tokenizer->name_buffer, TRUE);
g_bytes_unref (tokenizer->bytes);
g_array_unref (tokenizer->saved_states);
g_free (tokenizer);
}
GBytes *
gtk_css_tokenizer_get_bytes (GtkCssTokenizer *tokenizer)
{
return tokenizer->bytes;
}
const GtkCssLocation *
gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer)
{
@@ -1020,7 +1043,7 @@ gtk_css_tokenizer_read_ident_like (GtkCssTokenizer *tokenizer,
{
gtk_css_tokenizer_read_name (tokenizer);
if (*tokenizer->data == '(')
if (gtk_css_tokenizer_remaining (tokenizer) > 0 && *tokenizer->data == '(')
{
gtk_css_tokenizer_consume_ascii (tokenizer);
if (g_ascii_strcasecmp (tokenizer->name_buffer->str, "url") == 0)
@@ -1484,3 +1507,29 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
}
}
void
gtk_css_tokenizer_save (GtkCssTokenizer *tokenizer)
{
GtkCssTokenizerSavedState state;
state.position = tokenizer->position;
state.data = tokenizer->data;
g_array_append_val (tokenizer->saved_states, state);
}
void
gtk_css_tokenizer_restore (GtkCssTokenizer *tokenizer)
{
GtkCssTokenizerSavedState state;
int index = tokenizer->saved_states->len - 1;
g_assert (index >= 0);
state = g_array_index (tokenizer->saved_states, GtkCssTokenizerSavedState, index);
g_array_remove_index_fast (tokenizer->saved_states, index);
tokenizer->position = state.position;
tokenizer->data = state.data;
}

View File

@@ -138,15 +138,22 @@ void gtk_css_token_print (const GtkCssTok
char * gtk_css_token_to_string (const GtkCssToken *token);
GtkCssTokenizer * gtk_css_tokenizer_new (GBytes *bytes);
GtkCssTokenizer * gtk_css_tokenizer_new_for_range (GBytes *bytes,
gsize offset,
gsize length);
GtkCssTokenizer * gtk_css_tokenizer_ref (GtkCssTokenizer *tokenizer);
void gtk_css_tokenizer_unref (GtkCssTokenizer *tokenizer);
GBytes * gtk_css_tokenizer_get_bytes (GtkCssTokenizer *tokenizer);
const GtkCssLocation * gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer) G_GNUC_CONST;
gboolean gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer,
GtkCssToken *token,
GError **error);
void gtk_css_tokenizer_save (GtkCssTokenizer *tokenizer);
void gtk_css_tokenizer_restore (GtkCssTokenizer *tokenizer);
G_END_DECLS

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#include "gtkcssvariablevalueprivate.h"
GtkCssVariableValue *
gtk_css_variable_value_new (GBytes *bytes,
gsize offset,
gsize end_offset,
gsize length,
GtkCssVariableValueReference *references,
gsize n_references)
{
GtkCssVariableValue *self = g_new0 (GtkCssVariableValue, 1);
self->ref_count = 1;
self->bytes = g_bytes_ref (bytes);
self->offset = offset;
self->end_offset = end_offset;
self->length = length;
self->references = references;
self->n_references = n_references;
return self;
}
GtkCssVariableValue *
gtk_css_variable_value_new_initial (GBytes *bytes,
gsize offset,
gsize end_offset)
{
GtkCssVariableValue *self = gtk_css_variable_value_new (bytes, offset, end_offset, 1, NULL, 0);
self->is_invalid = TRUE;
return self;
}
GtkCssVariableValue *
gtk_css_variable_value_ref (GtkCssVariableValue *self)
{
self->ref_count++;
return self;
}
void
gtk_css_variable_value_unref (GtkCssVariableValue *self)
{
gsize i;
self->ref_count--;
if (self->ref_count > 0)
return;
g_bytes_unref (self->bytes);
for (i = 0; i < self->n_references; i++)
{
GtkCssVariableValueReference *ref = &self->references[i];
g_free (ref->name);
if (ref->fallback)
gtk_css_variable_value_unref (ref->fallback);
}
g_free (self->references);
g_free (self);
}
void
gtk_css_variable_value_print (GtkCssVariableValue *self,
GString *string)
{
gsize len = self->end_offset - self->offset;
gconstpointer data = g_bytes_get_region (self->bytes, 1, self->offset, len);
g_assert (data != NULL);
g_string_append_len (string, (const char *) data, len);
}
gboolean
gtk_css_variable_value_equal (const GtkCssVariableValue *value1,
const GtkCssVariableValue *value2)
{
if (value1 == value2)
return TRUE;
if (value1 == NULL || value2 == NULL)
return FALSE;
if (value1->bytes != value2->bytes)
return FALSE;
if (value1->offset != value2->offset)
return FALSE;
if (value1->end_offset != value2->end_offset)
return FALSE;
return TRUE;
}
GtkCssVariableValue *
gtk_css_variable_value_transition (GtkCssVariableValue *start,
GtkCssVariableValue *end,
double progress)
{
GtkCssVariableValue *ret = progress < 0.5 ? start : end;
if (ret == NULL)
return NULL;
return gtk_css_variable_value_ref (ret);
}
void
gtk_css_variable_value_set_section (GtkCssVariableValue *self,
GtkCssSection *section)
{
self->section = gtk_css_section_ref (section);
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#pragma once
#include "gtkcss.h"
#include "gtkcsstokenizerprivate.h"
G_BEGIN_DECLS
typedef struct _GtkCssVariableValueReference GtkCssVariableValueReference;
typedef struct _GtkCssVariableValue GtkCssVariableValue;
struct _GtkCssVariableValueReference
{
char *name;
gsize length;
GtkCssVariableValue *fallback;
};
struct _GtkCssVariableValue
{
int ref_count;
GBytes *bytes;
gsize offset;
gsize end_offset;
gsize length;
GtkCssVariableValueReference *references;
gsize n_references;
GtkCssSection *section;
gboolean is_invalid;
};
GtkCssVariableValue *gtk_css_variable_value_new (GBytes *bytes,
gsize offset,
gsize end_offset,
gsize length,
GtkCssVariableValueReference *references,
gsize n_references);
GtkCssVariableValue *gtk_css_variable_value_new_initial (GBytes *bytes,
gsize offset,
gsize end_offset);
GtkCssVariableValue *gtk_css_variable_value_ref (GtkCssVariableValue *self);
void gtk_css_variable_value_unref (GtkCssVariableValue *self);
void gtk_css_variable_value_print (GtkCssVariableValue *self,
GString *string);
gboolean gtk_css_variable_value_equal (const GtkCssVariableValue *value1,
const GtkCssVariableValue *value2) G_GNUC_PURE;
GtkCssVariableValue *gtk_css_variable_value_transition (GtkCssVariableValue *start,
GtkCssVariableValue *end,
double progress);
void gtk_css_variable_value_set_section (GtkCssVariableValue *self,
GtkCssSection *section);
G_END_DECLS

View File

@@ -6,8 +6,9 @@ gtk_css_public_sources = files([
gtk_css_private_sources = files([
'gtkcssdataurl.c',
'gtkcssparser.c',
'gtkcsstokenizer.c',
'gtkcssserializer.c',
'gtkcsstokenizer.c',
'gtkcssvariablevalue.c',
])
gtk_css_public_headers = files([

View File

@@ -1087,6 +1087,7 @@ gtk_accessible_platform_changed (GtkAccessible *self,
if (parent != NULL)
{
g_clear_object (&context);
context = gtk_accessible_get_at_context (parent);
g_object_unref (parent);
}

View File

@@ -541,6 +541,7 @@ gtk_at_context_set_accessible_parent (GtkATContext *self,
parent_context = get_parent_context (self);
if (parent_context && parent_context->realized)
gtk_at_context_realize (self);
g_clear_object (&parent_context);
}
}
}

View File

@@ -37,9 +37,178 @@
#include "gtkstyleanimationprivate.h"
#include "gtkstylepropertyprivate.h"
#include "gtkstyleproviderprivate.h"
#include "gtkcsscustompropertypoolprivate.h"
G_DEFINE_TYPE (GtkCssAnimatedStyle, gtk_css_animated_style, GTK_TYPE_CSS_STYLE)
static const int core_props[] = {
GTK_CSS_PROPERTY_COLOR,
GTK_CSS_PROPERTY_DPI,
GTK_CSS_PROPERTY_FONT_SIZE,
GTK_CSS_PROPERTY_ICON_PALETTE
};
static const int background_props[] = {
GTK_CSS_PROPERTY_BACKGROUND_COLOR,
GTK_CSS_PROPERTY_BOX_SHADOW,
GTK_CSS_PROPERTY_BACKGROUND_CLIP,
GTK_CSS_PROPERTY_BACKGROUND_ORIGIN,
GTK_CSS_PROPERTY_BACKGROUND_SIZE,
GTK_CSS_PROPERTY_BACKGROUND_POSITION,
GTK_CSS_PROPERTY_BACKGROUND_REPEAT,
GTK_CSS_PROPERTY_BACKGROUND_IMAGE,
GTK_CSS_PROPERTY_BACKGROUND_BLEND_MODE
};
static const int border_props[] = {
GTK_CSS_PROPERTY_BORDER_TOP_STYLE,
GTK_CSS_PROPERTY_BORDER_TOP_WIDTH,
GTK_CSS_PROPERTY_BORDER_LEFT_STYLE,
GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH,
GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE,
GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE,
GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH,
GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS,
GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS,
GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS,
GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS,
GTK_CSS_PROPERTY_BORDER_TOP_COLOR,
GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR,
GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR,
GTK_CSS_PROPERTY_BORDER_LEFT_COLOR,
GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE,
GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT,
GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE,
GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH
};
static const int icon_props[] = {
GTK_CSS_PROPERTY_ICON_SIZE,
GTK_CSS_PROPERTY_ICON_SHADOW,
GTK_CSS_PROPERTY_ICON_STYLE,
};
static const int outline_props[] = {
GTK_CSS_PROPERTY_OUTLINE_STYLE,
GTK_CSS_PROPERTY_OUTLINE_WIDTH,
GTK_CSS_PROPERTY_OUTLINE_OFFSET,
GTK_CSS_PROPERTY_OUTLINE_COLOR,
};
static const int font_props[] = {
GTK_CSS_PROPERTY_FONT_FAMILY,
GTK_CSS_PROPERTY_FONT_STYLE,
GTK_CSS_PROPERTY_FONT_WEIGHT,
GTK_CSS_PROPERTY_FONT_STRETCH,
GTK_CSS_PROPERTY_LETTER_SPACING,
GTK_CSS_PROPERTY_TEXT_SHADOW,
GTK_CSS_PROPERTY_CARET_COLOR,
GTK_CSS_PROPERTY_SECONDARY_CARET_COLOR,
GTK_CSS_PROPERTY_FONT_FEATURE_SETTINGS,
GTK_CSS_PROPERTY_FONT_VARIATION_SETTINGS,
GTK_CSS_PROPERTY_LINE_HEIGHT,
};
static const int font_variant_props[] = {
GTK_CSS_PROPERTY_TEXT_DECORATION_LINE,
GTK_CSS_PROPERTY_TEXT_DECORATION_COLOR,
GTK_CSS_PROPERTY_TEXT_DECORATION_STYLE,
GTK_CSS_PROPERTY_TEXT_TRANSFORM,
GTK_CSS_PROPERTY_FONT_KERNING,
GTK_CSS_PROPERTY_FONT_VARIANT_LIGATURES,
GTK_CSS_PROPERTY_FONT_VARIANT_POSITION,
GTK_CSS_PROPERTY_FONT_VARIANT_CAPS,
GTK_CSS_PROPERTY_FONT_VARIANT_NUMERIC,
GTK_CSS_PROPERTY_FONT_VARIANT_ALTERNATES,
GTK_CSS_PROPERTY_FONT_VARIANT_EAST_ASIAN,
};
static const int animation_props[] = {
GTK_CSS_PROPERTY_ANIMATION_NAME,
GTK_CSS_PROPERTY_ANIMATION_DURATION,
GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION,
GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT,
GTK_CSS_PROPERTY_ANIMATION_DIRECTION,
GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE,
GTK_CSS_PROPERTY_ANIMATION_DELAY,
GTK_CSS_PROPERTY_ANIMATION_FILL_MODE,
};
static const int transition_props[] = {
GTK_CSS_PROPERTY_TRANSITION_PROPERTY,
GTK_CSS_PROPERTY_TRANSITION_DURATION,
GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION,
GTK_CSS_PROPERTY_TRANSITION_DELAY,
};
static const int size_props[] = {
GTK_CSS_PROPERTY_MARGIN_TOP,
GTK_CSS_PROPERTY_MARGIN_LEFT,
GTK_CSS_PROPERTY_MARGIN_BOTTOM,
GTK_CSS_PROPERTY_MARGIN_RIGHT,
GTK_CSS_PROPERTY_PADDING_TOP,
GTK_CSS_PROPERTY_PADDING_LEFT,
GTK_CSS_PROPERTY_PADDING_BOTTOM,
GTK_CSS_PROPERTY_PADDING_RIGHT,
GTK_CSS_PROPERTY_BORDER_SPACING,
GTK_CSS_PROPERTY_MIN_WIDTH,
GTK_CSS_PROPERTY_MIN_HEIGHT,
};
static const int other_props[] = {
GTK_CSS_PROPERTY_ICON_SOURCE,
GTK_CSS_PROPERTY_ICON_TRANSFORM,
GTK_CSS_PROPERTY_ICON_FILTER,
GTK_CSS_PROPERTY_TRANSFORM,
GTK_CSS_PROPERTY_TRANSFORM_ORIGIN,
GTK_CSS_PROPERTY_OPACITY,
GTK_CSS_PROPERTY_FILTER,
};
#define DEFINE_VALUES(ENUM, TYPE, NAME) \
static inline void \
gtk_css_ ## NAME ## _values_recompute (GtkCssAnimatedStyle *animated) \
{ \
GtkCssStyle *style = (GtkCssStyle *)animated; \
GtkCssValue **values = (GtkCssValue **)((guint8*)(animated->style->NAME) + sizeof (GtkCssValues)); \
int i; \
\
for (i = 0; i < G_N_ELEMENTS (NAME ## _props); i++) \
{ \
guint id = NAME ## _props[i]; \
GtkCssValue *original, *computed; \
\
if (values[i] == NULL) \
continue; \
\
original = gtk_css_style_get_original_value (style, id); \
if (original == NULL) \
continue; \
\
computed = _gtk_css_value_compute (original, \
id, \
animated->provider, \
style, \
animated->parent_style, \
NULL); \
if (computed == NULL) \
continue; \
\
gtk_css_animated_style_set_animated_value (animated, id, computed); \
} \
}
DEFINE_VALUES (CORE, Core, core)
DEFINE_VALUES (BACKGROUND, Background, background)
DEFINE_VALUES (BORDER, Border, border)
DEFINE_VALUES (ICON, Icon, icon)
DEFINE_VALUES (OUTLINE, Outline, outline)
DEFINE_VALUES (FONT, Font, font)
DEFINE_VALUES (FONT_VARIANT, FontVariant, font_variant)
DEFINE_VALUES (ANIMATION, Animation, animation)
DEFINE_VALUES (TRANSITION, Transition, transition)
DEFINE_VALUES (SIZE, Size, size)
DEFINE_VALUES (OTHER, Other, other)
static GtkCssSection *
gtk_css_animated_style_get_section (GtkCssStyle *style,
@@ -74,6 +243,15 @@ gtk_css_animated_style_get_static_style (GtkCssStyle *style)
return (GtkCssStaticStyle *)animated->style;
}
static GtkCssValue *
gtk_css_animated_style_get_original_value (GtkCssStyle *style,
guint id)
{
GtkCssAnimatedStyle *animated = GTK_CSS_ANIMATED_STYLE (style);
return gtk_css_style_get_original_value (animated->style, id);
}
static void
gtk_css_animated_style_dispose (GObject *object)
{
@@ -96,6 +274,9 @@ gtk_css_animated_style_finalize (GObject *object)
GtkCssAnimatedStyle *style = GTK_CSS_ANIMATED_STYLE (object);
g_object_unref (style->style);
if (style->parent_style)
g_object_unref (style->parent_style);
g_object_unref (style->provider);
G_OBJECT_CLASS (gtk_css_animated_style_parent_class)->finalize (object);
}
@@ -112,6 +293,7 @@ gtk_css_animated_style_class_init (GtkCssAnimatedStyleClass *klass)
style_class->get_section = gtk_css_animated_style_get_section;
style_class->is_static = gtk_css_animated_style_is_static;
style_class->get_static_style = gtk_css_animated_style_get_static_style;
style_class->get_original_value = gtk_css_animated_style_get_original_value;
}
static void
@@ -546,6 +728,51 @@ gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style,
return gtk_css_style_get_value (style->style, id);
}
void
gtk_css_animated_style_set_animated_custom_value (GtkCssAnimatedStyle *animated,
int id,
GtkCssVariableValue *value)
{
GtkCssStyle *style = (GtkCssStyle *)animated;
gtk_internal_return_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style));
gtk_internal_return_if_fail (value != NULL);
if (style->variables == NULL)
{
style->variables = gtk_css_variable_set_new ();
if (animated->parent_style)
gtk_css_variable_set_set_parent (style->variables,
animated->parent_style->variables);
}
else if (style->variables == animated->style->variables)
{
gtk_css_variable_set_unref (style->variables);
style->variables = gtk_css_variable_set_copy (animated->style->variables);
}
gtk_css_variable_set_add (style->variables, id, value);
gtk_css_core_values_recompute (animated);
gtk_css_background_values_recompute (animated);
gtk_css_border_values_recompute (animated);
gtk_css_icon_values_recompute (animated);
gtk_css_outline_values_recompute (animated);
gtk_css_font_values_recompute (animated);
gtk_css_font_variant_values_recompute (animated);
gtk_css_animation_values_recompute (animated);
gtk_css_transition_values_recompute (animated);
gtk_css_size_values_recompute (animated);
gtk_css_other_values_recompute (animated);
}
GtkCssVariableValue *
gtk_css_animated_style_get_intrinsic_custom_value (GtkCssAnimatedStyle *style,
int id)
{
return gtk_css_style_get_custom_property (style->style, id);
}
static GPtrArray *
gtk_css_animated_style_create_dynamic (GPtrArray *animations,
GtkCssStyle *style,
@@ -770,7 +997,6 @@ gtk_css_animated_style_find_animation (GtkStyleAnimation **animations,
static GPtrArray *
gtk_css_animated_style_create_css_animations (GPtrArray *animations,
GtkCssStyle *base_style,
GtkCssStyle *parent_style,
gint64 timestamp,
GtkStyleProvider *provider,
GtkCssStyle *source)
@@ -832,8 +1058,6 @@ gtk_css_animated_style_create_css_animations (GPtrArray *animations,
if (keyframes == NULL)
continue;
keyframes = _gtk_css_keyframes_compute (keyframes, provider, base_style, parent_style);
animation = _gtk_css_animation_new (name,
keyframes,
timestamp,
@@ -844,7 +1068,6 @@ gtk_css_animated_style_create_css_animations (GPtrArray *animations,
_gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)),
_gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)),
_gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100));
_gtk_css_keyframes_unref (keyframes);
}
if (!animations)
@@ -893,7 +1116,7 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
if (previous_style != NULL)
animations = gtk_css_animated_style_create_css_transitions (animations, base_style, timestamp, previous_style);
animations = gtk_css_animated_style_create_css_animations (animations, base_style, parent_style, timestamp, provider, previous_style);
animations = gtk_css_animated_style_create_css_animations (animations, base_style, timestamp, provider, previous_style);
animations = gtk_css_animated_style_create_dynamic (animations, base_style, timestamp);
if (animations == NULL)
@@ -902,6 +1125,9 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
result = g_object_new (GTK_TYPE_CSS_ANIMATED_STYLE, NULL);
result->style = g_object_ref (base_style);
if (parent_style)
result->parent_style = g_object_ref (parent_style);
result->provider = g_object_ref (provider);
result->current_time = timestamp;
result->n_animations = animations->len;
result->animations = g_ptr_array_free (animations, FALSE);
@@ -918,6 +1144,8 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
style->transition = (GtkCssTransitionValues *)gtk_css_values_ref ((GtkCssValues *)base_style->transition);
style->size = (GtkCssSizeValues *)gtk_css_values_ref ((GtkCssValues *)base_style->size);
style->other = (GtkCssOtherValues *)gtk_css_values_ref ((GtkCssValues *)base_style->other);
if (base_style->variables)
style->variables = gtk_css_variable_set_ref (base_style->variables);
gtk_css_animated_style_apply_animations (result);
@@ -927,7 +1155,9 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
GtkCssStyle *
gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
GtkCssStyle *base_style,
gint64 timestamp)
GtkCssStyle *parent_style,
gint64 timestamp,
GtkStyleProvider *provider)
{
GtkCssAnimatedStyle *result;
GtkCssStyle *style;
@@ -936,6 +1166,8 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (source), NULL);
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (base_style), NULL);
gtk_internal_return_val_if_fail (parent_style == NULL || GTK_IS_CSS_STYLE (parent_style), NULL);
gtk_internal_return_val_if_fail (GTK_IS_STYLE_PROVIDER (provider), NULL);
if (timestamp == 0)
return g_object_ref (source->style);
@@ -966,6 +1198,9 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
result = g_object_new (GTK_TYPE_CSS_ANIMATED_STYLE, NULL);
result->style = g_object_ref (base_style);
if (parent_style)
result->parent_style = g_object_ref (parent_style);
result->provider = g_object_ref (provider);
result->current_time = timestamp;
result->n_animations = animations->len;
result->animations = g_ptr_array_free (animations, FALSE);
@@ -982,8 +1217,34 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
style->transition = (GtkCssTransitionValues *)gtk_css_values_ref ((GtkCssValues *)base_style->transition);
style->size = (GtkCssSizeValues *)gtk_css_values_ref ((GtkCssValues *)base_style->size);
style->other = (GtkCssOtherValues *)gtk_css_values_ref ((GtkCssValues *)base_style->other);
if (base_style->variables)
style->variables = gtk_css_variable_set_ref (base_style->variables);
gtk_css_animated_style_apply_animations (result);
return GTK_CSS_STYLE (result);
}
GtkCssStyle *
gtk_css_animated_style_get_base_style (GtkCssAnimatedStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
return style->style;
}
GtkCssStyle *
gtk_css_animated_style_get_parent_style (GtkCssAnimatedStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
return style->parent_style;
}
GtkStyleProvider *
gtk_css_animated_style_get_provider (GtkCssAnimatedStyle *style)
{
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (style), NULL);
return style->provider;
}

View File

@@ -38,6 +38,8 @@ struct _GtkCssAnimatedStyle
GtkCssStyle parent;
GtkCssStyle *style; /* the style if we weren't animating */
GtkCssStyle *parent_style;
GtkStyleProvider *provider;
gint64 current_time; /* the current time in our world */
gpointer *animations; /* GtkStyleAnimation**, least important one first */
@@ -57,15 +59,26 @@ GtkCssStyle * gtk_css_animated_style_new (GtkCssStyle
GtkStyleProvider *provider,
GtkCssStyle *previous_style);
GtkCssStyle * gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
GtkCssStyle *base,
gint64 timestamp);
GtkCssStyle *base_style,
GtkCssStyle *parent_style,
gint64 timestamp,
GtkStyleProvider *provider);
void gtk_css_animated_style_set_animated_value(GtkCssAnimatedStyle *style,
guint id,
GtkCssValue *value);
GtkCssValue * gtk_css_animated_style_get_intrinsic_value (GtkCssAnimatedStyle *style,
guint id);
void gtk_css_animated_style_set_animated_custom_value (GtkCssAnimatedStyle *animated,
int id,
GtkCssVariableValue *value);
GtkCssVariableValue * gtk_css_animated_style_get_intrinsic_custom_value (GtkCssAnimatedStyle *style,
int id);
GtkCssStyle * gtk_css_animated_style_get_base_style (GtkCssAnimatedStyle *style);
GtkCssStyle * gtk_css_animated_style_get_parent_style (GtkCssAnimatedStyle *style);
GtkStyleProvider * gtk_css_animated_style_get_provider (GtkCssAnimatedStyle *style);
G_END_DECLS

View File

@@ -90,6 +90,9 @@ gtk_css_animation_apply_values (GtkStyleAnimation *style_animation,
GtkCssAnimatedStyle *style)
{
GtkCssAnimation *animation = (GtkCssAnimation *)style_animation;
GtkCssStyle *base_style, *parent_style;
GtkStyleProvider *provider;
GtkCssKeyframes *resolved_keyframes;
double progress;
guint i;
@@ -99,19 +102,43 @@ gtk_css_animation_apply_values (GtkStyleAnimation *style_animation,
progress = gtk_css_animation_get_progress (animation);
progress = _gtk_css_ease_value_transform (animation->ease, progress);
for (i = 0; i < _gtk_css_keyframes_get_n_properties (animation->keyframes); i++)
base_style = gtk_css_animated_style_get_base_style (style);
parent_style = gtk_css_animated_style_get_parent_style (style);
provider = gtk_css_animated_style_get_provider (style);
resolved_keyframes = _gtk_css_keyframes_compute (animation->keyframes,
provider,
base_style,
parent_style);
for (i = 0; i < _gtk_css_keyframes_get_n_variables (resolved_keyframes); i++)
{
GtkCssVariableValue *value;
int variable_id;
variable_id = _gtk_css_keyframes_get_variable_id (resolved_keyframes, i);
value = _gtk_css_keyframes_get_variable (resolved_keyframes,
i,
progress,
gtk_css_animated_style_get_intrinsic_custom_value (style, variable_id));
gtk_css_animated_style_set_animated_custom_value (style, variable_id, value);
}
for (i = 0; i < _gtk_css_keyframes_get_n_properties (resolved_keyframes); i++)
{
GtkCssValue *value;
guint property_id;
property_id = _gtk_css_keyframes_get_property_id (animation->keyframes, i);
property_id = _gtk_css_keyframes_get_property_id (resolved_keyframes, i);
value = _gtk_css_keyframes_get_value (animation->keyframes,
value = _gtk_css_keyframes_get_value (resolved_keyframes,
i,
progress,
gtk_css_animated_style_get_intrinsic_value (style, property_id));
gtk_css_animated_style_set_animated_value (style, property_id, value);
}
_gtk_css_keyframes_unref (resolved_keyframes);
}
static gboolean

View File

@@ -41,11 +41,12 @@ gtk_css_value_array_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_array_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_array_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *result;
GtkCssValue *i_value;
@@ -54,7 +55,7 @@ gtk_css_value_array_compute (GtkCssValue *value,
result = NULL;
for (i = 0; i < value->n_values; i++)
{
i_value = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style);
i_value = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style, variables);
if (result == NULL &&
i_value != value->values[i])
@@ -342,6 +343,20 @@ gtk_css_value_array_get_dynamic_value (GtkCssValue *value,
return result;
}
static gboolean
gtk_css_value_array_contains_variables (const GtkCssValue *value)
{
guint i;
for (i = 0; i < value->n_values; i++)
{
if (gtk_css_value_contains_variables (value->values[i]))
return TRUE;
}
return FALSE;
}
static void
gtk_css_value_array_print (const GtkCssValue *value,
GString *string)
@@ -370,6 +385,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_ARRAY = {
gtk_css_value_array_transition,
gtk_css_value_array_is_dynamic,
gtk_css_value_array_get_dynamic_value,
gtk_css_value_array_contains_variables,
gtk_css_value_array_print
};

View File

@@ -41,11 +41,12 @@ gtk_css_value_bg_size_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_bg_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_bg_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *x, *y;
@@ -55,10 +56,10 @@ gtk_css_value_bg_size_compute (GtkCssValue *value,
x = y = NULL;
if (value->x)
x = _gtk_css_value_compute (value->x, property_id, provider, style, parent_style);
x = _gtk_css_value_compute (value->x, property_id, provider, style, parent_style, variables);
if (value->y)
y = _gtk_css_value_compute (value->y, property_id, provider, style, parent_style);
y = _gtk_css_value_compute (value->y, property_id, provider, style, parent_style, variables);
if (x == value->x && y == value->y)
{
@@ -160,6 +161,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_BG_SIZE = {
gtk_css_value_bg_size_transition,
NULL,
NULL,
NULL,
gtk_css_value_bg_size_print
};

View File

@@ -42,11 +42,12 @@ gtk_css_value_border_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_border_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_border_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *values[4];
GtkCssValue *computed;
@@ -57,7 +58,7 @@ gtk_css_value_border_compute (GtkCssValue *value,
{
if (value->values[i])
{
values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style);
values[i] = _gtk_css_value_compute (value->values[i], property_id, provider, style, parent_style, variables);
changed |= (values[i] != value->values[i]);
}
else
@@ -147,6 +148,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_BORDER = {
gtk_css_value_border_transition,
NULL,
NULL,
NULL,
gtk_css_value_border_print
};

View File

@@ -94,10 +94,11 @@ gtk_css_value_color_free (GtkCssValue *color)
}
static GtkCssValue *
gtk_css_value_color_get_fallback (guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_color_get_fallback (guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
switch (property_id)
{
@@ -120,7 +121,8 @@ gtk_css_value_color_get_fallback (guint property_id,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
case GTK_CSS_PROPERTY_ICON_PALETTE:
return _gtk_css_value_ref (style->core->color);
default:
@@ -132,11 +134,12 @@ gtk_css_value_color_get_fallback (guint property_id,
}
static GtkCssValue *
gtk_css_value_color_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_color_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *resolved;
@@ -173,7 +176,7 @@ gtk_css_value_color_compute (GtkCssValue *value,
}
if (resolved == NULL)
return gtk_css_value_color_get_fallback (property_id, provider, style, parent_style);
return gtk_css_value_color_get_fallback (property_id, provider, style, parent_style, variables);
return resolved;
}
@@ -293,6 +296,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_COLOR = {
gtk_css_value_color_transition,
NULL,
NULL,
NULL,
gtk_css_value_color_print
};

View File

@@ -37,16 +37,17 @@ gtk_css_value_corner_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_corner_compute (GtkCssValue *corner,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_corner_compute (GtkCssValue *corner,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *x, *y;
x = _gtk_css_value_compute (corner->x, property_id, provider, style, parent_style);
y = _gtk_css_value_compute (corner->y, property_id, provider, style, parent_style);
x = _gtk_css_value_compute (corner->x, property_id, provider, style, parent_style, variables);
y = _gtk_css_value_compute (corner->y, property_id, provider, style, parent_style, variables);
if (x == corner->x && y == corner->y)
{
_gtk_css_value_unref (x);
@@ -106,6 +107,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_CORNER = {
gtk_css_value_corner_transition,
NULL,
NULL,
NULL,
gtk_css_value_corner_print
};

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#include "gtkcsscustompropertypoolprivate.h"
struct _GtkCssCustomPropertyPool
{
GObject parent_instance;
GArray *names;
GHashTable *name_mappings;
};
struct _GtkCssCustomPropertyName
{
int ref_count;
char *name;
};
typedef struct _GtkCssCustomPropertyName GtkCssCustomPropertyName;
static GtkCssCustomPropertyPool *instance = NULL;
G_DEFINE_FINAL_TYPE (GtkCssCustomPropertyPool, gtk_css_custom_property_pool, G_TYPE_OBJECT)
static void
clear_custom_property_name (GtkCssCustomPropertyName *name)
{
g_clear_pointer (&name->name, g_free);
}
static void
gtk_css_custom_property_pool_finalize (GObject *object)
{
GtkCssCustomPropertyPool *self = (GtkCssCustomPropertyPool *)object;
g_hash_table_unref (self->name_mappings);
g_array_unref (self->names);
G_OBJECT_CLASS (gtk_css_custom_property_pool_parent_class)->finalize (object);
}
static void
gtk_css_custom_property_pool_class_init (GtkCssCustomPropertyPoolClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_css_custom_property_pool_finalize;
}
static void
gtk_css_custom_property_pool_init (GtkCssCustomPropertyPool *self)
{
self->name_mappings = g_hash_table_new (g_str_hash, g_str_equal);
self->names = g_array_new (FALSE, FALSE, sizeof (GtkCssCustomPropertyName));
g_array_set_clear_func (self->names, (GDestroyNotify) clear_custom_property_name);
}
GtkCssCustomPropertyPool *
gtk_css_custom_property_pool_get (void)
{
if (instance == NULL)
instance = g_object_new (GTK_TYPE_CSS_CUSTOM_PROPERTY_POOL, NULL);
return instance;
}
int
gtk_css_custom_property_pool_add (GtkCssCustomPropertyPool *self,
const char *str)
{
GtkCssCustomPropertyName name;
int id;
id = gtk_css_custom_property_pool_lookup (self, str);
if (id > 0)
return gtk_css_custom_property_pool_ref (self, id);
name.ref_count = 1;
name.name = g_strdup (str);
// TODO reuse slots after they're gone
g_array_append_val (self->names, name);
id = self->names->len;
g_hash_table_insert (self->name_mappings, (char *) name.name, GINT_TO_POINTER (id));
return id;
}
int
gtk_css_custom_property_pool_lookup (GtkCssCustomPropertyPool *self,
const char *str)
{
gpointer id;
id = g_hash_table_lookup (self->name_mappings, str);
return GPOINTER_TO_INT (id);
}
int
gtk_css_custom_property_pool_ref (GtkCssCustomPropertyPool *self,
int id)
{
GtkCssCustomPropertyName *name;
name = &g_array_index (self->names, GtkCssCustomPropertyName, id - 1);
name->ref_count++;
return id;
}
void
gtk_css_custom_property_pool_unref (GtkCssCustomPropertyPool *self,
int id)
{
GtkCssCustomPropertyName *name;
name = &g_array_index (self->names, GtkCssCustomPropertyName, id - 1);
g_assert (name->ref_count > 0);
name->ref_count--;
if (name->ref_count == 0)
{
g_hash_table_remove (self->name_mappings, name->name);
clear_custom_property_name (name);
}
}
const char *
gtk_css_custom_property_pool_get_name (GtkCssCustomPropertyPool *self,
int id)
{
GtkCssCustomPropertyName *name;
name = &g_array_index (self->names, GtkCssCustomPropertyName, id - 1);
return name->name;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2023 GNOME Foundation Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Alice Mikhaylenko <alicem@gnome.org>
*/
#pragma once
#include <glib-object.h>
G_BEGIN_DECLS
#define GTK_TYPE_CSS_CUSTOM_PROPERTY_POOL (gtk_css_custom_property_pool_get_type())
G_DECLARE_FINAL_TYPE (GtkCssCustomPropertyPool, gtk_css_custom_property_pool, GTK, CSS_CUSTOM_PROPERTY_POOL, GObject)
GtkCssCustomPropertyPool *gtk_css_custom_property_pool_get (void);
int gtk_css_custom_property_pool_add (GtkCssCustomPropertyPool *self,
const char *str);
int gtk_css_custom_property_pool_lookup (GtkCssCustomPropertyPool *self,
const char *str);
const char * gtk_css_custom_property_pool_get_name (GtkCssCustomPropertyPool *self,
int id);
int gtk_css_custom_property_pool_ref (GtkCssCustomPropertyPool *self,
int id);
void gtk_css_custom_property_pool_unref (GtkCssCustomPropertyPool *self,
int id);
G_END_DECLS

View File

@@ -50,11 +50,12 @@ gtk_css_value_ease_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_ease_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_ease_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (value);
}
@@ -142,6 +143,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_EASE = {
gtk_css_value_ease_transition,
NULL,
NULL,
NULL,
gtk_css_value_ease_print
};

View File

@@ -41,11 +41,12 @@ gtk_css_value_enum_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_enum_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_enum_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (value);
}
@@ -83,6 +84,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -141,6 +143,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_BLEND_MODE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -229,11 +232,12 @@ gtk_css_font_size_get_default_px (GtkStyleProvider *provider,
}
static GtkCssValue *
gtk_css_value_font_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_size_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
double font_size;
@@ -292,6 +296,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_SIZE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -349,6 +354,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -396,11 +402,12 @@ _gtk_css_font_style_value_get (const GtkCssValue *value)
#define LIGHTER -2
static GtkCssValue *
gtk_css_value_font_weight_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_weight_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
PangoWeight new_weight;
int parent_value;
@@ -448,6 +455,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
NULL,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -498,6 +506,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_STRETCH = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -555,6 +564,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_STYLE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -606,6 +616,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -663,6 +674,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_DIRECTION = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -724,6 +736,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_PLAY_STATE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -780,6 +793,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FILL_MODE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -838,6 +852,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_ICON_STYLE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -895,6 +910,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_KERNING = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -952,6 +968,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_POSITION = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -1009,6 +1026,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_CAPS = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -1070,6 +1088,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_ALTERNATE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};
@@ -1178,6 +1197,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_TEXT_DECORATION_LINE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_text_decoration_line_value_print
};
@@ -1277,6 +1297,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_LIGATURE = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_font_variant_ligature_value_print
};
@@ -1385,6 +1406,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_NUMERIC = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_font_variant_numeric_value_print
};
@@ -1490,6 +1512,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_font_variant_east_asian_value_print
};
@@ -1579,6 +1602,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_TEXT_TRANSFORM = {
gtk_css_value_enum_transition,
NULL,
NULL,
NULL,
gtk_css_value_enum_print
};

View File

@@ -307,55 +307,56 @@ gtk_css_value_filter_free (GtkCssValue *value)
/* returns TRUE if dest == src */
static gboolean
gtk_css_filter_compute (GtkCssFilter *dest,
GtkCssFilter *src,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_filter_compute (GtkCssFilter *dest,
GtkCssFilter *src,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
dest->type = src->type;
switch (src->type)
{
case GTK_CSS_FILTER_BRIGHTNESS:
dest->brightness.value = _gtk_css_value_compute (src->brightness.value, property_id, provider, style, parent_style);
dest->brightness.value = _gtk_css_value_compute (src->brightness.value, property_id, provider, style, parent_style, variables);
return dest->brightness.value == src->brightness.value;
case GTK_CSS_FILTER_CONTRAST:
dest->contrast.value = _gtk_css_value_compute (src->contrast.value, property_id, provider, style, parent_style);
dest->contrast.value = _gtk_css_value_compute (src->contrast.value, property_id, provider, style, parent_style, variables);
return dest->contrast.value == src->contrast.value;
case GTK_CSS_FILTER_GRAYSCALE:
dest->grayscale.value = _gtk_css_value_compute (src->grayscale.value, property_id, provider, style, parent_style);
dest->grayscale.value = _gtk_css_value_compute (src->grayscale.value, property_id, provider, style, parent_style, variables);
return dest->grayscale.value == src->grayscale.value;
case GTK_CSS_FILTER_HUE_ROTATE:
dest->hue_rotate.value = _gtk_css_value_compute (src->hue_rotate.value, property_id, provider, style, parent_style);
dest->hue_rotate.value = _gtk_css_value_compute (src->hue_rotate.value, property_id, provider, style, parent_style, variables);
return dest->hue_rotate.value == src->hue_rotate.value;
case GTK_CSS_FILTER_INVERT:
dest->invert.value = _gtk_css_value_compute (src->invert.value, property_id, provider, style, parent_style);
dest->invert.value = _gtk_css_value_compute (src->invert.value, property_id, provider, style, parent_style, variables);
return dest->invert.value == src->invert.value;
case GTK_CSS_FILTER_OPACITY:
dest->opacity.value = _gtk_css_value_compute (src->opacity.value, property_id, provider, style, parent_style);
dest->opacity.value = _gtk_css_value_compute (src->opacity.value, property_id, provider, style, parent_style, variables);
return dest->opacity.value == src->opacity.value;
case GTK_CSS_FILTER_SATURATE:
dest->saturate.value = _gtk_css_value_compute (src->saturate.value, property_id, provider, style, parent_style);
dest->saturate.value = _gtk_css_value_compute (src->saturate.value, property_id, provider, style, parent_style, variables);
return dest->saturate.value == src->saturate.value;
case GTK_CSS_FILTER_SEPIA:
dest->sepia.value = _gtk_css_value_compute (src->sepia.value, property_id, provider, style, parent_style);
dest->sepia.value = _gtk_css_value_compute (src->sepia.value, property_id, provider, style, parent_style, variables);
return dest->sepia.value == src->sepia.value;
case GTK_CSS_FILTER_BLUR:
dest->blur.value = _gtk_css_value_compute (src->blur.value, property_id, provider, style, parent_style);
dest->blur.value = _gtk_css_value_compute (src->blur.value, property_id, provider, style, parent_style, variables);
return dest->blur.value == src->blur.value;
case GTK_CSS_FILTER_DROP_SHADOW:
dest->drop_shadow.value = _gtk_css_value_compute (src->drop_shadow.value, property_id, provider, style, parent_style);
dest->drop_shadow.value = _gtk_css_value_compute (src->drop_shadow.value, property_id, provider, style, parent_style, variables);
return dest->drop_shadow.value == src->drop_shadow.value;
case GTK_CSS_FILTER_NONE:
@@ -366,11 +367,12 @@ gtk_css_filter_compute (GtkCssFilter *dest,
}
static GtkCssValue *
gtk_css_value_filter_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_filter_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssValue *result;
gboolean changes;
@@ -390,7 +392,8 @@ gtk_css_value_filter_compute (GtkCssValue *value,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
}
if (!changes)
@@ -720,6 +723,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FILTER = {
gtk_css_value_filter_transition,
NULL,
NULL,
NULL,
gtk_css_value_filter_print
};

View File

@@ -53,11 +53,12 @@ gtk_css_value_font_features_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_font_features_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_features_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (specified);
}
@@ -162,6 +163,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_FEATURES = {
gtk_css_value_font_features_transition,
NULL,
NULL,
NULL,
gtk_css_value_font_features_print
};

View File

@@ -52,11 +52,12 @@ gtk_css_value_font_variations_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_font_variations_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_font_variations_compute (GtkCssValue *specified,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return _gtk_css_value_ref (specified);
}
@@ -163,6 +164,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIATIONS = {
gtk_css_value_font_variations_transition,
NULL,
NULL,
NULL,
gtk_css_value_font_variations_print
};

View File

@@ -65,11 +65,12 @@ gtk_css_image_real_get_aspect_ratio (GtkCssImage *image)
}
static GtkCssImage *
gtk_css_image_real_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_real_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return g_object_ref (image);
}
@@ -173,11 +174,12 @@ _gtk_css_image_get_aspect_ratio (GtkCssImage *image)
}
GtkCssImage *
_gtk_css_image_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
_gtk_css_image_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageClass *klass;
@@ -187,7 +189,7 @@ _gtk_css_image_compute (GtkCssImage *image,
klass = GTK_CSS_IMAGE_GET_CLASS (image);
return klass->compute (image, property_id, provider, style, parent_style);
return klass->compute (image, property_id, provider, style, parent_style, variables);
}
GtkCssImage *

View File

@@ -313,11 +313,12 @@ gtk_css_image_conic_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_conic_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_conic_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageConic *self = GTK_CSS_IMAGE_CONIC (image);
GtkCssImageConic *copy;
@@ -325,8 +326,8 @@ gtk_css_image_conic_compute (GtkCssImage *image,
copy = g_object_new (GTK_TYPE_CSS_IMAGE_CONIC, NULL);
copy->center = _gtk_css_value_compute (self->center, property_id, provider, style, parent_style);
copy->rotation = _gtk_css_value_compute (self->rotation, property_id, provider, style, parent_style);
copy->center = _gtk_css_value_compute (self->center, property_id, provider, style, parent_style, variables);
copy->rotation = _gtk_css_value_compute (self->rotation, property_id, provider, style, parent_style, variables);
copy->n_stops = self->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageConicColorStop) * copy->n_stops);
@@ -335,11 +336,11 @@ gtk_css_image_conic_compute (GtkCssImage *image,
const GtkCssImageConicColorStop *stop = &self->color_stops[i];
GtkCssImageConicColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style, variables);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style, variables);
}
else
{

View File

@@ -399,11 +399,12 @@ gtk_css_image_cross_fade_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_cross_fade_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_cross_fade_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
GtkCssImageCrossFade *result;
@@ -418,7 +419,7 @@ gtk_css_image_cross_fade_compute (GtkCssImage *image,
gtk_css_image_cross_fade_add (result,
entry->has_progress,
entry->progress,
_gtk_css_image_compute (entry->image, property_id, provider, style, parent_style));
_gtk_css_image_compute (entry->image, property_id, provider, style, parent_style, variables));
}
return GTK_CSS_IMAGE (result);

View File

@@ -133,11 +133,12 @@ gtk_css_image_fallback_dispose (GObject *object)
static GtkCssImage *
gtk_css_image_fallback_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_fallback_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageFallback *fallback = GTK_CSS_IMAGE_FALLBACK (image);
GtkCssImageFallback *copy;
@@ -152,7 +153,8 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
/* image($color) that didn't change */
if (computed_color && !fallback->images &&
@@ -168,7 +170,8 @@ gtk_css_image_fallback_compute (GtkCssImage *image,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
if (gtk_css_image_is_invalid (copy->images[i]))
continue;

View File

@@ -138,11 +138,12 @@ gtk_css_image_icon_theme_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_icon_theme_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_icon_theme_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageIconTheme *icon_theme = GTK_CSS_IMAGE_ICON_THEME (image);
GtkCssImageIconTheme *copy;

View File

@@ -488,11 +488,12 @@ gtk_css_image_linear_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_linear_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_linear_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
GtkCssImageLinear *copy;
@@ -503,7 +504,7 @@ gtk_css_image_linear_compute (GtkCssImage *image,
copy->side = linear->side;
if (linear->angle)
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, style, parent_style);
copy->angle = _gtk_css_value_compute (linear->angle, property_id, provider, style, parent_style, variables);
copy->n_stops = linear->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageLinearColorStop) * copy->n_stops);
@@ -512,11 +513,11 @@ gtk_css_image_linear_compute (GtkCssImage *image,
const GtkCssImageLinearColorStop *stop = &linear->color_stops[i];
GtkCssImageLinearColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style, variables);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style, variables);
}
else
{

View File

@@ -96,11 +96,12 @@ gtk_css_image_paintable_get_static_image (GtkCssImage *image)
}
static GtkCssImage *
gtk_css_image_paintable_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_paintable_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
return gtk_css_image_paintable_get_static_image (image);
}

View File

@@ -26,6 +26,7 @@
#include "gtk/css/gtkcsstokenizerprivate.h"
#include "gtk/css/gtkcssparserprivate.h"
#include "gtk/gtkcsstypesprivate.h"
#include "gtk/gtkcssvariablesetprivate.h"
#include "gtk/gtksnapshot.h"
#include "gtk/gtkstyleprovider.h"
@@ -62,7 +63,8 @@ struct _GtkCssImageClass
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style);
GtkCssStyle *parent_style,
GtkCssVariableSet *variables);
/* compare two images for equality */
gboolean (* equal) (GtkCssImage *image1,
GtkCssImage *image2);
@@ -106,7 +108,8 @@ GtkCssImage * _gtk_css_image_compute (GtkCssImage *
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style);
GtkCssStyle *parent_style,
GtkCssVariableSet *variables);
gboolean _gtk_css_image_equal (GtkCssImage *image1,
GtkCssImage *image2) G_GNUC_PURE;
GtkCssImage * _gtk_css_image_transition (GtkCssImage *start,

View File

@@ -489,11 +489,12 @@ gtk_css_image_radial_print (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_radial_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_radial_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image);
GtkCssImageRadial *copy;
@@ -504,13 +505,13 @@ gtk_css_image_radial_compute (GtkCssImage *image,
copy->circle = radial->circle;
copy->size = radial->size;
copy->position = _gtk_css_value_compute (radial->position, property_id, provider, style, parent_style);
copy->position = _gtk_css_value_compute (radial->position, property_id, provider, style, parent_style, variables);
if (radial->sizes[0])
copy->sizes[0] = _gtk_css_value_compute (radial->sizes[0], property_id, provider, style, parent_style);
copy->sizes[0] = _gtk_css_value_compute (radial->sizes[0], property_id, provider, style, parent_style, variables);
if (radial->sizes[1])
copy->sizes[1] = _gtk_css_value_compute (radial->sizes[1], property_id, provider, style, parent_style);
copy->sizes[1] = _gtk_css_value_compute (radial->sizes[1], property_id, provider, style, parent_style, variables);
copy->n_stops = radial->n_stops;
copy->color_stops = g_malloc (sizeof (GtkCssImageRadialColorStop) * copy->n_stops);
@@ -519,11 +520,11 @@ gtk_css_image_radial_compute (GtkCssImage *image,
const GtkCssImageRadialColorStop *stop = &radial->color_stops[i];
GtkCssImageRadialColorStop *scopy = &copy->color_stops[i];
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style);
scopy->color = _gtk_css_value_compute (stop->color, property_id, provider, style, parent_style, variables);
if (stop->offset)
{
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style);
scopy->offset = _gtk_css_value_compute (stop->offset, property_id, provider, style, parent_style, variables);
}
else
{

View File

@@ -200,11 +200,12 @@ gtk_css_image_recolor_snapshot (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_recolor_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_recolor_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageRecolor *recolor = GTK_CSS_IMAGE_RECOLOR (image);
GtkCssValue *palette;
@@ -215,7 +216,7 @@ gtk_css_image_recolor_compute (GtkCssImage *image,
scale = gtk_style_provider_get_scale (provider);
if (recolor->palette)
palette = _gtk_css_value_compute (recolor->palette, property_id, provider, style, parent_style);
palette = _gtk_css_value_compute (recolor->palette, property_id, provider, style, parent_style, variables);
else
palette = _gtk_css_value_ref (style->core->icon_palette);

View File

@@ -97,11 +97,12 @@ gtk_css_image_scaled_dispose (GObject *object)
static GtkCssImage *
gtk_css_image_scaled_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_scaled_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageScaled *scaled = GTK_CSS_IMAGE_SCALED (image);
int scale;
@@ -137,7 +138,8 @@ gtk_css_image_scaled_compute (GtkCssImage *image,
property_id,
provider,
style,
parent_style);
parent_style,
variables);
res->scales[0] = scaled->scales[best];
return GTK_CSS_IMAGE (res);

View File

@@ -112,11 +112,12 @@ gtk_css_image_url_snapshot (GtkCssImage *image,
}
static GtkCssImage *
gtk_css_image_url_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_image_url_compute (GtkCssImage *image,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImageUrl *url = GTK_CSS_IMAGE_URL (image);
GtkCssImage *copy;

View File

@@ -34,11 +34,12 @@ gtk_css_value_image_free (GtkCssValue *value)
}
static GtkCssValue *
gtk_css_value_image_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style)
gtk_css_value_image_compute (GtkCssValue *value,
guint property_id,
GtkStyleProvider *provider,
GtkCssStyle *style,
GtkCssStyle *parent_style,
GtkCssVariableSet *variables)
{
GtkCssImage *image, *computed;
@@ -47,7 +48,7 @@ gtk_css_value_image_compute (GtkCssValue *value,
if (image == NULL)
return _gtk_css_value_ref (value);
computed = _gtk_css_image_compute (image, property_id, provider, style, parent_style);
computed = _gtk_css_image_compute (image, property_id, provider, style, parent_style, variables);
if (computed == image)
{
@@ -130,6 +131,7 @@ static const GtkCssValueClass GTK_CSS_VALUE_IMAGE = {
gtk_css_value_image_transition,
gtk_css_value_image_is_dynamic,
gtk_css_value_image_get_dynamic_value,
NULL,
gtk_css_value_image_print
};

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