This is an experiment for now, but it seems that encoding srgb inside
the depth makes sense, as we not just use depth to decide on the
GL fbconfigs/Vulkan formats to pick, depth also encodes how the [0...1]
color values are quantized when stored.
Let's see where this goes.
This commit just adds the flag, but I wanted to make it an individual
commit to explain the purpose:
The SRGB flag is meant to be used for images that have an SRGB format.
In Vulkan terms, that means VK_FORMAT_*_SRGB.
In GL, it means GL_SRGB or GL_SRGB_ALPHA.
As these formats have been madatory since GL 3.0, we can (ab)use them
uncoditionally. Images in these formats are renderable, too, so it's
not just usable for uploading.
What these images allow is treating the data as sRGB while shaders
access them as linear, thereby getting sRGB<=>linear conversions for
free.
It is also possible to switch off the linearization of these images and
treat them as sRGB, which allows all sorts of shenanigans, though one
has to be careful if that turning off applies to the relevant GL/Vulkan
code in question.
If the GL texture is exportable to a dmabuf, we can just use our dmabuf
importing code to get that texture into Vulkan.
There is no need to go via host memory in that case.
And if it doesn't work, we just fall back, like before.
Unimplemented nodes are a failure now.
We make this a soft failure with a g_warning() so that during
development when adding new nodes, the renderer doesn't instantly crash,
but instead prnts a warning.
But we do consider unimplemented nodes a bug now.
Because of that, add_fallback_node() is now renamed to add_cairo_node().
When determining which way is up for the offloaded texture, we
must take all transforms into account - the ones outside the
subsurface node, and the ones inside.
By moving negative affines to be treated like dihedrals, because they
also need support of the modelview, we can free up the affine branch for
doing work without it.
Not a big win I guess, but it makes scaling more efficient.
This allows handling them without ever needing to offscreen for losing
the clip, because the clip can always be transformed.
Also, all the optimizations keep working, like occlusion culling,
clears, and so on.
The main benefit of this work is the ability for offloading to now
handle dihedral transforms of the video buffer.
The other big advantage is that we can now start our rendering with a
dihedral transform from the compositor.
This category does a finer-grained categorization than
GskTransformCategory, but it is deliberatedly made to allow
easy backwards compatibility.
The reason for the categories is that they fit our renderers more
fine.
In particular, it allows implementing wl_output_transform support more
efficiently, thereby allowing rendering buffers the right way for
rotated phone screens or monitors.
The rectangles need to touch/overlap in both directions, otherwise
there's no coverage that covers both rectangles.
Test included.
Fixes rendering glitches in various apps when redrawing.
Fixes: #6849
... instead of init_draw(); add_node(); finish_node();
We hook into the infrastructure one step earlier and close to where the
default renderer_render() and renderer_render_texture() arrive in the
nodeprocessor.
Why is this relevant?
Because process() does occlusion culling.
TL;DR: offscreens do culling now
We import them as general, so they should be exported like that.
This was a longstanding issue that I never got around to fixing and I'm
touching this code anyway atm.
See commit 3aa6c27c26 for more details.
NULL disables clearing. We only implement this for GL as in Vulkan we'd
need to create different renderpasses with different attachment
descriptions and that would require more plumbing.
We need to check that the clip is inside the opaque region, not that the
opaque region is inside the clip.
Test included, using the only not that hits the fallback path with an
opaque region smaller than its bounds.
Sometimes container nodes contain lots of overlapping opaque items. In
that case we can use the container node itself as the first node even
though none of the children cover the whole paint area.
The use case for this is a grid of cells like in a terminal where all
the cells are opaque and we want to avoid drawing the background behind
them.
Due to the way the intermediate offscreen gets drawn, we might end up
with seams at the edges.
And I don't think it's worth spending more time on than saying "not
opaque".
Fixes the compare-render testsuite
New testcase included.
We want to operate with opacities, so it makes sense to have this radily
available.
And we're doing a walk over all children on creation anyway, so why not
just capture the rect there.
We want to be able to express opaque grids. This means that the app
provides either a row of columns of opaque nodes or a column of rows,
and then the containers will magically figure it out.
The main use case for this is terminals, which are uilt using cells. And
when there's a transparent background configured but the contents are
opaque, it'd be nice if we could figure that out.
Also remove the 80% requirement. It is rather arbitrary and while it
helps for some cases, the aforementioned grid would suffer.
Clip nodes often appear in the widget tree.
And the implementation can be trivial because of the sanity checks
already performed before calling the vfunc.
This is required because transform nodes appear everywhere.
We just exit for all transforms that can't transform the clip rect
losslessly. Both because they are rare and because we'd make the
coverage possibilities much lower.
Containers can walk the list of children back to front, trying to find
the topmost node that fully covers the viewport.
And then they can skip drawing all the nodes before that one.
Asks a node to add itself if it is fully covering the clip rectangle.
In that case, it is the first node that needs to be added.
If the node is not fully covering the clip, it should not draw itself,
because there might be stuff needing to be drawn below.
If a node adds itself, it should call gsk_gpu_render_pass_begin_op().
We find the first child that covers >80% of the container and return
that.
This is a nice speedup for the common case of a GtkWindow being covered
by a large opaque background.
It will fall apart for fancy themes that play with transparency or for
small windows because the shadow region gets too large.
But then we just scan the whole node tree.
We could think about adapting the 80% number, because that wasn't chosen
with any real scientific data behind it.
This takes both the vertical and horizontal rectangle that isn't
covering the rounded corners and intersects both with the child's opaque
rect.
And then it returns the larger of the two.
This means the small slices of a window near the left/right (or
top/bottom) will never be covered, but if we wanted that, we'd need to
use something else than a rectangle - either a region or actually a
rounded rect.
But that is a lot more expensive to implement.