Sometimes a scheduled render can end up doing nothing, e.g. if the
damage region is empty. In that case we don't have valid data to
collect and thus shouldn't update the statistics.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Add a render_statistics type to encapsulate all the statistics done on
rendering times. And use that to estimate the time budget for rendering
and frame pacing.
Tweak the rolling window utilities a bit so we can reuse one rolling
window for multiple statistics.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
We only checked render time. If we don't have frame time estimates, we
would divide by zero and end up with wild scheduling delays.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
So when the screen is off, we calls queue_redraw, hoping draw_callback
will be called and unredirects the screen. However, queue_redraw doesn't
queue another redraw when one is already queued. Redraws can be queued
in two ways: one is timer based, which is fine, because it will be
triggered no matter what; the other is frame based, which is triggered
by Present events.
When the screen is off, X server, depends on the driver, could send
abnormal Present events, which we ignore. But that also means queued
frame based redraw will stop being triggered.
Those two factors combined means sometimes unredirection does not happen
when the screen is off. Which means we aren't going to free the GL
context, which are still receiving Present events, but can't handle
them, because we are not rendering anything with GL. In the end all
these causes memory usage to balloon, until the screen is turned on and
we start rendering again.
And all these is not caught by leak checkers because this technically is
not a leak, as everything is eventually freed.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Sometimes X sends bogus complete notifies with invalid msc number.
Instead use a saved msc number to get the next complete notify.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Timer can sometimes drift randomly, like when the system is suspended.
we don't want to disable frame pacing for that
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
When the screen turns off, X sometimes sends present complete notify for
the same frame multiple times, or even events with invalid msc/ust
number.
This will cause us to ignore it and not send a subsequent NotifyMsc
request, causing the complete notify to stop.
Now we send NotifyMsc regardless to keep the events going.
Also detect when the complete notifies skip frames, divide the interval
by frame count to estimate frame time in that case.
Upstream bug report:
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1418
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Use frame timing and render time statistic to pace frames.
Right now the criteria are simple:
* Don't render multiple frames in one vblank cycle. Otherwise the
rendered frame will be delay multiple cycles, which isn't ideal.
* Start rendering as late as possible while still hitting vblank.
Refresh rate is estimated from a rolling average of frame timing. Render
time is predicted from the rolling maximum of past 128 frames. The
window size still needs to be investigated.
Remove glFinish calls and GL_MaxFramesAllowed=1, frame pacing superseeds
them.
Professionals might laugh at how rudimentary this is, but hopefully this
is better than what we had before. Which is absolutely nothing at all.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
there are two x extensions for working with monitors (especially
multiple): xinerama and randr. xinerama is old, feature-poor and in
general isn't used anymore compared to the randr: new, feature-rich and
widely-used. for some reason we were using both of them, so let's drop
xinerama to keep things simple, clean and small. and to be modern.
the drop was done in three steps:
* first step was to replace all the xinerama-based code with the
randr-based one and to replace or remove all the xinerama mentions;
* second step was to replace the xinerama's terminology with the
randr's one. xinerama was referring only to the word "screen", while
randr refers to multiple words and i think the word "monitor" is the
most suitable for us and, hopefully, clear both to a contributor and
to an end user;
* third step was to refactor the new randr-based code if needed and to
address related todo's (mostly about moving related functions
elsewhere).
all the steps were done well except addressing a leftover todo about
moving the win_update_monitor function to the x.c which wasn't done.
the xinerama-shadow-crop option was renamed to crop-shadow-to-monitor,
but it's previous name is still accepted, has effect and the
deprecation message is printed to preserve backwards-compatibility.
Use the DPMS extension to detect if screen is turned off, and unredirect
if it is. This also helps working around the problem where OpenGL
buffers lose data when screen is turned off, causing screen to flicker
later when it turns back on if use-damage is enabled.
Unfortunately the DPMS extension doesn't define an event, so we have to
periodically poll the screen state.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
We used to have a list of X errors we should ignore in case they do
occur. This commit expands that functionality to also allow us aborting
on certain errors.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Transparent clipping interacts poorly with programs whose transparent
interface elements must show windows below them for functionality,
for example screenshot utilities.
This needs the EGL_KHR_image_pixmap and the GL_EXT_EGL_image_storage
extensions, which unfortunately aren't available on NVIDIA cards.
Don't add documentation for these, for now.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
I also noticed there is an opportunity to unify fades, animated shaders,
and the benchmark mode. We should be able to get rid of the fade timer.
A TODO for the future.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Used for setting custom window shaders and rules for choosing custom
window shaders.
Added a "c2_userdata_free" parameter to c2_list_free, so allocated userdata
stored in nodes can be freed.
Signed-off-by: Bernd Busse <bernd@busse-net.de>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
It was deprecated in v6, but wasn't formally deprecated back then (e.g.
no warnings were printed for it). So formally deprecate it here.
This also left the refresh-rate option unused, so that will be
deprecated too.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
There were a few improper uses of %ld for 64 bit numbers, as well as
some other 32 bit related warnings that I've fixed.
Signed-off-by: ktprograms <ktprograms@gmail.com>
Explicitly set `xinerama_scr_regs` to `NULL` after calling free() to
avoid freeing them again.
Under normal operation we free the old xinerama screen region list on
root screen changes and allocate a new one with the updated regions.
On rare occasions — mainly reproducable by changing monitors while DPMS
is in standby — updating the region list might fail as for whatever
reason the xinerama extension is marked as inactive. This would leave
us with an invalid pointer to the already freed region list we would
then attempt to free again on the next root screen change.
Added the new `clip-shadow-above` configuration and wintype option.
These allow the user to select windows to clip from the shadow region of
other windows, i.e. don't paint shadows on top of them.
This should provide a more useful and userfriendly alternative to the
deprecated `shadow-exclude-reg` option — especially for docks and bars.
If the user has no access to the GPU, initialization of the GLX context
fails. In the legacy backend, this occurs BEFORE the session has been
successfully initialized.
At this point we cannot meaningfully filter xerrors as the session
hasn't been initialized yet. So we don't try to.
Currently there is some inconsistency in how image_op is implemented
across backends. The glx backend applies some of the image operations
lazily, and not always in the order the operations were made; while the
xrender backend applies the operations eagerly. This can lead to
different render result in some cases.
Instead of trying to preserving the order of operations, which would be
unnecessary, we re-model the API to better reflect the implementation.
We make it clear that setting the property doesn't change the image
data, and properties are only applied during composition and in a
specific order.
This makes sure the render result looks consistent across backends.
Should also improve the performance of the xrender backend, even if only
slightly.
Also distill out the property management code so they can be shared.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Since commit 95a64acf5a, fill_win doesn't
set the window geometry anymore, so we can't use it in
handle_new_windows.
However, we don't need to add damage in handle_new_windows anyway,
damage will be added later when the MAPPED flag is handled.
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Consider these 2 cases:
* A window is mapped while fading out
* A window is mapped and damaged while fading out
From the perspective of map_win_start, these 2 cases look the same. The
window will has ever_damage = true in both cases. However, map_win_start
has to distinguish between these 2 cases, because at the end of
map_win_start, window in the first case cannot have ever_damage = true,
while window in the second case should have ever_damage = true.
Currently, map_win_start always clears ever_damage in both cases
(indirectly through win_skip_fading), which causes windows in the second
case to not be rendered when they should be.
This commit move clearing of ever_damage from unmap_win_finish to
unmap_win_start, so when map_win_start sees ever_damage = true, it's
always to second case. And to make sure windows which are fading out are
still rendered, we relax the ever_damage check in paint_preprocess to
also accept windows that are fading out. (see code comment for
explanation why this is fine)
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>