This is an alternative to gdk_surface_create_gl_context() when the
context is meant to only draw to textures.
This is useful in the testsuite or in GStreamer or with GLArea,
basically whenever we want to do GL stuff but don't need to actually
draw anything on screen.
A bunch of code will need to be updated to deal with context->surface
being NULL.
The term "hdr" is so overloaded, we shouldn't use them anywhere, except
from maybe describing all of this work in blog posts and other marketing
materials.
So do renames:
* hdr => high_depth
* request_hdr => prefers_high_depth
This more accurately describes what is going on.
If EGL supports:
* no-config contexts
* >8bits pixel formats
* (optionally) floating point pixel formats
Then select such a profile as the HDR format and use it when HDR is
requested.
Now that we have the display's context to hook into, we can use it to
construct other GL contexts and don't need a GdkSurface vfunc anymore.
This has the added benefit that backends can have different GdkGLContext
classes on the display and get new GLContexts generated from them, so
we get multiple GL backend support per GDK backend for free.
I originally wanted to make this a vfunc on GdkGLContextClass, but
it turns out all the abckends would just call g_object_new() anyway.
... or more exactly: Only use paint contexts with
gdk_cairo_draw_from_gl().
Instead of paint contexts being the only contexts who call swapBuffer(),
any context can be used for this, when it's used with
begin_frame()/end_frame().
This removes 2 features:
1. We no longer need a big sharing hierarchy. All contexts are now
shared with gdk_display_get_gl_context().
2. There is no longer a difference between attached and non-attached
contexts. All contexts work the same way.
The vfunc is called to initialize GL and it returns a "base" context
that GDK then uses as the context all others are shared with. So the GL
context share tree now looks like:
+ context from init_gl
- context1
- context2
...
So this is a flat tree now, the complexity is gone.
The only caveat is that backends now need to create a GL context when
initializing GL so some refactoring was needed.
Two new functions have been added:
* gdk_display_prepare_gl()
This is public API and can be used to ensure that GL has been
initialized or if not, retrieve an error to display (or debug-print).
* gdk_display_get_gl_context()
This is a private function to retrieve the base context from
init_gl(). It replaces gdk_surface_get_shared_data_context().
Remove a boatload of "or %NULL" from nullable parameters
and return values. gi-docgen generates suitable text from
the annotation that we don't need to duplicate.
This adds a few missing nullable annotations too.
At times (most often when closing subsurfaces that are scheduling
relayouts) the PHASE_PAINT handling gets broken with the following
sequence:
1. Surface receives wl_callback.done for the previous frame.
Surface is thawed.
2. A new update on the surface is scheduled. PHASE_PAINT is
requested directly on the frame clock. priv->pending_phase is
left unset in the surface.
3. Surface gets frozen
4. Frame clock processes the update scheduled at 2. The surface
is frozen, so paint is prevented. PHASE_PAINT is considered
handled.
5. Compositor emits wl_callback.done again. Surface is thawed.
6. At this point the machinery is off
- The surface didn't paint but has pending update regions
- priv->draw_needed is set in the toplevel and other portions
of the widget tree
- So queueing redraws is ineffective at eventually calling
gdk_surface_schedule_update() again on the toplevel surface.
- We don't paint anymore, so this broken state is not flushed
until other subsurface changes manage to schedule the missing
update.
To fix this, always set PHASE_PAINT in priv->pending_phase when
doing gdk_surface_schedule_update(). If the frame clock turns
around before the surface is thawed, it will still be waiting to
be processed the next iteration.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3750
This is a more reliable calling point than ::resume-events, and a
good one to schedule things so they happen on a frame clock in no
special phase (Thus still fixing the original issue at 80d4a08e30)
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3461
Those requests are received while dealing with the ::layout frame
clock phase, this has the unintended side effect of making the
frame clock "rewind" to handle ::flush-events again during this
frame, which delays everything and practically halves the frame
rate.
We do intend to make the motion events dispatches on the next frame,
so do this in an idle at a slightly lower priority than layout/draw,
so the ::flush-events phase is actually requested for the next frame.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3264
It was used by all surfaces to track 'is-mapped', but still part of the
GdkToplevelState, and is now replaced with a separate boolean in the
GdkSurface structure.
It also caused issues when a widget was unmapped, and due to that
unmapped a popover which hid its corresponding surface. When this
surface was hidden, it emitted a state change event, which would then go
back into GTK and queue a resize on popover widget, which would travel
back down to the widget that was originally unmapped, causing confusino
when doing future allocations.
To summarize, one should not hide widgets during allocation, and to
avoid this, make this new is-mapped boolean asynchronous when hiding a
surface, meaning the notification event for the changed mapped state
will be emitted in an idle callback. This avoids the above described
reentry issue.
If compute_size() returns TRUE, the layout will not be propagated to
GTK. This will be used by the X11 backend to queue asynchronous resizes
that shouldn't yet allocate in GTK.
The allocation of popups are part dependent of the allocation of the
root, which means the root must still be allocated when updates are
frozen, otherwise we'll try to allocate non-laid out popups.
This removes the GDK_CONFIGURE event and all related functions and data
types; it includes untested changes to the MacOSX, Win32 and Broadway
backends.
This removes the gdk_surface_set_shadow_width() function and related
vfuncs. The point here is that the shadow width and surface size can now
be communicated to GDK atomically, meaning it's possible to avoid
intermediate stages where the surface size includes the shadow, but
without the shadow width set, or the other way around.
If a surface scheduled a relayout, got frozen, and a layout phase
happened, then got unfrozen, it wouldn't see it's layout being
requested; avoid this race by remembering the pending phases until they
actually happened.
Don't have GtkRoot listen directly to the layout signal on the frame
clock, but let it pass through GdkSurface. This will allow GdkSurface to
be more involved in the layout phase.
Scheduling an update when frozen would reschedule when unfrozen; change
this to a generic pending phase enum, and use this for resrcheduling
paint and compute-size.