Make the generator generate calls for the correct glBindAttribLocation()
calls.
Usually this was done correctly, but we can't rely on it. So do it
explicitly.
Add a testsuite called gsk-compare-vulkan to run
the gsk renderer tests with the Vulkan renderer and
gsk-compare-ngl to run them with the NGL renderer.
To run the tests locally, you can do:
meson test -C_build --suite gsk-compare-vulkan
When downscaling more than 2x in either dimension, force mipmap use for
the texture in a texture node.
It improves the quality of textures but takes extra work.
The GL renderer does this, too (for textures that aren't in the icon cache).
This can be disabled via GSK_GPU_SKIP=mipmap.
Fixes the big-checkerboard-scaled-down2 test.
Unless GSK_GPU_SKIP=gradients is given, we sample every point 4x instead
of 1x. That makes the shader run slower (by roughly a factor of 2.5x)
but it improves quality quite a bit.
I'm a bit unsure about using the zero rect in the fallback situtation
where one image doesn't exist, but it seems to work.
This removes the last pattern-only rendernode and with that the last
fallback usage with disabled ubershader.
This way we can toggle opacity handling on/off.
THe shader slowly turns into a fancy texture op - but I don't want to
rename it to "fancytexture" just yet.
A variation is a #define/specialization constant that every shader can
use to specialize itself as it sees fit.
This commit adds the infrastrcture, future commits will add
implementations.
gdk_texture_save_to_png_bytes() cannot fail, so ensure that it doesn't.
Testsuite has been updated to check for this case.
Note that we do not load the PNG file that we generate here.
Loading is a lot more scary than saving after all.
If people want to load oversized PNG files, they should use a real PNG
loader.
If we enter the situation where we need to redirect the clipping to an
offscreen, make sure that:
* the ubershader gets only used when beneficial
* we size the offscreen properly and don't let it grow infinitely.
Fixes the clip-intersection-fail-opacity test
There are various places where the alpha is implicitly assumed to be
handled, so just handle it.
As a bonus, this simplifies a bunch of code and makes the texture node
rendering work with alpha.
Use an offscreen and mask it if the clips get too complicated.
Technically, the code could be improved to set the rounded clip on the
offscreen instead of rendering it as a mask, but that would require more
sophisticated tracking of clip regions by respecting the scissor, and
the current clip handling can't do that yet.
This removes one of the last places where the GPU renderer was still
using Cairo fallbacks.
This is for generating descriptors for more than 1 image. The arguments
for this function are very awkward, but I couldn't come up with better
ones and the function isn't that important.
And the calling places still look a lot nicer now.
For now this uses Cairo to generate a mask and then runs a mask op.
This is different from just using fallback in that the child is rendered
with the GPU and not via fallback.
A generic part that can be shared by all gradient shaders that does the
color stop handling and a gradient-specific part that needs to be
implemented individually by each gradient implementation.
If there are more than 7 color stops, we can split the gradient into
multiple gradients with color stops like so:
0, 1, 2, 3, 4, 5, transparent
transparent, 6, 7, 8, 9, 10, transparent
...
transparent, n-2, n-1, n
and use the new BLEND_ADD to draw them on top of each other.
Adapt the testcae that tests this to use colors that work with the fancy
algorithm we use now, so that BLEND_ADD and transitions to transparent
do not cause issues.
Instead of scaled coordinates, use the unscaled ones.
This ensure that gradients get computed correctly as they are not safe
against nonorthogonal transforms - like scales with different scale
factors.
The shader can only deal with up to 7 color stops - but that's good
enough for the real world.
Plus, we have the uber shader.
And if that fails, we can still fall back to Cairo.
The code also doesn't handle repeating linear gradients yet.
This shader can take over from the ubershader. And it can be used
instead of launching the ubershader when no offscreens are necessary.
Also includes an optimization that uses the colorize shader when
appropriate.
The ubershader has some corner cases where it can't be used, in
particular when the child is massively larger than the repeat node and
the repeat node is used to clip lots of the source.
It's better than the Cairo renderer, so use it instead.
It's still only picked once GL fails, so it will probably only ever be
picked when people use GDK_DEBUG=gl-disable, but at least it will be
picked.
per-backend renderers and GL renderers are a different thing, so treat
them as such.
Also, try the GL renderer unconditionally. The renderer initialization
code will take care of GL not being available.
This is using the Vulkan renderer.
It also allows claiming support for all the formats that only Vulkan
supports, but that neither GL nor native mmap can handle.
Add GSK_GPU_IMAGE_RENDERABLE and GSK_GPU_IMAGE_FILTERABLE and make sure
to check formats for this feature.
This requires reorganizing code to actually do this work instead of just
pretending formats are supported.
This fixes GLES upload tests with NGL.
I did it because it unifies the code.
But it also gains the benefit of being debuggable because it can
now be turned off via GDK_VULKAN_SKIP=incremental-present
This ensures both that we signal a semaphore for a dmabuf when we export
an image and that we import semaphores for dmabufs and wait on them.
Fixes Vulkan node-editor displaying the Vulkan renderer in the sidebar.
Make gsk_renderer_render_texture() create a dmabuf texture if that is
possible.
If it isn't (ie if we're not on Linux or if dmabufs are otherwise not
working) fall back to the previous code of creating a memory texture.
When using the uber shader a lot, we may overflow the (only 16kB large)
storage buffer.
Stop crashing when that happens and instead just allocate a new one.
This makes the (currently single) storage buffer handled by
GskGpuDescriptors.
A side effect is that we now have support for multiple buffers in place.
We just have to use it.
Mixed into this commit is a complete rework of the pattern writer.
Instead of writing straight into the buffer (complete with repeatedly
backtracking when we have to do offscreens), write into a temporary
buffer and copy into the storage buffer on committing.
The GL branch should eventually call into gdk_gl_context_get_scale(),
which is what checks for GDK_DEBUG=gl-fractional; whereas the Vulkan
branch needs no change.
If we have the choice between running the ubershader or a normal shader
with offscreens, make the choice depend on if the ubershader would
offscreen anyway.
If so, just run the normal shader.
This really gets rid of all ubershader invocations in Adwaita
widget-factory.
Instead of using an enum, use a usual custom class struct like we use
for GskGpuOp.
As a side effect of that refactoring, the display gained a hash table
for textures where we can't use the render data because the texture is
used in multiple renderers.
The goal here is that a texture is always cached and we can ensure that
there is a 1:1 relation between textures and their GskGpuImage. This is
important in particular for external textures - like dmabufs - where we
absolutely don't want 2 images with 2 device memories, and where we use
toggle references to keep them alive.
Reserve 3 texture units per immutable sampler (because that's the
maximum per YUV sampler).
Ensure that the max-sampler calculations always include the immutable
samplers, too.
We now handle the case where memory is not HOST_CACHED.
We also track the memory type now so we can avoid mapping image memory
that is not HOST_CACHED and use buffer transfers instead.
Shader compilers struggle with compiling code that indexes texture
arrays by indexes, so keep the fallback shaders simple and don't do that
there.
There's not much of a performance difference anyway between those two
methods.
In the case where descriptor indexing is not enabled and the number of
max images is small (or we use extensive amounts of immutable samplers),
we need to be able to switch descriptors.
This patch makes that possible.
We compile custom shaders for Vulkan 1.0 that don't require the
extension.
We also ensure that our accesses are uniform by only executing one
shader at a time.
Let the objects track the number of samplers or buffers needed.
This is a required step for making Vulkan work with less featureful
(read: mobile) implementations.
This is relevant went encountering repeat nodes, where the repeat cutoff
will make the fwidth of the position go wild otherwise.
Gradients require more work now, because we need to compute offsets
twice - once for the pixel, once for the offst.
Carry an n_external_textures variable around when selecting programs and
compile different programs for different amounts of external textures.
For now, this code is unused, but dmabufs will need it.
This adds GSK_GPU_IMAGE_CAN_MIPMAP and GSK_GPU_IMAGE_MIPMAP flags and
support to ensure_image() and image creation functions for creating a
mipmapped image.
Mipmaps are created using the new mipmap op that uses
glGenerateMipmap() on GL and equivalent blit ops on Vulkan.
This is then used to ensure the image is mipmapped when rendering it
with a texture-scale node.
Add a GSK_GPU_IMAGE_STRAIGHT_ALPHA and use it for images that have
straight alpha.
Make sure those images get passed through a premultiplying pass with
the new straight alpha shader.
Also remove the old Postprocess flags from the Vulkan image that were a
leftover from copying that code from the old Vulkan renderer.
There's a well hidden line in the spec that says in
https://registry.khronos.org/vulkan/specs/1.3/html/chap15.html#interfaces-resources-descset
If the combined image sampler enables sampler Y′CBCR conversion,
it **must** be indexed only by constant integral expressions when
aggregated into arrays in shader code, irrespective of the
shaderSampledImageArrayDynamicIndexing feature.
So we'll use the same trick that we use for old GL here and do an
if dance that gives us dynamically uniform expressions.
This now uses all the previously added features to allow displaying YUV
images.
Also add a utility function that turns an image into a toggle ref for a
texture. This makes sure that reffing the image also refs the texture
and that ensures that textures stay alive as long as the image is in
use.
This code does not add a downloader, so we do not claim support for all
the new formats.
It just queries the formats. But this can be used to import dmabufs
directly into the Vulkaan renderer.
For now, the flags are just there because, and nobody uses them yet.
The only flag is EXTERNAL, which for now I'm using for YUV buffers,
though it's a bit undefined what that means.
Images can now have samplers - meaning they must be rendered with that
sampler. It also means that sampler must be handled as an immutable
sampler in descriptorsets.
These samplers can be created with a samplerYcbcrConversion, so code has
been added to pass that conversion when creating the imageview.
Also add code to GskVulkanFrame to track immutable samplers.
Nobody is making use of this yet.
Define an array with a compile-time-constant variable size for the
immutable samplers.
A bunch of work is necessary to ensure that at least one element is in
the sampler array, because the GLSL code
sampler2D immutable_textures[0];
is invalid.
This allows having different layouts sothat we can support immutable
samplers, whcih are required for multiplane and YUV formats.
We don't use them yet.
use it to collect the optional features we are interested in and turn
them on only if available.
For now we add the dmabuf features, but we don't use them yet.
The main reason here is that we want to not fail when the texture size
is larger than the supported GpuImage size.
When that happens, for now we just fallback slowly - ulitmately to
drawing with Cairo, which is going to be clipped.
There's multiple uses I want it for:
1. Generating the box-shadow area for blurring
2. Generating masks for rounded-rect masking
3. Optimizing the common use case of rounded-clip + color
Only the last one is implemented in this commit.
Don't try to use all those fancy GL features like glMapBuffer() and
such. Just malloc() some buffer memory and glBufferSubData() it later.
That works everywhere and is faster than (almost?) any combination of
fancy new buffer APIs. And yes I'm frustrated because I played with
those flags and none of them were better than this.
Doubles the framerate on my discrete AMD GPU.
Introduce a new GskGpuImageDescriptors object that tracks descriptors
for a set of images that can be managed by the GPU.
Then have each GskGpuShaderOp just reference the descriptors object they are
using, so that the coe can set things up properly.
To reference an image, the ops now just reference their descriptor -
which is the uint32 we've been sending to the shaders since forever.
Use glDrawArraysInstancedBaseInstance() to draw. (Yay for GL naming.)
That allows setting up the offset in the vertex array without having to
glVertexAttribPointer() everything again.
However, this is only supported since GL 4.2 and not at all in stock GLES,
so we need to have code that can work without it.
Fortunately, it is mandatory in Vulkan, so every recent GPU supports it.
And if that GPU has a proper driver, it will also expose the GL extension
for it.
(Hint: You can check https://opengles.gpuinfo.org/listextensions.php for
how many proper drivers exist outside of Mesa.)
The env var allows skipping various optimizations in the GPU shader.
This is useful for testing during development when trying to figure
out how to make a renderer as fast as possible.
We could also use it to enable/disable optimizations depending on GL
version or so, but I didn't think about that too much yet.
When drawing opaque color regions that are large enough, use
vkCmdClearAttachments()/glClear() instead of a shader. This speeds up
background rendering on particular on older GPUs.
See the commit messages of
bb2cd7225ece042f7ba10edd7547c1
for a further discussion of performance impacts.
The previous algorithm would reverse the order of subpasses, whcih leads
to unexpected behavior if dependent subpasses are not added as children
of a subpass, but just as a previous subpass - like when a subpass is
used multiple times later.
An example for this is a shadow node with multiple shadows - the source
of the shadow is used by the multiple shadows.
So ensure that adjacent subpasses stay in the same order.
The code generated by glslc -O is optimized worse by Mesa than
code generated unoptimized.
So generate unoptimized code until somebody figures out what's going
wrong here.
They're done using the pattern shader.
The pattern shader now gained a stack where vec4's can be pushed and
popped back later, which allows storing the position before computing
the new position inside the repeat node's child.
Due to GLES and old GL not allowing non-constant texture array
lookups,we need to turn the array lookup into a big switch statementin
those versions, and that requires putting the texture() call into that
switch.
But with that trick, we can use texture IDs in GLSL.
... and use it for glyphs.
The name is a slight variation of the "coloring" name from the GL
renderer.
The functionality is exactly what the "glyph" shader from the Vulkan
renderer does.
1. Compute the fwidth() twice with offset offsets
That way, we avoid glitches at the boundary between 0.0 and 1.0,
because by offsetting it by 0.5, that boundary goes away.
Then we take the min() of both which gives us the one we care about.
2. Set the gradient to repeating
By doing that, we don't get values at the 0.0/1.0 boundary clamped,
but things smoothly transition.
This smoothes the line at that boundary and makes it look just like
every other line.
Instead of strictly rounding to the given clip rectangle, increase the
rectangle to the next pixel boundary.
Also add docs that the clip_bounds do not influence the actual size of
the returned image.
It's just an object that encapsulates everything needed to create (the
data for) a pattern op.
It also clarifies which code does what, because now the NodeProcessor
and the PatternWriter are 2 different things.
Pretty much a copy of the Vulkan border shader.
A notable change is that the input arguments are changed, because GL
gets confused if you put a mat4 at the end.
when doing get_node_as_image(), that may spawn a new buffer writer that
writes into the samme buffer when rendering an offscreen with patterns.
So as a more or less hacky workaround, we now abort the current buffer
write and restart it once we've created the image.
If creation fails, create an offscreen image instead and draw that as a
texture.
Because offscreens basically always succeed, we can pretty much assume
success everywhere - apart from pattern creation functions that also
create images, because they can run out of shader space.
Frames now carry a timestamp for when they are used.
This is mainly intended to attach timestamps to cached items (textures
or glyphs), but it could in theory also be used when profiling.
We use wallclock time here, not server time, because it's cheaper and
because we're more intereseted in the local machine we're rendering on.
Now we can extend the pattern creation easily - and we can add new
patterns quickly later.
Plus, we need to keep this file in sync with pattern.glsl and it's neat
when those 2 files reference only each other.
Because GL flips its shit sometimes (ie when it's the framebuffer),
pass the height of the target as the flip variable, so commands
that need to operate on the pixels can flip the y axis around this value.
This is again mostly a copy of the Vulkan renderer.
It's a bit awkward codewise with the new invalidation framework,
because we need to cache the previous values individually now,
but it's a lot more finegrained, and we don't emit globals multiple
times when clips are nested.
... and use it to initialize the "proper" projection matrix to use in
shaders.
The resulting viewport will go from top left (0,0) to bottom right
(width, height) and the z clipping plane will go from -10000 to 10000.
This heaves over an inital chunk of code from the Vulkan renderer to
execute shaders.
The only shader that exists for now is a shader that draws a single
texture.
We use that to replace the blit op we were doing before.
For now, it just renders using cairo, uploads the result to the GPU,
blits it onto the framebuffer and then is happy.
But it can do that using Vulkan and using GL (no idea which version).
The most important thing still missing is shaders.
It also has a bunch of copy/paste from the Vulkan renderer that isn't
used yet.
But I didn't want to rip it out and then try to copy it back later
We want to introduce a new one next.
Technically, this breaks API, because gsk_vulkan_renderer_new() is going
away, but practically, we're gonna bring it back once we introduce that
renderer in a few commits.
We do extra work here to make the introspection scanner pick up
the docs for the static inline function, but that doesn't make the
function actually work in language bindings, so mark it as skip.
Fixes: #6298
According to EXT_color_buffer_half_float it should be renderable, but it
fails to glGenerateMipmap() with Mesa 23.3 so just pretend it's not
renderable until that is fixed.
Fixes CI from failing.
I naively assumed the EXT_color_buffer_float and
EXT_color_buffer_half_float extensions would mirror each other, but they
do not. The float extension explicitly excludes RGB32F from the
renderable formats.
These are not usable outside of GTK, so lets not burden bindings
with them.
I'll keep the get_child() function exposed, since it is needed to
iterate over node trees containing subsurface nodes.
asan randomly failed when this almost correct code wasn't quite correct.
Hopefully this is the correct incantation to compute the size.
Related: glib#205
The test ensures that offscreens render to the same pixel grid as the
actual image, and they are not offset by fractions of a pixel.
The Cairo renderer fails here because Cairo's clipping code rounds pixel
values wrong.
This is mostly untested and a result of reading the code.
The main effect here happens when a node was drawn that didn't start on
an integer boundary, which is very rare.
However, with specially crafted tests and when using fractional scaling,
this can happen.
This happened most often when clipping by the node bounds to restrict a
push_group() call. Enlarge that rectangle to fall on a pixel boundary.
Testcase included
The code was writing invalid memory, so this might not have always
crashed, but I did my best to write the test so it causes a SEGV.
Also included is a fix for the testsuite where the expected result was
wrong.
The replayed node/images weren't saved.
I wanted to check that an optimization is done when replaying a test,
but without a saved node file, I couldn't.
It is not material to this test, and it causes some hard to
understand problem with fontconfigs use of mmap, leading to
a sporadic segfaults in pangos fontconfig thread.
This test fails on my system currently, since rawhide libpng appears
to have changed the encoding of pngs so that the texture nodes no
longer match the reference. This will be a problem as long as our
ci systems have an older libpng, so disable this test for now.
Add a new activate signal that fires when enter is pressed after
editing, and make the default handler activate the default widget if
activates-default is set.
* Fix a bug where a zero increment would make the value unsettable,
when the more natural operation is to allow any value to be set.
* Factorise gtk_spin_button_snap into two parts (snapping + setting),
and make gtk_spin_button_snap only perform the snapping part.
* Avoid duplicate calls to gtk_adjustment_get_{lower/upper} and
reinvention of CLAMP macro.
These 2 rectangles used to intersect fine:
0 0 50 50 / 50 0
0 0 50 50 / 0 50
But the computed result was:
0 0 50 50 / 50
which is not a valid rectangle, because the corners overlap.
Make sure such rectangles return NOT_REPRESENTABLE.
The above rectangle has been added to the testsuite.
After discussion on IRC about debug messages:
- FALLBACK is meant to be used for printing stuff about fallbacks
(Cairo, offscreens, conversion when uploading, etc)
- CAIRO is for overdrawing everything drawn with Cairo
When hilighting Cairo nodes, use a different hilight color than when
hilighting other nodes.
This allows differentiating application use of Cairo (via nodes) from
renderer use of Cairo (via fallback).
Use it to overlay an error pattern over all Cairo drawing done by
renderers.
This has 2 purposes:
1. It allows detecting fallbacks in GPU renderers.
2. Application code can use it to detect where it is using Cairo
drawing.
As such, it is meant to trigger both with cairo nodes as well as when
renderers fallback for regular nodes.
The old use of the debug flag - which were 2 not very useful print
statements - was removed.
There are some tests that generate large images.
However, if we mask that image, we might have to generate offscreens
both for the source and for the mask.
And if we do that, it can take a long time. And especially on CI with
software rendering, that can quickly become noticable and result in
timeouts.
This test tests that shadows that are offset to outside the clip region
but where the blur goes back into the clip region get correctly drawn
and not optimized away.
To view what the test actually draws, remove at least the color-matrix
- it's only used so the blurring algorithm doesn't cause different
results - and maybe also the clip node.
The test existed in git but wasn't hooked up. So let's do that by:
1. Adding it to the build
2. Adapting it a bit so rounding errors really don't trigger (as the
original commit claimed they shouldn't).
3. Re-renaming it because this was actually about 3d gradients
The actual gradient line is covered by blocks, so there are no
artifacts. But if a renderer screws this up, the blue/red will seep
through these blocks.
When different scale factors are used to transform a diagonal
linear gradient, the angle between the gradient line and its
perpendicular is no longer a right angle, which makes the
gradient come out different.
So it is necessary to use transform nodes in that case so that the
correct gradient gets rendered.
Technically, the code could check if the scales are equal or the
gradient line is horizontal/vertical, but I don't think that's worth it.
Mask nodes are transparent outside of the intersection of source and
mask, unless the mask ode is inverted alpha.
Set the bounds accordingly.
Tests have been updated accordingly.
This test tests multiple things:
1. That huge contents are properly clipped by repeat nodes, even if the
repeat happens in the visible part
2. That repeating only horizontally or only vertically is done quickly
via offscreens when lots of repeating is done
Test that if the child is a texture that extends the child bounds, that
extension does not get repeated when rendering.
This can easily happen when the child is not drawn as an offscreen, but
instead the texture cache is consulted and no check for matching size is
done.
When we test repeat nodes, make sure we round the size of the original
node up to an integer.
The reference image for the node is a rounded up, so when we generate a
new reference image we cannot deal with anything else.
Fixes huge-width test with --repeat.
Instead of using "-3d" to exclude Cairo rendering, use "-no$renderer" to
allow excluding any renderer.
And because we use contains() for the check, we can exclude multiple
renderers by naming the test sth like "test-nogl-nocairo.node"
Sync the code in gtkwindow.c that generates focus change events
with the similar code in gtkmain.c that generates crossing events.
This fixes assertion failures that would trigger in nautilus when
opening a folder.
We don't want to set a misleading descendent in the case that
we don't have a shared ancestor at all (because the old and the
new targets are on different toplevels).
Doing this in a way that is picked up by gobject-introspection
requires splitting off new enum members into separate doc
comments, which is a bit unfortunate.
Some dmabuf formats were added in Vulkan 1.3.
Note that this does not require the Vulkan drivers to be version 1.3 -
it just means compilation against libvulkan 1.3
Right now, it's mentioned only in the class description of
GtkScrolledWindow that the accessors of the child property don't
necessarily roundtrip.
Let's make it more clear by expanding the documentation of the setter,
getter, and property.
See: #6275
The convert_texture() path only works for the GL renderer, the new
renderers potentially use dmabuf textures as result of render_texture(),
so they need to be smarter here.
This makes no sense by itself, but we want to create the EGLImage at
DmabufTexture construction so that we can actually reject dmabufs that
we can't create EGLImages for.
This will make it possible to bail when the stride limitation for AMD
GPUs hits.
Instead of having an add_formats() function, make the get_downloader()
function add the formats.
This allows putting the actual downloader in a different place from the
initialization code.
This is done without testing, just doing my best to map all the DRM
formats to VkFormats.
Once people start using them, they'll figure it out when it's wrong.
(Somebody needs to write a testsuite.)
When we use the builtin downloads via mmap(), it's a special case where
we don't need to initialize subsystems and query them for support. We
know what we can and can't do.
Also, we want to use these formats with the lowest priority but pick the
downloader first for supported formats, and queueing it in the
downloaders list doesn't reflect that. So don't do it.
This omission was noticed by Benjamin Otte. Add a premultiply
uniform to the external shader, and add a separate premultiply
shader for the non-external case.
When the GL renderer cannot upload a given format, print a FALLBACK
debug message with the failed format and the alternative that was
picked, for example:
Unsupported format b8g8r8a8, converting on CPU to b8g8r8a8-premultiplied
Makes it easier to figure out what's happening, especially when using
old GLES versions that don't support all formats.
Track fallback formats to use in the memoryformat directly instead of
using in the GL uploading code.
First of all, this allows sharing the code and ensuring all our
renderers use the same fallback mechanism.
But also, this allows tracking fallbacks per-format which is useful
because the fallback formats aren't really a tree. We want to make
FLOAT16 fall back to FLOAT32 when not available, but we also want
FLOAT32 fall back to FLOAT16.
By tracking the fallbacks per-format, we can achieve that.
Add gdk_memory_format_get_premultiplied() and
gdk_memory_format_get_straight() which return the matching
premultiplied/straight format.
Use this to pick the premultiplied format when uploading GL textures.
And remove the duplication in the dmabuf code, where we can now use
these functions instead of tracking both the premultiplied and straight
alpha versions.
Add an "RGBA" format that just maps to the swizzled version of the
default format.
This way, BGR gets mapped to RGB + swizzling first before trying to map
it to the default format for the depth.
The benefit here is that this format has the same memory width, so
uploading/downloading code can treat it equivalent to the original
format and there's no conversion neccessary later.
While not required by the GListModel interface, they are a useful
convention which is already implemented by other GListModel public
implementation in GTK, particularly for use in expressions and
bindings.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/6261
Now that we have gdk_gl_context_get_memory_flags() and code can use that
function, make the code do that.
Remove support checks from gdk_memory_format_gl_format().
This is an initial naive port that doesn't try to make use of the finer-grained
flags yet.
Checks which features of a given memory format are supported by
the current GL implementation.
We check:
* usable: Can be used as a texture with NEAREST filter
* renderable: Can be used as a render target
* filterable: Can be used with GL_LINEAR
In normal GL, all formats are all of these things, but GLES is a lot
more picky.
So far nobody uses this.
This is the result of experimenting with corner cases when blurring.
The result is a test that tests when the child of a blur node is
clipped out but the blurred child is not, the blurred parts are still
visible.
This immediately broke the cairo renderer, so the fix is included.
If a subsurface is not below, it is visible no matter what the opaque
region is.
Also, we don't need to care about transparency in the subsurface if we
ignore it anyway. So this is a win-win.
We accept transparent subsurfaces for passthrough now, when they are
above the surface.
But we did not unset the opaque region to empty when the texture is
transprent.
These are 2x2 combinations that:
1. Use a texture child node vs a color child node
This should force an offscreen vs straight up use a texture.
2. Switch opacity and color-matrix
Either put the color matrix into the opacity node or put the opacity
into the color matrix.
This is worth testing because renderers often combine opacity into the
color matrix to avoid offscreens.
And they do that because applications often create faded out symbolic
images, which end up as a combination of these nodes.
The public gtk_application_inhibit() API allows a NULL reason argument,
and we have a fallback in place when going through the session manager
proxy; when using the inhibit D-Bus API directly, though, we're just
passing a potentially NULL value to g_variant_new_string(), which will
rightfully complain.
Add new accessible roles
GTK_ACCESSIBLE_ROLE_ARTICLE and
GTK_ACCESSIBLE_ROLE_COMMENT.
ARIA has corresponding roles as well [1] [2],
with the article role being the superclass role
of the comment role.
Acccording to the ARIA spec, the article role
has the document role as superclass role and
the name can be set by the author.
For the comment role, the name can be set by the
author or come from the content.
The ARIA spec for the comment contains this sentence [2]:
> If the author has not explicitly declared aria-level, aria-posinset, or
> aria-setsize for a comment element, user agents MUST automatically
> compute the missing values and expose them to assistive technologies.
However, these properties are not listed as "Required States and
Properties" in the following table for that role. Potentially
the above requirement only applies for the first of the two
possible described cases of how the relationship between comments
and the commented content can be set, so don't hard-require
these attributes in the a11y overlay's
`check_widget_accessibility_errors` either.
[1] https://w3c.github.io/aria/#article
[2] https://w3c.github.io/aria/#comment
We need to make sure that all our textures have the same memory
format, or we'll run into trouble in the upload code, at least
on GLES, which isn't as forgiving about format mismatches.
Related: #6238
Allow setting the modified flag, but skip propagating the history state update
as it will be done by gtk_text_history_end_irreversible_action().
Fixes#6236Closes#6236
Our test setups are mostly about varying the rendering environment
(different backends, or renderers, etc). Therefore, we don't need
to duplicate the runs of the css or node parser or path tests.
Just run the gdk and gsk-gl tests under all setups.
That way, we can work with older libdrm versions.
The list was generated via a bit of sed and grep from the current
dmabuf-fourcc.h, which is why I put it into its own file and included
all the formats, no matter how old they are.
Add the matching GdkMemoryFormat for all dmabuf formats.
This way, we don't fall back to RGBA8 for 10- and 16-bit formats that we
don't support natively when EGL or Vulkan use them.
Also includes corrections for a few mixups.
Make DnD events get directed to the right places (and most
importantly, not to the wrong places) when happening over
modal parts of the UI.
Fixes DnD started from popovers being able to drop on their
modal toplevel.
Make this event behave like the other regular events, and emit
coordinates based on native surfaces. Fixes DnD over popovers
finding the correct coordinates.
This function takes an event, so the place(s) that do
not have one readily available can only pass NULL, so
the serial lookup will only work for the pointer.
Pass a device (plus optional sequence) to this function,
as these places do at least have the corresponding
GdkDevice at hand.
Fixes serial lookups for DnD, for other devices than
pointers (e.g. tablets, or touch).
Our test setups are mostly about varying the rendering environment
(different backends, or renderers, etc). Therefore, we don't need
to duplicate the runs of the css or node parser or path tests.
Just run the gdk and gsk-gl tests under all setups.
Sadly, subsurface positioning is undefined in this case. We'll
trust the compositor to not mess up if the device coordinates
after applying the scale are integral, but otherwise, we'll
decline.
Instead, do it all in attach(), which becomes more and more like
ConfigureWindow. This is good, because it will let us take the
above-ness into account when making decisions about attaching.
There was one branch in the success case that turned it into a failure,
yet we were still reporting a success (and discarding the buffer).
Don't do that.
Without this, offloading is very hit-and-miss, since you need
to hit the few size combinations where you get an exact integral
size when preserving the aspect ratio.
Add a wayland_gl setup that explicitly uses desktop GL, and rename
wayland_gles to wayland_gles2 (since that is what it does).
In ci, make the fedora-x86_64 runner run tests with wayland_gl
and wayland_gles2, and make the fedora-release runner run test
with wayland and x11.
With the advent of dmabuf support, using GLES has become more
attractive, since we can use its external texture support to
support more dmabuf formats.
You can go back to the previous preference order by setting
GDK_DEBUG=gl-prefer-gl
The recursive subdivide_info function works by soring the
selector infos it gets into 2 (or 3) buckets: exact matches,
matches, and remaining. Then it recurses on the matches and
remaining buckets. This can be done without allocating extra
arrays, by sorting the given array in the right way.
This needs some serious testing.
Fixes: #6583
When passing a directory via G_TEST_SRCDIR, still pay attention
to --verbose, and print out each file thats tests. This lets us
quickly pin down which test fails.
As the commit message in
commit 9f078bd5c9
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Mon Sep 25 10:41:42 2023 +0200
a11y: Add paragraph role
already says, the super role of the paragraph role
in ARIA is the section role [1]. But then, that commit
accidently set the structure role for the super role,
so fix that now.
[1] https://www.w3.org/TR/wai-aria-1.2/#paragraph
The default keymap and keymap layouts are calculated on request.
If done once a surface is setup and listening at win32 events,
we may then enter in a recursive loop.
To avoid this, precalculate the keymap as soon as displays are open.
Fixes#6203Closes#6203
This flag must be set when creating the class or offloading
will be disabled for this renderer.
Set that flag for the GL renderer.
Fixes the Cairo and Vulkan renderer not showing Video.
Map GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT and
GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT to the
corresponding AT-SPI object attributes
"colindextext" and "rowindextext", as it is specified
e.g. in the Core Accessibility Mappings 1.2 for the
corresponding attributes [1] [2].
Orca makes use of these object attributes in web browsers
and since recently also for LibreOffice [3] and is
planning to use that more globally.
[1] https://www.w3.org/TR/core-aam-1.2/#ariaColIndexText
[2] https://www.w3.org/TR/core-aam-1.2/#ariaRowIndexText
[3] 3c056cd7b5
These tests come in two variants.
The first takes .node and .offload file, parses the node file,
and compares the resulting subsurface attachments to expected results.
The second variant takes two .node/.offload file pairs and a .diff
file, parses the node files, compares the resulting subsurface
attachments, and then diffs the nodes, comparing the resulting
area to the region in the .diff file.
This is new widget that will attempt to pass through the content
of its child via a subsurface. This is mostly meant for internal
use, but the minimal api is available.
During rendering, restack offloaded subsurfaces below the main
surface, and clear the area so they peek through. After rendering,
raise the last subsurface if we haven't drawn over it.
Add a blend mode to the draw command, so it can draw transparent
black. This will be used to erase the area on top of a subsurface
when we do passthrough.
Add an extra argument to pass offload info to the diffing code.
This is then used for diffing subsurface nodes differently,
depending on their offloading status.
We have to be careful to not draw over the subsurface area with
our highlighting, otherwise this would interfere with raising
unobstructed subsurfaces.
Add api to allow creating subsurfaces, attaching textures to them,
and changing the stacking order.
This is just the api, there is no implementation yet.
This is a backport of !1143 to gtk4.
SetClipboardViewer() API is obsolete is prone to clipboard chain breaks
from other applications.
Use recommended AddClipboardFormatListener() instead.
Fixes#442
`gtk_window_get_default_size()` claims width/height are optional-out
arguments, but defers to `gtk_window_get_remembered_size()` which
may dereference a NULL-pointer.
Since `gtk_window_get_remembered_size()` is only called by
`gtk_window_get_default_size()`, collapse it into the latter
and perform the NULL check there.
Make sure all our dmabuf debug messages are display-scoped so the
inspector doesn't trigger them, use the same formatting throughout,
and improve consistency of wording here and there.
Getting this wrong matters, since we won't offload textures in
non-opaque formats. Found by Robert Mader. At the same time,
unify the two places we have for mapping from fourcc to memory
format.
Deep trees quickly add so much empty space on the left, so that it gets
really hard to read after an indentation level of ~10.
By halving, we still keep the visual clarity of indenting but we can now
handle twice as many indentation levels, ie ~20.
It is what sysprof has been using, and it also feels right in the
inspector.
It started out as busywork, but it does many separate things. If I could
start over, I'd take them apart into multiple commits:
1. Remove G_ENABLE_DEBUG around GDK_DEBUG_*() calls
This is not needed at all, the calls themselves take care of it.
2. Remove G_ENABLE_DEBUG around profiling code
This now enables profiling support in release builds.
3. Stop poking _gdk_debug_flags and use GDK_DEBUG_CHECK()
This was old code that was never updated.
4. Make !G_ENABLE_DEBUG turn off GDK_DEBUG_CHECK()
The code used to
#define GDK_DEBUG_CHECK(...) false
#define GDK_DEBUG(...)
which would compile away all the code inside those macros. This
means a lot of variable definitions and debug utility functions
would suddenly no longer be used and cause compiler errors.
1. Check GStreamer caps for premultiplied alpha and select
GdkMemoryFormat accordingly
2. Set a GdkMemoryFormat for GL textures
Fixes the video in widget-factory being treated as premultiplied when it
isn't.
Add a new GTK_ACCESSIBLE_ROLE_BLOCK_QUOTE role
for block quotes/block quotations.
ARIA has a corresponding "blockquote" role as well. [1]
The role is used e.g. in document editors
like LibreOffice or web browsers like Firefox.
According to the ARIA spec (§ 5.2.8.4, [2]), the
blockquote role is among those that can be named by
the author, and the superclass role is section. [1]
Related change for LibreOffice making use of the new
role: [3]
[1] https://www.w3.org/TR/wai-aria-1.2/#blockquote
[2] https://www.w3.org/TR/wai-aria-1.2/#namefromauthor
[3] https://gerrit.libreoffice.org/c/core/+/158685
We were using it in all cases, so, we were using it to compute descriptions,
and also for non-embedded controls. That was overriding descriptions
set, for example, in Gnome settings, and was causing the value of spinboxes
to be read multiple times.
We really always want to force-include msvc_recommended_pragmas.h to check for
things at compile time so that we can avoid stuff like missing includes or
attempting to return a value in a function that is supposed to have a
void-return-type.
The current problem is that, as indicated in the Visual Studio CI job, that we
couldn't locate msvc_recommended_pragmas.h during the build if GLib is built
as a subproject, and/or when msvc_recommended_pragmas.h is not in the paths
indicated by %INCLUDE%, meaning that the aforementioned issues would not be
caught by CI, which will then break builds on Visual Studio for people when
msvc_recommended_pragmas.h is found during their builds.
It would also be nice to be quiet from the warnings that we can really
disregard anyways.
So, add a copy of msvc_recommended_pragmas.h from GLib and update the build
files to look for it in build-aux/msvc, so that it can always be used during
the build, especially by the CI.
Remove all the roadblocks we've put up to keep implicit modifiers
out. Our importing code already handles them as a signal that says
'No modifiers, please!'. Now we just hope for the best and pass
things along.
This is necessary since some drivers won't produce any explicit
modifiers.
Check that the right filter is chosen and that that filter is
implemented correctly.
The test is disabled for Cairo because Cairo (or rather Pixman)
doesn't follow the filtering specifications for GL/Vulkan and in
particular the nearest filter picks a different pixel.
Drawing a texture-scale node like a texture node when the filter is set
to "linear" doesn't work, because the texture node switches to
trilinear when mipmaps are available.
There is no reason not check the alpha swizzle for being different
from its default value. I am thinking about implementing RGBx
upload with a swizzle of rgb1, and that would break here.
We just poking at display members here, there is no guarantee that
dmabuf formats have been initialized. So do it explicitly.
This prevents a crash in the inspector when viewing a recorded frame
containing a dmabuf texture, since the inspector uses a separate
display connection.
We were confusingly printing "supported format" for dmabuf formats
that we end up not adding to our list of supported formats. Don't
do that, it is confusing. At the same time, we shuold print out
the linear formats we support via mmap.
If we can't open /dev/dma_heap/system, fall back to using memfd_create.
It does not let us make a 'proper' dmabuf, but it is good enough to
test our handling of linear buffers in various formats.
When we are running under GLES, we can use GL_TEXTURE_EXTERNAL_OES
to support YUV formats.
Since we don't want to deal with the combinatorial explosion of
compiling all our shaders with all combinations of sampler2D vs
samplerExternalOES for all their textures, we copy the external
textures to a regular texture before using them.
This shader uses samplerExternalOES to sample an external texture
and blit it into a 'normal' texture. It only works in GLES, but
we won't use it outside of GLES.
Allow our shaders to use samplerExternalOES, by declaring
that we use the relevant extension. Unfortunately, this
only works for gles, and requires different extensions for
gles2 and gles3. Yay
Add a GSK_GL_DEFINE_PROGRAM_NO_CLIP, which is like
GSK_GL_DEFINE_PROGRAM but compiles the shader just once,
with NO_CLIP defined.
This will be used in the future for shaders that do
texture conversion.
Prepare the plumbing in the GL renderer for textures that use
target GL_TEXTURE_EXTERNAL_OES. These need to use a special sampler,
so make sure our sampler machinery does not run over it.
Add an implementation of GdkDmabufDownloader that uses
gsk_renderer_render_texture + GL texture download.
Since gsk isn't threadsafe, we do the download in the main thread,
taking care to not disturb the current GL context of whatever is
going on there at the time.
And since gsk renderers are expensive to create, we cache it
in the display.
Note that gsk does not yet have any special support for
dmabuf textures, so for now, they will always get downloaded
and then reuploaded as GL textures.
This is a simple helper that feed a GdkTexture
through a renderer and returns the resulting
texture. This will be used to convert dmabuf
textures to 'native' textures.
Restore the bigendian support that was lost in b0e26873f6,
by just not using GL_BGRA with GLES on bigendian. Should be a
very rare combination, but still.
Trying to use it is a programming error, applications should have code
that uses real modifiers.
Also add a check to the formatsbuilder so our code doesn't include the
invalid modifier by accident.
We don't really know how to deal with it, so better force applications
to figure out what to do.
When adding the formats of a downloader, allow them to return FALSE to
mean "This method is not supported", which is a useful way to opt out
when checking GL or Vulkan extensions and finding out that the desired
one isn't supported.
The code now by default puts all planes into the same fd - like
v4l does, too.
The old behavior of one fd per plane can be enabled via --disjoint.
Also, am --undecorated option has been added so that the window
isn't decorated and all that the renderer has to do is display the
dmabuf.
This is useful when debugging just the dmabuf rendering.
This seems to be what everyone does, so we should do it, too.
Previously it was assumed that an fd of -1 would mean reusing the
previous fd with a different offset, but that seems to be uncommon.
This uses the dma-heap kernel api to create a dma-buf
and use it for a GdkDmabufTexture. It supports a few
formats to test how well GL conversion of YUV works.
The YUV code is adapted from weston tests.
We did have 4 ordering variations of ARGB straight,
but only 3 premultiplied. Add the missing one.
Update all the places where we switch over memory formats.
1. Split out the download function from the mmap'ing of the plane(s)
2. Make the code mmap() all the planes
3. Determine size using lseek() as documented by libdrm, instead of
trying to guess it from the format.
4. Fix some bugs, like switcheroos of width and height
Tries to sanitize the dmabuf to conform to the values expected
by Vulkan/EGL which should also be the values expected by
Wayland compositors
We put these sanitized values into the GdkDmabufTexture, by
sanitizing the input from GdkDmabufTextureBuilder, which are
controlled by the callers.
Things we do here:
1. Disallow any dmabuf format that we do not know.
1. Treat the INVALID modifier the same as LINEAR.
2. Ignore all other modifiers.
3. Try and fix various inconsistencies between V4L and Mesa,
like NV12.
*** WARNING ***
This function is not absolutely perfect, you do not have a
perfect dmabuf afterwards.
In particular, it doesn't check sizes.
The glyph and icon libaries were also checking for GLES to
decide if data needs to be transformed from BGRA to RGBA.
Use the new has_bgra getter instead.
This will probably break on bigendian, because the
GL_BGRA + GL_UNSIGNED_BYTE combination is not equivalent
to the cairo format on bigendian, but this was already
broken for the gl format information that we get from
gdk_memory_format_gl_format.
Vertex arrays are available in GL and in GLES >= 3.
We don't check for the GLES extension that provided
vertex arrays in older GLES, since that requires
using different API.
This api avoids version checks all over the place.
Make gdk_memory_format_gl_format take the GdkGLContext,
instead of just a gles boolean. This will let us
check for extensions that may be needed for certain
formats.
Update all callers.
We always have a display - the default display - so there's no need to
accept NULL.
Plus, we need a display when building the texture, so accepthing NULL
wouldn't even make sense.
Includes update to defaultvalue test.
We are returning interned strings here, and
g-i seems to have trouble interpreting the const,
so lets help it out by being more explicit with
our annotations.
Fixes: #6167
We need to provide color stops to avoid rounding errors with different
shaders.
That makes the empty linear gradient somewhat less empty, but I think
it's the emptiest we can make it.
GdkDmabuf is a struct encapsulating all the values of a dmabuf, so
nothing to see here.
GdkDmabufDownloader is a vtable for a thing that can download dmabufs.
For now only one implementation exists, so this just looks like a ton
of work for no benefit.
The only neat thing is that gdkdmabuftexture.c got a whole lot tidier.
Add a new debug flag for dmabuf-related information,
and use it in gdkdmabuftexture.c.
This will let us separate out dmabuf debug spew from
opengl debug spew.
To avoid O(n²) behaviour, GtkFileChooserNativePortal uses the
classic prepend tatict. However, it does not reverse the file
list after building it.
It's not a big deal since the portal does not specify the order
in which the files are sent. But it's nice nonetheless to send
the file list in the order in which files were passed originally.
Reversing the list has no meaningful performance impact.
Patch originally made by Bastien Nocera.
See https://github.com/flatpak/xdg-desktop-portal/issues/548
As mentioned in
commit 368f2af634
Author: Matthias Clasen <mclasen@redhat.com>
Date: Mon Oct 2 08:47:53 2023 -0400
a11y: Be safe against non-UTF8 text
, the string insertion APIs take string + length
and only insert up to `length` bytes of the
given string.
The AT-SPI "TextChanged" event however
is using a character count, and `emit_text_changed`
also gets called with the character count
along with the string.
However, `g_strndup` used in `emit_text_changed`
so far takes a byte count, not a character count.
Adapt `emit_text_changed` to just use the
passed text as is and make it the responsibility
of the callers to pass only the actually
inserted/removed string.
Most of the callers in `gtk/a11y/gtkatspitext.c`
already did that. Adapt two missing ones to do
likewise.
Fixes: #6151
`gtk_accessible_range_default_set_current_value` needs
to return TRUE independent of whether the value was
actually changed, since that return value is required
for the proper dbus reply to be sent to AT-SPI.
Fixes a crash/assertion seen e.g. with the "Hypertext" gtk4-demo
example when trying to change "CurrentValue" for the
level bar via the AT-SPI Value interface:
GLib-GIO:ERROR:../../../gio/gdbusconnection.c:4354:invoke_set_property_in_idle_cb: assertion failed: (error != NULL)
Bail out! GLib-GIO:ERROR:../../../gio/gdbusconnection.c:4354:invoke_set_property_in_idle_cb: assertion failed: (error != NULL)
Aborted
Fixes: #6150
These are the dmabuf formats that we can import
into a GL context as an EGLImage, and successfully
download.
We skip the GdkDisplay:dmabuf-formats property
in the default value tests, since the nominal
default value is NULL, but the actual value is
constructed on demand.
Add an implementation of GdkDmabufTexture.
For now, this implementation is rather minimal,
since we need a roundtrip through GL to convert
most nottrivial formats.
Add a builder for a new GdkTexture subclass that
wraps dmabuf buffers on Linux. For now, this is
just an API. The implementation will follow in
subsequent commits.
`gtk_editable_delete_text` can be called with a
negative `end_pos`, in which case the characters
from the start pos to the end of the text are
removed. [1]
It e.g. gets called this way from
`gtk_editable_set_text`.
So far, that negative index was not converted,
but passed as is in the AT-SPI callback
`delete_text_cb` when calling the `text_changed`
handler (`emit_text_changed` in
`gtk/a11y/gtkatspicontext.c`) which just uses the
index as is, also in it's call to `g_strndup`,
resulting in a crash when negative indices are
used.
Fix this by converting negative values to the
actual end index in `delete_text_cb` before
calling the handler.
[1] https://docs.gtk.org/gtk3/method.Editable.delete_text.htmlFixes: #6149
Updating a Pango context can influence the layout of widget, in
particular that of a GtkLabel, not only its rendering. Make sure to
queue a resize when updating the context.
In particular, this fixes window titles getting suddenly truncated when
moving a window from a HiDPI display to a low DPI one, after
https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6190 has made font
hinting depend on the widget scale. With hinting enabled on low DPI,
the Pango layout needs ever so slightly more width to not get truncated.
There is plenty of space in the header bar that could be allocated to
the label, but for that to happen, it needs to know to queue a resize.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
The C standard does not specify whether the underlying type of an enum
is signed or unsigned, and until C23 there was no way to control this
explicitly. GCC appears to make enums unsigned unless there is a
negative value among cases of the enum, in which case it becomes signed.
MSCV appears to make enums signed by default.
A bitfield of an enum type (which is not specificied in the C standard
either) behaves as if it was an instance of a numeric type with a
reduced value range. Specifically, a 'signed int val : 2;' bitfield will
have the possible values of -2, -1, 0, and 1, with the usual wraparound
behavior for the values that don't fit (although this too is
implementation-defined).
This causes the following issue, if we have:
typedef enum
{
GTK_ZERO,
GTK_ONE,
GTK_TWO
} GtkFoo;
struct _GtkBar
{
GtkFoo foo : 2;
};
and then assign bar.foo = GTK_TWO and read it back, it will have the
expected value of 2 (aka GTK_TWO) on GCC, but a value of -2 (not
matching any of the enum variants) on MSVC.
There does not seem to be any way to influence signedness of an enum
prior to C23, nor is there a 'unsigned GtkFoo foo : 2;' syntax. The only
remaining options seems to be never using enums in bitfields, which is
what this change implements.
In practice, this fixes GdkPipeIOStream crashing with an assertion when
trying to copy-paste in-app in MSVC builds on GTK.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
This is useful for colorizing in the same fashion we do for the glyph
texture atlas. In fact, for small GdkTexture, you will end up in something
like the icon texture atlas.
The primary motivator for this optimization is to draw various glyph-like
features from VTE such as many forms of boxes, lines, arrows, etc.
As it turns out, ccache accelerates the build so much that it can
trigger a race condition in the gobject-introspection subproject. This
only surfaced recently as the introspection feature was previously
disabled due to missing build time dependencies.
The race condition surfaces as follows: the build breaks because
gobject-introspection starts to build Gdk-4.0.gir before
GdkPixbuf-2.0.gir, despite Gdk-4.0.gir depending on GdkPixbuf-2.0.gir.
The string we're passed here may not be zero-terminated
since our text insertion APIs take string + length. So
So be safe and copy the text we are interested in if
necessary.
Fixes: #6131
Make gtk_print_dialog_setup_finish return a GtkPrintSetup
object, which encapsulates all the data that needs to be
transferred between the setup and print calls, and make
the print_file and print methods take an extra GtkPrintSetup
argument.
Change the print call to return an output stream, rather
than take an input stream. The results are now returned
when the output stream is closed.
With some further cleanup, this makes the GtkPrintDialog
object a proper builder object - you can create multiple
print dialogs from the same GtkPrintDialog object, in
parallel, and they won't interfere with each other.
The portal printoperation inmplementation
relies on the file printbackend to be available.
If it isn't, we should report a proper error
status insetad of running into assertions deep
inside the printoperation code.
We don't need to be calling type node conformity checking from the tight
loop of the renderjob. Hoist that into the private header and use that
intead through via the Class pointer.
Anything that includes gskrendernodeprivate.h will get an alternate form
of ref/unref for render nodes which does not need to do type checking on
the parameter. We can expect that things are correct within GTK itself and
this saves excessive amounts of TypeNode conformities checking.
Let's assert that we schedule the idle callback exactly once.
These assertions are not perfect because if the callback executes before
we schedule it, then the assertion itself would be a use-after-free,
since I'm using the PrinterFinder to track whether the callback that
frees it has been scheduled. But in practice when using loupe's print
dialog, I was noticing the callback scheduled twice before it was
executed. The assertion would have caught this problem.
This is a little tricky. At first, I thought we had a codepath where we
fail to schedule the idle that completes the print operation: if we take
the gtk_print_backend_printer_list_is_done path for each printer
backend, then printer_list_done_cb() is never executed and we never
schedule the idle. But in fact, in this case, then backends == NULL at
the bottom of find_printer(), and we'll schedule the idle there, so it's
OK. Except it's not really OK, because we'll schedule it even if a
printer was already found, resulting in the callback completing twice
and a double free.
Simplify this. Schedule the idle in find_printer() only if there are
*initially* no backends, not also if all backends are immediately ready
and already removed from consideration. Instead, always call
printer_list_done_cb() for every backend in find_printer_init(). After
the previous commit, printer_list_done_cb() will schedule the idle when
appropriate.
printer_list_done_cb() additionally disconnects signals that we did not
connect in this codepath, but it does so using
g_signal_handlers_disconnect_by_func, which is harmless. Otherwise, the
only extra work it's doing is scheduling the idle, and that's exactly
what find_printer_init() is missing.
If we are the final backend, then after removing ourselves there is no
backend remaining. We will schedule the idle even if it has already been
scheduled. This idle is required to run exactly once and executing it
twices results in a double free that crashes loupe when printing. It
also causes the user callback to execute twice, which could cause
similar problems.
Fixes#6122
Like the previous change, this uses GdkArrayImpl instead of GArray for
tracking modelview changes. This is less important than clip tracking
simple due to being used less, but it keeps the implementation synchronous
with the Clip tracking code.
We can end up spending a lot of time in g_array_maybe_expand() through the
use of g_array_set_size() for clip tracking. That is somewhat due to the
simple nature of GArray being size-dynamic. Instead, we can use
GdkArrayImpl and let the compiler do what it does best to elide some
work and hoist other work into the calling function.
This also fixes a potential UAF in gsk_gl_render_job_push_contained_clip().
When getting a colorized texture we're downloading the texture as a
Cairo surface, and then feeding it to another texture, but we never drop
the reference of the new surface.
Using "1 << x" means that we are shifting a signed 32bit integer, but we
want a gsize, which is an unsigned 64bit integer.
So now we don't overflow anymore if the array reaches a size of 2GB.
The fix in commit a267dfac5d is wrong.
The function can return FALSE in normal operation.
Instead do a check for node == NULL that gracefully returns FALSE instead.
Fixes: #6114
Add new GTK_ACCESSIBLE_ROLE_PARAGRAPH role
for paragraphs.
ARIA has a paragraph role as well.
The paragraph role is used e.g. in document editors
like LibreOffice or web browsers like Firefox.
According to the ARIA spec [1], naming paragraphs
is forbidden (§ 5.2.8.6), and the superclass role
is section.
This role will be more useful once a way to expose
the textual data via the AT-SPI Text interface is
also available (s. issue #5912 [2]).
[1] https://www.w3.org/TR/wai-aria-1.2/
[2] https://gitlab.gnome.org/GNOME/gtk/-/issues/5912
This reverts commit cac0cb7f02.
This doesn't work since CI currently mixes flatpak-builder and the host git repo
and doesn't download the gtk sources, so all subprojects are missing.
Gdk-Win32 uses GetClientRect() internally to query the surfaces coordinates,
but this API may fail in some transient contexts (observed when iconifying
a maximized window).
Check if the rect area is null, and don't update the surface position in
that case. This will keep the current surface size, until Win32 notifies
the new valid window state later.
This prevents using a nulled next_layout for toplevel size computation,
which would break widgets allocation once notified on gtk side.
Fixes#5724Closes#5724
Instead of building the projects from my forks, build them as gtk
subprojects.
To avoid meson hitting the network for those wraps, add the required
files as extra sources and put them into subprojects/packagecache,
so meson can find them at build time.
At the moment of launching/activating an application, the
keyboard focus may be on a transient surface that quickly
disappears after activation. If this happens, and the
compositor handles surface destruction before the activated
application gets to reply, the activation request may be
deemed outdated, and the "demands attention" paths be taken.
Peek the toplevel from the focus surface, as that has larger
guarantees to remain valid for the whole duration of the
operation.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5820
When a widget in the GtkPointerFocus stack becomes insensitive, we've
so far broken the implicit grab entirely. This has the side effect of
breaking accounting of the active state on the widgets that are
ancestors of the widget that became insensitive.
The easiest, and most consistent thing to do (i.e. giving widgets
in the GtkPointerFocus stack certain level of isolation wrt state
changes in other widgets) is to transfer the implicit grab to the
topmost actor of the GtkPointerFocus stack that can keep handling
events.
This fixes the unbalanced accounting of active state on ancestors
of widgets becoming insensitive, and avoids thorny questions about
how to handle implicit active state with broken implicit grabs.
When altering the broken implicit grab due to sensitiveness changes,
also ensure to clear the active state from the affected actors. This
fixes unbalanced implicit active state accounting on the widgets going
insensitive.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5529
It does make sense to have GtkText not focus on click in some cases,
such as when its editable property is set to false.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
These widgets wrap a GtkButton internally. Make it possible to prevent
the inner button from grabbing focus on click by propagating the value
of the focus-on-click property from the widget to the inner button.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
When shadows were offset - in particular when offset so the original
source was out of bounds of the result - the drawing code would create a
pattern for it that didn't include enough of it to compose a shadow.
Fix that by not creating those patterns anymore, but instead drawing the
source (potentially multiple times) at the required offsets.
While that does more drawing, it simplifies the shadow node draw code,
and that's the primary goal of the Cairo rendering.
Test included.
Make circle contours use 'foreach coordinates' for
its points. This works here, but not for general
conics. As with the other custom contours, avoid
emitting collapsed conics.
We need to inist on the nonuniform access beuing available and that
requires Vulkan 1.2.
Also simplifies the descriptor indexing stuff, because that's all part
of Vulkan 1.2, too.
The code now follows gsk_rounded_rect_shrink() and with it the behavior
of the Cairo renderer and Webkit.
The old code did what the GL renderer and Cairo do, but I consider that
wrong.
I did not test Chrome.
Test attached
In the "Recent" view of GtkFileChooser widget, when right
clicking and selecting "Visit file" action, the action was
failing to scroll to target file.
Fix that by using gtk_column_view_scroll_to() which can
select, focus and scroll to the file.
Fixes#5799
The source uniform may or may not point
to a glyph atlas. The optimization we do
for color nodes is only possible if it does,
so check this.
Fixes: #6094
This function is deprecated, but we should still document it properly.
It appends, not prepends. This is clear enough from its implementation,
but also we have practical experience with WebKit in:
https://github.com/WebKit/WebKit/pull/8663
Matthias prefers to avoid the prepend, append, start, and end
terminology altogether.
Cairo and the GL renderer have a different idea of how to handle
transitioning of colors outside the defined range.
Consider these stops:
black 50%, white 50%
What color is at 0%?
Cairo would transition between the last and first stop, ie it'd do a
white-to-black transition and end up at rgb(0.5,0.5,0.5) at 0%.
GL would behave as it would for non-repeating gradients and use black
for the range [0%..50%] and white for [50%..100%].
The web would rescale the range so the first stop would be at 0% and
the last stop would be at 100%, so this gradient would be illegal.
Considering that it's possible for code to transition between the
different behaviors by adding explicit stops at 0%/100%, I could choose
any method.
So I chose the simplest one, which is what the GL renderer does and
which treats repeating and non-repeating gradients the same.
Tests attached.
This partially reverts ccae75022b.
Since FileChooserCell is used for ColumnView and GridView we should
treat the list item as a GtkListItem, not a ColumnViewCell otherwise
the menu fails to generate properly.
The main menu is too long and the column options belong in the column
header menu to begin with. Since this is only available in column
view, we should always show the menu items.
If the entry has icons, we may end up increasing our minimum and natural
height compared to the values the text child returned. In that case, we
should also adjust the baseline values to account for the text being
shifted down.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
The measure logic (unlike the allocation logic) was enforcing strict
baseline alignment of child widgets even if no child widget had valign
set to baseline. This was causing GtkCenterLayout to request more size
than it actually needed.
Instead, bring the logic closer to that of GtkBoxLayout by introducing
explicit have_baseline and align_baseline variables. We track and report
baseline if have_baseline gets set, but it only affects our reported
minimum and natural sizes if align_baseline ends up set, which happens
if there's a child widget that has valign set to either one of the two
baseline values, and itself reports a valid baseline.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
The compose table stores the keyvals to match against
in a guint16 array, so it can't handle directly encoded
Unicode codepoints (which have a high bit set). Warn
if we encounter those.
We require folks to include gskglrenderer.h in order
to create a GL renderer. So we be careful to only
include header in gskglrenderer.h that won't trigger
ugly warnings.
See !6363
There is no decomposition going on for any contours,
and the tolerance argument is entirely unused.
Decomposition and tolerance is handled entirely
in gskpath.c by its trampoline.
Without an explicit width, height, and viewBox, there is no single
correct way to render an SVG. In the absense of said information,
librsvg is capable of making a guess by rendering the SVG to a Cairo
surface and then analyzing that surface; however, this process is
merely heuristic.
There are three GTK tests for SVG images that are missing dimensions.
While this is not a violation of the SVG specification, it does
implicitly couple the test to the librsvg rendering heuristic. In this
commit we add that dimension information so that the expected result
is unambiguous.
Make gsk_path_builder_add_rect always
produce a clockwise rectangle. This matches
what we do for circles and rounded rects,
which also go clockwise. Note that we
still need to allow negative widths in
the contour code, to implement reverse().
Add a contour that optimizes some things for
rectangles. Also add rectangle detection to the
path parser, and add tests similar to what we
have for the other special contours.
Check that the start- and endpoint work
as expected and verify that their winding
numbers match the ones of the standard contour,
and are negated when the contour is reversed.
This special contour takes advantage of its
rounded-rect-ness for speeding up bounding
boxes and winding numbers. It falls back
to the standard contour code for everything
else.
Add a private gsk_path_point_to_string that
can be called in the debugger if you want
to see the contents of a GskPathPoint and
are too lazy to cast it to GskRealPathPoint
yourself.
Only do the work for a curve the first time
we need it. This should greatly speed up
use cases where you only create a measure
to get the length of the path.
In order to compute path lengths efficiently, we need
to cache lookup tables. This commit adds API to let
contours allocate and free such measure data, as well
as API to use the data to go length -> point and
vice versa.
The runner is not available in forks (on purpose / for security
reasons), so jobs created there will be stuck indefinitely until they
timeout and fail the pipeline, which is undesireable.
That also means that the initial goal to enable macOS jobs for all MRs
is out of reach: if you are an external contributor (read: non-project
member), your MR pipelines run in your fork, therefore have no access
to the runner.
...and not around the center of the render node, as one could expect
given that the render node syntax for rotation, transform: rotate(90);,
happens to match the CSS syntax for the same thing, and CSS does rotate
around the center by default.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
The logic would confuse empty child bounds (in which case nothing should
get rendered) with NULL child bounds (in which case the child node's own
bounds should get used). In fact, if the child bounds are empty, we can
discard the descendant render nodes completely, getting a nice little
optimization.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
This tests the merging of nested color matrix nodes feature of
GtkSnapshot, which was broken before commit 082fdfdb24.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
This takes a render node tree and "replays" it by using the GtkSnapshot
machinery. We don't necesserily expect to get back an exactly equal
render node tree back, since GtkSnapshot applies various small
optimizations where possible, but the original and the replayed nodes
should render to identical textures.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
We don't need to have the derivative as a curve,
it is enough for us to compute values of the
derivative at a given t, which we can also do
for conics.
Arcs were appealing, but they have a fatal flaw: we can't
split our arcs without changing the ellipse they trace.
That could be fixed by adding an extra parameter, but then
it is no longer any better than conics.
So switch back to conics, which have the advantage that they
are used elsewhere.
Texture downloads can be initiated due to the weirdest reasons - and if
they cause a GL context to be changed, it'd be basically unpredictable
when the GL context changes.
An example is the Cairo renderer - if it needs to draw a GL texture, it
will download it.
Now that no longer changes the GL context.
It's expected that gtk_widget_get_root() will return NULL if the widget
tree does not contain a root widget. I don't know what that means or why
it happens, but it's true in gnome-control-center's network panel when
displaying the OpenVPN configuration dialog. We need to handle it.
Fixes#6056
Add a new curve type for elliptical arcs
and use it for rounded rectangles and circles.
We use the 'E' command to represent elliptical
arcs in serialized paths.
FLT_EPSILON is the distance between 1.0 and the next distinct floating
point number, and doesn't necessarily have anything to do with the
precision we can expect from a series of floating-point calculations.
Experimentally, 1e-6 is achievable, even on platforms with unusual
floating point implementations like i387.
Resolves: https://gitlab.gnome.org/GNOME/gtk/-/issues/6051
Bug-Debian: https://bugs.debian.org/1050076
Signed-off-by: Simon McVittie <smcv@debian.org>
Linking on Windows can easily run out of memory, and limiting it
to a single link operation (i.e. disabling parallelization) should
be enough to avoid this problem.
That's a gcc warning (clang has the equivalent -Winitializer-overrides,
but that one is included in -Wall) that complains about things like:
VkOffset3D offset = { .x = pt.x, .x = pt.y, .y = 0 };
So you don't have to spend a few hours trying to understand what's going
on before realizing your copy/paste skills are substandard.
The magical term to know about (because the GLSL compiler or the
validation layers sure as hell don't) is:
"dynamically uniform expression"
because if you don't have that when indexing a texture or buffer array,
you need to add nonuniformEXT() around the index variable.
Fixes the close icon on AMD having glitches of the previous icon visible
in some pixels.
When redoing a history entry, its `is_modified` flag is not
reflected to the history state tracker. So GtkTextBuffers may
expose a modified=FALSE status, despite a change was actually
applied to the buffer.
For the undo case, an `is_modified_set` flag was set on the last
entry of the undo queue when a change of the modified state of
the history is requested. This commit does the same on the first
entry of the redo queue.
Closes#5777
…files, or other cases other than calling new_from_model_full(), which
generally makes it far easier to experiment with the effect of flags,
including by changing the value of the property in the Inspector.
fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6030#note_1818229
We must be careful with single-point contours
that contain just a move. These never occur in
practice, but our randomized tests produce them
regularly.
* The `.background` class gets put on `popover`, not `content`
* Use backticks to style node and class names with monospace
* Link to GtkPopoverMenu
* Add to PopoverMenu a bit outlining how items and sections look in CSS.
Based on reverse engineering the color node and contrary to my
expectations, the matrix/offset is expressed in, and applied to,
unpremultiplied colors. The colors are being explicitly
unpremultiplied, transformed according to the matrix/offset, and
premultiplied back (see color_matrix.glsl). The matrix is getting
transposed.
Also, copy the same blurb to the corresponding GtkSnapshot function.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
The code was appliying the matrices in the wrong order: we have to apply
the inner node's matrix first, and the outer one second. Due to the
matrices being implicitly transposed, the matrix multiplication was done
in the right order, yet the wrong matrix was being mutliplied by the
wrong offset vector.
To make the code a little easier to follow, create explicit variables
for the resulting matrix and offset (instead of reusing matrix2 and
offset2), and fix & expand the comment to document how matrix
transposition factors into this.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
The (out caller-allocates) and (out callee-allocates) annotations are
meant for structured or pointer types. Plain old data types are just
regular out parameters and don't need the annotation about who allocates
them.
See glib!2005, gjs#570
Widgets are flashed by the window when it receives Tree::object-selected
- but we were emitting said signal from select_object(), i.e. if we were
made to select by an external caller. We should also emit it if the user
interactively selects an item, so the window receives+flashes the widget
fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6022
Make all the action signal handlers call
begin/end_change(), so we can rely on
change_count being >0 to check later if
an action is user-initiated or programmatic.
Fixes: #6018
On macOS 14, NSComboBox can't popup the dropdown list of filters. That
makes native filechooser on macOS completed broken. And NSComboBox is
more complex since it is a widget focused on edit capability.
NSPopUpButton is more suitable for plain selectable dropdown list.
Fixes: 4986
Signed-off-by: Qiu Wenbo <qiuwenbo@kylinos.com.cn>
GContentType on macOS switched to UTI since glib 2.51. We should not assume it as MIME type anymore.
Fixes: #4986
Signed-off-by: Qiu Wenbo <qiuwenbo@kylinos.com.cn>
Appending `s` breaks the [type@NS.Object] notation, so fix that in
ListHeader. Add links to ListItem and Overlay, and avoid appending `s`
after `backtick`s just for consistency with the [type@NS.Object] issue.
Take a rendernode as source and a GskPath and GskStroke,
and fill the area that is covered when stroking the path
with the given stroke parameters, like cairo_stroke() would.
and friends. This used to work OK via Container.add() but stopped
working in GTK4. While we have some ways left to TRY to add children
(via GtkWindow and Box), those don't work and result in broken layout
and assertion failures. Add basic API that can allow this to work again.
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/6001
This commit adds the basic infrastructure for paths.
The public APIs consists of GskPath, GskPathPoint and
GskPathBuilder.
GskPath is a data structure for paths that consists
of contours, which in turn might contain Bézier curves.
The Bezier data structure is inspired by Skia, with separate
arrays for points and operations. One advantage of this
arrangement is that start and end points are shared
between adjacent curves.
A GskPathPoint represents a point on a path, which can
be queried for various properties.
GskPathBuilder is an auxiliary builder object for paths.
graphene_rect_t is not well-suited for this purpose,
since you end up with floating-point precision problems
at the upper bound (x + width, y + height).
This struct carries information about scrolling a scrollable, so that
individual scrollables can share this struct for their scrolling APIs.
For now, there's not much information here, we're still trying to cook
up an API that works well.
The protocol spec isn't clear about the relationship
between the capability enum and the uint in the capability
event.
Fix things to use the same relationship as mutter.
While working on deprecation cleanups, I noticed
that removing GDK_DEPRECATED_IN... from headers
does not have the effect of making the symbols
disappear, since we were forgetting to set the
default visibility to hidden.
The builder test was relying on default visiblity
for non-static functions. Make it explicit that we
want to export these functions, so the test keeps
working when we change the default visibility.
Under circumstances I haven't fully tracked down,
these demos refuse to run, failing to locate their
callbacks. So use the machinery we have, and set up
a GtkBuilderCScope for each of the problematic cases.
It was calling get_hexpand () / get_vexpand (), which only get whether
the expand properties are set on the widget itself. Use
compute_expand (), which properly walks the widget tree and finds
whether exapnd is set on the widget or any of its descendants.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
No longer crashes with my listview_clocks demo or in real scrolling in
my application. "GtkGridView failed to scroll to given position. Ignoring..."
warnings are printed when it would have crashed.
Sometimes the scroll jumps incorrectly when it doesn't crash, but that's
a separate bug but is probably related to whatever is causing this
crash.
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/5945, at least in
terms of the immediate crash.
Make .svg use the Cairo renderer to save to an SVG file.
It's useful when comparing rendering behavior and times with
web browsers (as long as one is aware that browsers build a full
DOM tree out of those SVGs).
Just like GtkInscription does since commit 883011f2. The layout offsets
are maintained as floats, and only converted to integers when exposing
them to callers.
This is implemented using a new xdg_toplevel `suspended` state, and is
meant for allowing applications to know when they can stop doing
unnecessary work and thus save power.
In the other backends, the `suspended` state is set at the same time as
`minimized` as it's the closest there is to traditional windowing
systems.
With our current font rendering stack, subpixel positioning simply does
not look good on non-HiDPI displays compared to font hinting.
While we have a setting as a way to restore font hinting, it's fairly
clunky to use with sandboxed applications, since it requires injecting a
settings.ini file in every application's configuration directory, or
adding the user's own configuration directory into the sandbox.
As a workaround, we can check the scaling factor used by GTK, and only
enable subpixel positioning if the factor is greater than one.
We told Pango to limit width to mid pixels, and it returned a layout
size of text_width by text_height; text_width can be considerably
smaller than mid. If the layout fits, we know that it fits at
text_width, so set max to that. This lets us skip many iterations in a
typical case.
If we don't set the alignment then there is a chance that it ends up
commonly on a 4-byte boundary and GResources will have to malloc/memcpy
the static data.
With --set-section-alignment (which takes a byte offset not ^2) available
in objcopy >= 2.33 we ensure that expectation is met.
To use markup label in menu items, when the menu item has a submenu.
Small additions to 'gtk/gtkmenusectionbox.c' to set the markup attribute
for menu items with submenus.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5946
The GtkFileDialog code was asserting that
we get exactly one file back. But the function
is nullable anyway, so lets just return NULL
if we don't have a file.
Fixes: #5975
If we have a non-zero Adjustment:page-size, the actual amount we draw is
reduced by that page-size. We account for this in various places, but we
did not when deciding how far to allocate the highlight widget, so we
were drawing the highlight not far enough, falling short of the value.
This fixes by subtracting the page-size from the drawn range here too.
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/5976
Instead of scale and whatnot, pass:
1. The image size
2. The viewport to map to that image size
and compute everything else from there.
In particular, we set the Vulkan viewport to the image dimensions
instead of the viewport size.
All of this makes things a lot simpler while keeping the required
functionality.
If people specify the filename, they should know what they're doing.
If they don't, abort if the guessed filename already exists and insist
on the user explicitly giving it.
As pointed out in #3417, there is a long-standing
difference in how GtkEntry and GtkTextView treat
Ctrl-Shift-Backspace (and other variations): GtkEntry
always operates on the selection first, if it exists.
GtkTextView only handled plain Backspace that way, and
ignores the selection for other variations.
There is no good reason for this difference, so just
remove it and make GtkTextView behave the same as
GtkEntry.
Fixes: #3417
The relevant question here is about details, because we have to choose
if we declare alpha-only formats as having their (nonexistant) color
channels premultiplied or not, so that the code paths using them can do
the right thing.
Because we are premultiplied by default, it makes sense to treat alpha
like that, because then the alpha-only code doesn't need to do
workarounds for straight alpha.
Where this is relevant of course is when expanding the alpha channel
into color channels, where we want to end up with white.
So make sure we do color = alpha there instead of color = 1 like we did
before.
We need them for mask-only textures.
For tiffs, we convert the formats to RGBA (the idea that tiff can save
everything needs to be buried I guess) as tiffs can't do alpha-only.
Add a bunch of inline functions for graphene_rectangle_t.
We use those quite extensively in tight loops so making them as fast as
possible via inlining has massive benefits.
The current render-heavy benchmark I am playing (th paris-30k in node-editor)
went from 49fps to 85fps on my AMD.
Basically, memcpy() asap if possible.
This happens a lot in Vulkan, where we gdk_memory_conert() image
data from memory textures straight into the VulkanBuffer.
And usually we support the format.
When a GdkMemoryFormat is not supported natively and there's
postprocessing required, add a way to mark a VulkanImage as such via the
new postprocess flags.
Also allow texting such iamges only with new_for_upload() and detect
when that is the case and then run a postprocessing step that converts
that image to a suitable format.
This is done with a new "convert" shader/op.
This now supports all formats natively, no conversions happen on the CPU
anymore (unless the GPU is old).
Add an explicit begin() and an end() op. For now, this looks like
overkill, but it allows doing renderpasses with custom ops that are not
meant to render a rendernode.
Examples for this are pre/postprocessing passes or 2-pass blur.
The API was using regions because it always had. But all the code ever
did was get the extents of the region.
So simplify everything by using rectangles everywhere.
These days, we can query it with gsk_vulkan_render_get_context().
Makes quite a few functions require one less argument.
And it also makes the GskVulkanRenderPass empty. Gotta figure out what
to do with it.
Instead, build-depnd on glslc to build them.
glslc is available in all important distros for a while:
Fedora >= 28
Ubuntu >= 23.04
Debian >= 12
Arch
Opensuse >= 15.2
msys2
are the ones I checked.
So we can depend on it and avoid having to deal with keeping spirv files
up-to-date in all commits.
It's also 700kB of data, and not updating it helps.
We now store all the relevant state of the image inside the VulkanImage
struct, so we can delay barriers for as long as possible.
Whenever we want to use an image, we call the new
gsk_vulkan_image_transition() and it will add a barrier to the desired
state if one is necessary.
... and all the remaining functions still using it.
It's all unused and has been replaced by upload and download ops.
With this change, all GPU operations now go via GskVulkanOp.command()
and no more side channels exist.
This op queues a download of an image. The image will only be available
once the commands finished executing, so it requires waiting for the
render to finish, which makes the API a bit awkward.
Included is also a download_png_op() useful for debugging.
The render pass ops were not updating the image's layout to the final
layout when a render pass ends.
Fix that.
Also make the layouts explicit arguments to the render pass op.
Split out the function that uploads using a buffer, so that it can be
used with an area to only update parts of the image.
That feature is not used yet, but will be in future commits.
We were clowing through all the Pango caches for no benefit.
It made the test generation stuck in fontconfig loops instead of
quickly generating tests.
So don't do that and limit the different fonts to some reasonable list
of options.
If a command takes too long to execute, Vulkan drivers will think they
are inflooping and abort what they were doing.
For the simple color shader with smallish nodes, this happens around
10M instances, as tested with the output of
./tests/rendernode-create-tests 10000000 colors.node
So just limit it to way lower, so that we barely never hit it, ut still
pick a big number so this optimization stays noticable.
For small regions, the optimization doesn't matter that much, so we
don't need to do lots of work on the CPU.
In particular, this should catch icons and their backgrounds (32x32),
but I was generous in selecting the number.
Gets my discrete AMD on widget-factory back to the 1900fps it had before
this optimization while making the driver clock the GPU's shader at
1.7GHz instead of the 2.1GHz it used before.
Using clear avoids the shader engine (see last commit), so if we can get
pixels out of it, we should.
So we detect the overlap with the rounded corners of the clip region and
emit shaders for those, but then use Clear() for the rest.
With this in place, widget-factory on my integrated Intel TigerLake gets
a 60% performance boost.
The op emits a vkCmdClearAttachments() with a given color. That can be
used with color nodes that are pixel-aligned and opaque to significantly
speed up rendering when the window background is a solid color.
However, currently this fails a bit outside of fullscreen when rounded
clip rectangles are in use to draw rounded corners.
Instead of using the upload vfunc and going via the code in
GskVulkanImage, copy/paste the relevant code into the command() vfunc.
This is meant to achieve multiple things:
1. Get rid of GskVulkanUploader and its own command buffer and general
non-integration with operations.
2. Get rid of GskVulkanOp:upload()
3. Get the upload/download code machinery for GskVulkanImage and put it
with the actual operations.
The current code can't do direct upload/download, that will follow in a
future commit.
... instead of doing the equivalent things manually by creating a
RenderPass and calling the relevant functions.
Now all renderpass operations are indeed stored in ops.
Also reshuffle the command emission code, because we no longer need to
emit the ops for the base renderpass.
As a result we only submit a single command buffer containing all the
render passes instead of once per render pass.
We also bind vertex buffers and descriptor sets only once now at the
start instead of once per renderpass.
Use the OpClass.stage to order operations:
1. Put upload ops first
This way we can ensure they are executed first.
2. Move subpasses for offscreens in front of the pass using them.
This is a massive refactoring because it collects all the renderops
of all renderpasses into one long array in the Render object.
Lots of code in there is still flaky and needs cleanup. That will
follow in further commits.
Other than that it does work fine though.
All the ops that just execute a shader do pretty much the same stuff, so
put it all in a single function that they all call.
It's basically faking a base class for them.
Instead of recreating the same renderpass object in every frame and for
every offscreen, just reuse it.
Technically, we can save this per-renderer or even per-display (it
should really be cached by VkDevice), but we have no infrastructure for
that.
The function name gsk_vulkan_render_get_pipeline() had been used for
GskVulkanPipeline. Since those are gone now, we can use that name for
VkPipelines.
Renderpasses get recreated every frame, but we keep render objects
around. So if we keep the vertex buffer in the render object, we can
also keep it around and just reuse it.
Also, we only need one buffer for all the render passes, which is
another bonus.
The initial buffer size is chosen at 128kB. Maximized Nautilus,
gnome-text-editor with an open file and widget-factory take ~100kB when
doing a full redraw. Other apps are between 30-50kB usually.
So I chose a value that is not too big, but catches ~90% of cases.
Interning strings is slow, especially if we can instead do direct
pointer compares.
Also refactor the pipeline lookup code a bit to make use of the
refactored code.
Set it after creating all the ops and then use it for iterating.
Note that we cannot set it while creating the ops because the array may
be realloc()ed into a different memory region which would invalidate all
the pointers.
It currently has no use, but that will come later.
Also put the typedefs into headers in gsk/vulkan, they have nthing to do
outside that directory.
Remove the function to add a node from both the GskVulkanRender and the
GskVulkanRenderPass.
That means they are both now meant to draw exactly one node.
This is a rudimentary - but working - port.
Glyph uploads are still using the old machinery, a bunch of functions
still exist that probably aren't necessary anymore and each glyph emits
its own node.
This will need to be improved in further commits.
This shader is an updated version of the mask shader, but I want to use
the mask name for the mask node and that's a different functionality.
Also, add an operation for it and partially implement the mask node
using it, so we can test that this shader works.
Replacing the shader used for text rendering is the next step.
The benefit here is that we can now properly cross-fade when one of
start/end is fully clipped out by just replacing it with an opacity op
for the other.
This was not possible with the old way we did things.
Instead of creating a pipeline GObject, just ask for the VkPipeline.
And instead of having the Op handle it, just let the renderpass look
up/create the relevant pipeline while creating commands so that it can
insert vkCmdBindPipeline calls as-needed.
This reverts commit 0f184d3270.
The renderer is good enough to make use of the clip region.
Or rather: If it isn't, the renderpass should take care of that, not the
render object.
This reverts most of commit f420c143e0
again because it turns out GPUs like combined images and samplers.
But: The one thing we don't revert is allowing the C code to select any
combination of sampler and image:
gsk_vulkan_render_get_image_descriptor() now takes a 2nd argument
specifying the sampler.
This allows the same flexibility as before, we just combine things
early.
This change was inspired by
https://developer.nvidia.com/blog/vulkan-dos-donts/
Have a resource path => vkShaderModule hash table instead of doing fancy
custom objects.
A benefit is that shader modules are now shared between all renderers
and pipelines.
Instead of creating the op manually, just pass in the renderpass and
have the op created from there.
This way ops aren't really initialized anymore, they are more appended
to the queue, so instead of foo_op_init() we can just call the function
foo_op().
The new code always uses an offscreen, even for children that are
exactly fitting texture nodes.
I would have had to write more code and didn't consider it worth it,
especially because it would have required complicating the
get_as_image() function.
This was the last node using the texture pipeline.
Instead of having one function that gets the image for the texture and
uploads it if it doesn't exist yet, make it 2 functions:
One to get the texture if it exists.
One to assign an uploaded image to the texture.
This way, we can potentially do the upload ourselves.
Allocate the memory up front instead of passing the Op into it.
This way, we can split ops into their own source file and use
init/finish style to use them.
GskVulkanOp is meant to be a proper abstraction of operations
the Vulkan renderer will be doing.
For now it's an atrocious clunky piece of junk wedged into the
renderpass codebase.
It's so temporary that I didn't even adjust indentation of the code.
Make sure to end the signal name with a colon so GIR recognizes the
signal. This should also fix the problem that the documentation for that
signal is currently missing in the rendered gi-docgen output.
Wait for device to be idle because this function is also called in
window resizes.
And if we destroy old swapchain it also destroy the old VkImages,
those images could be in use by a vulkan render.
This fixes a issue reported in Mesa repository when running
GTK with Xe KMD.
Fixes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9044
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
The validate command does need a display connection,
for better or worse. So exit in an orderly fashion
if we don't have one, instead of crashing.
Fixes: #5948
Intersection with a roudned clip takes too long.
Instead, rename the function to may_intersect() to be clear about what
it does and then just intersect with the regular rectangle.
If we don't clip anything, we stil have bounds - either the framebuffer
size or (more likely) the scissor rect. And we don't want to draw
anything that is outside these bounds.
So clip in those cases, too.
Stops gtk4-demo --run=listbox from trying to render the whole listbox
instead of only the visible parts.
Use G_TYPE_CHECK_INSTANCE_TYPE() instead of just checking for != NULL.
After all, this is a GTypeInstance.
Also fixes some gcc complaints when checking
node == NULL || GSK_IS_RENDERNODE (node)
which gcc was convinced would be always true.
We have largely moved away from changing styles when :backdropped, aside
for some things in HeaderBars and Buttons. So we probably should not be
automatically dimming text in labels in list[view]s anymore either, as
that introduces differences if text happens to be in such widgets vs not
PROP_STORAGE_TYPE was only notified if it was changing *to* EMPTY, in
gtk_image_clear_internal(). We did not notify when it changes *from*
EMPTY to something non-empty. We should as not doing so is confusing,
e.g. if a user wants to bind :storage-type to :visible if non-empty,
which I just did! So, in functions that apply an ImageType, now notify.
Also do so in gtk_image_set_from_definition, declared in imageprivate.h,
even though none of the function there are currently used anywhere.
(Should they be removed?)
This mapping of stylus evdev input event codes into GDK button numbers
makes gdk/wayland inconsistent with gdk/x11, so depending on the backend
the same button middle-click pastes or right-click pops up menus.
Make the wayland backend consistent with X11, so that a GNOME wayland
session gets these buttons consistently mapped across all kinds of
clients.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5935
* Add links to various symbols.
* Mention DirectoryList in the "ready-made choices available" section.
* Don't say that GridView can display headers: it makes no attempt to.
The match operator was added in Python 3.10, which is a bit too new for
some downstreams.
While at it, let's fix the flake8 errors and warnings.
Fixes: #5934
Ignore long lines; most of our Python scripts generate code or other
types of files, which makes long lines a necessity.
We should validate all our Python script in our CI as well.
Inverted alpha masks have an effect on the source, even if the mask
doesn't cover the source at all - or worse, is completely clipped out.
The GL renderer handles this fine, but Cairo and Vulkan had
optimizations that got this wrong.
In particular, fix the combination of luminance and alpha. We want to do
mask = luminance * alpha
and for inverted
mask = (1.0 - luminance) * alpha
so add a test that makes sure we do that and then fix the code and
existing tests to conform to it.
When color-matrix modifying a clear surface, the surface would remain
clear according to Cairo.
That's very unfortunate when we prepare a mask for inverted-alpha
masking.
If we build our own targets, we need to include those.
This is only relevant when adding new shaders because meson will
complain that the (unused) sources don't exist as it tries to include
those.
And that will make the build.ninja file not be generated which would
have build those shaders and would have allowed to copy them into the
sources.
Note that this makes builds with glslc not care about all the shader
files being included with the sources, but we have CI to check that.
In particular, catch radius values being < 0 by return_if_fail()ing in
the rendernode creation code, and by erroring out in the rendernode
parser.
I try too much dumb stuff in the node editor.
As this script is now also used in GLib, unify the formatting between
GLib and GTK. Make the formatting of the script conformant to the
Black[1] tool, as GLib requires, and add a copyright header to this
script.
[1]: https://black.readthedocs.io/en/stable/, see also
$(glibsrcroot)/.gitlab-ci/run-bash.sh
Our default theme is now Default, not Adwaita, & HighContrastInverse was
renamed to Default-hc. So these checks did not work anymore. Rather than
hard-coding the new names, & possibly running into the same issue again,
we can just look for the convention of appending -dark to the theme name
and/or the Settings:prefer-dark-theme prop. The latter, we can & likely
SHOULD also apply to all themes - not just ours as before. We also check
for the :dark suffix as that means the theme variant - & before checking
GtkSettings check the GTK_THEME env var, just as GtkSettings itself does
The objcopy+ld approach to fast resource building
relies on behavior that is specific to the binutils
linker, and does not work with the llvm one.
Therefore, check for ld.bfd. We still fall back
to trying with just ld, since I'm not 100% sure
if binutils unconditionally installs ld.bfd.
Fixes: #5672
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/5922
The docs of `Gtk.DropTarget::accept` say this:
> If the decision whether the drop will be accepted or rejected depends
> on the data, [`::accept`] should return `TRUE`, [`:preload`] should be
> set and the value should be inspected via the `::notify:value` signal,
> calling `gtk_drop_target_reject()` if required.
But this pattern causes a CRITICAL, given these steps:
* Create a `DragSource` and `DropTarget`
* Keep the default `::accept` handler and set `:preload` to `TRUE`
* Connect to `notify::value` and therein call `DropTarget.reject()`
* CRITICAL at `DropTarget.enter()`→`Drop.get_actions()` on NULL instance
We should let the documented case work without a CRITICAL or worse, null
deref. And per @otte on the bug, we should bail earlier before `::enter`
& setting `GTK_STATE_FLAG_DROP_ACTIVE`; neither should occur if rejected
This fixes that, by checking after `start_drop()` when notifications are
thawed, whether any handler has `reject()`ed & set our `drop` to `NULL`.
The IFUNC resolvers that we are using here get
run early, before asan had a chance to set up its
plumbing, and therefore things go badly if they
are compiled with asan. Turning it off makes things
work again.
The gcc bug tracking this problem:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110442
Thanks to Jakub Jelinek and Florian Weimer for
analyzing this and recommending the workaround.
g_hash_table_insert() frees the given key if it already exists
in the hashtable. But since we use the same pointer in the
following line, it will result in use-after-free.
So instead, insert the key only if it doesn't exist.
Make the display handle the cache, because we only need one.
We store the cache in
$CACHE_DIR/gtk-4.0/vulkan-pipeline-cache/$UUID.$VERSION
so we regenerate caches for each different device (different UUID) and
each different driver version.
We also keep track of the etag of the cache file, so if 2 different
applications update the cache, we can detect that.
Vulkan allows merging caches, so the 2nd app reloads the new cache file
and merges it into its cache before saving.
This will parse a <property/> containing the ISO 8601 format for a date
for use in GDateTime properties. For example:
<property name="sampled-at">2023-06-23T00:00:00.00</property>
The current documentation is narrative, but it lacks examples and proper
formatting, which makes it harder to read and visually scan.
Let's split off paragraphs and sections, so they can be easily linkend,
and add a few examples for each description.
When there isn't an accessible role set on the
instance or in class_init, we want to default
to 'generic'. There was one place where we
failed to do so.
We now need glib-2.76.0 or later, which removes our needs for the workarounds
that we need to build the media backends against GLib-2.74.x or earlier, so
clean up things a bit.
We are now using APIs that were introduced in 2.75.x, so let's use glib-2.76.0
here for our glib subproject.
Update the build and gobject-introspection items accordingly
It turns out variable length is only supported for the last binding in
a set, not for every binding.
So we need to create one set for each of our arrays.
[ VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004 ] Object 0: handle = 0x33a9f10, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xd3f353a | vkCreateDescriptorSetLayout(): pBindings[0] has VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT but 0 is the largest value of all the bindings. The Vulkan spec states: If an element of pBindingFlags includes VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT, then all other elements of VkDescriptorSetLayoutCreateInfo::pBindings must have a smaller value of binding (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004)
Somebody (me) had flipped the 2 flags in commit ba28971a18:
[ VUID-vkCmdCopyBufferToImage-srcBuffer-00174 ] Object 0: handle = 0x3cfaac0, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0x430000000043, type = VK_OBJECT_TYPE_BUFFER; | MessageID = 0xe1b276a1 | Invalid usage flag for VkBuffer 0x430000000043[] used by vkCmdCopyBufferToImage. In this case, VkBuffer should have VK_BUFFER_USAGE_TRANSFER_SRC_BIT set during creation. The Vulkan spec states: srcBuffer must have been created with VK_BUFFER_USAGE_TRANSFER_SRC_BIT usage flag (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-vkCmdCopyBufferToImage-srcBuffer-00174)
It's necessary now that we use storage buffers for gradients:
[ VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingStorageBufferUpdateAfterBind-03008 ] Object 0: handle = 0x1e72d70, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x943cc552 | vkCreateDescriptorSetLayout(): pBindings[0] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT for VK_DESCRIPTOR_TYPE_STORAGE_BUFFER since descriptorBindingStorageBufferUpdateAfterBind is not enabled. The Vulkan spec states: If VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingStorageBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingStorageBufferUpdateAfterBind-03008)
We only want to settle on subtree content
if it provides nonempty text. Otherwise,
the tooltip should still win.
This was clarified in the current Editor Draft
of the accessible name computation spec.
Make this track the widgets' mapped state
instead of visible. Also, set hidden to FALSE
initially, since the accessible name computation
checks for hidden==FALSE.
There is no good way to set an explicit label
on the tab list of a GtkNotebook, so showing
a blue overlay on it is annoying more than
helpful.
This is another little deviation from the ARIA
authoring guidelines.
Due to the way listviews are set up, there is not
much of an alternative to setting labels on the
listitems, so don't recommend against doing it.
This is a little deviation from the ARIA authoring
guidelines.
Add properties to GtkListItem to set the accessible
label and description of the listitem widget. This
is important, since orca will read these if the
listitem widget ends up with the focus.
Add a helper function to find out which roles are
superclasses of each other.
This isn't used yet (apart from the existing use for
ranges), but it might be in the future.
This warning triggers quite a lot when opening
a window while orca is running, which clearly
shows that what it warns about happens in
practice. But fixing it is reentry hell, and
not a battle I'm up for today.
Its been more than a decade since Wayland
has not supported screen coordinates. Clearly
spamming every apps stderr with warnings is
never going to make ATs stop asking for screen
coordinates.
Just give up. Go home
Avoids unaligned accesses when e.g. the key_size is 12 and key_align is
8. We need to round the key size up to 16 to ensure that all keys are
appropriately aligned.
This manifested as a failure in the `gtk:gtk / sorter` unit test on
sparc.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5907
There were two problems here:
First, the code was checking for the abstract
range role, instead of its subclasses.
Second, the code was calling a string value
getter on a number value. Oops.
We can't set the display if we don't have a root,
but the default display is more than good enough
for the tests which otherwise would need to do
quite a bit more setup work to make their test
widgets rooted.
These functions rely on self->accessible_role
being set, and that is only the case for realized
contexts.
In practice, this is not a problem. Contexts are
realized before ATs can get their names or descriptions,
and the inspector realizes contexts too, nowadays.
The only place where this caused a hickup is the
testsuite.
Reimplement the name computation to follow the spec
(https://www.w3.org/TR/accname-1.2) more closely.
Also, unify the functions for name and description,
since their only difference is which property/relation
they use.
Shorten the warnings, and lower some of the
errors to 'not recommended' (where the authoring
guidelines say 'do not label', but aria doesn't
prohibit labels outright).
This is another case of nested control, in this
case it goes two levels deep. Since we already
have this hack, lets use it for all the cases.
This avoids some more complicated workaround.
The group role that we've used before has some
implications of semantic grouping, whereas these
containers are mainly about layout, so use the
generic role instead.
This should not affect the translation to AT-SPI
at all.
The affected containers are: box, grid, centerbox,
scrolledwindow, viewport, windowhandle, aspectframe.
The role of GtkTreeExpander has been changed to
button instead, since it acts as a button.
If a node has a higher depth, pick the RGBA format that has that depth
as the texture format we're renderig to with render_texture().
Support for adapting the swapchain is not part of this.
When a GdkMemoryFormat isn't supported, pick close formats that have a
higher chance of being supported.
Make sure this works recursively and the whole loop always ends up at
R8G8B8A8_UNORM because that one is mandatory.
Roughly, follow these rules:
1. Drop the unpremultiplied
2. Expand channels to include all of RGBA
3. pick swizzle that is RGBA
4. pick next largest depth
5. pick R8G8B8A8_UNORM
This way, we unify the code paths for memory access to textures.
We also technically gain the ability to modify images, though I have no
use case for this.
That way, the offscreen can create images of different types.
Its not used in this commit, but will come in handy when we want to
support high bit depth.
Pretty much copy what GL does and just use the default display to create
GPU-related resources without the need for a display.
This also adds gdk_display_create_vulkan_context() but I've
kept it private because the Vulkan API is generally considered in flux,
in particular with our pending attempts to redo how renderers work.
Fixes a bug introduced in d1135f9e3c.
Luckily the buffer was large enough that all my testing didn't catch it
because it took a few minutes to overflow.
The result of calling update_property needs
to be that the property is marked as set
afterward, even if the value we pass happens
to match the default value.
After this change, scrollbars have value-now
show up as zero in the accessiblity page of
the inspector, even when that matches the lower
bound.
Test included.
Fixes: #5886
Replace gdk_memory_format_prefers_high_depth with the more generic
gdk_memory_format_get_depth() that returns the depth of the individual
channels.
Also make the GL renderer use that to pick the generic F16 format
instead of immediately going for F32 when uploading textures.
Special-case nested buttons in our name computation,
since it is hard to reconcile all the a11y attributes
being on the wrapper, but the focus ending up on the
button inside.
This is a pragmatic approach that works. The only
downside is that the wrapper and the button end up
with the same name+description, but at least orca
seems to only read the focus elements' ones.
This reverts commit 343b9d246f.
Unfortunately, this makes it so that the focus ends up on
the 'generic' accessible, not the one with the label, and
orca remains quiet.
This reverts commit 5ec0b07baf.
Unfortunately, this makes it so that the focus ends up on
the 'generic' accessible, not the one with the label, and
orca remains quiet.
Make the internal toggle button generic, so that
the a11y checker doesn't complain about it not
having a label. And mark the icons in the popup
as presentational.
Make the color button itself take the button role,
and make the internal toggle button just be generic.
This solves the problem that labelled-by relations
that are set up in ui files via mnemonics point at
the toplevel, not the toggle button.
Make sure the color of the swatch and the button
are initially in sync. As a side-effect, this
ensures that the swatch has its accessible label
computed at the outset.
Include the needed headers so that we don't break the build with C4013
warnings, which are treated as errors if msvc_recommended_pragmas.h is
found during build configuration.
Complete the API change from commit be1729b316 ("signallistitemfactory:
Update signal prototype").
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
We can not compute the correct value, but that does not mean we should return
basically random values from an unitialized stack space.
Rather than that behavior, return zeros concistently.
Now that we don't use the old environment variables anymore to force
staging buffer/image uploads, we don't need them.
However, we do autodetect the fast path for avoiding a staging buffer
now, and we might want to be able to turn that off for testing.
So add GSK_DEBUG=staging that does exactly that.
This is unused now that all the code uses map/unmap.
The only thing that map/unmap doesn't do that the old code did, was use
a staging image instead as alternative to a staging buffer for image
uploads.
However, that code is not necessary for anything, so I'm sure we can do
without.
If the memory heap that the GPU uses allows CPU access
(which is the case on basically every integrated GPU, including phones),
we can avoid a staging buffer and write directly into the image memory.
Check for this case and do that automatically.
Unfortunately we need to change the image format we use from
VK_IMAGE_TILING_OPTIMAL to VK_IMAGE_TILING_LINEAR, I haven't found a way
around that yet.
Use the new map/unmap image upload method for Cairo node drawing:
1. map() the memory
2. create an image surface or that memory
3. draw to that image surface
4. success
There's no longer a need for Cairo to allocate image memory.
As an alternative to gsk_vulkan_image_new_from_data() that
takes a given data and creates an image from it, add a 3 step process:
gsk_vulkan_image_new_for_upload()
gsk_vulkan_image_map_memory()
/* put data into memory */
gsk_vulkan_image_unmap_memory()
The benefit of this approach is that it potentially avoids a copy;
instead of creating a buffer to pass and writing the data into it before
then memcpy()ing it into the image, the data can be written straight
into image memory.
So far, only the staging buffer upload is implemented.
There are also no users, those come in the next commit(s).
The GDK_SEAT_CAPABILITY_TABLET_PAD stood awkwardly out of the
ALL value. Even though it's not a keyboard, its focus has more
resemblance to it, so it should be part of this group together
with keyboards.
We were creating the pad device on wp_tablet_pad.done, but
at that time we do not know what tablet it is associated with,
thus we cannot get appropriate vid/pid/name properties for it.
To get that, we need to wait for the pad to enter a surface,
at that time we do know what tablet it is associated with, so
we can get better information about the device.
There are pads that may plausibly "change" tablet between
one .enter event and the next (e.g. Wacom Express Key Remote),
but this situation is highly unlikely. The pad devices created
are thus persistent until that situation happens.
Problem is GtkFileLauncher is unable to handle all the types of URIs
that are supported by gtk_show_uri(), e.g. help: URIs. GtkUriLauncher
avoids this problem.
Another problem is that GtkUriLauncher is just generally a better choice
for launching URIs, since you don't have to create a GFile in order to
use it. Porting code is slightly simpler.
The documentation still mentions both GtkFileLauncher and GtkUriLauncher
as options, but most people will use whatever the compiler recommends
when it prints the deprecation warning.
When the pointer leaves the window surface, gtk_window_capture_motion
will not be called anymore, so priv->resize_cursor may remain non-NULL
indefinitely without this.
If update_cursor is later called (via gtk_window_maybe_update_cursor) on
a virtual enter notify event (e.g. because the pointer entered a
descendant surface), it would previously re-set the window surface
cursor to priv->resize_cursor, which could result in the wrong cursor
shape being shown for descendant surfaces.
This affected mutter-x11-frames, see
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1557.
One could also say that if the pointer leaves the window surface, it's
trivially not over any window edge.
Add an overlay that shows a11y issues.
For now, this checks for:
- abstract roles being used
- elements without labels
- required attributes
- required context
The tooltip text should only be considered after
all other means are exhausted. but it can be used
for both the name and the description.
See https://www.w3.org/TR/accname-1.2/
Implement this sentence from the "Accessible Name
and Description Computation 1.2" spec:
If the root node's role prohibits naming,
return the empty string ("").
See https://www.w3.org/TR/accname-1.2/
When nodes are added, nothing was warning us that we need to bump
N_RENDER_NODES.
Make sure that that's no longer necessary by refactoring the code to
remove the define.
This is more expensive, but it finds more cases, and in particular it
catches corner cases like empty nodes or fully clipped nodes that might
otherwise make the kernel throw signals in our direction.
When the GTK_MEDIA env var is set, check at startup that it works, not
only when the first MediaFile is instantiated.
This has the fortunate side effect that it prints help output for
GTK_MEDIA=help at startup, too.
With the current approach, we get duplicate labels
in the accessible name: _Cancel Cancel. Change things
around to always set the labelled-by accessible relation
if we have a label, and not the label accessible property.
We have to be careful to only use GDK_ALIGN_BASELINE_FILL when
permitted by GDK_VERSION_MAX_ALLOWED because gtkenums.h is a
public header.
Fixes: #5875
I don't think we can avoid conditional compilation here, because the old definition is going to cause deprecated declaration warnings unless you define an old GDK_VERSION_MIN_REQUIRED.
When running the tests, only run the random (and potentially large) size
download test once instead of 10 times.
There's no real benefit in doing that, both because it's unlikely to
fail only in the 2nd or 9th run and because the sizes are picked
randomly.
This also speeds up the test massively as the download test was
dominating the runtime.
Instead of picking a few numbers in advance and running them through the
test gauntlet every time, pick the random numbers at runtime.
This both increases the test coverage in that it ultimately tests more
combinations across many runs and it reduces the runtime of individual
runs because every tun only runs the download tests twice (with 1px and
the random size) instead of 5 times.
And that speedup benefits the CI, where the asan runs would cause this
test to timeout sometimes.
If one of the descriptor sets doesn't have any items, don't include it
in the sets passed to vkUpdateDescriptorSets().
This has no effect right now, because we either have both images and
samplers or neither, but it will become relevant once we also support
buffers.
- 25 chars sounds about right for the texts we use
- don't use min width so we allow shrinking the widget (large text or
small mobile devices)
- ellipsize the text instead of clipping it.
There were 3 different random numbers set to determine the sidebar width
and all of them were wrong. Remove them.
Instead, propagate the natural width of the listitems.
Sometimes, GLX can decide to use the previous request serial when faking
XErrors via __glXSendError() (look through the Mesa sources to enjoy).
This can cause the error trap we just installed to not feel responsible
for the error. And that makes GDK decide to immediately abort the
application.
That is not what we or GLX want.
So we use a no-op X Request to bump the request number so that when GLX
does its shenanigans, it uses a serial that our error trap will catch.
Fixes a crash in mutter's CI which apparently manages to drive GLX
without an X server.
In error cases, glXCreateContextAttribsARB() will always return NULL so
it is enough to run the loop until the first non-NULL context is
returned.
And at that point, we can just look at the return value and ignore all
errors.
Respect the matrix in use at time of encountering a repeat node so that
the offscreen uses roughly the same device pixel density as the target.
Fixes the handling of the clipped-repeat test.
Make it use an alpha value that is well defined, ie 0.4 instead of 0.5.
0.4 * 255 = 102
0.5 * 255 = 127.5
This avoids rounding issues where some math may cause the resulting
alpha value to be 127, and some other math ends up with 128.
We want to always reserve space for the clear icon,
but let the text widget use that space when the icon
isn't shown. A plain box layout can't do that, so
do our own size allocation.
Sometimes the GPU is still busy when the next frame starts (like when
no-vsync benchmarking), so we need to keep all those resources alone and
create new ones.
That's what the render object is for, so we just create another one.
However, when we create too many, we'll starve the CPU. So we'll limit
it. Currently, that limit is at 4, but I've never reached it (I've also
not starved the GPU yet), so that number may want to be set lower/higher
in the future.
Note that this is different from the number of outstanding buffers, as
those are not busy on the GPU but on the compositor, and as such a
buffer may have not finished rendering but have been returend from the
compositor (very busy GPU) or have finished rendering but not been
returned from the compositor (very idle GPU).
The idea here is that we can do more complex combinations and use that
to support texture-scale nodes or use fancy texture formats (suc as
YUV).
I'm not sure this is actually necessary, but for now it gives more
flexibility.
For blend and crossfade nodes, one of the children may exist and
influence the rendering, while the other does not.
Previously, we would skip the node, which would cause the required
rendering to not happen. We now send a valid texture id for the
invalid offscreen, thereby actually rendering the required parts.
Fixes the blend-invisible-child compare test
Current state for compare tests:
Ok: 397
Expected Fail: 0
Fail: 26
Unexpected Pass: 0
Skipped: 2
Timeout: 0
Instead of having a descriptor set per operation, we just have one
descriptor set and bind all our images into it.
Then the shaders get to use an index into the large texture array
instead.
Getting this to work - because it's a Vulkan extension that needs to be
manually enabled, even though it's officially part of Vulkan 1.2 - is
insane.
If we have a rectangular clip without transforms, we can use
scissoring. This works particularly well because it allows intersecting
rounded rectangles with regular rectangles in all cases:
Use the scissor rect for the rectangle and the normal clipping code for
the rounded rectangle.
The idea is to use it for clip nodes when they are integer-aligned.
To do that, we need to track the scissor rect in the parse state, so we
do that, too.
Also move the viewport offset out of the projection matrix, as it is
part of the transform between clip and scissor, so it needs to live in
the offset.
We align the data to a multiple of vertex stride, that way we use more
memory, but we could compute an offset into the vertex buffer without
changing the offset.
We can set the vertex offset while counting the data, this gets rid of
the need of passing all the counting machinery into the actual data
collection code.
When attempting a complex transform, check if the clip can be ignored
and do that if possible.
That way we don't cause fallbacks when transforming the clip is too
complex.
The idea is that for a rectangle intersection, each corner of the
result is either entirely part of one original rectangle or it is
an intersection point.
By detecting those 2 cases and treating them differently, we can
simplify the code to compare rounded rectangles.
Instead of emitting the render commands once per rectangle of the clip
region, just emit them once with the region's extents.
This is generally faster because it emits fewer commands to the GPU,
even though it may touch significantly more pixels.
For a proper method, we'd need to record the commands per clip rectangle
instead of emitting all of them all the time.
The border and color shaders - the ones that do AA - now multiply their
coordinates by the scale factor, which gives them better rounding
capabilities.
This in particular improves the case where they are used in fractional
scaling situations, where the scale is defined at the root element.
Previously, we just used the defaultscale factor, but now that we're
having it available in push constants, we can read it back for creating
offscreens and rendering fallbacks.
So do that.
It's a 1:1 replacement for GskVulkanPushConstants, just without the
indirection through a different file.
GskVulkanPushConstants as a struct is gone now.
The file still exists to handle the push_constants operation.
1. Use a graphene_vec2_t
2. Ensure it's always positive
3. Don't break with fallback
The scale value is nothing more than an indication of how many pixels to
assume per unit of a node.
We don't want to render the offscreen trnsformed, we want to render it
as-is.
We lose the correct scale factor, but that requires some separate work,
so for now it gets a bit blurry on hidpi.
This introduces the rect object and adds a rect_distance() and
rect_coverage() function.
_distance() returns the signed distance tp the rectangle.
_coverage() returns the coverage of a pixel centered at that position.
Note that the pixel size is computed using dFdx/dFdy.
When the node bounds were a non-integer size, the texture would get
ceil()ed pixels, but various viewport or scissor computations might
floor() instead, leaving the right/bottom row of pixels untouched.
Make sure those functions ceil(), too.
Instead of trapping errors for the whole loop trying to create GL
contexts, trap them once per GL context.
Apparently GLX does throw an error when a too high version is requested
and doesn't just return NULL and then that error lingers when we try
lower versions.
Fixes#5857
We may try to update the XRR outputs and Crtcs when they're changing in
the server, and so we may get BadRROutput that we're currently not
handling properly.
As per this, use traps and check whether we got errors, and if we did
let's ignore the current output.
It's not required to call init_randr13() again because if we got errors
it's very likely that there's a change coming that will be notified at
next iteration during which we'll repeat the init actions.
When registering an observer, we send a notification and for that we need
to query the action's state and param type. When setting up a muxer parent,
same thing happens, except the action is queried on the parent instead.
This means that the muxer will notify observers about the parent's actions,
but not about its own.
Add a test to verify it works.
Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/5861
This is not the optimal way of doing it: we're
reuploading the texture with client-side conversion.
But it fits nicely into our current handling of mipmaps.
We can do better once we use shaders for colorspace
conversions.
Add some odd-sized texture sizes to the
download tests, to trigger alignment issues
in the various upload code paths. And add
a size that is bigger than the max-texture-size
we force in one of our test setups.
To compensate, reduce the number of
runs per size from 20 to 10.
For non-gles, make it handle unpremultiplied formats,
and everything else, by downloading the texture in its
preferred format and, in most cases, doing a
gdk_memory_convert afterwards.
For gles, keep using glReadPixels, but handle cases
where the gl read format doesn't match the texture
format by doing the necessary swizzling before calling
gdk_memory_convert.
Make the callers of this function check for
straight alpha themselves, and only do the
version compatibility check here. This makes
the function usable in contexts where straight
alpha is acceptable.
Use &__ImageBase for the GTK DLL and GetModuleHandle (NULL)
for the application module. Then remove DllMain as it's not
necessary anymore.
References:
[1] Accessing the current module's HINSTANCE from a static library:
https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483
The display xevent signal connection takes the ownership of the stream
until we get a valid event, so it should manage the stream lifetime.
So make this clearer, by automatically removing the stream reference
when we disconnect from the xevent signal handler.
We create a new stream during gdk_x11_selection_input_stream_new_async()
then such stream is referenced when passed to the task via
g_task_return_pointer(), so there's no need to reference it again before
returning it, or we'd end up leaking.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4892
The GL renderers like to premultiply content that isn't, and due to the
data loss with alpha == 0 (transparent white, transparent black and
transparent anything are all represented by (0, 0, 0, 0) when
premultiplied) these values cannot be converted back.
There is no longer a need to use gdk_texture_download() and force
conversion to ARGB8 format. We can download the pixels in the original
format again.
That way we avoid testing the conversion code and avoid having to deal
with differences in representable colors.
However, some formats do do conversions, so we allow pixel comparisons
to be accurate (requires 16bit comparison accuracy) or inaccurate (we
only care about 8bit).
Note that for the default RGBA formats, this is identical and means they
need to be bit-exact the same, no matter what.
But the higher bit depth formats may be more different - floating point
can even have different values with high accuracy (the float mantissa is
23 bit, we only care about 16).
The groups hash table is initialized lazily when inserting
the first GActionGroup (gtk_action_muxer_insert ()). Do as
all surrounding code does and check for NULL before using
groups.
This avoids triggering a warning
Without this, there are still GdkMonitors present for displays that are
present but disconnected (such as when a laptop disables the internal
display to connect to an external monitor).
This commit adds a single additional condition to the maybe_flip_position
function in gdksurface.c. If a popup's unflipped position is below the
bounds of its containing area, the popup uses its flipped position
instead. This prevents tooltips from appearing below the bounds of the
screen when a small widget is positioned very close to the bottom edge of
the screen, such as in Budgie and XFCE panel applets.
<property name="label">“Copy” will copy the selected data the clipboard, “Paste” will show the current clipboard contents. You can also drag the data to the bottom.</property>
<property name="text">Grumpy wizards make toxic brew for the evil Queen and Jack. A quick movement of the enemy will jeopardize six gunboats. The job of waxing linoleum frequently peeves chintzy kids. My girl wove six dozen plaid jackets before she quit. Twelve ziggurats quickly jumped a finch box.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.