We were putting big glyphs in the cache, in their
own texture, but forgetting to mark the texture
as permanent, so it could be reused, leading to
occasional misrendering. Fix this by marking these
textures as permanent, and explicitly freeing them
when the cache entry gets old.
Every few frames, we do extra work for the
cache aging. Arrange for the glyph and icon
caches to not cause extra work on the same
frame, to smooth things out.
There is no need for us to be very precise about
aging the glyph entries. It is enough to check
occasionally and mark old entries. This reduces
the overhead of work we do every frame on the
caches, at the cost of letting glyphs linger
a bit longer in the cache.
Make this function more similar to the icon
cache equivalent, and simplify it a bit. We
don't use the boolean return, and we don't need
to look at the age of entry when marking it
used.
Remember which atlases were removed, and only
check those when looking for icons or glyphs
to remove. For most frames, we don't have to
check at all since no atlases were removed.
Instead of copying the (rather large) RenderOp to the GArray, we can
simply set the fields directly in the allocated space for the struct.
In most cases, there wont be any allocations to make as the array size
is kept in tact across frame renderings.
We can just use memcmp here because even in the use of lookup keys with
C99 initializers, we can rely on any space between fields added by the
compiler to be zeroed. So we might as well use wider memory cmopares.
We can't just assume that the pointer we'se using as a cache key will
stay unique forever. The texture might be freed, and a later allocated
texture might have the same addres now, causing the cache to return
incorrect results.
Pass the glyph position into the glyph caching functions,
not just the glyph index. This allows us to cache different
images for different subpixel positions.
We are currently using a weird mix of pango and cairo,
but there is no need for us to go through a pango
renderer here; we can just use cairo directly.
Use the same texture atlases to back both
the glyph and icon caches, and unify their
sizes and management. Store big glyphs
in separate textures, so all atlases have
the same size. Tweak some of the eviction
parameters.
We share the caches across all GL contexts
on a display, unless the GSK_NO_SHARED_CACHES
env var is set.
The logic here seems faulty. We want to keep
a timestamp that tells us when the glyph was
last used, so always update the timestamp.
And whenever we use a glyph, it turns 'young'
again, so remove it from the old pixels
accounting.
The (MAX_AGE, MAX_AGE+CHECK_INTERVAL) interval
is only relevant to prevent us from turning
a cached glyph old more than once, and that
is already taken care of.
We don't need to just look at the scale of the new modelview matrix, but
at the one we get when multiplying the new one with the current one.
Test case attached.
We blindly assume everywhere that a single glyph will definitely fit on
one atlas, but that's not always the case.
For now, don't crash or produce GL errors.
We can't just pretend we have an identity matrix when we are actually
scaling. This fixes the node editor sometimes not drawing things when
rendering to a texture. We were mistakenly discaring render nodes
because the bounds transformation was wrong.
We stuff both gl-drawn and cairo-drawn textures into the same cache, so
we can't really assume that we need to draw any of them flipped or not.
Fix this by drawing fallback stuff upside down and then using
upside-down vertex data for everything.
Fixes#1897
Apparently genTextures and friends only "reserves names", initializing
them will actually create them. Using glObjectLabel on textures before
initializing them will throw a GL_INVALID_VALUE error.
When rendering to a texture, collecting the render ops might bind a
different framebuffer, so bind the one we want again before doing the
actual rendering.
This adds debug groups in various places, including the debug
nodes if those are in use. This makes the traces in tools like
renderdoc much easier to read.
GL keeps the unoform state per-program, but not per-frame. So, we can't
pretend that this works for us. Keep the RenderOpBuilder around for the
entire lifetime of the renderer instead.
This fixes rendering to a texture on intel hardware. The glClear calls
would throw a GL_FRAMEBUFFER_INCOMPLETE error here, because the
gsk_gl_driver_begin_frame() call in do_render() reset the framebuffer
object in use.
We don't want the new transform while drawing things on a texture.
Instead, only apply the new transform matrix when adding the final
texture drawing ops.
This fixes the stack cube rotation transition to at least look somewhat
better.
Make the API expect a tranform of the proper category instead of
doing the check ourselves and returning TRUE/FALSE.
The benefit is that the mai use case is switch (transform->category)
statements and in those we know the category and don't need to check
TRUE/FALSE.
Using the wrong matrix will now cause a g_warning().
Since we can do partial redraws, dropping every shadow that's been
unused for one frame happens too fast. This is also a problem when a
shadow gets drawn on a texture for a few frames.
This can happen for certain transform nodes. The transform node's
child's bounds are fine, but the transform node bounds are all nan.
Just ignore those bounds since we can't meaningfully render them anyway.
They were a neat idea while they lasted. But now, it's time for
categorized transform nodes, where matrices with
GSK_MATRIX_CATEGORY_2D_TRANSLATE are the exact replacement.
Renderers have not been adapted for this purpose, so they (continue to)
run slow paths.
The first set of glyphs is created with a timestamp of 1. Later we
subtract the glyph timestamp from the cache timestamp, meaning we end up
with numbers ending in 9, e.g. 59. Now unfortunately !(60 <= 59), so we
do not end up incrasing the old_pixels count of the cache. Later we then
call lookup() and DEcrease the old_pixels count, which makes the
unsigned int wrap and cause a huge old_pixels value, which causes us to
drop the cache.
Some of the flags got lost in the meson transition or were demoted from
error flags to warning flags.
This commit reintroduces them.
It also includes fixes for the code that had warnings with those flags.
The big one being -Wshadow.
This broke the overlay blur demoe when resizing the window to a size
that would completely move the image below a button, causing the
GtkSnapshot code to remove the clip node below the blur node.
So we can check that the currently set clip is the first one and now
intersect with it. This first clip is always the entire viewport or the
entire render_area and we don't want to end up drawing things to a
texture because of it.
Instead of getting the translation x/y everytime we use the modelview,
get it once, when extracting the metadata. Do the same with the scale.
And save if the matrix is "simple" at all, i.e. if it only consists of a
translation and/or scale. This will be helpful later when we start
drawing transformed nodes on textures.
We do this for every single node, which is a little costly, especially
since the common case for the modelview matrix these days is a simple
translation. So, check whether the new modelview matrix is only a
translation matrix and if so, don't do a full matrix multiplication per
node.
As they require a draw context and the draw context is already bound to
the surface, it makes much more sense and reduces abiguity by moving
these APIs to the draw context.
As a side effect, we simplify GdkSurface APIs to a point where
GdkSurface now does not concern itself with drawing anymore at all,
apart from being the object that creates draw contexts.
Previously, we got the damage, then computed the changed area, then
started a frame with that changed area.
But starting a frame computes the damage for us.
So now we start a frame, then get the damage area from that, then
compute the change area.
This is a special case of the transform node that does a 2D translation.
The implementation in the Vulkan and GL renderers is crude and just does
the same as the transform node.
Nothing uses that node yet.
This is an automatic rename of various things related
to the window->surface rename.
Public symbols changed by this is:
GDK_MODE_WINDOW
gdk_device_get_window_at_position
gdk_device_get_window_at_position_double
gdk_device_get_last_event_window
gdk_display_get_monitor_at_window
gdk_drag_context_get_source_window
gdk_drag_context_get_dest_window
gdk_drag_context_get_drag_window
gdk_draw_context_get_window
gdk_drawing_context_get_window
gdk_gl_context_get_window
gdk_synthesize_window_state
gdk_surface_get_window_type
gdk_x11_display_set_window_scale
gsk_renderer_new_for_window
gsk_renderer_get_window
gtk_text_view_buffer_to_window_coords
gtk_tree_view_convert_widget_to_bin_window_coords
gtk_tree_view_convert_tree_to_bin_window_coords
The commands that generated this are:
git sed -f g "GDK window" "GDK surface"
git sed -f g window_impl surface_impl
(cd gdk; git sed -f g impl_window impl_surface)
git sed -f g WINDOW_IMPL SURFACE_IMPL
git sed -f g GDK_MODE_WINDOW GDK_MODE_SURFACE
git sed -f g gdk_draw_context_get_window gdk_draw_context_get_surface
git sed -f g gdk_drawing_context_get_window gdk_drawing_context_get_surface
git sed -f g gdk_gl_context_get_window gdk_gl_context_get_surface
git sed -f g gsk_renderer_get_window gsk_renderer_get_surface
git sed -f g gsk_renderer_new_for_window gsk_renderer_new_for_surface
(cd gdk; git sed -f g window_type surface_type)
git sed -f g gdk_surface_get_window_type gdk_surface_get_surface_type
git sed -f g window_at_position surface_at_position
git sed -f g event_window event_surface
git sed -f g window_coord surface_coord
git sed -f g window_state surface_state
git sed -f g window_cursor surface_cursor
git sed -f g window_scale surface_scale
git sed -f g window_events surface_events
git sed -f g monitor_at_window monitor_at_surface
git sed -f g window_under_pointer surface_under_pointer
(cd gdk; git sed -f g for_window for_surface)
git sed -f g window_anchor surface_anchor
git sed -f g WINDOW_IS_TOPLEVEL SURFACE_IS_TOPLEVEL
git sed -f g native_window native_surface
git sed -f g source_window source_surface
git sed -f g dest_window dest_surface
git sed -f g drag_window drag_surface
git sed -f g input_window input_surface
git checkout NEWS* po-properties po docs/reference/gtk/migrating-3to4.xml
This renames the GdkWindow class and related classes (impl, backend
subclasses) to surface. Additionally it renames related types:
GdkWindowAttr, GdkWindowPaint, GdkWindowWindowClass, GdkWindowType,
GdkWindowTypeHint, GdkWindowHints, GdkWindowState, GdkWindowEdge
This is an automatic conversion using the below commands:
git sed -f g GdkWindowWindowClass GdkSurfaceSurfaceClass
git sed -f g GdkWindow GdkSurface
git sed -f g "gdk_window\([ _\(\),;]\|$\)" "gdk_surface\1" # Avoid hitting gdk_windowing
git sed -f g "GDK_WINDOW\([ _\(]\|$\)" "GDK_SURFACE\1" # Avoid hitting GDK_WINDOWING
git sed "GDK_\([A-Z]*\)IS_WINDOW\([_ (]\|$\)" "GDK_\1IS_SURFACE\2"
git sed GDK_TYPE_WINDOW GDK_TYPE_SURFACE
git sed -f g GdkPointerWindowInfo GdkPointerSurfaceInfo
git sed -f g "BROADWAY_WINDOW" "BROADWAY_SURFACE"
git sed -f g "broadway_window" "broadway_surface"
git sed -f g "BroadwayWindow" "BroadwaySurface"
git sed -f g "WAYLAND_WINDOW" "WAYLAND_SURFACE"
git sed -f g "wayland_window" "wayland_surface"
git sed -f g "WaylandWindow" "WaylandSurface"
git sed -f g "X11_WINDOW" "X11_SURFACE"
git sed -f g "x11_window" "x11_surface"
git sed -f g "X11Window" "X11Surface"
git sed -f g "WIN32_WINDOW" "WIN32_SURFACE"
git sed -f g "win32_window" "win32_surface"
git sed -f g "Win32Window" "Win32Surface"
git sed -f g "QUARTZ_WINDOW" "QUARTZ_SURFACE"
git sed -f g "quartz_window" "quartz_surface"
git sed -f g "QuartzWindow" "QuartzSurface"
git checkout NEWS* po-properties
And then clip the texture using the current (maybe also rounded) clip.
This way, the result is correct. We don't necessarily have to do the
offscreen drawing in any case, but got the safe route for now.
Put GdkGLTexture into its own file and rename the API to
gdk_gl_texture_foo() instead of gdk_texture_foo_for_gl().
Apart from naming, no actual code changes.