mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-23 16:49:48 +01:00
Renderer: rewrite render scheduling (#8683)
This rewrites renderer scheduling. Occlusion is now unified in a new Pass type.
This commit is contained in:
parent
1cc1a46c2e
commit
e536b02248
42 changed files with 1576 additions and 775 deletions
|
@ -571,7 +571,7 @@ CConfigManager::CConfigManager() {
|
||||||
m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0});
|
||||||
|
|
||||||
m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2});
|
m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{1}); // TODO: remove this. I don't think it does us any good to disable intro.
|
||||||
|
|
||||||
m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2});
|
m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2});
|
||||||
m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0});
|
||||||
|
@ -612,6 +612,7 @@ CConfigManager::CConfigManager() {
|
||||||
m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2});
|
m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2});
|
||||||
m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0});
|
||||||
m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1});
|
||||||
|
m_pConfig->addConfigValue("render:xp_mode", Hyprlang::INT{0});
|
||||||
|
|
||||||
m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0});
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "HyprNotificationOverlay.hpp"
|
#include "HyprNotificationOverlay.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
#include "../render/pass/TexPassElement.hpp"
|
||||||
|
|
||||||
static inline auto iconBackendFromLayout(PangoLayout* layout) {
|
static inline auto iconBackendFromLayout(PangoLayout* layout) {
|
||||||
// preference: Nerd > FontAwesome > text
|
// preference: Nerd > FontAwesome > text
|
||||||
|
@ -241,8 +242,12 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||||
|
|
||||||
CBox pMonBox = {0, 0, MONSIZE.x, MONSIZE.y};
|
CTexPassElement::SRenderData data;
|
||||||
g_pHyprOpenGL->renderTexture(m_pTexture, &pMonBox, 1.f);
|
data.tex = m_pTexture;
|
||||||
|
data.box = {0, 0, MONSIZE.x, MONSIZE.y};
|
||||||
|
data.a = 1.F;
|
||||||
|
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprNotificationOverlay::hasAny() {
|
bool CHyprNotificationOverlay::hasAny() {
|
||||||
|
|
|
@ -210,7 +210,7 @@ void CLayerSurface::onUnmap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a snapshot and start fade
|
// make a snapshot and start fade
|
||||||
g_pHyprOpenGL->makeLayerSnapshot(self.lock());
|
g_pHyprRenderer->makeLayerSnapshot(self.lock());
|
||||||
|
|
||||||
startAnimation(false);
|
startAnimation(false);
|
||||||
|
|
||||||
|
|
|
@ -680,7 +680,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
|
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
|
||||||
|
|
||||||
// Allow the renderer to catch the last frame.
|
// Allow the renderer to catch the last frame.
|
||||||
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
|
g_pHyprRenderer->makeWindowSnapshot(PWINDOW);
|
||||||
|
|
||||||
// swallowing
|
// swallowing
|
||||||
if (valid(PWINDOW->m_pSwallowed)) {
|
if (valid(PWINDOW->m_pSwallowed)) {
|
||||||
|
|
|
@ -17,47 +17,6 @@ class CWLSurfaceResource;
|
||||||
|
|
||||||
AQUAMARINE_FORWARD(ISwitch);
|
AQUAMARINE_FORWARD(ISwitch);
|
||||||
|
|
||||||
struct SRenderData {
|
|
||||||
PHLMONITORREF pMonitor;
|
|
||||||
timespec* when;
|
|
||||||
double x, y;
|
|
||||||
|
|
||||||
// for iters
|
|
||||||
void* data = nullptr;
|
|
||||||
SP<CWLSurfaceResource> surface = nullptr;
|
|
||||||
double w, h;
|
|
||||||
|
|
||||||
// for rounding
|
|
||||||
bool dontRound = true;
|
|
||||||
|
|
||||||
// for fade
|
|
||||||
float fadeAlpha = 1.f;
|
|
||||||
|
|
||||||
// for alpha settings
|
|
||||||
float alpha = 1.f;
|
|
||||||
|
|
||||||
// for decorations (border)
|
|
||||||
bool decorate = false;
|
|
||||||
|
|
||||||
// for custom round values
|
|
||||||
int rounding = -1; // -1 means not set
|
|
||||||
|
|
||||||
// for blurring
|
|
||||||
bool blur = false;
|
|
||||||
bool blockBlurOptimization = false;
|
|
||||||
|
|
||||||
// only for windows, not popups
|
|
||||||
bool squishOversized = true;
|
|
||||||
|
|
||||||
// for calculating UV
|
|
||||||
PHLWINDOW pWindow;
|
|
||||||
|
|
||||||
bool popup = false;
|
|
||||||
|
|
||||||
// counts how many surfaces this pass has rendered
|
|
||||||
int surfaceCounter = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SSwipeGesture {
|
struct SSwipeGesture {
|
||||||
PHLWORKSPACE pWorkspaceBegin = nullptr;
|
PHLWORKSPACE pWorkspaceBegin = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "HyprError.hpp"
|
#include "HyprError.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
#include "../render/pass/TexPassElement.hpp"
|
||||||
|
|
||||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||||
using namespace Hyprutils::Utils;
|
using namespace Hyprutils::Utils;
|
||||||
|
@ -206,7 +207,12 @@ void CHyprError::draw() {
|
||||||
|
|
||||||
m_bMonitorChanged = false;
|
m_bMonitorChanged = false;
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTexture(m_pTexture, &monbox, m_fFadeOpacity.value(), 0);
|
CTexPassElement::SRenderData data;
|
||||||
|
data.tex = m_pTexture;
|
||||||
|
data.box = monbox;
|
||||||
|
data.a = m_fFadeOpacity.value();
|
||||||
|
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprError::destroy() {
|
void CHyprError::destroy() {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
#include "../protocols/core/Seat.hpp"
|
#include "../protocols/core/Seat.hpp"
|
||||||
#include "eventLoop/EventLoopManager.hpp"
|
#include "eventLoop/EventLoopManager.hpp"
|
||||||
|
#include "../render/pass/TexPassElement.hpp"
|
||||||
#include "SeatManager.hpp"
|
#include "SeatManager.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
|
@ -551,7 +552,15 @@ void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* no
|
||||||
box.x = std::round(box.x);
|
box.x = std::round(box.x);
|
||||||
box.y = std::round(box.y);
|
box.y = std::round(box.y);
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTextureWithDamage(texture, &box, &damage, 1.F, 0, false, false, currentCursorImage.waitTimeline, currentCursorImage.waitPoint);
|
CTexPassElement::SRenderData data;
|
||||||
|
data.tex = texture;
|
||||||
|
data.box = box.round();
|
||||||
|
data.syncTimeline = currentCursorImage.waitTimeline;
|
||||||
|
data.syncPoint = currentCursorImage.waitPoint;
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
|
|
||||||
|
currentCursorImage.waitTimeline.reset();
|
||||||
|
currentCursorImage.waitPoint = 0;
|
||||||
|
|
||||||
if (currentCursorImage.surface)
|
if (currentCursorImage.surface)
|
||||||
currentCursorImage.surface->resource()->frame(now);
|
currentCursorImage.surface->resource()->frame(now);
|
||||||
|
|
|
@ -522,10 +522,13 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor) {
|
void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor, bool discarded) {
|
||||||
frame(when);
|
frame(when);
|
||||||
auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock());
|
auto FEEDBACK = makeShared<CQueuedPresentationData>(self.lock());
|
||||||
FEEDBACK->attachMonitor(pMonitor);
|
FEEDBACK->attachMonitor(pMonitor);
|
||||||
|
if (discarded)
|
||||||
|
FEEDBACK->discarded();
|
||||||
|
else
|
||||||
FEEDBACK->presented();
|
FEEDBACK->presented();
|
||||||
PROTO::presentation->queueData(FEEDBACK);
|
PROTO::presentation->queueData(FEEDBACK);
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ class CWLSurfaceResource {
|
||||||
|
|
||||||
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
|
||||||
CRegion accumulateCurrentBufferDamage();
|
CRegion accumulateCurrentBufferDamage();
|
||||||
void presentFeedback(timespec* when, PHLMONITOR pMonitor);
|
void presentFeedback(timespec* when, PHLMONITOR pMonitor, bool discarded = false);
|
||||||
void lockPendingState();
|
void lockPendingState();
|
||||||
void unlockPendingState();
|
void unlockPendingState();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../../managers/PointerManager.hpp"
|
#include "../../managers/PointerManager.hpp"
|
||||||
#include "../../managers/eventLoop/EventLoopManager.hpp"
|
#include "../../managers/eventLoop/EventLoopManager.hpp"
|
||||||
#include "../../Compositor.hpp"
|
#include "../../Compositor.hpp"
|
||||||
|
#include "../../render/pass/TexPassElement.hpp"
|
||||||
#include "Seat.hpp"
|
#include "Seat.hpp"
|
||||||
#include "Compositor.hpp"
|
#include "Compositor.hpp"
|
||||||
#include "../../xwayland/XWayland.hpp"
|
#include "../../xwayland/XWayland.hpp"
|
||||||
|
@ -794,7 +795,11 @@ void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, timespec* when) {
|
||||||
const auto POS = g_pInputManager->getMouseCoordsInternal();
|
const auto POS = g_pInputManager->getMouseCoordsInternal();
|
||||||
|
|
||||||
CBox box = CBox{POS, dnd.dndSurface->current.size}.translate(-pMonitor->vecPosition + g_pPointerManager->cursorSizeLogical() / 2.F).scale(pMonitor->scale);
|
CBox box = CBox{POS, dnd.dndSurface->current.size}.translate(-pMonitor->vecPosition + g_pPointerManager->cursorSizeLogical() / 2.F).scale(pMonitor->scale);
|
||||||
g_pHyprOpenGL->renderTexture(dnd.dndSurface->current.texture, &box, 1.F);
|
|
||||||
|
CTexPassElement::SRenderData data;
|
||||||
|
data.tex = dnd.dndSurface->current.texture;
|
||||||
|
data.box = box;
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
|
|
||||||
box = CBox{POS, dnd.dndSurface->current.size}.translate(g_pPointerManager->cursorSizeLogical() / 2.F).expand(5);
|
box = CBox{POS, dnd.dndSurface->current.size}.translate(g_pPointerManager->cursorSizeLogical() / 2.F).expand(5);
|
||||||
g_pHyprRenderer->damageBox(&box);
|
g_pHyprRenderer->damageBox(&box);
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#include "../desktop/LayerSurface.hpp"
|
#include "../desktop/LayerSurface.hpp"
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
#include "../protocols/core/Compositor.hpp"
|
#include "../protocols/core/Compositor.hpp"
|
||||||
|
#include "pass/TexPassElement.hpp"
|
||||||
|
#include "pass/RectPassElement.hpp"
|
||||||
|
#include "pass/PreBlurElement.hpp"
|
||||||
|
#include "pass/ClearPassElement.hpp"
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
|
@ -584,7 +588,7 @@ GLuint CHyprOpenGLImpl::createProgram(const std::string& vert, const std::string
|
||||||
if (fragCompiled == 0)
|
if (fragCompiled == 0)
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT nullptr! Shader source:\n\n{}", frag.c_str());
|
RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT nullptr! Shader source:\n\n{}", frag);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto prog = glCreateProgram();
|
auto prog = glCreateProgram();
|
||||||
|
@ -663,7 +667,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) {
|
||||||
if (*PBLUR == 0)
|
if (*PBLUR == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_RenderData.pCurrentMonData->blurFBShouldRender)
|
if (preBlurQueued())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!pMonitor->solitaryClient.expired())
|
if (!pMonitor->solitaryClient.expired())
|
||||||
|
@ -1242,7 +1246,7 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) {
|
void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) {
|
||||||
if (!m_RenderData.damage.empty())
|
if (!m_RenderData.damage.empty())
|
||||||
renderRectWithDamage(box, col, &m_RenderData.damage, round);
|
renderRectWithDamage(box, col, m_RenderData.damage, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) {
|
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) {
|
||||||
|
@ -1278,7 +1282,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
|
||||||
m_bEndFrame = true; // fix transformed
|
m_bEndFrame = true; // fix transformed
|
||||||
const auto SAVEDRENDERMODIF = m_RenderData.renderModif;
|
const auto SAVEDRENDERMODIF = m_RenderData.renderModif;
|
||||||
m_RenderData.renderModif = {}; // fix shit
|
m_RenderData.renderModif = {}; // fix shit
|
||||||
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, &damage, 0, false, false, false);
|
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, false, false, false);
|
||||||
m_bEndFrame = false;
|
m_bEndFrame = false;
|
||||||
m_RenderData.renderModif = SAVEDRENDERMODIF;
|
m_RenderData.renderModif = SAVEDRENDERMODIF;
|
||||||
|
|
||||||
|
@ -1289,10 +1293,10 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
|
||||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||||
scissor((CBox*)nullptr);
|
scissor((CBox*)nullptr);
|
||||||
|
|
||||||
renderRectWithDamage(box, col, &m_RenderData.damage, round);
|
renderRectWithDamage(box, col, m_RenderData.damage, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRegion* damage, int round) {
|
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round) {
|
||||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
||||||
|
|
||||||
|
@ -1337,7 +1341,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRe
|
||||||
|
|
||||||
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
|
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
|
||||||
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
|
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
|
||||||
damageClip.intersect(*damage);
|
damageClip.intersect(damage);
|
||||||
|
|
||||||
if (!damageClip.empty()) {
|
if (!damageClip.empty()) {
|
||||||
for (auto const& RECT : damageClip.getRects()) {
|
for (auto const& RECT : damageClip.getRects()) {
|
||||||
|
@ -1346,7 +1350,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto const& RECT : damage->getRects()) {
|
for (auto const& RECT : damage.getRects()) {
|
||||||
scissor(&RECT);
|
scissor(&RECT);
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
}
|
}
|
||||||
|
@ -1360,12 +1364,12 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, CRe
|
||||||
void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
|
|
||||||
renderTextureInternalWithDamage(tex, pBox, alpha, &m_RenderData.damage, round, discardActive, false, allowCustomUV, true);
|
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, discardActive, false, allowCustomUV, true);
|
||||||
|
|
||||||
scissor((CBox*)nullptr);
|
scissor((CBox*)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV,
|
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, const CRegion& damage, float alpha, int round, bool discardActive, bool allowCustomUV,
|
||||||
SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
|
SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
|
|
||||||
|
@ -1374,8 +1378,8 @@ void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CReg
|
||||||
scissor((CBox*)nullptr);
|
scissor((CBox*)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
|
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, const CRegion& damage, int round, bool discardActive, bool noAA,
|
||||||
bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
|
bool allowCustomUV, bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!");
|
RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!");
|
||||||
|
|
||||||
|
@ -1383,7 +1387,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
|
||||||
|
|
||||||
alpha = std::clamp(alpha, 0.f, 1.f);
|
alpha = std::clamp(alpha, 0.f, 1.f);
|
||||||
|
|
||||||
if (damage->empty())
|
if (damage.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CBox newBox = *pBox;
|
CBox newBox = *pBox;
|
||||||
|
@ -1433,7 +1437,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.RGBX.valueOrDefault())
|
if (m_RenderData.currentWindow && m_RenderData.currentWindow->m_sWindowData.RGBX.valueOrDefault())
|
||||||
shader = &m_RenderData.pCurrentMonData->m_shRGBX;
|
shader = &m_RenderData.pCurrentMonData->m_shRGBX;
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
@ -1503,9 +1507,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
|
||||||
glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y);
|
glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y);
|
||||||
glUniform1f(shader->radius, round);
|
glUniform1f(shader->radius, round);
|
||||||
|
|
||||||
if (allowDim && m_pCurrentWindow.lock()) {
|
if (allowDim && m_RenderData.currentWindow) {
|
||||||
glUniform1i(shader->applyTint, 1);
|
glUniform1i(shader->applyTint, 1);
|
||||||
const auto DIM = m_pCurrentWindow->m_fDimPercent.value();
|
const auto DIM = m_RenderData.currentWindow->m_fDimPercent.value();
|
||||||
glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM);
|
glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM);
|
||||||
} else {
|
} else {
|
||||||
glUniform1i(shader->applyTint, 0);
|
glUniform1i(shader->applyTint, 0);
|
||||||
|
@ -1532,7 +1536,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
|
||||||
|
|
||||||
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
|
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
|
||||||
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
|
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
|
||||||
damageClip.intersect(*damage);
|
damageClip.intersect(damage);
|
||||||
|
|
||||||
if (!damageClip.empty()) {
|
if (!damageClip.empty()) {
|
||||||
for (auto const& RECT : damageClip.getRects()) {
|
for (auto const& RECT : damageClip.getRects()) {
|
||||||
|
@ -1541,7 +1545,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto const& RECT : damage->getRects()) {
|
for (auto const& RECT : damage.getRects()) {
|
||||||
scissor(&RECT);
|
scissor(&RECT);
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
}
|
}
|
||||||
|
@ -1993,7 +1997,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
|
||||||
clear(CHyprColor(0, 0, 0, 0));
|
clear(CHyprColor(0, 0, 0, 0));
|
||||||
|
|
||||||
m_bEndFrame = true; // fix transformed
|
m_bEndFrame = true; // fix transformed
|
||||||
renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, &fakeDamage, 0, false, true, false);
|
renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, false, true, false);
|
||||||
m_bEndFrame = false;
|
m_bEndFrame = false;
|
||||||
|
|
||||||
m_RenderData.currentFB->bind();
|
m_RenderData.currentFB->bind();
|
||||||
|
@ -2009,15 +2013,14 @@ void CHyprOpenGLImpl::preWindowPass() {
|
||||||
if (!preBlurQueued())
|
if (!preBlurQueued())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// blur the main FB, it will be rendered onto the mirror
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CPreBlurElement>());
|
||||||
preBlurForCurrentMonitor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprOpenGLImpl::preBlurQueued() {
|
bool CHyprOpenGLImpl::preBlurQueued() {
|
||||||
static auto PBLURNEWOPTIMIZE = CConfigValue<Hyprlang::INT>("decoration:blur:new_optimizations");
|
static auto PBLURNEWOPTIMIZE = CConfigValue<Hyprlang::INT>("decoration:blur:new_optimizations");
|
||||||
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
|
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
|
||||||
|
|
||||||
return !(!m_RenderData.pCurrentMonData->blurFBDirty || !*PBLURNEWOPTIMIZE || !*PBLUR || !m_RenderData.pCurrentMonData->blurFBShouldRender);
|
return m_RenderData.pCurrentMonData->blurFBDirty && *PBLURNEWOPTIMIZE && *PBLUR && m_RenderData.pCurrentMonData->blurFBShouldRender;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow) {
|
bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow) {
|
||||||
|
@ -2082,7 +2085,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
|
||||||
inverseOpaque.scale(m_RenderData.pMonitor->scale);
|
inverseOpaque.scale(m_RenderData.pMonitor->scale);
|
||||||
|
|
||||||
// vvv TODO: layered blur fbs?
|
// vvv TODO: layered blur fbs?
|
||||||
const bool USENEWOPTIMIZE = shouldUseNewBlurOptimizations(m_pCurrentLayer, m_pCurrentWindow.lock()) && !blockBlurOptimization;
|
const bool USENEWOPTIMIZE = shouldUseNewBlurOptimizations(m_RenderData.currentLS.lock(), m_RenderData.currentWindow.lock()) && !blockBlurOptimization;
|
||||||
|
|
||||||
CFramebuffer* POUTFB = nullptr;
|
CFramebuffer* POUTFB = nullptr;
|
||||||
if (!USENEWOPTIMIZE) {
|
if (!USENEWOPTIMIZE) {
|
||||||
|
@ -2091,9 +2094,8 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
|
||||||
inverseOpaque.intersect(texDamage);
|
inverseOpaque.intersect(texDamage);
|
||||||
|
|
||||||
POUTFB = blurMainFramebufferWithDamage(a, &inverseOpaque);
|
POUTFB = blurMainFramebufferWithDamage(a, &inverseOpaque);
|
||||||
} else {
|
} else
|
||||||
POUTFB = &m_RenderData.pCurrentMonData->blurFB;
|
POUTFB = &m_RenderData.pCurrentMonData->blurFB;
|
||||||
}
|
|
||||||
|
|
||||||
m_RenderData.currentFB->bind();
|
m_RenderData.currentFB->bind();
|
||||||
|
|
||||||
|
@ -2124,7 +2126,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
|
||||||
setMonitorTransformEnabled(true);
|
setMonitorTransformEnabled(true);
|
||||||
if (!USENEWOPTIMIZE)
|
if (!USENEWOPTIMIZE)
|
||||||
setRenderModifEnabled(false);
|
setRenderModifEnabled(false);
|
||||||
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, &texDamage, 0, false, false, false);
|
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, *PBLURIGNOREOPACITY ? blurA : a * blurA, texDamage, 0, false, false, false);
|
||||||
if (!USENEWOPTIMIZE)
|
if (!USENEWOPTIMIZE)
|
||||||
setRenderModifEnabled(true);
|
setRenderModifEnabled(true);
|
||||||
setMonitorTransformEnabled(false);
|
setMonitorTransformEnabled(false);
|
||||||
|
@ -2135,7 +2137,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
|
||||||
|
|
||||||
// draw window
|
// draw window
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
renderTextureInternalWithDamage(tex, pBox, a, &texDamage, round, false, false, true, true);
|
renderTextureInternalWithDamage(tex, pBox, a, texDamage, round, false, false, true, true);
|
||||||
|
|
||||||
glStencilMask(0xFF);
|
glStencilMask(0xFF);
|
||||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||||
|
@ -2148,7 +2150,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
|
||||||
|
|
||||||
TRACY_GPU_ZONE("RenderBorder");
|
TRACY_GPU_ZONE("RenderBorder");
|
||||||
|
|
||||||
if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.noBorder.valueOrDefault()))
|
if (m_RenderData.damage.empty() || (m_RenderData.currentWindow && m_RenderData.currentWindow->m_sWindowData.noBorder.valueOrDefault()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CBox newBox = *box;
|
CBox newBox = *box;
|
||||||
|
@ -2241,7 +2243,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c
|
||||||
|
|
||||||
TRACY_GPU_ZONE("RenderBorder2");
|
TRACY_GPU_ZONE("RenderBorder2");
|
||||||
|
|
||||||
if (m_RenderData.damage.empty() || (m_pCurrentWindow.lock() && m_pCurrentWindow->m_sWindowData.noBorder.valueOrDefault()))
|
if (m_RenderData.damage.empty() || (m_RenderData.currentWindow && m_RenderData.currentWindow->m_sWindowData.noBorder.valueOrDefault()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CBox newBox = *box;
|
CBox newBox = *box;
|
||||||
|
@ -2332,225 +2334,10 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c
|
||||||
blend(BLEND);
|
blend(BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFramebuffer) {
|
|
||||||
// we trust the window is valid.
|
|
||||||
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
|
||||||
|
|
||||||
if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// we need to "damage" the entire monitor
|
|
||||||
// so that we render the entire window
|
|
||||||
// this is temporary, doesnt mess with the actual damage
|
|
||||||
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
|
|
||||||
|
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
|
||||||
|
|
||||||
pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat);
|
|
||||||
pFramebuffer->addStencil(m_RenderData.pCurrentMonData->stencilTex);
|
|
||||||
|
|
||||||
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer);
|
|
||||||
|
|
||||||
clear(CHyprColor(0, 0, 0, 0)); // JIC
|
|
||||||
|
|
||||||
timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// TODO: how can we make this the size of the window? setting it to window's size makes the entire screen render with the wrong res forever more. odd.
|
|
||||||
glViewport(0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
|
||||||
|
|
||||||
m_RenderData.currentFB = pFramebuffer;
|
|
||||||
|
|
||||||
clear(CHyprColor(0, 0, 0, 0)); // JIC
|
|
||||||
|
|
||||||
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true);
|
|
||||||
|
|
||||||
**PBLUR = BLURVAL;
|
|
||||||
|
|
||||||
g_pHyprRenderer->endRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHyprOpenGLImpl::makeWindowSnapshot(PHLWINDOW pWindow) {
|
|
||||||
// we trust the window is valid.
|
|
||||||
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
|
||||||
|
|
||||||
if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!g_pHyprRenderer->shouldRenderWindow(pWindow))
|
|
||||||
return; // ignore, window is not being rendered
|
|
||||||
|
|
||||||
// we need to "damage" the entire monitor
|
|
||||||
// so that we render the entire window
|
|
||||||
// this is temporary, doesnt mess with the actual damage
|
|
||||||
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
|
|
||||||
|
|
||||||
PHLWINDOWREF ref{pWindow};
|
|
||||||
|
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
|
||||||
|
|
||||||
const auto PFRAMEBUFFER = &m_mWindowFramebuffers[ref];
|
|
||||||
|
|
||||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat);
|
|
||||||
|
|
||||||
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER);
|
|
||||||
|
|
||||||
g_pHyprRenderer->m_bRenderingSnapshot = true;
|
|
||||||
|
|
||||||
clear(CHyprColor(0, 0, 0, 0)); // JIC
|
|
||||||
|
|
||||||
timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
clear(CHyprColor(0, 0, 0, 0)); // JIC
|
|
||||||
|
|
||||||
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
|
|
||||||
|
|
||||||
**PBLUR = BLURVAL;
|
|
||||||
|
|
||||||
g_pHyprRenderer->endRender();
|
|
||||||
|
|
||||||
g_pHyprRenderer->m_bRenderingSnapshot = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHyprOpenGLImpl::makeLayerSnapshot(PHLLS pLayer) {
|
|
||||||
// we trust the window is valid.
|
|
||||||
const auto PMONITOR = pLayer->monitor.lock();
|
|
||||||
|
|
||||||
if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// we need to "damage" the entire monitor
|
|
||||||
// so that we render the entire window
|
|
||||||
// this is temporary, doesnt mess with the actual damage
|
|
||||||
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
|
|
||||||
|
|
||||||
g_pHyprRenderer->makeEGLCurrent();
|
|
||||||
|
|
||||||
const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer];
|
|
||||||
|
|
||||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->output->state->state().drmFormat);
|
|
||||||
|
|
||||||
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER);
|
|
||||||
|
|
||||||
g_pHyprRenderer->m_bRenderingSnapshot = true;
|
|
||||||
|
|
||||||
clear(CHyprColor(0, 0, 0, 0)); // JIC
|
|
||||||
|
|
||||||
timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
|
|
||||||
const auto BLURLSSTATUS = pLayer->forceBlur;
|
|
||||||
pLayer->forceBlur = false;
|
|
||||||
|
|
||||||
// draw the layer
|
|
||||||
g_pHyprRenderer->renderLayer(pLayer, PMONITOR, &now);
|
|
||||||
|
|
||||||
pLayer->forceBlur = BLURLSSTATUS;
|
|
||||||
|
|
||||||
g_pHyprRenderer->endRender();
|
|
||||||
|
|
||||||
g_pHyprRenderer->m_bRenderingSnapshot = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) {
|
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render snapshot rect without begin()!");
|
|
||||||
|
|
||||||
static auto PDIMAROUND = CConfigValue<Hyprlang::FLOAT>("decoration:dim_around");
|
|
||||||
|
|
||||||
PHLWINDOWREF ref{pWindow};
|
|
||||||
|
|
||||||
if (!m_mWindowFramebuffers.contains(ref))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto FBDATA = &m_mWindowFramebuffers.at(ref);
|
|
||||||
|
|
||||||
if (!FBDATA->getTexture())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto PMONITOR = pWindow->m_pMonitor.lock();
|
|
||||||
|
|
||||||
CBox windowBox;
|
|
||||||
// some mafs to figure out the correct box
|
|
||||||
// the originalClosedPos is relative to the monitor's pos
|
|
||||||
Vector2D scaleXY = Vector2D((PMONITOR->scale * pWindow->m_vRealSize.value().x / (pWindow->m_vOriginalClosedSize.x * PMONITOR->scale)),
|
|
||||||
(PMONITOR->scale * pWindow->m_vRealSize.value().y / (pWindow->m_vOriginalClosedSize.y * PMONITOR->scale)));
|
|
||||||
|
|
||||||
windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x;
|
|
||||||
windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y;
|
|
||||||
windowBox.x = ((pWindow->m_vRealPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x);
|
|
||||||
windowBox.y = ((pWindow->m_vRealPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y);
|
|
||||||
|
|
||||||
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
|
||||||
|
|
||||||
if (*PDIMAROUND && pWindow->m_sWindowData.dimAround.valueOrDefault()) {
|
|
||||||
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y};
|
|
||||||
g_pHyprOpenGL->renderRect(&monbox, CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value()));
|
|
||||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_bEndFrame = true;
|
|
||||||
|
|
||||||
renderTextureInternalWithDamage(FBDATA->getTexture(), &windowBox, pWindow->m_fAlpha.value(), &fakeDamage, 0);
|
|
||||||
|
|
||||||
m_bEndFrame = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) {
|
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render snapshot rect without begin()!");
|
|
||||||
|
|
||||||
if (!m_mLayerFramebuffers.contains(pLayer))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto FBDATA = &m_mLayerFramebuffers.at(pLayer);
|
|
||||||
|
|
||||||
if (!FBDATA->getTexture())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto PMONITOR = pLayer->monitor.lock();
|
|
||||||
|
|
||||||
CBox layerBox;
|
|
||||||
// some mafs to figure out the correct box
|
|
||||||
// the originalClosedPos is relative to the monitor's pos
|
|
||||||
Vector2D scaleXY = Vector2D((PMONITOR->scale * pLayer->realSize.value().x / (pLayer->geometry.w * PMONITOR->scale)),
|
|
||||||
(PMONITOR->scale * pLayer->realSize.value().y / (pLayer->geometry.h * PMONITOR->scale)));
|
|
||||||
|
|
||||||
layerBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x;
|
|
||||||
layerBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y;
|
|
||||||
layerBox.x = ((pLayer->realPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - (((pLayer->geometry.x - PMONITOR->vecPosition.x) * PMONITOR->scale) * scaleXY.x);
|
|
||||||
layerBox.y = ((pLayer->realPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - (((pLayer->geometry.y - PMONITOR->vecPosition.y) * PMONITOR->scale) * scaleXY.y);
|
|
||||||
|
|
||||||
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
|
||||||
|
|
||||||
m_bEndFrame = true;
|
|
||||||
|
|
||||||
renderTextureInternalWithDamage(FBDATA->getTexture(), &layerBox, pLayer->alpha.value(), &fakeDamage, 0);
|
|
||||||
|
|
||||||
m_bEndFrame = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) {
|
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
|
||||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
|
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
|
||||||
RASSERT(m_pCurrentWindow.lock(), "Tried to render shadow without a window!");
|
RASSERT(m_RenderData.currentWindow, "Tried to render shadow without a window!");
|
||||||
|
|
||||||
if (m_RenderData.damage.empty())
|
if (m_RenderData.damage.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -2645,7 +2432,7 @@ void CHyprOpenGLImpl::renderMirrored() {
|
||||||
auto monitor = m_RenderData.pMonitor;
|
auto monitor = m_RenderData.pMonitor;
|
||||||
auto mirrored = monitor->pMirrorOf;
|
auto mirrored = monitor->pMirrorOf;
|
||||||
|
|
||||||
double scale = std::min(monitor->vecTransformedSize.x / mirrored->vecTransformedSize.x, monitor->vecTransformedSize.y / mirrored->vecTransformedSize.y);
|
const double scale = std::min(monitor->vecTransformedSize.x / mirrored->vecTransformedSize.x, monitor->vecTransformedSize.y / mirrored->vecTransformedSize.y);
|
||||||
CBox monbox = {0, 0, mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale};
|
CBox monbox = {0, 0, mirrored->vecTransformedSize.x * scale, mirrored->vecTransformedSize.y * scale};
|
||||||
|
|
||||||
// transform box as it will be drawn on a transformed projection
|
// transform box as it will be drawn on a transformed projection
|
||||||
|
@ -2658,20 +2445,18 @@ void CHyprOpenGLImpl::renderMirrored() {
|
||||||
if (!PFB->isAllocated() || !PFB->getTexture())
|
if (!PFB->isAllocated() || !PFB->getTexture())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// replace monitor projection to undo the mirrored monitor's projection
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(0, 0, 0, 0)}));
|
||||||
m_RenderData.monitorProjection = Mat3x3::identity()
|
|
||||||
|
CTexPassElement::SRenderData data;
|
||||||
|
data.tex = PFB->getTexture();
|
||||||
|
data.box = monbox;
|
||||||
|
data.replaceProjection = Mat3x3::identity()
|
||||||
.translate(monitor->vecPixelSize / 2.0)
|
.translate(monitor->vecPixelSize / 2.0)
|
||||||
.transform(wlTransformToHyprutils(monitor->transform))
|
.transform(wlTransformToHyprutils(monitor->transform))
|
||||||
.transform(wlTransformToHyprutils(invertTransform(mirrored->transform)))
|
.transform(wlTransformToHyprutils(invertTransform(mirrored->transform)))
|
||||||
.translate(-monitor->vecTransformedSize / 2.0);
|
.translate(-monitor->vecTransformedSize / 2.0);
|
||||||
|
|
||||||
// clear stuff outside of mirrored area (e.g. when changing to mirrored)
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
clear(CHyprColor(0, 0, 0, 0));
|
|
||||||
|
|
||||||
renderTexture(PFB->getTexture(), &monbox, 1.f, 0, false, false);
|
|
||||||
|
|
||||||
// reset matrix for further drawing
|
|
||||||
m_RenderData.monitorProjection = monitor->projMatrix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const CAIROSURFACE, double offsetY, const Vector2D& size) {
|
void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const CAIROSURFACE, double offsetY, const Vector2D& size) {
|
||||||
|
@ -3005,11 +2790,11 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox texbox = CBox{origin, m_pBackgroundTexture->m_vSize * scale};
|
CBox texbox = CBox{origin, m_pBackgroundTexture->m_vSize * scale};
|
||||||
renderTextureInternalWithDamage(m_pBackgroundTexture, &texbox, 1.0, &fakeDamage);
|
renderTextureInternalWithDamage(m_pBackgroundTexture, &texbox, 1.0, fakeDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox monbox = {{}, pMonitor->vecPixelSize};
|
CBox monbox = {{}, pMonitor->vecPixelSize};
|
||||||
renderTextureInternalWithDamage(tex, &monbox, 1.0, &fakeDamage);
|
renderTextureInternalWithDamage(tex, &monbox, 1.0, fakeDamage);
|
||||||
|
|
||||||
// bind back
|
// bind back
|
||||||
if (m_RenderData.currentFB)
|
if (m_RenderData.currentFB)
|
||||||
|
@ -3021,8 +2806,6 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
|
||||||
void CHyprOpenGLImpl::clearWithTex() {
|
void CHyprOpenGLImpl::clearWithTex() {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
||||||
|
|
||||||
TRACY_GPU_ZONE("RenderClearWithTex");
|
|
||||||
|
|
||||||
auto TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor);
|
auto TEXIT = m_mMonitorBGFBs.find(m_RenderData.pMonitor);
|
||||||
|
|
||||||
if (TEXIT == m_mMonitorBGFBs.end()) {
|
if (TEXIT == m_mMonitorBGFBs.end()) {
|
||||||
|
@ -3031,10 +2814,11 @@ void CHyprOpenGLImpl::clearWithTex() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TEXIT != m_mMonitorBGFBs.end()) {
|
if (TEXIT != m_mMonitorBGFBs.end()) {
|
||||||
CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
CTexPassElement::SRenderData data;
|
||||||
m_bEndFrame = true;
|
data.box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||||
renderTexture(TEXIT->second.getTexture(), &monbox, 1);
|
data.flipEndFrame = true;
|
||||||
m_bEndFrame = false;
|
data.tex = TEXIT->second.getTexture();
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "Framebuffer.hpp"
|
#include "Framebuffer.hpp"
|
||||||
#include "Transformer.hpp"
|
#include "Transformer.hpp"
|
||||||
#include "Renderbuffer.hpp"
|
#include "Renderbuffer.hpp"
|
||||||
|
#include "pass/Pass.hpp"
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
@ -61,17 +62,31 @@ struct SRenderModifData {
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum eMonitorRenderFBs : uint8_t {
|
||||||
|
FB_MONITOR_RENDER_MAIN = 0,
|
||||||
|
FB_MONITOR_RENDER_CURRENT = 1,
|
||||||
|
FB_MONITOR_RENDER_OUT = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eMonitorExtraRenderFBs : uint8_t {
|
||||||
|
FB_MONITOR_RENDER_EXTRA_OFFLOAD = 0,
|
||||||
|
FB_MONITOR_RENDER_EXTRA_MIRROR,
|
||||||
|
FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP,
|
||||||
|
FB_MONITOR_RENDER_EXTRA_OFF_MAIN,
|
||||||
|
FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR,
|
||||||
|
FB_MONITOR_RENDER_EXTRA_BLUR,
|
||||||
|
};
|
||||||
|
|
||||||
struct SMonitorRenderData {
|
struct SMonitorRenderData {
|
||||||
CFramebuffer offloadFB;
|
CFramebuffer offloadFB;
|
||||||
CFramebuffer mirrorFB; // these are used for some effects,
|
CFramebuffer mirrorFB; // these are used for some effects,
|
||||||
CFramebuffer mirrorSwapFB; // etc
|
CFramebuffer mirrorSwapFB; // etc
|
||||||
CFramebuffer offMainFB;
|
CFramebuffer offMainFB;
|
||||||
|
|
||||||
CFramebuffer monitorMirrorFB; // used for mirroring outputs, does not contain artifacts like offloadFB
|
CFramebuffer monitorMirrorFB; // used for mirroring outputs, does not contain artifacts like offloadFB
|
||||||
|
CFramebuffer blurFB;
|
||||||
|
|
||||||
SP<CTexture> stencilTex = makeShared<CTexture>();
|
SP<CTexture> stencilTex = makeShared<CTexture>();
|
||||||
|
|
||||||
CFramebuffer blurFB;
|
|
||||||
bool blurFBDirty = true;
|
bool blurFBDirty = true;
|
||||||
bool blurFBShouldRender = false;
|
bool blurFBShouldRender = false;
|
||||||
|
|
||||||
|
@ -123,6 +138,9 @@ struct SCurrentRenderData {
|
||||||
|
|
||||||
uint32_t discardMode = DISCARD_OPAQUE;
|
uint32_t discardMode = DISCARD_OPAQUE;
|
||||||
float discardOpacity = 0.f;
|
float discardOpacity = 0.f;
|
||||||
|
|
||||||
|
PHLLSREF currentLS;
|
||||||
|
PHLWINDOWREF currentWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CEGLSync {
|
class CEGLSync {
|
||||||
|
@ -155,9 +173,9 @@ class CHyprOpenGLImpl {
|
||||||
|
|
||||||
void renderRect(CBox*, const CHyprColor&, int round = 0);
|
void renderRect(CBox*, const CHyprColor&, int round = 0);
|
||||||
void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false);
|
void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false);
|
||||||
void renderRectWithDamage(CBox*, const CHyprColor&, CRegion* damage, int round = 0);
|
void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0);
|
||||||
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||||
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false,
|
void renderTextureWithDamage(SP<CTexture>, CBox*, const CRegion& damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false,
|
||||||
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
|
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
|
||||||
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||||
void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0);
|
void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0);
|
||||||
|
@ -174,11 +192,6 @@ class CHyprOpenGLImpl {
|
||||||
|
|
||||||
void blend(bool enabled);
|
void blend(bool enabled);
|
||||||
|
|
||||||
void makeWindowSnapshot(PHLWINDOW);
|
|
||||||
void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*);
|
|
||||||
void makeLayerSnapshot(PHLLS);
|
|
||||||
void renderSnapshot(PHLWINDOW);
|
|
||||||
void renderSnapshot(PHLLS);
|
|
||||||
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
|
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
|
||||||
|
|
||||||
void clear(const CHyprColor&);
|
void clear(const CHyprColor&);
|
||||||
|
@ -225,9 +238,6 @@ class CHyprOpenGLImpl {
|
||||||
|
|
||||||
bool m_bReloadScreenShader = true; // at launch it can be set
|
bool m_bReloadScreenShader = true; // at launch it can be set
|
||||||
|
|
||||||
PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window
|
|
||||||
PHLLS m_pCurrentLayer; // hack to get the current rendered layer
|
|
||||||
|
|
||||||
std::map<PHLWINDOWREF, CFramebuffer> m_mWindowFramebuffers;
|
std::map<PHLWINDOWREF, CFramebuffer> m_mWindowFramebuffers;
|
||||||
std::map<PHLLSREF, CFramebuffer> m_mLayerFramebuffers;
|
std::map<PHLLSREF, CFramebuffer> m_mLayerFramebuffers;
|
||||||
std::map<PHLMONITORREF, SMonitorRenderData> m_mMonitorRenderResources;
|
std::map<PHLMONITORREF, SMonitorRenderData> m_mMonitorRenderResources;
|
||||||
|
@ -300,7 +310,7 @@ class CHyprOpenGLImpl {
|
||||||
// returns the out FB, can be either Mirror or MirrorSwap
|
// returns the out FB, can be either Mirror or MirrorSwap
|
||||||
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||||
|
|
||||||
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, const CRegion& damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
||||||
bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0);
|
bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0);
|
||||||
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
|
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
|
||||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
||||||
|
@ -310,6 +320,9 @@ class CHyprOpenGLImpl {
|
||||||
bool passRequiresIntrospection(PHLMONITOR pMonitor);
|
bool passRequiresIntrospection(PHLMONITOR pMonitor);
|
||||||
|
|
||||||
friend class CHyprRenderer;
|
friend class CHyprRenderer;
|
||||||
|
friend class CTexPassElement;
|
||||||
|
friend class CPreBlurElement;
|
||||||
|
friend class CSurfacePassElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -67,9 +67,6 @@ class CHyprRenderer {
|
||||||
bool fixMisalignedFSV1 = false);
|
bool fixMisalignedFSV1 = false);
|
||||||
std::tuple<float, float, float> getRenderTimes(PHLMONITOR pMonitor); // avg max min
|
std::tuple<float, float, float> getRenderTimes(PHLMONITOR pMonitor); // avg max min
|
||||||
void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry);
|
void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry);
|
||||||
void setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace);
|
|
||||||
void setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace); // TODO: merge occlusion methods
|
|
||||||
bool canSkipBackBufferClear(PHLMONITOR pMonitor);
|
|
||||||
void recheckSolitaryForMonitor(PHLMONITOR pMonitor);
|
void recheckSolitaryForMonitor(PHLMONITOR pMonitor);
|
||||||
void setCursorSurface(SP<CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
|
void setCursorSurface(SP<CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
|
||||||
void setCursorFromName(const std::string& name, bool force = false);
|
void setCursorFromName(const std::string& name, bool force = false);
|
||||||
|
@ -80,6 +77,11 @@ class CHyprRenderer {
|
||||||
void unsetEGL();
|
void unsetEGL();
|
||||||
SExplicitSyncSettings getExplicitSyncSettings();
|
SExplicitSyncSettings getExplicitSyncSettings();
|
||||||
void addWindowToRenderUnfocused(PHLWINDOW window);
|
void addWindowToRenderUnfocused(PHLWINDOW window);
|
||||||
|
void makeWindowSnapshot(PHLWINDOW);
|
||||||
|
void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*);
|
||||||
|
void makeLayerSnapshot(PHLLS);
|
||||||
|
void renderSnapshot(PHLWINDOW);
|
||||||
|
void renderSnapshot(PHLLS);
|
||||||
|
|
||||||
// if RENDER_MODE_NORMAL, provided damage will be written to.
|
// if RENDER_MODE_NORMAL, provided damage will be written to.
|
||||||
// otherwise, it will be the one used.
|
// otherwise, it will be the one used.
|
||||||
|
@ -110,6 +112,8 @@ class CHyprRenderer {
|
||||||
std::string name;
|
std::string name;
|
||||||
} m_sLastCursorData;
|
} m_sLastCursorData;
|
||||||
|
|
||||||
|
CRenderPass m_sRenderPass = {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*);
|
void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*);
|
||||||
void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
|
void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
|
||||||
|
@ -129,9 +133,8 @@ class CHyprRenderer {
|
||||||
bool m_bCursorHidden = false;
|
bool m_bCursorHidden = false;
|
||||||
bool m_bCursorHasSurface = false;
|
bool m_bCursorHasSurface = false;
|
||||||
SP<CRenderbuffer> m_pCurrentRenderbuffer = nullptr;
|
SP<CRenderbuffer> m_pCurrentRenderbuffer = nullptr;
|
||||||
SP<Aquamarine::IBuffer> m_pCurrentBuffer;
|
SP<Aquamarine::IBuffer> m_pCurrentBuffer = nullptr;
|
||||||
eRenderMode m_eRenderMode = RENDER_MODE_NORMAL;
|
eRenderMode m_eRenderMode = RENDER_MODE_NORMAL;
|
||||||
|
|
||||||
bool m_bNvidia = false;
|
bool m_bNvidia = false;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "Transformer.hpp"
|
#include "Transformer.hpp"
|
||||||
|
|
||||||
void IWindowTransformer::preWindowRender(SRenderData* pRenderData) {
|
void IWindowTransformer::preWindowRender(CSurfacePassElement::SRenderData* pRenderData) {
|
||||||
;
|
;
|
||||||
}
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Framebuffer.hpp"
|
#include "Framebuffer.hpp"
|
||||||
|
#include "pass/SurfacePassElement.hpp"
|
||||||
struct SRenderData;
|
|
||||||
|
|
||||||
// A window transformer can be attached to a window.
|
// A window transformer can be attached to a window.
|
||||||
// If any is attached, Hyprland will render the window to a separate fb, then call the transform() func with it,
|
// If any is attached, Hyprland will render the window to a separate fb, then call the transform() func with it,
|
||||||
|
@ -18,5 +17,5 @@ class IWindowTransformer {
|
||||||
virtual CFramebuffer* transform(CFramebuffer* in) = 0;
|
virtual CFramebuffer* transform(CFramebuffer* in) = 0;
|
||||||
|
|
||||||
// called by Hyprland before a window main pass is started.
|
// called by Hyprland before a window main pass is started.
|
||||||
virtual void preWindowRender(SRenderData* pRenderData);
|
virtual void preWindowRender(CSurfacePassElement::SRenderData* pRenderData);
|
||||||
};
|
};
|
|
@ -2,6 +2,7 @@
|
||||||
#include "../../Compositor.hpp"
|
#include "../../Compositor.hpp"
|
||||||
#include "../../config/ConfigValue.hpp"
|
#include "../../config/ConfigValue.hpp"
|
||||||
#include "../../managers/eventLoop/EventLoopManager.hpp"
|
#include "../../managers/eventLoop/EventLoopManager.hpp"
|
||||||
|
#include "../pass/BorderPassElement.hpp"
|
||||||
|
|
||||||
CHyprBorderDecoration::CHyprBorderDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_pWindow(pWindow) {
|
CHyprBorderDecoration::CHyprBorderDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_pWindow(pWindow) {
|
||||||
;
|
;
|
||||||
|
@ -69,10 +70,21 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
int borderSize = m_pWindow->getRealBorderSize();
|
int borderSize = m_pWindow->getRealBorderSize();
|
||||||
const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale;
|
const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale;
|
||||||
|
|
||||||
if (ANIMATED)
|
CBorderPassElement::SBorderData data;
|
||||||
g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, grad, m_pWindow->m_fBorderFadeAnimationProgress.value(), ROUNDING, borderSize, a);
|
data.box = windowBox;
|
||||||
else
|
data.grad1 = grad;
|
||||||
g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a);
|
data.round = ROUNDING;
|
||||||
|
data.a = a;
|
||||||
|
data.borderSize = borderSize;
|
||||||
|
|
||||||
|
if (ANIMATED) {
|
||||||
|
data.hasGrad2 = true;
|
||||||
|
data.grad1 = m_pWindow->m_cRealBorderColorPrevious;
|
||||||
|
data.grad2 = grad;
|
||||||
|
data.lerp = m_pWindow->m_fBorderFadeAnimationProgress.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CBorderPassElement>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
eDecorationType CHyprBorderDecoration::getDecorationType() {
|
eDecorationType CHyprBorderDecoration::getDecorationType() {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "../../Compositor.hpp"
|
#include "../../Compositor.hpp"
|
||||||
#include "../../config/ConfigValue.hpp"
|
#include "../../config/ConfigValue.hpp"
|
||||||
|
#include "../pass/ShadowPassElement.hpp"
|
||||||
|
|
||||||
CHyprDropShadowDecoration::CHyprDropShadowDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_pWindow(pWindow) {
|
CHyprDropShadowDecoration::CHyprDropShadowDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_pWindow(pWindow) {
|
||||||
;
|
;
|
||||||
|
@ -87,7 +88,13 @@ void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
|
CShadowPassElement::SShadowData data;
|
||||||
|
data.deco = this;
|
||||||
|
data.a = a;
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CShadowPassElement>(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
||||||
const auto PWINDOW = m_pWindow.lock();
|
const auto PWINDOW = m_pWindow.lock();
|
||||||
|
|
||||||
if (!validMapped(PWINDOW))
|
if (!validMapped(PWINDOW))
|
||||||
|
@ -141,6 +148,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
return; // don't draw invisible shadows
|
return; // don't draw invisible shadows
|
||||||
|
|
||||||
g_pHyprOpenGL->scissor((CBox*)nullptr);
|
g_pHyprOpenGL->scissor((CBox*)nullptr);
|
||||||
|
g_pHyprOpenGL->m_RenderData.currentWindow = m_pWindow;
|
||||||
|
|
||||||
// we'll take the liberty of using this as it should not be used rn
|
// we'll take the liberty of using this as it should not be used rn
|
||||||
CFramebuffer& alphaFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB;
|
CFramebuffer& alphaFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB;
|
||||||
|
@ -197,6 +205,7 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
LASTFB->bind();
|
LASTFB->bind();
|
||||||
|
|
||||||
CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
||||||
|
|
||||||
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||||
g_pHyprOpenGL->setRenderModifEnabled(false);
|
g_pHyprOpenGL->setRenderModifEnabled(false);
|
||||||
g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), &monbox, alphaFB);
|
g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), &monbox, alphaFB);
|
||||||
|
@ -209,6 +218,8 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
|
|
||||||
if (m_seExtents != m_seReportedExtents)
|
if (m_seExtents != m_seReportedExtents)
|
||||||
g_pDecorationPositioner->repositionDeco(this);
|
g_pDecorationPositioner->repositionDeco(this);
|
||||||
|
|
||||||
|
g_pHyprOpenGL->m_RenderData.currentWindow.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
|
eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
|
||||||
|
|
|
@ -25,6 +25,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
|
||||||
|
|
||||||
virtual std::string getDisplayName();
|
virtual std::string getDisplayName();
|
||||||
|
|
||||||
|
void render(PHLMONITOR, float const& a);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SBoxExtents m_seExtents;
|
SBoxExtents m_seExtents;
|
||||||
SBoxExtents m_seReportedExtents;
|
SBoxExtents m_seReportedExtents;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "managers/LayoutManager.hpp"
|
#include "managers/LayoutManager.hpp"
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
#include "../pass/TexPassElement.hpp"
|
||||||
|
#include "../pass/RectPassElement.hpp"
|
||||||
|
|
||||||
// shared things to conserve VRAM
|
// shared things to conserve VRAM
|
||||||
static SP<CTexture> m_tGradientActive = makeShared<CTexture>();
|
static SP<CTexture> m_tGradientActive = makeShared<CTexture>();
|
||||||
|
@ -71,11 +73,11 @@ void CHyprGroupBarDecoration::updateWindow(PHLWINDOW pWindow) {
|
||||||
|
|
||||||
m_dwGroupMembers.clear();
|
m_dwGroupMembers.clear();
|
||||||
PHLWINDOW head = pWindow->getGroupHead();
|
PHLWINDOW head = pWindow->getGroupHead();
|
||||||
m_dwGroupMembers.push_back(head);
|
m_dwGroupMembers.emplace_back(head);
|
||||||
|
|
||||||
PHLWINDOW curr = head->m_sGroupData.pNextWindow.lock();
|
PHLWINDOW curr = head->m_sGroupData.pNextWindow.lock();
|
||||||
while (curr != head) {
|
while (curr != head) {
|
||||||
m_dwGroupMembers.push_back(curr);
|
m_dwGroupMembers.emplace_back(curr);
|
||||||
curr = curr->m_sGroupData.pNextWindow.lock();
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,10 +115,9 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
m_fBarWidth = *PSTACKED ? ASSIGNEDBOX.w : (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw;
|
m_fBarWidth = *PSTACKED ? ASSIGNEDBOX.w : (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw;
|
||||||
m_fBarHeight = *PSTACKED ? ((ASSIGNEDBOX.h - 2 - BAR_PADDING_OUTER_VERT) - BAR_PADDING_OUTER_VERT * (barsToDraw)) / barsToDraw : ASSIGNEDBOX.h - BAR_PADDING_OUTER_VERT;
|
m_fBarHeight = *PSTACKED ? ((ASSIGNEDBOX.h - 2 - BAR_PADDING_OUTER_VERT) - BAR_PADDING_OUTER_VERT * (barsToDraw)) / barsToDraw : ASSIGNEDBOX.h - BAR_PADDING_OUTER_VERT;
|
||||||
|
|
||||||
const auto DESIREDHEIGHT = *PSTACKED ? (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT : BAR_PADDING_OUTER_VERT * 2 + ONEBARHEIGHT;
|
const auto DESIREDHEIGHT = *PSTACKED ? (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT : BAR_PADDING_OUTER_VERT * 2L + ONEBARHEIGHT;
|
||||||
if (DESIREDHEIGHT != ASSIGNEDBOX.h) {
|
if (DESIREDHEIGHT != ASSIGNEDBOX.h)
|
||||||
g_pDecorationPositioner->repositionDeco(this);
|
g_pDecorationPositioner->repositionDeco(this);
|
||||||
}
|
|
||||||
|
|
||||||
float xoff = 0;
|
float xoff = 0;
|
||||||
float yoff = 0;
|
float yoff = 0;
|
||||||
|
@ -148,7 +149,10 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
|
|
||||||
CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0];
|
CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0];
|
||||||
color.a *= a;
|
color.a *= a;
|
||||||
g_pHyprOpenGL->renderRect(&rect, color);
|
CRectPassElement::SRectData rectdata;
|
||||||
|
rectdata.color = color;
|
||||||
|
rectdata.box = rect;
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CRectPassElement>(rectdata));
|
||||||
|
|
||||||
rect = {ASSIGNEDBOX.x + floor(xoff) - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x,
|
rect = {ASSIGNEDBOX.x + floor(xoff) - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x,
|
||||||
ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - ONEBARHEIGHT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth,
|
ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - ONEBARHEIGHT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth,
|
||||||
|
@ -158,18 +162,22 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
if (*PGRADIENTS) {
|
if (*PGRADIENTS) {
|
||||||
const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
||||||
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
||||||
if (GRADIENTTEX->m_iTexID != 0)
|
if (GRADIENTTEX->m_iTexID) {
|
||||||
g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0);
|
CTexPassElement::SRenderData data;
|
||||||
|
data.tex = GRADIENTTEX;
|
||||||
|
data.box = rect;
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*PRENDERTITLES) {
|
if (*PRENDERTITLES) {
|
||||||
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_szTitle);
|
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_szTitle);
|
||||||
|
|
||||||
if (!pTitleTex)
|
if (!pTitleTex)
|
||||||
pTitleTex =
|
pTitleTex = m_sTitleTexs.titleTexs
|
||||||
m_sTitleTexs.titleTexs
|
|
||||||
.emplace_back(std::make_unique<CTitleTex>(m_dwGroupMembers[WINDOWINDEX].lock(),
|
.emplace_back(std::make_unique<CTitleTex>(m_dwGroupMembers[WINDOWINDEX].lock(),
|
||||||
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale))
|
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2L * BAR_TEXT_PAD) * pMonitor->scale},
|
||||||
|
pMonitor->scale))
|
||||||
.get();
|
.get();
|
||||||
rect.y += (rect.height - pTitleTex->textHeight) / 2.0;
|
rect.y += (rect.height - pTitleTex->textHeight) / 2.0;
|
||||||
rect.height = pTitleTex->textHeight;
|
rect.height = pTitleTex->textHeight;
|
||||||
|
@ -177,7 +185,10 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
||||||
rect.x += (m_fBarWidth * pMonitor->scale) / 2.0 - (pTitleTex->textWidth / 2.0);
|
rect.x += (m_fBarWidth * pMonitor->scale) / 2.0 - (pTitleTex->textWidth / 2.0);
|
||||||
rect.round();
|
rect.round();
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f);
|
CTexPassElement::SRenderData data;
|
||||||
|
data.tex = pTitleTex->tex;
|
||||||
|
data.box = rect;
|
||||||
|
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*PSTACKED)
|
if (*PSTACKED)
|
||||||
|
@ -203,10 +214,8 @@ void CHyprGroupBarDecoration::invalidateTextures() {
|
||||||
m_sTitleTexs.titleTexs.clear();
|
m_sTitleTexs.titleTexs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) {
|
CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) : szContent(pWindow->m_szTitle), pWindowOwner(pWindow) {
|
||||||
tex = makeShared<CTexture>();
|
tex = makeShared<CTexture>();
|
||||||
szContent = pWindow->m_szTitle;
|
|
||||||
pWindowOwner = pWindow;
|
|
||||||
const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
|
const auto LAYOUTSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
|
||||||
const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE);
|
const auto LAYOUTCAIRO = cairo_create(LAYOUTSURFACE);
|
||||||
|
|
||||||
|
@ -281,9 +290,7 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float
|
||||||
cairo_surface_destroy(CAIROSURFACE);
|
cairo_surface_destroy(CAIROSURFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTitleTex::~CTitleTex() {
|
CTitleTex::~CTitleTex() = default;
|
||||||
tex->destroyTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
|
void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
|
||||||
|
|
||||||
|
@ -435,7 +442,7 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND
|
||||||
} while (curr != members[0]);
|
} while (curr != members[0]);
|
||||||
|
|
||||||
// removes all windows
|
// removes all windows
|
||||||
for (PHLWINDOW w : members) {
|
for (const PHLWINDOW& w : members) {
|
||||||
w->m_sGroupData.pNextWindow.reset();
|
w->m_sGroupData.pNextWindow.reset();
|
||||||
w->m_sGroupData.head = false;
|
w->m_sGroupData.head = false;
|
||||||
w->m_sGroupData.locked = false;
|
w->m_sGroupData.locked = false;
|
||||||
|
@ -521,7 +528,7 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo
|
||||||
g_pCompositor->focusWindow(pWindow);
|
g_pCompositor->focusWindow(pWindow);
|
||||||
|
|
||||||
if (pWindow->m_bIsFloating)
|
if (pWindow->m_bIsFloating)
|
||||||
g_pCompositor->changeWindowZOrder(pWindow, 1);
|
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
21
src/render/pass/BorderPassElement.cpp
Normal file
21
src/render/pass/BorderPassElement.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "BorderPassElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
|
||||||
|
CBorderPassElement::CBorderPassElement(const CBorderPassElement::SBorderData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBorderPassElement::draw(const CRegion& damage) {
|
||||||
|
if (data.hasGrad2)
|
||||||
|
g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.borderSize, data.a, data.outerRound);
|
||||||
|
else
|
||||||
|
g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.borderSize, data.a, data.outerRound);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBorderPassElement::needsLiveBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBorderPassElement::needsPrecomputeBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
30
src/render/pass/BorderPassElement.hpp
Normal file
30
src/render/pass/BorderPassElement.hpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
#include "../../config/ConfigDataValues.hpp"
|
||||||
|
|
||||||
|
class CGradientValueData;
|
||||||
|
|
||||||
|
class CBorderPassElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct SBorderData {
|
||||||
|
CBox box;
|
||||||
|
CGradientValueData grad1, grad2;
|
||||||
|
bool hasGrad2 = false;
|
||||||
|
float lerp = 0.F, a = 1.F;
|
||||||
|
int round = 0, borderSize = 1, outerRound = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
CBorderPassElement(const SBorderData& data_);
|
||||||
|
virtual ~CBorderPassElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CBorderPassElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SBorderData data;
|
||||||
|
};
|
26
src/render/pass/ClearPassElement.cpp
Normal file
26
src/render/pass/ClearPassElement.cpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#include "ClearPassElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
|
||||||
|
CClearPassElement::CClearPassElement(const CClearPassElement::SClearData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClearPassElement::draw(const CRegion& damage) {
|
||||||
|
g_pHyprOpenGL->clear(data.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClearPassElement::needsLiveBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CClearPassElement::needsPrecomputeBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CBox> CClearPassElement::boundingBox() {
|
||||||
|
return CBox{{}, {INT16_MAX, INT16_MAX}};
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion CClearPassElement::opaqueRegion() {
|
||||||
|
return *boundingBox();
|
||||||
|
}
|
25
src/render/pass/ClearPassElement.hpp
Normal file
25
src/render/pass/ClearPassElement.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
|
||||||
|
class CClearPassElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct SClearData {
|
||||||
|
CHyprColor color;
|
||||||
|
};
|
||||||
|
|
||||||
|
CClearPassElement(const SClearData& data);
|
||||||
|
virtual ~CClearPassElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
virtual std::optional<CBox> boundingBox();
|
||||||
|
virtual CRegion opaqueRegion();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CClearPassElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SClearData data;
|
||||||
|
};
|
48
src/render/pass/FramebufferElement.cpp
Normal file
48
src/render/pass/FramebufferElement.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include "FramebufferElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
|
||||||
|
CFramebufferElement::CFramebufferElement(const CFramebufferElement::SFramebufferElementData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFramebufferElement::draw(const CRegion& damage) {
|
||||||
|
CFramebuffer* fb = nullptr;
|
||||||
|
|
||||||
|
if (data.main) {
|
||||||
|
switch (data.framebufferID) {
|
||||||
|
case FB_MONITOR_RENDER_MAIN: fb = g_pHyprOpenGL->m_RenderData.mainFB; break;
|
||||||
|
case FB_MONITOR_RENDER_CURRENT: fb = g_pHyprOpenGL->m_RenderData.currentFB; break;
|
||||||
|
case FB_MONITOR_RENDER_OUT: fb = g_pHyprOpenGL->m_RenderData.outFB; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fb) {
|
||||||
|
Debug::log(ERR, "BUG THIS: CFramebufferElement::draw: main but null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
switch (data.framebufferID) {
|
||||||
|
case FB_MONITOR_RENDER_EXTRA_OFFLOAD: fb = &g_pHyprOpenGL->m_RenderData.pCurrentMonData->offloadFB; break;
|
||||||
|
case FB_MONITOR_RENDER_EXTRA_MIRROR: fb = &g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB; break;
|
||||||
|
case FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP: fb = &g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorSwapFB; break;
|
||||||
|
case FB_MONITOR_RENDER_EXTRA_OFF_MAIN: fb = &g_pHyprOpenGL->m_RenderData.pCurrentMonData->offMainFB; break;
|
||||||
|
case FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR: fb = &g_pHyprOpenGL->m_RenderData.pCurrentMonData->monitorMirrorFB; break;
|
||||||
|
case FB_MONITOR_RENDER_EXTRA_BLUR: fb = &g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFB; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fb) {
|
||||||
|
Debug::log(ERR, "BUG THIS: CFramebufferElement::draw: not main but null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fb->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFramebufferElement::needsLiveBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFramebufferElement::needsPrecomputeBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
24
src/render/pass/FramebufferElement.hpp
Normal file
24
src/render/pass/FramebufferElement.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
|
||||||
|
class CFramebufferElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct SFramebufferElementData {
|
||||||
|
bool main = true;
|
||||||
|
uint8_t framebufferID = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CFramebufferElement(const SFramebufferElementData& data_);
|
||||||
|
virtual ~CFramebufferElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CFramebufferElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SFramebufferElementData data;
|
||||||
|
};
|
157
src/render/pass/Pass.cpp
Normal file
157
src/render/pass/Pass.cpp
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
#include "Pass.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <ranges>
|
||||||
|
#include "../../config/ConfigValue.hpp"
|
||||||
|
|
||||||
|
bool CRenderPass::empty() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRenderPass::single() const {
|
||||||
|
return m_vPassElements.size() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRenderPass::needsIntrospection() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderPass::add(SP<IPassElement> el) {
|
||||||
|
m_vPassElements.emplace_back(makeShared<SPassElementData>(CRegion{}, el));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderPass::simplify() {
|
||||||
|
// TODO: use precompute blur for instances where there is nothing in between
|
||||||
|
|
||||||
|
// if there is live blur, we need to NOT occlude any area where it will be influenced
|
||||||
|
const auto WILLBLUR = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsLiveBlur(); });
|
||||||
|
|
||||||
|
CRegion newDamage = damage.copy().intersect(CBox{{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize});
|
||||||
|
for (auto& el : m_vPassElements | std::views::reverse) {
|
||||||
|
|
||||||
|
if (newDamage.empty()) {
|
||||||
|
el->discard = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
el->elementDamage = newDamage;
|
||||||
|
auto bb1 = el->element->boundingBox();
|
||||||
|
if (!bb1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto bb = bb1->scale(g_pHyprOpenGL->m_RenderData.pMonitor->scale);
|
||||||
|
|
||||||
|
// drop if empty
|
||||||
|
if (CRegion copy = newDamage.copy(); copy.intersect(bb).empty()) {
|
||||||
|
el->discard = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto opaque = el->element->opaqueRegion();
|
||||||
|
|
||||||
|
if (!opaque.empty()) {
|
||||||
|
opaque.scale(g_pHyprOpenGL->m_RenderData.pMonitor->scale);
|
||||||
|
|
||||||
|
// if this intersects the liveBlur region, allow live blur to operate correctly.
|
||||||
|
// do not occlude a border near it.
|
||||||
|
if (WILLBLUR) {
|
||||||
|
CRegion liveBlurRegion;
|
||||||
|
for (auto& el2 : m_vPassElements) {
|
||||||
|
// if we reach self, no problem, we can break.
|
||||||
|
// if the blur is above us, we don't care, it will work fine.
|
||||||
|
if (el2 == el)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!el2->element->needsLiveBlur())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto BB = el2->element->boundingBox();
|
||||||
|
RASSERT(BB, "No bounding box for an element with live blur is illegal");
|
||||||
|
|
||||||
|
liveBlurRegion.add(*BB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto infringement = opaque.copy().intersect(liveBlurRegion); !infringement.empty()) {
|
||||||
|
// eh, this is not the correct solution, but it will do...
|
||||||
|
// TODO: is this *easily* fixable?
|
||||||
|
opaque.subtract(infringement.expand(oneBlurRadius()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newDamage.subtract(opaque);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderPass::clear() {
|
||||||
|
m_vPassElements.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion CRenderPass::render(const CRegion& damage_) {
|
||||||
|
const auto WILLBLUR = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsLiveBlur(); });
|
||||||
|
|
||||||
|
damage = damage_.copy();
|
||||||
|
|
||||||
|
if (damage.empty()) {
|
||||||
|
g_pHyprOpenGL->m_RenderData.damage = damage;
|
||||||
|
g_pHyprOpenGL->m_RenderData.finalDamage = damage;
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WILLBLUR) {
|
||||||
|
// combine blur regions into one that will be expanded
|
||||||
|
CRegion blurRegion;
|
||||||
|
for (auto& el : m_vPassElements) {
|
||||||
|
if (!el->element->needsLiveBlur())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto BB = el->element->boundingBox();
|
||||||
|
RASSERT(BB, "No bounding box for an element with live blur is illegal");
|
||||||
|
|
||||||
|
blurRegion.add(*BB);
|
||||||
|
}
|
||||||
|
|
||||||
|
blurRegion.intersect(damage).expand(oneBlurRadius());
|
||||||
|
|
||||||
|
g_pHyprOpenGL->m_RenderData.finalDamage = blurRegion.copy().add(damage);
|
||||||
|
|
||||||
|
// FIXME: why does this break on * 1.F ?
|
||||||
|
// used to work when we expand all the damage... I think? Well, before pass.
|
||||||
|
// moving a window over blur shows the edges being wonk.
|
||||||
|
blurRegion.expand(oneBlurRadius() * 1.5F);
|
||||||
|
|
||||||
|
damage = blurRegion.copy().add(damage);
|
||||||
|
} else
|
||||||
|
g_pHyprOpenGL->m_RenderData.finalDamage = damage;
|
||||||
|
|
||||||
|
if (std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->disableSimplification(); })) {
|
||||||
|
for (auto& el : m_vPassElements) {
|
||||||
|
el->elementDamage = damage;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
simplify();
|
||||||
|
|
||||||
|
g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFBShouldRender = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsPrecomputeBlur(); });
|
||||||
|
|
||||||
|
if (m_vPassElements.empty())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
for (auto& el : m_vPassElements) {
|
||||||
|
if (el->discard) {
|
||||||
|
el->element->discard();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pHyprOpenGL->m_RenderData.damage = el->elementDamage;
|
||||||
|
el->element->draw(el->elementDamage);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pHyprOpenGL->m_RenderData.damage = damage;
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CRenderPass::oneBlurRadius() {
|
||||||
|
// TODO: is this exact range correct?
|
||||||
|
static auto PBLURSIZE = CConfigValue<Hyprlang::INT>("decoration:blur:size");
|
||||||
|
static auto PBLURPASSES = CConfigValue<Hyprlang::INT>("decoration:blur:passes");
|
||||||
|
return *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
|
||||||
|
}
|
36
src/render/pass/Pass.hpp
Normal file
36
src/render/pass/Pass.hpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../defines.hpp"
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
|
||||||
|
class CGradientValueData;
|
||||||
|
|
||||||
|
class CRenderPass {
|
||||||
|
public:
|
||||||
|
bool empty() const;
|
||||||
|
bool single() const;
|
||||||
|
bool needsIntrospection() const;
|
||||||
|
|
||||||
|
void add(SP<IPassElement> elem);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
CRegion render(const CRegion& damage_);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CRegion damage;
|
||||||
|
|
||||||
|
struct SPassElementData {
|
||||||
|
CRegion elementDamage;
|
||||||
|
SP<IPassElement> element;
|
||||||
|
bool discard = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<SP<SPassElementData>> m_vPassElements;
|
||||||
|
|
||||||
|
SP<IPassElement> currentPassInfo = nullptr;
|
||||||
|
|
||||||
|
void simplify();
|
||||||
|
float oneBlurRadius();
|
||||||
|
|
||||||
|
friend class CHyprOpenGLImpl;
|
||||||
|
};
|
17
src/render/pass/PassElement.cpp
Normal file
17
src/render/pass/PassElement.cpp
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
|
||||||
|
std::optional<CBox> IPassElement::boundingBox() {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion IPassElement::opaqueRegion() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPassElement::disableSimplification() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPassElement::discard() {
|
||||||
|
;
|
||||||
|
}
|
18
src/render/pass/PassElement.hpp
Normal file
18
src/render/pass/PassElement.hpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../defines.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
class IPassElement {
|
||||||
|
public:
|
||||||
|
virtual ~IPassElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage) = 0;
|
||||||
|
virtual bool needsLiveBlur() = 0;
|
||||||
|
virtual bool needsPrecomputeBlur() = 0;
|
||||||
|
virtual const char* passName() = 0;
|
||||||
|
virtual void discard();
|
||||||
|
virtual std::optional<CBox> boundingBox();
|
||||||
|
virtual CRegion opaqueRegion();
|
||||||
|
virtual bool disableSimplification();
|
||||||
|
};
|
20
src/render/pass/PreBlurElement.cpp
Normal file
20
src/render/pass/PreBlurElement.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include "PreBlurElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
|
||||||
|
CPreBlurElement::CPreBlurElement() = default;
|
||||||
|
|
||||||
|
void CPreBlurElement::draw(const CRegion& damage) {
|
||||||
|
g_pHyprOpenGL->preBlurForCurrentMonitor();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPreBlurElement::needsLiveBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPreBlurElement::needsPrecomputeBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPreBlurElement::disableSimplification() {
|
||||||
|
return true;
|
||||||
|
}
|
17
src/render/pass/PreBlurElement.hpp
Normal file
17
src/render/pass/PreBlurElement.hpp
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
|
||||||
|
class CPreBlurElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
CPreBlurElement();
|
||||||
|
virtual ~CPreBlurElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
virtual bool disableSimplification();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CPreBlurElement";
|
||||||
|
}
|
||||||
|
};
|
29
src/render/pass/RectPassElement.cpp
Normal file
29
src/render/pass/RectPassElement.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include "RectPassElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
|
||||||
|
CRectPassElement::CRectPassElement(const CRectPassElement::SRectData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRectPassElement::draw(const CRegion& damage) {
|
||||||
|
if (data.color.a == 1.F || !data.blur)
|
||||||
|
g_pHyprOpenGL->renderRectWithDamage(&data.box, data.color, damage, data.round);
|
||||||
|
else
|
||||||
|
g_pHyprOpenGL->renderRectWithBlur(&data.box, data.color, data.round, data.blurA, data.xray);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRectPassElement::needsLiveBlur() {
|
||||||
|
return data.color.a < 1.F && !data.xray && data.blur;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRectPassElement::needsPrecomputeBlur() {
|
||||||
|
return data.color.a < 1.F && data.xray && data.blur;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CBox> CRectPassElement::boundingBox() {
|
||||||
|
return data.box.expand(-data.round);
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion CRectPassElement::opaqueRegion() {
|
||||||
|
return data.color.a >= 1.F ? *boundingBox() : CRegion{};
|
||||||
|
}
|
29
src/render/pass/RectPassElement.hpp
Normal file
29
src/render/pass/RectPassElement.hpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
|
||||||
|
class CRectPassElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct SRectData {
|
||||||
|
CBox box;
|
||||||
|
CHyprColor color;
|
||||||
|
int round = 0;
|
||||||
|
bool blur = false, xray = false;
|
||||||
|
float blurA = 1.F;
|
||||||
|
};
|
||||||
|
|
||||||
|
CRectPassElement(const SRectData& data);
|
||||||
|
virtual ~CRectPassElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
virtual std::optional<CBox> boundingBox();
|
||||||
|
virtual CRegion opaqueRegion();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CRectPassElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SRectData data;
|
||||||
|
};
|
19
src/render/pass/ShadowPassElement.cpp
Normal file
19
src/render/pass/ShadowPassElement.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "ShadowPassElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
#include "../decorations/CHyprDropShadowDecoration.hpp"
|
||||||
|
|
||||||
|
CShadowPassElement::CShadowPassElement(const CShadowPassElement::SShadowData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShadowPassElement::draw(const CRegion& damage) {
|
||||||
|
data.deco->render(g_pHyprOpenGL->m_RenderData.pMonitor.lock(), data.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CShadowPassElement::needsLiveBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CShadowPassElement::needsPrecomputeBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
26
src/render/pass/ShadowPassElement.hpp
Normal file
26
src/render/pass/ShadowPassElement.hpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
|
||||||
|
class CHyprDropShadowDecoration;
|
||||||
|
|
||||||
|
class CShadowPassElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct SShadowData {
|
||||||
|
CHyprDropShadowDecoration* deco = nullptr;
|
||||||
|
float a = 1.F;
|
||||||
|
};
|
||||||
|
|
||||||
|
CShadowPassElement(const SShadowData& data_);
|
||||||
|
virtual ~CShadowPassElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CShadowPassElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SShadowData data;
|
||||||
|
};
|
230
src/render/pass/SurfacePassElement.cpp
Normal file
230
src/render/pass/SurfacePassElement.cpp
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
#include "SurfacePassElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
#include "../../desktop/WLSurface.hpp"
|
||||||
|
#include "../../protocols/core/Compositor.hpp"
|
||||||
|
#include "../../protocols/DRMSyncobj.hpp"
|
||||||
|
#include "../../managers/input/InputManager.hpp"
|
||||||
|
#include "../Renderer.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||||
|
using namespace Hyprutils::Utils;
|
||||||
|
|
||||||
|
CSurfacePassElement::CSurfacePassElement(const CSurfacePassElement::SRenderData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSurfacePassElement::draw(const CRegion& damage) {
|
||||||
|
g_pHyprOpenGL->m_RenderData.currentWindow = data.pWindow;
|
||||||
|
g_pHyprOpenGL->m_RenderData.currentLS = data.pLS;
|
||||||
|
g_pHyprOpenGL->m_RenderData.clipBox = data.clipBox;
|
||||||
|
g_pHyprOpenGL->m_RenderData.discardMode = data.discardMode;
|
||||||
|
g_pHyprOpenGL->m_RenderData.discardOpacity = data.discardOpacity;
|
||||||
|
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = data.useNearestNeighbor;
|
||||||
|
g_pHyprOpenGL->m_bEndFrame = data.flipEndFrame;
|
||||||
|
|
||||||
|
CScopeGuard x = {[]() {
|
||||||
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||||
|
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||||
|
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||||
|
g_pHyprOpenGL->m_RenderData.clipBox = {};
|
||||||
|
g_pHyprOpenGL->m_RenderData.discardMode = 0;
|
||||||
|
g_pHyprOpenGL->m_RenderData.discardOpacity = 0;
|
||||||
|
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||||
|
g_pHyprOpenGL->m_bEndFrame = false;
|
||||||
|
g_pHyprOpenGL->m_RenderData.currentWindow.reset();
|
||||||
|
g_pHyprOpenGL->m_RenderData.currentLS.reset();
|
||||||
|
}};
|
||||||
|
|
||||||
|
if (!data.texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto& TEXTURE = data.texture;
|
||||||
|
|
||||||
|
// this is bad, probably has been logged elsewhere. Means the texture failed
|
||||||
|
// uploading to the GPU.
|
||||||
|
if (!TEXTURE->m_iTexID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// explicit sync: wait for the timeline, if any
|
||||||
|
if (data.surface->syncobj && data.surface->syncobj->current.acquireTimeline) {
|
||||||
|
if (!g_pHyprOpenGL->waitForTimelinePoint(data.surface->syncobj->current.acquireTimeline->timeline, data.surface->syncobj->current.acquirePoint)) {
|
||||||
|
Debug::log(ERR, "Renderer: failed to wait for explicit timeline");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto INTERACTIVERESIZEINPROGRESS = data.pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE;
|
||||||
|
TRACY_GPU_ZONE("RenderSurface");
|
||||||
|
|
||||||
|
auto PSURFACE = CWLSurface::fromResource(data.surface);
|
||||||
|
|
||||||
|
const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F);
|
||||||
|
const bool BLUR = data.blur && (!TEXTURE->m_bOpaque || ALPHA < 1.F);
|
||||||
|
|
||||||
|
auto windowBox = getTexBox();
|
||||||
|
|
||||||
|
const auto PROJSIZEUNSCALED = windowBox.size();
|
||||||
|
|
||||||
|
windowBox.scale(data.pMonitor->scale);
|
||||||
|
windowBox.round();
|
||||||
|
|
||||||
|
if (windowBox.width <= 1 || windowBox.height <= 1) {
|
||||||
|
discard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool MISALIGNEDFSV1 = std::floor(data.pMonitor->scale) != data.pMonitor->scale /* Fractional */ && data.surface->current.scale == 1 /* fs protocol */ &&
|
||||||
|
windowBox.size() != data.surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, data.surface->current.bufferSize.x, 3) &&
|
||||||
|
DELTALESSTHAN(windowBox.height, data.surface->current.bufferSize.y, 3) /* off by one-or-two */ &&
|
||||||
|
(!data.pWindow || (!data.pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */;
|
||||||
|
|
||||||
|
g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1);
|
||||||
|
|
||||||
|
// check for fractional scale surfaces misaligning the buffer size
|
||||||
|
// in those cases it's better to just force nearest neighbor
|
||||||
|
// as long as the window is not animated. During those it'd look weird.
|
||||||
|
// UV will fixup it as well
|
||||||
|
if (MISALIGNEDFSV1)
|
||||||
|
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
||||||
|
|
||||||
|
float rounding = data.rounding;
|
||||||
|
|
||||||
|
rounding -= 1; // to fix a border issue
|
||||||
|
|
||||||
|
if (data.dontRound)
|
||||||
|
rounding = 0;
|
||||||
|
|
||||||
|
const bool WINDOWOPAQUE = data.pWindow && data.pWindow->m_pWLSurface->resource() == data.surface ? data.pWindow->opaque() : false;
|
||||||
|
const bool CANDISABLEBLEND = ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE;
|
||||||
|
|
||||||
|
if (CANDISABLEBLEND)
|
||||||
|
g_pHyprOpenGL->blend(false);
|
||||||
|
else
|
||||||
|
g_pHyprOpenGL->blend(true);
|
||||||
|
|
||||||
|
// FIXME: This is wrong and will bug the blur out as shit if the first surface
|
||||||
|
// is a subsurface that does NOT cover the entire frame. In such cases, we probably should fall back
|
||||||
|
// to what we do for misaligned surfaces (blur the entire thing and then render shit without blur)
|
||||||
|
if (data.surfaceCounter == 0 && !data.popup) {
|
||||||
|
if (BLUR)
|
||||||
|
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, data.blockBlurOptimization, data.fadeAlpha);
|
||||||
|
else
|
||||||
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true);
|
||||||
|
} else {
|
||||||
|
if (BLUR && data.popup)
|
||||||
|
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, true, data.fadeAlpha);
|
||||||
|
else
|
||||||
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)
|
||||||
|
data.surface->presentFeedback(data.when, data.pMonitor->self.lock());
|
||||||
|
|
||||||
|
g_pHyprOpenGL->blend(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBox CSurfacePassElement::getTexBox() {
|
||||||
|
const double outputX = -data.pMonitor->vecPosition.x, outputY = -data.pMonitor->vecPosition.y;
|
||||||
|
|
||||||
|
const auto INTERACTIVERESIZEINPROGRESS = data.pWindow && g_pInputManager->currentlyDraggedWindow && g_pInputManager->dragMode == MBIND_RESIZE;
|
||||||
|
auto PSURFACE = CWLSurface::fromResource(data.surface);
|
||||||
|
|
||||||
|
CBox windowBox;
|
||||||
|
if (data.surface && data.mainSurface) {
|
||||||
|
windowBox = {(int)outputX + data.pos.x + data.localPos.x, (int)outputY + data.pos.y + data.localPos.y, data.w, data.h};
|
||||||
|
|
||||||
|
// however, if surface buffer w / h < box, we need to adjust them
|
||||||
|
const auto PWINDOW = PSURFACE ? PSURFACE->getWindow() : nullptr;
|
||||||
|
|
||||||
|
// center the surface if it's smaller than the viewport we assign it
|
||||||
|
if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees PWINDOW */) {
|
||||||
|
const auto CORRECT = PSURFACE->correctSmallVec();
|
||||||
|
const auto SIZE = PSURFACE->getViewporterCorrectedSize();
|
||||||
|
|
||||||
|
if (!INTERACTIVERESIZEINPROGRESS) {
|
||||||
|
windowBox.translate(CORRECT);
|
||||||
|
|
||||||
|
windowBox.width = SIZE.x * (PWINDOW->m_vRealSize.value().x / PWINDOW->m_vReportedSize.x);
|
||||||
|
windowBox.height = SIZE.y * (PWINDOW->m_vRealSize.value().y / PWINDOW->m_vReportedSize.y);
|
||||||
|
} else {
|
||||||
|
windowBox.width = SIZE.x;
|
||||||
|
windowBox.height = SIZE.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // here we clamp to 2, these might be some tiny specks
|
||||||
|
windowBox = {(int)outputX + data.pos.x + data.localPos.x, (int)outputY + data.pos.y + data.localPos.y, std::max((float)data.surface->current.size.x, 2.F),
|
||||||
|
std::max((float)data.surface->current.size.y, 2.F)};
|
||||||
|
if (data.pWindow && data.pWindow->m_vRealSize.isBeingAnimated() && data.surface && !data.mainSurface && data.squishOversized /* subsurface */) {
|
||||||
|
// adjust subsurfaces to the window
|
||||||
|
windowBox.width = (windowBox.width / data.pWindow->m_vReportedSize.x) * data.pWindow->m_vRealSize.value().x;
|
||||||
|
windowBox.height = (windowBox.height / data.pWindow->m_vReportedSize.y) * data.pWindow->m_vRealSize.value().y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.squishOversized) {
|
||||||
|
if (data.localPos.x + windowBox.width > data.w)
|
||||||
|
windowBox.width = data.w - data.localPos.x;
|
||||||
|
if (data.localPos.y + windowBox.height > data.h)
|
||||||
|
windowBox.height = data.h - data.localPos.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return windowBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSurfacePassElement::needsLiveBlur() {
|
||||||
|
auto PSURFACE = CWLSurface::fromResource(data.surface);
|
||||||
|
|
||||||
|
const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F);
|
||||||
|
const bool BLUR = data.blur && (!data.texture || !data.texture->m_bOpaque || ALPHA < 1.F);
|
||||||
|
|
||||||
|
if (!data.pLS && !data.pWindow)
|
||||||
|
return BLUR;
|
||||||
|
|
||||||
|
const bool NEWOPTIM = g_pHyprOpenGL->shouldUseNewBlurOptimizations(data.pLS, data.pWindow);
|
||||||
|
|
||||||
|
return BLUR && !NEWOPTIM;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSurfacePassElement::needsPrecomputeBlur() {
|
||||||
|
auto PSURFACE = CWLSurface::fromResource(data.surface);
|
||||||
|
|
||||||
|
const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F);
|
||||||
|
const bool BLUR = data.blur && (!data.texture || !data.texture->m_bOpaque || ALPHA < 1.F);
|
||||||
|
|
||||||
|
if (!data.pLS && !data.pWindow)
|
||||||
|
return BLUR;
|
||||||
|
|
||||||
|
const bool NEWOPTIM = g_pHyprOpenGL->shouldUseNewBlurOptimizations(data.pLS, data.pWindow);
|
||||||
|
|
||||||
|
return BLUR && NEWOPTIM;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CBox> CSurfacePassElement::boundingBox() {
|
||||||
|
return getTexBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion CSurfacePassElement::opaqueRegion() {
|
||||||
|
auto PSURFACE = CWLSurface::fromResource(data.surface);
|
||||||
|
|
||||||
|
const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F);
|
||||||
|
|
||||||
|
if (ALPHA < 1.F)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (data.surface && data.surface->current.size == Vector2D{data.w, data.h}) {
|
||||||
|
CRegion opaqueSurf = data.surface->current.opaque.copy().intersect(CBox{{}, {data.w, data.h}});
|
||||||
|
const auto texBox = getTexBox();
|
||||||
|
opaqueSurf.scale(texBox.size() / Vector2D{data.w, data.h});
|
||||||
|
return opaqueSurf.translate(data.pos + data.localPos - data.pMonitor->vecPosition).expand(-data.rounding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.texture && data.texture->m_bOpaque ? boundingBox()->expand(-data.rounding) : CRegion{};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSurfacePassElement::discard() {
|
||||||
|
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
|
||||||
|
Debug::log(TRACE, "discard for invisible surface");
|
||||||
|
data.surface->presentFeedback(data.when, data.pMonitor->self.lock(), true);
|
||||||
|
}
|
||||||
|
}
|
82
src/render/pass/SurfacePassElement.hpp
Normal file
82
src/render/pass/SurfacePassElement.hpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
class CWLSurfaceResource;
|
||||||
|
class CTexture;
|
||||||
|
class CSyncTimeline;
|
||||||
|
|
||||||
|
class CSurfacePassElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct SRenderData {
|
||||||
|
PHLMONITORREF pMonitor;
|
||||||
|
timespec* when = nullptr;
|
||||||
|
Vector2D pos, localPos;
|
||||||
|
|
||||||
|
// for iters
|
||||||
|
void* data = nullptr;
|
||||||
|
SP<CWLSurfaceResource> surface = nullptr;
|
||||||
|
SP<CTexture> texture = nullptr;
|
||||||
|
bool mainSurface = true;
|
||||||
|
double w = 0, h = 0;
|
||||||
|
|
||||||
|
// for rounding
|
||||||
|
bool dontRound = true;
|
||||||
|
|
||||||
|
// for fade
|
||||||
|
float fadeAlpha = 1.f;
|
||||||
|
|
||||||
|
// for alpha settings
|
||||||
|
float alpha = 1.f;
|
||||||
|
|
||||||
|
// for decorations (border)
|
||||||
|
bool decorate = false;
|
||||||
|
|
||||||
|
// for custom round values
|
||||||
|
int rounding = -1; // -1 means not set
|
||||||
|
|
||||||
|
// for blurring
|
||||||
|
bool blur = false;
|
||||||
|
bool blockBlurOptimization = false;
|
||||||
|
|
||||||
|
// only for windows, not popups
|
||||||
|
bool squishOversized = true;
|
||||||
|
|
||||||
|
// for calculating UV
|
||||||
|
PHLWINDOW pWindow;
|
||||||
|
PHLLS pLS;
|
||||||
|
|
||||||
|
bool popup = false;
|
||||||
|
|
||||||
|
// counts how many surfaces this pass has rendered
|
||||||
|
int surfaceCounter = 0;
|
||||||
|
|
||||||
|
CBox clipBox = {}; // scaled coordinates
|
||||||
|
|
||||||
|
uint32_t discardMode = 0;
|
||||||
|
float discardOpacity = 0.f;
|
||||||
|
|
||||||
|
bool useNearestNeighbor = false;
|
||||||
|
|
||||||
|
bool flipEndFrame = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSurfacePassElement(const SRenderData& data);
|
||||||
|
virtual ~CSurfacePassElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
virtual std::optional<CBox> boundingBox();
|
||||||
|
virtual CRegion opaqueRegion();
|
||||||
|
virtual void discard();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CSurfacePassElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SRenderData data;
|
||||||
|
|
||||||
|
CBox getTexBox();
|
||||||
|
};
|
44
src/render/pass/TexPassElement.cpp
Normal file
44
src/render/pass/TexPassElement.cpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "TexPassElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||||
|
using namespace Hyprutils::Utils;
|
||||||
|
|
||||||
|
CTexPassElement::CTexPassElement(const CTexPassElement::SRenderData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTexPassElement::draw(const CRegion& damage) {
|
||||||
|
g_pHyprOpenGL->m_bEndFrame = data.flipEndFrame;
|
||||||
|
|
||||||
|
CScopeGuard x = {[]() {
|
||||||
|
//
|
||||||
|
g_pHyprOpenGL->m_bEndFrame = false;
|
||||||
|
}};
|
||||||
|
|
||||||
|
if (data.replaceProjection)
|
||||||
|
g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection;
|
||||||
|
g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.syncTimeline, data.syncPoint);
|
||||||
|
if (data.replaceProjection)
|
||||||
|
g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTexPassElement::needsLiveBlur() {
|
||||||
|
return false; // TODO?
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTexPassElement::needsPrecomputeBlur() {
|
||||||
|
return false; // TODO?
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CBox> CTexPassElement::boundingBox() {
|
||||||
|
return data.box.copy().scale(1.F / g_pHyprOpenGL->m_RenderData.pMonitor->scale).round();
|
||||||
|
}
|
||||||
|
|
||||||
|
CRegion CTexPassElement::opaqueRegion() {
|
||||||
|
return {}; // TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTexPassElement::discard() {
|
||||||
|
;
|
||||||
|
}
|
39
src/render/pass/TexPassElement.hpp
Normal file
39
src/render/pass/TexPassElement.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
class CWLSurfaceResource;
|
||||||
|
class CTexture;
|
||||||
|
class CSyncTimeline;
|
||||||
|
|
||||||
|
class CTexPassElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct SRenderData {
|
||||||
|
SP<CTexture> tex;
|
||||||
|
CBox box;
|
||||||
|
float a = 1.F;
|
||||||
|
CRegion damage;
|
||||||
|
int round = 0;
|
||||||
|
bool flipEndFrame = false;
|
||||||
|
SP<CSyncTimeline> syncTimeline;
|
||||||
|
int64_t syncPoint = 0;
|
||||||
|
std::optional<Mat3x3> replaceProjection;
|
||||||
|
};
|
||||||
|
|
||||||
|
CTexPassElement(const SRenderData& data);
|
||||||
|
virtual ~CTexPassElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
virtual std::optional<CBox> boundingBox();
|
||||||
|
virtual CRegion opaqueRegion();
|
||||||
|
virtual void discard();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CTexPassElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SRenderData data;
|
||||||
|
};
|
25
src/render/pass/TextureMatteElement.cpp
Normal file
25
src/render/pass/TextureMatteElement.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "TextureMatteElement.hpp"
|
||||||
|
#include "../OpenGL.hpp"
|
||||||
|
|
||||||
|
CTextureMatteElement::CTextureMatteElement(const CTextureMatteElement::STextureMatteData& data_) : data(data_) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTextureMatteElement::draw(const CRegion& damage) {
|
||||||
|
if (data.disableTransformAndModify) {
|
||||||
|
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||||
|
g_pHyprOpenGL->setRenderModifEnabled(false);
|
||||||
|
g_pHyprOpenGL->renderTextureMatte(data.tex, &data.box, *data.fb);
|
||||||
|
g_pHyprOpenGL->setRenderModifEnabled(true);
|
||||||
|
g_pHyprOpenGL->setMonitorTransformEnabled(false);
|
||||||
|
} else
|
||||||
|
g_pHyprOpenGL->renderTextureMatte(data.tex, &data.box, *data.fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTextureMatteElement::needsLiveBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTextureMatteElement::needsPrecomputeBlur() {
|
||||||
|
return false;
|
||||||
|
}
|
29
src/render/pass/TextureMatteElement.hpp
Normal file
29
src/render/pass/TextureMatteElement.hpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
#include "PassElement.hpp"
|
||||||
|
#include "../Framebuffer.hpp"
|
||||||
|
|
||||||
|
class CTexture;
|
||||||
|
|
||||||
|
class CTextureMatteElement : public IPassElement {
|
||||||
|
public:
|
||||||
|
struct STextureMatteData {
|
||||||
|
CBox box;
|
||||||
|
SP<CTexture> tex;
|
||||||
|
SP<CFramebuffer> fb;
|
||||||
|
bool disableTransformAndModify = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
CTextureMatteElement(const STextureMatteData& data_);
|
||||||
|
virtual ~CTextureMatteElement() = default;
|
||||||
|
|
||||||
|
virtual void draw(const CRegion& damage);
|
||||||
|
virtual bool needsLiveBlur();
|
||||||
|
virtual bool needsPrecomputeBlur();
|
||||||
|
|
||||||
|
virtual const char* passName() {
|
||||||
|
return "CTextureMatteElement";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
STextureMatteData data;
|
||||||
|
};
|
Loading…
Reference in a new issue