mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-08 17:58:02 +02:00
renderer: refactor gl renderer (#13488)
This commit is contained in:
parent
b227efc849
commit
02f30ea15b
21 changed files with 1733 additions and 1394 deletions
|
|
@ -32,6 +32,7 @@
|
|||
#include <unordered_set>
|
||||
#include "debug/HyprCtl.hpp"
|
||||
#include "debug/crash/CrashReporter.hpp"
|
||||
#include "render/GLRenderer.hpp"
|
||||
#include "render/ShaderLoader.hpp"
|
||||
#ifdef USES_SYSTEMD
|
||||
#include <helpers/SdDaemon.hpp> // for SdNotify
|
||||
|
|
@ -658,6 +659,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
|||
Log::logger->log(Log::DEBUG, "Creating the CHyprOpenGLImpl!");
|
||||
g_pHyprOpenGL = makeUnique<CHyprOpenGLImpl>();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Creating the HyprRenderer!");
|
||||
g_pHyprRenderer = makeUnique<CHyprGLRenderer>();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Creating the ProtocolManager!");
|
||||
g_pProtocolManager = makeUnique<CProtocolManager>();
|
||||
|
||||
|
|
@ -676,9 +680,6 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
|||
Log::logger->log(Log::DEBUG, "Creating the InputManager!");
|
||||
g_pInputManager = makeUnique<CInputManager>();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Creating the HyprRenderer!");
|
||||
g_pHyprRenderer = makeUnique<CHyprRenderer>();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Creating the XWaylandManager!");
|
||||
g_pXWaylandManager = makeUnique<CHyprXWaylandManager>();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
class CHyprRenderer;
|
||||
class IHyprRenderer;
|
||||
|
||||
class CHyprMonitorDebugOverlay {
|
||||
public:
|
||||
|
|
@ -25,7 +25,7 @@ class CHyprMonitorDebugOverlay {
|
|||
PHLMONITORREF m_monitor;
|
||||
CBox m_lastDrawnBox;
|
||||
|
||||
friend class CHyprRenderer;
|
||||
friend class IHyprRenderer;
|
||||
};
|
||||
|
||||
class CHyprDebugOverlay {
|
||||
|
|
@ -45,7 +45,7 @@ class CHyprDebugOverlay {
|
|||
SP<ITexture> m_texture;
|
||||
|
||||
friend class CHyprMonitorDebugOverlay;
|
||||
friend class CHyprRenderer;
|
||||
friend class IHyprRenderer;
|
||||
};
|
||||
|
||||
inline UP<CHyprDebugOverlay> g_pDebugOverlay;
|
||||
|
|
|
|||
|
|
@ -591,16 +591,21 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
|||
|
||||
RBO->bind();
|
||||
|
||||
g_pHyprOpenGL->beginSimple(state->monitor.lock(), {0, 0, INT_MAX, INT_MAX}, RBO);
|
||||
g_pHyprOpenGL->clear(CHyprColor{0.F, 0.F, 0.F, 0.F}); // ensure the RBO is zero initialized.
|
||||
CRegion damageRegion = {0, 0, INT_MAX, INT_MAX};
|
||||
g_pHyprRenderer->beginFullFakeRender(state->monitor.lock(), damageRegion, RBO->getFB());
|
||||
g_pHyprRenderer->startRenderPass();
|
||||
g_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0.F, 0.F, 0.F, 0.F}}), {});
|
||||
|
||||
CBox xbox = {{}, Vector2D{m_currentCursorImage.size / m_currentCursorImage.scale * state->monitor->m_scale}.round()};
|
||||
Log::logger->log(Log::TRACE, "[pointer] monitor: {}, size: {}, hw buf: {}, scale: {:.2f}, monscale: {:.2f}, xbox: {}", state->monitor->m_name, m_currentCursorImage.size,
|
||||
cursorSize, m_currentCursorImage.scale, state->monitor->m_scale, xbox.size());
|
||||
|
||||
g_pHyprOpenGL->renderTexture(texture, xbox, {.noCM = true});
|
||||
CTexPassElement::SRenderData data;
|
||||
data.tex = texture;
|
||||
data.box = xbox;
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(std::move(data)), {});
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
g_pHyprRenderer->endRender();
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
|
||||
return buf;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <any>
|
||||
|
||||
class CInputManager;
|
||||
class CHyprRenderer;
|
||||
class IHyprRenderer;
|
||||
class CTextInputV1;
|
||||
class CInputMethodV2;
|
||||
|
||||
|
|
@ -54,9 +54,8 @@ class CInputMethodRelay {
|
|||
CHyprSignalListener newPopup;
|
||||
} m_listeners;
|
||||
|
||||
friend class CHyprRenderer;
|
||||
friend class IHyprRenderer;
|
||||
friend class CInputManager;
|
||||
friend class CTextInputV1ProtocolManager;
|
||||
friend class CTextInput;
|
||||
friend class CHyprRenderer;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -116,19 +116,24 @@ void CCursorshareSession::render() {
|
|||
|
||||
// TODO: implement a monitor independent render mode to buffer that does this in CHyprRenderer::begin() or something like that
|
||||
g_pHyprRenderer->m_renderData.transformDamage = false;
|
||||
g_pHyprOpenGL->setViewport(0, 0, m_bufferSize.x, m_bufferSize.y);
|
||||
g_pHyprRenderer->setViewport(0, 0, m_bufferSize.x, m_bufferSize.y);
|
||||
|
||||
bool overlaps = g_pPointerManager->getCursorBoxGlobal().overlaps(m_pendingFrame.sourceBoxCallback());
|
||||
g_pHyprRenderer->startRenderPass();
|
||||
if (PERM != PERMISSION_RULE_ALLOW_MODE_ALLOW || !overlaps) {
|
||||
// render black when not allowed
|
||||
g_pHyprOpenGL->clear(Colors::BLACK);
|
||||
g_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{Colors::BLACK}), {});
|
||||
} else if (!cursorImage.pBuffer || !cursorImage.surface || !cursorImage.bufferTex) {
|
||||
// render clear when cursor is probably hidden
|
||||
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0));
|
||||
g_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), {});
|
||||
} else {
|
||||
// render cursor
|
||||
CBox texbox = {{}, cursorImage.bufferTex->m_size};
|
||||
g_pHyprOpenGL->renderTexture(cursorImage.bufferTex, texbox, {});
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = cursorImage.bufferTex,
|
||||
.box = texbox,
|
||||
}),
|
||||
{});
|
||||
}
|
||||
|
||||
g_pHyprRenderer->m_renderData.blockScreenShader = true;
|
||||
|
|
@ -141,8 +146,6 @@ bool CCursorshareSession::copy() {
|
|||
// FIXME: this doesn't really make sense but just to be safe
|
||||
m_pendingFrame.callback(RESULT_TIMESTAMP);
|
||||
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
|
||||
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
|
||||
if (auto attrs = m_pendingFrame.buffer->dmabuf(); attrs.success) {
|
||||
if (attrs.format != m_format) {
|
||||
|
|
@ -150,7 +153,7 @@ bool CCursorshareSession::copy() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(m_pendingFrame.monitor, fakeDamage, RENDER_MODE_TO_BUFFER, m_pendingFrame.buffer, nullptr, true)) {
|
||||
if (!g_pHyprRenderer->beginRenderToBuffer(m_pendingFrame.monitor, fakeDamage, m_pendingFrame.buffer, true)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering to dmabuf");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -162,8 +165,7 @@ bool CCursorshareSession::copy() {
|
|||
callback(RESULT_COPIED);
|
||||
});
|
||||
} else if (auto attrs = m_pendingFrame.buffer->shm(); attrs.success) {
|
||||
auto [bufData, fmt, bufLen] = m_pendingFrame.buffer->beginDataPtr(0);
|
||||
const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(m_format);
|
||||
const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(m_format);
|
||||
|
||||
if (attrs.format != m_format || !PFORMAT) {
|
||||
LOGM(Log::ERR, "Can't copy: invalid format");
|
||||
|
|
@ -173,7 +175,7 @@ bool CCursorshareSession::copy() {
|
|||
auto outFB = g_pHyprRenderer->createFB();
|
||||
outFB->alloc(m_bufferSize.x, m_bufferSize.y, m_format);
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(m_pendingFrame.monitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, outFB, true)) {
|
||||
if (!g_pHyprRenderer->beginFullFakeRender(m_pendingFrame.monitor, fakeDamage, outFB)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering to shm");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -182,12 +184,6 @@ bool CCursorshareSession::copy() {
|
|||
|
||||
g_pHyprRenderer->endRender();
|
||||
|
||||
g_pHyprRenderer->m_renderData.pMonitor = m_pendingFrame.monitor;
|
||||
outFB->bind();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, GLFB(outFB)->getFBID());
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
int glFormat = PFORMAT->glFormat;
|
||||
|
||||
if (glFormat == GL_RGBA)
|
||||
|
|
@ -208,15 +204,10 @@ bool CCursorshareSession::copy() {
|
|||
}
|
||||
}
|
||||
|
||||
glReadPixels(0, 0, m_bufferSize.x, m_bufferSize.y, glFormat, PFORMAT->glType, bufData);
|
||||
outFB->readPixels(m_pendingFrame.buffer, 0, 0, m_bufferSize.x, m_bufferSize.y);
|
||||
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
|
||||
m_pendingFrame.buffer->endDataPtr();
|
||||
GLFB(outFB)->unbind();
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
m_pendingFrame.callback(RESULT_COPIED);
|
||||
} else {
|
||||
LOGM(Log::ERR, "Can't copy: invalid buffer type");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "../../helpers/Monitor.hpp"
|
||||
#include "../../desktop/view/Window.hpp"
|
||||
#include "../../desktop/state/FocusState.hpp"
|
||||
#include "render/pass/RectPassElement.hpp"
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
|
||||
using namespace Screenshare;
|
||||
|
|
@ -170,15 +171,19 @@ void CScreenshareFrame::renderMonitor() {
|
|||
CBox monbox = CBox{{}, PMONITOR->m_pixelSize}
|
||||
.transform(Math::wlTransformToHyprutils(Math::invertTransform(PMONITOR->m_transform)), PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y)
|
||||
.translate(-m_session->m_captureBox.pos()); // vvvv kinda ass-backwards but that's how I designed the renderer... sigh.
|
||||
g_pHyprRenderer->pushMonitorTransformEnabled(true);
|
||||
g_pHyprOpenGL->setRenderModifEnabled(false);
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, monbox,
|
||||
{
|
||||
.cmBackToSRGB = !IS_CM_AWARE,
|
||||
.cmBackToSRGBSource = !IS_CM_AWARE ? PMONITOR : nullptr,
|
||||
});
|
||||
g_pHyprOpenGL->setRenderModifEnabled(true);
|
||||
g_pHyprRenderer->popMonitorTransformEnabled();
|
||||
|
||||
const auto OLD = g_pHyprRenderer->m_renderData.renderModif.enabled;
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = false;
|
||||
g_pHyprRenderer->startRenderPass();
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = monbox,
|
||||
.flipEndFrame = true,
|
||||
.cmBackToSRGB = !IS_CM_AWARE,
|
||||
.cmBackToSRGBSource = !IS_CM_AWARE ? PMONITOR : nullptr,
|
||||
}),
|
||||
monbox);
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = OLD;
|
||||
|
||||
// render black boxes for noscreenshare
|
||||
auto hidePopups = [&](Vector2D popupBaseOffset) {
|
||||
|
|
@ -194,7 +199,11 @@ void CScreenshareFrame::renderMonitor() {
|
|||
CBox{popupBaseOffset + popRel + localOff, size}.translate(PMONITOR->m_position).scale(PMONITOR->m_scale).translate(-m_session->m_captureBox.pos());
|
||||
|
||||
if LIKELY (surfBox.w > 0 && surfBox.h > 0)
|
||||
g_pHyprOpenGL->renderRect(surfBox, Colors::BLACK, {});
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = surfBox,
|
||||
.color = Colors::BLACK,
|
||||
}),
|
||||
surfBox);
|
||||
},
|
||||
nullptr);
|
||||
};
|
||||
|
|
@ -215,7 +224,11 @@ void CScreenshareFrame::renderMonitor() {
|
|||
.scale(PMONITOR->m_scale)
|
||||
.translate(-m_session->m_captureBox.pos());
|
||||
|
||||
g_pHyprOpenGL->renderRect(noScreenShareBox, Colors::BLACK, {});
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = noScreenShareBox,
|
||||
.color = Colors::BLACK,
|
||||
}),
|
||||
noScreenShareBox);
|
||||
|
||||
const auto geom = l->m_geometry;
|
||||
const Vector2D popupBaseOffset = REALPOS - Vector2D{geom.pos().x, geom.pos().y};
|
||||
|
|
@ -250,7 +263,13 @@ void CScreenshareFrame::renderMonitor() {
|
|||
const auto rounding = dontRound ? 0 : w->rounding() * PMONITOR->m_scale;
|
||||
const auto roundingPower = dontRound ? 2.0f : w->roundingPower();
|
||||
|
||||
g_pHyprOpenGL->renderRect(noScreenShareBox, Colors::BLACK, {.round = rounding, .roundingPower = roundingPower});
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = noScreenShareBox,
|
||||
.color = Colors::BLACK,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
}),
|
||||
noScreenShareBox);
|
||||
|
||||
if (w->m_isX11 || !w->m_popupHead)
|
||||
continue;
|
||||
|
|
@ -281,7 +300,7 @@ void CScreenshareFrame::renderWindow() {
|
|||
g_pHyprRenderer->m_renderData.fbSize = m_bufferSize;
|
||||
g_pHyprRenderer->setProjectionType(RPT_FB);
|
||||
g_pHyprRenderer->m_renderData.transformDamage = false;
|
||||
g_pHyprOpenGL->setViewport(0, 0, m_bufferSize.x, m_bufferSize.y);
|
||||
g_pHyprRenderer->setViewport(0, 0, m_bufferSize.x, m_bufferSize.y);
|
||||
|
||||
g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(PWINDOW); // block the feedback to avoid spamming the surface if it's visible
|
||||
g_pHyprRenderer->renderWindow(PWINDOW, PMONITOR, NOW, false, RENDER_PASS_ALL, true, true);
|
||||
|
|
@ -313,22 +332,32 @@ void CScreenshareFrame::renderWindow() {
|
|||
void CScreenshareFrame::render() {
|
||||
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_session->m_client, PERMISSION_TYPE_SCREENCOPY);
|
||||
|
||||
CRegion frameRegion = {0, 0, g_pHyprRenderer->m_renderData.pMonitor->m_pixelSize.x, g_pHyprRenderer->m_renderData.pMonitor->m_pixelSize.y};
|
||||
if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) {
|
||||
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0));
|
||||
g_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), frameRegion);
|
||||
return;
|
||||
}
|
||||
|
||||
bool windowShareDenied = m_session->m_type == SHARE_WINDOW && m_session->m_window->m_ruleApplicator && m_session->m_window->m_ruleApplicator->noScreenShare().valueOrDefault();
|
||||
g_pHyprRenderer->startRenderPass();
|
||||
if (PERM == PERMISSION_RULE_ALLOW_MODE_DENY || windowShareDenied) {
|
||||
g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0));
|
||||
g_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), frameRegion);
|
||||
CBox texbox = CBox{m_bufferSize / 2.F, g_pHyprRenderer->m_screencopyDeniedTexture->m_size}.translate(-g_pHyprRenderer->m_screencopyDeniedTexture->m_size / 2.F);
|
||||
g_pHyprOpenGL->renderTexture(g_pHyprRenderer->m_screencopyDeniedTexture, texbox, {});
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = g_pHyprRenderer->m_screencopyDeniedTexture,
|
||||
.box = texbox,
|
||||
}),
|
||||
texbox);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_session->m_tempFB && m_session->m_tempFB->isAllocated()) {
|
||||
CBox texbox = {{}, m_bufferSize};
|
||||
g_pHyprOpenGL->renderTexture(m_session->m_tempFB->getTexture(), texbox, {});
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = m_session->m_tempFB->getTexture(),
|
||||
.box = texbox,
|
||||
}),
|
||||
texbox);
|
||||
m_session->m_tempFB->release();
|
||||
return;
|
||||
}
|
||||
|
|
@ -371,10 +400,7 @@ bool CScreenshareFrame::copyShm() {
|
|||
if (done())
|
||||
return false;
|
||||
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
|
||||
auto shm = m_buffer->shm();
|
||||
auto [pixelData, fmt, bufLen] = m_buffer->beginDataPtr(0); // no need for end, cuz it's shm
|
||||
auto shm = m_buffer->shm();
|
||||
|
||||
const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format);
|
||||
if (!PFORMAT) {
|
||||
|
|
@ -387,7 +413,7 @@ bool CScreenshareFrame::copyShm() {
|
|||
auto outFB = g_pHyprRenderer->createFB();
|
||||
outFB->alloc(m_bufferSize.x, m_bufferSize.y, shm.format);
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(PMONITOR, m_damage, RENDER_MODE_FULL_FAKE, nullptr, outFB, true)) {
|
||||
if (!g_pHyprRenderer->beginFullFakeRender(PMONITOR, m_damage, outFB)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -398,53 +424,11 @@ bool CScreenshareFrame::copyShm() {
|
|||
|
||||
g_pHyprRenderer->endRender();
|
||||
|
||||
g_pHyprRenderer->m_renderData.pMonitor = PMONITOR;
|
||||
outFB->bind();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, GLFB(outFB)->getFBID());
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
uint32_t packStride = NFormatUtils::minStride(PFORMAT, m_bufferSize.x);
|
||||
int glFormat = PFORMAT->glFormat;
|
||||
|
||||
if (glFormat == GL_RGBA)
|
||||
glFormat = GL_BGRA_EXT;
|
||||
|
||||
if (glFormat != GL_BGRA_EXT && glFormat != GL_RGB) {
|
||||
if (PFORMAT->swizzle.has_value()) {
|
||||
std::array<GLint, 4> RGBA = SWIZZLE_RGBA;
|
||||
std::array<GLint, 4> BGRA = SWIZZLE_BGRA;
|
||||
if (PFORMAT->swizzle == RGBA)
|
||||
glFormat = GL_RGBA;
|
||||
else if (PFORMAT->swizzle == BGRA)
|
||||
glFormat = GL_BGRA_EXT;
|
||||
else {
|
||||
LOGM(Log::ERR, "Copied frame via shm might be broken or color flipped");
|
||||
glFormat = GL_RGBA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use pixel buffer object to not block cpu
|
||||
if (packStride == sc<uint32_t>(shm.stride)) {
|
||||
m_damage.forEachRect([&](const auto& rect) {
|
||||
int width = rect.x2 - rect.x1;
|
||||
int height = rect.y2 - rect.y1;
|
||||
glReadPixels(rect.x1, rect.y1, width, height, glFormat, PFORMAT->glType, pixelData);
|
||||
});
|
||||
} else {
|
||||
m_damage.forEachRect([&](const auto& rect) {
|
||||
size_t width = rect.x2 - rect.x1;
|
||||
size_t height = rect.y2 - rect.y1;
|
||||
for (size_t i = rect.y1; i < height; ++i) {
|
||||
glReadPixels(rect.x1, i, width, 1, glFormat, PFORMAT->glType, pixelData + (rect.x1 * PFORMAT->bytesPerBlock) + (i * shm.stride));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
GLFB(outFB)->unbind();
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
m_damage.forEachRect([&](const auto& rect) {
|
||||
int width = rect.x2 - rect.x1;
|
||||
int height = rect.y2 - rect.y1;
|
||||
outFB->readPixels(m_buffer, rect.x1, rect.y1, width, height);
|
||||
});
|
||||
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
|
||||
|
|
@ -463,7 +447,7 @@ void CScreenshareFrame::storeTempFB() {
|
|||
|
||||
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(m_session->monitor(), fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, m_session->m_tempFB, true)) {
|
||||
if (!g_pHyprRenderer->beginFullFakeRender(m_session->monitor(), fakeDamage, m_session->m_tempFB)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering to temp fb");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
405
src/render/GLRenderer.cpp
Normal file
405
src/render/GLRenderer.cpp
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
#include "GLRenderer.hpp"
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../managers/CursorManager.hpp"
|
||||
#include "../managers/PointerManager.hpp"
|
||||
#include "../protocols/SessionLock.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../protocols/PresentationTime.hpp"
|
||||
#include "../protocols/core/DataDevice.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../debug/HyprDebugOverlay.hpp"
|
||||
#include "helpers/Monitor.hpp"
|
||||
#include "pass/TexPassElement.hpp"
|
||||
#include "pass/ClearPassElement.hpp"
|
||||
#include "pass/RectPassElement.hpp"
|
||||
#include "pass/SurfacePassElement.hpp"
|
||||
#include "debug/log/Logger.hpp"
|
||||
#include "../protocols/types/ContentType.hpp"
|
||||
#include "render/OpenGL.hpp"
|
||||
#include "render/Renderer.hpp"
|
||||
#include "render/gl/GLFramebuffer.hpp"
|
||||
#include "render/gl/GLTexture.hpp"
|
||||
#include "decorations/CHyprDropShadowDecoration.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <hyprutils/memory/SharedPtr.hpp>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
using namespace Hyprutils::Utils;
|
||||
using namespace Hyprutils::OS;
|
||||
using enum NContentType::eContentType;
|
||||
using namespace NColorManagement;
|
||||
|
||||
extern "C" {
|
||||
#include <xf86drm.h>
|
||||
}
|
||||
|
||||
CHyprGLRenderer::CHyprGLRenderer() : IHyprRenderer() {}
|
||||
|
||||
void CHyprGLRenderer::initRender() {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
g_pHyprRenderer->m_renderData.pMonitor = renderData().pMonitor;
|
||||
}
|
||||
|
||||
bool CHyprGLRenderer::initRenderBuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
|
||||
try {
|
||||
m_currentRenderbuffer = getOrCreateRenderbuffer(m_currentBuffer, fmt);
|
||||
} catch (std::exception& e) {
|
||||
Log::logger->log(Log::ERR, "getOrCreateRenderbuffer failed for {}", NFormatUtils::drmFormatName(fmt));
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_currentRenderbuffer;
|
||||
}
|
||||
|
||||
bool CHyprGLRenderer::beginFullFakeRenderInternal(PHLMONITOR pMonitor, CRegion& damage, SP<IFramebuffer> fb, bool simple) {
|
||||
initRender();
|
||||
|
||||
RASSERT(fb, "Cannot render FULL_FAKE without a provided fb!");
|
||||
fb->bind();
|
||||
if (simple)
|
||||
g_pHyprOpenGL->beginSimple(pMonitor, damage, nullptr, fb);
|
||||
else
|
||||
g_pHyprOpenGL->begin(pMonitor, damage, fb);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CHyprGLRenderer::beginRenderInternal(PHLMONITOR pMonitor, CRegion& damage, bool simple) {
|
||||
|
||||
m_currentRenderbuffer->bind();
|
||||
if (simple)
|
||||
g_pHyprOpenGL->beginSimple(pMonitor, damage, m_currentRenderbuffer);
|
||||
else
|
||||
g_pHyprOpenGL->begin(pMonitor, damage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::endRender(const std::function<void()>& renderingDoneCallback) {
|
||||
const auto PMONITOR = g_pHyprRenderer->m_renderData.pMonitor;
|
||||
static auto PNVIDIAANTIFLICKER = CConfigValue<Hyprlang::INT>("opengl:nvidia_anti_flicker");
|
||||
|
||||
g_pHyprRenderer->m_renderData.damage = m_renderPass.render(g_pHyprRenderer->m_renderData.damage);
|
||||
|
||||
auto cleanup = CScopeGuard([this]() {
|
||||
if (m_currentRenderbuffer)
|
||||
m_currentRenderbuffer->unbind();
|
||||
m_currentRenderbuffer = nullptr;
|
||||
m_currentBuffer = nullptr;
|
||||
});
|
||||
|
||||
if (m_renderMode != RENDER_MODE_TO_BUFFER_READ_ONLY)
|
||||
g_pHyprOpenGL->end();
|
||||
else {
|
||||
g_pHyprRenderer->m_renderData.pMonitor.reset();
|
||||
g_pHyprRenderer->m_renderData.mouseZoomFactor = 1.f;
|
||||
g_pHyprRenderer->m_renderData.mouseZoomUseMouse = true;
|
||||
}
|
||||
|
||||
if (m_renderMode == RENDER_MODE_FULL_FAKE)
|
||||
return;
|
||||
|
||||
if (m_renderMode == RENDER_MODE_NORMAL)
|
||||
PMONITOR->m_output->state->setBuffer(m_currentBuffer);
|
||||
|
||||
if (!explicitSyncSupported()) {
|
||||
Log::logger->log(Log::TRACE, "renderer: Explicit sync unsupported, falling back to implicit in endRender");
|
||||
|
||||
// nvidia doesn't have implicit sync, so we have to explicitly wait here, llvmpipe and other software renderer seems to bug out aswell.
|
||||
if ((isNvidia() && *PNVIDIAANTIFLICKER) || isSoftware())
|
||||
glFinish();
|
||||
else
|
||||
glFlush(); // mark an implicit sync point
|
||||
|
||||
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
||||
if (renderingDoneCallback)
|
||||
renderingDoneCallback();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
UP<CEGLSync> eglSync = CEGLSync::create();
|
||||
if LIKELY (eglSync && eglSync->isValid()) {
|
||||
for (auto const& buf : m_usedAsyncBuffers) {
|
||||
for (const auto& releaser : buf->m_syncReleasers) {
|
||||
releaser->addSyncFileFd(eglSync->fd());
|
||||
}
|
||||
}
|
||||
|
||||
// release buffer refs with release points now, since syncReleaser handles actual buffer release based on EGLSync
|
||||
std::erase_if(m_usedAsyncBuffers, [](const auto& buf) { return !buf->m_syncReleasers.empty(); });
|
||||
|
||||
// release buffer refs without release points when EGLSync sync_file/fence is signalled
|
||||
g_pEventLoopManager->doOnReadable(eglSync->fd().duplicate(), [renderingDoneCallback, prevbfs = std::move(m_usedAsyncBuffers)]() mutable {
|
||||
prevbfs.clear();
|
||||
if (renderingDoneCallback)
|
||||
renderingDoneCallback();
|
||||
});
|
||||
m_usedAsyncBuffers.clear();
|
||||
|
||||
if (m_renderMode == RENDER_MODE_NORMAL) {
|
||||
PMONITOR->m_inFence = eglSync->takeFd();
|
||||
PMONITOR->m_output->state->setExplicitInFence(PMONITOR->m_inFence.get());
|
||||
}
|
||||
} else {
|
||||
Log::logger->log(Log::ERR, "renderer: Explicit sync failed, releasing resources");
|
||||
|
||||
m_usedAsyncBuffers.clear(); // release all buffer refs and hope implicit sync works
|
||||
if (renderingDoneCallback)
|
||||
renderingDoneCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::renderOffToMain(IFramebuffer* off) {
|
||||
g_pHyprOpenGL->renderOffToMain(off);
|
||||
}
|
||||
|
||||
SP<IRenderbuffer> CHyprGLRenderer::getOrCreateRenderbufferInternal(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
return makeShared<CGLRenderbuffer>(buffer, fmt);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::createStencilTexture(const int width, const int height) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
auto tex = makeShared<CGLTexture>();
|
||||
tex->allocate({width, height});
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::createTexture(bool opaque) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
return makeShared<CGLTexture>(opaque);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy, bool opaque) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
return makeShared<CGLTexture>(drmFormat, pixels, stride, size, keepDataCopy, opaque);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::createTexture(const Aquamarine::SDMABUFAttrs& attrs, bool opaque) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
const auto image = g_pHyprOpenGL->createEGLImage(attrs);
|
||||
if (!image)
|
||||
return nullptr;
|
||||
return makeShared<CGLTexture>(attrs, image, opaque);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::createTexture(const int width, const int height, unsigned char* const data) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
SP<ITexture> tex = makeShared<CGLTexture>();
|
||||
|
||||
tex->allocate({width, height});
|
||||
|
||||
tex->m_size = {width, height};
|
||||
// copy the data to an OpenGL texture we have
|
||||
const GLint glFormat = GL_RGBA;
|
||||
const GLint glType = GL_UNSIGNED_BYTE;
|
||||
|
||||
tex->bind();
|
||||
tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, data);
|
||||
tex->unbind();
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::createTexture(cairo_surface_t* cairo) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
const auto CAIROFORMAT = cairo_image_surface_get_format(cairo);
|
||||
auto tex = makeShared<CGLTexture>();
|
||||
|
||||
tex->allocate({cairo_image_surface_get_width(cairo), cairo_image_surface_get_height(cairo)});
|
||||
|
||||
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : GL_RGBA;
|
||||
const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA;
|
||||
const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE;
|
||||
|
||||
const auto DATA = cairo_image_surface_get_data(cairo);
|
||||
tex->bind();
|
||||
tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) {
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::createTexture(std::span<const float> lut3D, size_t N) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
return makeShared<CGLTexture>(lut3D, N);
|
||||
}
|
||||
|
||||
bool CHyprGLRenderer::explicitSyncSupported() {
|
||||
return g_pHyprOpenGL->explicitSyncSupported();
|
||||
}
|
||||
|
||||
std::vector<SDRMFormat> CHyprGLRenderer::getDRMFormats() {
|
||||
return g_pHyprOpenGL->getDRMFormats();
|
||||
}
|
||||
|
||||
std::vector<uint64_t> CHyprGLRenderer::getDRMFormatModifiers(DRMFormat format) {
|
||||
return g_pHyprOpenGL->getDRMFormatModifiers(format);
|
||||
}
|
||||
|
||||
SP<IFramebuffer> CHyprGLRenderer::createFB(const std::string& name) {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
return makeShared<CGLFramebuffer>(name);
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::disableScissor() {
|
||||
g_pHyprOpenGL->scissor(nullptr);
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::blend(bool enabled) {
|
||||
g_pHyprOpenGL->blend(enabled);
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::drawShadow(const CBox& box, int round, float roundingPower, int range, CHyprColor color, float a) {
|
||||
g_pHyprOpenGL->renderRoundedShadow(box, round, roundingPower, range, color, a);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::blurFramebuffer(SP<IFramebuffer> source, float a, CRegion* originalDamage) {
|
||||
auto src = GLFB(source);
|
||||
return g_pHyprOpenGL->blurFramebufferWithDamage(a, originalDamage, *src)->getTexture();
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::setViewport(int x, int y, int width, int height) {
|
||||
g_pHyprOpenGL->setViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
bool CHyprGLRenderer::reloadShaders(const std::string& path) {
|
||||
return g_pHyprOpenGL->initShaders(path);
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::draw(CBorderPassElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
if (m_data.hasGrad2)
|
||||
g_pHyprOpenGL->renderBorder(
|
||||
m_data.box, m_data.grad1, m_data.grad2, m_data.lerp,
|
||||
{.round = m_data.round, .roundingPower = m_data.roundingPower, .borderSize = m_data.borderSize, .a = m_data.a, .outerRound = m_data.outerRound});
|
||||
else
|
||||
g_pHyprOpenGL->renderBorder(
|
||||
m_data.box, m_data.grad1,
|
||||
{.round = m_data.round, .roundingPower = m_data.roundingPower, .borderSize = m_data.borderSize, .a = m_data.a, .outerRound = m_data.outerRound});
|
||||
};
|
||||
|
||||
void CHyprGLRenderer::draw(CClearPassElement* element, const CRegion& damage) {
|
||||
g_pHyprOpenGL->clear(element->m_data.color);
|
||||
};
|
||||
|
||||
void CHyprGLRenderer::draw(CFramebufferElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
SP<IFramebuffer> fb = nullptr;
|
||||
|
||||
if (m_data.main) {
|
||||
switch (m_data.framebufferID) {
|
||||
case FB_MONITOR_RENDER_MAIN: fb = g_pHyprRenderer->m_renderData.mainFB; break;
|
||||
case FB_MONITOR_RENDER_CURRENT: fb = g_pHyprRenderer->m_renderData.currentFB; break;
|
||||
case FB_MONITOR_RENDER_OUT: fb = g_pHyprRenderer->m_renderData.outFB; break;
|
||||
default: fb = nullptr;
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
Log::logger->log(Log::ERR, "BUG THIS: CFramebufferElement::draw: main but null");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (m_data.framebufferID) {
|
||||
case FB_MONITOR_RENDER_EXTRA_OFFLOAD: fb = g_pHyprRenderer->m_renderData.pMonitor->m_offloadFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MIRROR: fb = m_renderData.pMonitor->m_mirrorFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP: fb = m_renderData.pMonitor->m_mirrorSwapFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_OFF_MAIN: fb = g_pHyprRenderer->m_renderData.pMonitor->m_offMainFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR: fb = g_pHyprRenderer->m_renderData.pMonitor->m_monitorMirrorFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_BLUR: fb = g_pHyprRenderer->m_renderData.pMonitor->m_blurFB; break;
|
||||
default: fb = nullptr;
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
Log::logger->log(Log::ERR, "BUG THIS: CFramebufferElement::draw: not main but null");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fb->bind();
|
||||
};
|
||||
|
||||
void CHyprGLRenderer::draw(CPreBlurElement* element, const CRegion& damage) {
|
||||
auto dmg = damage;
|
||||
g_pHyprRenderer->preBlurForCurrentMonitor(&dmg);
|
||||
};
|
||||
|
||||
void CHyprGLRenderer::draw(CRectPassElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
|
||||
if (m_data.color.a == 1.F || !m_data.blur)
|
||||
g_pHyprOpenGL->renderRect(m_data.box, m_data.color, {.damage = &damage, .round = m_data.round, .roundingPower = m_data.roundingPower});
|
||||
else
|
||||
g_pHyprOpenGL->renderRect(m_data.box, m_data.color,
|
||||
{.round = m_data.round, .roundingPower = m_data.roundingPower, .blur = true, .blurA = m_data.blurA, .xray = m_data.xray});
|
||||
};
|
||||
|
||||
void CHyprGLRenderer::draw(CShadowPassElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
m_data.deco->render(g_pHyprRenderer->m_renderData.pMonitor.lock(), m_data.a);
|
||||
};
|
||||
|
||||
void CHyprGLRenderer::draw(CTexPassElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
|
||||
g_pHyprOpenGL->renderTexture( //
|
||||
m_data.tex, m_data.box,
|
||||
{
|
||||
// blur settings for m_data.blur == true
|
||||
.blur = m_data.blur,
|
||||
.blurA = m_data.blurA,
|
||||
.overallA = m_data.overallA,
|
||||
.blockBlurOptimization = m_data.blockBlurOptimization.value_or(false),
|
||||
.blurredBG = m_data.blurredBG,
|
||||
|
||||
// common settings
|
||||
.damage = m_data.damage.empty() ? &damage : &m_data.damage,
|
||||
.surface = m_data.surface,
|
||||
.a = m_data.a,
|
||||
.round = m_data.round,
|
||||
.roundingPower = m_data.roundingPower,
|
||||
.discardActive = m_data.discardActive,
|
||||
.allowCustomUV = m_data.allowCustomUV,
|
||||
.cmBackToSRGB = m_data.cmBackToSRGB,
|
||||
.cmBackToSRGBSource = m_data.cmBackToSRGBSource,
|
||||
.discardMode = m_data.ignoreAlpha.has_value() ? sc<uint32_t>(DISCARD_ALPHA) : m_data.discardMode,
|
||||
.discardOpacity = m_data.ignoreAlpha.has_value() ? *m_data.ignoreAlpha : m_data.discardOpacity,
|
||||
.clipRegion = m_data.clipRegion,
|
||||
.currentLS = m_data.currentLS,
|
||||
|
||||
.primarySurfaceUVTopLeft = g_pHyprRenderer->m_renderData.primarySurfaceUVTopLeft,
|
||||
.primarySurfaceUVBottomRight = g_pHyprRenderer->m_renderData.primarySurfaceUVBottomRight,
|
||||
});
|
||||
};
|
||||
|
||||
void CHyprGLRenderer::draw(CTextureMatteElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
|
||||
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb);
|
||||
};
|
||||
|
||||
SP<ITexture> CHyprGLRenderer::getBlurTexture(PHLMONITORREF pMonitor) {
|
||||
return pMonitor->m_blurFB->getTexture();
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::unsetEGL() {
|
||||
if (!g_pHyprOpenGL)
|
||||
return;
|
||||
|
||||
eglMakeCurrent(g_pHyprOpenGL->m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
52
src/render/GLRenderer.hpp
Normal file
52
src/render/GLRenderer.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "Renderer.hpp"
|
||||
|
||||
class CHyprGLRenderer : public IHyprRenderer {
|
||||
public:
|
||||
CHyprGLRenderer();
|
||||
|
||||
void endRender(const std::function<void()>& renderingDoneCallback = {}) override;
|
||||
SP<ITexture> createStencilTexture(const int width, const int height) override;
|
||||
SP<ITexture> createTexture(bool opaque = false) override;
|
||||
SP<ITexture> createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false) override;
|
||||
SP<ITexture> createTexture(const Aquamarine::SDMABUFAttrs&, bool opaque = false) override;
|
||||
SP<ITexture> createTexture(const int width, const int height, unsigned char* const data) override;
|
||||
SP<ITexture> createTexture(cairo_surface_t* cairo) override;
|
||||
SP<ITexture> createTexture(std::span<const float> lut3D, size_t N) override;
|
||||
bool explicitSyncSupported() override;
|
||||
std::vector<SDRMFormat> getDRMFormats() override;
|
||||
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format) override;
|
||||
SP<IFramebuffer> createFB(const std::string& name = "") override;
|
||||
void disableScissor() override;
|
||||
void blend(bool enabled) override;
|
||||
void drawShadow(const CBox& box, int round, float roundingPower, int range, CHyprColor color, float a) override;
|
||||
SP<ITexture> blurFramebuffer(SP<IFramebuffer> source, float a, CRegion* originalDamage) override;
|
||||
void setViewport(int x, int y, int width, int height) override;
|
||||
bool reloadShaders(const std::string& path = "") override;
|
||||
|
||||
void unsetEGL();
|
||||
|
||||
private:
|
||||
void renderOffToMain(IFramebuffer* off) override;
|
||||
SP<IRenderbuffer> getOrCreateRenderbufferInternal(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) override;
|
||||
bool beginRenderInternal(PHLMONITOR pMonitor, CRegion& damage, bool simple = false) override;
|
||||
bool beginFullFakeRenderInternal(PHLMONITOR pMonitor, CRegion& damage, SP<IFramebuffer> fb, bool simple = false) override;
|
||||
void initRender() override;
|
||||
bool initRenderBuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) override;
|
||||
|
||||
void draw(CBorderPassElement* element, const CRegion& damage) override;
|
||||
void draw(CClearPassElement* element, const CRegion& damage) override;
|
||||
void draw(CFramebufferElement* element, const CRegion& damage) override;
|
||||
void draw(CPreBlurElement* element, const CRegion& damage) override;
|
||||
void draw(CRectPassElement* element, const CRegion& damage) override;
|
||||
void draw(CShadowPassElement* element, const CRegion& damage) override;
|
||||
void draw(CTexPassElement* element, const CRegion& damage) override;
|
||||
void draw(CTextureMatteElement* element, const CRegion& damage) override;
|
||||
|
||||
SP<ITexture> getBlurTexture(PHLMONITORREF pMonitor) override;
|
||||
|
||||
SP<IRenderbuffer> m_currentRenderbuffer = nullptr;
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -35,7 +35,7 @@
|
|||
#include "render/ShaderLoader.hpp"
|
||||
#include "render/gl/GLFramebuffer.hpp"
|
||||
#include "render/gl/GLRenderbuffer.hpp"
|
||||
#include "render/gl/GLTexture.hpp"
|
||||
#include "render/pass/TexPassElement.hpp"
|
||||
|
||||
#define GLFB(ifb) dc<CGLFramebuffer*>(ifb.get())
|
||||
|
||||
|
|
@ -56,11 +56,6 @@ constexpr std::array<SVertex, 4> fullVerts = {{
|
|||
|
||||
inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f};
|
||||
|
||||
enum eDiscardMode : uint8_t {
|
||||
DISCARD_OPAQUE = 1,
|
||||
DISCARD_ALPHA = 1 << 1
|
||||
};
|
||||
|
||||
struct SRenderModifData {
|
||||
enum eRenderModifType : uint8_t {
|
||||
RMOD_TYPE_SCALE, /* scale by a float */
|
||||
|
|
@ -186,24 +181,33 @@ class CHyprOpenGLImpl {
|
|||
};
|
||||
|
||||
struct STextureRenderData {
|
||||
const CRegion* damage = nullptr;
|
||||
SP<CWLSurfaceResource> surface = nullptr;
|
||||
float a = 1.F;
|
||||
bool blur = false;
|
||||
bool blur = false;
|
||||
float blurA = 1.F, overallA = 1.F;
|
||||
int round = 0;
|
||||
float roundingPower = 2.F;
|
||||
bool discardActive = false;
|
||||
bool allowCustomUV = false;
|
||||
bool allowDim = true;
|
||||
bool noAA = false;
|
||||
bool blockBlurOptimization = false;
|
||||
SP<ITexture> blurredBG;
|
||||
|
||||
const CRegion* damage = nullptr;
|
||||
SP<CWLSurfaceResource> surface = nullptr;
|
||||
float a = 1.F;
|
||||
int round = 0;
|
||||
float roundingPower = 2.F;
|
||||
bool discardActive = false;
|
||||
bool allowCustomUV = false;
|
||||
bool allowDim = true;
|
||||
bool noAA = false; // unused
|
||||
GLenum wrapX = GL_CLAMP_TO_EDGE, wrapY = GL_CLAMP_TO_EDGE;
|
||||
bool cmBackToSRGB = false;
|
||||
bool noCM = false;
|
||||
bool finalMonitorCM = false;
|
||||
SP<CMonitor> cmBackToSRGBSource;
|
||||
SP<ITexture> blurredBG;
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
CRegion clipRegion;
|
||||
PHLLSREF currentLS;
|
||||
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
};
|
||||
|
||||
struct SBorderRenderData {
|
||||
|
|
@ -227,37 +231,25 @@ class CHyprOpenGLImpl {
|
|||
void renderTextureMatte(SP<ITexture> tex, const CBox& pBox, SP<IFramebuffer> matte);
|
||||
void renderTexturePrimitive(SP<ITexture> tex, const CBox& box);
|
||||
|
||||
void setRenderModifEnabled(bool enabled);
|
||||
void setViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void setCapStatus(int cap, bool status);
|
||||
|
||||
void blend(bool enabled);
|
||||
|
||||
void clear(const CHyprColor&);
|
||||
void clearWithTex();
|
||||
void scissor(const CBox&, bool transform = true);
|
||||
void scissor(const pixman_box32*, bool transform = true);
|
||||
void scissor(const int x, const int y, const int w, const int h, bool transform = true);
|
||||
|
||||
void destroyMonitorResources(PHLMONITORREF);
|
||||
|
||||
void preWindowPass();
|
||||
bool preBlurQueued();
|
||||
void preRender(PHLMONITOR);
|
||||
|
||||
void saveBufferForMirror(const CBox&);
|
||||
void renderMirrored();
|
||||
|
||||
void applyScreenShader(const std::string& path);
|
||||
|
||||
void bindOffMain();
|
||||
void renderOffToMain(CGLFramebuffer* off);
|
||||
void bindBackOnMain();
|
||||
|
||||
SP<ITexture> texFromCairo(cairo_surface_t* cairo);
|
||||
|
||||
bool needsACopyFB(PHLMONITOR mon);
|
||||
void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
|
||||
void renderOffToMain(IFramebuffer* off);
|
||||
|
||||
std::vector<SDRMFormat> getDRMFormats();
|
||||
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
|
||||
|
|
@ -350,7 +342,6 @@ class CHyprOpenGLImpl {
|
|||
SP<CShader> m_finalScreenShader;
|
||||
GLuint m_currentProgram;
|
||||
|
||||
void createBGTextureForMonitor(PHLMONITOR);
|
||||
void initDRMFormats();
|
||||
void initEGL(bool gbm);
|
||||
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
|
||||
|
|
@ -365,13 +356,11 @@ class CHyprOpenGLImpl {
|
|||
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
||||
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
SP<IFramebuffer> blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||
SP<IFramebuffer> blurFramebufferWithDamage(float a, CRegion* damage, CGLFramebuffer& source);
|
||||
|
||||
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
||||
bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
||||
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription);
|
||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
||||
void renderRectInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
void renderRectWithBlurInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
void renderRectWithDamageInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
|
|
@ -380,9 +369,8 @@ class CHyprOpenGLImpl {
|
|||
void renderTextureInternal(SP<ITexture>, const CBox&, const STextureRenderData& data);
|
||||
void renderTextureWithBlurInternal(SP<ITexture>, const CBox&, const STextureRenderData& data);
|
||||
|
||||
void preBlurForCurrentMonitor();
|
||||
|
||||
friend class CHyprRenderer;
|
||||
friend class IHyprRenderer;
|
||||
friend class CHyprGLRenderer;
|
||||
friend class CTexPassElement;
|
||||
friend class CPreBlurElement;
|
||||
friend class CSurfacePassElement;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -109,12 +109,6 @@ struct SRenderData {
|
|||
|
||||
// TODO remove and pass directly
|
||||
CBox clipBox = {}; // scaled coordinates
|
||||
CRegion clipRegion;
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
PHLLSREF currentLS;
|
||||
PHLWINDOWREF currentWindow;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
|
||||
|
|
@ -145,10 +139,10 @@ struct SCMSettings {
|
|||
float sdrBrightnessMultiplier = 1.0;
|
||||
};
|
||||
|
||||
class CHyprRenderer {
|
||||
class IHyprRenderer {
|
||||
public:
|
||||
CHyprRenderer();
|
||||
~CHyprRenderer();
|
||||
IHyprRenderer();
|
||||
virtual ~IHyprRenderer();
|
||||
|
||||
WP<CHyprOpenGLImpl> glBackend();
|
||||
|
||||
|
|
@ -168,49 +162,45 @@ class CHyprRenderer {
|
|||
void setCursorHidden(bool hide);
|
||||
void calculateUVForSurface(PHLWINDOW, SP<CWLSurfaceResource>, PHLMONITOR pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {},
|
||||
bool fixMisalignedFSV1 = false);
|
||||
std::tuple<float, float, float> getRenderTimes(PHLMONITOR pMonitor); // avg max min
|
||||
void ensureLockTexturesRendered(bool load);
|
||||
void renderLockscreen(PHLMONITOR pMonitor, const Time::steady_tp& now, const CBox& geometry);
|
||||
void setCursorSurface(SP<Desktop::View::CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
|
||||
void setCursorFromName(const std::string& name, bool force = false);
|
||||
void onRenderbufferDestroy(IRenderbuffer* rb);
|
||||
SP<IRenderbuffer> getCurrentRBO();
|
||||
bool isNvidia();
|
||||
bool isIntel();
|
||||
bool isSoftware();
|
||||
bool isMgpu();
|
||||
void addWindowToRenderUnfocused(PHLWINDOW window);
|
||||
void makeSnapshot(PHLWINDOW);
|
||||
void makeSnapshot(PHLLS);
|
||||
void makeSnapshot(WP<Desktop::View::CPopup>);
|
||||
void renderSnapshot(PHLWINDOW);
|
||||
void renderSnapshot(PHLLS);
|
||||
void renderSnapshot(WP<Desktop::View::CPopup>);
|
||||
std::tuple<float, float, float> getRenderTimes(PHLMONITOR pMonitor); // avg max min
|
||||
void ensureLockTexturesRendered(bool load);
|
||||
void renderLockscreen(PHLMONITOR pMonitor, const Time::steady_tp& now, const CBox& geometry);
|
||||
void setCursorSurface(SP<Desktop::View::CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
|
||||
void setCursorFromName(const std::string& name, bool force = false);
|
||||
void onRenderbufferDestroy(IRenderbuffer* rb);
|
||||
bool isNvidia();
|
||||
bool isIntel();
|
||||
bool isSoftware();
|
||||
bool isMgpu();
|
||||
void addWindowToRenderUnfocused(PHLWINDOW window);
|
||||
void makeSnapshot(PHLWINDOW);
|
||||
void makeSnapshot(PHLLS);
|
||||
void makeSnapshot(WP<Desktop::View::CPopup>);
|
||||
void renderSnapshot(PHLWINDOW);
|
||||
void renderSnapshot(PHLLS);
|
||||
void renderSnapshot(WP<Desktop::View::CPopup>);
|
||||
bool beginFullFakeRender(PHLMONITOR pMonitor, CRegion& damage, SP<IFramebuffer> fb);
|
||||
bool beginRenderToBuffer(PHLMONITOR pMonitor, CRegion& damage, SP<IHLBuffer> buffer, bool simple = false);
|
||||
virtual void startRenderPass() {};
|
||||
virtual void endRender(const std::function<void()>& renderingDoneCallback = {}) = 0;
|
||||
|
||||
//
|
||||
NColorManagement::PImageDescription workBufferImageDescription();
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
bool m_bRenderingSnapshot = false;
|
||||
PHLMONITORREF m_mostHzMonitor;
|
||||
bool m_directScanoutBlocked = false;
|
||||
|
||||
// if RENDER_MODE_NORMAL, provided damage will be written to.
|
||||
// otherwise, it will be the one used.
|
||||
bool beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IHLBuffer> buffer = {}, SP<IFramebuffer> fb = nullptr, bool simple = false);
|
||||
void endRender(const std::function<void()>& renderingDoneCallback = {});
|
||||
void setSurfaceScanoutMode(SP<CWLSurfaceResource> surface, PHLMONITOR monitor); // nullptr monitor resets
|
||||
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
bool m_bRenderingSnapshot = false;
|
||||
PHLMONITORREF m_mostHzMonitor;
|
||||
bool m_directScanoutBlocked = false;
|
||||
void initiateManualCrash();
|
||||
const SRenderData& renderData();
|
||||
|
||||
void setSurfaceScanoutMode(SP<CWLSurfaceResource> surface, PHLMONITOR monitor); // nullptr monitor resets
|
||||
bool m_crashingInProgress = false;
|
||||
float m_crashingDistort = 0.5f;
|
||||
wl_event_source* m_crashingLoop = nullptr;
|
||||
wl_event_source* m_cursorTicker = nullptr;
|
||||
|
||||
void initiateManualCrash();
|
||||
const SRenderData& renderData();
|
||||
|
||||
bool m_crashingInProgress = false;
|
||||
float m_crashingDistort = 0.5f;
|
||||
wl_event_source* m_crashingLoop = nullptr;
|
||||
wl_event_source* m_cursorTicker = nullptr;
|
||||
|
||||
std::vector<CHLBufferReference> m_usedAsyncBuffers;
|
||||
std::vector<CHLBufferReference> m_usedAsyncBuffers;
|
||||
|
||||
struct {
|
||||
int hotspotX = 0;
|
||||
|
|
@ -222,62 +212,97 @@ class CHyprRenderer {
|
|||
std::string name;
|
||||
} m_lastCursorData;
|
||||
|
||||
CRenderPass m_renderPass = {};
|
||||
CRenderPass m_renderPass;
|
||||
|
||||
SP<IRenderbuffer> getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt); // TODO? move to protected and fix CPointerManager::renderHWCursorBuffer
|
||||
SRenderData m_renderData; // TODO? move to protected and fix CRenderPass
|
||||
SP<ITexture> m_screencopyDeniedTexture; // TODO? make readonly
|
||||
uint m_failedAssetsNo = 0; // TODO? make readonly
|
||||
bool m_reloadScreenShader = true; // at launch it can be set
|
||||
CTimer m_globalTimer;
|
||||
SP<ITexture> renderSplash(const std::function<SP<ITexture>(const int, const int, unsigned char* const)>& handleData, const int fontSize, const int maxWidth = 1024,
|
||||
const int maxHeight = 1024);
|
||||
|
||||
SP<ITexture> createStencilTexture(const int width, const int height);
|
||||
SP<ITexture> createTexture(bool opaque = false);
|
||||
SP<ITexture> createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false);
|
||||
SP<ITexture> createTexture(const Aquamarine::SDMABUFAttrs&, bool opaque = false);
|
||||
SP<ITexture> createTexture(const int width, const int height, unsigned char* const);
|
||||
SP<ITexture> createTexture(cairo_surface_t* cairo);
|
||||
SP<ITexture> createTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy = false);
|
||||
SP<ITexture> createTexture(std::span<const float> lut3D, size_t N);
|
||||
SP<ITexture> renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0, int weight = 400);
|
||||
SP<ITexture> loadAsset(const std::string& filename);
|
||||
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
|
||||
bool explicitSyncSupported();
|
||||
std::vector<SDRMFormat> getDRMFormats();
|
||||
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
|
||||
SP<IFramebuffer> createFB(const std::string& name = "");
|
||||
void pushMonitorTransformEnabled(bool enabled);
|
||||
void popMonitorTransformEnabled();
|
||||
bool monitorTransformEnabled();
|
||||
virtual SP<IRenderbuffer> getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt); // TODO? move to protected and fix CPointerManager::renderHWCursorBuffer
|
||||
bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); // TODO? move to protected and fix CMonitorFrameScheduler::onPresented
|
||||
SRenderData m_renderData; // TODO? move to protected and fix CRenderPass
|
||||
SP<ITexture> m_screencopyDeniedTexture; // TODO? make readonly
|
||||
uint m_failedAssetsNo = 0; // TODO? make readonly
|
||||
bool m_reloadScreenShader = true; // at launch it can be set
|
||||
CTimer m_globalTimer;
|
||||
|
||||
void setProjectionType(const Vector2D& fbSize);
|
||||
void setProjectionType(eRenderProjectionType projectionType);
|
||||
Mat3x3 getBoxProjection(const CBox& box, std::optional<eTransform> transform = std::nullopt);
|
||||
Mat3x3 projectBoxToTarget(const CBox& box, std::optional<eTransform> transform = std::nullopt);
|
||||
void draw(WP<IPassElement> element, const CRegion& damage);
|
||||
virtual SP<ITexture> createStencilTexture(const int width, const int height) = 0;
|
||||
virtual SP<ITexture> createTexture(bool opaque = false) = 0;
|
||||
virtual SP<ITexture> createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false) = 0;
|
||||
virtual SP<ITexture> createTexture(const Aquamarine::SDMABUFAttrs&, bool opaque = false) = 0;
|
||||
virtual SP<ITexture> createTexture(const int width, const int height, unsigned char* const) = 0;
|
||||
virtual SP<ITexture> createTexture(cairo_surface_t* cairo) = 0;
|
||||
virtual SP<ITexture> createTexture(std::span<const float> lut3D, size_t N) = 0;
|
||||
virtual SP<ITexture> createTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy = false);
|
||||
virtual SP<ITexture> renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0, int weight = 400);
|
||||
SP<ITexture> loadAsset(const std::string& filename);
|
||||
virtual bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
|
||||
virtual bool explicitSyncSupported() = 0;
|
||||
virtual std::vector<SDRMFormat> getDRMFormats() = 0;
|
||||
virtual std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format) = 0;
|
||||
virtual SP<IFramebuffer> createFB(const std::string& name = "") = 0;
|
||||
virtual void disableScissor() = 0;
|
||||
virtual void blend(bool enabled) = 0;
|
||||
virtual void drawShadow(const CBox& box, int round, float roundingPower, int range, CHyprColor color, float a) = 0;
|
||||
virtual void setViewport(int x, int y, int width, int height) = 0;
|
||||
|
||||
SCMSettings getCMSettings(const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
||||
SP<CWLSurfaceResource> surface = nullptr, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
||||
bool reloadShaders(const std::string& path = "");
|
||||
bool preBlurQueued(PHLMONITORREF pMonitor);
|
||||
void pushMonitorTransformEnabled(bool enabled);
|
||||
void popMonitorTransformEnabled();
|
||||
bool monitorTransformEnabled();
|
||||
|
||||
void draw(CBorderPassElement* element, const CRegion& damage);
|
||||
void draw(CClearPassElement* element, const CRegion& damage);
|
||||
void draw(CFramebufferElement* element, const CRegion& damage);
|
||||
void draw(CPreBlurElement* element, const CRegion& damage);
|
||||
void draw(CRectPassElement* element, const CRegion& damage);
|
||||
void draw(CRendererHintsPassElement* element, const CRegion& damage);
|
||||
void draw(CShadowPassElement* element, const CRegion& damage);
|
||||
void draw(CSurfacePassElement* element, const CRegion& damage);
|
||||
void draw(CTexPassElement* element, const CRegion& damage);
|
||||
void draw(CTextureMatteElement* element, const CRegion& damage);
|
||||
void draw(WP<IPassElement> element, const CRegion& damage);
|
||||
void setProjectionType(const Vector2D& fbSize);
|
||||
void setProjectionType(eRenderProjectionType projectionType);
|
||||
Mat3x3 getBoxProjection(const CBox& box, std::optional<eTransform> transform = std::nullopt);
|
||||
Mat3x3 projectBoxToTarget(const CBox& box, std::optional<eTransform> transform = std::nullopt);
|
||||
|
||||
SP<ITexture> m_lockDeadTexture;
|
||||
SP<ITexture> m_lockDead2Texture;
|
||||
SP<ITexture> m_lockTtyTextTexture;
|
||||
bool m_monitorTransformEnabled = false; // do not modify directly
|
||||
std::stack<bool> m_monitorTransformStack;
|
||||
SP<ITexture> blurMainFramebuffer(float a, CRegion* originalDamage);
|
||||
virtual SP<ITexture> blurFramebuffer(SP<IFramebuffer> source, float a, CRegion* originalDamage) = 0;
|
||||
void preBlurForCurrentMonitor(CRegion* fakeDamage);
|
||||
|
||||
private:
|
||||
SCMSettings getCMSettings(const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
||||
SP<CWLSurfaceResource> surface = nullptr, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
||||
virtual bool reloadShaders(const std::string& path = "") = 0;
|
||||
|
||||
bool needsACopyFB(PHLMONITOR mon);
|
||||
|
||||
protected:
|
||||
virtual void renderOffToMain(IFramebuffer* off) = 0;
|
||||
virtual SP<IRenderbuffer> getOrCreateRenderbufferInternal(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) = 0;
|
||||
void renderMirrored();
|
||||
void setDamage(const CRegion& damage_, std::optional<CRegion> finalDamage);
|
||||
// if RENDER_MODE_NORMAL, provided damage will be written to.
|
||||
// otherwise, it will be the one used.
|
||||
bool beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IHLBuffer> buffer = {}, SP<IFramebuffer> fb = nullptr, bool simple = false);
|
||||
|
||||
virtual bool beginRenderInternal(PHLMONITOR pMonitor, CRegion& damage, bool simple = false) {
|
||||
return false;
|
||||
};
|
||||
virtual bool beginFullFakeRenderInternal(PHLMONITOR pMonitor, CRegion& damage, SP<IFramebuffer> fb, bool simple = false) {
|
||||
return false;
|
||||
};
|
||||
virtual void initRender() {};
|
||||
virtual bool initRenderBuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
|
||||
return false;
|
||||
};
|
||||
|
||||
SP<ITexture> getBackground(PHLMONITOR pMonitor);
|
||||
virtual void draw(CBorderPassElement* element, const CRegion& damage) = 0;
|
||||
virtual void draw(CClearPassElement* element, const CRegion& damage) = 0;
|
||||
virtual void draw(CFramebufferElement* element, const CRegion& damage) = 0;
|
||||
virtual void draw(CPreBlurElement* element, const CRegion& damage) = 0;
|
||||
virtual void draw(CRectPassElement* element, const CRegion& damage) = 0;
|
||||
virtual void draw(CShadowPassElement* element, const CRegion& damage) = 0;
|
||||
virtual void draw(CTexPassElement* element, const CRegion& damage) = 0;
|
||||
virtual void draw(CTextureMatteElement* element, const CRegion& damage) = 0;
|
||||
virtual SP<ITexture> getBlurTexture(PHLMONITORREF pMonitor);
|
||||
SP<ITexture> m_lockDeadTexture;
|
||||
SP<ITexture> m_lockDead2Texture;
|
||||
SP<ITexture> m_lockTtyTextTexture;
|
||||
bool m_monitorTransformEnabled = false; // do not modify directly
|
||||
std::stack<bool> m_monitorTransformStack;
|
||||
|
||||
// old private:
|
||||
void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*);
|
||||
void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const CBox& geometry);
|
||||
void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
|
||||
|
|
@ -292,12 +317,7 @@ class CHyprRenderer {
|
|||
void renderSessionLockPrimer(PHLMONITOR pMonitor);
|
||||
void renderSessionLockMissing(PHLMONITOR pMonitor);
|
||||
void renderBackground(PHLMONITOR pMonitor);
|
||||
|
||||
bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor);
|
||||
|
||||
void requestBackgroundResource();
|
||||
//
|
||||
SP<IRenderbuffer> getOrCreateRenderbufferInternal(SP<Aquamarine::IBuffer> buffer, uint32_t fmt);
|
||||
std::string resolveAssetPath(const std::string& file);
|
||||
void initMissingAssetTexture();
|
||||
void initAssets();
|
||||
|
|
@ -312,7 +332,6 @@ class CHyprRenderer {
|
|||
bool m_cursorHidden = false;
|
||||
bool m_cursorHiddenByCondition = false;
|
||||
bool m_cursorHasSurface = false;
|
||||
SP<IRenderbuffer> m_currentRenderbuffer = nullptr;
|
||||
SP<Aquamarine::IBuffer> m_currentBuffer = nullptr;
|
||||
eRenderMode m_renderMode = RENDER_MODE_NORMAL;
|
||||
bool m_nvidia = false;
|
||||
|
|
@ -339,6 +358,18 @@ class CHyprRenderer {
|
|||
friend class CPointerManager;
|
||||
friend class CMonitor;
|
||||
friend class CMonitorFrameScheduler;
|
||||
|
||||
private:
|
||||
void bindOffMain();
|
||||
void bindBackOnMain();
|
||||
|
||||
void drawRect(CRectPassElement* element, const CRegion& damage);
|
||||
void drawHints(CRendererHintsPassElement* element, const CRegion& damage);
|
||||
void drawPreBlur(CPreBlurElement* element, const CRegion& damage);
|
||||
void drawSurface(CSurfacePassElement* element, const CRegion& damage);
|
||||
void preDrawSurface(CSurfacePassElement* element, const CRegion& damage);
|
||||
void drawTex(CTexPassElement* element, const CRegion& damage);
|
||||
void drawTexMatte(CTextureMatteElement* element, const CRegion& damage);
|
||||
};
|
||||
|
||||
inline UP<CHyprRenderer> g_pHyprRenderer;
|
||||
inline UP<IHyprRenderer> g_pHyprRenderer;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
|||
data.roundingPower = ROUNDINGPOWER;
|
||||
data.a = a;
|
||||
data.borderSize = borderSize;
|
||||
data.window = m_window;
|
||||
|
||||
if (ANIMATED) {
|
||||
data.hasGrad2 = true;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "../../config/ConfigValue.hpp"
|
||||
#include "../pass/ShadowPassElement.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "render/pass/TextureMatteElement.hpp"
|
||||
|
||||
CHyprDropShadowDecoration::CHyprDropShadowDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_window(pWindow) {
|
||||
;
|
||||
|
|
@ -95,37 +96,46 @@ void CHyprDropShadowDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
|||
g_pHyprRenderer->m_renderPass.add(makeUnique<CShadowPassElement>(data));
|
||||
}
|
||||
|
||||
void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
||||
bool CHyprDropShadowDecoration::canRender(PHLMONITOR pMonitor) {
|
||||
static auto PSHADOWS = CConfigValue<Hyprlang::INT>("decoration:shadow:enabled");
|
||||
if (*PSHADOWS != 1)
|
||||
return false; // disabled
|
||||
|
||||
const auto PWINDOW = m_window.lock();
|
||||
|
||||
if (!validMapped(PWINDOW))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (PWINDOW->m_realShadowColor->value() == CHyprColor(0, 0, 0, 0))
|
||||
return; // don't draw invisible shadows
|
||||
return false; // don't draw invisible shadows
|
||||
|
||||
if (!PWINDOW->m_ruleApplicator->decorate().valueOrDefault())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (PWINDOW->m_ruleApplicator->noShadow().valueOrDefault())
|
||||
return;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SShadowRenderData CHyprDropShadowDecoration::getRenderData(PHLMONITOR pMonitor, float const& a) {
|
||||
if (!canRender(pMonitor))
|
||||
return {};
|
||||
|
||||
const auto PWINDOW = m_window.lock();
|
||||
|
||||
static auto PSHADOWS = CConfigValue<Hyprlang::INT>("decoration:shadow:enabled");
|
||||
static auto PSHADOWSIZE = CConfigValue<Hyprlang::INT>("decoration:shadow:range");
|
||||
static auto PSHADOWIGNOREWINDOW = CConfigValue<Hyprlang::INT>("decoration:shadow:ignore_window");
|
||||
static auto PSHADOWSCALE = CConfigValue<Hyprlang::FLOAT>("decoration:shadow:scale");
|
||||
static auto PSHADOWOFFSET = CConfigValue<Hyprlang::VEC2>("decoration:shadow:offset");
|
||||
|
||||
if (*PSHADOWS != 1)
|
||||
return; // disabled
|
||||
|
||||
const auto BORDERSIZE = PWINDOW->getRealBorderSize();
|
||||
const auto ROUNDINGBASE = PWINDOW->rounding();
|
||||
const auto ROUNDINGPOWER = PWINDOW->roundingPower();
|
||||
const auto CORRECTIONOFFSET = (BORDERSIZE * (M_SQRT2 - 1) * std::max(2.0 - ROUNDINGPOWER, 0.0));
|
||||
const auto ROUNDING = ROUNDINGBASE > 0 ? (ROUNDINGBASE + BORDERSIZE) - CORRECTIONOFFSET : 0;
|
||||
const auto PWORKSPACE = PWINDOW->m_workspace;
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_pinned ? PWORKSPACE->m_renderOffset->value() : Vector2D();
|
||||
const auto BORDERSIZE = PWINDOW->getRealBorderSize();
|
||||
const auto ROUNDINGBASE = PWINDOW->rounding();
|
||||
const auto ROUNDINGPOWER = PWINDOW->roundingPower();
|
||||
const auto CORRECTIONOFFSET = (BORDERSIZE * (M_SQRT2 - 1) * std::max(2.0 - ROUNDINGPOWER, 0.0));
|
||||
const auto ROUNDING = ROUNDINGBASE > 0 ? (ROUNDINGBASE + BORDERSIZE) - CORRECTIONOFFSET : 0;
|
||||
const auto PWORKSPACE = PWINDOW->m_workspace;
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_pinned ? PWORKSPACE->m_renderOffset->value() : Vector2D();
|
||||
|
||||
// draw the shadow
|
||||
CBox fullBox = m_lastWindowBoxWithDecos;
|
||||
|
|
@ -142,27 +152,31 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
|
||||
updateWindow(PWINDOW);
|
||||
m_lastWindowPos += WORKSPACEOFFSET;
|
||||
m_extents = {{m_lastWindowPos.x - fullBox.x - pMonitor->m_position.x + 2, m_lastWindowPos.y - fullBox.y - pMonitor->m_position.y + 2},
|
||||
{fullBox.x + fullBox.width + pMonitor->m_position.x - m_lastWindowPos.x - m_lastWindowSize.x + 2,
|
||||
fullBox.y + fullBox.height + pMonitor->m_position.y - m_lastWindowPos.y - m_lastWindowSize.y + 2}};
|
||||
m_extents = {
|
||||
.topLeft =
|
||||
{
|
||||
m_lastWindowPos.x - fullBox.x - pMonitor->m_position.x + 2,
|
||||
m_lastWindowPos.y - fullBox.y - pMonitor->m_position.y + 2,
|
||||
},
|
||||
.bottomRight =
|
||||
{
|
||||
fullBox.x + fullBox.width + pMonitor->m_position.x - m_lastWindowPos.x - m_lastWindowSize.x + 2,
|
||||
fullBox.y + fullBox.height + pMonitor->m_position.y - m_lastWindowPos.y - m_lastWindowSize.y + 2,
|
||||
},
|
||||
};
|
||||
|
||||
fullBox.translate(PWINDOW->m_floatingOffset);
|
||||
|
||||
if (fullBox.width < 1 || fullBox.height < 1)
|
||||
return; // don't draw invisible shadows
|
||||
return {}; // don't draw invisible shadows
|
||||
|
||||
g_pHyprOpenGL->scissor(nullptr);
|
||||
g_pHyprRenderer->m_renderData.currentWindow = m_window;
|
||||
|
||||
// we'll take the liberty of using this as it should not be used rn
|
||||
auto alphaFB = g_pHyprRenderer->m_renderData.pMonitor->m_mirrorFB;
|
||||
auto alphaSwapFB = g_pHyprRenderer->m_renderData.pMonitor->m_mirrorSwapFB;
|
||||
auto LASTFB = g_pHyprRenderer->m_renderData.currentFB;
|
||||
|
||||
CBox windowBox;
|
||||
CRegion saveDamage;
|
||||
fullBox.scale(pMonitor->m_scale).round();
|
||||
|
||||
if (*PSHADOWIGNOREWINDOW) {
|
||||
CBox windowBox = m_lastWindowBox;
|
||||
windowBox = m_lastWindowBox;
|
||||
CBox withDecos = m_lastWindowBoxWithDecos;
|
||||
|
||||
// get window box
|
||||
|
|
@ -180,51 +194,98 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
windowBox.scale(pMonitor->m_scale).round().addExtents(scaledExtentss);
|
||||
|
||||
if (windowBox.width < 1 || windowBox.height < 1)
|
||||
return; // prevent assert failed
|
||||
return {}; // prevent assert failed
|
||||
|
||||
CRegion saveDamage = g_pHyprRenderer->m_renderData.damage;
|
||||
saveDamage = g_pHyprRenderer->m_renderData.damage;
|
||||
|
||||
g_pHyprRenderer->m_renderData.damage = fullBox;
|
||||
g_pHyprRenderer->m_renderData.damage.subtract(windowBox.copy().expand(-ROUNDING * pMonitor->m_scale)).intersect(saveDamage);
|
||||
g_pHyprRenderer->m_renderData.renderModif.applyToRegion(g_pHyprRenderer->m_renderData.damage);
|
||||
}
|
||||
|
||||
return {
|
||||
.ignoreWindow = *PSHADOWIGNOREWINDOW,
|
||||
.valid = true,
|
||||
.fullBox = fullBox,
|
||||
.windowBox = windowBox,
|
||||
.saveDamage = saveDamage,
|
||||
.rounding = ROUNDING,
|
||||
.roundingPower = ROUNDINGPOWER,
|
||||
.size = *PSHADOWSIZE,
|
||||
};
|
||||
}
|
||||
|
||||
void CHyprDropShadowDecoration::reposition() {
|
||||
if (m_extents != m_reportedExtents)
|
||||
g_pDecorationPositioner->repositionDeco(this);
|
||||
|
||||
g_pHyprRenderer->m_renderData.currentWindow.reset();
|
||||
}
|
||||
|
||||
// TODO remove
|
||||
void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
||||
auto data = getRenderData(pMonitor, a);
|
||||
if (!data.valid)
|
||||
return;
|
||||
|
||||
const auto PWINDOW = m_window.lock();
|
||||
|
||||
g_pHyprRenderer->disableScissor();
|
||||
|
||||
if (data.ignoreWindow) {
|
||||
// we'll take the liberty of using this as it should not be used rn
|
||||
const auto alphaFB = g_pHyprRenderer->m_renderData.pMonitor->m_mirrorFB;
|
||||
const auto alphaSwapFB = g_pHyprRenderer->m_renderData.pMonitor->m_mirrorSwapFB;
|
||||
const auto LASTFB = g_pHyprRenderer->m_renderData.currentFB;
|
||||
|
||||
CBox monbox = {0, 0, pMonitor->m_transformedSize.x, pMonitor->m_transformedSize.y};
|
||||
|
||||
alphaFB->bind();
|
||||
|
||||
// build the matte
|
||||
// 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest.
|
||||
// first, clear region of interest with black (fully transparent)
|
||||
g_pHyprOpenGL->renderRect(fullBox, CHyprColor(0, 0, 0, 1), {.round = 0});
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{.box = data.fullBox, .color = CHyprColor(0, 0, 0, 1), .round = 0}), monbox);
|
||||
|
||||
// render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit)
|
||||
drawShadowInternal(fullBox, ROUNDING * pMonitor->m_scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->m_scale, CHyprColor(1, 1, 1, PWINDOW->m_realShadowColor->value().a), a);
|
||||
drawShadowInternal(data.fullBox, data.rounding * pMonitor->m_scale, data.roundingPower, data.size * pMonitor->m_scale,
|
||||
CHyprColor(1, 1, 1, PWINDOW->m_realShadowColor->value().a), a);
|
||||
|
||||
// render black window box ("clip")
|
||||
g_pHyprOpenGL->renderRect(windowBox, CHyprColor(0, 0, 0, 1.0),
|
||||
{.round = (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->m_scale, .roundingPower = ROUNDINGPOWER});
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = data.windowBox,
|
||||
.color = CHyprColor(0, 0, 0, 1),
|
||||
.round = (data.rounding + 1 /* This fixes small pixel gaps. */) * pMonitor->m_scale,
|
||||
.roundingPower = data.roundingPower,
|
||||
}),
|
||||
monbox);
|
||||
|
||||
alphaSwapFB->bind();
|
||||
|
||||
// alpha swap just has the shadow color. It will be the "texture" to render.
|
||||
g_pHyprOpenGL->renderRect(fullBox, PWINDOW->m_realShadowColor->value().stripA(), {.round = 0});
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{.box = data.fullBox, .color = PWINDOW->m_realShadowColor->value().stripA(), .round = 0}),
|
||||
monbox);
|
||||
|
||||
LASTFB->bind();
|
||||
|
||||
CBox monbox = {0, 0, pMonitor->m_transformedSize.x, pMonitor->m_transformedSize.y};
|
||||
|
||||
g_pHyprRenderer->pushMonitorTransformEnabled(true);
|
||||
g_pHyprOpenGL->setRenderModifEnabled(false);
|
||||
g_pHyprOpenGL->renderTextureMatte(alphaSwapFB->getTexture(), monbox, alphaFB);
|
||||
g_pHyprOpenGL->setRenderModifEnabled(true);
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = false;
|
||||
|
||||
g_pHyprRenderer->draw(makeUnique<CTextureMatteElement>(CTextureMatteElement::STextureMatteData{
|
||||
.box = monbox,
|
||||
.tex = alphaSwapFB->getTexture(),
|
||||
.fb = alphaFB,
|
||||
}),
|
||||
{});
|
||||
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = true;
|
||||
g_pHyprRenderer->popMonitorTransformEnabled();
|
||||
|
||||
g_pHyprRenderer->m_renderData.damage = saveDamage;
|
||||
g_pHyprRenderer->m_renderData.damage = data.saveDamage;
|
||||
} else
|
||||
drawShadowInternal(fullBox, ROUNDING * pMonitor->m_scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->m_scale, PWINDOW->m_realShadowColor->value(), a);
|
||||
drawShadowInternal(data.fullBox, data.rounding * pMonitor->m_scale, data.roundingPower, data.size * pMonitor->m_scale, PWINDOW->m_realShadowColor->value(), a);
|
||||
|
||||
if (m_extents != m_reportedExtents)
|
||||
g_pDecorationPositioner->repositionDeco(this);
|
||||
|
||||
g_pHyprRenderer->m_renderData.currentWindow.reset();
|
||||
reposition();
|
||||
}
|
||||
|
||||
eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
|
||||
|
|
@ -237,12 +298,18 @@ void CHyprDropShadowDecoration::drawShadowInternal(const CBox& box, int round, f
|
|||
if (box.w < 1 || box.h < 1)
|
||||
return;
|
||||
|
||||
g_pHyprOpenGL->blend(true);
|
||||
g_pHyprRenderer->blend(true);
|
||||
|
||||
color.a *= a;
|
||||
|
||||
if (*PSHADOWSHARP)
|
||||
g_pHyprOpenGL->renderRect(box, color, {.round = round, .roundingPower = roundingPower});
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = box,
|
||||
.color = color,
|
||||
.round = round,
|
||||
.roundingPower = roundingPower,
|
||||
}),
|
||||
{});
|
||||
else
|
||||
g_pHyprOpenGL->renderRoundedShadow(box, round, roundingPower, range, color, 1.F);
|
||||
g_pHyprRenderer->drawShadow(box, round, roundingPower, range, color, 1.F);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,17 @@
|
|||
|
||||
#include "IHyprWindowDecoration.hpp"
|
||||
|
||||
struct SShadowRenderData {
|
||||
bool ignoreWindow = false;
|
||||
bool valid = false;
|
||||
CBox fullBox;
|
||||
CBox windowBox;
|
||||
CRegion saveDamage;
|
||||
float rounding = 0;
|
||||
float roundingPower = 0;
|
||||
int size = 0;
|
||||
};
|
||||
|
||||
class CHyprDropShadowDecoration : public IHyprWindowDecoration {
|
||||
public:
|
||||
CHyprDropShadowDecoration(PHLWINDOW);
|
||||
|
|
@ -25,7 +36,12 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
|
|||
|
||||
virtual std::string getDisplayName();
|
||||
|
||||
void render(PHLMONITOR, float const& a);
|
||||
bool canRender(PHLMONITOR);
|
||||
SShadowRenderData getRenderData(PHLMONITOR, float const& a);
|
||||
void reposition();
|
||||
|
||||
// TODO remove
|
||||
void render(PHLMONITOR, float const& a);
|
||||
|
||||
private:
|
||||
SBoxExtents m_extents;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "../OpenGL.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "render/Framebuffer.hpp"
|
||||
#include "../Framebuffer.hpp"
|
||||
|
||||
CGLFramebuffer::CGLFramebuffer() : IFramebuffer() {}
|
||||
CGLFramebuffer::CGLFramebuffer(const std::string& name) : IFramebuffer(name) {}
|
||||
|
|
@ -71,9 +71,10 @@ void CGLFramebuffer::addStencil(SP<ITexture> tex) {
|
|||
void CGLFramebuffer::bind() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb);
|
||||
|
||||
if (g_pHyprOpenGL)
|
||||
g_pHyprOpenGL->setViewport(0, 0, g_pHyprRenderer->m_renderData.pMonitor->m_pixelSize.x, g_pHyprRenderer->m_renderData.pMonitor->m_pixelSize.y);
|
||||
else
|
||||
if (g_pHyprOpenGL) {
|
||||
const auto& size = g_pHyprRenderer->m_renderData.pMonitor ? g_pHyprRenderer->m_renderData.pMonitor->m_pixelSize : m_size;
|
||||
g_pHyprOpenGL->setViewport(0, 0, size.x, size.y);
|
||||
} else
|
||||
glViewport(0, 0, m_size.x, m_size.y);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class CBorderPassElement : public IPassElement {
|
|||
float lerp = 0.F, a = 1.F;
|
||||
int round = 0, borderSize = 1, outerRound = -1;
|
||||
float roundingPower = 2.F;
|
||||
PHLWINDOWREF window;
|
||||
};
|
||||
|
||||
CBorderPassElement(const SBorderData& data_);
|
||||
|
|
|
|||
|
|
@ -213,9 +213,15 @@ void CRenderPass::renderDebugData() {
|
|||
const auto pMonitor = g_pHyprRenderer->m_renderData.pMonitor;
|
||||
CBox box = {{}, pMonitor->m_transformedSize};
|
||||
for (const auto& rg : m_occludedRegions) {
|
||||
g_pHyprOpenGL->renderRect(box, Colors::RED.modifyA(0.1F), {.damage = &rg});
|
||||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = Colors::RED.modifyA(0.1F);
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), rg);
|
||||
}
|
||||
g_pHyprOpenGL->renderRect(box, Colors::GREEN.modifyA(0.1F), {.damage = &m_totalLiveBlurRegion});
|
||||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = Colors::GREEN.modifyA(0.1F);
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), m_totalLiveBlurRegion);
|
||||
|
||||
std::unordered_map<CWLSurfaceResource*, float> offsets;
|
||||
|
||||
|
|
@ -238,9 +244,12 @@ void CRenderPass::renderDebugData() {
|
|||
if (box.intersection(CBox{{}, pMonitor->m_size}).empty())
|
||||
return;
|
||||
|
||||
static const auto FULL_REGION = CRegion{0, 0, INT32_MAX, INT32_MAX};
|
||||
static const auto FULL_REGION = CRegion{0, 0, INT32_MAX, INT32_MAX};
|
||||
|
||||
g_pHyprOpenGL->renderRect(box, color, {.damage = &FULL_REGION});
|
||||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = color;
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), FULL_REGION);
|
||||
|
||||
if (offsets.contains(surface.get()))
|
||||
box.translate(Vector2D{0.F, offsets[surface.get()]});
|
||||
|
|
@ -248,8 +257,16 @@ void CRenderPass::renderDebugData() {
|
|||
offsets[surface.get()] = 0;
|
||||
|
||||
box = {box.pos(), texture->m_size};
|
||||
g_pHyprOpenGL->renderRect(box, CHyprColor{0.F, 0.F, 0.F, 0.2F}, {.damage = &FULL_REGION, .round = std::min(5.0, box.size().y)});
|
||||
g_pHyprOpenGL->renderTexture(texture, box, {});
|
||||
CRectPassElement::SRectData data2;
|
||||
data.box = box;
|
||||
data.color = color;
|
||||
data.round = std::min(5.0, box.size().y);
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data2), FULL_REGION);
|
||||
|
||||
CTexPassElement::SRenderData texData;
|
||||
texData.tex = texture;
|
||||
texData.box = box;
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(texData), {});
|
||||
|
||||
offsets[surface.get()] += texture->m_size.y;
|
||||
};
|
||||
|
|
@ -267,7 +284,10 @@ void CRenderPass::renderDebugData() {
|
|||
auto BOX = hlSurface->getSurfaceBoxGlobal();
|
||||
if (BOX) {
|
||||
auto region = g_pSeatManager->m_state.pointerFocus->m_current.input.copy().scale(pMonitor->m_scale).translate(BOX->pos() - pMonitor->m_position);
|
||||
g_pHyprOpenGL->renderRect(box, CHyprColor{0.8F, 0.8F, 0.2F, 0.4F}, {.damage = ®ion});
|
||||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = CHyprColor{0.8F, 0.8F, 0.2F, 0.4F};
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -280,7 +300,10 @@ void CRenderPass::renderDebugData() {
|
|||
|
||||
if (tex) {
|
||||
box = CBox{{0.F, pMonitor->m_size.y - tex->m_size.y}, tex->m_size}.scale(pMonitor->m_scale);
|
||||
g_pHyprOpenGL->renderTexture(tex, box, {});
|
||||
CTexPassElement::SRenderData texData;
|
||||
texData.tex = tex;
|
||||
texData.box = box;
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(texData), {});
|
||||
}
|
||||
|
||||
std::string passStructure;
|
||||
|
|
@ -297,7 +320,10 @@ void CRenderPass::renderDebugData() {
|
|||
tex = g_pHyprRenderer->renderText(passStructure, Colors::WHITE, 12);
|
||||
if (tex) {
|
||||
box = CBox{{pMonitor->m_size.x - tex->m_size.x, pMonitor->m_size.y - tex->m_size.y}, tex->m_size}.scale(pMonitor->m_scale);
|
||||
g_pHyprOpenGL->renderTexture(tex, box, {});
|
||||
CTexPassElement::SRenderData texData;
|
||||
texData.tex = tex;
|
||||
texData.box = box;
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(texData), {});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@ class CRectPassElement : public IPassElement {
|
|||
bool blur = false, xray = false;
|
||||
float blurA = 1.F;
|
||||
CBox clipBox;
|
||||
|
||||
// internal
|
||||
CBox modifiedBox;
|
||||
float TOPLEFT[2];
|
||||
float FULLSIZE[2];
|
||||
CRegion drawRegion;
|
||||
};
|
||||
|
||||
CRectPassElement(const SRectData& data);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "PassElement.hpp"
|
||||
#include "TexPassElement.hpp"
|
||||
#include <optional>
|
||||
#include "../../helpers/time/Time.hpp"
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ class CSurfacePassElement : public IPassElement {
|
|||
|
||||
CBox clipBox = {}; // scaled coordinates
|
||||
|
||||
uint32_t discardMode = 0;
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
bool useNearestNeighbor = false;
|
||||
|
|
|
|||
|
|
@ -6,22 +6,42 @@ class CWLSurfaceResource;
|
|||
class ITexture;
|
||||
class CSyncTimeline;
|
||||
|
||||
enum eDiscardMode : uint8_t {
|
||||
DISCARD_OPAQUE = 1,
|
||||
DISCARD_ALPHA = 1 << 1
|
||||
};
|
||||
|
||||
class CTexPassElement : public IPassElement {
|
||||
public:
|
||||
struct SRenderData {
|
||||
SP<ITexture> tex;
|
||||
CBox box;
|
||||
float a = 1.F;
|
||||
float blurA = 1.F;
|
||||
CRegion damage;
|
||||
int round = 0;
|
||||
float roundingPower = 2.0f;
|
||||
bool flipEndFrame = false;
|
||||
bool useMirrorProjection = false;
|
||||
CBox clipBox;
|
||||
bool blur = false;
|
||||
std::optional<float> ignoreAlpha;
|
||||
std::optional<bool> blockBlurOptimization;
|
||||
SP<ITexture> tex;
|
||||
CBox box;
|
||||
float a = 1.F;
|
||||
float blurA = 1.F;
|
||||
float overallA = 1.F;
|
||||
CRegion damage;
|
||||
int round = 0;
|
||||
float roundingPower = 2.0f;
|
||||
bool flipEndFrame = false;
|
||||
bool useMirrorProjection = false;
|
||||
CBox clipBox;
|
||||
bool blur = false;
|
||||
std::optional<float> ignoreAlpha;
|
||||
std::optional<bool> blockBlurOptimization;
|
||||
bool cmBackToSRGB = false;
|
||||
SP<CMonitor> cmBackToSRGBSource;
|
||||
|
||||
bool discardActive = false;
|
||||
bool allowCustomUV = false;
|
||||
SP<CWLSurfaceResource> surface = nullptr;
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
CRegion clipRegion;
|
||||
PHLLSREF currentLS;
|
||||
|
||||
SP<ITexture> blurredBG;
|
||||
};
|
||||
|
||||
CTexPassElement(const SRenderData& data);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue