Added a fix for X11 / Cinnamon window popups and maximize button not visible.
This commit is contained in:
@@ -44,7 +44,6 @@ _X_PROPERTY_CHANGE_MASK = 1 << 22
|
|||||||
_X_SUBSTRUCTURE_NOTIFY_MASK = 1 << 19
|
_X_SUBSTRUCTURE_NOTIFY_MASK = 1 << 19
|
||||||
_X_SUBSTRUCTURE_REDIRECT_MASK = 1 << 20
|
_X_SUBSTRUCTURE_REDIRECT_MASK = 1 << 20
|
||||||
_X_WM_STATE_WITHDRAWN = 0
|
_X_WM_STATE_WITHDRAWN = 0
|
||||||
_X_WM_STATE_NORMAL = 1
|
|
||||||
_X_WM_STATE_ICONIC = 3
|
_X_WM_STATE_ICONIC = 3
|
||||||
_NET_WM_STATE_REMOVE = 0
|
_NET_WM_STATE_REMOVE = 0
|
||||||
_NET_WM_STATE_SOURCE_APPLICATION = 1
|
_NET_WM_STATE_SOURCE_APPLICATION = 1
|
||||||
@@ -450,18 +449,6 @@ class _X11:
|
|||||||
return None
|
return None
|
||||||
return values[0]
|
return values[0]
|
||||||
|
|
||||||
def restore_normal_window_state(self, window: int) -> bool:
|
|
||||||
"""Undo a nested iconify request without raising the host window."""
|
|
||||||
|
|
||||||
self._replace_long_property(
|
|
||||||
window,
|
|
||||||
b"WM_STATE",
|
|
||||||
b"WM_STATE",
|
|
||||||
(_X_WM_STATE_NORMAL, 0),
|
|
||||||
)
|
|
||||||
self.library.XSync(self.display, 0)
|
|
||||||
return self.window_state(window) == _X_WM_STATE_NORMAL
|
|
||||||
|
|
||||||
def window_is_borderless(self, window: int) -> bool | None:
|
def window_is_borderless(self, window: int) -> bool | None:
|
||||||
"""Return whether the client currently requests no Motif decorations."""
|
"""Return whether the client currently requests no Motif decorations."""
|
||||||
|
|
||||||
@@ -1010,6 +997,13 @@ class _X11:
|
|||||||
return False
|
return False
|
||||||
return int(focused.value) == window
|
return int(focused.value) == window
|
||||||
|
|
||||||
|
def window_is_active(self, window: int) -> bool:
|
||||||
|
"""Return whether the desktop already considers this client active."""
|
||||||
|
|
||||||
|
root = self.library.XDefaultRootWindow(self.display)
|
||||||
|
active = self._long_property(root, b"_NET_ACTIVE_WINDOW", 1)
|
||||||
|
return bool(active and active[0] == window)
|
||||||
|
|
||||||
def activate_window(self, window: int) -> bool:
|
def activate_window(self, window: int) -> bool:
|
||||||
"""Ask the window manager to restore and activate one client."""
|
"""Ask the window manager to restore and activate one client."""
|
||||||
|
|
||||||
@@ -1436,15 +1430,19 @@ def _focus_game_window(mapper: _X11, window: int) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def _repair_game_window_focus(mapper: _X11, window: int) -> bool:
|
def _repair_game_window_focus(mapper: _X11, window: int) -> bool:
|
||||||
|
"""Repair Wine's input focus only while its desktop window remains active."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if mapper.window_state(window) == _X_WM_STATE_ICONIC:
|
||||||
|
return False
|
||||||
|
if not mapper.window_is_active(window):
|
||||||
|
return False
|
||||||
if mapper.window_is_focused(window):
|
if mapper.window_is_focused(window):
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
mapper.activate_window(window)
|
mapper.restore_input_focus(window)
|
||||||
time.sleep(WINDOW_ACTIVATION_DELAY_SECONDS)
|
|
||||||
mapper.focus_window(window)
|
|
||||||
return mapper.window_is_focused(window)
|
return mapper.window_is_focused(window)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(
|
print(
|
||||||
@@ -1460,6 +1458,8 @@ def _repair_gamescope_game_window_focus(mapper: _X11, window: int) -> bool:
|
|||||||
"""Restore nested focus without asking the desktop to activate Gamescope."""
|
"""Restore nested focus without asking the desktop to activate Gamescope."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if mapper.window_state(window) == _X_WM_STATE_ICONIC:
|
||||||
|
return False
|
||||||
if mapper.window_is_focused(window):
|
if mapper.window_is_focused(window):
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -1491,18 +1491,9 @@ def _resolve_gamescope_game_window(
|
|||||||
except Exception:
|
except Exception:
|
||||||
state = None
|
state = None
|
||||||
if state == _X_WM_STATE_ICONIC:
|
if state == _X_WM_STATE_ICONIC:
|
||||||
try:
|
# IconicState can be a real desktop minimize request. Monitoring must never
|
||||||
if not mapper.restore_normal_window_state(window):
|
# turn that user-controlled state back into a visible window.
|
||||||
return None
|
return None
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
print(
|
|
||||||
"Game login window requested minimization; kept it visible inside "
|
|
||||||
"Gamescope.",
|
|
||||||
file=sys.stderr,
|
|
||||||
flush=True,
|
|
||||||
)
|
|
||||||
return window
|
|
||||||
if state is not None and state != _X_WM_STATE_WITHDRAWN:
|
if state is not None and state != _X_WM_STATE_WITHDRAWN:
|
||||||
return window
|
return window
|
||||||
|
|
||||||
@@ -1733,18 +1724,22 @@ def _guard_game_window_startup(
|
|||||||
became_iconic = state == _X_WM_STATE_ICONIC
|
became_iconic = state == _X_WM_STATE_ICONIC
|
||||||
entered_screen_filling_mode = screen_filling is True
|
entered_screen_filling_mode = screen_filling is True
|
||||||
login_style_reset = borderless_was_applied and borderless_now is False
|
login_style_reset = borderless_was_applied and borderless_now is False
|
||||||
|
if became_iconic:
|
||||||
|
print(
|
||||||
|
"Game startup window was minimized; leaving it minimized.",
|
||||||
|
file=sys.stderr,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
return False
|
||||||
if (
|
if (
|
||||||
not became_iconic
|
not entered_screen_filling_mode
|
||||||
and not entered_screen_filling_mode
|
|
||||||
and not login_style_reset
|
and not login_style_reset
|
||||||
):
|
):
|
||||||
time.sleep(WINDOW_STARTUP_POLL_SECONDS)
|
time.sleep(WINDOW_STARTUP_POLL_SECONDS)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
recovery_count += 1
|
recovery_count += 1
|
||||||
if became_iconic:
|
if entered_screen_filling_mode:
|
||||||
reason = "was minimized"
|
|
||||||
elif entered_screen_filling_mode:
|
|
||||||
reason = "entered fullscreen/maximized mode"
|
reason = "entered fullscreen/maximized mode"
|
||||||
else:
|
else:
|
||||||
reason = "changed its window layout"
|
reason = "changed its window layout"
|
||||||
|
|||||||
@@ -291,13 +291,16 @@ def _tune_process_window(
|
|||||||
window = mapper.find_window_by_pid(process.pid)
|
window = mapper.find_window_by_pid(process.pid)
|
||||||
if window is not None:
|
if window is not None:
|
||||||
increments = resize_increments(width, height)
|
increments = resize_increments(width, height)
|
||||||
|
# Some X11 window managers keep the maximize decoration hidden until
|
||||||
|
# both the size constraints and allowed actions advertise resizing.
|
||||||
|
scaling_enabled = mapper.enable_window_scaling(window)
|
||||||
increments_applied = mapper.set_resize_increments(
|
increments_applied = mapper.set_resize_increments(
|
||||||
window,
|
window,
|
||||||
(width, height),
|
(width, height),
|
||||||
increments,
|
increments,
|
||||||
)
|
)
|
||||||
compositing_preferred = mapper.prefer_composited_presentation(window)
|
compositing_preferred = mapper.prefer_composited_presentation(window)
|
||||||
if increments_applied and compositing_preferred:
|
if scaling_enabled and increments_applied and compositing_preferred:
|
||||||
return increments
|
return increments
|
||||||
time.sleep(WINDOW_DISCOVERY_POLL_SECONDS)
|
time.sleep(WINDOW_DISCOVERY_POLL_SECONDS)
|
||||||
return None
|
return None
|
||||||
|
|||||||
BIN
ptlinux/native/gamescope-3.16.20-ubuntu26.04-amd64
Executable file
BIN
ptlinux/native/gamescope-3.16.20-ubuntu26.04-amd64
Executable file
Binary file not shown.
54
ptlinux/native/gamescope-compat.README
Normal file
54
ptlinux/native/gamescope-compat.README
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
Gamescope compatibility binary
|
||||||
|
================================
|
||||||
|
|
||||||
|
gamescope-3.16.20-ubuntu26.04-amd64 is an isolated compatibility build for
|
||||||
|
Ubuntu 26.04 amd64. The launcher uses it only when the installed system
|
||||||
|
Gamescope reports version 3.16.20 and the binary passes its embedded SHA-256
|
||||||
|
check. It never replaces /usr/games/gamescope.
|
||||||
|
|
||||||
|
Source package:
|
||||||
|
Ubuntu gamescope 3.16.20+ds-1
|
||||||
|
gamescope_3.16.20+ds.orig.tar.xz
|
||||||
|
SHA-256 a27984fdab2bbfe353efc772de214ae88cccab07c4507747ed4b7f063b2faa0e
|
||||||
|
gamescope_3.16.20+ds-1.debian.tar.xz
|
||||||
|
SHA-256 ae6e9bac39b576e7d9c15912a713796049a29756f6858364ef49bd02197cb153
|
||||||
|
|
||||||
|
Build:
|
||||||
|
ubuntu:26.04 container
|
||||||
|
apt-get build-dep gamescope
|
||||||
|
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --build=binary --no-sign -jauto
|
||||||
|
|
||||||
|
The source changes are:
|
||||||
|
|
||||||
|
gamescope-wayland-letterbox-backing.patch
|
||||||
|
Backports upstream commit 66450376038864700f9b4721343b4d15b29c4198
|
||||||
|
("Use a backing surface for letter-boxing"). It fixes direct Wayland
|
||||||
|
output when a unity-scaled game surface has a nonzero letterbox offset.
|
||||||
|
|
||||||
|
gamescope-wayland-libdecor-input-scope.patch
|
||||||
|
Keeps libdecor titlebar and resize-border button events out of the nested
|
||||||
|
application while preserving complete button sequences that begin on the
|
||||||
|
game surface. This prevents a decoration operation from leaving the game
|
||||||
|
with a permanently held mouse button. It addresses the behavior tracked
|
||||||
|
at https://github.com/ValveSoftware/gamescope/issues/2299.
|
||||||
|
|
||||||
|
gamescope-lazy-output-images.patch
|
||||||
|
Backports upstream commit e383171ff1c0f7b5b37f05f2bb67f7c5282b087f
|
||||||
|
("rendervulkan: make the shared output images on first use"). Direct
|
||||||
|
Wayland frames no longer allocate six output-sized Vulkan images at every
|
||||||
|
intermediate host-window size.
|
||||||
|
|
||||||
|
gamescope-wayland-live-resize.patch
|
||||||
|
Skips the remaining device-idle wait and transparent fallback-image rebuild
|
||||||
|
when direct Wayland presentation has no live output images. Full-composition
|
||||||
|
frames still allocate correctly sized images on demand.
|
||||||
|
|
||||||
|
gamescope-keep-nested-windows-visible.patch
|
||||||
|
Honors PTLINUX_GAMESCOPE_KEEP_WINDOWS_VISIBLE by rejecting the game's
|
||||||
|
login-transition iconify request. The outer desktop window retains its
|
||||||
|
normal size and visibility while host minimize and focus remain untouched.
|
||||||
|
|
||||||
|
Binary SHA-256:
|
||||||
|
3fc81536c22dcce2c593c11507a612c13221f5b2ce2e5326f7c63706ca965639
|
||||||
|
|
||||||
|
Licensing and copyright notices are in gamescope-compat.copyright.
|
||||||
343
ptlinux/native/gamescope-compat.copyright
Normal file
343
ptlinux/native/gamescope-compat.copyright
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Source: https://github.com/ValveSoftware/gamescope
|
||||||
|
Upstream-Name: gamescope
|
||||||
|
Upstream-Contact: Pierre-Loup A. Griffais <https://www.valvesoftware.com/en/contact?contact-person=Pierre-Loup%20Griffais>
|
||||||
|
Comment: Build depends on libopenvr-dev which is in contrib
|
||||||
|
Files-Excluded:
|
||||||
|
# These files were excluded in the patch 0005_add_reshade_696b14c.patch
|
||||||
|
src/reshade/.gitignore
|
||||||
|
src/reshade/.gitmodules
|
||||||
|
src/reshade/res/main_icon.ico
|
||||||
|
src/reshade/res/main_icon_small.png
|
||||||
|
src/reshade/res/shaders/imgui_ps.spv
|
||||||
|
src/reshade/res/shaders/imgui_ps_hdr.spv
|
||||||
|
src/reshade/res/shaders/imgui_vs.spv
|
||||||
|
src/reshade/tools/7za.exe
|
||||||
|
src/reshade/examples
|
||||||
|
src/reshade/setup/Pages/Resources
|
||||||
|
# reshade gitmodules
|
||||||
|
src/reshade/deps/imgui
|
||||||
|
src/reshade/deps/minhook
|
||||||
|
src/reshade/deps/stb
|
||||||
|
src/reshade/deps/gl3w
|
||||||
|
src/reshade/deps/utfcpp
|
||||||
|
src/reshade/deps/spirv
|
||||||
|
src/reshade/deps/vma
|
||||||
|
src/reshade/deps/vulkan
|
||||||
|
src/reshade/deps/fpng
|
||||||
|
src/reshade/deps/d3d12
|
||||||
|
src/reshade/deps/openxr
|
||||||
|
|
||||||
|
|
||||||
|
Files:
|
||||||
|
*
|
||||||
|
Copyright:
|
||||||
|
2013-2023, Valve Corporation
|
||||||
|
2022, NVIDIA CORPORATION
|
||||||
|
License: BSD-2-Clause
|
||||||
|
|
||||||
|
Files: thirdparty/sol/*
|
||||||
|
Copyright: 2013-2020, Rapptz, ThePhD and contributors
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files: scripts/00-gamescope/common/inspect.lua
|
||||||
|
Copyright: 2022, Enrique García Cota
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files: src/color_helpers.h
|
||||||
|
Copyright: 2021-2022 Collabora, Ltd
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files: src/messagey.h
|
||||||
|
Copyright: 1997-2022, Sam Lantinga <slouken@libsdl.org>
|
||||||
|
License: Zlib
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/color-management-v1.xml
|
||||||
|
Copyright:
|
||||||
|
2019 Sebastian Wick
|
||||||
|
2019 Erwin Burema
|
||||||
|
2020 AMD
|
||||||
|
2020-2024 Collabora, Ltd.
|
||||||
|
2024 Xaver Hugl
|
||||||
|
2022-2025 Red Hat, Inc.
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/frog-color-management-v1.xml
|
||||||
|
Copyright:
|
||||||
|
2023, Joshua Ashton for Valve Software
|
||||||
|
2023, Xaver Hugl
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/gamescope-action-binding.xml
|
||||||
|
Copyright:
|
||||||
|
2024 Valve Corporation
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/gamescope-control.xml
|
||||||
|
protocol/gamescope-private.xml
|
||||||
|
Copyright:
|
||||||
|
2023 Valve Corporation
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/gamescope-input-method.xml
|
||||||
|
Copyright:
|
||||||
|
2008-2011 Kristian Høgsberg
|
||||||
|
2010-2011 Intel Corporation
|
||||||
|
2012-2013 Collabora, Ltd.
|
||||||
|
2012, 2013 Intel Corporation
|
||||||
|
2015, 2016 Jan Arne Petersen
|
||||||
|
2017, 2018 Red Hat, Inc.
|
||||||
|
2018 Purism SPC
|
||||||
|
2021 Valve Corporation
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/gamescope-pipewire.xml
|
||||||
|
protocol/gamescope-xwayland.xml
|
||||||
|
Copyright:
|
||||||
|
2021 Valve Corporation
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/gamescope-reshade.xml
|
||||||
|
Copyright:
|
||||||
|
2024, Wayne Heaney
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/gamescope-swapchain.xml
|
||||||
|
Copyright:
|
||||||
|
2023, Joshua Ashton for Valve Software
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/wlr-layer-shell-unstable-v1.xml
|
||||||
|
Copyright:
|
||||||
|
2017, Drew DeVault
|
||||||
|
License: HPND-sell-variant or NTP~disclaimer
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that copyright notice and this permission
|
||||||
|
notice appear in supporting documentation, and that the name of
|
||||||
|
the copyright holders not be used in advertising or publicity
|
||||||
|
pertaining to distribution of the software without specific,
|
||||||
|
written prior permission. The copyright holders make no
|
||||||
|
representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied
|
||||||
|
warranty.
|
||||||
|
.
|
||||||
|
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||||
|
THIS SOFTWARE.
|
||||||
|
|
||||||
|
Files:
|
||||||
|
protocol/xdg-toplevel-icon-v1.xml
|
||||||
|
Copyright:
|
||||||
|
2023-2024, Matthias Klumpp
|
||||||
|
2024, David Edmundson
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/shaders/NVIDIAImageScaling/*
|
||||||
|
Copyright:
|
||||||
|
2022 NVIDIA CORPORATION & AFFILIATES
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/shaders/ffx_*.h
|
||||||
|
Copyright:
|
||||||
|
2021 Advanced Micro Devices, Inc.
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/gpuvis_trace_utils.h
|
||||||
|
Copyright:
|
||||||
|
Michael Sartain
|
||||||
|
License: public-domain-dual
|
||||||
|
This software is dual-licensed to the public domain and under the following
|
||||||
|
license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||||
|
publish, and distribute this file as you see fit.
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/modegen.cpp
|
||||||
|
Copyright:
|
||||||
|
2005-2006 Luc Verhaegen
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/shaders/heatmap.h
|
||||||
|
Copyright:
|
||||||
|
Microsoft Corporation
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/steamcompmgr.cpp
|
||||||
|
Copyright:
|
||||||
|
2003 Keith Packard
|
||||||
|
Matthew Hawn
|
||||||
|
License: HPND-sell-variant
|
||||||
|
Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation, and that the name of Keith Packard not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the software without
|
||||||
|
specific, written prior permission. Keith Packard makes no
|
||||||
|
representations about the suitability of this software for any purpose. It
|
||||||
|
is provided "as is" without express or implied warranty.
|
||||||
|
.
|
||||||
|
KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
Files:
|
||||||
|
debian/*
|
||||||
|
Copyright:
|
||||||
|
2022-2024 Stephan Lachnit <stephanlachnit@debian.org>
|
||||||
|
2023-2024 Safir Secerovic <sapphire@linux.org.ba>
|
||||||
|
2025 Ilya Orlov <ilyaorlov124@gmail.com>,
|
||||||
|
License: BSD-2-Clause
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/reshade/*
|
||||||
|
Copyright:
|
||||||
|
2014-2024 Patrick Mours. All rights reserved.
|
||||||
|
License: BSD-3-Clause
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/reshade/deps/d3d911on12/*
|
||||||
|
Copyright:
|
||||||
|
Microsoft Corporation.
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
Files:
|
||||||
|
src/reshade/deps/vulkan_layer/vk_layer_dispatch_table.h
|
||||||
|
Copyright:
|
||||||
|
2015-2023, Google Inc.
|
||||||
|
2015-2023, LunarG, Inc.
|
||||||
|
2015-2023, The Khronos Group Inc.
|
||||||
|
2015-2023, Valve Corporation
|
||||||
|
License: Apache-2.0
|
||||||
|
|
||||||
|
Files: src/reshade/source/imgui_code_editor.cpp
|
||||||
|
Copyright:
|
||||||
|
2017, BalazsJako
|
||||||
|
2018, Patrick Mours
|
||||||
|
License: Expat
|
||||||
|
|
||||||
|
License: BSD-2-Clause
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
.
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
License: Expat
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
License: BSD-3-Clause
|
||||||
|
Copyright (c) The Regents of the University of California.
|
||||||
|
All rights reserved.
|
||||||
|
.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the University nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
License: Zlib
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
.
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
.
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
License: Apache-2.0
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
.
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
.
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
.
|
||||||
|
On Debian systems, the full text of the Apache Software License version 2 can
|
||||||
|
be found in the file `/usr/share/common-licenses/Apache-2.0'.
|
||||||
34
ptlinux/native/gamescope-keep-nested-windows-visible.patch
Normal file
34
ptlinux/native/gamescope-keep-nested-windows-visible.patch
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
From: PT Linux Launcher maintainers
|
||||||
|
Subject: Keep the nested game window visible during its login transition
|
||||||
|
|
||||||
|
PristonTale replaces its startup presentation while entering the login screen
|
||||||
|
and asks the nested X11 window manager to mark the game window iconic. Gamescope
|
||||||
|
3.16.20 acknowledges that request by publishing IconicState even though the
|
||||||
|
surface stays mapped. Wine then hides or resizes the client, which also changes
|
||||||
|
the outer Gamescope presentation.
|
||||||
|
|
||||||
|
When the launcher opts in through PTLINUX_GAMESCOPE_KEEP_WINDOWS_VISIBLE, keep
|
||||||
|
the nested client in NormalState. This is scoped to the launcher environment;
|
||||||
|
Gamescope retains its upstream behavior for every other invocation. Desktop
|
||||||
|
minimize and focus operate on the outer Wayland window and remain unaffected.
|
||||||
|
|
||||||
|
--- a/src/steamcompmgr.cpp
|
||||||
|
+++ b/src/steamcompmgr.cpp
|
||||||
|
@@ -5361,8 +5361,17 @@ static void
|
||||||
|
handle_wm_change_state(xwayland_ctx_t *ctx, steamcompmgr_win_t *w, XClientMessageEvent *ev)
|
||||||
|
{
|
||||||
|
long state = ev->data.l[0];
|
||||||
|
+ static const bool bKeepNestedWindowsVisible = env_to_bool(
|
||||||
|
+ getenv( "PTLINUX_GAMESCOPE_KEEP_WINDOWS_VISIBLE" ) );
|
||||||
|
|
||||||
|
if (state == ICCCM_ICONIC_STATE) {
|
||||||
|
+ if ( bKeepNestedWindowsVisible )
|
||||||
|
+ {
|
||||||
|
+ xwm_log.debugf("Ignoring WM_CHANGE_STATE to ICONIC for window 0x%lx", w->xwayland().id);
|
||||||
|
+ set_wm_state( ctx, w->xwayland().id, ICCCM_NORMAL_STATE );
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
xwm_log.debugf("Faking WM_CHANGE_STATE to ICONIC for window 0x%lx", w->xwayland().id);
|
||||||
|
set_wm_state( ctx, w->xwayland().id, ICCCM_ICONIC_STATE );
|
||||||
|
} else {
|
||||||
80
ptlinux/native/gamescope-lazy-output-images.patch
Normal file
80
ptlinux/native/gamescope-lazy-output-images.patch
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
From: Matthew Schwartz <matthew.schwartz@linux.dev>
|
||||||
|
Subject: Lazily allocate shared Vulkan output images
|
||||||
|
Origin: upstream, commit e383171ff1c0f7b5b37f05f2bb67f7c5282b087f
|
||||||
|
|
||||||
|
Backport the upstream lazy-allocation change to Gamescope 3.16.20. Native
|
||||||
|
Wayland presentation normally sends the game's DMA-BUF directly to the host
|
||||||
|
compositor, so allocating six output-sized Vulkan images at startup and after
|
||||||
|
every host-window configure is unnecessary. Allocate those images only if a
|
||||||
|
frame actually needs full Vulkan composition.
|
||||||
|
|
||||||
|
--- a/src/rendervulkan.cpp
|
||||||
|
+++ b/src/rendervulkan.cpp
|
||||||
|
@@ -3345,6 +3345,31 @@ static bool vulkan_make_output_images( VulkanOutput_t *pOutput )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+// Without a swapchain the shared images are ours to make, so they wait for their first use.
|
||||||
|
+static bool vulkan_defer_output_images()
|
||||||
|
+{
|
||||||
|
+ return !GetBackend()->UsesVulkanSwapchain();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool vulkan_ensure_output_images()
|
||||||
|
+{
|
||||||
|
+ if ( !vulkan_defer_output_images() )
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ VulkanOutput_t *pOutput = &g_output;
|
||||||
|
+ if ( !pOutput->outputImages.empty() && pOutput->outputImages[0] )
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ vk_log.debugf( "Making the shared output images on first use" );
|
||||||
|
+ if ( vulkan_make_output_images( pOutput ) )
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ // A half-made set would pass the check above, so the next use tries again from nothing.
|
||||||
|
+ pOutput->outputImages.clear();
|
||||||
|
+ pOutput->outputImagesPartialOverlay.clear();
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool vulkan_remake_output_images()
|
||||||
|
{
|
||||||
|
VulkanOutput_t *pOutput = &g_output;
|
||||||
|
@@ -3355,6 +3380,14 @@ bool vulkan_remake_output_images()
|
||||||
|
for (auto& pScreenshotImage : pOutput->pScreenshotImages)
|
||||||
|
pScreenshotImage = nullptr;
|
||||||
|
|
||||||
|
+ if ( vulkan_defer_output_images() )
|
||||||
|
+ {
|
||||||
|
+ pOutput->outputImages.clear();
|
||||||
|
+ pOutput->outputImagesPartialOverlay.clear();
|
||||||
|
+ pOutput->temporaryHackyBlankImage = vulkan_create_debug_blank_texture();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
bool bRet = vulkan_make_output_images( pOutput );
|
||||||
|
assert( bRet );
|
||||||
|
return bRet;
|
||||||
|
@@ -3433,7 +3466,9 @@ bool vulkan_make_output()
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ( !vulkan_make_output_images( pOutput ) )
|
||||||
|
+ if ( vulkan_defer_output_images() )
|
||||||
|
+ pOutput->temporaryHackyBlankImage = vulkan_create_debug_blank_texture();
|
||||||
|
+ else if ( !vulkan_make_output_images( pOutput ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -3980,6 +4015,9 @@ std::optional<uint64_t> vulkan_composite( struct FrameInfo_t *frameInfo, gamesco
|
||||||
|
g_reshadeManager.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if ( !pOutputOverride && !vulkan_ensure_output_images() )
|
||||||
|
+ return std::nullopt;
|
||||||
|
+
|
||||||
|
gamescope::Rc<CVulkanTexture> compositeImage;
|
||||||
|
if ( pOutputOverride )
|
||||||
|
compositeImage = pOutputOverride;
|
||||||
21
ptlinux/native/gamescope-wayland-letterbox-backing.patch
Normal file
21
ptlinux/native/gamescope-wayland-letterbox-backing.patch
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
From: PT Linux Launcher maintainers
|
||||||
|
Subject: Use a backing surface for letter-boxing
|
||||||
|
|
||||||
|
Backport upstream commit 66450376038864700f9b4721343b4d15b29c4198 so
|
||||||
|
native Wayland presentation covers the complete configured output when the
|
||||||
|
game layer is unity-scaled with a non-zero letterbox offset.
|
||||||
|
|
||||||
|
--- a/src/Backends/WaylandBackend.cpp
|
||||||
|
+++ b/src/Backends/WaylandBackend.cpp
|
||||||
|
@@ -1081,7 +1081,10 @@ namespace gamescope
|
||||||
|
bool bNeedsBacking = true;
|
||||||
|
if ( pFrameInfo->layerCount >= 1 )
|
||||||
|
{
|
||||||
|
- if ( pFrameInfo->layers[0].isScreenSize() && !pFrameInfo->layers[0].hasAlpha() )
|
||||||
|
+ if ( pFrameInfo->layers[0].isScreenSize() &&
|
||||||
|
+ close_enough( pFrameInfo->layers[0].offset.x, 0.0f ) &&
|
||||||
|
+ close_enough( pFrameInfo->layers[0].offset.y, 0.0f ) &&
|
||||||
|
+ !pFrameInfo->layers[0].hasAlpha() )
|
||||||
|
bNeedsBacking = false;
|
||||||
|
}
|
||||||
|
|
||||||
64
ptlinux/native/gamescope-wayland-libdecor-input-scope.patch
Normal file
64
ptlinux/native/gamescope-wayland-libdecor-input-scope.patch
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
From: PT Linux Launcher maintainers
|
||||||
|
Subject: Keep client-side decoration clicks out of nested applications
|
||||||
|
Bug: https://github.com/ValveSoftware/gamescope/issues/2299
|
||||||
|
Forwarded: https://github.com/ValveSoftware/gamescope/issues/2299
|
||||||
|
|
||||||
|
On compositors without xdg-decoration support, libdecor creates client-side
|
||||||
|
surfaces owned by the Gamescope Wayland connection. Pointer button callbacks
|
||||||
|
for those titlebar and resize surfaces consequently also reach Gamescope's
|
||||||
|
input thread. Forwarding a decoration press to the nested application can
|
||||||
|
leave its button permanently held because libdecor consumes the matching
|
||||||
|
release while performing a move, resize, or maximize operation.
|
||||||
|
|
||||||
|
Only begin nested button sequences while the pointer is over Gamescope's
|
||||||
|
actual toplevel surface. Track those presses so their releases are delivered
|
||||||
|
even if the pointer or keyboard focus changes during a game-originated drag.
|
||||||
|
|
||||||
|
--- a/src/Backends/WaylandBackend.cpp
|
||||||
|
+++ b/src/Backends/WaylandBackend.cpp
|
||||||
|
@@ -562,6 +562,7 @@
|
||||||
|
|
||||||
|
std::atomic<std::shared_ptr<zwp_relative_pointer_v1>> m_pRelativePointer = nullptr;
|
||||||
|
std::unordered_set<uint32_t> m_uScancodesHeld;
|
||||||
|
+ std::unordered_set<uint32_t> m_uMouseButtonsHeld;
|
||||||
|
|
||||||
|
void Wayland_Registry_Global( wl_registry *pRegistry, uint32_t uName, const char *pInterface, uint32_t uVersion );
|
||||||
|
static const wl_registry_listener s_RegistryListener;
|
||||||
|
@@ -3091,13 +3092,33 @@
|
||||||
|
}
|
||||||
|
void CWaylandInputThread::Wayland_Pointer_Button( wl_pointer *pPointer, uint32_t uSerial, uint32_t uTime, uint32_t uButton, uint32_t uState )
|
||||||
|
{
|
||||||
|
- // Don't do any motion/movement stuff if we don't have kb focus
|
||||||
|
- if ( !cv_wayland_mouse_warp_without_keyboard_focus && !m_bKeyboardEntered )
|
||||||
|
- return;
|
||||||
|
+ const bool bPressed = uState == WL_POINTER_BUTTON_STATE_PRESSED;
|
||||||
|
+ const bool bWasPressed = m_uMouseButtonsHeld.contains( uButton );
|
||||||
|
+
|
||||||
|
+ if ( bPressed )
|
||||||
|
+ {
|
||||||
|
+ // libdecor's client-side decorations share our Wayland seat, but
|
||||||
|
+ // their button events must not be sent to the nested application.
|
||||||
|
+ if ( !m_bMouseEntered || bWasPressed )
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ // Don't start an application click without keyboard focus.
|
||||||
|
+ if ( !cv_wayland_mouse_warp_without_keyboard_focus && !m_bKeyboardEntered )
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ else if ( !bWasPressed )
|
||||||
|
+ {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
wlserver_lock();
|
||||||
|
- wlserver_mousebutton( uButton, uState == WL_POINTER_BUTTON_STATE_PRESSED, ++m_uFakeTimestamp );
|
||||||
|
+ wlserver_mousebutton( uButton, bPressed, ++m_uFakeTimestamp );
|
||||||
|
wlserver_unlock();
|
||||||
|
+
|
||||||
|
+ if ( bPressed )
|
||||||
|
+ m_uMouseButtonsHeld.emplace( uButton );
|
||||||
|
+ else
|
||||||
|
+ m_uMouseButtonsHeld.erase( uButton );
|
||||||
|
}
|
||||||
|
void CWaylandInputThread::Wayland_Pointer_Axis( wl_pointer *pPointer, uint32_t uTime, uint32_t uAxis, wl_fixed_t fValue )
|
||||||
|
{
|
||||||
50
ptlinux/native/gamescope-wayland-live-resize.patch
Normal file
50
ptlinux/native/gamescope-wayland-live-resize.patch
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
From: PT Linux Launcher maintainers
|
||||||
|
Subject: Avoid idle waits for direct Wayland resize configures
|
||||||
|
|
||||||
|
The lazy-output-images backport leaves no shared output images allocated while
|
||||||
|
Gamescope is presenting the game directly as Wayland planes. A host-window
|
||||||
|
configure nevertheless calls vulkan_remake_output_images(), whose unconditional
|
||||||
|
device-idle wait and output-sized blank-texture recreation stall the compositor
|
||||||
|
thread for every intermediate drag size.
|
||||||
|
|
||||||
|
Wait only when an output or screenshot image actually exists. The transparent
|
||||||
|
fallback texture is unused by the non-session Wayland backend, so retain it
|
||||||
|
across Wayland size changes; session backends preserve the existing recreation
|
||||||
|
behavior. If a frame later requires full composition, the lazy allocation path
|
||||||
|
creates correctly sized output images before rendering it.
|
||||||
|
|
||||||
|
--- a/src/rendervulkan.cpp
|
||||||
|
+++ b/src/rendervulkan.cpp
|
||||||
|
@@ -3374,7 +3374,21 @@ static bool vulkan_ensure_output_images()
|
||||||
|
bool vulkan_remake_output_images()
|
||||||
|
{
|
||||||
|
VulkanOutput_t *pOutput = &g_output;
|
||||||
|
- g_device.waitIdle();
|
||||||
|
+ bool bHasLiveImages =
|
||||||
|
+ !pOutput->outputImages.empty() && pOutput->outputImages[0];
|
||||||
|
+ if ( !bHasLiveImages )
|
||||||
|
+ {
|
||||||
|
+ for ( const auto &pScreenshotImage : pOutput->pScreenshotImages )
|
||||||
|
+ {
|
||||||
|
+ if ( pScreenshotImage )
|
||||||
|
+ {
|
||||||
|
+ bHasLiveImages = true;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if ( bHasLiveImages )
|
||||||
|
+ g_device.waitIdle();
|
||||||
|
|
||||||
|
pOutput->nOutImage = 0;
|
||||||
|
|
||||||
|
@@ -3386,7 +3400,8 @@ bool vulkan_remake_output_images()
|
||||||
|
{
|
||||||
|
pOutput->outputImages.clear();
|
||||||
|
pOutput->outputImagesPartialOverlay.clear();
|
||||||
|
- pOutput->temporaryHackyBlankImage = vulkan_create_debug_blank_texture();
|
||||||
|
+ if ( GetBackend()->IsSessionBased() || !pOutput->temporaryHackyBlankImage )
|
||||||
|
+ pOutput->temporaryHackyBlankImage = vulkan_create_debug_blank_texture();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user