Compare commits

...

29 Commits

Author SHA1 Message Date
Vaxry
eb3b38d40b
eventLoop: fixup event source callbacks 2025-05-19 01:27:30 +02:00
Vaxry
d9c8a37811
input: always allow focus to permission popups 2025-05-18 19:34:20 +02:00
Vaxry
158c0f2911
permissions: add permission management for keyboards (#10367) 2025-05-18 19:13:20 +02:00
zacoons
44cb8f769e
internal: added error log when getEdgeDefinedPoint is impossible (#10462) 2025-05-18 19:10:06 +02:00
Vaxry
705b97c4ac
input: revert #10416 and #10418
fixes #10451
2025-05-17 19:43:12 +02:00
Vaxry
c19f383685
hyprpm: fix crash with enable without an arg 2025-05-17 19:07:18 +02:00
Vaxry
bb5cd5b2dd
screencopy: store a fb before permission popup if the permission is pending (#10455)
stops rendering the permission popup on stuff like grim when it asks
2025-05-17 19:03:35 +02:00
Vaxry
bb9aa79b21
hyprpm: reject remove without a param
ref #10458
2025-05-17 18:10:35 +02:00
Vaxry
dfa4836216
hyprpm: fix execute permission bit on installed dirs (#10435) 2025-05-17 18:08:42 +02:00
vaxerski
18377d221d [gha] Nix: update inputs 2025-05-17 11:08:13 +00:00
outfoxxed
2aa21625bd
input: ensure seat grabs from exclusive layers can be dismissed (#10418) 2025-05-17 13:06:48 +02:00
outfoxxed
2946009006
input: do not send mouse events when outside of a surface (#10416) 2025-05-16 23:39:28 +02:00
outfoxxed
b0cc49218d
protocols: simulate mouse movement after activating a toplevel (#10429) 2025-05-16 23:38:45 +02:00
Zach DeCook
a5c9b3e490
core: Include cstring whenever strncpy is used (#10404)
Fixes ppc64le build in alpine
2025-05-15 10:31:44 +01:00
outfoxxed
dfb841c303
desktop: prevent layers from dismissing their own seat grabs on map (#10417) 2025-05-15 10:16:03 +01:00
Tom Englund
5ceb0ec15d
core: drop the legacy renderer (#10408)
* core: drop the legacy renderer

the legacy renderer is broken and barely used, drop it.

* Nix: drop support for legacyRenderer

---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
2025-05-15 10:13:24 +01:00
outfoxxed
f707d86912
protocols/hyprland-surface: account for scaled monitor positions (#10415) 2025-05-15 10:12:55 +01:00
Yukari Chiba
75f2cb5f65
xwayland: do not include xcb.h when xwayland is disabled (#10407)
xcb.h should not be included when xwayland is disabled. 
This allows hyprland to not use X11 libraries at all when xwayland is disabled.
2025-05-14 19:31:19 +01:00
Vaxry
a51e639d81
input: disallow virtual keyboards from changing LED state (#10402) 2025-05-14 17:48:17 +01:00
Tom Englund
59b2340680
opengl: add missing vao for screenshader (#10397)
missed creating vertex array objects in 04124988e8b4a9cdfc5995388ebfaad0005b4b31
add it.
2025-05-13 23:46:29 +01:00
outfoxxed
da3583fd5e
opengl: publicize shader creation/usage functions (#10378)
Allows plugins to create and use shaders again
2025-05-12 14:15:47 +02:00
Tom Englund
04124988e8
opengl: optimize shaders and reduce unneeded drawcalls (#10364)
* opengl: remove unnecessery glflush calls

glflushing forces the driver to break batching and issue commands
prematurely and prevents optimisations like command reordering and
merging.

many glFunctions already internally glflushes and eglsync creation still
has a glflush at end render. so lets reduce the overhead of these calls.

* opengl: reduce glUseProgram calls

apitrace shows cases where the same program gets called multiple times,
add a helper function that keeps track of current program and only call
it once on same program. reduces slight overhead.

* opengl: use more efficient vertex array object

use a more modern vertex array object approach with the shaders, makes
it a onetime setup on shader creation instead of once per drawcall, also
should make the driver not have to revalidate the vertex format on each
call.
2025-05-11 18:36:20 +02:00
Vaxry
390a357859
renderer: use alpha for the lockttytext texture
ref #10348
2025-05-11 13:15:03 +01:00
Vaxry
9a87498bb1
renderer: minor damage fixes 2025-05-10 23:53:05 +01:00
Vaxry
f58bb72d3a
renderer: render blur on fade out (#10356) 2025-05-10 19:31:26 +02:00
vaxerski
60cd5b7a48 renderer: always render snapshots as 8bit
fixes issues with transparent windows on 10b
2025-05-09 22:16:21 +01:00
Florian "sp1rit
25cf06f6cf
build: require hyprgraphics>=0.1.3 (#10350)
49974d5 introduced use of types, which were only added in 0.1.3
2025-05-09 14:47:28 +02:00
Jan Beich
e44aae0c20
hyprpm: switch to numeric owner/group after f8bbe5124c00 (#10345)
On BSDs "root" is in "wheel" group. Instead of enumerating platforms
or probing "wheel" explicitly use numeric value for the superuser.

$ truss hyprpm add <url>
[...]
read(5,"install: unknown group root\n",1023)     = 28 (0x1c)
[...]
[ERR] ✖ Failed to write plugin state
2025-05-09 14:18:15 +02:00
Jan Beich
fcb6f936ea
hyprpm: add missing include for libc++ after 1c530cbc66db (#10344)
hyprpm/src/helpers/Sys.cpp:24:24: error: implicit instantiation of undefined temp
late 'std::basic_ostringstream<char>'
   24 |     std::ostringstream oss;
      |                        ^
/usr/include/c++/v1/__fwd/sstream.h:27:28: note: template is declared here
   27 | class _LIBCPP_TEMPLATE_VIS basic_ostringstream;
      |                            ^
2025-05-09 03:42:19 +02:00
52 changed files with 477 additions and 509 deletions

View File

@ -99,18 +99,14 @@ message(STATUS "Checking deps...")
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
if(LEGACY_RENDERER) set(GLES_VERSION "GLES3")
set(GLES_VERSION "GLES2")
else()
set(GLES_VERSION "GLES3")
endif()
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.8.0) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.8.0)
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.7.0) pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.7.0)
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.3)
string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION}) string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION})
list(GET AQ_VERSION_LIST 0 AQ_VERSION_MAJOR) list(GET AQ_VERSION_LIST 0 AQ_VERSION_MAJOR)
@ -216,11 +212,6 @@ if(NOT HAS_INOTIFY AND inotify_FOUND)
target_link_libraries(Hyprland PkgConfig::inotify) target_link_libraries(Hyprland PkgConfig::inotify)
endif() endif()
if(LEGACY_RENDERER)
message(STATUS "Using the legacy GLES2 renderer!")
add_compile_definitions(LEGACY_RENDERER)
endif()
if(NO_XWAYLAND) if(NO_XWAYLAND)
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!") message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
add_compile_definitions(NO_XWAYLAND) add_compile_definitions(NO_XWAYLAND)

View File

@ -3,14 +3,6 @@ PREFIX = /usr/local
stub: stub:
@echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland." @echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland."
legacyrenderer:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
legacyrendererdebug:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
release: release:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`

12
flake.lock generated
View File

@ -276,11 +276,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1746461020, "lastModified": 1747327360,
"narHash": "sha256-7+pG1I9jvxNlmln4YgnlW4o+w0TZX24k688mibiFDUE=", "narHash": "sha256-LSmTbiq/nqZR9B2t4MRnWG7cb0KVNU70dB7RT4+wYK4=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "3730d8a308f94996a9ba7c7138ede69c1b9ac4ae", "rev": "e06158e58f3adee28b139e9c2bcfcc41f8625b46",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -299,11 +299,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1746537231, "lastModified": 1747372754,
"narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=", "narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "fa466640195d38ec97cf0493d6d6882bc4d14969", "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -132,7 +132,6 @@
# hyprland-packages # hyprland-packages
hyprland hyprland
hyprland-debug hyprland-debug
hyprland-legacy-renderer
hyprland-unwrapped hyprland-unwrapped
# hyprland-extras # hyprland-extras
xdg-desktop-portal-hyprland xdg-desktop-portal-hyprland

View File

@ -5,6 +5,7 @@
#include <print> #include <print>
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h> #include <unistd.h>
#include <cstring>
static int getUID() { static int getUID() {
const auto UID = getuid(); const auto UID = getuid();

View File

@ -566,7 +566,7 @@ bool CPluginManager::updateHeaders(bool force) {
ret = execAndGet(cmd); ret = execAndGet(cmd);
cmd = std::format("make -C '{}' installheaders && chmod -R 644 '{}' && find '{}' -type d -exec chmod o+x {{}} \\;", WORKINGDIR, DataState::getHeadersPath(), cmd = std::format("make -C '{}' installheaders && chmod -R 644 '{}' && find '{}' -type d -exec chmod a+x {{}} \\;", WORKINGDIR, DataState::getHeadersPath(),
DataState::getHeadersPath()); DataState::getHeadersPath());
if (m_bVerbose) if (m_bVerbose)

View File

@ -4,6 +4,7 @@
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
#include <sstream>
#include <print> #include <print>
#include <filesystem> #include <filesystem>
#include <algorithm> #include <algorithm>
@ -152,7 +153,7 @@ bool NSys::root::install(const std::string& what, const std::string& where, cons
if (!std::ranges::all_of(mode, [](const char& c) { return c >= '0' && c <= '9'; })) if (!std::ranges::all_of(mode, [](const char& c) { return c >= '0' && c <= '9'; }))
return false; return false;
CProcess proc(subin(), {"install", "-m" + mode, "-o", "root", "-g", "root", what, where}); CProcess proc(subin(), {"install", "-m" + mode, "-o", "0", "-g", "0", what, where});
return proc.runSync() && proc.exitCode() == 0; return proc.runSync() && proc.exitCode() == 0;
} }

View File

@ -106,7 +106,7 @@ int main(int argc, char** argv, char** envp) {
return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1; return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1;
} else if (command[0] == "remove") { } else if (command[0] == "remove") {
if (ARGS.size() < 2) { if (command.size() < 2) {
std::println(stderr, "{}", failureString("Not enough args for remove.")); std::println(stderr, "{}", failureString("Not enough args for remove."));
return 1; return 1;
} }
@ -142,7 +142,7 @@ int main(int argc, char** argv, char** envp) {
} else if (notify) } else if (notify)
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers"); g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers");
} else if (command[0] == "enable") { } else if (command[0] == "enable") {
if (ARGS.size() < 2) { if (command.size() < 2) {
std::println(stderr, "{}", failureString("Not enough args for enable.")); std::println(stderr, "{}", failureString("Not enough args for enable."));
return 1; return 1;
} }

View File

@ -33,7 +33,7 @@ endif
aquamarine = dependency('aquamarine', version: '>=0.8.0') aquamarine = dependency('aquamarine', version: '>=0.8.0')
hyprcursor = dependency('hyprcursor', version: '>=0.1.7') hyprcursor = dependency('hyprcursor', version: '>=0.1.7')
hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.1') hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.3')
hyprlang = dependency('hyprlang', version: '>= 0.3.2') hyprlang = dependency('hyprlang', version: '>= 0.3.2')
hyprutils = dependency('hyprutils', version: '>= 0.7.0') hyprutils = dependency('hyprutils', version: '>= 0.7.0')
aquamarine_version_list = aquamarine.version().split('.') aquamarine_version_list = aquamarine.version().split('.')
@ -77,10 +77,6 @@ if (systemd_option.enabled())
subdir('systemd') subdir('systemd')
endif endif
if get_option('legacy_renderer').enabled()
add_project_arguments('-DLEGACY_RENDERER', language: 'cpp')
endif
if get_option('buildtype') == 'debug' if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp') add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif endif

View File

@ -1,6 +1,5 @@
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration') option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')
option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)') option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)')
option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
option('hyprpm', type: 'feature', value: 'enabled', description: 'Enable hyprpm') option('hyprpm', type: 'feature', value: 'enabled', description: 'Enable hyprpm')
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling') option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')

View File

@ -41,7 +41,6 @@
xwayland, xwayland,
debug ? false, debug ? false,
enableXWayland ? true, enableXWayland ? true,
legacyRenderer ? false,
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd, withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
wrapRuntimeDeps ? true, wrapRuntimeDeps ? true,
version ? "git", version ? "git",
@ -52,6 +51,7 @@
enableNvidiaPatches ? false, enableNvidiaPatches ? false,
nvidiaPatches ? false, nvidiaPatches ? false,
hidpiXWayland ? false, hidpiXWayland ? false,
legacyRenderer ? false,
}: let }: let
inherit (builtins) baseNameOf foldl' readFile; inherit (builtins) baseNameOf foldl' readFile;
inherit (lib.asserts) assertMsg; inherit (lib.asserts) assertMsg;
@ -70,6 +70,7 @@ in
assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
assert assertMsg (!legacyRenderer) "The option `legacyRenderer` has been removed. Legacy renderer is no longer supported.";
customStdenv.mkDerivation (finalAttrs: { customStdenv.mkDerivation (finalAttrs: {
pname = "hyprland${optionalString debug "-debug"}"; pname = "hyprland${optionalString debug "-debug"}";
inherit version; inherit version;
@ -142,7 +143,7 @@ in
wayland-scanner wayland-scanner
xorg.libXcursor xorg.libXcursor
] ]
(optionals customStdenv.hostPlatform.isBSD [ epoll-shim ]) (optionals customStdenv.hostPlatform.isBSD [epoll-shim])
(optionals customStdenv.hostPlatform.isMusl [libexecinfo]) (optionals customStdenv.hostPlatform.isMusl [libexecinfo])
(optionals enableXWayland [ (optionals enableXWayland [
xorg.libxcb xorg.libxcb
@ -165,7 +166,6 @@ in
mesonFlags = flatten [ mesonFlags = flatten [
(mapAttrsToList mesonEnable { (mapAttrsToList mesonEnable {
"xwayland" = enableXWayland; "xwayland" = enableXWayland;
"legacy_renderer" = legacyRenderer;
"systemd" = withSystemd; "systemd" = withSystemd;
"uwsm" = false; "uwsm" = false;
"hyprpm" = false; "hyprpm" = false;

View File

@ -50,9 +50,15 @@ in {
hyprutils = final.hyprutils.override {debug = true;}; hyprutils = final.hyprutils.override {debug = true;};
debug = true; debug = true;
}; };
hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;};
# deprecated packages # deprecated packages
hyprland-legacy-renderer =
builtins.trace ''
hyprland-legacy-renderer was removed. Please use the hyprland package.
Legacy renderer is no longer supported.
''
final.hyprland;
hyprland-nvidia = hyprland-nvidia =
builtins.trace '' builtins.trace ''
hyprland-nvidia was removed. Please use the hyprland package. hyprland-nvidia was removed. Please use the hyprland package.

View File

@ -870,10 +870,14 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
static auto PBORDERGRABEXTEND = CConfigValue<Hyprlang::INT>("general:extend_border_grab_area"); static auto PBORDERGRABEXTEND = CConfigValue<Hyprlang::INT>("general:extend_border_grab_area");
static auto PSPECIALFALLTHRU = CConfigValue<Hyprlang::INT>("input:special_fallthrough"); static auto PSPECIALFALLTHRU = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
const bool ONLY_PRIORITY = properties & FOCUS_PRIORITY;
// pinned windows on top of floating regardless // pinned windows on top of floating regardless
if (properties & ALLOW_FLOATING) { if (properties & ALLOW_FLOATING) {
for (auto const& w : m_windows | std::views::reverse) { for (auto const& w : m_windows | std::views::reverse) {
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
if (w->m_isFloating && w->m_isMapped && !w->isHidden() && !w->m_X11ShouldntFocus && w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { if (w->m_isFloating && w->m_isMapped && !w->isHidden() && !w->m_X11ShouldntFocus && w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow) {
const auto BB = w->getWindowBoxUnified(properties); const auto BB = w->getWindowBoxUnified(properties);
CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0); CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0);
@ -898,6 +902,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
if (!w->m_workspace) if (!w->m_workspace)
continue; continue;
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
const auto PWINDOWMONITOR = w->m_monitor.lock(); const auto PWINDOWMONITOR = w->m_monitor.lock();
// to avoid focusing windows behind special workspaces from other monitors // to avoid focusing windows behind special workspaces from other monitors
@ -950,7 +957,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
const WORKSPACEID WSPID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID(); const WORKSPACEID WSPID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID();
const auto PWORKSPACE = getWorkspaceByID(WSPID); const auto PWORKSPACE = getWorkspaceByID(WSPID);
if (PWORKSPACE->m_hasFullscreenWindow && !(properties & SKIP_FULLSCREEN_PRIORITY)) if (PWORKSPACE->m_hasFullscreenWindow && !(properties & SKIP_FULLSCREEN_PRIORITY) && !ONLY_PRIORITY)
return PWORKSPACE->getFullscreenWindow(); return PWORKSPACE->getFullscreenWindow();
auto found = floating(false); auto found = floating(false);
@ -959,6 +966,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
// for windows, we need to check their extensions too, first. // for windows, we need to check their extensions too, first.
for (auto const& w : m_windows) { for (auto const& w : m_windows) {
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
if (special != w->onSpecialWorkspace()) if (special != w->onSpecialWorkspace())
continue; continue;
@ -973,6 +983,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
} }
for (auto const& w : m_windows) { for (auto const& w : m_windows) {
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
if (special != w->onSpecialWorkspace()) if (special != w->onSpecialWorkspace())
continue; continue;
@ -1083,6 +1096,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse"); static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough"); static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
if (!pWindow || !pWindow->priorityFocus()) {
if (g_pSessionLockManager->isSessionLocked()) { if (g_pSessionLockManager->isSessionLocked()) {
Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock"); Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock");
return; return;
@ -1092,6 +1106,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls"); Debug::log(LOG, "Refusing a keyboard focus to a window because of an exclusive ls");
return; return;
} }
}
if (pWindow && pWindow->m_isX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_xwaylandSurface->wantsFocus()) if (pWindow && pWindow->m_isX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_xwaylandSurface->wantsFocus())
return; return;
@ -1487,7 +1502,6 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) {
Debug::log(LOG, "Cleanup: destroyed a layersurface"); Debug::log(LOG, "Cleanup: destroyed a layersurface");
glFlush(); // to free mem NOW.
return; return;
} }
} }

View File

@ -2900,6 +2900,8 @@ std::optional<std::string> CConfigManager::handlePermission(const std::string& c
type = PERMISSION_TYPE_SCREENCOPY; type = PERMISSION_TYPE_SCREENCOPY;
else if (data[1] == "plugin") else if (data[1] == "plugin")
type = PERMISSION_TYPE_PLUGIN; type = PERMISSION_TYPE_PLUGIN;
else if (data[1] == "keyboard" || data[1] == "keeb")
type = PERMISSION_TYPE_KEYBOARD;
if (data[2] == "ask") if (data[2] == "ask")
mode = PERMISSION_RULE_ALLOW_MODE_ASK; mode = PERMISSION_RULE_ALLOW_MODE_ASK;

View File

@ -109,9 +109,6 @@ void NCrashReporter::createAndSaveCrash(int sig) {
finalCrashReport += "\nDate: "; finalCrashReport += "\nDate: ";
finalCrashReport += GIT_COMMIT_DATE; finalCrashReport += GIT_COMMIT_DATE;
finalCrashReport += "\nFlags:\n"; finalCrashReport += "\nFlags:\n";
#ifdef LEGACY_RENDERER
finalCrashReport += "legacyrenderer\n";
#endif
#if ISDEBUG #if ISDEBUG
finalCrashReport += "debug\n"; finalCrashReport += "debug\n";
#endif #endif

View File

@ -931,13 +931,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION, HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION,
HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION); HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
#if (!defined(LEGACY_RENDERER) && !ISDEBUG && !defined(NO_XWAYLAND)) #if (!ISDEBUG && !defined(NO_XWAYLAND))
result += "no flags were set\n"; result += "no flags were set\n";
#else #else
result += "flags set:\n"; result += "flags set:\n";
#ifdef LEGACY_RENDERER
result += "legacyrenderer\n";
#endif
#if ISDEBUG #if ISDEBUG
result += "debug\n"; result += "debug\n";
#endif #endif
@ -966,9 +963,6 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_BRANCH, GIT_COMMIT_HASH, HYPRLAND_VERSION, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG,
GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION); GIT_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
#ifdef LEGACY_RENDERER
result += "\"legacyrenderer\",";
#endif
#if ISDEBUG #if ISDEBUG
result += "\"debug\","; result += "\"debug\",";
#endif #endif

View File

@ -263,11 +263,8 @@ void CHyprDebugOverlay::draw() {
glBindTexture(GL_TEXTURE_2D, m_texture->m_texID); glBindTexture(GL_TEXTURE_2D, m_texture->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);

View File

@ -238,11 +238,8 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
glBindTexture(GL_TEXTURE_2D, m_texture->m_texID); glBindTexture(GL_TEXTURE_2D, m_texture->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);

View File

@ -167,7 +167,9 @@ void CLayerSurface::onMap() {
if (GRABSFOCUS) { if (GRABSFOCUS) {
// TODO: use the new superb really very cool grab // TODO: use the new superb really very cool grab
if (g_pSeatManager->m_seatGrab && !g_pSeatManager->m_seatGrab->accepts(m_surface->resource()))
g_pSeatManager->setGrab(nullptr); g_pSeatManager->setGrab(nullptr);
g_pInputManager->releaseAllMouseButtons(); g_pInputManager->releaseAllMouseButtons();
g_pCompositor->focusSurface(m_surface->resource()); g_pCompositor->focusSurface(m_surface->resource());

View File

@ -1149,7 +1149,7 @@ bool CWindow::opaque() {
if (m_wlSurface->small() && !m_wlSurface->m_fillIgnoreSmall) if (m_wlSurface->small() && !m_wlSurface->m_fillIgnoreSmall)
return false; return false;
if (PWORKSPACE->m_alpha->value() != 1.f) if (PWORKSPACE && PWORKSPACE->m_alpha->value() != 1.f)
return false; return false;
if (m_isX11 && m_xwaylandSurface && m_xwaylandSurface->m_surface && m_xwaylandSurface->m_surface->m_current.texture) if (m_isX11 && m_xwaylandSurface && m_xwaylandSurface->m_surface && m_xwaylandSurface->m_surface->m_current.texture)
@ -1836,3 +1836,7 @@ PHLWINDOW CWindow::parent() {
return m_xdgSurface->m_toplevel->m_parent->m_window.lock(); return m_xdgSurface->m_toplevel->m_parent->m_window.lock();
} }
bool CWindow::priorityFocus() {
return !m_isX11 && CAsyncDialogBox::isPriorityDialogBox(getPID());
}

View File

@ -51,6 +51,7 @@ enum eGetWindowProperties : uint8_t {
ALLOW_FLOATING = 1 << 4, ALLOW_FLOATING = 1 << 4,
USE_PROP_TILED = 1 << 5, USE_PROP_TILED = 1 << 5,
SKIP_FULLSCREEN_PRIORITY = 1 << 6, SKIP_FULLSCREEN_PRIORITY = 1 << 6,
FOCUS_PRIORITY = 1 << 7,
}; };
enum eSuppressEvents : uint8_t { enum eSuppressEvents : uint8_t {
@ -408,6 +409,7 @@ class CWindow {
std::optional<std::string> xdgTag(); std::optional<std::string> xdgTag();
std::optional<std::string> xdgDescription(); std::optional<std::string> xdgDescription();
PHLWINDOW parent(); PHLWINDOW parent();
bool priorityFocus();
CBox getWindowMainSurfaceBox() const { CBox getWindowMainSurfaceBox() const {
return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y}; return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y};

View File

@ -78,6 +78,9 @@ class IKeyboard : public IHID {
bool m_enabled = true; bool m_enabled = true;
bool m_allowBinds = true; bool m_allowBinds = true;
// permission flag: whether this keyboard is allowed to be processed
bool m_allowed = true;
// if the keymap is overridden by the implementation, // if the keymap is overridden by the implementation,
// don't try to set keyboard rules anymore, to avoid overwriting the requested one. // don't try to set keyboard rules anymore, to avoid overwriting the requested one.
// e.g. Virtual keyboards with custom maps. // e.g. Virtual keyboards with custom maps.

View File

@ -754,6 +754,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
// Allow the renderer to catch the last frame. // Allow the renderer to catch the last frame.
if (g_pHyprRenderer->shouldRenderWindow(PWINDOW))
g_pHyprRenderer->makeWindowSnapshot(PWINDOW); g_pHyprRenderer->makeWindowSnapshot(PWINDOW);
// swallowing // swallowing

View File

@ -7,7 +7,7 @@
using namespace Hyprutils::OS; using namespace Hyprutils::OS;
static std::vector<pid_t> asyncDialogBoxes; static std::vector<std::pair<pid_t, WP<CAsyncDialogBox>>> asyncDialogBoxes;
// //
SP<CAsyncDialogBox> CAsyncDialogBox::create(const std::string& title, const std::string& description, std::vector<std::string> buttons) { SP<CAsyncDialogBox> CAsyncDialogBox::create(const std::string& title, const std::string& description, std::vector<std::string> buttons) {
@ -24,7 +24,18 @@ SP<CAsyncDialogBox> CAsyncDialogBox::create(const std::string& title, const std:
} }
bool CAsyncDialogBox::isAsyncDialogBox(pid_t pid) { bool CAsyncDialogBox::isAsyncDialogBox(pid_t pid) {
return std::ranges::contains(asyncDialogBoxes, pid); return std::ranges::find_if(asyncDialogBoxes, [pid](const auto& e) { return e.first == pid; }) != asyncDialogBoxes.end();
}
bool CAsyncDialogBox::isPriorityDialogBox(pid_t pid) {
for (const auto& [p, db] : asyncDialogBoxes) {
if (p != pid)
continue;
return db && db->m_priority;
}
return false;
} }
CAsyncDialogBox::CAsyncDialogBox(const std::string& title, const std::string& description, std::vector<std::string> buttons) : CAsyncDialogBox::CAsyncDialogBox(const std::string& title, const std::string& description, std::vector<std::string> buttons) :
@ -68,7 +79,7 @@ void CAsyncDialogBox::onWrite(int fd, uint32_t mask) {
Debug::log(LOG, "CAsyncDialogBox: dialog {:x} hung up, closed."); Debug::log(LOG, "CAsyncDialogBox: dialog {:x} hung up, closed.");
m_promiseResolver->resolve(m_stdout); m_promiseResolver->resolve(m_stdout);
std::erase(asyncDialogBoxes, m_dialogPid); std::erase_if(asyncDialogBoxes, [this](const auto& e) { return e.first == m_dialogPid; });
wl_event_source_remove(m_readEventSource); wl_event_source_remove(m_readEventSource);
m_selfReference.reset(); m_selfReference.reset();
@ -112,7 +123,7 @@ SP<CPromise<std::string>> CAsyncDialogBox::open() {
} }
m_dialogPid = proc.pid(); m_dialogPid = proc.pid();
asyncDialogBoxes.emplace_back(m_dialogPid); asyncDialogBoxes.emplace_back(std::make_pair<>(m_dialogPid, m_selfWeakReference));
// close the write fd, only the dialog owns it now // close the write fd, only the dialog owns it now
close(outPipe[1]); close(outPipe[1]);

View File

@ -16,6 +16,7 @@ class CAsyncDialogBox {
public: public:
static SP<CAsyncDialogBox> create(const std::string& title, const std::string& description, std::vector<std::string> buttons); static SP<CAsyncDialogBox> create(const std::string& title, const std::string& description, std::vector<std::string> buttons);
static bool isAsyncDialogBox(pid_t pid); static bool isAsyncDialogBox(pid_t pid);
static bool isPriorityDialogBox(pid_t pid);
CAsyncDialogBox(const CAsyncDialogBox&) = delete; CAsyncDialogBox(const CAsyncDialogBox&) = delete;
CAsyncDialogBox(CAsyncDialogBox&&) = delete; CAsyncDialogBox(CAsyncDialogBox&&) = delete;
@ -26,6 +27,9 @@ class CAsyncDialogBox {
void kill(); void kill();
bool isRunning() const; bool isRunning() const;
// focus priority, only permission popups
bool m_priority = false;
void onWrite(int fd, uint32_t mask); void onWrite(int fd, uint32_t mask);
private: private:

View File

@ -16,11 +16,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_ARGB8888, .drmFormat = DRM_FORMAT_ARGB8888,
.flipRB = true, .flipRB = true,
#ifndef GLES2
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#else
.glFormat = GL_BGRA_EXT,
#endif
.glType = GL_UNSIGNED_BYTE, .glType = GL_UNSIGNED_BYTE,
.withAlpha = true, .withAlpha = true,
.alphaStripped = DRM_FORMAT_XRGB8888, .alphaStripped = DRM_FORMAT_XRGB8888,
@ -29,11 +25,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_XRGB8888, .drmFormat = DRM_FORMAT_XRGB8888,
.flipRB = true, .flipRB = true,
#ifndef GLES2
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#else
.glFormat = GL_BGRA_EXT,
#endif
.glType = GL_UNSIGNED_BYTE, .glType = GL_UNSIGNED_BYTE,
.withAlpha = false, .withAlpha = false,
.alphaStripped = DRM_FORMAT_XRGB8888, .alphaStripped = DRM_FORMAT_XRGB8888,
@ -106,11 +98,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_XBGR2101010, .drmFormat = DRM_FORMAT_XBGR2101010,
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#ifndef GLES2
.glType = GL_UNSIGNED_INT_2_10_10_10_REV, .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
#else
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
#endif
.withAlpha = false, .withAlpha = false,
.alphaStripped = DRM_FORMAT_XBGR2101010, .alphaStripped = DRM_FORMAT_XBGR2101010,
.bytesPerBlock = 4, .bytesPerBlock = 4,
@ -118,11 +106,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_ABGR2101010, .drmFormat = DRM_FORMAT_ABGR2101010,
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#ifndef GLES2
.glType = GL_UNSIGNED_INT_2_10_10_10_REV, .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
#else
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
#endif
.withAlpha = true, .withAlpha = true,
.alphaStripped = DRM_FORMAT_XBGR2101010, .alphaStripped = DRM_FORMAT_XBGR2101010,
.bytesPerBlock = 4, .bytesPerBlock = 4,
@ -130,11 +114,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_XRGB2101010, .drmFormat = DRM_FORMAT_XRGB2101010,
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#ifndef GLES2
.glType = GL_UNSIGNED_INT_2_10_10_10_REV, .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
#else
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
#endif
.withAlpha = false, .withAlpha = false,
.alphaStripped = DRM_FORMAT_XRGB2101010, .alphaStripped = DRM_FORMAT_XRGB2101010,
.bytesPerBlock = 4, .bytesPerBlock = 4,
@ -142,11 +122,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_ARGB2101010, .drmFormat = DRM_FORMAT_ARGB2101010,
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#ifndef GLES2
.glType = GL_UNSIGNED_INT_2_10_10_10_REV, .glType = GL_UNSIGNED_INT_2_10_10_10_REV,
#else
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
#endif
.withAlpha = true, .withAlpha = true,
.alphaStripped = DRM_FORMAT_XRGB2101010, .alphaStripped = DRM_FORMAT_XRGB2101010,
.bytesPerBlock = 4, .bytesPerBlock = 4,
@ -154,11 +130,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_XBGR16161616F, .drmFormat = DRM_FORMAT_XBGR16161616F,
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#ifndef GLES2
.glType = GL_HALF_FLOAT, .glType = GL_HALF_FLOAT,
#else
.glType = GL_HALF_FLOAT_OES,
#endif
.withAlpha = false, .withAlpha = false,
.alphaStripped = DRM_FORMAT_XBGR16161616F, .alphaStripped = DRM_FORMAT_XBGR16161616F,
.bytesPerBlock = 8, .bytesPerBlock = 8,
@ -166,22 +138,14 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
{ {
.drmFormat = DRM_FORMAT_ABGR16161616F, .drmFormat = DRM_FORMAT_ABGR16161616F,
.glFormat = GL_RGBA, .glFormat = GL_RGBA,
#ifndef GLES2
.glType = GL_HALF_FLOAT, .glType = GL_HALF_FLOAT,
#else
.glType = GL_HALF_FLOAT_OES,
#endif
.withAlpha = true, .withAlpha = true,
.alphaStripped = DRM_FORMAT_XBGR16161616F, .alphaStripped = DRM_FORMAT_XBGR16161616F,
.bytesPerBlock = 8, .bytesPerBlock = 8,
}, },
{ {
.drmFormat = DRM_FORMAT_XBGR16161616, .drmFormat = DRM_FORMAT_XBGR16161616,
#ifndef GLES2
.glFormat = GL_RGBA16UI, .glFormat = GL_RGBA16UI,
#else
.glFormat = GL_RGBA16_EXT,
#endif
.glType = GL_UNSIGNED_SHORT, .glType = GL_UNSIGNED_SHORT,
.withAlpha = false, .withAlpha = false,
.alphaStripped = DRM_FORMAT_XBGR16161616, .alphaStripped = DRM_FORMAT_XBGR16161616,
@ -189,11 +153,7 @@ inline const std::vector<SPixelFormat> GLES3_FORMATS = {
}, },
{ {
.drmFormat = DRM_FORMAT_ABGR16161616, .drmFormat = DRM_FORMAT_ABGR16161616,
#ifndef GLES2
.glFormat = GL_RGBA16UI, .glFormat = GL_RGBA16UI,
#else
.glFormat = GL_RGBA16_EXT,
#endif
.glType = GL_UNSIGNED_SHORT, .glType = GL_UNSIGNED_SHORT,
.withAlpha = true, .withAlpha = true,
.alphaStripped = DRM_FORMAT_XBGR16161616, .alphaStripped = DRM_FORMAT_XBGR16161616,
@ -290,12 +250,7 @@ uint32_t NFormatUtils::drmFormatToGL(DRMFormat drm) {
case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case. case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XRGB2101010:
case DRM_FORMAT_XBGR2101010: case DRM_FORMAT_XBGR2101010: return GL_RGB10_A2;
#ifdef GLES2
return GL_RGB10_A2_EXT;
#else
return GL_RGB10_A2;
#endif
default: return GL_RGBA; default: return GL_RGBA;
} }
UNREACHABLE(); UNREACHABLE();
@ -303,13 +258,7 @@ uint32_t NFormatUtils::drmFormatToGL(DRMFormat drm) {
} }
uint32_t NFormatUtils::glFormatToType(uint32_t gl) { uint32_t NFormatUtils::glFormatToType(uint32_t gl) {
return gl != GL_RGBA ? return gl != GL_RGBA ? GL_UNSIGNED_INT_2_10_10_10_REV : GL_UNSIGNED_BYTE;
#ifdef GLES2
GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
#else
GL_UNSIGNED_INT_2_10_10_10_REV :
#endif
GL_UNSIGNED_BYTE;
} }
std::string NFormatUtils::drmFormatName(DRMFormat drm) { std::string NFormatUtils::drmFormatName(DRMFormat drm) {

View File

@ -146,11 +146,8 @@ void CHyprError::createQueued() {
glBindTexture(GL_TEXTURE_2D, m_texture->m_texID); glBindTexture(GL_TEXTURE_2D, m_texture->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);

View File

@ -17,15 +17,9 @@
#include <unistd.h> #include <unistd.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#ifdef LEGACY_RENDERER
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#define GLES2
#else
#define GLES32 #define GLES32
#include <GLES3/gl32.h> #include <GLES3/gl32.h>
#include <GLES3/gl3ext.h> #include <GLES3/gl3ext.h>
#endif
#ifdef NO_XWAYLAND #ifdef NO_XWAYLAND
#define XWAYLAND false #define XWAYLAND false

View File

@ -584,7 +584,6 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
g_pHyprOpenGL->renderTexture(texture, xbox, 1.F); g_pHyprOpenGL->renderTexture(texture, xbox, 1.F);
g_pHyprOpenGL->end(); g_pHyprOpenGL->end();
glFlush();
g_pHyprOpenGL->m_renderData.pMonitor.reset(); g_pHyprOpenGL->m_renderData.pMonitor.reset();
g_pHyprRenderer->onRenderbufferDestroy(RBO.get()); g_pHyprRenderer->onRenderbufferDestroy(RBO.get());

View File

@ -70,16 +70,20 @@ static int handleWaiterFD(int fd, uint32_t mask, void* data) {
void CEventLoopManager::onFdReadable(SReadableWaiter* waiter) { void CEventLoopManager::onFdReadable(SReadableWaiter* waiter) {
auto it = std::ranges::find_if(m_readableWaiters, [waiter](const UP<SReadableWaiter>& w) { return waiter == w.get() && w->fd == waiter->fd && w->source == waiter->source; }); auto it = std::ranges::find_if(m_readableWaiters, [waiter](const UP<SReadableWaiter>& w) { return waiter == w.get() && w->fd == waiter->fd && w->source == waiter->source; });
if (waiter->source) { // ???
wl_event_source_remove(waiter->source); if (it == m_readableWaiters.end())
waiter->source = nullptr; return;
UP<SReadableWaiter> taken = std::move(*it);
m_readableWaiters.erase(it);
if (taken->source) {
wl_event_source_remove(taken->source);
taken->source = nullptr;
} }
if (waiter->fn) if (taken->fn)
waiter->fn(); taken->fn();
if (it != m_readableWaiters.end())
m_readableWaiters.erase(it);
} }
void CEventLoopManager::enterLoop() { void CEventLoopManager::enterLoop() {

View File

@ -36,6 +36,7 @@
#include "../../managers/HookSystemManager.hpp" #include "../../managers/HookSystemManager.hpp"
#include "../../managers/EventManager.hpp" #include "../../managers/EventManager.hpp"
#include "../../managers/LayoutManager.hpp" #include "../../managers/LayoutManager.hpp"
#include "../../managers/permissions/DynamicPermissionManager.hpp"
#include "../../helpers/time/Time.hpp" #include "../../helpers/time/Time.hpp"
@ -249,7 +250,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
if (PMONITOR != g_pCompositor->m_lastMonitor && (*PMOUSEFOCUSMON || refocus) && m_forcedFocus.expired()) if (PMONITOR != g_pCompositor->m_lastMonitor && (*PMOUSEFOCUSMON || refocus) && m_forcedFocus.expired())
g_pCompositor->setActiveMonitor(PMONITOR); g_pCompositor->setActiveMonitor(PMONITOR);
if (g_pSessionLockManager->isSessionLocked()) { // check for windows that have focus priority like our permission popups
pFoundWindow = g_pCompositor->vectorToWindowUnified(mouseCoords, FOCUS_PRIORITY);
if (pFoundWindow)
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
if (!foundSurface && g_pSessionLockManager->isSessionLocked()) {
// set keyboard focus on session lock surface regardless of layers // set keyboard focus on session lock surface regardless of layers
const auto PSESSIONLOCKSURFACE = g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->m_id); const auto PSESSIONLOCKSURFACE = g_pSessionLockManager->getSessionLockSurfaceForMonitor(PMONITOR->m_id);
@ -287,7 +293,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
if (!forcedFocus) if (!forcedFocus)
forcedFocus = g_pCompositor->getForceFocus(); forcedFocus = g_pCompositor->getForceFocus();
if (forcedFocus) { if (forcedFocus && !foundSurface) {
pFoundWindow = forcedFocus; pFoundWindow = forcedFocus;
surfacePos = pFoundWindow->m_realPosition->value(); surfacePos = pFoundWindow->m_realPosition->value();
foundSurface = pFoundWindow->m_wlSurface->resource(); foundSurface = pFoundWindow->m_wlSurface->resource();
@ -1054,6 +1060,27 @@ void CInputManager::applyConfigToKeyboard(SP<IKeyboard> pKeyboard) {
pKeyboard->m_resolveBindsBySym = RESOLVEBINDSBYSYM; pKeyboard->m_resolveBindsBySym = RESOLVEBINDSBYSYM;
pKeyboard->m_allowBinds = ALLOWBINDS; pKeyboard->m_allowBinds = ALLOWBINDS;
const auto PERM = g_pDynamicPermissionManager->clientPermissionModeWithString(-1, pKeyboard->m_hlName, PERMISSION_TYPE_KEYBOARD);
if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) {
const auto PROMISE = g_pDynamicPermissionManager->promiseFor(-1, pKeyboard->m_hlName, PERMISSION_TYPE_KEYBOARD);
if (!PROMISE)
Debug::log(ERR, "BUG THIS: No promise for client permission for keyboard");
else {
PROMISE->then([k = WP<IKeyboard>{pKeyboard}](SP<CPromiseResult<eDynamicPermissionAllowMode>> r) {
if (r->hasError()) {
Debug::log(ERR, "BUG THIS: No permission returned for keyboard");
return;
}
if (!k)
return;
k->m_allowed = r->result() == PERMISSION_RULE_ALLOW_MODE_ALLOW;
});
}
} else
pKeyboard->m_allowed = PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW;
try { try {
if (NUMLOCKON == pKeyboard->m_numlockOn && REPEATDELAY == pKeyboard->m_repeatDelay && REPEATRATE == pKeyboard->m_repeatRate && RULES != "" && if (NUMLOCKON == pKeyboard->m_numlockOn && REPEATDELAY == pKeyboard->m_repeatDelay && REPEATRATE == pKeyboard->m_repeatRate && RULES != "" &&
RULES == pKeyboard->m_currentRules.rules && MODEL == pKeyboard->m_currentRules.model && LAYOUT == pKeyboard->m_currentRules.layout && RULES == pKeyboard->m_currentRules.rules && MODEL == pKeyboard->m_currentRules.model && LAYOUT == pKeyboard->m_currentRules.layout &&
@ -1368,7 +1395,7 @@ void CInputManager::destroyTabletPad(SP<CTabletPad> pad) {
} }
void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) { void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) {
if (!pKeyboard) if (!pKeyboard || pKeyboard->isVirtual())
return; return;
std::optional<uint32_t> leds = pKeyboard->getLEDs(); std::optional<uint32_t> leds = pKeyboard->getLEDs();
@ -1382,7 +1409,7 @@ void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) {
} }
void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) { void CInputManager::onKeyboardKey(std::any event, SP<IKeyboard> pKeyboard) {
if (!pKeyboard->m_enabled) if (!pKeyboard->m_enabled || !pKeyboard->m_allowed)
return; return;
const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard); const bool DISALLOWACTION = pKeyboard->isVirtual() && shouldIgnoreVirtualKeyboard(pKeyboard);

View File

@ -52,6 +52,7 @@ static const char* permissionToString(eDynamicPermissionType type) {
case PERMISSION_TYPE_UNKNOWN: return "PERMISSION_TYPE_UNKNOWN"; case PERMISSION_TYPE_UNKNOWN: return "PERMISSION_TYPE_UNKNOWN";
case PERMISSION_TYPE_SCREENCOPY: return "PERMISSION_TYPE_SCREENCOPY"; case PERMISSION_TYPE_SCREENCOPY: return "PERMISSION_TYPE_SCREENCOPY";
case PERMISSION_TYPE_PLUGIN: return "PERMISSION_TYPE_PLUGIN"; case PERMISSION_TYPE_PLUGIN: return "PERMISSION_TYPE_PLUGIN";
case PERMISSION_TYPE_KEYBOARD: return "PERMISSION_TYPE_KEYBOARD";
} }
return "error"; return "error";
@ -59,9 +60,10 @@ static const char* permissionToString(eDynamicPermissionType type) {
static const char* permissionToHumanString(eDynamicPermissionType type) { static const char* permissionToHumanString(eDynamicPermissionType type) {
switch (type) { switch (type) {
case PERMISSION_TYPE_UNKNOWN: return "requesting an unknown permission"; case PERMISSION_TYPE_UNKNOWN: return "An application <b>{}</b> is requesting an unknown permission.";
case PERMISSION_TYPE_SCREENCOPY: return "trying to capture your screen"; case PERMISSION_TYPE_SCREENCOPY: return "An application <b>{}</b> is trying to capture your screen.<br/><br/>Do you want to allow it to do so?";
case PERMISSION_TYPE_PLUGIN: return "trying to load a plugin"; case PERMISSION_TYPE_PLUGIN: return "An application <b>{}</b> is trying to load a plugin: <b>{}</b>.<br/><br/>Do you want to load it?";
case PERMISSION_TYPE_KEYBOARD: return "A new keyboard has been plugged in: {}.<br/><br/>Do you want to allow it to operate?";
} }
return "error"; return "error";
@ -184,7 +186,7 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionMode(wl_c
return PERMISSION_RULE_ALLOW_MODE_PENDING; return PERMISSION_RULE_ALLOW_MODE_PENDING;
} }
// if we are here, we need to ask. // if we are here, we need to ask, that's the fallback for all these (keyboards wont come here)
askForPermission(client, LOOKUP.value_or(""), permission); askForPermission(client, LOOKUP.value_or(""), permission);
return PERMISSION_RULE_ALLOW_MODE_PENDING; return PERMISSION_RULE_ALLOW_MODE_PENDING;
@ -232,6 +234,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS
} else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_PENDING) { } else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_PENDING) {
Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission pending by config rule"); Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission pending by config rule");
return PERMISSION_RULE_ALLOW_MODE_PENDING; return PERMISSION_RULE_ALLOW_MODE_PENDING;
} else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_ASK) {
Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule");
askForPermission(nullptr, str, permission, pid);
return PERMISSION_RULE_ALLOW_MODE_PENDING;
} else } else
Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule"); Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule");
} }
@ -247,6 +253,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS
return PERMISSION_RULE_ALLOW_MODE_PENDING; return PERMISSION_RULE_ALLOW_MODE_PENDING;
} }
// keyboards are allow default
if (permission == PERMISSION_TYPE_KEYBOARD)
return PERMISSION_RULE_ALLOW_MODE_ALLOW;
// if we are here, we need to ask. // if we are here, we need to ask.
askForPermission(nullptr, str, permission, pid); askForPermission(nullptr, str, permission, pid);
@ -263,22 +273,20 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s
std::string description = ""; std::string description = "";
if (binaryPath.empty()) if (binaryPath.empty())
description = std::format("An unknown application (wayland client ID 0x{:x}) is {}.", (uintptr_t)client, permissionToHumanString(type)); description = std::format(std::runtime_format(permissionToHumanString(type)), std::format("unknown application (wayland client ID 0x{:x})", (uintptr_t)client));
else if (client) { else if (client) {
std::string binaryName = binaryPath.contains("/") ? binaryPath.substr(binaryPath.find_last_of('/') + 1) : binaryPath; std::string binaryName = binaryPath.contains("/") ? binaryPath.substr(binaryPath.find_last_of('/') + 1) : binaryPath;
description = std::format("An application <b>{}</b> ({}) is {}.", binaryName, binaryPath, permissionToHumanString(type)); description = std::format(std::runtime_format(permissionToHumanString(type)), std::format("{}</b> ({})", binaryName, binaryPath));
} else if (pid >= 0) { } else if (pid >= 0) {
if (type == PERMISSION_TYPE_PLUGIN) { if (type == PERMISSION_TYPE_PLUGIN) {
const auto LOOKUP = binaryNameForPid(pid); const auto LOOKUP = binaryNameForPid(pid);
description = std::format("An application <b>{}</b> is {}:<br/><b>{}</b>", LOOKUP.value_or("Unknown"), permissionToHumanString(type), binaryPath); description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath);
} else { } else {
const auto LOOKUP = binaryNameForPid(pid); const auto LOOKUP = binaryNameForPid(pid);
description = std::format("An application <b>{}</b> ({}) is {}.", LOOKUP.value_or("Unknown"), binaryPath, permissionToHumanString(type)); description = std::format(std::runtime_format(permissionToHumanString(type)), LOOKUP.value_or("Unknown"), binaryPath);
} }
} else } else
description = std::format("An application is {}:<br/><b>{}</b>", permissionToHumanString(type), binaryPath); description = std::format(std::runtime_format(permissionToHumanString(type)), binaryPath);
description += "<br/><br/>Do you want to allow this?";
std::vector<std::string> options; std::vector<std::string> options;
@ -289,6 +297,7 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s
options = {"Deny", "Allow"}; options = {"Deny", "Allow"};
rule->m_dialogBox = CAsyncDialogBox::create("Permission request", description, options); rule->m_dialogBox = CAsyncDialogBox::create("Permission request", description, options);
rule->m_dialogBox->m_priority = true;
if (!rule->m_dialogBox) { if (!rule->m_dialogBox) {
Debug::log(ERR, "CDynamicPermissionManager::askForPermission: hyprland-qtutils likely missing, cannot ask! Disabling permission control..."); Debug::log(ERR, "CDynamicPermissionManager::askForPermission: hyprland-qtutils likely missing, cannot ask! Disabling permission control...");

View File

@ -17,6 +17,7 @@ enum eDynamicPermissionType : uint8_t {
PERMISSION_TYPE_UNKNOWN = 0, PERMISSION_TYPE_UNKNOWN = 0,
PERMISSION_TYPE_SCREENCOPY, PERMISSION_TYPE_SCREENCOPY,
PERMISSION_TYPE_PLUGIN, PERMISSION_TYPE_PLUGIN,
PERMISSION_TYPE_KEYBOARD,
}; };
enum eDynamicPermissionRuleSource : uint8_t { enum eDynamicPermissionRuleSource : uint8_t {

View File

@ -1,6 +1,7 @@
#include "ForeignToplevelWlr.hpp" #include "ForeignToplevelWlr.hpp"
#include <algorithm> #include <algorithm>
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "managers/input/InputManager.hpp"
#include "protocols/core/Output.hpp" #include "protocols/core/Output.hpp"
#include "render/Renderer.hpp" #include "render/Renderer.hpp"
#include "../managers/HookSystemManager.hpp" #include "../managers/HookSystemManager.hpp"
@ -24,6 +25,7 @@ CForeignToplevelHandleWlr::CForeignToplevelHandleWlr(SP<CZwlrForeignToplevelHand
// these requests bypass the config'd stuff cuz it's usually like // these requests bypass the config'd stuff cuz it's usually like
// window switchers and shit // window switchers and shit
PWINDOW->activate(true); PWINDOW->activate(true);
g_pInputManager->simulateMouseMovement();
}); });
m_resource->setSetFullscreen([this](CZwlrForeignToplevelHandleV1* p, wl_resource* output) { m_resource->setSetFullscreen([this](CZwlrForeignToplevelHandleV1* p, wl_resource* output) {

View File

@ -187,19 +187,11 @@ void CScreencopyFrame::share() {
callback(copyShm()); callback(copyShm());
} }
void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) { void CScreencopyFrame::renderMon() {
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
auto TEXTURE = makeShared<CTexture>(m_monitor->m_output->state->state().buffer); auto TEXTURE = makeShared<CTexture>(m_monitor->m_output->state->state().buffer);
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
if (!g_pHyprRenderer->beginRender(m_monitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, m_buffer.m_buffer, nullptr, true)) {
LOGM(ERR, "Can't copy: failed to begin rendering to dma frame");
callback(false);
return;
}
if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) {
CBox monbox = CBox{0, 0, m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y} CBox monbox = CBox{0, 0, m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y}
.translate({-m_box.x, -m_box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. .translate({-m_box.x, -m_box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh.
.transform(wlTransformToHyprutils(invertTransform(m_monitor->m_transform)), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y); .transform(wlTransformToHyprutils(invertTransform(m_monitor->m_transform)), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y);
@ -211,6 +203,43 @@ void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
if (m_overlayCursor) if (m_overlayCursor)
g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage, g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage,
g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true); g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true);
}
void CScreencopyFrame::storeTempFB() {
g_pHyprRenderer->makeEGLCurrent();
m_tempFb.alloc(m_box.w, m_box.h);
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
if (!g_pHyprRenderer->beginRender(m_monitor.lock(), fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &m_tempFb, true)) {
LOGM(ERR, "Can't copy: failed to begin rendering to temp fb");
return;
}
renderMon();
g_pHyprRenderer->endRender();
}
void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
if (!g_pHyprRenderer->beginRender(m_monitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, m_buffer.m_buffer, nullptr, true)) {
LOGM(ERR, "Can't copy: failed to begin rendering to dma frame");
callback(false);
return;
}
if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) {
if (m_tempFb.isAllocated()) {
CBox texbox = {{}, m_box.size()};
g_pHyprOpenGL->renderTexture(m_tempFb.getTexture(), texbox, 1);
m_tempFb.release();
} else
renderMon();
} else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING)
g_pHyprOpenGL->clear(Colors::BLACK); g_pHyprOpenGL->clear(Colors::BLACK);
else { else {
@ -229,7 +258,6 @@ void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
bool CScreencopyFrame::copyShm() { bool CScreencopyFrame::copyShm() {
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY); const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
auto TEXTURE = makeShared<CTexture>(m_monitor->m_output->state->state().buffer);
auto shm = m_buffer->shm(); auto shm = m_buffer->shm();
auto [pixelData, fmt, bufLen] = m_buffer->beginDataPtr(0); // no need for end, cuz it's shm auto [pixelData, fmt, bufLen] = m_buffer->beginDataPtr(0); // no need for end, cuz it's shm
@ -247,15 +275,12 @@ bool CScreencopyFrame::copyShm() {
} }
if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) {
CBox monbox = CBox{0, 0, m_monitor->m_transformedSize.x, m_monitor->m_transformedSize.y}.translate({-m_box.x, -m_box.y}); if (m_tempFb.isAllocated()) {
g_pHyprOpenGL->setMonitorTransformEnabled(true); CBox texbox = {{}, m_box.size()};
g_pHyprOpenGL->setRenderModifEnabled(false); g_pHyprOpenGL->renderTexture(m_tempFb.getTexture(), texbox, 1);
g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); m_tempFb.release();
g_pHyprOpenGL->setRenderModifEnabled(true); } else
g_pHyprOpenGL->setMonitorTransformEnabled(false); renderMon();
if (m_overlayCursor)
g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage,
g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true);
} else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING)
g_pHyprOpenGL->clear(Colors::BLACK); g_pHyprOpenGL->clear(Colors::BLACK);
else { else {
@ -264,11 +289,7 @@ bool CScreencopyFrame::copyShm() {
g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_screencopyDeniedTexture, texbox, 1); g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_screencopyDeniedTexture, texbox, 1);
} }
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID()); glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID());
#else
glBindFramebuffer(GL_FRAMEBUFFER, fb.getFBID());
#endif
const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format); const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format);
if (!PFORMAT) { if (!PFORMAT) {
@ -304,11 +325,7 @@ bool CScreencopyFrame::copyShm() {
g_pHyprOpenGL->m_renderData.pMonitor.reset(); g_pHyprOpenGL->m_renderData.pMonitor.reset();
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
LOGM(TRACE, "Copied frame via shm"); LOGM(TRACE, "Copied frame via shm");
@ -428,8 +445,12 @@ void CScreencopyProtocol::onOutputCommit(PHLMONITOR pMonitor) {
// check permissions // check permissions
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(f->m_resource->client(), PERMISSION_TYPE_SCREENCOPY); const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(f->m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) {
if (!f->m_tempFb.isAllocated())
f->storeTempFB(); // make a snapshot before the popup
continue; // pending an answer, don't do anything yet. continue; // pending an answer, don't do anything yet.
}
// otherwise share. If it's denied, it will be black. // otherwise share. If it's denied, it will be black.

View File

@ -10,6 +10,7 @@
#include "../managers/HookSystemManager.hpp" #include "../managers/HookSystemManager.hpp"
#include "../helpers/time/Timer.hpp" #include "../helpers/time/Timer.hpp"
#include "../helpers/time/Time.hpp" #include "../helpers/time/Time.hpp"
#include "../render/Framebuffer.hpp"
#include "../managers/eventLoop/EventLoopTimer.hpp" #include "../managers/eventLoop/EventLoopTimer.hpp"
#include <aquamarine/buffer/Buffer.hpp> #include <aquamarine/buffer/Buffer.hpp>
@ -72,9 +73,14 @@ class CScreencopyFrame {
int m_shmStride = 0; int m_shmStride = 0;
CBox m_box = {}; CBox m_box = {};
// if we have a pending perm, hold the buffer.
CFramebuffer m_tempFb;
void copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer); void copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer);
void copyDmabuf(std::function<void(bool)> callback); void copyDmabuf(std::function<void(bool)> callback);
bool copyShm(); bool copyShm();
void renderMon();
void storeTempFB();
void share(); void share();
friend class CScreencopyProtocol; friend class CScreencopyProtocol;

View File

@ -281,10 +281,7 @@ bool CToplevelExportFrame::copyShm(const Time::steady_tp& now) {
g_pHyprOpenGL->m_renderData.pMonitor = PMONITOR; g_pHyprOpenGL->m_renderData.pMonitor = PMONITOR;
outFB.bind(); outFB.bind();
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID()); glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID());
#endif
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
auto glFormat = PFORMAT->flipRB ? GL_BGRA_EXT : GL_RGBA; auto glFormat = PFORMAT->flipRB ? GL_BGRA_EXT : GL_RGBA;
@ -318,10 +315,7 @@ bool CToplevelExportFrame::copyShm(const Time::steady_tp& now) {
} }
outFB.unbind(); outFB.unbind();
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
#endif
return true; return true;
} }

View File

@ -12,6 +12,11 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
uint32_t glFormat = NFormatUtils::drmFormatToGL(drmFormat); uint32_t glFormat = NFormatUtils::drmFormatToGL(drmFormat);
uint32_t glType = NFormatUtils::glFormatToType(glFormat); uint32_t glType = NFormatUtils::glFormatToType(glFormat);
if (drmFormat != m_drmFormat || m_size != Vector2D{w, h})
release();
m_drmFormat = drmFormat;
if (!m_tex) { if (!m_tex) {
m_tex = makeShared<CTexture>(); m_tex = makeShared<CTexture>();
m_tex->allocate(); m_tex->allocate();
@ -35,14 +40,11 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
glBindFramebuffer(GL_FRAMEBUFFER, m_fb); glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex->m_texID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex->m_texID, 0);
// TODO: Allow this with gles2
#ifndef GLES2
if (m_stencilTex) { if (m_stencilTex) {
glBindTexture(GL_TEXTURE_2D, m_stencilTex->m_texID); glBindTexture(GL_TEXTURE_2D, m_stencilTex->m_texID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_stencilTex->m_texID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_stencilTex->m_texID, 0);
} }
#endif
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER); auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Framebuffer incomplete, couldn't create! (FB status: {}, GL Error: 0x{:x})", status, (int)glGetError()); RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Framebuffer incomplete, couldn't create! (FB status: {}, GL Error: 0x{:x})", status, (int)glGetError());
@ -59,8 +61,6 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
} }
void CFramebuffer::addStencil(SP<CTexture> tex) { void CFramebuffer::addStencil(SP<CTexture> tex) {
// TODO: Allow this with gles2
#ifndef GLES2
m_stencilTex = tex; m_stencilTex = tex;
glBindTexture(GL_TEXTURE_2D, m_stencilTex->m_texID); glBindTexture(GL_TEXTURE_2D, m_stencilTex->m_texID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_size.x, m_size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_size.x, m_size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
@ -74,15 +74,10 @@ void CFramebuffer::addStencil(SP<CTexture> tex) {
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
} }
void CFramebuffer::bind() { void CFramebuffer::bind() {
#ifndef GLES2
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb);
#else
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
#endif
if (g_pHyprOpenGL) if (g_pHyprOpenGL)
glViewport(0, 0, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.x, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.y); glViewport(0, 0, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.x, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.y);
@ -91,11 +86,7 @@ void CFramebuffer::bind() {
} }
void CFramebuffer::unbind() { void CFramebuffer::unbind() {
#ifndef GLES2
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
} }
void CFramebuffer::release() { void CFramebuffer::release() {

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../defines.hpp" #include "../defines.hpp"
#include "../helpers/Format.hpp"
#include "Texture.hpp" #include "Texture.hpp"
class CFramebuffer { class CFramebuffer {
@ -20,6 +21,7 @@ class CFramebuffer {
GLuint getFBID(); GLuint getFBID();
Vector2D m_size; Vector2D m_size;
DRMFormat m_drmFormat = 0 /* DRM_FORMAT_INVALID */;
private: private:
SP<CTexture> m_tex; SP<CTexture> m_tex;

View File

@ -162,24 +162,14 @@ void CHyprOpenGLImpl::initEGL(bool gbm) {
auto attrsNoVer = attrs; auto attrsNoVer = attrs;
#ifndef GLES2
attrs.push_back(EGL_CONTEXT_MAJOR_VERSION); attrs.push_back(EGL_CONTEXT_MAJOR_VERSION);
attrs.push_back(3); attrs.push_back(3);
attrs.push_back(EGL_CONTEXT_MINOR_VERSION); attrs.push_back(EGL_CONTEXT_MINOR_VERSION);
attrs.push_back(2); attrs.push_back(2);
#else
attrs.push_back(EGL_CONTEXT_CLIENT_VERSION);
attrs.push_back(2);
m_eglContextVersion = EGL_CONTEXT_GLES_2_0;
#endif
attrs.push_back(EGL_NONE); attrs.push_back(EGL_NONE);
m_eglContext = eglCreateContext(m_eglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data()); m_eglContext = eglCreateContext(m_eglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data());
if (m_eglContext == EGL_NO_CONTEXT) { if (m_eglContext == EGL_NO_CONTEXT) {
#ifdef GLES2
RASSERT(false, "EGL: failed to create a context with GLES2.0");
#endif
Debug::log(WARN, "EGL: Failed to create a context with GLES3.2, retrying 3.0"); Debug::log(WARN, "EGL: Failed to create a context with GLES3.2, retrying 3.0");
attrs = attrsNoVer; attrs = attrsNoVer;
@ -362,10 +352,6 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
TRACY_GPU_CONTEXT; TRACY_GPU_CONTEXT;
#ifdef GLES2
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
#endif
initDRMFormats(); initDRMFormats();
initAssets(); initAssets();
@ -669,7 +655,6 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool
void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP<CRenderbuffer> rb, CFramebuffer* fb) { void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP<CRenderbuffer> rb, CFramebuffer* fb) {
m_renderData.pMonitor = pMonitor; m_renderData.pMonitor = pMonitor;
#ifndef GLES2
const GLenum RESETSTATUS = glGetGraphicsResetStatus(); const GLenum RESETSTATUS = glGetGraphicsResetStatus();
if (RESETSTATUS != GL_NO_ERROR) { if (RESETSTATUS != GL_NO_ERROR) {
std::string errStr = ""; std::string errStr = "";
@ -682,7 +667,6 @@ void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP
RASSERT(false, "Aborting, glGetGraphicsResetStatus returned {}. Cannot continue until proper GPU reset handling is implemented.", errStr); RASSERT(false, "Aborting, glGetGraphicsResetStatus returned {}. Cannot continue until proper GPU reset handling is implemented.", errStr);
return; return;
} }
#endif
TRACY_GPU_ZONE("RenderBeginSimple"); TRACY_GPU_ZONE("RenderBeginSimple");
@ -721,7 +705,6 @@ void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP
void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional<CRegion> finalDamage) { void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional<CRegion> finalDamage) {
m_renderData.pMonitor = pMonitor; m_renderData.pMonitor = pMonitor;
#ifndef GLES2
const GLenum RESETSTATUS = glGetGraphicsResetStatus(); const GLenum RESETSTATUS = glGetGraphicsResetStatus();
if (RESETSTATUS != GL_NO_ERROR) { if (RESETSTATUS != GL_NO_ERROR) {
std::string errStr = ""; std::string errStr = "";
@ -734,7 +717,6 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
RASSERT(false, "Aborting, glGetGraphicsResetStatus returned {}. Cannot continue until proper GPU reset handling is implemented.", errStr); RASSERT(false, "Aborting, glGetGraphicsResetStatus returned {}. Cannot continue until proper GPU reset handling is implemented.", errStr);
return; return;
} }
#endif
TRACY_GPU_ZONE("RenderBegin"); TRACY_GPU_ZONE("RenderBegin");
@ -752,13 +734,15 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
if (!m_shadersInitialized) if (!m_shadersInitialized)
initShaders(); initShaders();
const auto DRM_FORMAT = fb ? fb->m_drmFormat : pMonitor->m_output->state->state().drmFormat;
// ensure a framebuffer for the monitor exists // ensure a framebuffer for the monitor exists
if (m_renderData.pCurrentMonData->offloadFB.m_size != pMonitor->m_pixelSize) { if (m_renderData.pCurrentMonData->offloadFB.m_size != pMonitor->m_pixelSize || DRM_FORMAT != m_renderData.pCurrentMonData->offloadFB.m_drmFormat) {
m_renderData.pCurrentMonData->stencilTex->allocate(); m_renderData.pCurrentMonData->stencilTex->allocate();
m_renderData.pCurrentMonData->offloadFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, pMonitor->m_output->state->state().drmFormat); m_renderData.pCurrentMonData->offloadFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
m_renderData.pCurrentMonData->mirrorFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, pMonitor->m_output->state->state().drmFormat); m_renderData.pCurrentMonData->mirrorFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
m_renderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, pMonitor->m_output->state->state().drmFormat); m_renderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
m_renderData.pCurrentMonData->offloadFB.addStencil(m_renderData.pCurrentMonData->stencilTex); m_renderData.pCurrentMonData->offloadFB.addStencil(m_renderData.pCurrentMonData->stencilTex);
m_renderData.pCurrentMonData->mirrorFB.addStencil(m_renderData.pCurrentMonData->stencilTex); m_renderData.pCurrentMonData->mirrorFB.addStencil(m_renderData.pCurrentMonData->stencilTex);
@ -858,11 +842,7 @@ void CHyprOpenGLImpl::end() {
// check for gl errors // check for gl errors
const GLenum ERR = glGetError(); const GLenum ERR = glGetError();
#ifdef GLES2
if (ERR == GL_CONTEXT_LOST_KHR) /* We don't have infra to recover from this */
#else
if (ERR == GL_CONTEXT_LOST) /* We don't have infra to recover from this */ if (ERR == GL_CONTEXT_LOST) /* We don't have infra to recover from this */
#endif
RASSERT(false, "glGetError at Opengl::end() returned GL_CONTEXT_LOST. Cannot continue until proper GPU reset handling is implemented."); RASSERT(false, "glGetError at Opengl::end() returned GL_CONTEXT_LOST. Cannot continue until proper GPU reset handling is implemented.");
} }
@ -944,9 +924,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->TEXVERTSRC320 = processShader("tex320.vert", includes); shaders->TEXVERTSRC320 = processShader("tex320.vert", includes);
GLuint prog; GLuint prog;
#ifdef GLES2
m_cmSupported = false;
#else
if (!*PCM) if (!*PCM)
m_cmSupported = false; m_cmSupported = false;
else { else {
@ -975,12 +953,12 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shCM.applyTint = glGetUniformLocation(prog, "applyTint"); shaders->m_shCM.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shCM.tint = glGetUniformLocation(prog, "tint"); shaders->m_shCM.tint = glGetUniformLocation(prog, "tint");
shaders->m_shCM.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); shaders->m_shCM.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
shaders->m_shCM.createVao();
} else } else
Debug::log(ERR, Debug::log(ERR,
"WARNING: CM Shader failed compiling, color management will not work. It's likely because your GPU is an old piece of garbage, don't file bug reports " "WARNING: CM Shader failed compiling, color management will not work. It's likely because your GPU is an old piece of garbage, don't file bug reports "
"about this!"); "about this!");
} }
#endif
const auto FRAGSHADOW = processShader(m_cmSupported ? "shadow.frag" : "shadow_legacy.frag", includes); const auto FRAGSHADOW = processShader(m_cmSupported ? "shadow.frag" : "shadow_legacy.frag", includes);
const auto FRAGBORDER1 = processShader(m_cmSupported ? "border.frag" : "border_legacy.frag", includes); const auto FRAGBORDER1 = processShader(m_cmSupported ? "border.frag" : "border_legacy.frag", includes);
@ -1004,6 +982,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shQUAD.proj = glGetUniformLocation(prog, "proj"); shaders->m_shQUAD.proj = glGetUniformLocation(prog, "proj");
shaders->m_shQUAD.color = glGetUniformLocation(prog, "color"); shaders->m_shQUAD.color = glGetUniformLocation(prog, "color");
shaders->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos"); shaders->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
shaders->m_shQUAD.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBA, isDynamic); prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBA, isDynamic);
if (!prog) if (!prog)
@ -1023,6 +1002,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); shaders->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); shaders->m_shRGBA.tint = glGetUniformLocation(prog, "tint");
shaders->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); shaders->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
shaders->m_shRGBA.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAPASSTHRU, isDynamic); prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAPASSTHRU, isDynamic);
if (!prog) if (!prog)
@ -1032,6 +1012,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shPASSTHRURGBA.tex = glGetUniformLocation(prog, "tex"); shaders->m_shPASSTHRURGBA.tex = glGetUniformLocation(prog, "tex");
shaders->m_shPASSTHRURGBA.texAttrib = glGetAttribLocation(prog, "texcoord"); shaders->m_shPASSTHRURGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shPASSTHRURGBA.posAttrib = glGetAttribLocation(prog, "pos"); shaders->m_shPASSTHRURGBA.posAttrib = glGetAttribLocation(prog, "pos");
shaders->m_shPASSTHRURGBA.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAMATTE, isDynamic); prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAMATTE, isDynamic);
if (!prog) if (!prog)
@ -1042,6 +1023,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shMATTE.alphaMatte = glGetUniformLocation(prog, "texMatte"); shaders->m_shMATTE.alphaMatte = glGetUniformLocation(prog, "texMatte");
shaders->m_shMATTE.texAttrib = glGetAttribLocation(prog, "texcoord"); shaders->m_shMATTE.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shMATTE.posAttrib = glGetAttribLocation(prog, "pos"); shaders->m_shMATTE.posAttrib = glGetAttribLocation(prog, "pos");
shaders->m_shMATTE.createVao();
prog = createProgram(shaders->TEXVERTSRC, FRAGGLITCH, isDynamic); prog = createProgram(shaders->TEXVERTSRC, FRAGGLITCH, isDynamic);
if (!prog) if (!prog)
@ -1054,6 +1036,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shGLITCH.distort = glGetUniformLocation(prog, "distort"); shaders->m_shGLITCH.distort = glGetUniformLocation(prog, "distort");
shaders->m_shGLITCH.time = glGetUniformLocation(prog, "time"); shaders->m_shGLITCH.time = glGetUniformLocation(prog, "time");
shaders->m_shGLITCH.fullSize = glGetUniformLocation(prog, "screenSize"); shaders->m_shGLITCH.fullSize = glGetUniformLocation(prog, "screenSize");
shaders->m_shGLITCH.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBX, isDynamic); prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBX, isDynamic);
if (!prog) if (!prog)
@ -1070,6 +1053,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shRGBX.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); shaders->m_shRGBX.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
shaders->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint"); shaders->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shRGBX.tint = glGetUniformLocation(prog, "tint"); shaders->m_shRGBX.tint = glGetUniformLocation(prog, "tint");
shaders->m_shRGBX.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCEXT, isDynamic); prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCEXT, isDynamic);
if (!prog) if (!prog)
@ -1086,6 +1070,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shEXT.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); shaders->m_shEXT.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
shaders->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); shaders->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shEXT.tint = glGetUniformLocation(prog, "tint"); shaders->m_shEXT.tint = glGetUniformLocation(prog, "tint");
shaders->m_shEXT.createVao();
prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR1, isDynamic); prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR1, isDynamic);
if (!prog) if (!prog)
@ -1101,6 +1086,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLUR1.passes = glGetUniformLocation(prog, "passes"); shaders->m_shBLUR1.passes = glGetUniformLocation(prog, "passes");
shaders->m_shBLUR1.vibrancy = glGetUniformLocation(prog, "vibrancy"); shaders->m_shBLUR1.vibrancy = glGetUniformLocation(prog, "vibrancy");
shaders->m_shBLUR1.vibrancy_darkness = glGetUniformLocation(prog, "vibrancy_darkness"); shaders->m_shBLUR1.vibrancy_darkness = glGetUniformLocation(prog, "vibrancy_darkness");
shaders->m_shBLUR1.createVao();
prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR2, isDynamic); prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR2, isDynamic);
if (!prog) if (!prog)
@ -1113,6 +1099,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord"); shaders->m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shBLUR2.radius = glGetUniformLocation(prog, "radius"); shaders->m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
shaders->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel"); shaders->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
shaders->m_shBLUR2.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBLURPREPARE, isDynamic); prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBLURPREPARE, isDynamic);
if (!prog) if (!prog)
@ -1127,6 +1114,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLURPREPARE.texAttrib = glGetAttribLocation(prog, "texcoord"); shaders->m_shBLURPREPARE.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shBLURPREPARE.contrast = glGetUniformLocation(prog, "contrast"); shaders->m_shBLURPREPARE.contrast = glGetUniformLocation(prog, "contrast");
shaders->m_shBLURPREPARE.brightness = glGetUniformLocation(prog, "brightness"); shaders->m_shBLURPREPARE.brightness = glGetUniformLocation(prog, "brightness");
shaders->m_shBLURPREPARE.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBLURFINISH, isDynamic); prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBLURFINISH, isDynamic);
if (!prog) if (!prog)
@ -1140,6 +1128,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLURFINISH.texAttrib = glGetAttribLocation(prog, "texcoord"); shaders->m_shBLURFINISH.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness"); shaders->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness");
shaders->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise"); shaders->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise");
shaders->m_shBLURFINISH.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGSHADOW, isDynamic); prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGSHADOW, isDynamic);
if (!prog) if (!prog)
@ -1155,6 +1144,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shSHADOW.range = glGetUniformLocation(prog, "range"); shaders->m_shSHADOW.range = glGetUniformLocation(prog, "range");
shaders->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); shaders->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
shaders->m_shSHADOW.color = glGetUniformLocation(prog, "color"); shaders->m_shSHADOW.color = glGetUniformLocation(prog, "color");
shaders->m_shSHADOW.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBORDER1, isDynamic); prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBORDER1, isDynamic);
if (!prog) if (!prog)
@ -1179,6 +1169,8 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBORDER1.angle2 = glGetUniformLocation(prog, "angle2"); shaders->m_shBORDER1.angle2 = glGetUniformLocation(prog, "angle2");
shaders->m_shBORDER1.gradientLerp = glGetUniformLocation(prog, "gradientLerp"); shaders->m_shBORDER1.gradientLerp = glGetUniformLocation(prog, "gradientLerp");
shaders->m_shBORDER1.alpha = glGetUniformLocation(prog, "alpha"); shaders->m_shBORDER1.alpha = glGetUniformLocation(prog, "alpha");
shaders->m_shBORDER1.createVao();
} catch (const std::exception& e) { } catch (const std::exception& e) {
if (!m_shadersInitialized) if (!m_shadersInitialized)
throw e; throw e;
@ -1245,6 +1237,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) {
} }
m_finalScreenShader.texAttrib = glGetAttribLocation(m_finalScreenShader.program, "texcoord"); m_finalScreenShader.texAttrib = glGetAttribLocation(m_finalScreenShader.program, "texcoord");
m_finalScreenShader.posAttrib = glGetAttribLocation(m_finalScreenShader.program, "pos"); m_finalScreenShader.posAttrib = glGetAttribLocation(m_finalScreenShader.program, "pos");
m_finalScreenShader.createVao();
} }
void CHyprOpenGLImpl::clear(const CHyprColor& color) { void CHyprOpenGLImpl::clear(const CHyprColor& color) {
@ -1373,14 +1366,8 @@ void CHyprOpenGLImpl::renderRectWithDamage(const CBox& box, const CHyprColor& co
newBox, wlTransformToHyprutils(invertTransform(!m_endFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot); newBox, wlTransformToHyprutils(invertTransform(!m_endFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_renderData.pMonitor->m_transform)), newBox.rot);
Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix); Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix);
glUseProgram(m_shaders->m_shQUAD.program); useProgram(m_shaders->m_shQUAD.program);
#ifndef GLES2
glUniformMatrix3fv(m_shaders->m_shQUAD.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(m_shaders->m_shQUAD.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(m_renderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
// premultiply the color as well as we don't work with straight alpha // premultiply the color as well as we don't work with straight alpha
glUniform4f(m_shaders->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a); glUniform4f(m_shaders->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a);
@ -1398,9 +1385,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(const CBox& box, const CHyprColor& co
glUniform1f(m_shaders->m_shQUAD.radius, round); glUniform1f(m_shaders->m_shQUAD.radius, round);
glUniform1f(m_shaders->m_shQUAD.roundingPower, roundingPower); glUniform1f(m_shaders->m_shQUAD.roundingPower, roundingPower);
glVertexAttribPointer(m_shaders->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(m_shaders->m_shQUAD.shaderVao);
glEnableVertexAttribArray(m_shaders->m_shQUAD.posAttrib);
if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) { if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) {
CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height}; CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height};
@ -1419,7 +1404,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(const CBox& box, const CHyprColor& co
} }
} }
glDisableVertexAttribArray(m_shaders->m_shQUAD.posAttrib); glBindVertexArray(0);
scissor(nullptr); scissor(nullptr);
} }
@ -1579,19 +1564,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, const CB
if (!skipCM && !usingFinalShader && (texType == TEXTURE_RGBA || texType == TEXTURE_RGBX)) if (!skipCM && !usingFinalShader && (texType == TEXTURE_RGBA || texType == TEXTURE_RGBX))
shader = &m_shaders->m_shCM; shader = &m_shaders->m_shCM;
glUseProgram(shader->program); useProgram(shader->program);
if (shader == &m_shaders->m_shCM) { if (shader == &m_shaders->m_shCM) {
glUniform1i(shader->texType, texType); glUniform1i(shader->texType, texType);
passCMUniforms(*shader, imageDescription); passCMUniforms(*shader, imageDescription);
} }
#ifndef GLES2
glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform1i(shader->tex, 0); glUniform1i(shader->tex, 0);
if ((usingFinalShader && *PDT == 0) || CRASHING) { if ((usingFinalShader && *PDT == 0) || CRASHING) {
@ -1653,22 +1633,20 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, const CB
glUniform1i(shader->applyTint, 0); glUniform1i(shader->applyTint, 0);
} }
const float verts[] = { glBindVertexArray(shader->shaderVao);
m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVTopLeft.y, // top right if (allowCustomUV && m_renderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
m_renderData.primarySurfaceUVTopLeft.x, m_renderData.primarySurfaceUVTopLeft.y, // top left const float customUVs[] = {
m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVBottomRight.y, // bottom right m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVTopLeft.y, m_renderData.primarySurfaceUVTopLeft.x,
m_renderData.primarySurfaceUVTopLeft.x, m_renderData.primarySurfaceUVBottomRight.y, // bottom left m_renderData.primarySurfaceUVTopLeft.y, m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVBottomRight.y,
m_renderData.primarySurfaceUVTopLeft.x, m_renderData.primarySurfaceUVBottomRight.y,
}; };
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindBuffer(GL_ARRAY_BUFFER, shader->shaderVboUv);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(customUVs), customUVs);
if (allowCustomUV && m_renderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) } else {
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts); glBindBuffer(GL_ARRAY_BUFFER, shader->shaderVboUv);
else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(fullVerts), fullVerts);
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); }
glEnableVertexAttribArray(shader->posAttrib);
glEnableVertexAttribArray(shader->texAttrib);
if (!m_renderData.clipBox.empty() || !m_renderData.clipRegion.empty()) { if (!m_renderData.clipBox.empty() || !m_renderData.clipRegion.empty()) {
CRegion damageClip = m_renderData.clipBox; CRegion damageClip = m_renderData.clipBox;
@ -1693,9 +1671,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, const CB
} }
} }
glDisableVertexAttribArray(shader->posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(shader->texAttrib); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(tex->m_target, 0); glBindTexture(tex->m_target, 0);
} }
@ -1721,21 +1698,10 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, const CBox& box)
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(tex->m_target, tex->m_texID); glBindTexture(tex->m_target, tex->m_texID);
glUseProgram(shader->program); useProgram(shader->program);
#ifndef GLES2
glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform1i(shader->tex, 0); glUniform1i(shader->tex, 0);
glBindVertexArray(shader->shaderVao);
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(shader->posAttrib);
glEnableVertexAttribArray(shader->texAttrib);
for (auto const& RECT : m_renderData.damage.getRects()) { for (auto const& RECT : m_renderData.damage.getRects()) {
scissor(&RECT); scissor(&RECT);
@ -1744,9 +1710,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, const CBox& box)
scissor(nullptr); scissor(nullptr);
glDisableVertexAttribArray(shader->posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(shader->texAttrib);
glBindTexture(tex->m_target, 0); glBindTexture(tex->m_target, 0);
} }
@ -1769,14 +1733,8 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
SShader* shader = &m_shaders->m_shMATTE; SShader* shader = &m_shaders->m_shMATTE;
glUseProgram(shader->program); useProgram(shader->program);
#ifndef GLES2
glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform1i(shader->tex, 0); glUniform1i(shader->tex, 0);
glUniform1i(shader->alphaMatte, 1); glUniform1i(shader->alphaMatte, 1);
@ -1787,11 +1745,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
auto matteTex = matte.getTexture(); auto matteTex = matte.getTexture();
glBindTexture(matteTex->m_target, matteTex->m_texID); glBindTexture(matteTex->m_target, matteTex->m_texID);
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(shader->shaderVao);
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(shader->posAttrib);
glEnableVertexAttribArray(shader->texAttrib);
for (auto const& RECT : m_renderData.damage.getRects()) { for (auto const& RECT : m_renderData.damage.getRects()) {
scissor(&RECT); scissor(&RECT);
@ -1800,9 +1754,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
scissor(nullptr); scissor(nullptr);
glDisableVertexAttribArray(shader->posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(shader->texAttrib);
glBindTexture(tex->m_target, 0); glBindTexture(tex->m_target, 0);
} }
@ -1811,13 +1763,16 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
// //
// Dual (or more) kawase blur // Dual (or more) kawase blur
CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) { CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) {
if (!m_renderData.currentFB->getTexture()) { if (!m_renderData.currentFB->getTexture()) {
Debug::log(ERR, "BUG THIS: null fb texture while attempting to blur main fb?! (introspection off?!)"); Debug::log(ERR, "BUG THIS: null fb texture while attempting to blur main fb?! (introspection off?!)");
return &m_renderData.pCurrentMonData->mirrorFB; // return something to sample from at least return &m_renderData.pCurrentMonData->mirrorFB; // return something to sample from at least
} }
TRACY_GPU_ZONE("RenderBlurMainFramebufferWithDamage"); return blurFramebufferWithDamage(a, originalDamage, *m_renderData.currentFB);
}
CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* originalDamage, CFramebuffer& source) {
TRACY_GPU_ZONE("RenderBlurFramebufferWithDamage");
const auto BLENDBEFORE = m_blend; const auto BLENDBEFORE = m_blend;
blend(false); blend(false);
@ -1857,13 +1812,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
auto currentTex = m_renderData.currentFB->getTexture(); auto currentTex = source.getTexture();
glBindTexture(currentTex->m_target, currentTex->m_texID); glBindTexture(currentTex->m_target, currentTex->m_texID);
glTexParameteri(currentTex->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(currentTex->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(m_shaders->m_shBLURPREPARE.program); useProgram(m_shaders->m_shBLURPREPARE.program);
// From FB to sRGB // From FB to sRGB
const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{}; const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{};
@ -1882,21 +1837,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
1.0f); 1.0f);
} }
#ifndef GLES2
glUniformMatrix3fv(m_shaders->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(m_shaders->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(m_shaders->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform1f(m_shaders->m_shBLURPREPARE.contrast, *PBLURCONTRAST); glUniform1f(m_shaders->m_shBLURPREPARE.contrast, *PBLURCONTRAST);
glUniform1f(m_shaders->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS); glUniform1f(m_shaders->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS);
glUniform1i(m_shaders->m_shBLURPREPARE.tex, 0); glUniform1i(m_shaders->m_shBLURPREPARE.tex, 0);
glVertexAttribPointer(m_shaders->m_shBLURPREPARE.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(m_shaders->m_shBLURPREPARE.shaderVao);
glVertexAttribPointer(m_shaders->m_shBLURPREPARE.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shaders->m_shBLURPREPARE.posAttrib);
glEnableVertexAttribArray(m_shaders->m_shBLURPREPARE.texAttrib);
if (!damage.empty()) { if (!damage.empty()) {
for (auto const& RECT : damage.getRects()) { for (auto const& RECT : damage.getRects()) {
@ -1905,9 +1851,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
} }
} }
glDisableVertexAttribArray(m_shaders->m_shBLURPREPARE.posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(m_shaders->m_shBLURPREPARE.texAttrib);
currentRenderToFB = PMIRRORSWAPFB; currentRenderToFB = PMIRRORSWAPFB;
} }
@ -1926,15 +1870,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glTexParameteri(currentTex->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(currentTex->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(pShader->program); useProgram(pShader->program);
// prep two shaders // prep two shaders
#ifndef GLES2
glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a
if (pShader == &m_shaders->m_shBLUR1) { if (pShader == &m_shaders->m_shBLUR1) {
glUniform2f(m_shaders->m_shBLUR1.halfpixel, 0.5f / (m_renderData.pMonitor->m_pixelSize.x / 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y / 2.f)); glUniform2f(m_shaders->m_shBLUR1.halfpixel, 0.5f / (m_renderData.pMonitor->m_pixelSize.x / 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y / 2.f));
@ -1945,12 +1884,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glUniform2f(m_shaders->m_shBLUR2.halfpixel, 0.5f / (m_renderData.pMonitor->m_pixelSize.x * 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y * 2.f)); glUniform2f(m_shaders->m_shBLUR2.halfpixel, 0.5f / (m_renderData.pMonitor->m_pixelSize.x * 2.f), 0.5f / (m_renderData.pMonitor->m_pixelSize.y * 2.f));
glUniform1i(pShader->tex, 0); glUniform1i(pShader->tex, 0);
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(pShader->shaderVao);
glVertexAttribPointer(pShader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(pShader->posAttrib);
glEnableVertexAttribArray(pShader->texAttrib);
if (!pDamage->empty()) { if (!pDamage->empty()) {
for (auto const& RECT : pDamage->getRects()) { for (auto const& RECT : pDamage->getRects()) {
scissor(&RECT, false /* this region is already transformed */); scissor(&RECT, false /* this region is already transformed */);
@ -1958,8 +1892,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
} }
} }
glDisableVertexAttribArray(pShader->posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(pShader->texAttrib);
if (currentRenderToFB != PMIRRORFB) if (currentRenderToFB != PMIRRORFB)
currentRenderToFB = PMIRRORFB; currentRenderToFB = PMIRRORFB;
@ -2004,24 +1937,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glTexParameteri(currentTex->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(currentTex->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(m_shaders->m_shBLURFINISH.program); useProgram(m_shaders->m_shBLURFINISH.program);
#ifndef GLES2
glUniformMatrix3fv(m_shaders->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(m_shaders->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(m_shaders->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform1f(m_shaders->m_shBLURFINISH.noise, *PBLURNOISE); glUniform1f(m_shaders->m_shBLURFINISH.noise, *PBLURNOISE);
glUniform1f(m_shaders->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS); glUniform1f(m_shaders->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS);
glUniform1i(m_shaders->m_shBLURFINISH.tex, 0); glUniform1i(m_shaders->m_shBLURFINISH.tex, 0);
glVertexAttribPointer(m_shaders->m_shBLURFINISH.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(m_shaders->m_shBLURFINISH.shaderVao);
glVertexAttribPointer(m_shaders->m_shBLURFINISH.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shaders->m_shBLURFINISH.posAttrib);
glEnableVertexAttribArray(m_shaders->m_shBLURFINISH.texAttrib);
if (!damage.empty()) { if (!damage.empty()) {
for (auto const& RECT : damage.getRects()) { for (auto const& RECT : damage.getRects()) {
@ -2030,8 +1953,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
} }
} }
glDisableVertexAttribArray(m_shaders->m_shBLURFINISH.posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(m_shaders->m_shBLURFINISH.texAttrib);
if (currentRenderToFB != PMIRRORFB) if (currentRenderToFB != PMIRRORFB)
currentRenderToFB = PMIRRORFB; currentRenderToFB = PMIRRORFB;
@ -2224,7 +2146,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, const CBox& box, f
// amazing hack: the surface has an opaque region! // amazing hack: the surface has an opaque region!
CRegion inverseOpaque; CRegion inverseOpaque;
if (a >= 1.f && std::round(pSurface->m_current.size.x * m_renderData.pMonitor->m_scale) == box.w && if (a >= 1.f && pSurface && std::round(pSurface->m_current.size.x * m_renderData.pMonitor->m_scale) == box.w &&
std::round(pSurface->m_current.size.y * m_renderData.pMonitor->m_scale) == box.h) { std::round(pSurface->m_current.size.y * m_renderData.pMonitor->m_scale) == box.h) {
pixman_box32_t surfbox = {0, 0, pSurface->m_current.size.x * pSurface->m_current.scale, pSurface->m_current.size.y * pSurface->m_current.scale}; pixman_box32_t surfbox = {0, 0, pSurface->m_current.size.x * pSurface->m_current.scale, pSurface->m_current.size.y * pSurface->m_current.scale};
inverseOpaque = pSurface->m_current.opaque; inverseOpaque = pSurface->m_current.opaque;
@ -2247,7 +2169,6 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, const CBox& box, f
inverseOpaque.translate(box.pos()); inverseOpaque.translate(box.pos());
m_renderData.renderModif.applyToRegion(inverseOpaque); m_renderData.renderModif.applyToRegion(inverseOpaque);
inverseOpaque.intersect(texDamage); inverseOpaque.intersect(texDamage);
POUTFB = blurMainFramebufferWithDamage(a, &inverseOpaque); POUTFB = blurMainFramebufferWithDamage(a, &inverseOpaque);
} else } else
POUTFB = &m_renderData.pCurrentMonData->blurFB; POUTFB = &m_renderData.pCurrentMonData->blurFB;
@ -2348,20 +2269,14 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
const auto BLEND = m_blend; const auto BLEND = m_blend;
blend(true); blend(true);
glUseProgram(m_shaders->m_shBORDER1.program); useProgram(m_shaders->m_shBORDER1.program);
const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{}; const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{};
glUniform1i(m_shaders->m_shBORDER1.skipCM, skipCM); glUniform1i(m_shaders->m_shBORDER1.skipCM, skipCM);
if (!skipCM) if (!skipCM)
passCMUniforms(m_shaders->m_shBORDER1, SImageDescription{}); passCMUniforms(m_shaders->m_shBORDER1, SImageDescription{});
#ifndef GLES2
glUniformMatrix3fv(m_shaders->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(m_shaders->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(m_shaders->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform4fv(m_shaders->m_shBORDER1.gradient, grad.m_colorsOkLabA.size() / 4, (float*)grad.m_colorsOkLabA.data()); glUniform4fv(m_shaders->m_shBORDER1.gradient, grad.m_colorsOkLabA.size() / 4, (float*)grad.m_colorsOkLabA.data());
glUniform1i(m_shaders->m_shBORDER1.gradientLength, grad.m_colorsOkLabA.size() / 4); glUniform1i(m_shaders->m_shBORDER1.gradientLength, grad.m_colorsOkLabA.size() / 4);
glUniform1f(m_shaders->m_shBORDER1.angle, (int)(grad.m_angle / (PI / 180.0)) % 360 * (PI / 180.0)); glUniform1f(m_shaders->m_shBORDER1.angle, (int)(grad.m_angle / (PI / 180.0)) % 360 * (PI / 180.0));
@ -2383,11 +2298,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
glUniform1f(m_shaders->m_shBORDER1.roundingPower, roundingPower); glUniform1f(m_shaders->m_shBORDER1.roundingPower, roundingPower);
glUniform1f(m_shaders->m_shBORDER1.thick, scaledBorderSize); glUniform1f(m_shaders->m_shBORDER1.thick, scaledBorderSize);
glVertexAttribPointer(m_shaders->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(m_shaders->m_shBORDER1.shaderVao);
glVertexAttribPointer(m_shaders->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shaders->m_shBORDER1.posAttrib);
glEnableVertexAttribArray(m_shaders->m_shBORDER1.texAttrib);
if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) { if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) {
CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height}; CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height};
@ -2406,8 +2317,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
} }
} }
glDisableVertexAttribArray(m_shaders->m_shBORDER1.posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(m_shaders->m_shBORDER1.texAttrib);
blend(BLEND); blend(BLEND);
} }
@ -2446,15 +2356,8 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
const auto BLEND = m_blend; const auto BLEND = m_blend;
blend(true); blend(true);
glUseProgram(m_shaders->m_shBORDER1.program); useProgram(m_shaders->m_shBORDER1.program);
#ifndef GLES2
glUniformMatrix3fv(m_shaders->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(m_shaders->m_shBORDER1.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(m_shaders->m_shBORDER1.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform4fv(m_shaders->m_shBORDER1.gradient, grad1.m_colorsOkLabA.size() / 4, (float*)grad1.m_colorsOkLabA.data()); glUniform4fv(m_shaders->m_shBORDER1.gradient, grad1.m_colorsOkLabA.size() / 4, (float*)grad1.m_colorsOkLabA.data());
glUniform1i(m_shaders->m_shBORDER1.gradientLength, grad1.m_colorsOkLabA.size() / 4); glUniform1i(m_shaders->m_shBORDER1.gradientLength, grad1.m_colorsOkLabA.size() / 4);
glUniform1f(m_shaders->m_shBORDER1.angle, (int)(grad1.m_angle / (PI / 180.0)) % 360 * (PI / 180.0)); glUniform1f(m_shaders->m_shBORDER1.angle, (int)(grad1.m_angle / (PI / 180.0)) % 360 * (PI / 180.0));
@ -2480,11 +2383,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
glUniform1f(m_shaders->m_shBORDER1.roundingPower, roundingPower); glUniform1f(m_shaders->m_shBORDER1.roundingPower, roundingPower);
glUniform1f(m_shaders->m_shBORDER1.thick, scaledBorderSize); glUniform1f(m_shaders->m_shBORDER1.thick, scaledBorderSize);
glVertexAttribPointer(m_shaders->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(m_shaders->m_shBORDER1.shaderVao);
glVertexAttribPointer(m_shaders->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shaders->m_shBORDER1.posAttrib);
glEnableVertexAttribArray(m_shaders->m_shBORDER1.texAttrib);
if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) { if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) {
CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height}; CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height};
@ -2503,9 +2402,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
} }
} }
glDisableVertexAttribArray(m_shaders->m_shBORDER1.posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(m_shaders->m_shBORDER1.texAttrib);
blend(BLEND); blend(BLEND);
} }
@ -2534,18 +2431,13 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
blend(true); blend(true);
glUseProgram(m_shaders->m_shSHADOW.program); useProgram(m_shaders->m_shSHADOW.program);
const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{}; const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{};
glUniform1i(m_shaders->m_shSHADOW.skipCM, skipCM); glUniform1i(m_shaders->m_shSHADOW.skipCM, skipCM);
if (!skipCM) if (!skipCM)
passCMUniforms(m_shaders->m_shSHADOW, SImageDescription{}); passCMUniforms(m_shaders->m_shSHADOW, SImageDescription{});
#ifndef GLES2
glUniformMatrix3fv(m_shaders->m_shSHADOW.proj, 1, GL_TRUE, glMatrix.getMatrix().data()); glUniformMatrix3fv(m_shaders->m_shSHADOW.proj, 1, GL_TRUE, glMatrix.getMatrix().data());
#else
glMatrix.transpose();
glUniformMatrix3fv(m_shaders->m_shSHADOW.proj, 1, GL_FALSE, glMatrix.getMatrix().data());
#endif
glUniform4f(m_shaders->m_shSHADOW.color, col.r, col.g, col.b, col.a * a); glUniform4f(m_shaders->m_shSHADOW.color, col.r, col.g, col.b, col.a * a);
const auto TOPLEFT = Vector2D(range + round, range + round); const auto TOPLEFT = Vector2D(range + round, range + round);
@ -2561,11 +2453,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
glUniform1f(m_shaders->m_shSHADOW.range, range); glUniform1f(m_shaders->m_shSHADOW.range, range);
glUniform1f(m_shaders->m_shSHADOW.shadowPower, SHADOWPOWER); glUniform1f(m_shaders->m_shSHADOW.shadowPower, SHADOWPOWER);
glVertexAttribPointer(m_shaders->m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glBindVertexArray(m_shaders->m_shSHADOW.shaderVao);
glVertexAttribPointer(m_shaders->m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shaders->m_shSHADOW.posAttrib);
glEnableVertexAttribArray(m_shaders->m_shSHADOW.texAttrib);
if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) { if (m_renderData.clipBox.width != 0 && m_renderData.clipBox.height != 0) {
CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height}; CRegion damageClip{m_renderData.clipBox.x, m_renderData.clipBox.y, m_renderData.clipBox.width, m_renderData.clipBox.height};
@ -2584,8 +2472,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
} }
} }
glDisableVertexAttribArray(m_shaders->m_shSHADOW.posAttrib); glBindVertexArray(0);
glDisableVertexAttribArray(m_shaders->m_shSHADOW.texAttrib);
} }
void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) { void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) {
@ -2705,13 +2592,7 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
tex->allocate(); tex->allocate();
tex->m_size = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; tex->m_size = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)};
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : GL_RGBA;
#ifdef GLES2
GL_RGB32F_EXT :
#else
GL_RGB32F :
#endif
GL_RGBA;
const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA; const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA;
const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE;
@ -2719,12 +2600,12 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
glBindTexture(GL_TEXTURE_2D, tex->m_texID); glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) { if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
} }
#endif
glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA); glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA);
cairo_surface_destroy(CAIROSURFACE); cairo_surface_destroy(CAIROSURFACE);
@ -2802,10 +2683,8 @@ SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col
glBindTexture(GL_TEXTURE_2D, tex->m_texID); glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->m_size.x, tex->m_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->m_size.x, tex->m_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
cairo_destroy(CAIRO); cairo_destroy(CAIRO);
@ -2845,10 +2724,8 @@ void CHyprOpenGLImpl::initMissingAssetTexture() {
glBindTexture(GL_TEXTURE_2D, tex->m_texID); glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA); glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA);
cairo_surface_destroy(CAIROSURFACE); cairo_surface_destroy(CAIROSURFACE);
@ -2857,6 +2734,14 @@ void CHyprOpenGLImpl::initMissingAssetTexture() {
m_missingAssetTexture = tex; m_missingAssetTexture = tex;
} }
void CHyprOpenGLImpl::useProgram(GLuint prog) {
if (m_currentProgram == prog)
return;
glUseProgram(prog);
m_currentProgram = prog;
}
void CHyprOpenGLImpl::initAssets() { void CHyprOpenGLImpl::initAssets() {
initMissingAssetTexture(); initMissingAssetTexture();
@ -2950,10 +2835,8 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
glBindTexture(GL_TEXTURE_2D, tex->m_texID); glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA); glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA);
cairo_surface_destroy(CAIROSURFACE); cairo_surface_destroy(CAIROSURFACE);

View File

@ -119,6 +119,7 @@ struct SCurrentRenderData {
Mat3x3 savedProjection; Mat3x3 savedProjection;
Mat3x3 monitorProjection; Mat3x3 monitorProjection;
// FIXME: raw pointer galore!
SMonitorRenderData* pCurrentMonData = nullptr; SMonitorRenderData* pCurrentMonData = nullptr;
CFramebuffer* currentFB = nullptr; // current rendering to CFramebuffer* currentFB = nullptr; // current rendering to
CFramebuffer* mainFB = nullptr; // main to render to CFramebuffer* mainFB = nullptr; // main to render to
@ -239,6 +240,11 @@ class CHyprOpenGLImpl {
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs); EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
bool initShaders(); bool initShaders();
GLuint createProgram(const std::string&, const std::string&, bool dynamic = false, bool silent = false);
GLuint compileShader(const GLuint&, std::string, bool dynamic = false, bool silent = false);
void useProgram(GLuint prog);
bool m_shadersInitialized = false; bool m_shadersInitialized = false;
SP<SPreparedShaders> m_shaders; SP<SPreparedShaders> m_shaders;
@ -311,6 +317,7 @@ class CHyprOpenGLImpl {
SShader m_finalScreenShader; SShader m_finalScreenShader;
CTimer m_globalTimer; CTimer m_globalTimer;
GLuint m_currentProgram;
SP<CTexture> m_missingAssetTexture; SP<CTexture> m_missingAssetTexture;
SP<CTexture> m_backgroundTexture; SP<CTexture> m_backgroundTexture;
@ -319,8 +326,6 @@ class CHyprOpenGLImpl {
SP<CTexture> m_lockTtyTextTexture; // TODO: don't always load lock SP<CTexture> m_lockTtyTextTexture; // TODO: don't always load lock
void logShaderError(const GLuint&, bool program = false, bool silent = false); void logShaderError(const GLuint&, bool program = false, bool silent = false);
GLuint createProgram(const std::string&, const std::string&, bool dynamic = false, bool silent = false);
GLuint compileShader(const GLuint&, std::string, bool dynamic = false, bool silent = false);
void createBGTextureForMonitor(PHLMONITOR); void createBGTextureForMonitor(PHLMONITOR);
void initDRMFormats(); void initDRMFormats();
void initEGL(bool gbm); void initEGL(bool gbm);
@ -333,6 +338,7 @@ class CHyprOpenGLImpl {
// returns the out FB, can be either Mirror or MirrorSwap // returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
CFramebuffer* blurFramebufferWithDamage(float a, CRegion* damage, CFramebuffer& source);
void passCMUniforms(const SShader&, const NColorManagement::SImageDescription& imageDescription, const NColorManagement::SImageDescription& targetImageDescription, void passCMUniforms(const SShader&, const NColorManagement::SImageDescription& imageDescription, const NColorManagement::SImageDescription& targetImageDescription,
bool modifySDR = false); bool modifySDR = false);

View File

@ -175,7 +175,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) {
return false; return false;
if (!pWindow->m_workspace && pWindow->m_fadingOut) if (!pWindow->m_workspace && pWindow->m_fadingOut)
return pWindow->workspaceID() == pMonitor->activeWorkspaceID(); return pWindow->workspaceID() == pMonitor->activeWorkspaceID() || pWindow->workspaceID() == pMonitor->activeSpecialWorkspaceID();
if (pWindow->m_pinned) if (pWindow->m_pinned)
return true; return true;
@ -493,7 +493,6 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T
// whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws // whether to use m_fMovingToWorkspaceAlpha, only if fading out into an invisible ws
const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_monitorMovedFrom != -1 && (!PWORKSPACE || !PWORKSPACE->isVisible()); const bool USE_WORKSPACE_FADE_ALPHA = pWindow->m_monitorMovedFrom != -1 && (!PWORKSPACE || !PWORKSPACE->isVisible());
const bool DONT_BLUR = pWindow->m_windowData.noBlur.valueOrDefault() || pWindow->m_windowData.RGBX.valueOrDefault() || pWindow->opaque();
renderdata.surface = pWindow->m_wlSurface->resource(); renderdata.surface = pWindow->m_wlSurface->resource();
renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_windowData.noRounding.valueOrDefault(); renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_windowData.noRounding.valueOrDefault();
@ -503,7 +502,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T
renderdata.decorate = decorate && !pWindow->m_X11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); renderdata.decorate = decorate && !pWindow->m_X11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN);
renderdata.rounding = standalone || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->m_scale; renderdata.rounding = standalone || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->m_scale;
renderdata.roundingPower = standalone || renderdata.dontRound ? 2.0f : pWindow->roundingPower(); renderdata.roundingPower = standalone || renderdata.dontRound ? 2.0f : pWindow->roundingPower();
renderdata.blur = !standalone && *PBLUR && !DONT_BLUR; renderdata.blur = !standalone && shouldBlur(pWindow);
renderdata.pWindow = pWindow; renderdata.pWindow = pWindow;
if (standalone) { if (standalone) {
@ -572,7 +571,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T
if ((pWindow->m_isX11 && *PXWLUSENN) || pWindow->m_windowData.nearestNeighbor.valueOrDefault()) if ((pWindow->m_isX11 && *PXWLUSENN) || pWindow->m_windowData.nearestNeighbor.valueOrDefault())
renderdata.useNearestNeighbor = true; renderdata.useNearestNeighbor = true;
if (!pWindow->m_windowData.noBlur.valueOrDefault() && pWindow->m_wlSurface->small() && !pWindow->m_wlSurface->m_fillIgnoreSmall && renderdata.blur && *PBLUR) { if (pWindow->m_wlSurface->small() && !pWindow->m_wlSurface->m_fillIgnoreSmall && renderdata.blur) {
CBox wb = {renderdata.pos.x - pMonitor->m_position.x, renderdata.pos.y - pMonitor->m_position.y, renderdata.w, renderdata.h}; CBox wb = {renderdata.pos.x - pMonitor->m_position.x, renderdata.pos.y - pMonitor->m_position.y, renderdata.w, renderdata.h};
wb.scale(pMonitor->m_scale).round(); wb.scale(pMonitor->m_scale).round();
CRectPassElement::SRectData data; CRectPassElement::SRectData data;
@ -712,8 +711,6 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, const Time::s
return; return;
} }
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
TRACY_GPU_ZONE("RenderLayer"); TRACY_GPU_ZONE("RenderLayer");
const auto REALPOS = pLayer->m_realPosition->value(); const auto REALPOS = pLayer->m_realPosition->value();
@ -721,7 +718,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, const Time::s
CSurfacePassElement::SRenderData renderdata = {pMonitor, time, REALPOS}; CSurfacePassElement::SRenderData renderdata = {pMonitor, time, REALPOS};
renderdata.fadeAlpha = pLayer->m_alpha->value(); renderdata.fadeAlpha = pLayer->m_alpha->value();
renderdata.blur = pLayer->m_forceBlur && *PBLUR; renderdata.blur = shouldBlur(pLayer);
renderdata.surface = pLayer->m_surface->resource(); renderdata.surface = pLayer->m_surface->resource();
renderdata.decorate = false; renderdata.decorate = false;
renderdata.w = REALSIZ.x; renderdata.w = REALSIZ.x;
@ -874,12 +871,15 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
renderLayer(ls.lock(), pMonitor, time); renderLayer(ls.lock(), pMonitor, time);
} }
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
renderLayer(ls.lock(), pMonitor, time); renderLayer(ls.lock(), pMonitor, time);
} }
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
renderLayer(ls.lock(), pMonitor, time); renderLayer(ls.lock(), pMonitor, time);
} }
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
renderLayer(ls.lock(), pMonitor, time); renderLayer(ls.lock(), pMonitor, time);
} }
@ -896,6 +896,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
renderLayer(ls.lock(), pMonitor, time); renderLayer(ls.lock(), pMonitor, time);
} }
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) { for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
renderLayer(ls.lock(), pMonitor, time); renderLayer(ls.lock(), pMonitor, time);
} }
@ -940,9 +941,9 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
// special // special
for (auto const& ws : g_pCompositor->m_workspaces) { for (auto const& ws : g_pCompositor->m_workspaces) {
if (ws->m_alpha->value() > 0.f && ws->m_isSpecialWorkspace) { if (ws->m_alpha->value() > 0.f && ws->m_isSpecialWorkspace) {
if (ws->m_hasFullscreenWindow) if (ws->m_hasFullscreenWindow) {
renderWorkspaceWindowsFullscreen(pMonitor, ws, time); renderWorkspaceWindowsFullscreen(pMonitor, ws, time);
else } else
renderWorkspaceWindows(pMonitor, ws, time); renderWorkspaceWindows(pMonitor, ws, time);
} }
} }
@ -1036,7 +1037,7 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) {
// also render text for the tty number // also render text for the tty number
if (g_pHyprOpenGL->m_lockTtyTextTexture) { if (g_pHyprOpenGL->m_lockTtyTextTexture) {
CBox texbox = {{}, g_pHyprOpenGL->m_lockTtyTextTexture->m_size}; CBox texbox = {{}, g_pHyprOpenGL->m_lockTtyTextTexture->m_size};
g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_lockTtyTextTexture, texbox, 1.F); g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_lockTtyTextTexture, texbox, ALPHA);
} }
} }
@ -2279,9 +2280,6 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
g_pHyprOpenGL->m_renderData.mouseZoomUseMouse = true; g_pHyprOpenGL->m_renderData.mouseZoomUseMouse = true;
} }
// send all queued opengl commands so rendering starts happening immediately
glFlush();
if (m_renderMode == RENDER_MODE_FULL_FAKE) if (m_renderMode == RENDER_MODE_FULL_FAKE)
return; return;
@ -2389,7 +2387,7 @@ void CHyprRenderer::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFram
makeEGLCurrent(); makeEGLCurrent();
pFramebuffer->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, PMONITOR->m_output->state->state().drmFormat); pFramebuffer->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
pFramebuffer->addStencil(g_pHyprOpenGL->m_renderData.pCurrentMonData->stencilTex); pFramebuffer->addStencil(g_pHyprOpenGL->m_renderData.pCurrentMonData->stencilTex);
beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer);
@ -2440,7 +2438,7 @@ void CHyprRenderer::makeWindowSnapshot(PHLWINDOW pWindow) {
const auto PFRAMEBUFFER = &g_pHyprOpenGL->m_windowFramebuffers[ref]; const auto PFRAMEBUFFER = &g_pHyprOpenGL->m_windowFramebuffers[ref];
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, PMONITOR->m_output->state->state().drmFormat); PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER);
@ -2448,21 +2446,8 @@ void CHyprRenderer::makeWindowSnapshot(PHLWINDOW pWindow) {
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC
// this is a hack but it works :P
// we need to disable blur or else we will get a black background, as the shader
// will try to copy the bg to apply blur.
// this isn't entirely correct, but like, oh well.
// small todo: maybe make this correct? :P
static auto* const PBLUR = (Hyprlang::INT* const*)(g_pConfigManager->getConfigValuePtr("decoration:blur:enabled"));
const auto BLURVAL = **PBLUR;
**PBLUR = 0;
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC
renderWindow(pWindow, PMONITOR, Time::steadyNow(), !pWindow->m_X11DoesntWantBorders, RENDER_PASS_ALL); renderWindow(pWindow, PMONITOR, Time::steadyNow(), !pWindow->m_X11DoesntWantBorders, RENDER_PASS_ALL);
**PBLUR = BLURVAL;
endRender(); endRender();
m_bRenderingSnapshot = false; m_bRenderingSnapshot = false;
@ -2484,7 +2469,7 @@ void CHyprRenderer::makeLayerSnapshot(PHLLS pLayer) {
const auto PFRAMEBUFFER = &g_pHyprOpenGL->m_layerFramebuffers[pLayer]; const auto PFRAMEBUFFER = &g_pHyprOpenGL->m_layerFramebuffers[pLayer];
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, PMONITOR->m_output->state->state().drmFormat); PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER);
@ -2492,14 +2477,9 @@ void CHyprRenderer::makeLayerSnapshot(PHLLS pLayer) {
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC
const auto BLURLSSTATUS = pLayer->m_forceBlur;
pLayer->m_forceBlur = false;
// draw the layer // draw the layer
renderLayer(pLayer, PMONITOR, Time::steadyNow()); renderLayer(pLayer, PMONITOR, Time::steadyNow());
pLayer->m_forceBlur = BLURLSSTATUS;
endRender(); endRender();
m_bRenderingSnapshot = false; m_bRenderingSnapshot = false;
@ -2534,14 +2514,25 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) {
CRegion fakeDamage{0, 0, PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y}; CRegion fakeDamage{0, 0, PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y};
if (*PDIMAROUND && pWindow->m_windowData.dimAround.valueOrDefault()) { if (*PDIMAROUND && pWindow->m_windowData.dimAround.valueOrDefault()) {
CRectPassElement::SRectData data; CRectPassElement::SRectData data;
data.box = {0, 0, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.x, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.y}; data.box = {0, 0, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.x, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.y};
data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_alpha->value()); data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_alpha->value());
m_renderPass.add(makeShared<CRectPassElement>(data)); m_renderPass.add(makeShared<CRectPassElement>(data));
damageMonitor(PMONITOR); }
if (shouldBlur(pWindow)) {
CRectPassElement::SRectData data;
data.box = CBox{pWindow->m_realPosition->value(), pWindow->m_realSize->value()}.translate(-PMONITOR->m_position).scale(PMONITOR->m_scale).round();
data.color = CHyprColor{0, 0, 0, 0};
data.blur = true;
data.blurA = sqrt(pWindow->m_alpha->value()); // sqrt makes the blur fadeout more realistic.
data.round = pWindow->rounding();
data.roundingPower = pWindow->roundingPower();
data.xray = pWindow->m_windowData.xray.valueOr(false);
m_renderPass.add(makeShared<CRectPassElement>(data));
} }
CTexPassElement::SRenderData data; CTexPassElement::SRenderData data;
@ -2580,12 +2571,35 @@ void CHyprRenderer::renderSnapshot(PHLLS pLayer) {
CRegion fakeDamage{0, 0, PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y}; CRegion fakeDamage{0, 0, PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y};
const bool SHOULD_BLUR = shouldBlur(pLayer);
CTexPassElement::SRenderData data; CTexPassElement::SRenderData data;
data.flipEndFrame = true; data.flipEndFrame = true;
data.tex = FBDATA->getTexture(); data.tex = FBDATA->getTexture();
data.box = layerBox; data.box = layerBox;
data.a = pLayer->m_alpha->value(); data.a = pLayer->m_alpha->value();
data.damage = fakeDamage; data.damage = fakeDamage;
data.blur = SHOULD_BLUR;
data.blurA = sqrt(pLayer->m_alpha->value()); // sqrt makes the blur fadeout more realistic.
if (SHOULD_BLUR)
data.ignoreAlpha = pLayer->m_ignoreAlpha ? pLayer->m_ignoreAlphaValue : 0.01F /* ignore the alpha 0 regions */;
m_renderPass.add(makeShared<CTexPassElement>(data)); m_renderPass.add(makeShared<CTexPassElement>(data));
} }
bool CHyprRenderer::shouldBlur(PHLLS ls) {
if (m_bRenderingSnapshot)
return false;
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
return *PBLUR && ls->m_forceBlur;
}
bool CHyprRenderer::shouldBlur(PHLWINDOW w) {
if (m_bRenderingSnapshot)
return false;
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
const bool DONT_BLUR = w->m_windowData.noBlur.valueOrDefault() || w->m_windowData.RGBX.valueOrDefault() || w->opaque();
return *PBLUR && !DONT_BLUR;
}

View File

@ -45,6 +45,11 @@ struct SExplicitSyncSettings {
bool explicitEnabled = false, explicitKMSEnabled = false; bool explicitEnabled = false, explicitKMSEnabled = false;
}; };
struct SRenderWorkspaceUntilData {
PHLLS ls;
PHLWINDOW w;
};
class CHyprRenderer { class CHyprRenderer {
public: public:
CHyprRenderer(); CHyprRenderer();
@ -117,20 +122,23 @@ class CHyprRenderer {
private: private:
void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*); void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*);
void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const CBox& geometry);
void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
void renderWindow(PHLWINDOW, PHLMONITOR, const Time::steady_tp&, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false); void renderWindow(PHLWINDOW, PHLMONITOR, const Time::steady_tp&, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false);
void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false, bool lockscreen = false); void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false, bool lockscreen = false);
void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&); void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&);
void renderDragIcon(PHLMONITOR, const Time::steady_tp&); void renderDragIcon(PHLMONITOR, const Time::steady_tp&);
void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&); void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&);
void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const CBox& geometry);
void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything
void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
void renderSessionLockMissing(PHLMONITOR pMonitor); void renderSessionLockMissing(PHLMONITOR pMonitor);
bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor);
bool shouldBlur(PHLLS ls);
bool shouldBlur(PHLWINDOW w);
bool m_cursorHidden = false; bool m_cursorHidden = false;
bool m_cursorHasSurface = false; bool m_cursorHasSurface = false;
SP<CRenderbuffer> m_currentRenderbuffer = nullptr; SP<CRenderbuffer> m_currentRenderbuffer = nullptr;

View File

@ -1,14 +1,48 @@
#include "Shader.hpp" #include "Shader.hpp"
#include "render/OpenGL.hpp"
SShader::~SShader() { SShader::~SShader() {
destroy(); destroy();
} }
void SShader::createVao() {
glGenVertexArrays(1, &shaderVao);
glBindVertexArray(shaderVao);
if (posAttrib != -1) {
glGenBuffers(1, &shaderVboPos);
glBindBuffer(GL_ARRAY_BUFFER, shaderVboPos);
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW);
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
}
// UV VBO (dynamic, may be updated per frame)
if (texAttrib != -1) {
glGenBuffers(1, &shaderVboUv);
glBindBuffer(GL_ARRAY_BUFFER, shaderVboUv);
glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_DYNAMIC_DRAW); // Initial dummy UVs
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
}
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void SShader::destroy() { void SShader::destroy() {
if (program == 0) if (program == 0)
return; return;
glDeleteProgram(program); if (shaderVao)
glDeleteVertexArrays(1, &shaderVao);
if (shaderVboPos)
glDeleteBuffers(1, &shaderVboPos);
if (shaderVboUv)
glDeleteBuffers(1, &shaderVboUv);
glDeleteProgram(program);
program = 0; program = 0;
} }

View File

@ -32,6 +32,10 @@ struct SShader {
GLint discardAlpha = -1; GLint discardAlpha = -1;
GLfloat discardAlphaValue = -1; GLfloat discardAlphaValue = -1;
GLuint shaderVao = 0;
GLuint shaderVboPos = 0;
GLuint shaderVboUv = 0;
GLint topLeft = -1; GLint topLeft = -1;
GLint bottomRight = -1; GLint bottomRight = -1;
GLint fullSize = -1; GLint fullSize = -1;
@ -76,5 +80,6 @@ struct SShader {
GLint brightness = -1; GLint brightness = -1;
GLint noise = -1; GLint noise = -1;
void createVao();
void destroy(); void destroy();
}; };

View File

@ -72,12 +72,12 @@ void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t strid
GLCALL(glBindTexture(GL_TEXTURE_2D, m_texID)); GLCALL(glBindTexture(GL_TEXTURE_2D, m_texID));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
#ifndef GLES2
if (format->flipRB) { if (format->flipRB) {
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE)); GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED)); GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
} }
#endif
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock)); GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels)); GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels));
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0)); GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
@ -120,12 +120,10 @@ void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, cons
auto rects = damage.copy().intersect(CBox{{}, m_size}).getRects(); auto rects = damage.copy().intersect(CBox{{}, m_size}).getRects();
#ifndef GLES2
if (format->flipRB) { if (format->flipRB) {
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE)); GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED)); GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
} }
#endif
for (auto const& rect : rects) { for (auto const& rect : rects) {
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock)); GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));

View File

@ -332,11 +332,8 @@ static void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
glBindTexture(GL_TEXTURE_2D, tex->m_texID); glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferSize.x, bufferSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferSize.x, bufferSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);

View File

@ -42,7 +42,6 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW
return wb.pos() + Vector2D{0.0, wb.size().y / 2.0}; return wb.pos() + Vector2D{0.0, wb.size().y / 2.0};
else if (RIGHT) else if (RIGHT)
return wb.pos() + Vector2D{wb.size().x, wb.size().y / 2.0}; return wb.pos() + Vector2D{wb.size().x, wb.size().y / 2.0};
UNREACHABLE();
} else { } else {
if (TOP && LEFT) if (TOP && LEFT)
return wb.pos(); return wb.pos();
@ -52,9 +51,8 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW
return wb.pos() + wb.size(); return wb.pos() + wb.size();
if (BOTTOM && LEFT) if (BOTTOM && LEFT)
return wb.pos() + Vector2D{0.0, wb.size().y}; return wb.pos() + Vector2D{0.0, wb.size().y};
UNREACHABLE();
} }
UNREACHABLE(); Debug::log(ERR, "getEdgeDefinedPoint: invalid configuration of edges");
return {}; return {};
} }

View File

@ -273,7 +273,7 @@ CRegion CSurfacePassElement::visibleRegion(bool& cancel) {
texBox.round(); texBox.round();
visibleRegion.scale((Vector2D(1, 1) / (uvBR - uvTL)) * (texBox.size() / bufferSize)); visibleRegion.scale((Vector2D(1, 1) / (uvBR - uvTL)) * (texBox.size() / bufferSize));
visibleRegion.translate((m_data.pos + m_data.localPos) * m_data.pMonitor->m_scale - m_data.pMonitor->m_position); visibleRegion.translate((m_data.pos + m_data.localPos - m_data.pMonitor->m_position) * m_data.pMonitor->m_scale);
return visibleRegion; return visibleRegion;
} }

View File

@ -11,10 +11,14 @@ CTexPassElement::CTexPassElement(const CTexPassElement::SRenderData& data_) : m_
void CTexPassElement::draw(const CRegion& damage) { void CTexPassElement::draw(const CRegion& damage) {
g_pHyprOpenGL->m_endFrame = m_data.flipEndFrame; g_pHyprOpenGL->m_endFrame = m_data.flipEndFrame;
CScopeGuard x = {[]() { CScopeGuard x = {[this]() {
// //
g_pHyprOpenGL->m_endFrame = false; g_pHyprOpenGL->m_endFrame = false;
g_pHyprOpenGL->m_renderData.clipBox = {}; g_pHyprOpenGL->m_renderData.clipBox = {};
if (m_data.replaceProjection)
g_pHyprOpenGL->m_renderData.monitorProjection = g_pHyprOpenGL->m_renderData.pMonitor->m_projMatrix;
if (m_data.ignoreAlpha.has_value())
g_pHyprOpenGL->m_renderData.discardMode = 0;
}}; }};
if (!m_data.clipBox.empty()) if (!m_data.clipBox.empty())
@ -22,9 +26,16 @@ void CTexPassElement::draw(const CRegion& damage) {
if (m_data.replaceProjection) if (m_data.replaceProjection)
g_pHyprOpenGL->m_renderData.monitorProjection = *m_data.replaceProjection; g_pHyprOpenGL->m_renderData.monitorProjection = *m_data.replaceProjection;
if (m_data.ignoreAlpha.has_value()) {
g_pHyprOpenGL->m_renderData.discardMode = DISCARD_ALPHA;
g_pHyprOpenGL->m_renderData.discardOpacity = *m_data.ignoreAlpha;
}
if (m_data.blur)
g_pHyprOpenGL->renderTextureWithBlur(m_data.tex, m_data.box, m_data.a, nullptr, m_data.round, m_data.roundingPower, false, m_data.blurA, 1.F);
else
g_pHyprOpenGL->renderTextureInternalWithDamage(m_data.tex, m_data.box, m_data.a, m_data.damage.empty() ? damage : m_data.damage, m_data.round, m_data.roundingPower); g_pHyprOpenGL->renderTextureInternalWithDamage(m_data.tex, m_data.box, m_data.a, m_data.damage.empty() ? damage : m_data.damage, m_data.round, m_data.roundingPower);
if (m_data.replaceProjection)
g_pHyprOpenGL->m_renderData.monitorProjection = g_pHyprOpenGL->m_renderData.pMonitor->m_projMatrix;
} }
bool CTexPassElement::needsLiveBlur() { bool CTexPassElement::needsLiveBlur() {

View File

@ -12,12 +12,15 @@ class CTexPassElement : public IPassElement {
SP<CTexture> tex; SP<CTexture> tex;
CBox box; CBox box;
float a = 1.F; float a = 1.F;
float blurA = 1.F;
CRegion damage; CRegion damage;
int round = 0; int round = 0;
float roundingPower = 2.0f; float roundingPower = 2.0f;
bool flipEndFrame = false; bool flipEndFrame = false;
std::optional<Mat3x3> replaceProjection; std::optional<Mat3x3> replaceProjection;
CBox clipBox; CBox clipBox;
bool blur = false;
std::optional<float> ignoreAlpha;
}; };
CTexPassElement(const SRenderData& data); CTexPassElement(const SRenderData& data);

View File

@ -5,7 +5,9 @@
#include "../managers/input/InputManager.hpp" #include "../managers/input/InputManager.hpp"
#include <wayland-server-protocol.h> #include <wayland-server-protocol.h>
#include <hyprutils/os/FileDescriptor.hpp> #include <hyprutils/os/FileDescriptor.hpp>
#ifndef NO_XWAYLAND
#include <xcb/xcb.h> #include <xcb/xcb.h>
#endif
#define XDND_VERSION 5 #define XDND_VERSION 5