When directly scanning out game buffers, we need to make sure the game
buffer is suitable for scanout. If that's not the case, we need to
fallback to composition.
The fallback path was implemented, but we never checked whether scan-out
is possible in drm_can_avoid_composite. Perform an atomic test-only
commit to fix this.
wlroots headers can mostly be included with extern "C" blocks. Two
exceptions are the use of `static` for array args and `class` as a
struct field. These can be #define'ed to avoid C++ build errors.
This allows the whole project to be built as a single C++ codebase,
without having to maintain hybrid header files.
This commit fixes two issues.
A first issue is that fbids_in_req was previously populated
drm_can_avoid_composite and read from in page_flip_handler. As a
result, calling drm_can_avoid_composite then page_flip_handler would
prevent drm_atomic_commit from referencing the right FBs
(page_flip_handler runs in a separate thread and clears fbids_in_req).
To fix this, add a new fbids_queued vector filled by drm_atomic_commit.
Make page_flip_handler read from this new vector instead of
fbids_in_req. As a bonus, this fixes a data race since fbids_queued is
now protected by flip_lock.
The second issue is that drm_can_avoid_composite assumes all layers made
it into a hw plane when liftoff_output_apply succeeds. That's not the
case because libliftoff supports mixed hw plane + composition (where
some layers make it into a hw plane and the others get composited).
To fix this, make drm_can_avoid_composite fail if some but not all
layers make it into a hw plane. In the future, we'll want to support the
mixed mode too.
Closes: https://github.com/Plagman/gamescope/issues/65
References: https://github.com/Plagman/gamescope/issues/41
Only works when switching to fbcon for now. We need to stop
page-flipping when the DRM FD is paused to support switching to another
compositor.
References: https://github.com/Plagman/gamescope/issues/6
win objects are allocated with `new`, so they need to be de-allocated
with `delete` instead of `free`.
==589398==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x61200017f140
(EE) failed to read Wayland events: Broken pipe
X connection to :1 broken (explicit kill or server shutdown).
#0 0x7f5468ae4720 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
#1 0x559820f5c9a0 in finish_destroy_win ../src/steamcompmgr.cpp:1743
#2 0x559820f5ca6d in destroy_win ../src/steamcompmgr.cpp:1759
#3 0x559820f6163e in steamcompmgr_main ../src/steamcompmgr.cpp:2288
#4 0x559820f8e977 in steamCompMgrThreadRun() ../src/main.cpp:121
#5 0x559820f8e3e9 in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:60
#6 0x559820f8e24f in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:95
#7 0x559820f8e0b3 in void std:🧵:_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/9.3.0/thread:244
#8 0x559820f8dfae in std:🧵:_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/9.3.0/thread:251
#9 0x559820f8d7ba in std:🧵:_State_impl<std:🧵:_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/9.3.0/thread:195
#10 0x7f5468006b23 in execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80
#11 0x7f546745346e in start_thread (/usr/lib/libpthread.so.0+0x946e)
#12 0x7f54673833d2 in clone (/usr/lib/libc.so.6+0xff3d2)
0x61200017f140 is located 0 bytes inside of 296-byte region [0x61200017f140,0x61200017f268)
allocated by thread T40 here:
#0 0x7f5468ae6968 in operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cc:104
#1 0x559820f595fe in add_win ../src/steamcompmgr.cpp:1548
#2 0x559820f614e8 in steamcompmgr_main ../src/steamcompmgr.cpp:2278
#3 0x559820f8e977 in steamCompMgrThreadRun() ../src/main.cpp:121
#4 0x559820f8e3e9 in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:60
#5 0x559820f8e24f in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:95
#6 0x559820f8e0b3 in void std:🧵:_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/9.3.0/thread:244
#7 0x559820f8dfae in std:🧵:_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/9.3.0/thread:251
#8 0x559820f8d7ba in std:🧵:_State_impl<std:🧵:_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/9.3.0/thread:195
#9 0x7f5468006b23 in execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80
Thread T40 created by T0 here:
#0 0x7f5468a0e377 in __interceptor_pthread_create /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cc:208
#1 0x7f5468006df9 in __gthread_create /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663
#2 0x7f5468006df9 in std:🧵:_M_start_thread(std::unique_ptr<std:🧵:_State, std::default_delete<std:🧵:_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135
#3 0x559820f8ea10 in startSteamCompMgr ../src/main.cpp:126
#4 0x559820f95cfb in xwayland_ready ../src/wlserver.c:119
#5 0x5598210de191 in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
#6 0x559820ff596b in xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:251
#7 0x7f5468744434 (/usr/lib/libwayland-server.so.0+0xa434)
#8 0x7ffc9796869f ([stack]+0x1f69f)
Activate libliftoff's internal log when layers are enabled and the parameter
'd' is provided.
Note: this needs some patches to libliftoff to make the debug readable that I
have proposed upstream.
Trying to layer onto planes should be continued when fb ids are set and
not the other way around. Here the assert also failed when only having
one layer.
It is enough to get the global cursor location when repainting it. So we do not
need to query the relative position. If later on we find this is not right we
should be still able to get the relative position from the surface position
instead of calling into XWayland.
Also it is not expected and apparently unnecessary to move the cursor in the
paint function. Therefore remove this call too.