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)
if(LEGACY_RENDERER)
set(GLES_VERSION "GLES2")
else()
set(GLES_VERSION "GLES3")
endif()
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
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(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
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})
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)
endif()
if(LEGACY_RENDERER)
message(STATUS "Using the legacy GLES2 renderer!")
add_compile_definitions(LEGACY_RENDERER)
endif()
if(NO_XWAYLAND)
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
add_compile_definitions(NO_XWAYLAND)

View File

@ -3,14 +3,6 @@ PREFIX = /usr/local
stub:
@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:
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`

12
flake.lock generated
View File

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

View File

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

View File

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

View File

@ -566,7 +566,7 @@ bool CPluginManager::updateHeaders(bool force) {
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());
if (m_bVerbose)

View File

@ -4,6 +4,7 @@
#include <pwd.h>
#include <unistd.h>
#include <sstream>
#include <print>
#include <filesystem>
#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'; }))
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;
}

View File

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

View File

@ -33,7 +33,7 @@ endif
aquamarine = dependency('aquamarine', version: '>=0.8.0')
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')
hyprutils = dependency('hyprutils', version: '>= 0.7.0')
aquamarine_version_list = aquamarine.version().split('.')
@ -77,10 +77,6 @@ if (systemd_option.enabled())
subdir('systemd')
endif
if get_option('legacy_renderer').enabled()
add_project_arguments('-DLEGACY_RENDERER', language: 'cpp')
endif
if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif

View File

@ -1,6 +1,5 @@
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
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('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
option('hyprpm', type: 'feature', value: 'enabled', description: 'Enable hyprpm')
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')

View File

@ -41,7 +41,6 @@
xwayland,
debug ? false,
enableXWayland ? true,
legacyRenderer ? false,
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
wrapRuntimeDeps ? true,
version ? "git",
@ -52,6 +51,7 @@
enableNvidiaPatches ? false,
nvidiaPatches ? false,
hidpiXWayland ? false,
legacyRenderer ? false,
}: let
inherit (builtins) baseNameOf foldl' readFile;
inherit (lib.asserts) assertMsg;
@ -70,6 +70,7 @@ in
assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` 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 (!legacyRenderer) "The option `legacyRenderer` has been removed. Legacy renderer is no longer supported.";
customStdenv.mkDerivation (finalAttrs: {
pname = "hyprland${optionalString debug "-debug"}";
inherit version;
@ -165,7 +166,6 @@ in
mesonFlags = flatten [
(mapAttrsToList mesonEnable {
"xwayland" = enableXWayland;
"legacy_renderer" = legacyRenderer;
"systemd" = withSystemd;
"uwsm" = false;
"hyprpm" = false;

View File

@ -50,9 +50,15 @@ in {
hyprutils = final.hyprutils.override {debug = true;};
debug = true;
};
hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;};
# 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 =
builtins.trace ''
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 PSPECIALFALLTHRU = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
const bool ONLY_PRIORITY = properties & FOCUS_PRIORITY;
// pinned windows on top of floating regardless
if (properties & ALLOW_FLOATING) {
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) {
const auto BB = w->getWindowBoxUnified(properties);
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)
continue;
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
const auto PWINDOWMONITOR = w->m_monitor.lock();
// 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 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();
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 (auto const& w : m_windows) {
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
if (special != w->onSpecialWorkspace())
continue;
@ -973,6 +983,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
}
for (auto const& w : m_windows) {
if (ONLY_PRIORITY && !w->priorityFocus())
continue;
if (special != w->onSpecialWorkspace())
continue;
@ -1083,6 +1096,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
static auto PSPECIALFALLTHROUGH = CConfigValue<Hyprlang::INT>("input:special_fallthrough");
if (!pWindow || !pWindow->priorityFocus()) {
if (g_pSessionLockManager->isSessionLocked()) {
Debug::log(LOG, "Refusing a keyboard focus to a window because of a sessionlock");
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");
return;
}
}
if (pWindow && pWindow->m_isX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_xwaylandSurface->wantsFocus())
return;
@ -1487,7 +1502,6 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) {
Debug::log(LOG, "Cleanup: destroyed a layersurface");
glFlush(); // to free mem NOW.
return;
}
}

View File

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

View File

@ -109,9 +109,6 @@ void NCrashReporter::createAndSaveCrash(int sig) {
finalCrashReport += "\nDate: ";
finalCrashReport += GIT_COMMIT_DATE;
finalCrashReport += "\nFlags:\n";
#ifdef LEGACY_RENDERER
finalCrashReport += "legacyrenderer\n";
#endif
#if ISDEBUG
finalCrashReport += "debug\n";
#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,
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";
#else
result += "flags set:\n";
#ifdef LEGACY_RENDERER
result += "legacyrenderer\n";
#endif
#if ISDEBUG
result += "debug\n";
#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_COMMITS, AQUAMARINE_VERSION, HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
#ifdef LEGACY_RENDERER
result += "\"legacyrenderer\",";
#endif
#if ISDEBUG
result += "\"debug\",";
#endif

View File

@ -263,11 +263,8 @@ void CHyprDebugOverlay::draw() {
glBindTexture(GL_TEXTURE_2D, m_texture->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_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);

View File

@ -238,11 +238,8 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
glBindTexture(GL_TEXTURE_2D, m_texture->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_B, GL_RED);
#endif
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) {
// 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_pInputManager->releaseAllMouseButtons();
g_pCompositor->focusSurface(m_surface->resource());

View File

@ -1149,7 +1149,7 @@ bool CWindow::opaque() {
if (m_wlSurface->small() && !m_wlSurface->m_fillIgnoreSmall)
return false;
if (PWORKSPACE->m_alpha->value() != 1.f)
if (PWORKSPACE && PWORKSPACE->m_alpha->value() != 1.f)
return false;
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();
}
bool CWindow::priorityFocus() {
return !m_isX11 && CAsyncDialogBox::isPriorityDialogBox(getPID());
}

View File

@ -51,6 +51,7 @@ enum eGetWindowProperties : uint8_t {
ALLOW_FLOATING = 1 << 4,
USE_PROP_TILED = 1 << 5,
SKIP_FULLSCREEN_PRIORITY = 1 << 6,
FOCUS_PRIORITY = 1 << 7,
};
enum eSuppressEvents : uint8_t {
@ -408,6 +409,7 @@ class CWindow {
std::optional<std::string> xdgTag();
std::optional<std::string> xdgDescription();
PHLWINDOW parent();
bool priorityFocus();
CBox getWindowMainSurfaceBox() const {
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_allowBinds = true;
// permission flag: whether this keyboard is allowed to be processed
bool m_allowed = true;
// if the keymap is overridden by the implementation,
// don't try to set keyboard rules anymore, to avoid overwriting the requested one.
// 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);
// Allow the renderer to catch the last frame.
if (g_pHyprRenderer->shouldRenderWindow(PWINDOW))
g_pHyprRenderer->makeWindowSnapshot(PWINDOW);
// swallowing

View File

@ -7,7 +7,7 @@
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) {
@ -24,7 +24,18 @@ SP<CAsyncDialogBox> CAsyncDialogBox::create(const std::string& title, const std:
}
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) :
@ -68,7 +79,7 @@ void CAsyncDialogBox::onWrite(int fd, uint32_t mask) {
Debug::log(LOG, "CAsyncDialogBox: dialog {:x} hung up, closed.");
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);
m_selfReference.reset();
@ -112,7 +123,7 @@ SP<CPromise<std::string>> CAsyncDialogBox::open() {
}
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(outPipe[1]);

View File

@ -16,6 +16,7 @@ class CAsyncDialogBox {
public:
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 isPriorityDialogBox(pid_t pid);
CAsyncDialogBox(const CAsyncDialogBox&) = delete;
CAsyncDialogBox(CAsyncDialogBox&&) = delete;
@ -26,6 +27,9 @@ class CAsyncDialogBox {
void kill();
bool isRunning() const;
// focus priority, only permission popups
bool m_priority = false;
void onWrite(int fd, uint32_t mask);
private:

View File

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

View File

@ -146,11 +146,8 @@ void CHyprError::createQueued() {
glBindTexture(GL_TEXTURE_2D, m_texture->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_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);

View File

@ -17,15 +17,9 @@
#include <unistd.h>
#include <wayland-server-core.h>
#ifdef LEGACY_RENDERER
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#define GLES2
#else
#define GLES32
#include <GLES3/gl32.h>
#include <GLES3/gl3ext.h>
#endif
#ifdef NO_XWAYLAND
#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->end();
glFlush();
g_pHyprOpenGL->m_renderData.pMonitor.reset();
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) {
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);
waiter->source = nullptr;
// ???
if (it == m_readableWaiters.end())
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)
waiter->fn();
if (it != m_readableWaiters.end())
m_readableWaiters.erase(it);
if (taken->fn)
taken->fn();
}
void CEventLoopManager::enterLoop() {

View File

@ -36,6 +36,7 @@
#include "../../managers/HookSystemManager.hpp"
#include "../../managers/EventManager.hpp"
#include "../../managers/LayoutManager.hpp"
#include "../../managers/permissions/DynamicPermissionManager.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())
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
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)
forcedFocus = g_pCompositor->getForceFocus();
if (forcedFocus) {
if (forcedFocus && !foundSurface) {
pFoundWindow = forcedFocus;
surfacePos = pFoundWindow->m_realPosition->value();
foundSurface = pFoundWindow->m_wlSurface->resource();
@ -1054,6 +1060,27 @@ void CInputManager::applyConfigToKeyboard(SP<IKeyboard> pKeyboard) {
pKeyboard->m_resolveBindsBySym = RESOLVEBINDSBYSYM;
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 {
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 &&
@ -1368,7 +1395,7 @@ void CInputManager::destroyTabletPad(SP<CTabletPad> pad) {
}
void CInputManager::updateKeyboardsLeds(SP<IKeyboard> pKeyboard) {
if (!pKeyboard)
if (!pKeyboard || pKeyboard->isVirtual())
return;
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) {
if (!pKeyboard->m_enabled)
if (!pKeyboard->m_enabled || !pKeyboard->m_allowed)
return;
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_SCREENCOPY: return "PERMISSION_TYPE_SCREENCOPY";
case PERMISSION_TYPE_PLUGIN: return "PERMISSION_TYPE_PLUGIN";
case PERMISSION_TYPE_KEYBOARD: return "PERMISSION_TYPE_KEYBOARD";
}
return "error";
@ -59,9 +60,10 @@ static const char* permissionToString(eDynamicPermissionType type) {
static const char* permissionToHumanString(eDynamicPermissionType type) {
switch (type) {
case PERMISSION_TYPE_UNKNOWN: return "requesting an unknown permission";
case PERMISSION_TYPE_SCREENCOPY: return "trying to capture your screen";
case PERMISSION_TYPE_PLUGIN: return "trying to load a plugin";
case PERMISSION_TYPE_UNKNOWN: return "An application <b>{}</b> is requesting an unknown permission.";
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 "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";
@ -184,7 +186,7 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionMode(wl_c
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);
return PERMISSION_RULE_ALLOW_MODE_PENDING;
@ -232,6 +234,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS
} else if ((*it)->m_allowMode == PERMISSION_RULE_ALLOW_MODE_PENDING) {
Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission pending by config rule");
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
Debug::log(TRACE, "CDynamicPermissionManager::clientHasPermission: permission ask by config rule");
}
@ -247,6 +253,10 @@ eDynamicPermissionAllowMode CDynamicPermissionManager::clientPermissionModeWithS
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.
askForPermission(nullptr, str, permission, pid);
@ -263,22 +273,20 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s
std::string description = "";
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) {
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) {
if (type == PERMISSION_TYPE_PLUGIN) {
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 {
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
description = std::format("An application is {}:<br/><b>{}</b>", permissionToHumanString(type), binaryPath);
description += "<br/><br/>Do you want to allow this?";
description = std::format(std::runtime_format(permissionToHumanString(type)), binaryPath);
std::vector<std::string> options;
@ -289,6 +297,7 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s
options = {"Deny", "Allow"};
rule->m_dialogBox = CAsyncDialogBox::create("Permission request", description, options);
rule->m_dialogBox->m_priority = true;
if (!rule->m_dialogBox) {
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_SCREENCOPY,
PERMISSION_TYPE_PLUGIN,
PERMISSION_TYPE_KEYBOARD,
};
enum eDynamicPermissionRuleSource : uint8_t {

View File

@ -1,6 +1,7 @@
#include "ForeignToplevelWlr.hpp"
#include <algorithm>
#include "../Compositor.hpp"
#include "managers/input/InputManager.hpp"
#include "protocols/core/Output.hpp"
#include "render/Renderer.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
// window switchers and shit
PWINDOW->activate(true);
g_pInputManager->simulateMouseMovement();
});
m_resource->setSetFullscreen([this](CZwlrForeignToplevelHandleV1* p, wl_resource* output) {

View File

@ -187,19 +187,11 @@ void CScreencopyFrame::share() {
callback(copyShm());
}
void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
void CScreencopyFrame::renderMon() {
auto TEXTURE = makeShared<CTexture>(m_monitor->m_output->state->state().buffer);
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}
.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);
@ -211,6 +203,43 @@ void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
if (m_overlayCursor)
g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage,
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)
g_pHyprOpenGL->clear(Colors::BLACK);
else {
@ -229,7 +258,6 @@ void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
bool CScreencopyFrame::copyShm() {
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 [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) {
CBox monbox = CBox{0, 0, m_monitor->m_transformedSize.x, m_monitor->m_transformedSize.y}.translate({-m_box.x, -m_box.y});
g_pHyprOpenGL->setMonitorTransformEnabled(true);
g_pHyprOpenGL->setRenderModifEnabled(false);
g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1);
g_pHyprOpenGL->setRenderModifEnabled(true);
g_pHyprOpenGL->setMonitorTransformEnabled(false);
if (m_overlayCursor)
g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage,
g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true);
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)
g_pHyprOpenGL->clear(Colors::BLACK);
else {
@ -264,11 +289,7 @@ bool CScreencopyFrame::copyShm() {
g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_screencopyDeniedTexture, texbox, 1);
}
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID());
#else
glBindFramebuffer(GL_FRAMEBUFFER, fb.getFBID());
#endif
const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format);
if (!PFORMAT) {
@ -304,11 +325,7 @@ bool CScreencopyFrame::copyShm() {
g_pHyprOpenGL->m_renderData.pMonitor.reset();
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
LOGM(TRACE, "Copied frame via shm");
@ -428,8 +445,12 @@ void CScreencopyProtocol::onOutputCommit(PHLMONITOR pMonitor) {
// check permissions
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.
}
// otherwise share. If it's denied, it will be black.

View File

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

View File

@ -281,10 +281,7 @@ bool CToplevelExportFrame::copyShm(const Time::steady_tp& now) {
g_pHyprOpenGL->m_renderData.pMonitor = PMONITOR;
outFB.bind();
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID());
#endif
glPixelStorei(GL_PACK_ALIGNMENT, 1);
auto glFormat = PFORMAT->flipRB ? GL_BGRA_EXT : GL_RGBA;
@ -318,10 +315,7 @@ bool CToplevelExportFrame::copyShm(const Time::steady_tp& now) {
}
outFB.unbind();
#ifndef GLES2
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
#endif
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 glType = NFormatUtils::glFormatToType(glFormat);
if (drmFormat != m_drmFormat || m_size != Vector2D{w, h})
release();
m_drmFormat = drmFormat;
if (!m_tex) {
m_tex = makeShared<CTexture>();
m_tex->allocate();
@ -35,14 +40,11 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex->m_texID, 0);
// TODO: Allow this with gles2
#ifndef GLES2
if (m_stencilTex) {
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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_stencilTex->m_texID, 0);
}
#endif
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
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) {
// TODO: Allow this with gles2
#ifndef GLES2
m_stencilTex = tex;
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);
@ -74,15 +74,10 @@ void CFramebuffer::addStencil(SP<CTexture> tex) {
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
}
void CFramebuffer::bind() {
#ifndef GLES2
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb);
#else
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
#endif
if (g_pHyprOpenGL)
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() {
#ifndef GLES2
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
}
void CFramebuffer::release() {

View File

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

View File

@ -162,24 +162,14 @@ void CHyprOpenGLImpl::initEGL(bool gbm) {
auto attrsNoVer = attrs;
#ifndef GLES2
attrs.push_back(EGL_CONTEXT_MAJOR_VERSION);
attrs.push_back(3);
attrs.push_back(EGL_CONTEXT_MINOR_VERSION);
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);
m_eglContext = eglCreateContext(m_eglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, attrs.data());
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");
attrs = attrsNoVer;
@ -362,10 +352,6 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() : m_drmFD(g_pCompositor->m_drmFD) {
TRACY_GPU_CONTEXT;
#ifdef GLES2
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
#endif
initDRMFormats();
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) {
m_renderData.pMonitor = pMonitor;
#ifndef GLES2
const GLenum RESETSTATUS = glGetGraphicsResetStatus();
if (RESETSTATUS != GL_NO_ERROR) {
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);
return;
}
#endif
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) {
m_renderData.pMonitor = pMonitor;
#ifndef GLES2
const GLenum RESETSTATUS = glGetGraphicsResetStatus();
if (RESETSTATUS != GL_NO_ERROR) {
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);
return;
}
#endif
TRACY_GPU_ZONE("RenderBegin");
@ -752,13 +734,15 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
if (!m_shadersInitialized)
initShaders();
const auto DRM_FORMAT = fb ? fb->m_drmFormat : pMonitor->m_output->state->state().drmFormat;
// 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->offloadFB.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, pMonitor->m_output->state->state().drmFormat);
m_renderData.pCurrentMonData->mirrorSwapFB.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, DRM_FORMAT);
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->mirrorFB.addStencil(m_renderData.pCurrentMonData->stencilTex);
@ -858,11 +842,7 @@ void CHyprOpenGLImpl::end() {
// check for gl errors
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 */
#endif
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);
GLuint prog;
#ifdef GLES2
m_cmSupported = false;
#else
if (!*PCM)
m_cmSupported = false;
else {
@ -975,12 +953,12 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shCM.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shCM.tint = glGetUniformLocation(prog, "tint");
shaders->m_shCM.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
shaders->m_shCM.createVao();
} else
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 "
"about this!");
}
#endif
const auto FRAGSHADOW = processShader(m_cmSupported ? "shadow.frag" : "shadow_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.color = glGetUniformLocation(prog, "color");
shaders->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
shaders->m_shQUAD.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBA, isDynamic);
if (!prog)
@ -1023,6 +1002,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shRGBA.tint = glGetUniformLocation(prog, "tint");
shaders->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
shaders->m_shRGBA.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAPASSTHRU, isDynamic);
if (!prog)
@ -1032,6 +1012,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shPASSTHRURGBA.tex = glGetUniformLocation(prog, "tex");
shaders->m_shPASSTHRURGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shPASSTHRURGBA.posAttrib = glGetAttribLocation(prog, "pos");
shaders->m_shPASSTHRURGBA.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBAMATTE, isDynamic);
if (!prog)
@ -1042,6 +1023,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shMATTE.alphaMatte = glGetUniformLocation(prog, "texMatte");
shaders->m_shMATTE.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shMATTE.posAttrib = glGetAttribLocation(prog, "pos");
shaders->m_shMATTE.createVao();
prog = createProgram(shaders->TEXVERTSRC, FRAGGLITCH, isDynamic);
if (!prog)
@ -1054,6 +1036,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shGLITCH.distort = glGetUniformLocation(prog, "distort");
shaders->m_shGLITCH.time = glGetUniformLocation(prog, "time");
shaders->m_shGLITCH.fullSize = glGetUniformLocation(prog, "screenSize");
shaders->m_shGLITCH.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCRGBX, isDynamic);
if (!prog)
@ -1070,6 +1053,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shRGBX.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
shaders->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shRGBX.tint = glGetUniformLocation(prog, "tint");
shaders->m_shRGBX.createVao();
prog = createProgram(shaders->TEXVERTSRC, TEXFRAGSRCEXT, isDynamic);
if (!prog)
@ -1086,6 +1070,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shEXT.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue");
shaders->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint");
shaders->m_shEXT.tint = glGetUniformLocation(prog, "tint");
shaders->m_shEXT.createVao();
prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR1, isDynamic);
if (!prog)
@ -1101,6 +1086,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLUR1.passes = glGetUniformLocation(prog, "passes");
shaders->m_shBLUR1.vibrancy = glGetUniformLocation(prog, "vibrancy");
shaders->m_shBLUR1.vibrancy_darkness = glGetUniformLocation(prog, "vibrancy_darkness");
shaders->m_shBLUR1.createVao();
prog = createProgram(shaders->TEXVERTSRC, FRAGBLUR2, isDynamic);
if (!prog)
@ -1113,6 +1099,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLUR2.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
shaders->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
shaders->m_shBLUR2.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBLURPREPARE, isDynamic);
if (!prog)
@ -1127,6 +1114,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLURPREPARE.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shBLURPREPARE.contrast = glGetUniformLocation(prog, "contrast");
shaders->m_shBLURPREPARE.brightness = glGetUniformLocation(prog, "brightness");
shaders->m_shBLURPREPARE.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBLURFINISH, isDynamic);
if (!prog)
@ -1140,6 +1128,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBLURFINISH.texAttrib = glGetAttribLocation(prog, "texcoord");
shaders->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness");
shaders->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise");
shaders->m_shBLURFINISH.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGSHADOW, isDynamic);
if (!prog)
@ -1155,6 +1144,7 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shSHADOW.range = glGetUniformLocation(prog, "range");
shaders->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
shaders->m_shSHADOW.color = glGetUniformLocation(prog, "color");
shaders->m_shSHADOW.createVao();
prog = createProgram(m_cmSupported ? shaders->TEXVERTSRC300 : shaders->TEXVERTSRC, FRAGBORDER1, isDynamic);
if (!prog)
@ -1179,6 +1169,8 @@ bool CHyprOpenGLImpl::initShaders() {
shaders->m_shBORDER1.angle2 = glGetUniformLocation(prog, "angle2");
shaders->m_shBORDER1.gradientLerp = glGetUniformLocation(prog, "gradientLerp");
shaders->m_shBORDER1.alpha = glGetUniformLocation(prog, "alpha");
shaders->m_shBORDER1.createVao();
} catch (const std::exception& e) {
if (!m_shadersInitialized)
throw e;
@ -1245,6 +1237,7 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) {
}
m_finalScreenShader.texAttrib = glGetAttribLocation(m_finalScreenShader.program, "texcoord");
m_finalScreenShader.posAttrib = glGetAttribLocation(m_finalScreenShader.program, "pos");
m_finalScreenShader.createVao();
}
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);
Mat3x3 glMatrix = m_renderData.projection.copy().multiply(matrix);
glUseProgram(m_shaders->m_shQUAD.program);
#ifndef GLES2
useProgram(m_shaders->m_shQUAD.program);
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
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.roundingPower, roundingPower);
glVertexAttribPointer(m_shaders->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_shaders->m_shQUAD.posAttrib);
glBindVertexArray(m_shaders->m_shQUAD.shaderVao);
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};
@ -1419,7 +1404,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(const CBox& box, const CHyprColor& co
}
}
glDisableVertexAttribArray(m_shaders->m_shQUAD.posAttrib);
glBindVertexArray(0);
scissor(nullptr);
}
@ -1579,19 +1564,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, const CB
if (!skipCM && !usingFinalShader && (texType == TEXTURE_RGBA || texType == TEXTURE_RGBX))
shader = &m_shaders->m_shCM;
glUseProgram(shader->program);
useProgram(shader->program);
if (shader == &m_shaders->m_shCM) {
glUniform1i(shader->texType, texType);
passCMUniforms(*shader, imageDescription);
}
#ifndef GLES2
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);
if ((usingFinalShader && *PDT == 0) || CRASHING) {
@ -1653,22 +1633,20 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, const CB
glUniform1i(shader->applyTint, 0);
}
const float verts[] = {
m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVTopLeft.y, // top right
m_renderData.primarySurfaceUVTopLeft.x, m_renderData.primarySurfaceUVTopLeft.y, // top left
m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVBottomRight.y, // bottom right
m_renderData.primarySurfaceUVTopLeft.x, m_renderData.primarySurfaceUVBottomRight.y, // bottom left
glBindVertexArray(shader->shaderVao);
if (allowCustomUV && m_renderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
const float customUVs[] = {
m_renderData.primarySurfaceUVBottomRight.x, m_renderData.primarySurfaceUVTopLeft.y, m_renderData.primarySurfaceUVTopLeft.x,
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);
if (allowCustomUV && m_renderData.primarySurfaceUVTopLeft != Vector2D(-1, -1))
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
else
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(shader->posAttrib);
glEnableVertexAttribArray(shader->texAttrib);
glBindBuffer(GL_ARRAY_BUFFER, shader->shaderVboUv);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(customUVs), customUVs);
} else {
glBindBuffer(GL_ARRAY_BUFFER, shader->shaderVboUv);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(fullVerts), fullVerts);
}
if (!m_renderData.clipBox.empty() || !m_renderData.clipRegion.empty()) {
CRegion damageClip = m_renderData.clipBox;
@ -1693,9 +1671,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, const CB
}
}
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(tex->m_target, 0);
}
@ -1721,21 +1698,10 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, const CBox& box)
glActiveTexture(GL_TEXTURE0);
glBindTexture(tex->m_target, tex->m_texID);
glUseProgram(shader->program);
#ifndef GLES2
useProgram(shader->program);
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);
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);
glBindVertexArray(shader->shaderVao);
for (auto const& RECT : m_renderData.damage.getRects()) {
scissor(&RECT);
@ -1744,9 +1710,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, const CBox& box)
scissor(nullptr);
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
glBindVertexArray(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;
glUseProgram(shader->program);
#ifndef GLES2
useProgram(shader->program);
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->alphaMatte, 1);
@ -1787,11 +1745,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
auto matteTex = matte.getTexture();
glBindTexture(matteTex->m_target, matteTex->m_texID);
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);
glBindVertexArray(shader->shaderVao);
for (auto const& RECT : m_renderData.damage.getRects()) {
scissor(&RECT);
@ -1800,9 +1754,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
scissor(nullptr);
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
glBindVertexArray(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
CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) {
if (!m_renderData.currentFB->getTexture()) {
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
}
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;
blend(false);
@ -1857,13 +1812,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glActiveTexture(GL_TEXTURE0);
auto currentTex = m_renderData.currentFB->getTexture();
auto currentTex = source.getTexture();
glBindTexture(currentTex->m_target, currentTex->m_texID);
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
const bool skipCM = !m_cmSupported || m_renderData.pMonitor->m_imageDescription == SImageDescription{};
@ -1882,21 +1837,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
1.0f);
}
#ifndef GLES2
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.brightness, *PBLURBRIGHTNESS);
glUniform1i(m_shaders->m_shBLURPREPARE.tex, 0);
glVertexAttribPointer(m_shaders->m_shBLURPREPARE.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
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);
glBindVertexArray(m_shaders->m_shBLURPREPARE.shaderVao);
if (!damage.empty()) {
for (auto const& RECT : damage.getRects()) {
@ -1905,9 +1851,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
}
}
glDisableVertexAttribArray(m_shaders->m_shBLURPREPARE.posAttrib);
glDisableVertexAttribArray(m_shaders->m_shBLURPREPARE.texAttrib);
glBindVertexArray(0);
currentRenderToFB = PMIRRORSWAPFB;
}
@ -1926,15 +1870,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
glTexParameteri(currentTex->m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(pShader->program);
useProgram(pShader->program);
// prep two shaders
#ifndef GLES2
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
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));
@ -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));
glUniform1i(pShader->tex, 0);
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(pShader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(pShader->posAttrib);
glEnableVertexAttribArray(pShader->texAttrib);
glBindVertexArray(pShader->shaderVao);
if (!pDamage->empty()) {
for (auto const& RECT : pDamage->getRects()) {
scissor(&RECT, false /* this region is already transformed */);
@ -1958,8 +1892,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
}
}
glDisableVertexAttribArray(pShader->posAttrib);
glDisableVertexAttribArray(pShader->texAttrib);
glBindVertexArray(0);
if (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);
glUseProgram(m_shaders->m_shBLURFINISH.program);
#ifndef GLES2
useProgram(m_shaders->m_shBLURFINISH.program);
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.brightness, *PBLURBRIGHTNESS);
glUniform1i(m_shaders->m_shBLURFINISH.tex, 0);
glVertexAttribPointer(m_shaders->m_shBLURFINISH.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
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);
glBindVertexArray(m_shaders->m_shBLURFINISH.shaderVao);
if (!damage.empty()) {
for (auto const& RECT : damage.getRects()) {
@ -2030,8 +1953,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
}
}
glDisableVertexAttribArray(m_shaders->m_shBLURFINISH.posAttrib);
glDisableVertexAttribArray(m_shaders->m_shBLURFINISH.texAttrib);
glBindVertexArray(0);
if (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!
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) {
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;
@ -2247,7 +2169,6 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, const CBox& box, f
inverseOpaque.translate(box.pos());
m_renderData.renderModif.applyToRegion(inverseOpaque);
inverseOpaque.intersect(texDamage);
POUTFB = blurMainFramebufferWithDamage(a, &inverseOpaque);
} else
POUTFB = &m_renderData.pCurrentMonData->blurFB;
@ -2348,20 +2269,14 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
const auto BLEND = m_blend;
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{};
glUniform1i(m_shaders->m_shBORDER1.skipCM, skipCM);
if (!skipCM)
passCMUniforms(m_shaders->m_shBORDER1, SImageDescription{});
#ifndef GLES2
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());
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));
@ -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.thick, scaledBorderSize);
glVertexAttribPointer(m_shaders->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
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);
glBindVertexArray(m_shaders->m_shBORDER1.shaderVao);
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};
@ -2406,8 +2317,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
}
}
glDisableVertexAttribArray(m_shaders->m_shBORDER1.posAttrib);
glDisableVertexAttribArray(m_shaders->m_shBORDER1.texAttrib);
glBindVertexArray(0);
blend(BLEND);
}
@ -2446,15 +2356,8 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
const auto BLEND = m_blend;
blend(true);
glUseProgram(m_shaders->m_shBORDER1.program);
#ifndef GLES2
useProgram(m_shaders->m_shBORDER1.program);
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());
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));
@ -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.thick, scaledBorderSize);
glVertexAttribPointer(m_shaders->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
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);
glBindVertexArray(m_shaders->m_shBORDER1.shaderVao);
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};
@ -2503,9 +2402,7 @@ void CHyprOpenGLImpl::renderBorder(const CBox& box, const CGradientValueData& gr
}
}
glDisableVertexAttribArray(m_shaders->m_shBORDER1.posAttrib);
glDisableVertexAttribArray(m_shaders->m_shBORDER1.texAttrib);
glBindVertexArray(0);
blend(BLEND);
}
@ -2534,18 +2431,13 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
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{};
glUniform1i(m_shaders->m_shSHADOW.skipCM, skipCM);
if (!skipCM)
passCMUniforms(m_shaders->m_shSHADOW, SImageDescription{});
#ifndef GLES2
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);
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.shadowPower, SHADOWPOWER);
glVertexAttribPointer(m_shaders->m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
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);
glBindVertexArray(m_shaders->m_shSHADOW.shaderVao);
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};
@ -2584,8 +2472,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
}
}
glDisableVertexAttribArray(m_shaders->m_shSHADOW.posAttrib);
glDisableVertexAttribArray(m_shaders->m_shSHADOW.texAttrib);
glBindVertexArray(0);
}
void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) {
@ -2705,13 +2592,7 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
tex->allocate();
tex->m_size = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)};
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ?
#ifdef GLES2
GL_RGB32F_EXT :
#else
GL_RGB32F :
#endif
GL_RGBA;
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : 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;
@ -2719,12 +2600,12 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
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);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_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);
cairo_destroy(CAIRO);
@ -2845,10 +2724,8 @@ void CHyprOpenGLImpl::initMissingAssetTexture() {
glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA);
cairo_surface_destroy(CAIROSURFACE);
@ -2857,6 +2734,14 @@ void CHyprOpenGLImpl::initMissingAssetTexture() {
m_missingAssetTexture = tex;
}
void CHyprOpenGLImpl::useProgram(GLuint prog) {
if (m_currentProgram == prog)
return;
glUseProgram(prog);
m_currentProgram = prog;
}
void CHyprOpenGLImpl::initAssets() {
initMissingAssetTexture();
@ -2950,10 +2835,8 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
glBindTexture(GL_TEXTURE_2D, tex->m_texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_B, GL_RED);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA);
cairo_surface_destroy(CAIROSURFACE);

View File

@ -119,6 +119,7 @@ struct SCurrentRenderData {
Mat3x3 savedProjection;
Mat3x3 monitorProjection;
// FIXME: raw pointer galore!
SMonitorRenderData* pCurrentMonData = nullptr;
CFramebuffer* currentFB = nullptr; // current rendering to
CFramebuffer* mainFB = nullptr; // main to render to
@ -239,6 +240,11 @@ class CHyprOpenGLImpl {
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
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;
SP<SPreparedShaders> m_shaders;
@ -311,6 +317,7 @@ class CHyprOpenGLImpl {
SShader m_finalScreenShader;
CTimer m_globalTimer;
GLuint m_currentProgram;
SP<CTexture> m_missingAssetTexture;
SP<CTexture> m_backgroundTexture;
@ -319,8 +326,6 @@ class CHyprOpenGLImpl {
SP<CTexture> m_lockTtyTextTexture; // TODO: don't always load lock
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 initDRMFormats();
void initEGL(bool gbm);
@ -333,6 +338,7 @@ class CHyprOpenGLImpl {
// returns the out FB, can be either Mirror or MirrorSwap
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,
bool modifySDR = false);

View File

@ -175,7 +175,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) {
return false;
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)
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
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.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.rounding = standalone || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->m_scale;
renderdata.roundingPower = standalone || renderdata.dontRound ? 2.0f : pWindow->roundingPower();
renderdata.blur = !standalone && *PBLUR && !DONT_BLUR;
renderdata.blur = !standalone && shouldBlur(pWindow);
renderdata.pWindow = pWindow;
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())
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};
wb.scale(pMonitor->m_scale).round();
CRectPassElement::SRectData data;
@ -712,8 +711,6 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, const Time::s
return;
}
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
TRACY_GPU_ZONE("RenderLayer");
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};
renderdata.fadeAlpha = pLayer->m_alpha->value();
renderdata.blur = pLayer->m_forceBlur && *PBLUR;
renderdata.blur = shouldBlur(pLayer);
renderdata.surface = pLayer->m_surface->resource();
renderdata.decorate = false;
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]) {
renderLayer(ls.lock(), pMonitor, time);
}
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
renderLayer(ls.lock(), pMonitor, time);
}
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
renderLayer(ls.lock(), pMonitor, time);
}
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
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]) {
renderLayer(ls.lock(), pMonitor, time);
}
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
renderLayer(ls.lock(), pMonitor, time);
}
@ -940,9 +941,9 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
// special
for (auto const& ws : g_pCompositor->m_workspaces) {
if (ws->m_alpha->value() > 0.f && ws->m_isSpecialWorkspace) {
if (ws->m_hasFullscreenWindow)
if (ws->m_hasFullscreenWindow) {
renderWorkspaceWindowsFullscreen(pMonitor, ws, time);
else
} else
renderWorkspaceWindows(pMonitor, ws, time);
}
}
@ -1036,7 +1037,7 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) {
// also render text for the tty number
if (g_pHyprOpenGL->m_lockTtyTextTexture) {
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;
}
// send all queued opengl commands so rendering starts happening immediately
glFlush();
if (m_renderMode == RENDER_MODE_FULL_FAKE)
return;
@ -2389,7 +2387,7 @@ void CHyprRenderer::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFram
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);
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];
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);
@ -2448,21 +2446,8 @@ void CHyprRenderer::makeWindowSnapshot(PHLWINDOW pWindow) {
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);
**PBLUR = BLURVAL;
endRender();
m_bRenderingSnapshot = false;
@ -2484,7 +2469,7 @@ void CHyprRenderer::makeLayerSnapshot(PHLLS 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);
@ -2492,14 +2477,9 @@ void CHyprRenderer::makeLayerSnapshot(PHLLS pLayer) {
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC
const auto BLURLSSTATUS = pLayer->m_forceBlur;
pLayer->m_forceBlur = false;
// draw the layer
renderLayer(pLayer, PMONITOR, Time::steadyNow());
pLayer->m_forceBlur = BLURLSSTATUS;
endRender();
m_bRenderingSnapshot = false;
@ -2534,14 +2514,25 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) {
CRegion fakeDamage{0, 0, PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y};
if (*PDIMAROUND && pWindow->m_windowData.dimAround.valueOrDefault()) {
CRectPassElement::SRectData data;
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());
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;
@ -2580,12 +2571,35 @@ void CHyprRenderer::renderSnapshot(PHLLS pLayer) {
CRegion fakeDamage{0, 0, PMONITOR->m_transformedSize.x, PMONITOR->m_transformedSize.y};
const bool SHOULD_BLUR = shouldBlur(pLayer);
CTexPassElement::SRenderData data;
data.flipEndFrame = true;
data.tex = FBDATA->getTexture();
data.box = layerBox;
data.a = pLayer->m_alpha->value();
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));
}
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;
};
struct SRenderWorkspaceUntilData {
PHLLS ls;
PHLWINDOW w;
};
class CHyprRenderer {
public:
CHyprRenderer();
@ -117,20 +122,23 @@ class CHyprRenderer {
private:
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 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 renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false, bool lockscreen = false);
void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&);
void renderDragIcon(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 renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
void renderSessionLockMissing(PHLMONITOR pMonitor);
bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor);
bool shouldBlur(PHLLS ls);
bool shouldBlur(PHLWINDOW w);
bool m_cursorHidden = false;
bool m_cursorHasSurface = false;
SP<CRenderbuffer> m_currentRenderbuffer = nullptr;

View File

@ -1,14 +1,48 @@
#include "Shader.hpp"
#include "render/OpenGL.hpp"
SShader::~SShader() {
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() {
if (program == 0)
return;
glDeleteProgram(program);
if (shaderVao)
glDeleteVertexArrays(1, &shaderVao);
if (shaderVboPos)
glDeleteBuffers(1, &shaderVboPos);
if (shaderVboUv)
glDeleteBuffers(1, &shaderVboUv);
glDeleteProgram(program);
program = 0;
}

View File

@ -32,6 +32,10 @@ struct SShader {
GLint discardAlpha = -1;
GLfloat discardAlphaValue = -1;
GLuint shaderVao = 0;
GLuint shaderVboPos = 0;
GLuint shaderVboUv = 0;
GLint topLeft = -1;
GLint bottomRight = -1;
GLint fullSize = -1;
@ -76,5 +80,6 @@ struct SShader {
GLint brightness = -1;
GLint noise = -1;
void createVao();
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(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));
#ifndef GLES2
if (format->flipRB) {
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
}
#endif
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(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();
#ifndef GLES2
if (format->flipRB) {
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
}
#endif
for (auto const& rect : rects) {
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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_B, GL_RED);
#endif
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};
else if (RIGHT)
return wb.pos() + Vector2D{wb.size().x, wb.size().y / 2.0};
UNREACHABLE();
} else {
if (TOP && LEFT)
return wb.pos();
@ -52,9 +51,8 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, PHLWINDOW pW
return wb.pos() + wb.size();
if (BOTTOM && LEFT)
return wb.pos() + Vector2D{0.0, wb.size().y};
UNREACHABLE();
}
UNREACHABLE();
Debug::log(ERR, "getEdgeDefinedPoint: invalid configuration of edges");
return {};
}

View File

@ -273,7 +273,7 @@ CRegion CSurfacePassElement::visibleRegion(bool& cancel) {
texBox.round();
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;
}

View File

@ -11,10 +11,14 @@ CTexPassElement::CTexPassElement(const CTexPassElement::SRenderData& data_) : m_
void CTexPassElement::draw(const CRegion& damage) {
g_pHyprOpenGL->m_endFrame = m_data.flipEndFrame;
CScopeGuard x = {[]() {
CScopeGuard x = {[this]() {
//
g_pHyprOpenGL->m_endFrame = false;
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())
@ -22,9 +26,16 @@ void CTexPassElement::draw(const CRegion& damage) {
if (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);
if (m_data.replaceProjection)
g_pHyprOpenGL->m_renderData.monitorProjection = g_pHyprOpenGL->m_renderData.pMonitor->m_projMatrix;
}
bool CTexPassElement::needsLiveBlur() {

View File

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

View File

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