Use the new cache feature to split oversized textures into tiles the
size given by the new device API.
Then number those tiles from left to right and top to bottom and use
that number as the tile id.
When we draw large images, we absolutely do not want to keep memory that
we do not need. So do a GC run after every tile. That otentially slows
down things, but it also improves the chances of not running out of
memory.
Here's the node for the image I managed to create after I applied this
patch:
repeat {
bounds: 0 0 50000 50000;
child: text {
font: "Noto Color Emoji 10000px";
glyphs: 661 0 0 0 color;
offset: 0 10000;
hint-style: none;
}
}
Functions should behave as I expect, and I just spent an hour debugging
a refcount issue because I assumed our image creation functions return
refrences. Which is a very sane assumption.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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
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.
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.
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.
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.
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.