Treat first frame after redirection differently

Because first frame no window has their pixmap bound, which doesn't
happen in frames after the first. If a window is unmapped in that frame,
the compositor will try to render a window with no pixmap bound if
fading is enabled.

Now we keep track if we are in the first frame, and if that's the case
we skip fading in unmap/destroy.

Fixes #239, bug number 2

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-09-29 00:11:32 +01:00
parent f493447b33
commit a69ed89114
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
2 changed files with 18 additions and 0 deletions

View File

@ -210,6 +210,8 @@ typedef struct session {
#endif
/// Sync fence to sync draw operations
xcb_sync_fence_t sync_fence;
/// Whether we are rendering the first frame after screen is redirected
bool first_frame;
// === Operation related ===
/// Flags related to the root window

View File

@ -1212,6 +1212,7 @@ static bool redirect_start(session_t *ps) {
x_sync(ps->c);
ps->redirected = true;
ps->first_frame = true;
// Re-detect driver since we now have a backend
ps->drivers = detect_driver(ps->c, ps->backend_data, ps->root);
@ -1378,6 +1379,20 @@ static void handle_pending_updates(EV_P_ struct session *ps) {
static void _draw_callback(EV_P_ session_t *ps, int revents attr_unused) {
handle_pending_updates(EV_A_ ps);
if (ps->first_frame) {
// If we are still rendering the first frame, if some of the windows are
// unmapped/destroyed during the above handle_pending_updates() call, they
// won't have pixmap before we rendered it, causing us to crash.
// But we will only render them if they are in fading. So we just skip
// fading for all windows here.
//
// Using foreach_safe here since skipping fading can cause window to be
// freed if it's destroyed.
win_stack_foreach_managed_safe(w, &ps->window_stack) {
auto _ attr_unused = win_skip_fading(ps, w);
}
}
if (ps->o.benchmark) {
if (ps->o.benchmark_wid) {
auto w = find_managed_win(ps, ps->o.benchmark_wid);
@ -1428,6 +1443,7 @@ static void _draw_callback(EV_P_ session_t *ps, int revents attr_unused) {
paint_all(ps, bottom, false);
}
ps->first_frame = false;
paint++;
if (ps->o.benchmark && paint >= ps->o.benchmark)
exit(0);