Giter VIP home page Giter VIP logo

gamescope's Introduction

gamescope: the micro-compositor formerly known as steamcompmgr

In an embedded session usecase, gamescope does the same thing as steamcompmgr, but with less extra copies and latency:

  • It's getting game frames through Wayland by way of Xwayland, so there's no copy within X itself before it gets the frame.
  • It can use DRM/KMS to directly flip game frames to the screen, even when stretching or when notifications are up, removing another copy.
  • When it does need to composite with the GPU, it does so with async Vulkan compute, meaning you get to see your frame quick even if the game already has the GPU busy with the next frame.

It also runs on top of a regular desktop, the 'nested' usecase steamcompmgr didn't support.

  • Because the game is running in its own personal Xwayland sandbox desktop, it can't interfere with your desktop and your desktop can't interfere with it.
  • You can spoof a virtual screen with a desired resolution and refresh rate as the only thing the game sees, and control/resize the output as needed. This can be useful in exotic display configurations like ultrawide or multi-monitor setups that involve rotation.

It runs on Mesa + AMD or Intel, and could be made to run on other Mesa/DRM drivers with minimal work. AMD requires Mesa 20.3+, Intel requires Mesa 21.2+. For NVIDIA's proprietary driver, version 515.43.04+ is required (make sure the nvidia-drm.modeset=1 kernel parameter is set).

If running RadeonSI clients with older cards (GFX8 and below), currently have to set R600_DEBUG=nodcc, or corruption will be observed until the stack picks up DRM modifiers support.

Building

git submodule update --init
meson build/
ninja -C build/
build/gamescope -- <game>

Install with:

meson install -C build/ --skip-subprojects

Keyboard shortcuts

  • Super + F : Toggle fullscreen
  • Super + N : Toggle nearest neighbour filtering
  • Super + U : Toggle FSR upscaling
  • Super + Y : Toggle NIS upscaling
  • Super + I : Increase FSR sharpness by 1
  • Super + O : Decrease FSR sharpness by 1
  • Super + S : Take screenshot (currently goes to /tmp/gamescope_$DATE.png)
  • Super + G : Toggle keyboard grab

Examples

On any X11 or Wayland desktop, you can set the Steam launch arguments of your game as follows:

# Upscale a 720p game to 1440p with integer scaling
gamescope -h 720 -H 1440 -S integer -- %command%

# Limit a vsynced game to 30 FPS
gamescope -r 30 -- %command%

# Run the game at 1080p, but scale output to a fullscreen 3440×1440 pillarboxed ultrawide window
gamescope -w 1920 -h 1080 -W 3440 -H 1440 -b -- %command%

Options

See gamescope --help for a full list of options.

  • -W, -H: set the resolution used by gamescope. Resizing the gamescope window will update these settings. Ignored in embedded mode. If -H is specified but -W isn't, a 16:9 aspect ratio is assumed. Defaults to 1280×720.
  • -w, -h: set the resolution used by the game. If -h is specified but -w isn't, a 16:9 aspect ratio is assumed. Defaults to the values specified in -W and -H.
  • -r: set a frame-rate limit for the game. Specified in frames per second. Defaults to unlimited.
  • -o: set a frame-rate limit for the game when unfocused. Specified in frames per second. Defaults to unlimited.
  • -F fsr: use AMD FidelityFX™ Super Resolution 1.0 for upscaling
  • -F nis: use NVIDIA Image Scaling v1.0.3 for upscaling
  • -S integer: use integer scaling.
  • -S stretch: use stretch scaling, the game will fill the window. (e.g. 4:3 to 16:9)
  • -b: create a border-less window.
  • -f: create a full-screen window.

Reshade support

Gamescope supports a subset of Reshade effects/shaders using the --reshade-effect [path] and --reshade-technique-idx [idx] command line parameters.

This provides an easy way to do shader effects (ie. CRT shader, film grain, debugging HDR with histograms, etc) on top of whatever is being displayed in Gamescope without having to hook into the underlying process.

There is currently no way to set the value of uniforms/options, they will just be their initializer values currently.

Using Reshade effects will increase latency as there will be work performed on the general gfx + compute queue as opposed to only using the realtime async compute queue which can run in tandem with the game's gfx work.

Using Reshade effects is highly discouraged for doing simple transformations which can be achieved with LUTs/CTMs which are possible to do in the DC (Display Core) on AMDGPU at scanout time, or with the current regular async compute composite path. The looks system where you can specify your own 3D LUTs would be a better alternative for such transformations.

Pull requests for improving Reshade compatibility support are appreciated.

Status of Gamescope Packages

Packaging status

gamescope's People

Contributors

ajoneil avatar bjj avatar bnieuwenhuizen avatar boukehaarsma23 avatar cubanismo avatar dadschoorse avatar emersion avatar esullivan-nvidia avatar flightlessmango avatar forthereallys avatar hanabishirecca avatar hanskristian-work avatar ishitatsuyuki avatar jbeich avatar jeremyselan avatar joshua-ashton avatar libcg avatar lolzballs avatar nekopsykose avatar oschowa avatar plagman avatar romangg avatar ruineka avatar samsagax avatar scrumplex avatar sharkautarch avatar slouken avatar tcoyvwac avatar trigg avatar zamundaaa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gamescope's Issues

Steam Controller Wayland pointer input

Steam Controller can be used in two modes basically:

  1. Mouse/keyboard emulation going through libinput (check libnput --list-devices)
  2. Higher-level logic internal to the Steam-client.

Current issues:

In mode 1

Works in X11 sessions, but not in desktop Wayland sessions at the moment, tested on KWin Wayland, see for GNOME [1] and [2]. Apparently has worked in the past though (sure?). Interestingly a short test showed that it works in sway. Maybe the other compositors just don't support multiple pointer devices with different characteristic (i.e. different device groups etc.)?

In mode 2

Is activated once the Steam client starts up. Mode 1 gets deactivated at that point in time. Has some more gimmicks. But it uses XTestFakeRelativeMotionEvent for sending pointer motions to the OS. Changing the cursor position by that is currently not supported in XWayland (warping pointers is).

So even if problem of mode 1 is solved as soon as mode 2 is activated, i.e. the Steam compositor starts up, the pointer input should be broken in any current Wayland desktop session again.

In gamescope currently the compositor itself listens into the X11 connection to get the XTest induced cursor position. That blocks us from going Wayland-determined cursor-position only at the moment and leads to corner-case issues when the synchronization lags behind (mouse position only updated after first move, returns to last position where it was moved with mouse before controller etc.).

Solution ideas

Without changing the Steam-client internal code solutions could be:

  • For (2): support XTestFakeRelativeMotionEvent in XWayland.
  • ...

Assertion failed in page_flip_handler

Just ran gamescope -l -d -- xterm and kept the Enter key pressed. Likely caused by a race condition.

(gdb) bt
#0  0x00007fe9de558355 in raise () at /usr/lib/libc.so.6
#1  0x00007fe9de541853 in abort () at /usr/lib/libc.so.6
#2  0x00007fe9de541727 in _nl_load_domain.cold () at /usr/lib/libc.so.6
#3  0x00007fe9de550936 in  () at /usr/lib/libc.so.6
#4  0x0000558fd2f9148a in page_flip_handler(int, unsigned int, unsigned int, unsigned int, void*) (fd=45, frame=0, sec=0, usec=0, data=0x2)
    at ../src/drm.cpp:212
#5  0x00007fe9dee48875 in drmHandleEvent () at /usr/lib/libdrm.so.2
#6  0x0000558fd2f917ff in flip_handler_thread_run() () at ../src/drm.cpp:275
#7  0x0000558fd2f8d7bd in std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)())
    (__f=@0x558fd500c9c8: 0x558fd2f91685 <flip_handler_thread_run()>) at /usr/include/c++/10.1.0/bits/invoke.h:60
#8  0x0000558fd2f8d767 in std::__invoke<void (*)()>(void (*&&)()) (__fn=@0x558fd500c9c8: 0x558fd2f91685 <flip_handler_thread_run()>)
    at /usr/include/c++/10.1.0/bits/invoke.h:95
#9  0x0000558fd2f8d714 in std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0x558fd500c9c8)
    at /usr/include/c++/10.1.0/thread:264
#10 0x0000558fd2f8d6e8 in std::thread::_Invoker<std::tuple<void (*)()> >::operator()() (this=0x558fd500c9c8)
    at /usr/include/c++/10.1.0/thread:271
#11 0x0000558fd2f8d5bc in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() (this=0x558fd500c9c0)
    at /usr/include/c++/10.1.0/thread:215
#12 0x00007fe9de935b74 in std::execute_native_thread_routine(void*) (__p=0x558fd500c9c0)
    at /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80
#13 0x00007fe9de6ec422 in start_thread () at /usr/lib/libpthread.so.0
#14 0x00007fe9de61bbf3 in clone () at /usr/lib/libc.so.6

Segfault on exit

==590402==ERROR: AddressSanitizer: attempting double-free on 0x610000050540 in thread T40:
X connection to :1 broken (explicit kill or server shutdown).
    #0 0x7f334a311720 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
    #1 0x7f334429ae39  (/usr/lib/dri/radeonsi_dri.so+0xb47e39)
    #2 0x7f3348aef536 in __run_exit_handlers (/usr/lib/libc.so.6+0x3e536)
    #3 0x7f3348aef6ed in exit (/usr/lib/libc.so.6+0x3e6ed)
    #4 0x7f334a0bb3f1 in _XDefaultIOError (/usr/lib/libX11.so.6+0x433f1)
    #5 0x7f334a0bb69d in _XIOError (/usr/lib/libX11.so.6+0x4369d)
    #6 0x7f334a0b901e in _XReadEvents (/usr/lib/libX11.so.6+0x4101e)
    #7 0x7f334a0a7c98 in XNextEvent (/usr/lib/libX11.so.6+0x2fc98)
    #8 0x561ee62212dd in steamcompmgr_main ../src/steamcompmgr.cpp:2267
    #9 0x561ee624e9ab in steamCompMgrThreadRun() ../src/main.cpp:121
    #10 0x561ee624e41d in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:60
    #11 0x561ee624e283 in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:95
    #12 0x561ee624e0e7 in void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/9.3.0/thread:244
    #13 0x561ee624dfe2 in std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/9.3.0/thread:251
    #14 0x561ee624d7ee in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/9.3.0/thread:195
    #15 0x7f3349833b23 in execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80
    #16 0x7f3348c8046e in start_thread (/usr/lib/libpthread.so.0+0x946e)
    #17 0x7f3348bb03d2 in clone (/usr/lib/libc.so.6+0xff3d2)

0x610000050540 is located 0 bytes inside of 184-byte region [0x610000050540,0x6100000505f8)
freed by thread T0 here:
    #0 0x7f334a311720 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
    #1 0x7f334429ae39  (/usr/lib/dri/radeonsi_dri.so+0xb47e39)

previously allocated by thread T0 here:
    #0 0x7f334a311b3a in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x7f33442a101d  (/usr/lib/dri/radeonsi_dri.so+0xb4e01d)

Thread T40 created by T0 here:
    #0 0x7f334a23b377 in __interceptor_pthread_create /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cc:208
    #1 0x7f3349833df9 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 0x7f3349833df9 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135
    #3 0x561ee624ea44 in startSteamCompMgr ../src/main.cpp:126
    #4 0x561ee6255d2f in xwayland_ready ../src/wlserver.c:119
    #5 0x561ee639e1c5 in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
    #6 0x561ee62b599f in xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:251
    #7 0x7f3349f71434  (/usr/lib/libwayland-server.so.0+0xa434)
    #8 0x7ffda7c84daf  ([stack]+0x1ddaf)

Get layers working consistently

libliftoff is hooked up with -l, and Roman has done some fixes already, but doesn't seem to work reliably still. Would be really nice to get that 100% robust on amdgpu so we could have the FPS meter or notifications up without killing perf.

[Crusader Kings 2]Very slow in fullscreen mode with upscaling

Hi,
I launch CK2 on my second screen with 1440p upscaling with this command :
gamescope -w 2560 -h 1440 -W 1280 -H 720 -- %command%

The game works and it's fully playable if i stay in window mode. But if you enable fullscreen mode with Win+F, the game is really slow when a new game is loaded and during a party.

vainfo crashes if gamescope is running

it somehow detects a wayland compositor is running and tries connecting to it, even though i'm running it from a completely separate context without WAYLAND_DISPLAY set. how come?

ThreadSanitizer races in embedded mode

Only picked the first few races.

==================
WARNING: ThreadSanitizer: data race (pid=123555)
  Read of size 8 at 0x55b92e309330 by thread T17:
    #0 std::vector<unsigned int, std::allocator<unsigned int> >::size() const /usr/include/c++/10.1.0/bits/stl_vector.h:919 (gamescope+0x42576)
    #1 page_flip_handler ../src/drm.cpp:238 (gamescope+0x3e226)
    #2 drmHandleEvent <null> (libdrm.so.2+0x6874)
    #3 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #4 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #5 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #6 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #7 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #8 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 8 at 0x55b92e309330 by thread T18:
    #0 void std::vector<unsigned int, std::allocator<unsigned int> >::_M_realloc_insert<unsigned int const&>(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >, unsigned int const&) /usr/include/c++/10.1.0/bits/vector.tcc:503 (games
cope+0x437c6)
    #1 std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int const&) /usr/include/c++/10.1.0/bits/stl_vector.h:1198 (gamescope+0x42a3c)
    #2 drm_can_avoid_composite ../src/drm.cpp:833 (gamescope+0x4188f)
    #3 paint_all ../src/steamcompmgr.cpp:1118 (gamescope+0x1f812)
    #4 steamcompmgr_main ../src/steamcompmgr.cpp:2622 (gamescope+0x26523)
    #5 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'g_DRM' of size 352 at 0x55b92e3092a0 (gamescope+0x00000010e330)

  Thread T17 (tid=123590, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 init_drm ../src/drm.cpp:446 (gamescope+0x3f912)
    #4 initOutput ../src/main.cpp:171 (gamescope+0x38b0d)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T18 (tid=123624, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

SUMMARY: ThreadSanitizer: data race /usr/include/c++/10.1.0/bits/stl_vector.h:919 in std::vector<unsigned int, std::allocator<unsigned int> >::size() const
==================

==================
WARNING: ThreadSanitizer: data race (pid=123555)
  Read of size 8 at 0x55b92e309328 by thread T17:
    #0 std::vector<unsigned int, std::allocator<unsigned int> >::size() const /usr/include/c++/10.1.0/bits/stl_vector.h:919 (gamescope+0x4258a)
    #1 page_flip_handler ../src/drm.cpp:238 (gamescope+0x3e226)
    #2 drmHandleEvent <null> (libdrm.so.2+0x6874)
    #3 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #4 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #5 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #6 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #7 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #8 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 8 at 0x55b92e309328 by thread T18:
    #0 void std::vector<unsigned int, std::allocator<unsigned int> >::_M_realloc_insert<unsigned int const&>(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >, unsigned int const&) /usr/include/c++/10.1.0/bits/vector.tcc:502 (gamescope+0x437ab)
    #1 std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int const&) /usr/include/c++/10.1.0/bits/stl_vector.h:1198 (gamescope+0x42a3c)
    #2 drm_can_avoid_composite ../src/drm.cpp:833 (gamescope+0x4188f)
    #3 paint_all ../src/steamcompmgr.cpp:1118 (gamescope+0x1f812)
    #4 steamcompmgr_main ../src/steamcompmgr.cpp:2622 (gamescope+0x26523)
    #5 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'g_DRM' of size 352 at 0x55b92e3092a0 (gamescope+0x00000010e328)

  Thread T17 (tid=123590, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 init_drm ../src/drm.cpp:446 (gamescope+0x3f912)
    #4 initOutput ../src/main.cpp:171 (gamescope+0x38b0d)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T18 (tid=123624, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

SUMMARY: ThreadSanitizer: data race /usr/include/c++/10.1.0/bits/stl_vector.h:919 in std::vector<unsigned int, std::allocator<unsigned int> >::size() const
==================

==================
WARNING: ThreadSanitizer: data race (pid=123555)
  Read of size 4 at 0x7b0400039d30 by thread T17:
    #0 void __gnu_cxx::new_allocator<unsigned int>::construct<unsigned int, unsigned int const&>(unsigned int*, unsigned int const&) /usr/include/c++/10.1.0/ext/new_allocator.h:150 (gamescope+0x44131)
    #1 void std::allocator_traits<std::allocator<unsigned int> >::construct<unsigned int, unsigned int const&>(std::allocator<unsigned int>&, unsigned int*, unsigned int const&) /usr/include/c++/10.1.0/bits/alloc_traits.h:512 (gamescope+0x4344c)
    #2 void std::vector<unsigned int, std::allocator<unsigned int> >::_M_realloc_insert<unsigned int const&>(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >, unsigned int const&) /usr/include/c++/10.1.0/bits/vector.tcc:449 (gamescope+0x43617)
    #3 std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int const&) /usr/include/c++/10.1.0/bits/stl_vector.h:1198 (gamescope+0x42a3c)
    #4 page_flip_handler ../src/drm.cpp:240 (gamescope+0x3e251)
    #5 drmHandleEvent <null> (libdrm.so.2+0x6874)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 8 at 0x7b0400039d30 by thread T18:
    #0 operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.0+0x8d1c4)
    #1 __gnu_cxx::new_allocator<unsigned int>::allocate(unsigned long, void const*) <null> (gamescope+0x45800)
    #2 std::allocator_traits<std::allocator<unsigned int> >::allocate(std::allocator<unsigned int>&, unsigned long) /usr/include/c++/10.1.0/bits/alloc_traits.h:460 (gamescope+0x44e2d)
    #3 std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_allocate(unsigned long) /usr/include/c++/10.1.0/bits/stl_vector.h:346 (gamescope+0x4434a)
    #4 void std::vector<unsigned int, std::allocator<unsigned int> >::_M_realloc_insert<unsigned int const&>(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >, unsigned int const&) /usr/include/c++/10.1.0/bits/vector.tcc:440 (gamescope+0x435da)
    #5 std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int const&) /usr/include/c++/10.1.0/bits/stl_vector.h:1198 (gamescope+0x42a3c)
    #6 drm_can_avoid_composite ../src/drm.cpp:833 (gamescope+0x4188f)
    #7 paint_all ../src/steamcompmgr.cpp:1118 (gamescope+0x1f812)
    #8 steamcompmgr_main ../src/steamcompmgr.cpp:2622 (gamescope+0x26523)
    #9 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #10 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #11 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #12 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #13 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #14 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #15 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is heap block of size 4 at 0x7b0400039d30 allocated by thread T18:
    #0 operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.0+0x8d1c4)
    #1 __gnu_cxx::new_allocator<unsigned int>::allocate(unsigned long, void const*) <null> (gamescope+0x45800)
    #2 std::allocator_traits<std::allocator<unsigned int> >::allocate(std::allocator<unsigned int>&, unsigned long) /usr/include/c++/10.1.0/bits/alloc_traits.h:460 (gamescope+0x44e2d)
    #3 std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_allocate(unsigned long) /usr/include/c++/10.1.0/bits/stl_vector.h:346 (gamescope+0x4434a)
    #4 void std::vector<unsigned int, std::allocator<unsigned int> >::_M_realloc_insert<unsigned int const&>(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >, unsigned int const&) /usr/include/c++/10.1.0/bits/vector.tcc:440 (gamescope+0x435da)
    #5 std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int const&) /usr/include/c++/10.1.0/bits/stl_vector.h:1198 (gamescope+0x42a3c)
    #6 drm_can_avoid_composite ../src/drm.cpp:833 (gamescope+0x4188f)
    #7 paint_all ../src/steamcompmgr.cpp:1118 (gamescope+0x1f812)
    #8 steamcompmgr_main ../src/steamcompmgr.cpp:2622 (gamescope+0x26523)
    #9 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #10 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #11 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #12 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #13 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #14 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #15 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Thread T17 (tid=123590, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 init_drm ../src/drm.cpp:446 (gamescope+0x3f912)
    #4 initOutput ../src/main.cpp:171 (gamescope+0x38b0d)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T18 (tid=123624, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

SUMMARY: ThreadSanitizer: data race /usr/include/c++/10.1.0/ext/new_allocator.h:150 in void __gnu_cxx::new_allocator<unsigned int>::construct<unsigned int, unsigned int const&>(unsigned int*, unsigned int const&)
==================

==================
WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) (pid=123555)
    #0 pthread_mutex_unlock /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4162 (libtsan.so.0+0x3a68e)
    #1 __gthread_mutex_unlock /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:779 (gamescope+0x26ec8)
    #2 std::mutex::unlock() /usr/include/c++/10.1.0/bits/std_mutex.h:118 (gamescope+0x27085)
    #3 page_flip_handler ../src/drm.cpp:245 (gamescope+0x3e26f)
    #4 drmHandleEvent <null> (libdrm.so.2+0x6874)
    #5 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #6 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #7 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #8 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #9 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #10 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'g_DRM' of size 352 at 0x55b92e3092a0 (gamescope+0x00000010e3d0)

  Mutex M64270548522275792 is already destroyed.

SUMMARY: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:779 in __gthread_mutex_unlock
==================

==================
WARNING: ThreadSanitizer: data race (pid=123555)
  Read of size 8 at 0x7b1c00090200 by thread T17:
    #0 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned int const&, unsigned long) const /usr/include/c++/10.1.0/bits/hashtable.h:1573 (gamescope+0x44745)
    #1 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_node(unsigned long, unsigned int const&, unsigned long) const /usr/include/c++/10.1.0/bits/hashtable.h:693 (gamescope+0x43b80)
    #2 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:709 (gamescope+0x42fd7)
    #3 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #4 page_flip_handler ../src/drm.cpp:210 (gamescope+0x3e045)
    #5 drmHandleEvent <null> (libdrm.so.2+0x6874)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 8 at 0x7b1c00090200 by thread T18 (mutexes: write M64270548522275792):
    #0 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_bucket_begin(unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>*) /usr/include/c++/10.1.0/bits/hashtable.h:1616 (gamescope+0x44c5a)
    #1 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned int const&, unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>*, unsigned long) /usr/include/c++/10.1.0/bits/hashtable.h:1735 (gamescope+0x43e9b)
    #2 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:719 (gamescope+0x43064)
    #3 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #4 drm_fbid_from_dmabuf ../src/drm.cpp:650 (gamescope+0x4071d)
    #5 import_commit ../src/steamcompmgr.cpp:524 (gamescope+0x1bc0c)
    #6 check_new_wayland_res() ../src/steamcompmgr.cpp:2043 (gamescope+0x23722)
    #7 steamcompmgr_main ../src/steamcompmgr.cpp:2618 (gamescope+0x264d8)
    #8 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #9 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #10 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #11 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #12 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #13 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #14 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)
  Location is heap block of size 104 at 0x7b1c000901a0 allocated by thread T18:
    #0 operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.0+0x8d1c4)
    #1 __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::allocate(unsigned long, void const*) /usr/include/c++/10.1.0/ext/new_allocator.h:115 (gamescope+0x3799c)
    #2 std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::allocate(std::allocator<std::__detail::_Hash_node_base*>&, unsigned long) /usr/include/c++/10.1.0/bits/alloc_traits.h:460 (gamescope+0x36ea9)
    #3 std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::_M_allocate_buckets(unsigned long) <null> (gamescope+0x4619e)
    #4 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_allocate_buckets(unsigned long) <null> (gamescope+0x45dd1)
    #5 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_rehash_aux(unsigned long, std::integral_constant<bool, true>) <null> (gamescope+0x453bb)
    #6 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_rehash(unsigned long, unsigned long const&) /usr/include/c++/10.1.0/bits/hashtable.h:2070 (gamescope+0x44a6d)
    #7 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node(unsigned int const&, unsigned long, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>*, unsigned long) /usr/include/c++/10.1.0/bits/hashtable.h:1728 (gamescope+0x43e52)
    #8 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:719 (gamescope+0x43064)
    #9 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #10 drm_fbid_from_dmabuf ../src/drm.cpp:650 (gamescope+0x4071d)
    #11 CVulkanTexture::BInit(unsigned int, unsigned int, VkFormat, bool, bool, wlr_dmabuf_attributes*) ../src/rendervulkan.cpp:380 (gamescope+0x49c90)
    #12 vulkan_make_output(VulkanOutput_t*) ../src/rendervulkan.cpp:949 (gamescope+0x4c8bc)
    #13 vulkan_init ../src/rendervulkan.cpp:1082 (gamescope+0x4d2c7)
    #14 steamcompmgr_main ../src/steamcompmgr.cpp:2200 (gamescope+0x24476)
    #15 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #16 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #17 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #18 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #19 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #20 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #21 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Mutex M64270548522275792 is already destroyed.

  Thread T17 (tid=123590, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 init_drm ../src/drm.cpp:446 (gamescope+0x3f912)
    #4 initOutput ../src/main.cpp:171 (gamescope+0x38b0d)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T18 (tid=123624, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

SUMMARY: ThreadSanitizer: data race /usr/include/c++/10.1.0/bits/hashtable.h:1573 in std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned int const&, unsigned long) const
==================

==================
WARNING: ThreadSanitizer: data race (pid=123555)
  Read of size 8 at 0x7b0800021ec0 by thread T17:
    #0 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned int const&, unsigned long) const /usr/include/c++/10.1.0/bits/hashtable.h:1577 (gamescope+0x44769)
    #1 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_node(unsigned long, unsigned int const&, unsigned long) const /usr/include/c++/10.1.0/bits/hashtable.h:693 (gamescope+0x43b80)
    #2 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:709 (gamescope+0x42fd7)
    #3 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #4 page_flip_handler ../src/drm.cpp:210 (gamescope+0x3e045)
    #5 drmHandleEvent <null> (libdrm.so.2+0x6874)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 8 at 0x7b0800021ec0 by thread T18 (mutexes: write M64270548522275792):
    #0 operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.0+0x8d1c4)
    #1 __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> >::allocate(unsigned long, void const*) /usr/include/c++/10.1.0/ext/new_allocator.h:115 (gamescope+0x45be1)
    #2 std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::allocate(std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> >&, unsigned long) <null> (gamescope+0x45283)
    #3 std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>* std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::_M_allocate_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:2032 (gamescope+0x44947)
    #4 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Scoped_node::_Scoped_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >*, std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable.h:272 (gamescope+0x43cba)
    #5 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:712 (gamescope+0x4302f)
    #6 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #7 drm_fbid_from_dmabuf ../src/drm.cpp:650 (gamescope+0x4071d)
    #8 import_commit ../src/steamcompmgr.cpp:524 (gamescope+0x1bc0c)
    #9 check_new_wayland_res() ../src/steamcompmgr.cpp:2043 (gamescope+0x23722)
    #10 steamcompmgr_main ../src/steamcompmgr.cpp:2618 (gamescope+0x264d8)
    #11 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #12 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #13 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #14 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #15 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #16 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #17 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)
  Location is heap block of size 24 at 0x7b0800021ec0 allocated by thread T18:
    #0 operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.0+0x8d1c4)
    #1 __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> >::allocate(unsigned long, void const*) /usr/include/c++/10.1.0/ext/new_allocator.h:115 (gamescope+0x45be1)
    #2 std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::allocate(std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> >&, unsigned long) <null> (gamescope+0x45283)
    #3 std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>* std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::_M_allocate_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:2032 (gamescope+0x44947)
    #4 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Scoped_node::_Scoped_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >*, std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable.h:272 (gamescope+0x43cba)
    #5 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:712 (gamescope+0x4302f)
    #6 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #7 drm_fbid_from_dmabuf ../src/drm.cpp:650 (gamescope+0x4071d)
    #8 import_commit ../src/steamcompmgr.cpp:524 (gamescope+0x1bc0c)
    #9 check_new_wayland_res() ../src/steamcompmgr.cpp:2043 (gamescope+0x23722)
    #10 steamcompmgr_main ../src/steamcompmgr.cpp:2618 (gamescope+0x264d8)
    #11 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #12 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #13 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #14 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #15 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #16 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #17 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Mutex M64270548522275792 is already destroyed.

  Thread T17 (tid=123590, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 init_drm ../src/drm.cpp:446 (gamescope+0x3f912)
    #4 initOutput ../src/main.cpp:171 (gamescope+0x38b0d)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T18 (tid=123624, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

SUMMARY: ThreadSanitizer: data race /usr/include/c++/10.1.0/bits/hashtable.h:1577 in std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned int const&, unsigned long) const
==================

==================
WARNING: ThreadSanitizer: data race (pid=123555)
  Read of size 4 at 0x7b0800058d68 by thread T17:
    #0 std::equal_to<unsigned int>::operator()(unsigned int const&, unsigned int const&) const /usr/include/c++/10.1.0/bits/stl_function.h:356 (gamescope+0x45ab8)
    #1 std::__detail::_Hashtable_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, st
d::__detail::_Hashtable_traits<false, false, true> >::_M_equals(unsigned int const&, unsigned long, std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>*) const <null> (gamescope+0x4514c)
    #2 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned i
nt>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_before_node(unsigned long, unsigned int const&, unsigned long) const /usr/include/c++/10.1.0/bits/hashtabl
e.h:1580 (gamescope+0x4478c)
    #3 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned i
nt>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_find_node(unsigned long, unsigned int const&, unsigned long) const /usr/include/c++/10.1.0/bits/hashtable.h:693
 (gamescope+0x43b80)
    #4 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<u
nsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:709 (gamescope+0x42f
d7)
    #5 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/
10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #6 page_flip_handler ../src/drm.cpp:210 (gamescope+0x3e045)
    #7 drmHandleEvent <null> (libdrm.so.2+0x6874)
    #8 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #9 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #10 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #11 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #12 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #13 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 8 at 0x7b0800058d68 by thread T18:
    #0 operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.0+0x8d1c4)
    #1 __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> >::allocate(unsigned long, void const*) /usr/include/c++/10.1.0/ext/new_allocator.h:115 (gamescope+0x45be1)
    #2 std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::allocate(std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >
, false> >&, unsigned long) <null> (gamescope+0x45283)
    #3 std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>* std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::_M_a
llocate_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:2032 (gamescope+0x44947)
    #4 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned i
nt>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Scoped_node::_Scoped_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std:
:__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >*, std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable.
h:272 (gamescope+0x43cba)
    #5 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<u
nsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:712 (gamescope+0x430
2f)
    #6 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #7 drm_fbid_from_dmabuf ../src/drm.cpp:650 (gamescope+0x4071d)
    #8 import_commit ../src/steamcompmgr.cpp:524 (gamescope+0x1bc0c)
    #9 check_new_wayland_res() ../src/steamcompmgr.cpp:2043 (gamescope+0x23722)
    #10 steamcompmgr_main ../src/steamcompmgr.cpp:2618 (gamescope+0x264d8)
    #11 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #12 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #13 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #14 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #15 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #16 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #17 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is heap block of size 24 at 0x7b0800058d60 allocated by thread T18:
    #0 operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/tsan/tsan_new_delete.cpp:64 (libtsan.so.0+0x8d1c4)
    #1 __gnu_cxx::new_allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> >::allocate(unsigned long, void const*) /usr/include/c++/10.1.0/ext/new_allocator.h:115 (gamescope+0x45be1)
    #2 std::allocator_traits<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::allocate(std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> >&, unsigned long) <null> (gamescope+0x45283)
    #3 std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false>* std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >::_M_allocate_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:2032 (gamescope+0x44947)
    #4 std::_Hashtable<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_Scoped_node::_Scoped_node<std::piecewise_construct_t const&, std::tuple<unsigned int const&>, std::tuple<> >(std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, false> > >*, std::piecewise_construct_t const&, std::tuple<unsigned int const&>&&, std::tuple<>&&) /usr/include/c++/10.1.0/bits/hashtable.h:272 (gamescope+0x43cba)
    #5 std::__detail::_Map_base<unsigned int, std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > >, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > >, std::__detail::_Select1st, std::equal_to<unsigned int>, std::hash<unsigned int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/hashtable_policy.h:712 (gamescope+0x4302f)
    #6 std::unordered_map<unsigned int, std::pair<bool, std::atomic<unsigned int> >, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, std::pair<bool, std::atomic<unsigned int> > > > >::operator[](unsigned int const&) /usr/include/c++/10.1.0/bits/unordered_map.h:984 (gamescope+0x42627)
    #7 drm_fbid_from_dmabuf ../src/drm.cpp:650 (gamescope+0x4071d)
    #8 import_commit ../src/steamcompmgr.cpp:524 (gamescope+0x1bc0c)
    #9 check_new_wayland_res() ../src/steamcompmgr.cpp:2043 (gamescope+0x23722)
    #10 steamcompmgr_main ../src/steamcompmgr.cpp:2618 (gamescope+0x264d8)
    #11 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #12 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #13 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #14 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #15 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #16 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #17 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Thread T17 (tid=123590, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 init_drm ../src/drm.cpp:446 (gamescope+0x3f912)
    #4 initOutput ../src/main.cpp:171 (gamescope+0x38b0d)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T18 (tid=123624, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

SUMMARY: ThreadSanitizer: data race /usr/include/c++/10.1.0/bits/stl_function.h:356 in std::equal_to<unsigned int>::operator()(unsigned int const&, unsigned int const&) const
==================

==================
WARNING: ThreadSanitizer: data race (pid=123555)
  Write of size 1 at 0x55b92e3069ec by thread T24:
    #0 operator() ../src/steamcompmgr.cpp:2277 (gamescope+0x2394d)
    #1 __invoke_impl<void, steamcompmgr_main(int, char**)::<lambda()> > /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x26d7e)
    #2 __invoke<steamcompmgr_main(int, char**)::<lambda()> > /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x26ceb)
    #3 _M_invoke<0> /usr/include/c++/10.1.0/thread:264 (gamescope+0x26c50)
    #4 operator() /usr/include/c++/10.1.0/thread:271 (gamescope+0x26bfa)
    #5 _M_run /usr/include/c++/10.1.0/thread:215 (gamescope+0x26bb4)
    #6 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous read of size 1 at 0x55b92e3069ec by main thread:
    #0 wlserver_run ../src/wlserver.c:450 (gamescope+0x3d13c)
    #1 main ../src/main.cpp:120 (gamescope+0x38821)

  Location is global 'run' of size 1 at 0x55b92e3069ec (gamescope+0x00000010b9ec)

  Thread T24 (tid=123632, running) created by thread T18 at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 steamcompmgr_main ../src/steamcompmgr.cpp:2278 (gamescope+0x24ac1)
    #4 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #5 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #6 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #7 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #8 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #9 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #10 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

SUMMARY: ThreadSanitizer: data race ../src/steamcompmgr.cpp:2277 in operator()
==================

`-r 30` stopped working

It used to be that passing -r 30 properly got vsynced clients like glxgears to meter themselves to 30fps, etc.

we still make the wlr_output_set_custom_mode() call with the nested refresh and nested xrandr still reports it, so how come it's getting ignored?

Screen 0: minimum 16 x 16, current 1280 x 720, maximum 32767 x 32767
XWAYLAND0 connected 1280x720+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
1280x720      29.93*+

ThreadSanitizer race conditions in nested mode

In nested mode:

==================
WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) (pid=121151)
    #0 pthread_mutex_unlock /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4162 (libtsan.so.0+0x3a68e)
    #1 __gthread_mutex_unlock /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:779 (gamescope+0x26ec8)
    #2 std::mutex::unlock() /usr/include/c++/10.1.0/bits/std_mutex.h:118 (gamescope+0x27085)
    #3 inputSDLThreadRun() ../src/inputsdl.cpp:363 (gamescope+0x46a0f)
    #4 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #5 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #6 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #7 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #8 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #9 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'g_SDLInitLock' of size 40 at 0x561af0c0b420 (gamescope+0x00000010e420)

  Mutex M2051 (0x561af0c0b420) created at:
    #0 pthread_mutex_lock /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4148 (libtsan.so.0+0x528ce)
    #1 __gthread_mutex_lock /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:749 (gamescope+0x26e7f)
    #2 std::mutex::lock() /usr/include/c++/10.1.0/bits/std_mutex.h:100 (gamescope+0x2702e)
    #3 inputsdl_init ../src/inputsdl.cpp:440 (gamescope+0x46e74)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

SUMMARY: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:779 in __gthread_mutex_unlock
==================
==================
WARNING: ThreadSanitizer: data race (pid=121151)
  Write of size 1 at 0x7b6800070034 by main thread (mutexes: write M2051):
    #0 memcpy /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:806 (libtsan.so.0+0x41fdd)
    #1 memcpy /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:798 (libtsan.so.0+0x41fdd)
    #2 <null> <null> (libSDL2-2.0.so.0+0x6f461)
    #3 main ../src/main.cpp:114 (gamescope+0x387e0)

  Previous write of size 8 at 0x7b6800070030 by thread T17:
    [failed to restore the stack]

  Location is heap block of size 1384 at 0x7b680006fc00 allocated by thread T17:
    #0 calloc /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:668 (libtsan.so.0+0x2ffbc)
    #1 <null> <null> (libSDL2-2.0.so.0+0x6ecc1)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #7 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Mutex M2051 (0x561af0c0b420) created at:
    #0 pthread_mutex_lock /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4148 (libtsan.so.0+0x528ce)
    #1 __gthread_mutex_lock /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:749 (gamescope+0x26e7f)
    #2 std::mutex::lock() /usr/include/c++/10.1.0/bits/std_mutex.h:100 (gamescope+0x2702e)
    #3 inputsdl_init ../src/inputsdl.cpp:440 (gamescope+0x46e74)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T17 (tid=121171, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 inputsdl_init ../src/inputsdl.cpp:442 (gamescope+0x46e87)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

SUMMARY: ThreadSanitizer: data race (/usr/lib/libSDL2-2.0.so.0+0x6f461) 
==================
==================
WARNING: ThreadSanitizer: data race (pid=121151)
  Atomic read of size 1 at 0x7b0c00024510 by main thread (mutexes: write M2051):
    #0 pthread_mutex_lock /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4148 (libtsan.so.0+0x528ce)
    #1 <null> <null> (libX11.so.6+0x2e803)
    #2 main ../src/main.cpp:114 (gamescope+0x387e0)

  Previous write of size 8 at 0x7b0c00024510 by thread T17:
    [failed to restore the stack]

  Location is heap block of size 40 at 0x7b0c00024510 allocated by thread T17:
    #0 malloc /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:651 (libtsan.so.0+0x2fd25)
    #1 <null> <null> (libX11.so.6+0x2e522)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #7 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Mutex M2051 (0x561af0c0b420) created at:
    #0 pthread_mutex_lock /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4148 (libtsan.so.0+0x528ce)
    #1 __gthread_mutex_lock /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:749 (gamescope+0x26e7f)
    #2 std::mutex::lock() /usr/include/c++/10.1.0/bits/std_mutex.h:100 (gamescope+0x2702e)
    #3 inputsdl_init ../src/inputsdl.cpp:440 (gamescope+0x46e74)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T17 (tid=121171, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 inputsdl_init ../src/inputsdl.cpp:442 (gamescope+0x46e87)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

SUMMARY: ThreadSanitizer: data race (/usr/lib/libX11.so.6+0x2e803) 
==================
==================
WARNING: ThreadSanitizer: data race (pid=121151)
  Read of size 8 at 0x561af0c0b0f0 by thread T17:
    #0 updateOutputRefresh() ../src/inputsdl.cpp:340 (gamescope+0x46904)
    #1 inputSDLThreadRun() ../src/inputsdl.cpp:421 (gamescope+0x46d9d)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #7 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 8 at 0x561af0c0b0f0 by main thread (mutexes: write M2051):
    #0 initOutput ../src/main.cpp:149 (gamescope+0x38a08)
    #1 main ../src/main.cpp:114 (gamescope+0x387e0)

  As if synchronized via sleep:
    #0 nanosleep /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:362 (libtsan.so.0+0x639a2)
    #1 <null> <null> (libSDL2-2.0.so.0+0x10018b)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #7 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'window' of size 8 at 0x561af0c0b0f0 (gamescope+0x00000010e0f0)

  Mutex M2051 (0x561af0c0b420) created at:
    #0 pthread_mutex_lock /build/gcc/src/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:4148 (libtsan.so.0+0x528ce)
    #1 __gthread_mutex_lock /usr/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:749 (gamescope+0x26e7f)
    #2 std::mutex::lock() /usr/include/c++/10.1.0/bits/std_mutex.h:100 (gamescope+0x2702e)
    #3 inputsdl_init ../src/inputsdl.cpp:440 (gamescope+0x46e74)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T17 (tid=121171, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 inputsdl_init ../src/inputsdl.cpp:442 (gamescope+0x46e87)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

SUMMARY: ThreadSanitizer: data race ../src/inputsdl.cpp:340 in updateOutputRefresh()
==================
==================
WARNING: ThreadSanitizer: data race (pid=121151)
  Read of size 4 at 0x561af0c08970 by thread T34:
    #0 gpuvis_trace_init ../src/gpuvis_trace_utils.h:390 (gamescope+0x195f8)
    #1 trace_printf_impl ../src/gpuvis_trace_utils.h:485 (gamescope+0x19c96)
    #2 gpuvis_trace_vprintf ../src/gpuvis_trace_utils.h:530 (gamescope+0x19f51)
    #3 gpuvis_trace_printf ../src/gpuvis_trace_utils.h:522 (gamescope+0x19eda)
    #4 steamcompmgr_main ../src/steamcompmgr.cpp:2537 (gamescope+0x2603e)
    #5 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 4 at 0x561af0c08970 by thread T40:
    #0 gpuvis_trace_init ../src/gpuvis_trace_utils.h:398 (gamescope+0x19667)
    #1 trace_printf_impl ../src/gpuvis_trace_utils.h:485 (gamescope+0x19c96)
    #2 gpuvis_trace_vprintf ../src/gpuvis_trace_utils.h:530 (gamescope+0x19f51)
    #3 gpuvis_trace_printf ../src/gpuvis_trace_utils.h:522 (gamescope+0x19eda)
    #4 vblankThreadRun() ../src/vblankmanager.cpp:53 (gamescope+0x471b5)
    #5 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #6 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #7 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #8 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #9 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #10 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'g_trace_fd' of size 4 at 0x561af0c08970 (gamescope+0x00000010b970)

  Thread T34 (tid=121236, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

  Thread T40 (tid=121243, running) created by thread T34 at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 vblank_init() ../src/vblankmanager.cpp:73 (gamescope+0x473aa)
    #4 steamcompmgr_main ../src/steamcompmgr.cpp:2205 (gamescope+0x244b1)
    #5 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

SUMMARY: ThreadSanitizer: data race ../src/gpuvis_trace_utils.h:390 in gpuvis_trace_init
==================
==================
WARNING: ThreadSanitizer: data race (pid=121151)
  Write of size 4 at 0x561af0c089e4 by thread T17:
    #0 updateOutputRefresh() ../src/inputsdl.cpp:343 (gamescope+0x4694f)
    #1 inputSDLThreadRun() ../src/inputsdl.cpp:421 (gamescope+0x46d9d)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #7 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous read of size 4 at 0x561af0c089e4 by thread T40:
    #0 vblankThreadRun() ../src/vblankmanager.cpp:31 (gamescope+0x46f67)
    #1 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #2 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #3 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #4 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #5 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #6 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'g_nOutputRefresh' of size 4 at 0x561af0c089e4 (gamescope+0x00000010b9e4)

  Thread T17 (tid=121171, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 inputsdl_init ../src/inputsdl.cpp:442 (gamescope+0x46e87)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

  Thread T40 (tid=121243, running) created by thread T34 at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 vblank_init() ../src/vblankmanager.cpp:73 (gamescope+0x473aa)
    #4 steamcompmgr_main ../src/steamcompmgr.cpp:2205 (gamescope+0x244b1)
    #5 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #6 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #7 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #8 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #9 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #10 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #11 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

SUMMARY: ThreadSanitizer: data race ../src/inputsdl.cpp:343 in updateOutputRefresh()
==================
==================
WARNING: ThreadSanitizer: data race (pid=121151)
  Read of size 4 at 0x561af0c089dc by thread T34:
    #0 steamcompmgr_main ../src/steamcompmgr.cpp:2582 (gamescope+0x262b6)
    #1 steamCompMgrThreadRun() ../src/main.cpp:125 (gamescope+0x3888c)
    #2 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #3 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #4 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #5 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #6 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #7 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Previous write of size 4 at 0x561af0c089dc by thread T17:
    #0 inputSDLThreadRun() ../src/inputsdl.cpp:424 (gamescope+0x46dc6)
    #1 void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:60 (gamescope+0x38408)
    #2 std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/10.1.0/bits/invoke.h:95 (gamescope+0x3835f)
    #3 void std::thread::_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/10.1.0/thread:264 (gamescope+0x382c4)
    #4 std::thread::_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/10.1.0/thread:271 (gamescope+0x3826e)
    #5 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/10.1.0/thread:215 (gamescope+0x380ae)
    #6 execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80 (libstdc++.so.6+0xcfb73)

  Location is global 'g_nOutputWidth' of size 4 at 0x561af0c089dc (gamescope+0x00000010b9dc)

  Thread T34 (tid=121236, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 startSteamCompMgr ../src/main.cpp:130 (gamescope+0x388e3)
    #4 xwayland_ready ../src/wlserver.c:105 (gamescope+0x3b614)
    #5 wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29 (gamescope+0xa8096)
    #6 xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:250 (gamescope+0xa912d)
    #7 <null> <null> (libwayland-server.so.0+0xa434)
    #8 main ../src/main.cpp:120 (gamescope+0x38821)

  Thread T17 (tid=121171, running) created by main thread at:
    #0 pthread_create /build/gcc/src/gcc/libsanitizer/tsan/tsan_interceptors_posix.cpp:962 (libtsan.so.0+0x5efab)
    #1 __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 (libstdc++.so.6+0xcfe49)
    #2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135 (libstdc++.so.6+0xcfe49)
    #3 inputsdl_init ../src/inputsdl.cpp:442 (gamescope+0x46e87)
    #4 initOutput ../src/main.cpp:140 (gamescope+0x3898a)
    #5 main ../src/main.cpp:114 (gamescope+0x387e0)

SUMMARY: ThreadSanitizer: data race ../src/steamcompmgr.cpp:2582 in steamcompmgr_main
==================

Plus a bunch of other races when cleaning up, but we're segfaulting anyway on shutdown.

GEM handles aren't closed

We call drmPrimeFDToHandle but we never close them. We should perform a DRM_IOCTL_GEM_CLOSE ioctl to do so.

However we need to implement some kind of refcounting: two DMA-BUF imports may yield the same GEM handle.

Tearing in embedded mode

On DC at least, sometimes there's crazy tearing. We know we need to import a fence, so not too unexpected, but you'd think implicit sync would take care of it.

Stuck in "performing first time setup"

  1. Install Mirror's Edge
  2. Run it from the first time in the embedded session
  3. Installer is stuck on "performing first time setup"

The first time setup actually installs NVIDIA PhysX, which requires user interaction to accept the license. The embedded session doesn't show the license window and gets stuck forever.

gamescope installs files in the same location as wlroots

error: failed to commit transaction (conflicting files)
gamescope-git: /usr/include/wlr/backend.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/drm.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/headless.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/interface.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/libinput.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/multi.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/noop.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/session.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/session/interface.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/wayland.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/backend/x11.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/config.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_input_device.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_keyboard.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_output.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_pointer.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_switch.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_tablet_pad.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_tablet_tool.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/interfaces/wlr_touch.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/render/dmabuf.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/render/drm_format_set.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/render/egl.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/render/gles2.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/render/interface.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/render/wlr_renderer.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/render/wlr_texture.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_box.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_buffer.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_compositor.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_cursor.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_data_control_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_data_device.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_export_dmabuf_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_foreign_toplevel_management_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_fullscreen_shell_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_gamma_control_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_gtk_primary_selection.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_idle.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_idle_inhibit_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_input_device.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_input_inhibitor.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_input_method_v2.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_keyboard.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_layer_shell_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_linux_dmabuf_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_list.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_matrix.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_output.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_output_damage.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_output_layout.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_output_management_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_pointer.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_pointer_constraints_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_pointer_gestures_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_presentation_time.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_primary_selection.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_primary_selection_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_region.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_relative_pointer_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_screencopy_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_seat.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_server_decoration.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_surface.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_switch.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_tablet_pad.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_tablet_tool.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_tablet_v2.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_text_input_v3.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_touch.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_virtual_keyboard_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_xcursor_manager.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_xdg_decoration_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_xdg_output_v1.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_xdg_shell.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/types/wlr_xdg_shell_v6.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/util/edges.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/util/log.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/util/region.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/version.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/xcursor.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/include/wlr/xwayland.h exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/lib/libwlroots.so exists in filesystem (owned by wlroots-git)
gamescope-git: /usr/lib/pkgconfig/wlroots.pc exists in filesystem (owned by wlroots-git)

X-side synthetic input broken with latest commits

can be reproduced in nested:

./gamescope -e -- steam -tenfoot -steamos

Connect a Steam controller or any controller, launch Factorio or any game that uses the normal OS cursor, configure a mouse mode on the trackpad, observe that cursor doesn't move when mouse input is issues despite the game properly reacting to the X-side cursor position.

error: ‘nsc_context_set_pixel_format’ is deprecated

FAILED: subprojects/wlroots/backend/86510e7@@wlr_backend@sta/rdp_peer.c.o 
cc -Isubprojects/wlroots/backend/86510e7@@wlr_backend@sta -Isubprojects/wlroots/backend -I../subprojects/wlroots/backend -Isubprojects/wlroots -I../subprojects/wlroots -Isubprojects/wlroots/include -I../subprojects/wlroots/include -Isubprojects/wlroots/protocol -I../subprojects/wlroots/protocol -Isubprojects/wlroots/render -I/usr/include/libdrm -I/usr/include/pixman-1 -I/usr/include/freerdp2/ -I/usr/include/winpr2 -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Werror -O3 -DWLR_USE_UNSTABLE -Wundef -Wlogical-op -Wmissing-include-dirs -Wold-style-definition -Wpointer-arith -Winit-self -Wstrict-prototypes -Wimplicit-fallthrough=2 -Wendif-labels -Wstrict-aliasing=2 -Woverflow -Wno-missing-braces -Wno-missing-field-initializers -Wno-unused-parameter -fmacro-prefix-map=../subprojects/wlroots/= -DLIBINPUT_MAJOR=1 -DLIBINPUT_MINOR=15 -DLIBINPUT_PATCH=5 -fPIC -MD -MQ 'subprojects/wlroots/backend/86510e7@@wlr_backend@sta/rdp_peer.c.o' -MF 'subprojects/wlroots/backend/86510e7@@wlr_backend@sta/rdp_peer.c.o.d' -o 'subprojects/wlroots/backend/86510e7@@wlr_backend@sta/rdp_peer.c.o' -c ../subprojects/wlroots/backend/rdp/peer.c
../subprojects/wlroots/backend/rdp/peer.c: In function ‘rdp_peer_context_new’:
../subprojects/wlroots/backend/rdp/peer.c:256:2: error: ‘nsc_context_set_pixel_format’ is deprecated [-Werror=deprecated-declarations]
  256 |  nsc_context_set_pixel_format(context->nsc_context, PIXEL_FORMAT_BGRA32);
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/winpr2/winpr/synch.h:29,
                 from /usr/include/winpr2/winpr/wlog.h:33,
                 from /usr/include/freerdp2/freerdp/codec/color.h:26,
                 from ../subprojects/wlroots/include/backend/rdp.h:3,
                 from ../subprojects/wlroots/backend/rdp/peer.c:10:
/usr/include/freerdp2/freerdp/codec/nsc.h:47:36: note: declared here
   47 |  FREERDP_API WINPR_DEPRECATED(BOOL nsc_context_set_pixel_format(NSC_CONTEXT* context,
      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/winpr2/winpr/winpr.h:53:31: note: in definition of macro ‘WINPR_DEPRECATED’
   53 | #define WINPR_DEPRECATED(obj) obj __attribute__((deprecated))
      |                               ^~~
cc1: all warnings being treated as errors

Zero copy when nested

Avoid copying buffers when running nested: directly hand over the game's DMA-BUF to the parent compositor.

Xwayland is delaying commits for vsynced clients

Looking at gpuvis captures for vsynced games running is xwayland, unwanted things are happening. Xwayland is decoupled from the thing actually handling the output, so I'm not sure it ought having a say. Ideally Xwayland would just forward whether the client wants vsync to the compositor, and the compositor could pass back enough information to have the right behavior instead.

Use high-priority compute

Right now if there's concurrenct graphics work our copy is significantly worse in terms of latency. Throughput might be better due to concurrency.

Fix frame cadence interaction with cursor repainting

We want to note we want to repaint next vblank, but not actually trigger a new frame just by moving the cursor. We just need to defer the decision until as close to vblank as possible, right now we're emitting twice the frames and getting behind if you're moving the cursor a bunch.

DOOM Eternal black buffers in embedded

But is consistently fine for me on a desktop or nested. DOOM 2016 is fine too. Maybe Vega vs. Raven? Haven't tried nested on Raven, maybe good next step.

Failed to find physical device on Intel

I'm trying to start gamescope (e.g. gamescope command without params), but then I get segfault with the following errors:

glamor: No eglstream capable devices found
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Internal error: Could not resolve keysym XF86FullScreen
Errors from xkbcomp are not fatal to the X server
2020-05-08 18:52:25 - [types/wlr_surface.c:609] New wlr_surface ????? (res ?????)
2020-05-08 18:52:25 - [xwayland/xwayland.c:349] sent SIGUSR1 to process ?????
2020-05-08 18:52:25 - [xwayland/xwayland.c:227] Xserver is ready
The XKEYBOARD keymap compiler (xkbcomp) reports:
> Warning: Unsupported maximum keycode 569, clipping.
> X11 cannot support keycodes above 255.
> Internal error: Could not resolve keysym Invalid
Errors from xkbcomp are not fatal to the X server
(EE) failed to read Wayland events: Broken pipe
Segmentation fault (core dumped)

Any ideas?

Gracefully handle drmModeAddFB failures

If the display engine doesn't support a buffer format, drmModeAddFB may fail. We need to properly fallback to composition in this case. Right now we have an assert( commit.fb_id != 0 ).

Allow shortcuts to be configurable

Allow shortcuts to be configurable through a config file or something, as I have discovered to my dismay that my new keyboard doesn't have a Meta key. :(

Move to xres pid querying

Right now we're getting appids through the atom set by gameoverlayrenderer. It's not super robust and there's a bunch of cases where the current hooks don't set the Atom (like Dead Cells native) - getting the pid through xres 1.2 should be robust (see keithp recent commit in xrestop), and then we can walk up /proc/ until we find the SteamChildMontior, which would give us the appid reliably

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.