Render nodes can end up with bounds < 1 since they are floats, and the
implicit cast to int ends up creating a texture with 0 width or height.
Use ceil() instead in create_texture so we don't have to do that on the
caller side everywhere.
VkImage contains a reference to the VkDeviceMemory and, because
the current code frees the VkDeviceMemory before destroying the
VkImage that references it, a warning is triggered by the validation
layers.
This is not critical, since we release both resources at the same
place. But the warning triggered by the validation layers sums up
adding 1 MB per second of extra debug logging, making the debugging
process much more painful.
This commit simply swaps the destruction order, and destroys the
VkImage first, then the now unused VkDeviceMemory.
This means we can directly upload these as textures, rather than
create a new surface and draw it into that. We still have to upload,
but there isn't a lot we can do about this as for these nodes
we generally redraw everything each time.
We cannot unrealize a renderer in the dispose function, because that
would cause this chain to happen:
gsk_gl_renderer_dispose
gsk_renderer_dispose
gsk_renderer_unrealize
gsk_gl_renderer_unrealize
So we would call into thje GL renderers unrealize when it has already
(partially) disposed itself and ause accesses to dead variables.
This fixes blurry text and icons whenever we apply shadows
in a hidpi window. Shadow nodes are the last ones that we
still use fallback for, and this was causing us to render
the text blurry.
Pass a scale factor when caching glyphs or looking them
up in the cache. The glyphs in the cache are rendered
with subpixel precision determined by the scale. Update
all callers to pass a scale factor according to the window
scale. This lets us render crisp glyphs on hidpi systems.
The copy of the PangoGlyphString we do here was showing up
in some profiles. To avoid it, allocate the PangoGlyphInfo array
as part of the node itself. Update all callers to deal with
the slight api change required for this.
Rename the surface getter to peek, following other render
node getters, and make the surface-based constructor private,
since it is not something we want to encourage.
Update all callers.
The color-matrix shader was creating pixels with r,g,b > a in
some cases, which leads to unexpected test failures. In particular
this as visible the opacity render node test for opacity 0.
We were node handling coordinates correctly when dealing
with differently sized child nodes in a blendmode node.
This was showing up in the gtk4-demo css blendmode example,
for blendmodes other than normal.
This patch makes that work using 1 of 2 options:
1. Add all missing enums to the switch statement
or
2. Cast the switch argument to a uint to avoid having to do that (mostly
for GdkEventType).
I even found a bug while doing that: clearing a GtkImage with a surface
did not notify thae surface property.
The reason for enabling this flag even though it is tedious at times is
that it is very useful when adding values to an enum, because it makes
GTK immediately warn about all the switch statements where this enum is
relevant.
And I expect changes to enums to be frequent during the GTK4 development
cycle.
-Wint-conversion is important because it checks casts from ints to
pointers.
-Wdiscarded-qualifiers is important to catch cases where we don't
strings when we should.
In some cases, we were creating gigantic intermediate textures
only to clip out a small section afterwards (e.g. in the listbox
example in gtk4-demo). This is wasteful if we apply effects on
the texture, such as blur or color-matrix. So, clip the dimensions
of the intermediate texture with the current clip. To make this
feasible, we move the texture coordinate computation out of the
pipeline setup functions into the node_as_texture function where
this clipping happens.
One extra complication we encounter is that the node might get
clipped away completely. Since Vulkan does not allow to create
empty images, we bail out in this case and not draw anything.
With these changes, the listbox example in gtk4-demo goes from
32M pixels of intermediate texture to 320000.
Instead of having a function with lots of arguments in
GskVulkanRender that we call from GskVulkanRenderPass which
then just calls back into GskVulkanRenderPass, just create
the new render pass object locally, and an api to add it
to the list that GskVulkanRender keeps. This makes it
a lot easier to preserve all the relevant parameters from
the parent render pass.
Move away from the idea of intra-frame sampling, since we only
push samples once per frame, anyway. Instead, make the profiler
keep a rolling average of the last n frames.
Whenever we need a node as a texture, we now start a new render
pass that renders the node into a new intermediate texture, and
set up a semaphore to make the current render pass wait for it.
As part of this reorganization, much of the setup and drawing
code moved from gskvulkanrender.c to gskvulkanrenderpass.c.
Allow to pass in semaphores to wait for before executing
and to signal after executing the command buffer. This
just exposes the capabilities of the underlying Vulkan
api. Update all callers to pass no semaphores, for now.
We will use this in the future.
I've finally figured out the right combination of src and dest
stage and access flags to make all validation warnings go away.
This commit only fixes the direct upload code.
This is another example for a 2-texture shader.
So far, only separable blend modes are implemented.
The implementation is not optimized, with an
if-else cascade in the shader.
We were looking at uninitialized memory here, instead
of the type of the source clip, as we should.
This showed up as mispositioned clip in the first frame
of a crossfade stack transition, and also as overdraw in
sliding stack transitions.
We already move the descriptor set layout out of it,
so we can just as well keep the pipeline layouts in
the render object as well, and get rid of this extra
object. Update all callers.
Instead of doing multiple copy commands with a tiny buffer
for each glyph, we can just batch them all together. This
also avoids the issue of creating multiple barriers for the
same image.
By tracking the last transition we can build the appropriate barriers.
Also use the most appropriate initial layout/access at creation :
for linear image : predefined (we prepare the content ourself through memcpy)
for everything else : undefined (we don't care about the content, will most likely be erase)
Move the glyph caching api to something that can support using
multiple textures. We now split the text render ops into multiple
ops for different textures, and make each op render just a substring
of the text node's glyph string.
This is just a proof of concept - we use a single 1024x1024 surface,
and just give up when we run out of space. The cache is populated
incrementally, and items are never removed.
This commit takes several steps towards rendering text
like we want to.
The creation of the cairo surface and texture is moved
to the backend (in GskVulkanRenderer). We add a mask
shader that is used in the next text pipeline to use
the texture as a mask, like cairo_mask_surface does.
There is a separate color text pipeline that uses the
already existing blend shaders to use the texture as
a source, like cairo_paint does.
The text node api is simplified to have just a single
offset, which determines the left end of the text baseline,
like all our other text drawing APIs.
This fixes the proper dependencies getting set up for generating
the shaders and only the necessary things getting rebuilt on
resources changing in gsk.
Currently, this information is not used since cairo_show_glyphs
deals with color glyphs for us. But when we get to uploading
glyphs to a texture atlas, we will need it to do the right thing.
We don't look at individual glyphs here, but just whether the
font has the has-color flag set. In practice, all glyphs in
such a font will be color glyphs, and we can avoid loading all
the glyphs this way.
The memory alignment requirements are different from the image layout.
We want the rowPitch to know where to upload the lines.
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
https://bugzilla.gnome.org/show_bug.cgi?id=786485
Spooky action at a distance is not really allowed in Meson, so the rules
to generate the SPV files should go in their own directory.
Tested by: Rico Tzschichholz <ricotz@ubuntu.com>
If glslc is found, rebuild the shaders from GLSL to SPIR-V; otherwise,
we're just going to use the built files we have committed in the source
repository.
We have to work around some ordering problems here. We still
manage to keep most of the guts in modules/input/meson.build,
so it's not too ugly overall.
(The autotools build solves this with a 'make -C ../../input/modules'
inside gtk/Makefile, but that's not something we can or want to do.)
Add back dependencies on libgdk_dep and libsk_dep which are declared
dependencies. We removed this before because these declarations had
link_with: lines that dragged in the static libgdk.a and libgsk.a libs
which are linked into libgtk-4.so anyway and thus shouldn't be used
when linking internal exes/tools against libgtk-4. Remove the static
libs from the declared dependencies and have libgtk link those in
explicitly, so that the declared deps now just provide all the built
dependencies and include dirs and such for declared libgtk_dep users
such as the internal exes/tools, which want all the generated gsk/gdk/gtk
headers to exist before attempting to compile anything against the
gtk+ headers.
gtk_shader_builder_add_define should check both define_name and
define_value for not-NULL and not-empty, but the second precondition
check checks define_name again for not-empty-ness.
If you set GTK_INSPECTOR_RENDERER to the same type of
values that GSK_RENDERER takes this can change the renderer
used for the inspector. This is useful if you're debugging
one renderer and don't want to affect the inspector.