Keep at least 1 second of frame timings.
This is necessary for 2 reasons - a real one and a fun one.
First, with the difference in monitor refresh rates, we can have 48Hz
latops as well as 240Hz high refresh rate monitors. That's a factor of
4, and tracking frame rates in both situations reliably is kind of hard
- either we track over too many frames and the fps take a lot of time to
adjust, or we track too little time and the fps fluctuate wildly.
Second, when benchmarking with GDK_DEBUG=no-vsync with a somewhat fast
renderer (*cough*Vulkan*cough*) frame rates can go into insane dimensions
and only very few frames are actually getting presentation times
reported. So to report accurate frame rates in those cases, we need a
*very* large history that can be 1000s of times larger than the usual
history. And that's just a waste for normal usage.
Previously, our reported fps numbers could be too low when the start
timings weren't complete. In that case we would use the frame time, but
the frame time is the time when the frame was rendered, which is quite a
few milliseconds before it is presented.
So in that case we would not report the difference in presentation
times, but the difference from start of rendering. However, those times
are way more variable and can smear over the whole frame because they
depend on when we received the frame callbacks to high priority GSources
as well as our own render time predictions.
This happened in particular with GDK_DEBUG=no-vsync and could report
number that are off by a factor of 2.
Now we skip any incomplete frames, because those frames never have
presentation times reported. This makes it theoretically more likely to
not being able to report fps at all, but I'd rather have no fps than fps
off by a factor of 2.
This is done with a NSCursor whose content is an NSImage. Image pixels are filled by a NSBitmap, and the format is premultiplied RGBA. So we can just use the texture downloader with GDK_MEMORY_R8G8B8A8_PREMULTIPLIED format.
While it’s documented as being safe, it triggers warnings from ubsan.
While we work out the best way to deal with that inside the
implementation of `G_ADD_PRIVATE` in GLib, let’s pragmatically just
short-circuit the code which triggers the warning here. This is helpful
because `gdk_display_get_debug_flags()` is called from a number of
locations within GTK, so is likely to be hit if anyone is running a UI
app under ubsan.
See https://gitlab.gnome.org/GNOME/glib/-/issues/3267#note_2033550
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: https://gitlab.gnome.org/GNOME/glib/-/issues/3267
It turns out that the workaround in 7b380b2ffc was insufficient.
During initialization, we end up calling apply_monitor_changes()
while xdg_output is set, but xdg_output_geometry isn't. Be more
careful and prevent that from wreaking havoc with negative scales.
Fixes: #6472
unsigned char is promoted to int, which lacks the 32nd bit to
make 0xff << 24 work. Explicitly cast to unsigned int to make
it clear what we want to happen.
Unspecified attributes are not interpreted as "leave this feature out",
rather as "pick a default value". For depth, stencil and accum bits the
defaults may be different than 0. For example, with AMD drivers we get:
* WGL_DEPTH_BITS_ARB: 32
* WGL_STENCIL_BITS_ARB: 8
* WGL_ACCUM_BITS_ARB: 0
Set the attributes to 0 as a hint that depth, stencil and accum buffers
should not be created.
The driver may still create them (matching criteria is "minimum" [1]),
but that's outside of our control (and unlikely to happen).
References:
[1] - WGL_ARB_pixel_format specification
https://registry.khronos.org/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt
See #6401
This fixes monitor enter and leave events on X11, and probably other
things. Previously, it looks like the coordinates were relative to the
top left corner of the window shadow and so never changed.
With our custom logic out of the way, this just works.
Maximized state is also update on move, since a moved maximized
window is no longer considered maximized in macOS land.
In macOS, when moving a maximized window, it's not automatically
restored to its default size.
In addition, GdkMacosWindow should not check surface layout properties,
since those properties are lagging, e.i. are set after the (native)
window state has been updated.
GdkSurface maintains state that shadows the actual window state.
This state is not always updated in the macos backend.
In our case, when a window is initially maximized, `setFrame:display:`
was called and `inMaximizeTransition` was set. However,
`windowDidEndLiveResize:` was never called and `inMaximizeTransition`
was never unset, making the application think the window is still
maximized.
Additionally, `windowShouldZoom:toFrame:` is only called when the window
is maximized, not when it's unmaximized.
By checking and setting the state in `windowDidResize:` we can at least
be sure that the internal maximized state is only set if the window
takes up all desktop space: the screen's visible frame.
Currently dmabuf_dep is found when the following conditions are met:
- linux/dma-buf.h is present;
- libdrm is found.
This is because Linux dmabuf support requires drm_fourcc.h which is part
of libdrm.
However, dmabuf_dep is used for two purposes:
- define HAVE_DMABUF to state dmabuf support;
- ensure the presence of drm_fourcc.h for gdk and for the
media-gstreamer module.
Decouple this, unconditionally check for libdrm and require it on
Linux. Then, use libdrm_dep only to state the drm_fourcc.h presence.
Given that now we unconditionally require libdrm on Linux, HAVE_DMABUF
depends only on the linux/dma-buf.h presence.
This will let us use a subset of the full texture, which can
be necessary in the case that converters put padding around
content in dmabufs. The naming follows the Wayland viewporter
spec.
For now, make all callers pass the full texture rect.
We are going to introduce another rect, so better to be clear in
naming. We are following the naming of the Wayland viewporter spec
and call the rectangle that we drawing into the dest(ination).
Random code can call that function and cause unexpected GL context
changes. This is especially bad because it can happen nested.
Fixes the NGL renderer breaking in the inspector when importing a dmabuf
initializes the dmabuf backend which creates a GL renderer which creates
a GL context and makes it current causing the NGL renderer to break when
it continues rendering.
Fixes#6398
The 'icon_list' implementation of gtk+3 was somehow dropped
during the early conversion of GdkWindow to GdkSurface for gtk4.
Add it again, with minor tweaks to support GdkSurface.
Share the GdkTexture-to-HICON internal API with GdkCursor.
This allows 'gtk_window_set_icon_name()' to work on win32.
Expose information about if an event is handled to the backends.
This will allow a backend to deal with unhandled events, such as
macOS' default key bindings.
The first time this function is called, has_xdg_output() returns
true, but haven't yet received all the xdg-output events, so wait
for that to be done. Otherwise, the logical size is 0, and nothing
useful comes from that.
This fixes a problem that is apparent in
https://bugzilla.mozilla.org/show_bug.cgi?id=1869724, but that also
reproduces on any GTK application as described in
https://bugzilla.mozilla.org/show_bug.cgi?id=1869724#c16.
xdg_output sizes might be physical if the compositor doesn't scale them,
it seems. So to report the correct logical geometry in GDK pixels, we
need to detect this case. We do this by checking whether the wl_output
size matches the xdg_output size.
According to the Mesa developers, the correct way to determine
disjointness is to check the actual inode of the fd because dup()ing can
cause these duplications to happen when planes are carelessly copied or
when planes are sent over dbus or other unix sockets.
Related: https://bugs.webkit.org/show_bug.cgi?id=267578
We keep various pieces of double-buffered state on our side,
and then explicitly sync it over to the Wayland side.
Add a function to find out if we have any.
The ngl renderer has good support for fractional scaling, so we
can enable this by default now.
If you are using the gl renderer, you can disable fractional
scaling with the
GDK_DEBUG=gl-no-fractional
environment variable.
When a toplevel is focused programmatically and there is no
underlying seat, we cannot attempt to focus it with no
focus to be obtained, nor serials serials to use.
Related: https://gitlab.gnome.org/GNOME/gtk/-/issues/6335
In GLES, BGRA is still done by GL_EXT_texture_format_BGRA8888 which is
an extension that is older than GLES 2.0.
And back then, internal formats had to be specified unsized. And when
that was changed with GLES3, nobody updated the extension.
However, on OpenGL, this extension doesn't exist, and internal formats
need to be sized.
So let's use different internal formats depending on GL version.
Fixes#6333
Whether or not switches include shapes to indicate their ON/OFF
state is currently controlled by the stylesheet (in particular
the HighContrast style).
However there are use cases for both using the HighContrast style
without shapes, and for using shapes with the regular stylesheet,
so follow the newly added "show-status-shapes" setting instead.
https://gitlab.gnome.org/GNOME/gtk/-/issues/5354
For tablet tools if we have NULL cursor, we use the default cursor
instead. This provides us with a tablet cursor when an application never
sets the cursor.
However, on proximity out when we clear said cursor we also
need to toggle off cursor_is_default, otherwise on the next proximity in
we assume we already have a cursor and never update it again.
This leads to an invisible cursor over GTK application when the tablet
tool is brought into proximity over the widget (but not when moving into
the widget from the outside).
Closes: #6312
If shaders don't support nonuniform indexing, we emulate it via if/else
ladders (or switch ladders) which get inlined by the GLSL compiles and
massively blow up the code.
And that makes compilation of the shaders take minutes and results in
shader code that isn't necessarily faster.
So we disable it on GL entirely and on Vulkan if the required features
aren't available.
As it's only an optimization and does not fall back to Cairo anymore,
this should be fine.
gdk_texture_save_to_png_bytes() cannot fail, so ensure that it doesn't.
Testsuite has been updated to check for this case.
Note that we do not load the PNG file that we generate here.
Loading is a lot more scary than saving after all.
If people want to load oversized PNG files, they should use a real PNG
loader.
This is using the Vulkan renderer.
It also allows claiming support for all the formats that only Vulkan
supports, but that neither GL nor native mmap can handle.
I did it because it unifies the code.
But it also gains the benefit of being debuggable because it can
now be turned off via GDK_VULKAN_SKIP=incremental-present
This ensures both that we signal a semaphore for a dmabuf when we export
an image and that we import semaphores for dmabufs and wait on them.
Fixes Vulkan node-editor displaying the Vulkan renderer in the sidebar.
This code does not add a downloader, so we do not claim support for all
the new formats.
It just queries the formats. But this can be used to import dmabufs
directly into the Vulkaan renderer.
use it to collect the optional features we are interested in and turn
them on only if available.
For now we add the dmabuf features, but we don't use them yet.
According to EXT_color_buffer_half_float it should be renderable, but it
fails to glGenerateMipmap() with Mesa 23.3 so just pretend it's not
renderable until that is fixed.
Fixes CI from failing.
I naively assumed the EXT_color_buffer_float and
EXT_color_buffer_half_float extensions would mirror each other, but they
do not. The float extension explicitly excludes RGB32F from the
renderable formats.
Doing this in a way that is picked up by gobject-introspection
requires splitting off new enum members into separate doc
comments, which is a bit unfortunate.
Some dmabuf formats were added in Vulkan 1.3.
Note that this does not require the Vulkan drivers to be version 1.3 -
it just means compilation against libvulkan 1.3
This makes no sense by itself, but we want to create the EGLImage at
DmabufTexture construction so that we can actually reject dmabufs that
we can't create EGLImages for.
This will make it possible to bail when the stride limitation for AMD
GPUs hits.
Instead of having an add_formats() function, make the get_downloader()
function add the formats.
This allows putting the actual downloader in a different place from the
initialization code.
This is done without testing, just doing my best to map all the DRM
formats to VkFormats.
Once people start using them, they'll figure it out when it's wrong.
(Somebody needs to write a testsuite.)
When we use the builtin downloads via mmap(), it's a special case where
we don't need to initialize subsystems and query them for support. We
know what we can and can't do.
Also, we want to use these formats with the lowest priority but pick the
downloader first for supported formats, and queueing it in the
downloaders list doesn't reflect that. So don't do it.