This avoids a bunch of allocations, and additionally it has better
cache behaviour, as we don't follow pointers to the separate GList
node memory areas during traversal.
From Christian Hergert:
This machine is a Retina mac book pro so I've been working on getting
GtkTextView (GtkPixelCache) up to our performance level on
X11/Wayland. I'm seeing a jump from about 43 FPS to about 50 FPS.
https://bugzilla.gnome.org/show_bug.cgi?id=754687
An pass_through window is something you can draw in but does not
affect event handling. Normally if a window has with no event mask set
for a particular event then input events in it go to its parent window
(X11 semantics), whereas if pass_through is enabled the window below
the window will get the event. The later mode is useful when the
window is partially transparent. Note that an pass-through windows can
have child windows that are not pass-through so they can still get events
on some parts.
Semantically, this behaves the same as an regular window with
gdk_window_set_child_input_shapes() called on it (and re-called any
time a child is changed), but its far more efficient and easy to use.
This allows us to fix the testoverlay input stacking test.
https://bugzilla.gnome.org/show_bug.cgi?id=750568https://bugs.freedesktop.org/show_bug.cgi?id=90917
If we are disconnecting from a frame clock that has paused event
processing and hasn't issued a resume yet make sure we resume the
events or they will stay blocked forever.
https://bugzilla.gnome.org/show_bug.cgi?id=742636
This is required for the X backend GL integration. If the
window has a height that is not a multiple of the window scale
we can't properly do the y coordinate flipping that GL needs.
Other backends can ignore this and use the default implementation.
https://bugzilla.gnome.org/show_bug.cgi?id=739750
We need to export the symbols so they can be used in the
inspector, but we don't really want to make this supported
public API, so keep them out of installed headers.
This moves the GDK_ALWAYS_USE_GL env var to GDK_GL=always.
It also changes GDK_DEBUG=nogl to GDK_GL=disable, as GDK_DEBUG
is really only about debug loggin.
It also adds some completely new flags:
software-draw-gl:
Always use software fallback for drawing gl content to a cairo_t.
This disables the fastpaths that exist for drawing directly to
a window and instead reads back the pixels into a cairo image
surface.
software-draw-surface:
Always use software fallback for drawing cairo surfaces onto a
gl-using window. This disables e.g. texture-from-pixmap on X11.
software-draw:
Enables both the above.
This is mostly useful for fallback testing.
I suppose if people want finer grained GL ability testing, they can use
Mesa environment variables to tune things.
This adds the new type GdkGLContext that wraps an OpenGL context for a
particular native window. It also adds support for the gdk paint
machinery to use OpenGL to draw everything. As soon as anyone creates
a GL context for a native window we create a "paint context" for that
GdkWindow and switch to using GL for painting it.
This commit contains only an implementation for X11 (using GLX).
The way painting works is that all client gl contexts draw into
offscreen buffers rather than directly to the back buffer, and the
way something gets onto the window is by using gdk_cairo_draw_from_gl()
to draw part of that buffer onto the draw cairo context.
As a fallback (if we're doing redirected drawing or some effect like a
cairo_push_group()) we read back the gl buffer into memory and composite
using cairo. This means that GL rendering works in all cases, including
rendering to a PDF. However, this is not particularly fast.
In the *typical* case, where we're drawing directly to the window in
the regular paint loop we hit the fast path. The fast path uses opengl
to draw the buffer to the window back buffer, either by blitting or
texturing. Then we track the region that was drawn, and when the draw
ends we paint the normal cairo surface to the window (using
texture-from-pixmap in the X11 case, or texture from cairo image
otherwise) in the regions where there is no gl painted.
There are some complexities wrt layering of gl and cairo areas though:
* We track via gdk_window_mark_paint_from_clip() whenever gtk is
painting over a region we previously rendered with opengl
(flushed_region). This area (needs_blend_region) is blended
rather than copied at the end of the frame.
* If we're drawing a gl texture with alpha we first copy the current
cairo_surface inside the target region to the back buffer before
we blend over it.
These two operations allow us full stacking of transparent gl and cairo
regions.
First of all we track the current update area during an
update in window->active_update_area. This will be used later
in end_paint to know the damaged area.
Secondly we keep track of old update areas for the last 2
frames. This will later allow us to reuse old framebuffer
contents in double or tripple buffer setups, only painting
what has changed since then.
gdk_x11_display_set_window_scale() affects the interpretation of the
Xft/DPI XSETTING - it is substituted inside GDK with the value of
Gdk/UnscaledDPI xsetting. However, this change is not propagated to
GTK+ and from GTK+ back to gdk_screen_set_resolution() until the
main loop is run.
Fix this by handling the screen resolution directly in gdk/x11.
This requires duplication of code between GDK and GTK+ since we still
have to handle DPI in GTK+ in the case that GdkSettings:gtk-xft-dpi
is set by the application.
https://bugzilla.gnome.org/show_bug.cgi?id=733076
Previously, each begin_paint_region added to a stack of current paints,
and when end_paint was called, the paint was popped off of the stack and
the surface was composited into the parent paint surface.
However, the code was broken in the case of a backend like Wayland which
didn't keep track of nested calls and simply wiped and returned the
native impl backing surface every time.
Since this feature is flat out unused by GTK+ and we don't want to
really support tricksy things like these for other clients, just remove
the feature. If somebody does call begin_paint_region more than once,
warn and return without doing anything.
Traditionally, the way painting was done in GTK+ was with the
"expose-event" handler, where you'd use GDK methods to do drawing on
your surface. In GTK+ 2.24, we added cairo support with gdk_cairo_create,
so you could paint your graphics with cairo.
Since then, we've added client-side windows, double buffering, the paint
clock, and various other enhancements, and the modern way to do drawing
is to connect to the "draw" signal on GtkWidget, which hands you a
cairo_t. To do double-buffering, the cairo_t we hand you is actually on
a secret surface, not the actual backing store of the window, and when
the draw handler completes we blit it into the main backing store
atomically.
The code to do this is with the APIs gdk_window_begin_paint_region,
which creates the temporary surface, and gdk_window_end_paint which
blits it back into the backing store. GTK+'s implementation of the
"draw" signal uses these APIs.
We've always sort-of supported people calling gdk_cairo_create
"outside" of a begin_paint / end_paint like old times, but then you're
not getting the benefit of double-buffering, and it's harder for GDK to
optimize.
Additionally, newer backends like Mir and Wayland can't actually support
this model, since they're based on double-buffering and swapping buffers
at various points in time. If we hand you a random cairo_t, we have no
idea when is a good time to swap.
Remove support for this.
This is technically a GDK API break: a warning is added in cases where
gdk_cairo_create is called outside of a paint cycle, and the returned
surface is a dummy that won't ever be composited back onto the main
surface. Testing with complex applications like Ardour didn't produce
any warnings.
Wayland's mechanism tells us all of our new states, rather than
telling us which ones were added and removed. Add a new private
interface so that we can simply specify the new states as a
bitfield directly rather than having to compute which ones were
added and removed.
If a motion event handler (or other handler running from the flush-events
phase of the frame clock) recursed the main loop then flushing wouldn't
complete until after the recursed main loop returned, and various aspects
of the state would get out of sync.
To fix this, change flushing of the event queue to simply mark events as
ready to flush, and let normal event delivery handle the rest.
https://bugzilla.gnome.org/show_bug.cgi?id=705176
Setting event compression to false will allow inter-frame
mouse motion events to be delivered, which are necessary
for painting applications to produce smooth strokes.
https://bugzilla.gnome.org/show_bug.cgi?id=702392
We've long had double precision mouse coordinates on wayland (e.g.
when rotating a window) but with the new scaling we even have it on
X (and, its also in Xinput2), so convert all the internal mouse/device
position getters to use doubles and add new accessors for the
public APIs that take doubles instead of ints.
We don't track the full clip for each window anymore, as this
is not useful when no windows are opaque. However, we still
need the full clip for the shape, so its calculated manually.
However, it was previously only recalculated when the clip changes
which doesn't correctly handle the case of a sibling geometry changing.
So, instead of doing this directly when geometry changes we just
set a bit in the toplevel whenever some window geometry changes, and
we then handle this in process_updates, updating the shape for all
native windows. This should be ok performance-wise because we don't
expect a lot of native children.
This removes the typechecks in GDK_WINDOW_TYPE and GDK_WINDOW_DESTROYED. These
are only used internally in gdkwindow.c and gdkdisplay.c anyway, and these
functions check for typesafety of arguments on function entry.
This lets you register callbacks for when child widgets invalidate
areas of the window read it and/or change it.
For instance, this lets you do rendering effects and keeping offscreen
caches uptodate.
We now only do one expose event per native window, so there will
only be one begin/end_paint() call. This means all the work with
implicit paints to combine the paints on a single double buffer
surface is unnecessary, so we can just delete it.
Since we're not exporting the ability to create your own frame
clock for now, remove the setters for GdkFrameTimings fields.
Also remove all setters and getters for fields that are more
about implementation than about quantities that are meaningful
to the applcation and just access the fields directly within
GDK.
Now that GdkFrameClock is a class, not interface, there's no real advantage
to splitting the frame history into an aggregate object, so directly
merge it into GdkFrameClock.
When we have pending motion events, instead of delivering them
directly, request the new FLUSH_EVENTS phase of the frame clock.
This allows us to compress repeated motion events sent to the
same window.
In the FLUSH_EVENTS phase, which occur at priority GDK_PRIORITY_EVENTS + 1,
we deliver any pending motion events then turn off event delivery
until the end of the next frame. Turning off event delivery means
that we'll reliably paint the compressed motion events even if more
have arrived.
Add a motion-compression test case which demonstrates behavior when
an application takes too long handle motion events. It is unusable
without this patch but behaves fine with the patch.
https://bugzilla.gnome.org/show_bug.cgi?id=685460
We now store the current opacity for all windows. For native windows
we just call into the native implementation whenever the opacity changes.
However, for non-native windows we implement opacity by pushing a
second implicit paint that "stacks" on the existing one, acting as
an opacity group while rendering the window and its children.
This works well in general, although any native child windows will of
course not be opaque. However, there is no way to implement
implicit paint flushing (i.e. draw the currently drawn double buffer
to the window in order to allow direct drawing to the window).
We can't flush in the stacked implicit paint case because there
is no way to get the right drawing behaviour when drawing directly
to the window. We *must* draw to the opacity group to get the right
behaviour.
We currently flush if:
* A widget disables double buffering
* You call move/resize/scroll a window and it has non-native children
during the expose handler
In case this happens we warn and flush the outermost group, so there may
be drawing errors.
https://bugzilla.gnome.org/show_bug.cgi?id=687842