Commit Graph

3040 Commits

Author SHA1 Message Date
Benjamin Otte
e40ad5faa5 gpu: Cache textures when doing copies
The texture and texture-scale node code is creating image copies
for mipmaps and to adapt to the compositing colorstate.

Those texture should be cached.
2024-07-11 14:57:20 +02:00
Benjamin Otte
dd393a4a0e gpu: Split out texture lookup function
It's unused in 3 function and has become somewhat unwieldy.
2024-07-11 14:57:20 +02:00
Benjamin Otte
881954dfca gpu: Rework texture caching
We want to cache textures in the compositing color state, not in their
original color state. However, the compositing color state may change
(think multimonitor setups).

So we additionally keep a cache per colorstate.

That means texture lookup is now a 3-step process:

1. Look up in the compositing colorstate's cache

2. Look up in the general cache

3. Upload
2024-07-11 14:57:20 +02:00
Benjamin Otte
cf12503fec gpu: Don't replace cache items
Instead, keep them. This is not useful yet, but will become so in the
next commits.
2024-07-11 14:57:20 +02:00
Benjamin Otte
ad757cccb6 Don't use GL_SRGB for premultiplied textures
GL_SRGB is doing postmultiplied alpha, so if the texture is
premultiplied, we can't use this optimization.

The optimization still works for unpremultiplied and opaque images,
because those don't do that step.
2024-07-11 14:57:20 +02:00
Benjamin Otte
b801eae00f gpu: All ops obey the ccs now
Remove the macro used for the not-yet converted ops.
2024-07-11 14:57:20 +02:00
Benjamin Otte
2fe9ff7918 gpu: Make mask op obey ccs
No colorstate conversions allowed here, though technically we could use
the alternate color state for the source most of the time, as the mask's
colorstate is only relevant for luminance.
2024-07-11 14:57:20 +02:00
Benjamin Otte
c407582096 gpu: Make blur op obey ccs
Blend ops don't do colorspace conversion, so this commit just hardcodes
that and rewrites the shader to use recent APIs.
2024-07-11 14:57:20 +02:00
Benjamin Otte
0fc3dbaa9b gpu: Make texture op obey ccs
Well, texture ops actually don't do any colorspace stuff, but let's
explicitly hardcode that.
2024-07-11 14:57:20 +02:00
Benjamin Otte
77ed264714 gpu: Introduce gsk_gpu_color_states_create_equal()
This is a function that's meant to be used whenever both color states
of the shader are equal. In that case no colorspace conversion code
needs to be created and shaders can be shared.
2024-07-11 14:57:20 +02:00
Benjamin Otte
a14efce914 gpu: Make blur op obey ccs 2024-07-11 14:57:20 +02:00
Benjamin Otte
08f90a188c gl: Force U8 textures for U8_SRGB depths
The GL renderer is using FLOAT32 instead of GL_SRGB, which is screwing
up the node-editor by making it turn on high bit depth unconditionally.

So until someone fixes the GL renderer properly, do this quickfix.
2024-07-11 14:57:20 +02:00
Benjamin Otte
df46eeafdb gpu: Make colormatrix op obey ccs
The colormatrix needs to be applied to unpremultiplied values, so we use
the alternative colorstate for that.
2024-07-11 14:57:20 +02:00
Benjamin Otte
0029286a1e gpu: Remove unused function
The colormatrix shader is no longer used for opacity.
2024-07-11 14:57:20 +02:00
Benjamin Otte
0e46d4eb98 gpu: Pass sampler to the image op
That way, we can use it in one other place where we want to use mipmaps.

I don't really like it because it adds yet another argument,
but then the one new caller was selecting suboptimal shaders, and that's
worse.
2024-07-11 14:57:20 +02:00
Benjamin Otte
f80e3fff92 gpu: Don't use the colormatrix shader for opacity
The colormatrix shade does a whole matrix multiplication, which is
absolutely not necessary.

The convert shader has builtin opacity handling and when the colorstates
match will do no conversion.
2024-07-11 14:57:20 +02:00
Benjamin Otte
504c6ba792 gpu: Don't use color matrix for opacity
We can use the regular image op which will select the fastest shader.
2024-07-11 14:57:20 +02:00
Benjamin Otte
c0aba9aee1 gpu: Make crossfade op obey ccs
I didn't have an idea what to use the alternate color state for, so I
don't use it.
2024-07-11 14:57:20 +02:00
Benjamin Otte
b97cf2b9d9 gpu: Track image colorstate
So far we only track the image colorstate and convert if necessary.

There is no caching of the converted images happening.
2024-07-11 14:57:20 +02:00
Benjamin Otte
f81e7b2112 gpu: Make conic gradient op obey ccs
Straight copy of the linear gradient changes.
2024-07-11 14:57:20 +02:00
Benjamin Otte
b59e4a929e gpu: Make radial gradient op obey ccs
Straight copy of the linear gradient changes.
2024-07-11 14:57:20 +02:00
Benjamin Otte
099d72f037 gpu: Make box shadow op obey ccs 2024-07-11 14:57:20 +02:00
Benjamin Otte
73acb41931 gpu: Make colorize op obey ccs 2024-07-11 14:57:20 +02:00
Benjamin Otte
ebb7fdb099 gpu: Make linear gradient op obey ccs
The alternative color state is used as the interpolation color state.
Colors are transformed into that space on the CPU.

For now we set the interpolation color state to SRGB, because ultimately
we want to let callers specify it, so having something that's easy to
map to that behavior is desirable.
Otherwise we might have chosen to interpolate in the compositing
colorstate.

It also means that we need to premultiply colors on the CPU now because
of the limitations of the shader colorstates APIs.
2024-07-11 14:57:20 +02:00
Benjamin Otte
ec3cb0ad9a gpu: Make border op obey ccs 2024-07-11 14:57:20 +02:00
Benjamin Otte
7ffef6792f gpu: Make rounded-color op obey ccs
This is the same as the color op.
2024-07-11 14:57:20 +02:00
Benjamin Otte
383148dc31 gpu: Make color op obey ccs
This makes use of the GskGpuColorStates by setting the ccs as output
colorstate and the color's colorstate as alternative color state.

The shader adaption is very straightforward because of that.
2024-07-11 14:57:20 +02:00
Benjamin Otte
a31601ccfc gpu: Make clear op obey ccs
This is the first op to obey the compositing color state. This means
from now on until all ops obey the ccs rendering is broken when ccs is
not set to linear.

I'll keep individual ops in seperate commits for easier review, because
they all need different adaptations.
2024-07-11 14:57:20 +02:00
Benjamin Otte
a587492cad gpu: Handle target not being composite colorstate
Render to an offscreen and add a final conversion if the target
colorstate is not a rendering colorstate.

This now allows the GPU renderer to render to any colorstate.
2024-07-11 14:57:20 +02:00
Benjamin Otte
f65d4914e4 gpu: Port convert op to GskGpuColorStates
Make it handle straight alpha, too, by checking if the alt colorspace is
premultiplied - which is the colorspace of the source.
2024-07-11 14:57:20 +02:00
Benjamin Otte
88dc49a5b6 gpu: Print the color states of shader ops
Makes the verbose output (a lot) more verbose, but it makes the
colorstates used in the shaders very visible.

And it will be relevant once people start using different colorstates
everywhere (like oklab for gradients/colors and so on).
2024-07-11 14:57:20 +02:00
Benjamin Otte
91d970e9c5 gpu: Add shaders for the new specialization constant
This adds the following functions:

output_color_from_alt()
alt_color_from_output()
  Converts between the two colors

output_color_alpha()
alt_color_alpha()
  Multiplies a color with an alpha value
2024-07-11 14:57:20 +02:00
Benjamin Otte
6c5ae48a05 gpu: Pass color states as specialization constant
This adds a GdkColorStates that encodes 2 of the default GdkColorStates
and wether their values are premultiplied or not.

Neither do the shaders do anything with this information yet, nor do the
shaders do anything with it yet, this is just the plumbing.
2024-07-11 14:57:20 +02:00
Benjamin Otte
d85ec2cbb4 gpu: create SRGB images
If desired, try creating GL_SRGB images. Pass a try_srgb boolean down to
the image creation functions and have them attempt to create images like
that.

When it is not possible to create srgb images in the given format, just
fall back to regular images. The calling code is meant to check the
GSK_GPU_IMAGE_SRGB flags to determine the actual format of the resulting
image.
2024-07-11 14:57:20 +02:00
Benjamin Otte
05b79bc378 gpu: Handle SRGB in render_texture()
When GDK_MEMORY_U8_SRGB is desired by the node, and a SRGB image is
created, pick SRGB_LINEAR as the colorspace to pass to frame_render().
2024-07-11 14:57:20 +02:00
Matthias Clasen
3ba63315d5 gpu: Pass compositing color states
Make the node processor and the pattern writer track the current
compositing color state. Color state nodes change it. We pass
the surface color state down via the frame apis.

The name of the variable is "ccs" for "compositing color space". It's an
unused variable name and it's common enough to deserve a short and sweet
name.
2024-07-11 14:57:20 +02:00
Benjamin Otte
eccdb594eb gpu: Remove straightalpha shader
As the new convert shader can do everything this shader could, use it
instead.
2024-07-11 14:57:20 +02:00
Matthias Clasen
a78796f22c gpu: Add a color convert shader
This shader converts between two color states, by using the
same functions that we use on the cpu. The conversion to perform
is passed as part of the variation.

As premultiplication is part of color states on the shader, we also
encode the premultiplication in the shader.
And because opacity is a useful optimization, we also allow setting
opacity.

For now, the only possible color states are srgb and srgb-linear.
2024-07-11 14:57:20 +02:00
Benjamin Otte
4fa6f791f4 cairo: Use the draw context's color state
This just passes through the sRGB set by the GDK backends instead of
hardcoding sRGB, so no functional changes.
2024-07-11 14:57:20 +02:00
Benjamin Otte
6287eaa745 cairo: Add colorstate to GskRenderNode::draw and use it
This adds the following:
- ccs argument to GskRenderNode::draw
  This is the compositing color state to use when drawing.

- make implementations use the CCS argument
  FIXME: Some implementations are missing

- gsk_render_node_draw_with_color_state()
  Draws a node with any color state, by switching to its compositing
  color state, drawing in that color state and then converting to the
  desired color state.
  This does draw the result OVER the previous contents in the passed in
  color state, so this function should be called with the target being
  empty.

- gsk_render_node_draw_ccs()
  This needs to be passed a css and then draws with that ccs.
  The main use for this is chaining up in rendernode draw()
  implementations.

- split out shared Cairo functions into gdkcairoprivate.h
  gskrendernode.c and gskrendernodeimpl.c need the same functions.
  Plus, there's various code in GDK that wants to use it, so put it in
  gdk/ not in gsk/

gsk_render_node_draw() now calls gsk_render_node_draw_with_color_state()
with GDK_COLOR_STATE_SRGB.
2024-07-11 14:57:20 +02:00
Benjamin Otte
ab7d969700 gdk: Add color state arg to gdk_texture_download_surface()
All callers set it to SRGB at the moment.
2024-07-11 14:57:20 +02:00
Matthias Clasen
5a7d7cc9f5 gsk: Show srgb information in verbose output
Show which offscreens are using an srgb format.
2024-07-11 14:57:20 +02:00
Benjamin Otte
1bbf5f7a17 gdk: Add GDK_MEMORY_NONE depth
That's basically the "undefined" value. We need that when drawing
nothing, which so far only happens with empty container nodes.

But empty container nodes can be children of other nodes, and that makes
things propagate. So instead of catching them, force the whole rest of
the code to deal with an undefined depth.

We also can't just set a random depth, because that will cause merging
to fail.
2024-07-11 14:57:20 +02:00
Matthias Clasen
db3b3c62bb ngl: Mark backbuffers as srgb
When the surface tells us that a surface is using an sRGB backbuffer,
set the corresponding flag on the backbuffer.
2024-07-11 14:57:20 +02:00
Matthias Clasen
de76045939 vulkan: Mark swapchain images as GSK_GPU_IMAGE_SRGB
Detect if an SRGB format is in use and mark the images as such.

So far this doesn't happen, but once it does, things will work.
2024-07-11 14:57:20 +02:00
Benjamin Otte
16c29a7db5 texture: Add gdk_texture_get_depth()
... and use it.
2024-07-11 14:57:20 +02:00
Benjamin Otte
b5b0002d24 rendernode: Return the right depth for colors
This makes sure we return U8_SRGB for GdkRGBA colors with linear
compositing.
2024-07-11 14:57:19 +02:00
Benjamin Otte
a7ceb8ce66 gdk: Add GDK_MEMORY_U8_SRGB depth
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.
2024-07-11 14:57:19 +02:00
Benjamin Otte
6dea23128a gpu: Add the GSK_GPU_IMAGE_SRGB flag
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.
2024-07-11 14:57:19 +02:00
Benjamin Otte
2f4e19d514 gdk: Allow querying GL SRGB formats
Nobody is using this yet.
2024-07-11 14:57:19 +02:00