Make renderer_texture_from_dmabuf a no-op, since we handle client
DMA-BUFs with Vulkan. We're using wlr_buffer_get_dmabuf to directly
access the client-submitted FDs.
An overlay going away wasn't getting considered. Steam also doesn't
set the 'games running' property if Big Picture isn't running, and
we have more robust appID tracking now, so we can start to phase it out.
Doesn't make sense now that we poll() the DMA-BUF fd directly. We can
do that directly from steamcompmgr. Vulkan's fence used to be an actual
fence we made up with an empty submission.
We should also set the focus to something else that makes sense, which
means there's another bug in a higher-level layer somewhere, but at least
don't crash.
It wasn't actually causing crashes and the memory stomp is fixed.
The option only existed for a very short time and didn't do anything
useful, so should be safe.
Cleans up the composite shader significantly as well as it uses
arrays of descriptors/samplers now.
This all gets unrolled as the loop is spec-constant sized.
According to the spec, this is invalid:
> If the tiling of the image is VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, then
> the aspectMask member of pSubresource must be
> VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT
This triggers an assertion in anv.
References: https://github.com/Plagman/gamescope/issues/49
This can cause issues with Xwayland. Setting R600_DEBUG=nodcc
prevents Xwayland from being able to import DCC buffers coming
from Vulkan clients.
Closes: https://github.com/Plagman/gamescope/issues/185
Also: Update liftoff dependency to b08bbaa5e6331ed2
("Split liftoff_log_init into set_handler and set_priority")
The callback parameter was moved into a different method, though it is
not needed in this case as we didn't give it one before.
Right now scale games by default to 720p even if the screen is 1080p.
This happens when -w/-h is *not* specified.
Instead, don't scale the game by default. This means using a 720p
window when nested (shouldn't change anything), and using the screen's
resolution when embedded.
Tested with radv + radeonsi + glxgears on navi21 to work with DCC (assuming
the nodcc bit is disabled).
This is conservative and will fall back to the legacy path if the modifier
isn't supported. At the same time it also avoids the wird mesa WSI struct
if the modifier is supported.
This avoids needlessly creating buffers for an headless output we won't
use, and will allow us to more easily replace the headless backend with
a custom renderer in the future.
Instead of handling both cases in a single function, split the work of
populating the atomic request in two new functions, and keep the common
bits in drm_prepare.
Shouldn't have any functional change.
drm_can_avoid_composite doesn't merely checks whether we can avoid
composition: it also prepares a pending atomic request. It's always
necessary to call this function before drm_atomic_commit.
Rename the function to make this clearer.
Before the window is mapped, the client can set the initial NET_WM_STATE
directly in the window property. After the window is mapped, the client
must use a client message and shouldn't touch the property anymore.
Sometimes we hide our window and show it again after some time.
SDL_SetRelativeMouseMode doesn't seem to properly cope with this, at
least on my setup.
VUID-VkSwapchainCreateInfoKHR-surface-01270(ERROR / SPEC): msgNum: -1585220531 - Validation Error: [ VUID-VkSwapchainCreateInfoKHR-surface-01270 ] Object 0: handle = 0x628000040100, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0xa183744d | vkCreateSwapchainKHR(): pCreateInfo->surface is not known at this time to be supported for presentation by this device. The vkGetPhysicalDeviceSurfaceSupportKHR() must be called beforehand, and it must return VK_TRUE support with this surface for at least one queue family of this device. The Vulkan spec states: surface must be a surface that is supported by the device as determined using vkGetPhysicalDeviceSurfaceSupportKHR (https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-VkSwapchainCreateInfoKHR-surface-01270)
VUID-vkCreateInstance-ppEnabledExtensionNames-01388(ERROR / SPEC): msgNum: -437968512 - Validation Error: [ VUID-vkCreateInstance-ppEnabledExtensionNames-01388 ] Object 0: VK_NULL_HANDLE, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0xe5e52180 | Missing extension required by the instance extension VK_KHR_external_memory_capabilities: VK_KHR_get_physical_device_properties2. The Vulkan spec states: All required extensions for each extension in the VkInstanceCreateInfo::ppEnabledExtensionNames list must also be present in that list (https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VUID-vkCreateInstance-ppEnabledExtensionNames-01388)
In file included from ../src/steamcompmgr.cpp:74:
src/steamcompmgr.hpp:75:7: warning: private field 'm_hasPlane' is not used [-Wunused-private-field]
bool m_hasPlane;
^
src/steamcompmgr.cpp: In function 'void statsThreadMain()':
src/steamcompmgr.cpp:357:62: error: 'O_WRONLY' was not declared in this scope
357 | statsPipeFD = open( statsThreadPath.c_str(), O_WRONLY );
| ^~~~~~~~
src/steamcompmgr.cpp:357:31: error: 'open' was not declared in this scope; did you mean 'popen'?
357 | statsPipeFD = open( statsThreadPath.c_str(), O_WRONLY );
| ^~~~
| popen
src/steamcompmgr.cpp: In function 'void steamcompmgr_main(int, char**)':
src/steamcompmgr.cpp:2559:61: error: 'O_WRONLY' was not declared in this scope
2559 | readyPipeFD = open( optarg, O_WRONLY );
| ^~~~~~~~
src/steamcompmgr.cpp:2559:47: error: 'open' was not declared in this scope; did you mean 'popen'?
2559 | readyPipeFD = open( optarg, O_WRONLY );
| ^~~~
| popen
Should let people run against Intel and other non-AMD Mesa GPUs.
Also force compute+graphics if vkBasalt is enabled, as it won't support
compute-only rings. Also always composite if vkBasalt is enabled, so it
applies always in embedded.
Calling nice() in the very beginning ensures that Mesa worker threads in
gamescope and Xwayland can properly reduce their priority without us stomping
it later.
Move away from posix_spawn, since there's no easy way (that seems to work)
to keep priority normal for the spawned process and get the right behaviour
for gamescope and Xwayland.
The intermediate fork() lets us simplify the logic for LD_PRELOAD rewriting.
Avoid setting it for our children processes, by spawning them in a new
thread group and setting group-wide priority, which also conveniently
gets Xwayland.
If running through Steam, we want the overlay hooked into gamescope and
not the underlying game, or we'll get double overlay, and one with wrong
scaling.
This strips any token containing gameoverlayrenderer.so from LD_PRELOAD.
The new-ish code to listen for destroy on surfaces on the wlserver side
installs a dynamic listener. We need to remove it from the list before
freeing it, or wayland will try to do it when the signal gets destroyed,
which involves updating the link member in the freed memory.
Some xcb protocol allocations would often get allocated there in that
short time window and get scribbled on.
https://github.com/Plagman/gamescope/issues/7
Ironic. 064d132c could save others from use-after-free, but not itself.
wlr_texture_to_dmabuf involves issuing EGL commands to get a DMA-BUF out
of an EGLImage.
When the client submits a DMA-BUF via the linux-dmabuf protocol, there's
no need to go through EGL. We can directly import the client's DMA-BUF
into Vulkan.
The old code is still retained as a fallback in case the client uses
wl_drm (old Xwayland) or wl_shm. Removing it would involve creating a
Vulkan-based wlr_renderer.
References: https://github.com/Plagman/gamescope/issues/16
Avoid override redirect windows.
Raise new windows, don't focus tiny windows. If we only raised windows
that want to be activated, we probably wouldn't need the hack to filter
out small windows. TBD.
When directly scanning out game buffers, we need to make sure the game
buffer is suitable for scanout. If that's not the case, we need to
fallback to composition.
The fallback path was implemented, but we never checked whether scan-out
is possible in drm_can_avoid_composite. Perform an atomic test-only
commit to fix this.
wlroots headers can mostly be included with extern "C" blocks. Two
exceptions are the use of `static` for array args and `class` as a
struct field. These can be #define'ed to avoid C++ build errors.
This allows the whole project to be built as a single C++ codebase,
without having to maintain hybrid header files.
This commit fixes two issues.
A first issue is that fbids_in_req was previously populated
drm_can_avoid_composite and read from in page_flip_handler. As a
result, calling drm_can_avoid_composite then page_flip_handler would
prevent drm_atomic_commit from referencing the right FBs
(page_flip_handler runs in a separate thread and clears fbids_in_req).
To fix this, add a new fbids_queued vector filled by drm_atomic_commit.
Make page_flip_handler read from this new vector instead of
fbids_in_req. As a bonus, this fixes a data race since fbids_queued is
now protected by flip_lock.
The second issue is that drm_can_avoid_composite assumes all layers made
it into a hw plane when liftoff_output_apply succeeds. That's not the
case because libliftoff supports mixed hw plane + composition (where
some layers make it into a hw plane and the others get composited).
To fix this, make drm_can_avoid_composite fail if some but not all
layers make it into a hw plane. In the future, we'll want to support the
mixed mode too.
Closes: https://github.com/Plagman/gamescope/issues/65
References: https://github.com/Plagman/gamescope/issues/41
Only works when switching to fbcon for now. We need to stop
page-flipping when the DRM FD is paused to support switching to another
compositor.
References: https://github.com/Plagman/gamescope/issues/6
win objects are allocated with `new`, so they need to be de-allocated
with `delete` instead of `free`.
==589398==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x61200017f140
(EE) failed to read Wayland events: Broken pipe
X connection to :1 broken (explicit kill or server shutdown).
#0 0x7f5468ae4720 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:122
#1 0x559820f5c9a0 in finish_destroy_win ../src/steamcompmgr.cpp:1743
#2 0x559820f5ca6d in destroy_win ../src/steamcompmgr.cpp:1759
#3 0x559820f6163e in steamcompmgr_main ../src/steamcompmgr.cpp:2288
#4 0x559820f8e977 in steamCompMgrThreadRun() ../src/main.cpp:121
#5 0x559820f8e3e9 in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:60
#6 0x559820f8e24f in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:95
#7 0x559820f8e0b3 in void std:🧵:_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/9.3.0/thread:244
#8 0x559820f8dfae in std:🧵:_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/9.3.0/thread:251
#9 0x559820f8d7ba in std:🧵:_State_impl<std:🧵:_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/9.3.0/thread:195
#10 0x7f5468006b23 in execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80
#11 0x7f546745346e in start_thread (/usr/lib/libpthread.so.0+0x946e)
#12 0x7f54673833d2 in clone (/usr/lib/libc.so.6+0xff3d2)
0x61200017f140 is located 0 bytes inside of 296-byte region [0x61200017f140,0x61200017f268)
allocated by thread T40 here:
#0 0x7f5468ae6968 in operator new(unsigned long) /build/gcc/src/gcc/libsanitizer/asan/asan_new_delete.cc:104
#1 0x559820f595fe in add_win ../src/steamcompmgr.cpp:1548
#2 0x559820f614e8 in steamcompmgr_main ../src/steamcompmgr.cpp:2278
#3 0x559820f8e977 in steamCompMgrThreadRun() ../src/main.cpp:121
#4 0x559820f8e3e9 in void std::__invoke_impl<void, void (*)()>(std::__invoke_other, void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:60
#5 0x559820f8e24f in std::__invoke_result<void (*)()>::type std::__invoke<void (*)()>(void (*&&)()) /usr/include/c++/9.3.0/bits/invoke.h:95
#6 0x559820f8e0b3 in void std:🧵:_Invoker<std::tuple<void (*)()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/9.3.0/thread:244
#7 0x559820f8dfae in std:🧵:_Invoker<std::tuple<void (*)()> >::operator()() /usr/include/c++/9.3.0/thread:251
#8 0x559820f8d7ba in std:🧵:_State_impl<std:🧵:_Invoker<std::tuple<void (*)()> > >::_M_run() /usr/include/c++/9.3.0/thread:195
#9 0x7f5468006b23 in execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:80
Thread T40 created by T0 here:
#0 0x7f5468a0e377 in __interceptor_pthread_create /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cc:208
#1 0x7f5468006df9 in __gthread_create /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663
#2 0x7f5468006df9 in std:🧵:_M_start_thread(std::unique_ptr<std:🧵:_State, std::default_delete<std:🧵:_State> >, void (*)()) /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:135
#3 0x559820f8ea10 in startSteamCompMgr ../src/main.cpp:126
#4 0x559820f95cfb in xwayland_ready ../src/wlserver.c:119
#5 0x5598210de191 in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
#6 0x559820ff596b in xserver_handle_ready ../subprojects/wlroots/xwayland/xwayland.c:251
#7 0x7f5468744434 (/usr/lib/libwayland-server.so.0+0xa434)
#8 0x7ffc9796869f ([stack]+0x1f69f)