mirror of
https://github.com/hyprwm/Hyprland
synced 2026-05-08 09:18:05 +02:00
namespaces & element renderer
This commit is contained in:
parent
8726a7363e
commit
d071feb9b6
35 changed files with 1520 additions and 1377 deletions
|
|
@ -98,6 +98,7 @@ using namespace Hyprutils::String;
|
|||
using namespace Aquamarine;
|
||||
using enum NContentType::eContentType;
|
||||
using namespace NColorManagement;
|
||||
using namespace Render::GL;
|
||||
|
||||
static int handleCritSignal(int signo, void* data) {
|
||||
Log::logger->log(Log::DEBUG, "Hyprland received signal {}", signo);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ using namespace Hyprutils::OS;
|
|||
#include "../layout/algorithm/TiledAlgorithm.hpp"
|
||||
#include "../layout/supplementary/WorkspaceAlgoMatcher.hpp"
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
#include <sys/ucred.h>
|
||||
#define CRED_T xucred
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
class IHyprRenderer;
|
||||
namespace Render {
|
||||
class IHyprRenderer;
|
||||
}
|
||||
|
||||
class CHyprMonitorDebugOverlay {
|
||||
public:
|
||||
|
|
@ -25,7 +27,7 @@ class CHyprMonitorDebugOverlay {
|
|||
PHLMONITORREF m_monitor;
|
||||
CBox m_lastDrawnBox;
|
||||
|
||||
friend class IHyprRenderer;
|
||||
friend class Render::IHyprRenderer;
|
||||
};
|
||||
|
||||
class CHyprDebugOverlay {
|
||||
|
|
@ -45,7 +47,7 @@ class CHyprDebugOverlay {
|
|||
SP<ITexture> m_texture;
|
||||
|
||||
friend class CHyprMonitorDebugOverlay;
|
||||
friend class IHyprRenderer;
|
||||
friend class Render::IHyprRenderer;
|
||||
};
|
||||
|
||||
inline UP<CHyprDebugOverlay> g_pDebugOverlay;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ using namespace Hyprutils::Utils;
|
|||
using namespace Hyprutils::OS;
|
||||
using enum NContentType::eContentType;
|
||||
using namespace NColorManagement;
|
||||
using namespace Render::GL;
|
||||
|
||||
CMonitor::CMonitor(SP<Aquamarine::IOutput> output_) : m_state(this), m_output(output_), m_imageDescription(DEFAULT_IMAGE_DESCRIPTION) {
|
||||
g_pAnimationManager->createAnimation(0.f, m_specialFade, Config::animationTree()->getAnimationPropertyConfig("specialWorkspaceIn"), AVARDAMAGE_NONE);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@
|
|||
class CMonitorFrameScheduler;
|
||||
class CMonitor;
|
||||
class CSyncTimeline;
|
||||
class CEGLSync;
|
||||
namespace Render::GL {
|
||||
class CEGLSync;
|
||||
}
|
||||
class CEventLoopTimer;
|
||||
|
||||
class CMonitorState {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include "../render/Renderer.hpp"
|
||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
CMonitorFrameScheduler::CMonitorFrameScheduler(PHLMONITOR m) : m_monitor(m) {
|
||||
;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
#include <chrono>
|
||||
|
||||
class CEGLSync;
|
||||
namespace Render::GL {
|
||||
class CEGLSync;
|
||||
}
|
||||
|
||||
class CMonitorFrameScheduler {
|
||||
public:
|
||||
|
|
@ -32,7 +34,7 @@ class CMonitorFrameScheduler {
|
|||
|
||||
PHLMONITORREF m_monitor;
|
||||
|
||||
UP<CEGLSync> m_sync;
|
||||
UP<Render::GL::CEGLSync> m_sync;
|
||||
|
||||
WP<CMonitorFrameScheduler> m_self;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "desktop/DesktopTypes.hpp"
|
||||
#include "render/Renderer.hpp"
|
||||
|
||||
void CMonitorZoomController::zoomWithDetachedCamera(CBox& result, const SRenderData& m_renderData) {
|
||||
void CMonitorZoomController::zoomWithDetachedCamera(CBox& result, const Render::SRenderData& m_renderData) {
|
||||
const auto m = m_renderData.pMonitor;
|
||||
auto monbox = CBox(0, 0, m->m_size.x, m->m_size.y);
|
||||
const auto ZOOM = g_pHyprRenderer->m_renderData.mouseZoomFactor;
|
||||
|
|
@ -68,7 +68,7 @@ void CMonitorZoomController::zoomWithDetachedCamera(CBox& result, const SRenderD
|
|||
result = monbox;
|
||||
}
|
||||
|
||||
void CMonitorZoomController::applyZoomTransform(CBox& monbox, const SRenderData& m_renderData) {
|
||||
void CMonitorZoomController::applyZoomTransform(CBox& monbox, const Render::SRenderData& m_renderData) {
|
||||
static auto PZOOMRIGID = CConfigValue<Hyprlang::INT>("cursor:zoom_rigid");
|
||||
static auto PZOOMDETACHEDCAMERA = CConfigValue<Hyprlang::INT>("cursor:zoom_detached_camera");
|
||||
const auto ZOOM = g_pHyprRenderer->m_renderData.mouseZoomFactor;
|
||||
|
|
|
|||
|
|
@ -2,16 +2,18 @@
|
|||
|
||||
#include "./math/Math.hpp"
|
||||
|
||||
struct SRenderData;
|
||||
namespace Render {
|
||||
struct SRenderData;
|
||||
}
|
||||
|
||||
class CMonitorZoomController {
|
||||
public:
|
||||
bool m_resetCameraState = true;
|
||||
|
||||
void applyZoomTransform(CBox& monbox, const SRenderData& m_renderData);
|
||||
void applyZoomTransform(CBox& monbox, const Render::SRenderData& m_renderData);
|
||||
|
||||
private:
|
||||
void zoomWithDetachedCamera(CBox& result, const SRenderData& m_renderData);
|
||||
void zoomWithDetachedCamera(CBox& result, const Render::SRenderData& m_renderData);
|
||||
|
||||
CBox m_camera;
|
||||
float m_lastZoomLevel = 1.0f;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "../protocols/core/Seat.hpp"
|
||||
#include "debug/log/Logger.hpp"
|
||||
#include "eventLoop/EventLoopManager.hpp"
|
||||
#include "../render/pass/ClearPassElement.hpp"
|
||||
#include "../render/pass/TexPassElement.hpp"
|
||||
#include "../managers/input/InputManager.hpp"
|
||||
#include "../render/Renderer.hpp"
|
||||
|
|
@ -594,7 +595,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
|
|||
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}}), {});
|
||||
g_pHyprRenderer->draw(makeShared<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,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
#include <any>
|
||||
|
||||
class CInputManager;
|
||||
class IHyprRenderer;
|
||||
namespace Render {
|
||||
class IHyprRenderer;
|
||||
}
|
||||
class CTextInputV1;
|
||||
class CInputMethodV2;
|
||||
|
||||
|
|
@ -54,7 +56,7 @@ class CInputMethodRelay {
|
|||
CHyprSignalListener newPopup;
|
||||
} m_listeners;
|
||||
|
||||
friend class IHyprRenderer;
|
||||
friend class Render::IHyprRenderer;
|
||||
friend class CInputManager;
|
||||
friend class CTextInputV1ProtocolManager;
|
||||
friend class CTextInput;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
#include "../../protocols/core/Seat.hpp"
|
||||
#include "../permissions/DynamicPermissionManager.hpp"
|
||||
#include "../../render/Renderer.hpp"
|
||||
#include "render/pass/TexPassElement.hpp"
|
||||
#include "../../render/pass/ClearPassElement.hpp"
|
||||
#include "../../render/pass/TexPassElement.hpp"
|
||||
|
||||
using namespace Screenshare;
|
||||
|
||||
|
|
@ -122,14 +123,14 @@ void CCursorshareSession::render() {
|
|||
g_pHyprRenderer->startRenderPass();
|
||||
if (PERM != PERMISSION_RULE_ALLOW_MODE_ALLOW || !overlaps) {
|
||||
// render black when not allowed
|
||||
g_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{Colors::BLACK}), {});
|
||||
g_pHyprRenderer->draw(makeShared<CClearPassElement>(CClearPassElement::SClearData{Colors::BLACK}), {});
|
||||
} else if (!cursorImage.pBuffer || !cursorImage.surface || !cursorImage.bufferTex) {
|
||||
// render clear when cursor is probably hidden
|
||||
g_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), {});
|
||||
g_pHyprRenderer->draw(makeShared<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), {});
|
||||
} else {
|
||||
// render cursor
|
||||
CBox texbox = {{}, cursorImage.bufferTex->m_size};
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
g_pHyprRenderer->draw(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = cursorImage.bufferTex,
|
||||
.box = texbox,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
#include "../../helpers/Monitor.hpp"
|
||||
#include "../../desktop/view/Window.hpp"
|
||||
#include "../../desktop/state/FocusState.hpp"
|
||||
#include "render/pass/RectPassElement.hpp"
|
||||
#include "../../render/pass/ClearPassElement.hpp"
|
||||
#include "../../render/pass/RectPassElement.hpp"
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
|
||||
using namespace Screenshare;
|
||||
|
|
@ -175,7 +176,7 @@ void CScreenshareFrame::renderMonitor() {
|
|||
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{
|
||||
g_pHyprRenderer->draw(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = monbox,
|
||||
.flipEndFrame = true,
|
||||
|
|
@ -199,7 +200,7 @@ 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_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = surfBox,
|
||||
.color = Colors::BLACK,
|
||||
}),
|
||||
|
|
@ -224,7 +225,7 @@ void CScreenshareFrame::renderMonitor() {
|
|||
.scale(PMONITOR->m_scale)
|
||||
.translate(-m_session->m_captureBox.pos());
|
||||
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = noScreenShareBox,
|
||||
.color = Colors::BLACK,
|
||||
}),
|
||||
|
|
@ -263,7 +264,7 @@ void CScreenshareFrame::renderMonitor() {
|
|||
const auto rounding = dontRound ? 0 : w->rounding() * PMONITOR->m_scale;
|
||||
const auto roundingPower = dontRound ? 2.0f : w->roundingPower();
|
||||
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = noScreenShareBox,
|
||||
.color = Colors::BLACK,
|
||||
.round = rounding,
|
||||
|
|
@ -298,12 +299,12 @@ void CScreenshareFrame::renderWindow() {
|
|||
|
||||
// TODO: implement a monitor independent render mode to buffer that does this in CHyprRenderer::begin() or something like that
|
||||
g_pHyprRenderer->m_renderData.fbSize = m_bufferSize;
|
||||
g_pHyprRenderer->setProjectionType(RPT_EXPORT);
|
||||
g_pHyprRenderer->setProjectionType(Render::RPT_EXPORT);
|
||||
g_pHyprRenderer->m_renderData.transformDamage = false;
|
||||
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);
|
||||
g_pHyprRenderer->renderWindow(PWINDOW, PMONITOR, NOW, false, Render::RENDER_PASS_ALL, true, true);
|
||||
g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
|
||||
|
||||
if (!m_overlayCursor)
|
||||
|
|
@ -334,16 +335,16 @@ void CScreenshareFrame::render() {
|
|||
|
||||
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_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), frameRegion);
|
||||
g_pHyprRenderer->draw(makeShared<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_pHyprRenderer->draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), frameRegion);
|
||||
g_pHyprRenderer->draw(makeShared<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_pHyprRenderer->draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
g_pHyprRenderer->draw(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = g_pHyprRenderer->m_screencopyDeniedTexture,
|
||||
.box = texbox,
|
||||
}),
|
||||
|
|
@ -353,7 +354,7 @@ void CScreenshareFrame::render() {
|
|||
|
||||
if (m_session->m_tempFB && m_session->m_tempFB->isAllocated()) {
|
||||
CBox texbox = {{}, m_bufferSize};
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
g_pHyprRenderer->draw(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = m_session->m_tempFB->getTexture(),
|
||||
.box = texbox,
|
||||
}),
|
||||
|
|
@ -375,7 +376,7 @@ bool CScreenshareFrame::copyDmabuf() {
|
|||
if (done())
|
||||
return false;
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(m_session->monitor(), m_damage, RENDER_MODE_TO_BUFFER, m_buffer, nullptr, true)) {
|
||||
if (!g_pHyprRenderer->beginRender(m_session->monitor(), m_damage, Render::RENDER_MODE_TO_BUFFER, m_buffer, nullptr, true)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering to dma frame");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
478
src/render/ElementRenderer.cpp
Normal file
478
src/render/ElementRenderer.cpp
Normal file
|
|
@ -0,0 +1,478 @@
|
|||
#include "ElementRenderer.hpp"
|
||||
#include "Renderer.hpp"
|
||||
#include "../layout/LayoutManager.hpp"
|
||||
#include "../desktop/view/Window.hpp"
|
||||
#include <hyprutils/memory/SharedPtr.hpp>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
|
||||
using namespace Render;
|
||||
|
||||
void IElementRenderer::drawElement(WP<IPassElement> element, const CRegion& damage) {
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
switch (element->type()) {
|
||||
case EK_BORDER: draw(dynamicPointerCast<CBorderPassElement>(element), damage); break;
|
||||
case EK_CLEAR: draw(dynamicPointerCast<CClearPassElement>(element), damage); break;
|
||||
case EK_FRAMEBUFFER: draw(dynamicPointerCast<CFramebufferElement>(element), damage); break;
|
||||
case EK_PRE_BLUR: drawPreBlur(dynamicPointerCast<CPreBlurElement>(element), damage); break;
|
||||
case EK_RECT: drawRect(dynamicPointerCast<CRectPassElement>(element), damage); break;
|
||||
case EK_HINTS: drawHints(dynamicPointerCast<CRendererHintsPassElement>(element), damage); break;
|
||||
case EK_SHADOW: draw(dynamicPointerCast<CShadowPassElement>(element), damage); break;
|
||||
case EK_SURFACE: preDrawSurface(dynamicPointerCast<CSurfacePassElement>(element), damage); break;
|
||||
case EK_TEXTURE: drawTex(dynamicPointerCast<CTexPassElement>(element), damage); break;
|
||||
case EK_TEXTURE_MATTE: drawTexMatte(dynamicPointerCast<CTextureMatteElement>(element), damage); break;
|
||||
default: Log::logger->log(Log::WARN, "Unimplimented draw for {}", element->passName());
|
||||
}
|
||||
}
|
||||
|
||||
static std::optional<Vector2D> getSurfaceExpectedSize(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, PHLMONITOR pMonitor, bool main) {
|
||||
const auto CAN_USE_WINDOW = pWindow && main;
|
||||
const auto WINDOW_SIZE_MISALIGN = CAN_USE_WINDOW && pWindow->getReportedSize() != pWindow->wlSurface()->resource()->m_current.size;
|
||||
|
||||
if (pSurface->m_current.viewport.hasDestination)
|
||||
return (pSurface->m_current.viewport.destination * pMonitor->m_scale).round();
|
||||
|
||||
if (pSurface->m_current.viewport.hasSource)
|
||||
return (pSurface->m_current.viewport.source.size() * pMonitor->m_scale).round();
|
||||
|
||||
if (WINDOW_SIZE_MISALIGN)
|
||||
return (pSurface->m_current.size * pMonitor->m_scale).round();
|
||||
|
||||
if (CAN_USE_WINDOW)
|
||||
return (pWindow->getReportedSize() * pMonitor->m_scale).round();
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void IElementRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, PHLMONITOR pMonitor, bool main, const Vector2D& projSize,
|
||||
const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) {
|
||||
auto& m_renderData = g_pHyprRenderer->m_renderData;
|
||||
|
||||
if (!pWindow || !pWindow->m_isX11) {
|
||||
static auto PEXPANDEDGES = CConfigValue<Hyprlang::INT>("render:expand_undersized_textures");
|
||||
|
||||
Vector2D uvTL;
|
||||
Vector2D uvBR = Vector2D(1, 1);
|
||||
|
||||
if (pSurface->m_current.viewport.hasSource) {
|
||||
// we stretch it to dest. if no dest, to 1,1
|
||||
Vector2D const& bufferSize = pSurface->m_current.bufferSize;
|
||||
auto const& bufferSource = pSurface->m_current.viewport.source;
|
||||
|
||||
// calculate UV for the basic src_box. Assume dest == size. Scale to dest later
|
||||
uvTL = Vector2D(bufferSource.x / bufferSize.x, bufferSource.y / bufferSize.y);
|
||||
uvBR = Vector2D((bufferSource.x + bufferSource.width) / bufferSize.x, (bufferSource.y + bufferSource.height) / bufferSize.y);
|
||||
|
||||
if (uvBR.x < 0.01f || uvBR.y < 0.01f) {
|
||||
uvTL = Vector2D();
|
||||
uvBR = Vector2D(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (projSize != Vector2D{} && fixMisalignedFSV1) {
|
||||
// instead of nearest_neighbor (we will repeat / skip)
|
||||
// just cut off / expand surface
|
||||
const Vector2D PIXELASUV = Vector2D{1, 1} / pSurface->m_current.bufferSize;
|
||||
const auto& BUFFER_SIZE = pSurface->m_current.bufferSize;
|
||||
|
||||
// compute MISALIGN from the adjusted UV coordinates.
|
||||
const Vector2D MISALIGNMENT = (uvBR - uvTL) * BUFFER_SIZE - projSize;
|
||||
|
||||
if (MISALIGNMENT != Vector2D{})
|
||||
uvBR -= MISALIGNMENT * PIXELASUV;
|
||||
} else {
|
||||
// if the surface is smaller than our viewport, extend its edges.
|
||||
// this will break if later on xdg geometry is hit, but we really try
|
||||
// to let the apps know to NOT add CSD. Also if source is there.
|
||||
// there is no way to fix this if that's the case
|
||||
const auto MONITOR_WL_SCALE = std::ceil(pMonitor->m_scale);
|
||||
const bool SCALE_UNAWARE = pMonitor->m_scale != 1.f && (MONITOR_WL_SCALE == pSurface->m_current.scale || !pSurface->m_current.viewport.hasDestination);
|
||||
const auto EXPECTED_SIZE = getSurfaceExpectedSize(pWindow, pSurface, pMonitor, main).value_or((projSize * pMonitor->m_scale).round());
|
||||
|
||||
const auto RATIO = projSize / EXPECTED_SIZE;
|
||||
if (!SCALE_UNAWARE || MONITOR_WL_SCALE == 1) {
|
||||
if (*PEXPANDEDGES && !SCALE_UNAWARE && (RATIO.x > 1 || RATIO.y > 1)) {
|
||||
const auto FIX = RATIO.clamp(Vector2D{1, 1}, Vector2D{1000000, 1000000});
|
||||
uvBR = uvBR * FIX;
|
||||
}
|
||||
|
||||
// FIXME: probably do this for in anims on all views...
|
||||
const auto SHOULD_SKIP = !pWindow || pWindow->m_animatingIn;
|
||||
if (!SHOULD_SKIP && (RATIO.x < 1 || RATIO.y < 1)) {
|
||||
const auto FIX = RATIO.clamp(Vector2D{0.0001, 0.0001}, Vector2D{1, 1});
|
||||
uvBR = uvBR * FIX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_renderData.primarySurfaceUVTopLeft = uvTL;
|
||||
m_renderData.primarySurfaceUVBottomRight = uvBR;
|
||||
|
||||
if (m_renderData.primarySurfaceUVTopLeft == Vector2D() && m_renderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
|
||||
// No special UV mods needed
|
||||
m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
|
||||
if (!main || !pWindow)
|
||||
return;
|
||||
|
||||
// FIXME: this doesn't work. We always set MAXIMIZED anyways, so this doesn't need to work, but it's problematic.
|
||||
|
||||
// CBox geom = pWindow->m_xdgSurface->m_current.geometry;
|
||||
|
||||
// // Adjust UV based on the xdg_surface geometry
|
||||
// if (geom.x != 0 || geom.y != 0 || geom.w != 0 || geom.h != 0) {
|
||||
// const auto XPERC = geom.x / pSurface->m_current.size.x;
|
||||
// const auto YPERC = geom.y / pSurface->m_current.size.y;
|
||||
// const auto WPERC = (geom.x + geom.w ? geom.w : pSurface->m_current.size.x) / pSurface->m_current.size.x;
|
||||
// const auto HPERC = (geom.y + geom.h ? geom.h : pSurface->m_current.size.y) / pSurface->m_current.size.y;
|
||||
|
||||
// const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y));
|
||||
// uvBR = uvBR - Vector2D((1.0 - WPERC) * (uvBR.x - uvTL.x), (1.0 - HPERC) * (uvBR.y - uvTL.y));
|
||||
// uvTL = uvTL + TOADDTL;
|
||||
// }
|
||||
|
||||
m_renderData.primarySurfaceUVTopLeft = uvTL;
|
||||
m_renderData.primarySurfaceUVBottomRight = uvBR;
|
||||
|
||||
if (m_renderData.primarySurfaceUVTopLeft == Vector2D() && m_renderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
|
||||
// No special UV mods needed
|
||||
m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
} else {
|
||||
m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void IElementRenderer::drawRect(WP<CRectPassElement> element, const CRegion& damage) {
|
||||
auto& data = element->m_data;
|
||||
auto& m_renderData = g_pHyprRenderer->m_renderData;
|
||||
|
||||
if (data.box.w <= 0 || data.box.h <= 0)
|
||||
return;
|
||||
|
||||
if (!data.clipBox.empty())
|
||||
m_renderData.clipBox = data.clipBox;
|
||||
|
||||
data.modifiedBox = data.box;
|
||||
m_renderData.renderModif.applyToBox(data.modifiedBox);
|
||||
|
||||
CBox transformedBox = data.box;
|
||||
transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x,
|
||||
m_renderData.pMonitor->m_transformedSize.y);
|
||||
|
||||
data.TOPLEFT[0] = sc<float>(transformedBox.x);
|
||||
data.TOPLEFT[1] = sc<float>(transformedBox.y);
|
||||
data.FULLSIZE[0] = sc<float>(transformedBox.width);
|
||||
data.FULLSIZE[1] = sc<float>(transformedBox.height);
|
||||
|
||||
data.drawRegion = data.color.a == 1.F || !data.blur ? damage : m_renderData.damage;
|
||||
|
||||
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};
|
||||
data.drawRegion = damageClip.intersect(data.drawRegion);
|
||||
}
|
||||
|
||||
draw(element, damage);
|
||||
|
||||
m_renderData.clipBox = {};
|
||||
}
|
||||
|
||||
void IElementRenderer::drawHints(WP<CRendererHintsPassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
if (m_data.renderModif.has_value())
|
||||
g_pHyprRenderer->m_renderData.renderModif = *m_data.renderModif;
|
||||
}
|
||||
|
||||
void IElementRenderer::drawPreBlur(WP<CPreBlurElement> element, const CRegion& damage) {
|
||||
TRACY_GPU_ZONE("RenderPreBlurForCurrentMonitor");
|
||||
auto& m_renderData = g_pHyprRenderer->m_renderData;
|
||||
|
||||
const auto SAVEDRENDERMODIF = m_renderData.renderModif;
|
||||
m_renderData.renderModif = {}; // fix shit
|
||||
|
||||
// make the fake dmg
|
||||
CRegion fakeDamage{0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y};
|
||||
|
||||
draw(element, fakeDamage);
|
||||
|
||||
m_renderData.pMonitor->m_blurFBDirty = false;
|
||||
m_renderData.pMonitor->m_blurFBShouldRender = false;
|
||||
|
||||
m_renderData.renderModif = SAVEDRENDERMODIF;
|
||||
}
|
||||
|
||||
void IElementRenderer::drawSurface(WP<CSurfacePassElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
auto& m_renderData = g_pHyprRenderer->m_renderData;
|
||||
|
||||
Hyprutils::Utils::CScopeGuard x = {[]() {
|
||||
g_pHyprRenderer->m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
g_pHyprRenderer->m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}};
|
||||
|
||||
if (!m_data.texture)
|
||||
return;
|
||||
|
||||
const auto& TEXTURE = m_data.texture;
|
||||
|
||||
// this is bad, probably has been logged elsewhere. Means the texture failed
|
||||
// uploading to the GPU.
|
||||
if (!TEXTURE->ok())
|
||||
return;
|
||||
|
||||
const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_layoutManager->dragController()->target() && g_layoutManager->dragController()->mode() == MBIND_RESIZE;
|
||||
TRACY_GPU_ZONE("RenderSurface");
|
||||
|
||||
auto PSURFACE = Desktop::View::CWLSurface::fromResource(m_data.surface);
|
||||
|
||||
const float ALPHA = m_data.alpha * m_data.fadeAlpha * (PSURFACE ? PSURFACE->m_alphaModifier : 1.F);
|
||||
const float OVERALL_ALPHA = PSURFACE ? PSURFACE->m_overallOpacity : 1.F;
|
||||
const bool BLUR = m_data.blur && (!TEXTURE->m_opaque || ALPHA < 1.F || OVERALL_ALPHA < 1.F);
|
||||
|
||||
auto windowBox = element->getTexBox();
|
||||
|
||||
const auto PROJSIZEUNSCALED = windowBox.size();
|
||||
|
||||
windowBox.scale(m_data.pMonitor->m_scale);
|
||||
windowBox.round();
|
||||
|
||||
if (windowBox.width <= 1 || windowBox.height <= 1) {
|
||||
element->discard();
|
||||
return;
|
||||
}
|
||||
|
||||
const bool MISALIGNEDFSV1 = std::floor(m_data.pMonitor->m_scale) != m_data.pMonitor->m_scale /* Fractional */ && m_data.surface->m_current.scale == 1 /* fs protocol */ &&
|
||||
windowBox.size() != m_data.surface->m_current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, m_data.surface->m_current.bufferSize.x, 3) &&
|
||||
DELTALESSTHAN(windowBox.height, m_data.surface->m_current.bufferSize.y, 3) /* off by one-or-two */ &&
|
||||
(!m_data.pWindow || (!m_data.pWindow->m_realSize->isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */ &&
|
||||
(!m_data.pLS || (!m_data.pLS->m_realSize->isBeingAnimated())); /* not LS or not animated */
|
||||
|
||||
calculateUVForSurface(m_data.pWindow, m_data.surface, m_data.pMonitor->m_self.lock(), m_data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1);
|
||||
|
||||
auto cancelRender = false;
|
||||
auto clipRegion = element->visibleRegion(cancelRender);
|
||||
if (cancelRender)
|
||||
return;
|
||||
|
||||
// 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)
|
||||
m_renderData.useNearestNeighbor = true;
|
||||
|
||||
float rounding = m_data.rounding;
|
||||
float roundingPower = m_data.roundingPower;
|
||||
|
||||
rounding -= 1; // to fix a border issue
|
||||
|
||||
if (m_data.dontRound) {
|
||||
rounding = 0;
|
||||
roundingPower = 2.0f;
|
||||
}
|
||||
|
||||
const bool WINDOWOPAQUE = m_data.pWindow && m_data.pWindow->wlSurface()->resource() == m_data.surface ? m_data.pWindow->opaque() : false;
|
||||
const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding <= 0 && WINDOWOPAQUE;
|
||||
|
||||
if (CANDISABLEBLEND)
|
||||
g_pHyprRenderer->blend(false);
|
||||
else
|
||||
g_pHyprRenderer->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 (m_data.surfaceCounter == 0 && !m_data.popup) {
|
||||
if (BLUR)
|
||||
drawElement(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA,
|
||||
.blurA = m_data.fadeAlpha,
|
||||
.overallA = OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.blur = true,
|
||||
.blockBlurOptimization = m_data.blockBlurOptimization,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
else
|
||||
drawElement(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA * OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.discardActive = false,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
} else {
|
||||
if (BLUR && m_data.popup)
|
||||
drawElement(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA,
|
||||
.blurA = m_data.fadeAlpha,
|
||||
.overallA = OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.blur = true,
|
||||
.blockBlurOptimization = true,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
else
|
||||
drawElement(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA * OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.discardActive = false,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
}
|
||||
|
||||
g_pHyprRenderer->blend(true);
|
||||
};
|
||||
|
||||
void IElementRenderer::preDrawSurface(WP<CSurfacePassElement> element, const CRegion& damage) {
|
||||
auto& m_renderData = g_pHyprRenderer->m_renderData;
|
||||
m_renderData.clipBox = element->m_data.clipBox;
|
||||
m_renderData.useNearestNeighbor = element->m_data.useNearestNeighbor;
|
||||
g_pHyprRenderer->pushMonitorTransformEnabled(element->m_data.flipEndFrame);
|
||||
m_renderData.currentWindow = element->m_data.pWindow;
|
||||
|
||||
drawSurface(element, damage);
|
||||
|
||||
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)
|
||||
element->m_data.surface->presentFeedback(element->m_data.when, element->m_data.pMonitor->m_self.lock());
|
||||
|
||||
// add async (dmabuf) buffers to usedBuffers so we can handle release later
|
||||
// sync (shm) buffers will be released in commitState, so no need to track them here
|
||||
if (element->m_data.surface->m_current.buffer && !element->m_data.surface->m_current.buffer->isSynchronous())
|
||||
g_pHyprRenderer->m_usedAsyncBuffers.emplace_back(element->m_data.surface->m_current.buffer);
|
||||
|
||||
m_renderData.clipBox = {};
|
||||
m_renderData.useNearestNeighbor = false;
|
||||
g_pHyprRenderer->popMonitorTransformEnabled();
|
||||
m_renderData.currentWindow.reset();
|
||||
}
|
||||
|
||||
void IElementRenderer::drawTex(WP<CTexPassElement> element, const CRegion& damage) {
|
||||
auto& m_renderData = g_pHyprRenderer->m_renderData;
|
||||
if (!element->m_data.clipBox.empty())
|
||||
m_renderData.clipBox = element->m_data.clipBox;
|
||||
|
||||
g_pHyprRenderer->pushMonitorTransformEnabled(element->m_data.flipEndFrame);
|
||||
if (element->m_data.useMirrorProjection)
|
||||
g_pHyprRenderer->setProjectionType(RPT_MIRROR);
|
||||
|
||||
m_renderData.surface = element->m_data.surface;
|
||||
|
||||
Hyprutils::Utils::CScopeGuard x = {[useMirrorProjection = element->m_data.useMirrorProjection]() {
|
||||
g_pHyprRenderer->popMonitorTransformEnabled();
|
||||
if (useMirrorProjection)
|
||||
g_pHyprRenderer->setProjectionType(RPT_MONITOR);
|
||||
g_pHyprRenderer->m_renderData.surface.reset();
|
||||
}};
|
||||
|
||||
if (element->m_data.blur) {
|
||||
// make a damage region for this window
|
||||
CRegion texDamage{m_renderData.damage};
|
||||
texDamage.intersect(element->m_data.box.x, element->m_data.box.y, element->m_data.box.width, element->m_data.box.height);
|
||||
|
||||
// While renderTextureInternalWithDamage will clip the blur as well,
|
||||
// clipping texDamage here allows blur generation to be optimized.
|
||||
if (!element->m_data.clipRegion.empty())
|
||||
texDamage.intersect(element->m_data.clipRegion);
|
||||
|
||||
if (texDamage.empty())
|
||||
return;
|
||||
|
||||
m_renderData.renderModif.applyToRegion(texDamage);
|
||||
|
||||
element->m_data.damage = texDamage;
|
||||
|
||||
// amazing hack: the surface has an opaque region!
|
||||
const auto& surface = element->m_data.surface;
|
||||
const auto& box = element->m_data.box;
|
||||
CRegion inverseOpaque;
|
||||
if (element->m_data.a >= 1.f && surface && std::round(surface->m_current.size.x * m_renderData.pMonitor->m_scale) == box.w &&
|
||||
std::round(surface->m_current.size.y * m_renderData.pMonitor->m_scale) == box.h) {
|
||||
pixman_box32_t surfbox = {0, 0, surface->m_current.size.x * surface->m_current.scale, surface->m_current.size.y * surface->m_current.scale};
|
||||
inverseOpaque = surface->m_current.opaque;
|
||||
inverseOpaque.invert(&surfbox).intersect(0, 0, surface->m_current.size.x * surface->m_current.scale, surface->m_current.size.y * surface->m_current.scale);
|
||||
|
||||
if (inverseOpaque.empty()) {
|
||||
element->m_data.blur = false;
|
||||
draw(element, damage);
|
||||
m_renderData.clipBox = {};
|
||||
return;
|
||||
}
|
||||
} else
|
||||
inverseOpaque = {0, 0, element->m_data.box.width, element->m_data.box.height};
|
||||
|
||||
inverseOpaque.scale(m_renderData.pMonitor->m_scale);
|
||||
element->m_data.blockBlurOptimization = element->m_data.blockBlurOptimization.value_or(false) ||
|
||||
!g_pHyprRenderer->shouldUseNewBlurOptimizations(element->m_data.currentLS.lock(), m_renderData.currentWindow.lock());
|
||||
|
||||
// vvv TODO: layered blur fbs?
|
||||
if (element->m_data.blockBlurOptimization) {
|
||||
inverseOpaque.translate(box.pos());
|
||||
m_renderData.renderModif.applyToRegion(inverseOpaque);
|
||||
inverseOpaque.intersect(element->m_data.damage);
|
||||
element->m_data.blurredBG = g_pHyprRenderer->blurMainFramebuffer(element->m_data.a, &inverseOpaque);
|
||||
m_renderData.currentFB->bind();
|
||||
} else
|
||||
element->m_data.blurredBG = m_renderData.pMonitor->m_blurFB ? m_renderData.pMonitor->m_blurFB->getTexture() : nullptr;
|
||||
|
||||
draw(element, damage);
|
||||
} else
|
||||
draw(element, damage);
|
||||
|
||||
m_renderData.clipBox = {};
|
||||
}
|
||||
|
||||
void IElementRenderer::drawTexMatte(WP<CTextureMatteElement> element, const CRegion& damage) {
|
||||
if (g_pHyprRenderer->m_renderData.damage.empty())
|
||||
return;
|
||||
|
||||
const auto m_data = element->m_data;
|
||||
if (m_data.disableTransformAndModify) {
|
||||
g_pHyprRenderer->pushMonitorTransformEnabled(true);
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = false;
|
||||
draw(element, damage);
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = true;
|
||||
g_pHyprRenderer->popMonitorTransformEnabled();
|
||||
} else
|
||||
draw(element, damage);
|
||||
}
|
||||
45
src/render/ElementRenderer.hpp
Normal file
45
src/render/ElementRenderer.hpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "./pass/BorderPassElement.hpp"
|
||||
#include "./pass/ClearPassElement.hpp"
|
||||
#include "./pass/FramebufferElement.hpp"
|
||||
#include "./pass/PreBlurElement.hpp"
|
||||
#include "./pass/RectPassElement.hpp"
|
||||
#include "./pass/RendererHintsPassElement.hpp"
|
||||
#include "./pass/ShadowPassElement.hpp"
|
||||
#include "./pass/SurfacePassElement.hpp"
|
||||
#include "./pass/TexPassElement.hpp"
|
||||
#include "./pass/TextureMatteElement.hpp"
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
|
||||
namespace Render {
|
||||
class IElementRenderer {
|
||||
public:
|
||||
IElementRenderer() = default;
|
||||
virtual ~IElementRenderer() = default;
|
||||
|
||||
void drawElement(WP<IPassElement> element, const CRegion& damage);
|
||||
|
||||
protected:
|
||||
virtual void draw(WP<CBorderPassElement> element, const CRegion& damage) = 0;
|
||||
virtual void draw(WP<CClearPassElement> element, const CRegion& damage) = 0;
|
||||
virtual void draw(WP<CFramebufferElement> element, const CRegion& damage) = 0;
|
||||
virtual void draw(WP<CPreBlurElement> element, const CRegion& damage) = 0;
|
||||
virtual void draw(WP<CRectPassElement> element, const CRegion& damage) = 0;
|
||||
virtual void draw(WP<CShadowPassElement> element, const CRegion& damage) = 0;
|
||||
virtual void draw(WP<CTexPassElement> element, const CRegion& damage) = 0;
|
||||
virtual void draw(WP<CTextureMatteElement> element, const CRegion& damage) = 0;
|
||||
|
||||
private:
|
||||
void calculateUVForSurface(PHLWINDOW, SP<CWLSurfaceResource>, PHLMONITOR pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {},
|
||||
bool fixMisalignedFSV1 = false);
|
||||
|
||||
void drawRect(WP<CRectPassElement> element, const CRegion& damage);
|
||||
void drawHints(WP<CRendererHintsPassElement> element, const CRegion& damage);
|
||||
void drawPreBlur(WP<CPreBlurElement> element, const CRegion& damage);
|
||||
void drawSurface(WP<CSurfacePassElement> element, const CRegion& damage);
|
||||
void preDrawSurface(WP<CSurfacePassElement> element, const CRegion& damage);
|
||||
void drawTex(WP<CTexPassElement> element, const CRegion& damage);
|
||||
void drawTexMatte(WP<CTextureMatteElement> element, const CRegion& damage);
|
||||
};
|
||||
}
|
||||
|
|
@ -11,30 +11,37 @@
|
|||
#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 "OpenGL.hpp"
|
||||
#include "Renderer.hpp"
|
||||
#include "gl/GLFramebuffer.hpp"
|
||||
#include "gl/GLTexture.hpp"
|
||||
#include "decorations/CHyprDropShadowDecoration.hpp"
|
||||
#include "./gl/GLElementRenderer.hpp"
|
||||
#include "./gl/GLFramebuffer.hpp"
|
||||
#include "./gl/GLTexture.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <hyprutils/memory/SharedPtr.hpp>
|
||||
#include <hyprutils/memory/UniquePtr.hpp>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
using namespace Hyprutils::Utils;
|
||||
using namespace Hyprutils::OS;
|
||||
using enum NContentType::eContentType;
|
||||
using namespace NColorManagement;
|
||||
using namespace Render;
|
||||
using namespace Render::GL;
|
||||
|
||||
extern "C" {
|
||||
#include <xf86drm.h>
|
||||
}
|
||||
|
||||
CHyprGLRenderer::CHyprGLRenderer() : IHyprRenderer() {}
|
||||
CHyprGLRenderer::CHyprGLRenderer() : IHyprRenderer() {
|
||||
m_elementRenderer = makeUnique<CGLElementRenderer>();
|
||||
}
|
||||
|
||||
CHyprGLRenderer::~CHyprGLRenderer() {
|
||||
m_elementRenderer.reset();
|
||||
}
|
||||
|
||||
void CHyprGLRenderer::initRender() {
|
||||
g_pHyprOpenGL->makeEGLCurrent();
|
||||
|
|
@ -281,118 +288,6 @@ 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) {
|
||||
if (!pMonitor->m_blurFB)
|
||||
return nullptr;
|
||||
|
|
@ -405,3 +300,7 @@ void CHyprGLRenderer::unsetEGL() {
|
|||
|
||||
eglMakeCurrent(g_pHyprOpenGL->m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
WP<IElementRenderer> CHyprGLRenderer::elementRenderer() {
|
||||
return m_elementRenderer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "Renderer.hpp"
|
||||
#include "render/ElementRenderer.hpp"
|
||||
|
||||
class CHyprGLRenderer : public IHyprRenderer {
|
||||
public:
|
||||
CHyprGLRenderer();
|
||||
namespace Render::GL {
|
||||
class CHyprGLRenderer : public Render::IHyprRenderer {
|
||||
public:
|
||||
CHyprGLRenderer();
|
||||
~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 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();
|
||||
void unsetEGL();
|
||||
WP<IElementRenderer> elementRenderer() override;
|
||||
|
||||
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;
|
||||
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<ITexture> getBlurTexture(PHLMONITORREF pMonitor) override;
|
||||
SP<IRenderbuffer> m_currentRenderbuffer;
|
||||
UP<IElementRenderer> m_elementRenderer;
|
||||
|
||||
SP<IRenderbuffer> m_currentRenderbuffer = nullptr;
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
};
|
||||
friend class CHyprOpenGLImpl;
|
||||
};
|
||||
}
|
||||
|
|
@ -60,6 +60,7 @@
|
|||
using namespace Hyprutils::OS;
|
||||
using namespace NColorManagement;
|
||||
using namespace Render;
|
||||
using namespace Render::GL;
|
||||
|
||||
static inline void loadGLProc(void* pProc, const char* name) {
|
||||
void* proc = rc<void*>(eglGetProcAddress(name));
|
||||
|
|
@ -951,21 +952,6 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) {
|
|||
uniformRequireNoDamage(SHADER_POINTER_SHAPE_PREVIOUS, "pointer_shape_previous");
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::clear(const CHyprColor& color) {
|
||||
RASSERT(g_pHyprRenderer->m_renderData.pMonitor, "Tried to render without begin()!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderClear");
|
||||
|
||||
GLCALL(glClearColor(color.r, color.g, color.b, color.a));
|
||||
|
||||
if (!g_pHyprRenderer->m_renderData.damage.empty()) {
|
||||
g_pHyprRenderer->m_renderData.damage.forEachRect([this](const auto& RECT) {
|
||||
scissor(&RECT, g_pHyprRenderer->m_renderData.transformDamage);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::blend(bool enabled) {
|
||||
if (enabled) {
|
||||
setCapStatus(GL_BLEND, true);
|
||||
|
|
@ -1446,7 +1432,7 @@ WP<CShader> CHyprOpenGLImpl::renderToFBInternal(const STextureRenderData& data,
|
|||
|
||||
void CHyprOpenGLImpl::renderTextureInternal(SP<ITexture> tex, const CBox& box, const STextureRenderData& data) {
|
||||
RASSERT(g_pHyprRenderer->m_renderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex->ok()), "Attempted to draw nullptr texture!");
|
||||
RASSERT((tex && tex->ok()), "Attempted to draw nullptr texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureInternalWithDamage");
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include "types.hpp"
|
||||
#include "Shader.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
|
|
@ -40,342 +41,326 @@
|
|||
#define GLFB(ifb) dc<CGLFramebuffer*>(ifb.get())
|
||||
|
||||
struct gbm_device;
|
||||
class IHyprRenderer;
|
||||
|
||||
namespace Config {
|
||||
class CGradientValueData;
|
||||
namespace Render {
|
||||
class IHyprRenderer;
|
||||
}
|
||||
class CGradientValueData;
|
||||
|
||||
struct SVertex {
|
||||
float x, y; // position
|
||||
float u, v; // uv
|
||||
};
|
||||
namespace Render::GL {
|
||||
|
||||
constexpr std::array<SVertex, 4> fullVerts = {{
|
||||
{0.0f, 0.0f, 0.0f, 0.0f}, // top-left
|
||||
{0.0f, 1.0f, 0.0f, 1.0f}, // bottom-left
|
||||
{1.0f, 0.0f, 1.0f, 0.0f}, // top-right
|
||||
{1.0f, 1.0f, 1.0f, 1.0f}, // bottom-right
|
||||
}};
|
||||
|
||||
inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f};
|
||||
|
||||
struct SRenderModifData {
|
||||
enum eRenderModifType : uint8_t {
|
||||
RMOD_TYPE_SCALE, /* scale by a float */
|
||||
RMOD_TYPE_SCALECENTER, /* scale by a float from the center */
|
||||
RMOD_TYPE_TRANSLATE, /* translate by a Vector2D */
|
||||
RMOD_TYPE_ROTATE, /* rotate by a float in rad from top left */
|
||||
RMOD_TYPE_ROTATECENTER, /* rotate by a float in rad from center */
|
||||
struct SVertex {
|
||||
float x, y; // position
|
||||
float u, v; // uv
|
||||
};
|
||||
|
||||
std::vector<std::pair<eRenderModifType, std::any>> modifs;
|
||||
constexpr std::array<SVertex, 4> fullVerts = {{
|
||||
{0.0f, 0.0f, 0.0f, 0.0f}, // top-left
|
||||
{0.0f, 1.0f, 0.0f, 1.0f}, // bottom-left
|
||||
{1.0f, 0.0f, 1.0f, 0.0f}, // top-right
|
||||
{1.0f, 1.0f, 1.0f, 1.0f}, // bottom-right
|
||||
}};
|
||||
|
||||
void applyToBox(CBox& box);
|
||||
void applyToRegion(CRegion& rg);
|
||||
float combinedScale();
|
||||
inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f};
|
||||
|
||||
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 SFragShaderDesc {
|
||||
Render::ePreparedFragmentShader id;
|
||||
const char* file;
|
||||
};
|
||||
|
||||
struct SPreparedShaders {
|
||||
// SPreparedShaders() {
|
||||
// for (auto& f : frag) {
|
||||
// f = makeShared<CShader>();
|
||||
// }
|
||||
// }
|
||||
|
||||
std::string TEXVERTSRC;
|
||||
std::string TEXVERTSRC320;
|
||||
// std::array<SP<CShader>, SH_FRAG_LAST> frag;
|
||||
// std::map<uint8_t, SP<CShader>> fragVariants;
|
||||
std::array<std::map<Render::ShaderFeatureFlags, SP<CShader>>, Render::SH_FRAG_LAST> fragVariants;
|
||||
};
|
||||
|
||||
struct SCurrentRenderData {
|
||||
PHLMONITORREF pMonitor;
|
||||
Mat3x3 projection;
|
||||
Mat3x3 savedProjection;
|
||||
Mat3x3 monitorProjection;
|
||||
|
||||
SP<IFramebuffer> currentFB = nullptr; // current rendering to
|
||||
SP<IFramebuffer> mainFB = nullptr; // main to render to
|
||||
SP<IFramebuffer> outFB = nullptr; // out to render to (if offloaded, etc)
|
||||
|
||||
CRegion damage;
|
||||
CRegion finalDamage; // damage used for funal off -> main
|
||||
|
||||
SRenderModifData renderModif;
|
||||
float mouseZoomFactor = 1.f;
|
||||
bool mouseZoomUseMouse = true; // true by default
|
||||
bool useNearestNeighbor = false;
|
||||
bool blockScreenShader = false;
|
||||
bool simplePass = false;
|
||||
bool transformDamage = true;
|
||||
bool noSimplify = false;
|
||||
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
|
||||
CBox clipBox = {}; // scaled coordinates
|
||||
CRegion clipRegion;
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
PHLLSREF currentLS;
|
||||
PHLWINDOWREF currentWindow;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
};
|
||||
|
||||
class CEGLSync {
|
||||
public:
|
||||
static UP<CEGLSync> create();
|
||||
|
||||
~CEGLSync();
|
||||
|
||||
Hyprutils::OS::CFileDescriptor& fd();
|
||||
Hyprutils::OS::CFileDescriptor&& takeFd();
|
||||
bool isValid();
|
||||
|
||||
private:
|
||||
CEGLSync() = default;
|
||||
|
||||
Hyprutils::OS::CFileDescriptor m_fd;
|
||||
EGLSyncKHR m_sync = EGL_NO_SYNC_KHR;
|
||||
bool m_valid = false;
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
};
|
||||
|
||||
class CHyprOpenGLImpl {
|
||||
public:
|
||||
CHyprOpenGLImpl();
|
||||
~CHyprOpenGLImpl();
|
||||
|
||||
struct SRectRenderData {
|
||||
const CRegion* damage = nullptr;
|
||||
int round = 0;
|
||||
float roundingPower = 2.F;
|
||||
bool blur = false;
|
||||
float blurA = 1.F;
|
||||
bool xray = false;
|
||||
enum eMonitorRenderFBs : uint8_t {
|
||||
FB_MONITOR_RENDER_MAIN = 0,
|
||||
FB_MONITOR_RENDER_CURRENT = 1,
|
||||
FB_MONITOR_RENDER_OUT = 2,
|
||||
};
|
||||
|
||||
struct STextureRenderData {
|
||||
bool blur = false;
|
||||
float blurA = 1.F, overallA = 1.F;
|
||||
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 finalMonitorCM = false;
|
||||
SP<CMonitor> cmBackToSRGBSource;
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
CRegion clipRegion;
|
||||
PHLLSREF currentLS;
|
||||
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
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 SBorderRenderData {
|
||||
int round = 0;
|
||||
float roundingPower = 2.F;
|
||||
int borderSize = 1;
|
||||
float a = 1.0;
|
||||
int outerRound = -1; /* use round */
|
||||
struct SFragShaderDesc {
|
||||
Render::ePreparedFragmentShader id;
|
||||
const char* file;
|
||||
};
|
||||
|
||||
void makeEGLCurrent();
|
||||
void begin(PHLMONITOR, const CRegion& damage, SP<IFramebuffer> fb = nullptr, std::optional<CRegion> finalDamage = {});
|
||||
void beginSimple(PHLMONITOR, const CRegion& damage, SP<IRenderbuffer> rb = nullptr, SP<IFramebuffer> fb = nullptr);
|
||||
void end();
|
||||
struct SPreparedShaders {
|
||||
// SPreparedShaders() {
|
||||
// for (auto& f : frag) {
|
||||
// f = makeShared<CShader>();
|
||||
// }
|
||||
// }
|
||||
|
||||
void renderRect(const CBox&, const CHyprColor&, SRectRenderData data);
|
||||
void renderTexture(SP<ITexture>, const CBox&, STextureRenderData data);
|
||||
void renderRoundedShadow(const CBox&, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0);
|
||||
void renderBorder(const CBox&, const Config::CGradientValueData&, SBorderRenderData data);
|
||||
void renderBorder(const CBox&, const Config::CGradientValueData&, const Config::CGradientValueData&, float lerp, SBorderRenderData data);
|
||||
void renderTextureMatte(SP<ITexture> tex, const CBox& pBox, SP<IFramebuffer> matte);
|
||||
void renderTexturePrimitive(SP<ITexture> tex, const CBox& box);
|
||||
|
||||
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 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 preRender(PHLMONITOR);
|
||||
|
||||
void saveBufferForMirror(const CBox&);
|
||||
|
||||
void applyScreenShader(const std::string& path);
|
||||
|
||||
void renderOffToMain(IFramebuffer* off);
|
||||
|
||||
std::vector<SDRMFormat> getDRMFormats();
|
||||
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
|
||||
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
||||
|
||||
bool initShaders(const std::string& path = "");
|
||||
|
||||
WP<CShader> useShader(WP<CShader> prog);
|
||||
|
||||
bool explicitSyncSupported();
|
||||
WP<CShader> getShaderVariant(Render::ePreparedFragmentShader frag, Render::ShaderFeatureFlags features = 0);
|
||||
|
||||
bool m_shadersInitialized = false;
|
||||
SP<SPreparedShaders> m_shaders;
|
||||
|
||||
Hyprutils::OS::CFileDescriptor m_gbmFD;
|
||||
gbm_device* m_gbmDevice = nullptr;
|
||||
EGLContext m_eglContext = nullptr;
|
||||
EGLDisplay m_eglDisplay = nullptr;
|
||||
EGLDeviceEXT m_eglDevice = nullptr;
|
||||
|
||||
std::map<PHLMONITORREF, SP<IFramebuffer>> m_monitorBGFBs;
|
||||
|
||||
struct {
|
||||
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
|
||||
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr;
|
||||
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = nullptr;
|
||||
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
|
||||
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr;
|
||||
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = nullptr;
|
||||
PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR = nullptr;
|
||||
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = nullptr;
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = nullptr;
|
||||
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT = nullptr;
|
||||
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR = nullptr;
|
||||
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = nullptr;
|
||||
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID = nullptr;
|
||||
PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR = nullptr;
|
||||
} m_proc;
|
||||
|
||||
struct {
|
||||
bool EXT_read_format_bgra = false;
|
||||
bool EXT_image_dma_buf_import = false;
|
||||
bool EXT_image_dma_buf_import_modifiers = false;
|
||||
bool KHR_context_flush_control = false;
|
||||
bool KHR_display_reference = false;
|
||||
bool IMG_context_priority = false;
|
||||
bool EXT_create_context_robustness = false;
|
||||
bool EGL_ANDROID_native_fence_sync_ext = false;
|
||||
} m_exts;
|
||||
|
||||
enum eEGLContextVersion : uint8_t {
|
||||
EGL_CONTEXT_GLES_2_0 = 0,
|
||||
EGL_CONTEXT_GLES_3_0,
|
||||
EGL_CONTEXT_GLES_3_2,
|
||||
std::string TEXVERTSRC;
|
||||
std::string TEXVERTSRC320;
|
||||
// std::array<SP<CShader>, SH_FRAG_LAST> frag;
|
||||
// std::map<uint8_t, SP<CShader>> fragVariants;
|
||||
std::array<std::map<Render::ShaderFeatureFlags, SP<CShader>>, Render::SH_FRAG_LAST> fragVariants;
|
||||
};
|
||||
|
||||
eEGLContextVersion m_eglContextVersion = EGL_CONTEXT_GLES_3_2;
|
||||
struct SCurrentRenderData {
|
||||
PHLMONITORREF pMonitor;
|
||||
Mat3x3 projection;
|
||||
Mat3x3 savedProjection;
|
||||
Mat3x3 monitorProjection;
|
||||
|
||||
enum eCachedCapStatus : uint8_t {
|
||||
CAP_STATUS_BLEND = 0,
|
||||
CAP_STATUS_SCISSOR_TEST,
|
||||
CAP_STATUS_STENCIL_TEST,
|
||||
CAP_STATUS_END
|
||||
SP<IFramebuffer> currentFB = nullptr; // current rendering to
|
||||
SP<IFramebuffer> mainFB = nullptr; // main to render to
|
||||
SP<IFramebuffer> outFB = nullptr; // out to render to (if offloaded, etc)
|
||||
|
||||
CRegion damage;
|
||||
CRegion finalDamage; // damage used for funal off -> main
|
||||
|
||||
Render::SRenderModifData renderModif;
|
||||
float mouseZoomFactor = 1.f;
|
||||
bool mouseZoomUseMouse = true; // true by default
|
||||
bool useNearestNeighbor = false;
|
||||
bool blockScreenShader = false;
|
||||
bool simplePass = false;
|
||||
bool transformDamage = true;
|
||||
bool noSimplify = false;
|
||||
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
|
||||
CBox clipBox = {}; // scaled coordinates
|
||||
CRegion clipRegion;
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
PHLLSREF currentLS;
|
||||
PHLWINDOWREF currentWindow;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
};
|
||||
|
||||
private:
|
||||
struct {
|
||||
GLint x = 0;
|
||||
GLint y = 0;
|
||||
GLsizei width = 0;
|
||||
GLsizei height = 0;
|
||||
} m_lastViewport;
|
||||
class CEGLSync {
|
||||
public:
|
||||
static UP<CEGLSync> create();
|
||||
|
||||
std::array<bool, CAP_STATUS_END> m_capStatus = {};
|
||||
~CEGLSync();
|
||||
|
||||
std::vector<SDRMFormat> m_drmFormats;
|
||||
bool m_hasModifiers = false;
|
||||
Hyprutils::OS::CFileDescriptor& fd();
|
||||
Hyprutils::OS::CFileDescriptor&& takeFd();
|
||||
bool isValid();
|
||||
|
||||
int m_drmFD = -1;
|
||||
std::string m_extensions;
|
||||
private:
|
||||
CEGLSync() = default;
|
||||
|
||||
bool m_fakeFrame = false;
|
||||
bool m_applyFinalShader = false;
|
||||
bool m_blend = false;
|
||||
bool m_offloadedFramebuffer = false;
|
||||
bool m_cmSupported = true;
|
||||
Hyprutils::OS::CFileDescriptor m_fd;
|
||||
EGLSyncKHR m_sync = EGL_NO_SYNC_KHR;
|
||||
bool m_valid = false;
|
||||
|
||||
SP<CShader> m_finalScreenShader;
|
||||
GLuint m_currentProgram;
|
||||
friend class CHyprOpenGLImpl;
|
||||
};
|
||||
|
||||
void initDRMFormats();
|
||||
void initEGL(bool gbm);
|
||||
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
|
||||
class CHyprOpenGLImpl {
|
||||
public:
|
||||
CHyprOpenGLImpl();
|
||||
~CHyprOpenGLImpl();
|
||||
|
||||
// for the final shader
|
||||
std::array<CTimer, POINTER_PRESSED_HISTORY_LENGTH> m_pressedHistoryTimers = {};
|
||||
std::array<Vector2D, POINTER_PRESSED_HISTORY_LENGTH> m_pressedHistoryPositions = {};
|
||||
GLint m_pressedHistoryKilled = 0;
|
||||
GLint m_pressedHistoryTouched = 0;
|
||||
struct SRectRenderData {
|
||||
const CRegion* damage = nullptr;
|
||||
int round = 0;
|
||||
float roundingPower = 2.F;
|
||||
bool blur = false;
|
||||
float blurA = 1.F;
|
||||
bool xray = false;
|
||||
};
|
||||
|
||||
//
|
||||
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
||||
struct STextureRenderData {
|
||||
bool blur = false;
|
||||
float blurA = 1.F, overallA = 1.F;
|
||||
bool blockBlurOptimization = false;
|
||||
SP<ITexture> blurredBG;
|
||||
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
SP<IFramebuffer> blurFramebufferWithDamage(float a, CRegion* damage, CGLFramebuffer& source);
|
||||
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 finalMonitorCM = false;
|
||||
SP<CMonitor> cmBackToSRGBSource;
|
||||
|
||||
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 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);
|
||||
WP<CShader> renderToOutputInternal();
|
||||
WP<CShader> renderToFBInternal(const STextureRenderData& data, eTextureType texType, const CBox& newBox);
|
||||
void renderTextureInternal(SP<ITexture>, const CBox&, const STextureRenderData& data);
|
||||
void renderTextureWithBlurInternal(SP<ITexture>, const CBox&, const STextureRenderData& data);
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
|
||||
friend class IHyprRenderer;
|
||||
friend class CHyprGLRenderer;
|
||||
friend class CTexPassElement;
|
||||
friend class CPreBlurElement;
|
||||
friend class CSurfacePassElement;
|
||||
};
|
||||
CRegion clipRegion;
|
||||
PHLLSREF currentLS;
|
||||
|
||||
inline UP<CHyprOpenGLImpl> g_pHyprOpenGL;
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
};
|
||||
|
||||
struct SBorderRenderData {
|
||||
int round = 0;
|
||||
float roundingPower = 2.F;
|
||||
int borderSize = 1;
|
||||
float a = 1.0;
|
||||
int outerRound = -1; /* use round */
|
||||
};
|
||||
|
||||
void makeEGLCurrent();
|
||||
void begin(PHLMONITOR, const CRegion& damage, SP<IFramebuffer> fb = nullptr, std::optional<CRegion> finalDamage = {});
|
||||
void beginSimple(PHLMONITOR, const CRegion& damage, SP<IRenderbuffer> rb = nullptr, SP<IFramebuffer> fb = nullptr);
|
||||
void end();
|
||||
|
||||
void renderRect(const CBox&, const CHyprColor&, SRectRenderData data);
|
||||
void renderTexture(SP<ITexture>, const CBox&, STextureRenderData data);
|
||||
void renderRoundedShadow(const CBox&, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0);
|
||||
void renderBorder(const CBox&, const CGradientValueData&, SBorderRenderData data);
|
||||
void renderBorder(const CBox&, const CGradientValueData&, const CGradientValueData&, float lerp, SBorderRenderData data);
|
||||
void renderTextureMatte(SP<ITexture> tex, const CBox& pBox, SP<IFramebuffer> matte);
|
||||
void renderTexturePrimitive(SP<ITexture> tex, const CBox& box);
|
||||
|
||||
void setViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
void setCapStatus(int cap, bool status);
|
||||
|
||||
void blend(bool enabled);
|
||||
|
||||
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 preRender(PHLMONITOR);
|
||||
|
||||
void saveBufferForMirror(const CBox&);
|
||||
|
||||
void applyScreenShader(const std::string& path);
|
||||
|
||||
void renderOffToMain(IFramebuffer* off);
|
||||
|
||||
std::vector<SDRMFormat> getDRMFormats();
|
||||
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
|
||||
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
||||
|
||||
bool initShaders(const std::string& path = "");
|
||||
|
||||
WP<CShader> useShader(WP<CShader> prog);
|
||||
|
||||
bool explicitSyncSupported();
|
||||
WP<CShader> getShaderVariant(Render::ePreparedFragmentShader frag, Render::ShaderFeatureFlags features = 0);
|
||||
|
||||
bool m_shadersInitialized = false;
|
||||
SP<SPreparedShaders> m_shaders;
|
||||
|
||||
Hyprutils::OS::CFileDescriptor m_gbmFD;
|
||||
gbm_device* m_gbmDevice = nullptr;
|
||||
EGLContext m_eglContext = nullptr;
|
||||
EGLDisplay m_eglDisplay = nullptr;
|
||||
EGLDeviceEXT m_eglDevice = nullptr;
|
||||
|
||||
std::map<PHLMONITORREF, SP<IFramebuffer>> m_monitorBGFBs;
|
||||
|
||||
struct {
|
||||
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
|
||||
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr;
|
||||
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = nullptr;
|
||||
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
|
||||
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr;
|
||||
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = nullptr;
|
||||
PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR = nullptr;
|
||||
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = nullptr;
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = nullptr;
|
||||
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT = nullptr;
|
||||
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR = nullptr;
|
||||
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = nullptr;
|
||||
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID = nullptr;
|
||||
PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR = nullptr;
|
||||
} m_proc;
|
||||
|
||||
struct {
|
||||
bool EXT_read_format_bgra = false;
|
||||
bool EXT_image_dma_buf_import = false;
|
||||
bool EXT_image_dma_buf_import_modifiers = false;
|
||||
bool KHR_context_flush_control = false;
|
||||
bool KHR_display_reference = false;
|
||||
bool IMG_context_priority = false;
|
||||
bool EXT_create_context_robustness = false;
|
||||
bool EGL_ANDROID_native_fence_sync_ext = false;
|
||||
} m_exts;
|
||||
|
||||
enum eEGLContextVersion : uint8_t {
|
||||
EGL_CONTEXT_GLES_2_0 = 0,
|
||||
EGL_CONTEXT_GLES_3_0,
|
||||
EGL_CONTEXT_GLES_3_2,
|
||||
};
|
||||
|
||||
eEGLContextVersion m_eglContextVersion = EGL_CONTEXT_GLES_3_2;
|
||||
|
||||
enum eCachedCapStatus : uint8_t {
|
||||
CAP_STATUS_BLEND = 0,
|
||||
CAP_STATUS_SCISSOR_TEST,
|
||||
CAP_STATUS_STENCIL_TEST,
|
||||
CAP_STATUS_END
|
||||
};
|
||||
|
||||
private:
|
||||
struct {
|
||||
GLint x = 0;
|
||||
GLint y = 0;
|
||||
GLsizei width = 0;
|
||||
GLsizei height = 0;
|
||||
} m_lastViewport;
|
||||
|
||||
std::array<bool, CAP_STATUS_END> m_capStatus = {};
|
||||
|
||||
std::vector<SDRMFormat> m_drmFormats;
|
||||
bool m_hasModifiers = false;
|
||||
|
||||
int m_drmFD = -1;
|
||||
std::string m_extensions;
|
||||
|
||||
bool m_fakeFrame = false;
|
||||
bool m_applyFinalShader = false;
|
||||
bool m_blend = false;
|
||||
bool m_offloadedFramebuffer = false;
|
||||
bool m_cmSupported = true;
|
||||
|
||||
SP<CShader> m_finalScreenShader;
|
||||
GLuint m_currentProgram;
|
||||
|
||||
void initDRMFormats();
|
||||
void initEGL(bool gbm);
|
||||
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
|
||||
|
||||
// for the final shader
|
||||
std::array<CTimer, POINTER_PRESSED_HISTORY_LENGTH> m_pressedHistoryTimers = {};
|
||||
std::array<Vector2D, POINTER_PRESSED_HISTORY_LENGTH> m_pressedHistoryPositions = {};
|
||||
GLint m_pressedHistoryKilled = 0;
|
||||
GLint m_pressedHistoryTouched = 0;
|
||||
|
||||
//
|
||||
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
||||
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
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 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);
|
||||
WP<CShader> renderToOutputInternal();
|
||||
WP<CShader> renderToFBInternal(const STextureRenderData& data, eTextureType texType, const CBox& newBox);
|
||||
void renderTextureInternal(SP<ITexture>, const CBox&, const STextureRenderData& data);
|
||||
void renderTextureWithBlurInternal(SP<ITexture>, const CBox&, const STextureRenderData& data);
|
||||
|
||||
friend class IHyprRenderer;
|
||||
friend class CHyprGLRenderer;
|
||||
friend class CGLElementRenderer;
|
||||
friend class CTexPassElement;
|
||||
friend class CPreBlurElement;
|
||||
friend class CSurfacePassElement;
|
||||
};
|
||||
|
||||
inline UP<CHyprOpenGLImpl> g_pHyprOpenGL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@
|
|||
#include "../protocols/types/ContentType.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include "AsyncResourceGatherer.hpp"
|
||||
#include "ElementRenderer.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include "pass/BorderPassElement.hpp"
|
||||
#include "pass/PreBlurElement.hpp"
|
||||
#include "./pass/PreBlurElement.hpp"
|
||||
#include <hyprutils/math/Mat3x3.hpp>
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
|
|
@ -65,6 +65,7 @@ using namespace Hyprutils::Utils;
|
|||
using namespace Hyprutils::OS;
|
||||
using enum NContentType::eContentType;
|
||||
using namespace NColorManagement;
|
||||
using namespace Render;
|
||||
|
||||
extern "C" {
|
||||
#include <xf86drm.h>
|
||||
|
|
@ -212,8 +213,8 @@ IHyprRenderer::~IHyprRenderer() {
|
|||
wl_event_source_remove(m_cursorTicker);
|
||||
}
|
||||
|
||||
WP<CHyprOpenGLImpl> IHyprRenderer::glBackend() {
|
||||
return g_pHyprOpenGL;
|
||||
WP<Render::GL::CHyprOpenGLImpl> IHyprRenderer::glBackend() {
|
||||
return Render::GL::g_pHyprOpenGL;
|
||||
}
|
||||
|
||||
bool IHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) {
|
||||
|
|
@ -502,7 +503,7 @@ void IHyprRenderer::bindOffMain() {
|
|||
RASSERT(m_renderData.pMonitor->m_offMainFB->isAllocated(), "IHyprRenderer::beginRender should allocate monitor FBs")
|
||||
|
||||
m_renderData.pMonitor->m_offMainFB->bind();
|
||||
draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), {});
|
||||
draw(makeShared<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), {});
|
||||
m_renderData.currentFB = m_renderData.pMonitor->m_offMainFB;
|
||||
}
|
||||
|
||||
|
|
@ -769,347 +770,12 @@ void IHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T
|
|||
m_renderData.currentWindow.reset();
|
||||
}
|
||||
|
||||
void IHyprRenderer::drawRect(CRectPassElement* element, const CRegion& damage) {
|
||||
auto& data = element->m_data;
|
||||
|
||||
if (data.box.w <= 0 || data.box.h <= 0)
|
||||
return;
|
||||
|
||||
if (!data.clipBox.empty())
|
||||
m_renderData.clipBox = data.clipBox;
|
||||
|
||||
data.modifiedBox = data.box;
|
||||
m_renderData.renderModif.applyToBox(data.modifiedBox);
|
||||
|
||||
CBox transformedBox = data.box;
|
||||
transformedBox.transform(Math::wlTransformToHyprutils(Math::invertTransform(m_renderData.pMonitor->m_transform)), m_renderData.pMonitor->m_transformedSize.x,
|
||||
m_renderData.pMonitor->m_transformedSize.y);
|
||||
|
||||
data.TOPLEFT[0] = sc<float>(transformedBox.x);
|
||||
data.TOPLEFT[1] = sc<float>(transformedBox.y);
|
||||
data.FULLSIZE[0] = sc<float>(transformedBox.width);
|
||||
data.FULLSIZE[1] = sc<float>(transformedBox.height);
|
||||
|
||||
data.drawRegion = data.color.a == 1.F || !data.blur ? damage : m_renderData.damage;
|
||||
|
||||
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};
|
||||
data.drawRegion = damageClip.intersect(data.drawRegion);
|
||||
}
|
||||
|
||||
draw(element, damage);
|
||||
|
||||
m_renderData.clipBox = {};
|
||||
}
|
||||
|
||||
void IHyprRenderer::drawHints(CRendererHintsPassElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
if (m_data.renderModif.has_value())
|
||||
m_renderData.renderModif = *m_data.renderModif;
|
||||
}
|
||||
|
||||
void IHyprRenderer::drawPreBlur(CPreBlurElement* element, const CRegion& damage) {
|
||||
TRACY_GPU_ZONE("RenderPreBlurForCurrentMonitor");
|
||||
|
||||
const auto SAVEDRENDERMODIF = m_renderData.renderModif;
|
||||
m_renderData.renderModif = {}; // fix shit
|
||||
|
||||
// make the fake dmg
|
||||
CRegion fakeDamage{0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y};
|
||||
|
||||
draw(element, fakeDamage);
|
||||
|
||||
m_renderData.pMonitor->m_blurFBDirty = false;
|
||||
m_renderData.pMonitor->m_blurFBShouldRender = false;
|
||||
|
||||
m_renderData.renderModif = SAVEDRENDERMODIF;
|
||||
}
|
||||
|
||||
void IHyprRenderer::drawSurface(CSurfacePassElement* element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
|
||||
CScopeGuard x = {[]() {
|
||||
g_pHyprRenderer->m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
g_pHyprRenderer->m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}};
|
||||
|
||||
if (!m_data.texture)
|
||||
return;
|
||||
|
||||
const auto& TEXTURE = m_data.texture;
|
||||
|
||||
// this is bad, probably has been logged elsewhere. Means the texture failed
|
||||
// uploading to the GPU.
|
||||
if (!TEXTURE->ok())
|
||||
return;
|
||||
|
||||
const auto INTERACTIVERESIZEINPROGRESS = m_data.pWindow && g_layoutManager->dragController()->target() && g_layoutManager->dragController()->mode() == MBIND_RESIZE;
|
||||
TRACY_GPU_ZONE("RenderSurface");
|
||||
|
||||
auto PSURFACE = Desktop::View::CWLSurface::fromResource(m_data.surface);
|
||||
|
||||
const float ALPHA = m_data.alpha * m_data.fadeAlpha * (PSURFACE ? PSURFACE->m_alphaModifier : 1.F);
|
||||
const float OVERALL_ALPHA = PSURFACE ? PSURFACE->m_overallOpacity : 1.F;
|
||||
const bool BLUR = m_data.blur && (!TEXTURE->m_opaque || ALPHA < 1.F || OVERALL_ALPHA < 1.F);
|
||||
|
||||
auto windowBox = element->getTexBox();
|
||||
|
||||
const auto PROJSIZEUNSCALED = windowBox.size();
|
||||
|
||||
windowBox.scale(m_data.pMonitor->m_scale);
|
||||
windowBox.round();
|
||||
|
||||
if (windowBox.width <= 1 || windowBox.height <= 1) {
|
||||
element->discard();
|
||||
return;
|
||||
}
|
||||
|
||||
const bool MISALIGNEDFSV1 = std::floor(m_data.pMonitor->m_scale) != m_data.pMonitor->m_scale /* Fractional */ && m_data.surface->m_current.scale == 1 /* fs protocol */ &&
|
||||
windowBox.size() != m_data.surface->m_current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, m_data.surface->m_current.bufferSize.x, 3) &&
|
||||
DELTALESSTHAN(windowBox.height, m_data.surface->m_current.bufferSize.y, 3) /* off by one-or-two */ &&
|
||||
(!m_data.pWindow || (!m_data.pWindow->m_realSize->isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */ &&
|
||||
(!m_data.pLS || (!m_data.pLS->m_realSize->isBeingAnimated())); /* not LS or not animated */
|
||||
|
||||
calculateUVForSurface(m_data.pWindow, m_data.surface, m_data.pMonitor->m_self.lock(), m_data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1);
|
||||
|
||||
auto cancelRender = false;
|
||||
auto clipRegion = element->visibleRegion(cancelRender);
|
||||
if (cancelRender)
|
||||
return;
|
||||
|
||||
// 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)
|
||||
m_renderData.useNearestNeighbor = true;
|
||||
|
||||
float rounding = m_data.rounding;
|
||||
float roundingPower = m_data.roundingPower;
|
||||
|
||||
rounding -= 1; // to fix a border issue
|
||||
|
||||
if (m_data.dontRound) {
|
||||
rounding = 0;
|
||||
roundingPower = 2.0f;
|
||||
}
|
||||
|
||||
const bool WINDOWOPAQUE = m_data.pWindow && m_data.pWindow->wlSurface()->resource() == m_data.surface ? m_data.pWindow->opaque() : false;
|
||||
const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding <= 0 && WINDOWOPAQUE;
|
||||
|
||||
if (CANDISABLEBLEND)
|
||||
blend(false);
|
||||
else
|
||||
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 (m_data.surfaceCounter == 0 && !m_data.popup) {
|
||||
if (BLUR)
|
||||
draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA,
|
||||
.blurA = m_data.fadeAlpha,
|
||||
.overallA = OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.blur = true,
|
||||
.blockBlurOptimization = m_data.blockBlurOptimization,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
else
|
||||
draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA * OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.discardActive = false,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
} else {
|
||||
if (BLUR && m_data.popup)
|
||||
draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA,
|
||||
.blurA = m_data.fadeAlpha,
|
||||
.overallA = OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.blur = true,
|
||||
.blockBlurOptimization = true,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
else
|
||||
draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = TEXTURE,
|
||||
.box = windowBox,
|
||||
.a = ALPHA * OVERALL_ALPHA,
|
||||
.round = rounding,
|
||||
.roundingPower = roundingPower,
|
||||
.discardActive = false,
|
||||
.allowCustomUV = true,
|
||||
.surface = m_data.surface,
|
||||
.discardMode = m_data.discardMode,
|
||||
.discardOpacity = m_data.discardOpacity,
|
||||
.clipRegion = clipRegion,
|
||||
.currentLS = m_data.pLS,
|
||||
}),
|
||||
m_renderData.damage.copy().intersect(windowBox));
|
||||
}
|
||||
|
||||
blend(true);
|
||||
};
|
||||
|
||||
void IHyprRenderer::preDrawSurface(CSurfacePassElement* element, const CRegion& damage) {
|
||||
m_renderData.clipBox = element->m_data.clipBox;
|
||||
m_renderData.useNearestNeighbor = element->m_data.useNearestNeighbor;
|
||||
pushMonitorTransformEnabled(element->m_data.flipEndFrame);
|
||||
m_renderData.currentWindow = element->m_data.pWindow;
|
||||
|
||||
drawSurface(element, damage);
|
||||
|
||||
if (!m_bBlockSurfaceFeedback)
|
||||
element->m_data.surface->presentFeedback(element->m_data.when, element->m_data.pMonitor->m_self.lock());
|
||||
|
||||
// add async (dmabuf) buffers to usedBuffers so we can handle release later
|
||||
// sync (shm) buffers will be released in commitState, so no need to track them here
|
||||
if (element->m_data.surface->m_current.buffer && !element->m_data.surface->m_current.buffer->isSynchronous())
|
||||
m_usedAsyncBuffers.emplace_back(element->m_data.surface->m_current.buffer);
|
||||
|
||||
m_renderData.clipBox = {};
|
||||
m_renderData.useNearestNeighbor = false;
|
||||
popMonitorTransformEnabled();
|
||||
m_renderData.currentWindow.reset();
|
||||
}
|
||||
|
||||
void IHyprRenderer::drawTex(CTexPassElement* element, const CRegion& damage) {
|
||||
if (!element->m_data.clipBox.empty())
|
||||
m_renderData.clipBox = element->m_data.clipBox;
|
||||
|
||||
pushMonitorTransformEnabled(element->m_data.flipEndFrame);
|
||||
if (element->m_data.useMirrorProjection)
|
||||
setProjectionType(RPT_MIRROR);
|
||||
|
||||
m_renderData.surface = element->m_data.surface;
|
||||
|
||||
CScopeGuard x = {[useMirrorProjection = element->m_data.useMirrorProjection]() {
|
||||
g_pHyprRenderer->popMonitorTransformEnabled();
|
||||
if (useMirrorProjection)
|
||||
g_pHyprRenderer->setProjectionType(RPT_MONITOR);
|
||||
g_pHyprRenderer->m_renderData.surface.reset();
|
||||
}};
|
||||
|
||||
if (element->m_data.blur) {
|
||||
// make a damage region for this window
|
||||
CRegion texDamage{m_renderData.damage};
|
||||
texDamage.intersect(element->m_data.box.x, element->m_data.box.y, element->m_data.box.width, element->m_data.box.height);
|
||||
|
||||
// While renderTextureInternalWithDamage will clip the blur as well,
|
||||
// clipping texDamage here allows blur generation to be optimized.
|
||||
if (!element->m_data.clipRegion.empty())
|
||||
texDamage.intersect(element->m_data.clipRegion);
|
||||
|
||||
if (texDamage.empty())
|
||||
return;
|
||||
|
||||
m_renderData.renderModif.applyToRegion(texDamage);
|
||||
|
||||
element->m_data.damage = texDamage;
|
||||
|
||||
// amazing hack: the surface has an opaque region!
|
||||
const auto& surface = element->m_data.surface;
|
||||
const auto& box = element->m_data.box;
|
||||
CRegion inverseOpaque;
|
||||
if (element->m_data.a >= 1.f && surface && std::round(surface->m_current.size.x * m_renderData.pMonitor->m_scale) == box.w &&
|
||||
std::round(surface->m_current.size.y * m_renderData.pMonitor->m_scale) == box.h) {
|
||||
pixman_box32_t surfbox = {0, 0, surface->m_current.size.x * surface->m_current.scale, surface->m_current.size.y * surface->m_current.scale};
|
||||
inverseOpaque = surface->m_current.opaque;
|
||||
inverseOpaque.invert(&surfbox).intersect(0, 0, surface->m_current.size.x * surface->m_current.scale, surface->m_current.size.y * surface->m_current.scale);
|
||||
|
||||
if (inverseOpaque.empty()) {
|
||||
element->m_data.blur = false;
|
||||
draw(element, damage);
|
||||
m_renderData.clipBox = {};
|
||||
return;
|
||||
}
|
||||
} else
|
||||
inverseOpaque = {0, 0, element->m_data.box.width, element->m_data.box.height};
|
||||
|
||||
inverseOpaque.scale(m_renderData.pMonitor->m_scale);
|
||||
element->m_data.blockBlurOptimization =
|
||||
element->m_data.blockBlurOptimization.value_or(false) || !shouldUseNewBlurOptimizations(element->m_data.currentLS.lock(), m_renderData.currentWindow.lock());
|
||||
|
||||
// vvv TODO: layered blur fbs?
|
||||
if (element->m_data.blockBlurOptimization.value_or(false)) {
|
||||
inverseOpaque.translate(box.pos());
|
||||
m_renderData.renderModif.applyToRegion(inverseOpaque);
|
||||
inverseOpaque.intersect(element->m_data.damage);
|
||||
element->m_data.blurredBG = blurMainFramebuffer(element->m_data.a, &inverseOpaque);
|
||||
m_renderData.currentFB->bind();
|
||||
} else
|
||||
element->m_data.blurredBG = m_renderData.pMonitor->m_blurFB ? m_renderData.pMonitor->m_blurFB->getTexture() : nullptr;
|
||||
|
||||
draw(element, damage);
|
||||
} else
|
||||
draw(element, damage);
|
||||
|
||||
m_renderData.clipBox = {};
|
||||
}
|
||||
|
||||
void IHyprRenderer::drawTexMatte(CTextureMatteElement* element, const CRegion& damage) {
|
||||
if (m_renderData.damage.empty())
|
||||
return;
|
||||
|
||||
const auto m_data = element->m_data;
|
||||
if (m_data.disableTransformAndModify) {
|
||||
pushMonitorTransformEnabled(true);
|
||||
m_renderData.renderModif.enabled = false;
|
||||
draw(element, damage);
|
||||
m_renderData.renderModif.enabled = true;
|
||||
popMonitorTransformEnabled();
|
||||
} else
|
||||
draw(element, damage);
|
||||
}
|
||||
|
||||
void IHyprRenderer::draw(WP<IPassElement> element, const CRegion& damage) {
|
||||
ASSERT(element);
|
||||
if (!element)
|
||||
return;
|
||||
|
||||
switch (element->type()) {
|
||||
case EK_BORDER: draw(dc<CBorderPassElement*>(element.get()), damage); break;
|
||||
case EK_CLEAR: draw(dc<CClearPassElement*>(element.get()), damage); break;
|
||||
case EK_FRAMEBUFFER: draw(dc<CFramebufferElement*>(element.get()), damage); break;
|
||||
case EK_PRE_BLUR: drawPreBlur(dc<CPreBlurElement*>(element.get()), damage); break;
|
||||
case EK_RECT: drawRect(dc<CRectPassElement*>(element.get()), damage); break;
|
||||
case EK_HINTS: drawHints(dc<CRendererHintsPassElement*>(element.get()), damage); break;
|
||||
case EK_SHADOW: draw(dc<CShadowPassElement*>(element.get()), damage); break;
|
||||
case EK_SURFACE: preDrawSurface(dc<CSurfacePassElement*>(element.get()), damage); break;
|
||||
case EK_TEXTURE: drawTex(dc<CTexPassElement*>(element.get()), damage); break;
|
||||
case EK_TEXTURE_MATTE: drawTexMatte(dc<CTextureMatteElement*>(element.get()), damage); break;
|
||||
default: Log::logger->log(Log::WARN, "Unimplimented draw for {}", element->passName());
|
||||
}
|
||||
elementRenderer()->drawElement(element, damage);
|
||||
}
|
||||
|
||||
bool IHyprRenderer::preBlurQueued(PHLMONITORREF pMonitor) {
|
||||
|
|
@ -1892,126 +1558,6 @@ void IHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) {
|
|||
}
|
||||
}
|
||||
|
||||
static std::optional<Vector2D> getSurfaceExpectedSize(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, PHLMONITOR pMonitor, bool main) {
|
||||
const auto CAN_USE_WINDOW = pWindow && main;
|
||||
const auto WINDOW_SIZE_MISALIGN = CAN_USE_WINDOW && pWindow->getReportedSize() != pWindow->wlSurface()->resource()->m_current.size;
|
||||
|
||||
if (pSurface->m_current.viewport.hasDestination)
|
||||
return (pSurface->m_current.viewport.destination * pMonitor->m_scale).round();
|
||||
|
||||
if (pSurface->m_current.viewport.hasSource)
|
||||
return (pSurface->m_current.viewport.source.size() * pMonitor->m_scale).round();
|
||||
|
||||
if (WINDOW_SIZE_MISALIGN)
|
||||
return (pSurface->m_current.size * pMonitor->m_scale).round();
|
||||
|
||||
if (CAN_USE_WINDOW)
|
||||
return (pWindow->getReportedSize() * pMonitor->m_scale).round();
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void IHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, PHLMONITOR pMonitor, bool main, const Vector2D& projSize,
|
||||
const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) {
|
||||
if (!pWindow || !pWindow->m_isX11) {
|
||||
static auto PEXPANDEDGES = CConfigValue<Hyprlang::INT>("render:expand_undersized_textures");
|
||||
|
||||
Vector2D uvTL;
|
||||
Vector2D uvBR = Vector2D(1, 1);
|
||||
|
||||
if (pSurface->m_current.viewport.hasSource) {
|
||||
// we stretch it to dest. if no dest, to 1,1
|
||||
Vector2D const& bufferSize = pSurface->m_current.bufferSize;
|
||||
auto const& bufferSource = pSurface->m_current.viewport.source;
|
||||
|
||||
// calculate UV for the basic src_box. Assume dest == size. Scale to dest later
|
||||
uvTL = Vector2D(bufferSource.x / bufferSize.x, bufferSource.y / bufferSize.y);
|
||||
uvBR = Vector2D((bufferSource.x + bufferSource.width) / bufferSize.x, (bufferSource.y + bufferSource.height) / bufferSize.y);
|
||||
|
||||
if (uvBR.x < 0.01f || uvBR.y < 0.01f) {
|
||||
uvTL = Vector2D();
|
||||
uvBR = Vector2D(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (projSize != Vector2D{} && fixMisalignedFSV1) {
|
||||
// instead of nearest_neighbor (we will repeat / skip)
|
||||
// just cut off / expand surface
|
||||
const Vector2D PIXELASUV = Vector2D{1, 1} / pSurface->m_current.bufferSize;
|
||||
const auto& BUFFER_SIZE = pSurface->m_current.bufferSize;
|
||||
|
||||
// compute MISALIGN from the adjusted UV coordinates.
|
||||
const Vector2D MISALIGNMENT = (uvBR - uvTL) * BUFFER_SIZE - projSize;
|
||||
|
||||
if (MISALIGNMENT != Vector2D{})
|
||||
uvBR -= MISALIGNMENT * PIXELASUV;
|
||||
} else {
|
||||
// if the surface is smaller than our viewport, extend its edges.
|
||||
// this will break if later on xdg geometry is hit, but we really try
|
||||
// to let the apps know to NOT add CSD. Also if source is there.
|
||||
// there is no way to fix this if that's the case
|
||||
const auto MONITOR_WL_SCALE = std::ceil(pMonitor->m_scale);
|
||||
const bool SCALE_UNAWARE = pMonitor->m_scale != 1.f && (MONITOR_WL_SCALE == pSurface->m_current.scale || !pSurface->m_current.viewport.hasDestination);
|
||||
const auto EXPECTED_SIZE = getSurfaceExpectedSize(pWindow, pSurface, pMonitor, main).value_or((projSize * pMonitor->m_scale).round());
|
||||
|
||||
const auto RATIO = projSize / EXPECTED_SIZE;
|
||||
if (!SCALE_UNAWARE || MONITOR_WL_SCALE == 1) {
|
||||
if (*PEXPANDEDGES && !SCALE_UNAWARE && (RATIO.x > 1 || RATIO.y > 1)) {
|
||||
const auto FIX = RATIO.clamp(Vector2D{1, 1}, Vector2D{1000000, 1000000});
|
||||
uvBR = uvBR * FIX;
|
||||
}
|
||||
|
||||
// FIXME: probably do this for in anims on all views...
|
||||
const auto SHOULD_SKIP = !pWindow || pWindow->m_animatingIn;
|
||||
if (!SHOULD_SKIP && (RATIO.x < 1 || RATIO.y < 1)) {
|
||||
const auto FIX = RATIO.clamp(Vector2D{0.0001, 0.0001}, Vector2D{1, 1});
|
||||
uvBR = uvBR * FIX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_renderData.primarySurfaceUVTopLeft = uvTL;
|
||||
m_renderData.primarySurfaceUVBottomRight = uvBR;
|
||||
|
||||
if (m_renderData.primarySurfaceUVTopLeft == Vector2D() && m_renderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
|
||||
// No special UV mods needed
|
||||
m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
|
||||
if (!main || !pWindow)
|
||||
return;
|
||||
|
||||
// FIXME: this doesn't work. We always set MAXIMIZED anyways, so this doesn't need to work, but it's problematic.
|
||||
|
||||
// CBox geom = pWindow->m_xdgSurface->m_current.geometry;
|
||||
|
||||
// // Adjust UV based on the xdg_surface geometry
|
||||
// if (geom.x != 0 || geom.y != 0 || geom.w != 0 || geom.h != 0) {
|
||||
// const auto XPERC = geom.x / pSurface->m_current.size.x;
|
||||
// const auto YPERC = geom.y / pSurface->m_current.size.y;
|
||||
// const auto WPERC = (geom.x + geom.w ? geom.w : pSurface->m_current.size.x) / pSurface->m_current.size.x;
|
||||
// const auto HPERC = (geom.y + geom.h ? geom.h : pSurface->m_current.size.y) / pSurface->m_current.size.y;
|
||||
|
||||
// const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y));
|
||||
// uvBR = uvBR - Vector2D((1.0 - WPERC) * (uvBR.x - uvTL.x), (1.0 - HPERC) * (uvBR.y - uvTL.y));
|
||||
// uvTL = uvTL + TOADDTL;
|
||||
// }
|
||||
|
||||
m_renderData.primarySurfaceUVTopLeft = uvTL;
|
||||
m_renderData.primarySurfaceUVBottomRight = uvBR;
|
||||
|
||||
if (m_renderData.primarySurfaceUVTopLeft == Vector2D() && m_renderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
|
||||
// No special UV mods needed
|
||||
m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
} else {
|
||||
m_renderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
m_renderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
bool IHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode, SP<IHLBuffer> buffer, SP<IFramebuffer> fb, bool simple) {
|
||||
m_renderPass.clear();
|
||||
m_renderMode = mode;
|
||||
|
|
@ -2165,11 +1711,11 @@ void IHyprRenderer::preBlurForCurrentMonitor(CRegion* fakeDamage) {
|
|||
m_renderData.pMonitor->m_blurFB->alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y, m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
m_renderData.pMonitor->m_blurFB->bind();
|
||||
|
||||
draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), {});
|
||||
draw(makeShared<CClearPassElement>(CClearPassElement::SClearData{{0, 0, 0, 0}}), {});
|
||||
|
||||
pushMonitorTransformEnabled(true);
|
||||
|
||||
draw(makeUnique<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
draw(makeShared<CTexPassElement>(CTexPassElement::SRenderData{
|
||||
.tex = blurredTex,
|
||||
.box = CBox{0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y},
|
||||
.damage = *fakeDamage,
|
||||
|
|
@ -3351,7 +2897,7 @@ void IHyprRenderer::makeSnapshot(PHLWINDOW pWindow) {
|
|||
|
||||
m_bRenderingSnapshot = true;
|
||||
|
||||
draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(0, 0, 0, 0)}), {});
|
||||
draw(makeShared<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(0, 0, 0, 0)}), {});
|
||||
startRenderPass();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "renderer: cleared a snapshot of {:x}", rc<uintptr_t>(pWindow.get()));
|
||||
|
|
@ -3392,7 +2938,7 @@ void IHyprRenderer::makeSnapshot(PHLLS pLayer) {
|
|||
|
||||
m_bRenderingSnapshot = true;
|
||||
|
||||
draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(0, 0, 0, 0)}), {});
|
||||
draw(makeShared<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(0, 0, 0, 0)}), {});
|
||||
startRenderPass();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "renderer: cleared a snapshot of layer {:x}", rc<uintptr_t>(pLayer.get()));
|
||||
|
|
@ -3434,7 +2980,7 @@ void IHyprRenderer::makeSnapshot(WP<Desktop::View::CPopup> popup) {
|
|||
|
||||
m_bRenderingSnapshot = true;
|
||||
|
||||
draw(makeUnique<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(0, 0, 0, 0)}), {});
|
||||
draw(makeShared<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(0, 0, 0, 0)}), {});
|
||||
|
||||
CSurfacePassElement::SRenderData renderdata;
|
||||
renderdata.pos = popup->coordsGlobal();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include <hyprutils/math/Box.hpp>
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include "OpenGL.hpp"
|
||||
#include "types.hpp"
|
||||
#include "../helpers/Monitor.hpp"
|
||||
#include "../desktop/view/LayerSurface.hpp"
|
||||
#include "./pass/Pass.hpp"
|
||||
|
|
@ -13,19 +15,12 @@
|
|||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/time/Time.hpp"
|
||||
#include "../../protocols/cursor-shape-v1.hpp"
|
||||
#include "../desktop/view/Popup.hpp"
|
||||
#include "desktop/view/Popup.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include "pass/BorderPassElement.hpp"
|
||||
#include "pass/ClearPassElement.hpp"
|
||||
#include "pass/FramebufferElement.hpp"
|
||||
#include "pass/PreBlurElement.hpp"
|
||||
#include "pass/RectPassElement.hpp"
|
||||
#include "pass/RendererHintsPassElement.hpp"
|
||||
#include "pass/ShadowPassElement.hpp"
|
||||
#include "pass/SurfacePassElement.hpp"
|
||||
#include "pass/TexPassElement.hpp"
|
||||
#include "pass/TextureMatteElement.hpp"
|
||||
#include "./pass/SurfacePassElement.hpp"
|
||||
#include "./pass/TexPassElement.hpp"
|
||||
#include "./pass/TextureMatteElement.hpp"
|
||||
|
||||
struct SMonitorRule;
|
||||
class CWorkspace;
|
||||
|
|
@ -33,14 +28,6 @@ class CInputPopup;
|
|||
class IHLBuffer;
|
||||
class CEventLoopTimer;
|
||||
class CRenderPass;
|
||||
|
||||
const std::vector<const char*> ASSET_PATHS = {
|
||||
#ifdef DATAROOTDIR
|
||||
DATAROOTDIR,
|
||||
#endif
|
||||
"/usr/share",
|
||||
"/usr/local/share",
|
||||
};
|
||||
class CToplevelExportProtocolManager;
|
||||
class CInputManager;
|
||||
struct SSessionLockSurface;
|
||||
|
|
@ -48,329 +35,229 @@ namespace Screenshare {
|
|||
class CScreenshareFrame;
|
||||
};
|
||||
|
||||
enum eDamageTrackingModes : int8_t {
|
||||
DAMAGE_TRACKING_INVALID = -1,
|
||||
DAMAGE_TRACKING_NONE = 0,
|
||||
DAMAGE_TRACKING_MONITOR,
|
||||
DAMAGE_TRACKING_FULL,
|
||||
};
|
||||
namespace Render {
|
||||
class IElementRenderer;
|
||||
|
||||
enum eRenderPassMode : uint8_t {
|
||||
RENDER_PASS_ALL = 0,
|
||||
RENDER_PASS_MAIN,
|
||||
RENDER_PASS_POPUP
|
||||
};
|
||||
class IHyprRenderer {
|
||||
public:
|
||||
IHyprRenderer();
|
||||
virtual ~IHyprRenderer();
|
||||
|
||||
enum eRenderMode : uint8_t {
|
||||
RENDER_MODE_NORMAL = 0,
|
||||
RENDER_MODE_FULL_FAKE = 1,
|
||||
RENDER_MODE_TO_BUFFER = 2,
|
||||
RENDER_MODE_TO_BUFFER_READ_ONLY = 3,
|
||||
};
|
||||
WP<Render::GL::CHyprOpenGLImpl> glBackend();
|
||||
|
||||
struct SRenderWorkspaceUntilData {
|
||||
PHLLS ls;
|
||||
PHLWINDOW w;
|
||||
};
|
||||
void renderMonitor(PHLMONITOR pMonitor, bool commit = true);
|
||||
void arrangeLayersForMonitor(const MONITORID&);
|
||||
void damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
|
||||
void damageWindow(PHLWINDOW, bool forceFull = false);
|
||||
void damageBox(const CBox&, bool skipFrameSchedule = false);
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageRegion(const CRegion&);
|
||||
void damageMonitor(PHLMONITOR);
|
||||
void damageMirrorsWith(PHLMONITOR, const CRegion&);
|
||||
bool shouldRenderWindow(PHLWINDOW, PHLMONITOR);
|
||||
bool shouldRenderWindow(PHLWINDOW);
|
||||
void ensureCursorRenderingMode();
|
||||
bool shouldRenderCursor();
|
||||
void setCursorHidden(bool hide);
|
||||
|
||||
enum eRenderProjectionType : uint8_t {
|
||||
RPT_MONITOR,
|
||||
RPT_MIRROR,
|
||||
RPT_FB,
|
||||
RPT_EXPORT,
|
||||
};
|
||||
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;
|
||||
|
||||
struct SRenderData {
|
||||
// can be private
|
||||
Mat3x3 targetProjection;
|
||||
NColorManagement::PImageDescription workBufferImageDescription();
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
bool m_bRenderingSnapshot = false;
|
||||
PHLMONITORREF m_mostHzMonitor;
|
||||
bool m_directScanoutBlocked = false;
|
||||
|
||||
// ----------------------
|
||||
void setSurfaceScanoutMode(SP<CWLSurfaceResource> surface, PHLMONITOR monitor); // nullptr monitor resets
|
||||
|
||||
// used by public
|
||||
Vector2D fbSize = {-1, -1};
|
||||
PHLMONITORREF pMonitor;
|
||||
void initiateManualCrash();
|
||||
const SRenderData& renderData();
|
||||
|
||||
eRenderProjectionType projectionType = RPT_MONITOR;
|
||||
bool m_crashingInProgress = false;
|
||||
float m_crashingDistort = 0.5f;
|
||||
wl_event_source* m_crashingLoop = nullptr;
|
||||
wl_event_source* m_cursorTicker = nullptr;
|
||||
|
||||
SP<IFramebuffer> currentFB = nullptr; // current rendering to
|
||||
SP<IFramebuffer> mainFB = nullptr; // main to render to
|
||||
SP<IFramebuffer> outFB = nullptr; // out to render to (if offloaded, etc)
|
||||
std::vector<CHLBufferReference> m_usedAsyncBuffers;
|
||||
|
||||
CRegion damage;
|
||||
CRegion finalDamage; // damage used for funal off -> main
|
||||
struct {
|
||||
int hotspotX = 0;
|
||||
int hotspotY = 0;
|
||||
wpCursorShapeDeviceV1Shape shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
|
||||
wpCursorShapeDeviceV1Shape shapePrevious = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
|
||||
CTimer switchedTimer;
|
||||
std::optional<SP<Desktop::View::CWLSurface>> surf;
|
||||
std::string name;
|
||||
} m_lastCursorData;
|
||||
|
||||
SRenderModifData renderModif;
|
||||
float mouseZoomFactor = 1.f;
|
||||
bool mouseZoomUseMouse = true; // true by default
|
||||
bool useNearestNeighbor = false;
|
||||
bool blockScreenShader = false;
|
||||
CRenderPass m_renderPass;
|
||||
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
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);
|
||||
|
||||
// TODO remove and pass directly
|
||||
CBox clipBox = {}; // scaled coordinates
|
||||
PHLWINDOWREF currentWindow;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
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;
|
||||
|
||||
bool transformDamage = true;
|
||||
bool noSimplify = false;
|
||||
};
|
||||
void draw(WP<IPassElement> element, const CRegion& damage);
|
||||
virtual WP<IElementRenderer> elementRenderer() = 0;
|
||||
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;
|
||||
|
||||
struct STFRange {
|
||||
float min = 0;
|
||||
float max = 80;
|
||||
};
|
||||
bool preBlurQueued(PHLMONITORREF pMonitor);
|
||||
void pushMonitorTransformEnabled(bool enabled);
|
||||
void popMonitorTransformEnabled();
|
||||
bool monitorTransformEnabled();
|
||||
|
||||
struct SCMSettings {
|
||||
NColorManagement::eTransferFunction sourceTF = NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22;
|
||||
NColorManagement::eTransferFunction targetTF = NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22;
|
||||
STFRange srcTFRange;
|
||||
STFRange dstTFRange;
|
||||
float srcRefLuminance = 80;
|
||||
float dstRefLuminance = 80;
|
||||
std::array<std::array<double, 3>, 3> convertMatrix;
|
||||
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);
|
||||
|
||||
bool needsTonemap = false;
|
||||
float maxLuminance = 80;
|
||||
float dstMaxLuminance = 80;
|
||||
std::array<std::array<double, 3>, 3> dstPrimaries2XYZ;
|
||||
bool needsSDRmod = false;
|
||||
float sdrSaturation = 1.0;
|
||||
float sdrBrightnessMultiplier = 1.0;
|
||||
};
|
||||
SP<ITexture> blurMainFramebuffer(float a, CRegion* originalDamage);
|
||||
virtual SP<ITexture> blurFramebuffer(SP<IFramebuffer> source, float a, CRegion* originalDamage) = 0;
|
||||
void preBlurForCurrentMonitor(CRegion* fakeDamage);
|
||||
|
||||
class IHyprRenderer {
|
||||
public:
|
||||
IHyprRenderer();
|
||||
virtual ~IHyprRenderer();
|
||||
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;
|
||||
|
||||
WP<CHyprOpenGLImpl> glBackend();
|
||||
bool needsACopyFB(PHLMONITOR mon);
|
||||
|
||||
void renderMonitor(PHLMONITOR pMonitor, bool commit = true);
|
||||
void arrangeLayersForMonitor(const MONITORID&);
|
||||
void damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
|
||||
void damageWindow(PHLWINDOW, bool forceFull = false);
|
||||
void damageBox(const CBox&, bool skipFrameSchedule = false);
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageRegion(const CRegion&);
|
||||
void damageMonitor(PHLMONITOR);
|
||||
void damageMirrorsWith(PHLMONITOR, const CRegion&);
|
||||
bool shouldRenderWindow(PHLWINDOW, PHLMONITOR);
|
||||
bool shouldRenderWindow(PHLWINDOW);
|
||||
void ensureCursorRenderingMode();
|
||||
bool shouldRenderCursor();
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
|
||||
NColorManagement::PImageDescription workBufferImageDescription();
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
bool m_bRenderingSnapshot = false;
|
||||
PHLMONITORREF m_mostHzMonitor;
|
||||
bool m_directScanoutBlocked = 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;
|
||||
};
|
||||
|
||||
void setSurfaceScanoutMode(SP<CWLSurfaceResource> surface, PHLMONITOR monitor); // nullptr monitor resets
|
||||
SP<ITexture> getBackground(PHLMONITOR pMonitor);
|
||||
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;
|
||||
|
||||
void initiateManualCrash();
|
||||
const SRenderData& renderData();
|
||||
// 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)
|
||||
void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
|
||||
void renderWindow(PHLWINDOW, PHLMONITOR, const Time::steady_tp&, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false);
|
||||
void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false, bool lockscreen = false);
|
||||
void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&);
|
||||
void renderDragIcon(PHLMONITOR, const Time::steady_tp&);
|
||||
void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&);
|
||||
void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace,
|
||||
const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything
|
||||
void renderSessionLockPrimer(PHLMONITOR pMonitor);
|
||||
void renderSessionLockMissing(PHLMONITOR pMonitor);
|
||||
void renderBackground(PHLMONITOR pMonitor);
|
||||
void requestBackgroundResource();
|
||||
std::string resolveAssetPath(const std::string& file);
|
||||
void initMissingAssetTexture();
|
||||
void initAssets();
|
||||
SP<ITexture> m_missingAssetTexture;
|
||||
ASP<Hyprgraphics::CImageResource> m_backgroundResource;
|
||||
bool m_backgroundResourceFailed = false;
|
||||
|
||||
bool m_crashingInProgress = false;
|
||||
float m_crashingDistort = 0.5f;
|
||||
wl_event_source* m_crashingLoop = nullptr;
|
||||
wl_event_source* m_cursorTicker = nullptr;
|
||||
bool shouldBlur(PHLLS ls);
|
||||
bool shouldBlur(PHLWINDOW w);
|
||||
bool shouldBlur(WP<Desktop::View::CPopup> p);
|
||||
|
||||
std::vector<CHLBufferReference> m_usedAsyncBuffers;
|
||||
bool m_cursorHidden = false;
|
||||
bool m_cursorHiddenByCondition = false;
|
||||
bool m_cursorHasSurface = false;
|
||||
SP<Aquamarine::IBuffer> m_currentBuffer = nullptr;
|
||||
eRenderMode m_renderMode = RENDER_MODE_NORMAL;
|
||||
bool m_nvidia = false;
|
||||
bool m_intel = false;
|
||||
bool m_software = false;
|
||||
bool m_mgpu = false;
|
||||
|
||||
struct {
|
||||
int hotspotX = 0;
|
||||
int hotspotY = 0;
|
||||
wpCursorShapeDeviceV1Shape shape = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
|
||||
wpCursorShapeDeviceV1Shape shapePrevious = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
|
||||
CTimer switchedTimer;
|
||||
std::optional<SP<Desktop::View::CWLSurface>> surf;
|
||||
std::string name;
|
||||
} m_lastCursorData;
|
||||
struct {
|
||||
bool hiddenOnTouch = false;
|
||||
bool hiddenOnTablet = false;
|
||||
bool hiddenOnTimeout = false;
|
||||
bool hiddenOnKeyboard = false;
|
||||
} m_cursorHiddenConditions;
|
||||
|
||||
CRenderPass m_renderPass;
|
||||
std::vector<SP<IRenderbuffer>> m_renderbuffers;
|
||||
std::vector<PHLWINDOWREF> m_renderUnfocused;
|
||||
SP<CEventLoopTimer> m_renderUnfocusedTimer;
|
||||
|
||||
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);
|
||||
friend class CRenderPass;
|
||||
friend class Render::GL::CHyprOpenGLImpl;
|
||||
friend class CToplevelExportFrame;
|
||||
friend class Screenshare::CScreenshareFrame;
|
||||
friend class CInputManager;
|
||||
friend class CPointerManager;
|
||||
friend class CMonitor;
|
||||
friend class CMonitorFrameScheduler;
|
||||
|
||||
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 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;
|
||||
|
||||
bool preBlurQueued(PHLMONITORREF pMonitor);
|
||||
void pushMonitorTransformEnabled(bool enabled);
|
||||
void popMonitorTransformEnabled();
|
||||
bool monitorTransformEnabled();
|
||||
|
||||
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> blurMainFramebuffer(float a, CRegion* originalDamage);
|
||||
virtual SP<ITexture> blurFramebuffer(SP<IFramebuffer> source, float a, CRegion* originalDamage) = 0;
|
||||
void preBlurForCurrentMonitor(CRegion* fakeDamage);
|
||||
|
||||
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;
|
||||
private:
|
||||
void bindOffMain();
|
||||
void bindBackOnMain();
|
||||
};
|
||||
|
||||
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)
|
||||
void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
|
||||
void renderWindow(PHLWINDOW, PHLMONITOR, const Time::steady_tp&, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false);
|
||||
void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false, bool lockscreen = false);
|
||||
void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&);
|
||||
void renderDragIcon(PHLMONITOR, const Time::steady_tp&);
|
||||
void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&);
|
||||
void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything
|
||||
void renderSessionLockPrimer(PHLMONITOR pMonitor);
|
||||
void renderSessionLockMissing(PHLMONITOR pMonitor);
|
||||
void renderBackground(PHLMONITOR pMonitor);
|
||||
void requestBackgroundResource();
|
||||
std::string resolveAssetPath(const std::string& file);
|
||||
void initMissingAssetTexture();
|
||||
void initAssets();
|
||||
SP<ITexture> m_missingAssetTexture;
|
||||
ASP<Hyprgraphics::CImageResource> m_backgroundResource;
|
||||
bool m_backgroundResourceFailed = false;
|
||||
|
||||
bool shouldBlur(PHLLS ls);
|
||||
bool shouldBlur(PHLWINDOW w);
|
||||
bool shouldBlur(WP<Desktop::View::CPopup> p);
|
||||
|
||||
bool m_cursorHidden = false;
|
||||
bool m_cursorHiddenByCondition = false;
|
||||
bool m_cursorHasSurface = false;
|
||||
SP<Aquamarine::IBuffer> m_currentBuffer = nullptr;
|
||||
eRenderMode m_renderMode = RENDER_MODE_NORMAL;
|
||||
bool m_nvidia = false;
|
||||
bool m_intel = false;
|
||||
bool m_software = false;
|
||||
bool m_mgpu = false;
|
||||
|
||||
struct {
|
||||
bool hiddenOnTouch = false;
|
||||
bool hiddenOnTablet = false;
|
||||
bool hiddenOnTimeout = false;
|
||||
bool hiddenOnKeyboard = false;
|
||||
} m_cursorHiddenConditions;
|
||||
|
||||
std::vector<SP<IRenderbuffer>> m_renderbuffers;
|
||||
std::vector<PHLWINDOWREF> m_renderUnfocused;
|
||||
SP<CEventLoopTimer> m_renderUnfocusedTimer;
|
||||
|
||||
friend class CRenderPass;
|
||||
friend class CHyprOpenGLImpl;
|
||||
friend class CToplevelExportFrame;
|
||||
friend class Screenshare::CScreenshareFrame;
|
||||
friend class CInputManager;
|
||||
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<IHyprRenderer> g_pHyprRenderer;
|
||||
inline UP<Render::IHyprRenderer> g_pHyprRenderer;
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#define EPSILON(x, y) (std::abs((x) - (y)) < 1e-5f)
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
static bool compareFloat(auto a, auto b) {
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
|
||||
using namespace Render;
|
||||
|
||||
using namespace Render;
|
||||
|
||||
CShaderLoader::CShaderLoader(const std::vector<std::string> includes, const std::array<std::string, SH_FRAG_LAST>& frags, const std::string shaderPath) : m_shaderPath(shaderPath) {
|
||||
m_callbacks = glsl_include_callbacks_t{
|
||||
.include_local =
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "../../config/ConfigValue.hpp"
|
||||
#include "../pass/ShadowPassElement.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "../pass/RectPassElement.hpp"
|
||||
#include "../pass/TextureMatteElement.hpp"
|
||||
|
||||
CHyprDropShadowDecoration::CHyprDropShadowDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_window(pWindow) {
|
||||
|
|
@ -245,14 +246,14 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
// 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_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{.box = data.fullBox, .color = CHyprColor(0, 0, 0, 1), .round = 0}), monbox);
|
||||
g_pHyprRenderer->draw(makeShared<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(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_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = data.windowBox,
|
||||
.color = CHyprColor(0, 0, 0, 1),
|
||||
.round = (data.rounding + 1 /* This fixes small pixel gaps. */) * pMonitor->m_scale,
|
||||
|
|
@ -263,7 +264,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
alphaSwapFB->bind();
|
||||
|
||||
// alpha swap just has the shadow color. It will be the "texture" to render.
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{.box = data.fullBox, .color = PWINDOW->m_realShadowColor->value().stripA(), .round = 0}),
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(CRectPassElement::SRectData{.box = data.fullBox, .color = PWINDOW->m_realShadowColor->value().stripA(), .round = 0}),
|
||||
monbox);
|
||||
|
||||
LASTFB->bind();
|
||||
|
|
@ -271,7 +272,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
g_pHyprRenderer->pushMonitorTransformEnabled(true);
|
||||
g_pHyprRenderer->m_renderData.renderModif.enabled = false;
|
||||
|
||||
g_pHyprRenderer->draw(makeUnique<CTextureMatteElement>(CTextureMatteElement::STextureMatteData{
|
||||
g_pHyprRenderer->draw(makeShared<CTextureMatteElement>(CTextureMatteElement::STextureMatteData{
|
||||
.box = monbox,
|
||||
.tex = alphaSwapFB->getTexture(),
|
||||
.fb = alphaFB,
|
||||
|
|
@ -303,7 +304,7 @@ void CHyprDropShadowDecoration::drawShadowInternal(const CBox& box, int round, f
|
|||
color.a *= a;
|
||||
|
||||
if (*PSHADOWSHARP)
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(CRectPassElement::SRectData{
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(CRectPassElement::SRectData{
|
||||
.box = box,
|
||||
.color = color,
|
||||
.round = round,
|
||||
|
|
|
|||
131
src/render/gl/GLElementRenderer.cpp
Normal file
131
src/render/gl/GLElementRenderer.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#include "GLElementRenderer.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "../decorations/CHyprDropShadowDecoration.hpp"
|
||||
#include "../OpenGL.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
void CGLElementRenderer::draw(WP<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 CGLElementRenderer::draw(WP<CClearPassElement> element, const CRegion& damage) {
|
||||
const auto& color = element->m_data.color;
|
||||
RASSERT(g_pHyprRenderer->m_renderData.pMonitor, "Tried to render without begin()!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderClear");
|
||||
|
||||
GLCALL(glClearColor(color.r, color.g, color.b, color.a));
|
||||
|
||||
if (!g_pHyprRenderer->m_renderData.damage.empty()) {
|
||||
g_pHyprRenderer->m_renderData.damage.forEachRect([](const auto& RECT) {
|
||||
g_pHyprOpenGL->scissor(&RECT, g_pHyprRenderer->m_renderData.transformDamage);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
void CGLElementRenderer::draw(WP<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 = g_pHyprRenderer->m_renderData.pMonitor->m_mirrorFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP: fb = g_pHyprRenderer->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 CGLElementRenderer::draw(WP<CPreBlurElement> element, const CRegion& damage) {
|
||||
auto dmg = damage;
|
||||
g_pHyprRenderer->preBlurForCurrentMonitor(&dmg);
|
||||
};
|
||||
|
||||
void CGLElementRenderer::draw(WP<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 CGLElementRenderer::draw(WP<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 CGLElementRenderer::draw(WP<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 CGLElementRenderer::draw(WP<CTextureMatteElement> element, const CRegion& damage) {
|
||||
const auto m_data = element->m_data;
|
||||
|
||||
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb);
|
||||
};
|
||||
21
src/render/gl/GLElementRenderer.hpp
Normal file
21
src/render/gl/GLElementRenderer.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "../ElementRenderer.hpp"
|
||||
|
||||
namespace Render::GL {
|
||||
class CGLElementRenderer : public Render::IElementRenderer {
|
||||
public:
|
||||
CGLElementRenderer() = default;
|
||||
~CGLElementRenderer() = default;
|
||||
|
||||
private:
|
||||
void draw(WP<CBorderPassElement> element, const Hyprutils::Math::CRegion& damage);
|
||||
void draw(WP<CClearPassElement> element, const CRegion& damage);
|
||||
void draw(WP<CFramebufferElement> element, const CRegion& damage);
|
||||
void draw(WP<CPreBlurElement> element, const CRegion& damage);
|
||||
void draw(WP<CRectPassElement> element, const CRegion& damage);
|
||||
void draw(WP<CShadowPassElement> element, const CRegion& damage);
|
||||
void draw(WP<CTexPassElement> element, const CRegion& damage);
|
||||
void draw(WP<CTextureMatteElement> element, const CRegion& damage);
|
||||
};
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
#include "macros.hpp"
|
||||
#include "../Framebuffer.hpp"
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
CGLFramebuffer::CGLFramebuffer() : IFramebuffer() {}
|
||||
CGLFramebuffer::CGLFramebuffer(const std::string& name) : IFramebuffer(name) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,26 +5,28 @@
|
|||
#include "../Framebuffer.hpp"
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
class CGLFramebuffer : public IFramebuffer {
|
||||
public:
|
||||
CGLFramebuffer();
|
||||
CGLFramebuffer(const std::string& name);
|
||||
~CGLFramebuffer();
|
||||
namespace Render::GL {
|
||||
class CGLFramebuffer : public IFramebuffer {
|
||||
public:
|
||||
CGLFramebuffer();
|
||||
CGLFramebuffer(const std::string& name);
|
||||
~CGLFramebuffer();
|
||||
|
||||
void addStencil(SP<ITexture> tex) override;
|
||||
void release() override;
|
||||
bool readPixels(CHLBufferReference buffer, uint32_t offsetX = 0, uint32_t offsetY = 0, uint32_t width = 0, uint32_t height = 0) override;
|
||||
void addStencil(SP<ITexture> tex) override;
|
||||
void release() override;
|
||||
bool readPixels(CHLBufferReference buffer, uint32_t offsetX = 0, uint32_t offsetY = 0, uint32_t width = 0, uint32_t height = 0) override;
|
||||
|
||||
void bind() override;
|
||||
void unbind();
|
||||
GLuint getFBID();
|
||||
void invalidate(const std::vector<GLenum>& attachments);
|
||||
void bind() override;
|
||||
void unbind();
|
||||
GLuint getFBID();
|
||||
void invalidate(const std::vector<GLenum>& attachments);
|
||||
|
||||
protected:
|
||||
bool internalAlloc(int w, int h, uint32_t format = DRM_FORMAT_ARGB8888) override;
|
||||
protected:
|
||||
bool internalAlloc(int w, int h, uint32_t format = DRM_FORMAT_ARGB8888) override;
|
||||
|
||||
private:
|
||||
GLuint m_fb = -1;
|
||||
private:
|
||||
GLuint m_fb = -1;
|
||||
|
||||
friend class CGLRenderbuffer;
|
||||
};
|
||||
friend class CGLRenderbuffer;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <dlfcn.h>
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
CGLRenderbuffer::~CGLRenderbuffer() {
|
||||
if (!g_pCompositor || g_pCompositor->m_isShuttingDown || !g_pHyprRenderer)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -6,15 +6,17 @@
|
|||
|
||||
class CMonitor;
|
||||
|
||||
class CGLRenderbuffer : public IRenderbuffer {
|
||||
public:
|
||||
CGLRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format);
|
||||
~CGLRenderbuffer();
|
||||
namespace Render::GL {
|
||||
class CGLRenderbuffer : public IRenderbuffer {
|
||||
public:
|
||||
CGLRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format);
|
||||
~CGLRenderbuffer();
|
||||
|
||||
void bind() override;
|
||||
void unbind() override;
|
||||
void bind() override;
|
||||
void unbind() override;
|
||||
|
||||
private:
|
||||
void* m_image = nullptr;
|
||||
GLuint m_rbo = 0;
|
||||
};
|
||||
private:
|
||||
void* m_image = nullptr;
|
||||
GLuint m_rbo = 0;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include "../Texture.hpp"
|
||||
#include <cstring>
|
||||
|
||||
using namespace Render::GL;
|
||||
|
||||
CGLTexture::CGLTexture(bool opaque) {
|
||||
m_opaque = opaque;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,46 +4,49 @@
|
|||
#include <aquamarine/buffer/Buffer.hpp>
|
||||
#include <hyprutils/math/Misc.hpp>
|
||||
|
||||
class CGLTexture : public ITexture {
|
||||
public:
|
||||
using ITexture::ITexture;
|
||||
namespace Render::GL {
|
||||
|
||||
CGLTexture(CGLTexture&) = delete;
|
||||
CGLTexture(CGLTexture&&) = delete;
|
||||
CGLTexture(const CGLTexture&&) = delete;
|
||||
CGLTexture(const CGLTexture&) = delete;
|
||||
class CGLTexture : public ITexture {
|
||||
public:
|
||||
using ITexture::ITexture;
|
||||
|
||||
CGLTexture(bool opaque = false);
|
||||
CGLTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false);
|
||||
CGLTexture(const Aquamarine::SDMABUFAttrs&, void* image, bool opaque = false);
|
||||
CGLTexture(std::span<const float> lut3D, size_t N);
|
||||
~CGLTexture();
|
||||
CGLTexture(CGLTexture&) = delete;
|
||||
CGLTexture(CGLTexture&&) = delete;
|
||||
CGLTexture(const CGLTexture&&) = delete;
|
||||
CGLTexture(const CGLTexture&) = delete;
|
||||
|
||||
void allocate(const Vector2D& size, uint32_t drmFormat = 0) override;
|
||||
void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) override;
|
||||
void bind() override;
|
||||
void unbind() override;
|
||||
void setTexParameter(GLenum pname, GLint param) override;
|
||||
bool ok() override;
|
||||
bool isDMA() override;
|
||||
CGLTexture(bool opaque = false);
|
||||
CGLTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false);
|
||||
CGLTexture(const Aquamarine::SDMABUFAttrs&, void* image, bool opaque = false);
|
||||
CGLTexture(std::span<const float> lut3D, size_t N);
|
||||
~CGLTexture();
|
||||
|
||||
private:
|
||||
void* m_eglImage = nullptr;
|
||||
void allocate(const Vector2D& size, uint32_t drmFormat = 0) override;
|
||||
void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) override;
|
||||
void bind() override;
|
||||
void unbind() override;
|
||||
void setTexParameter(GLenum pname, GLint param) override;
|
||||
bool ok() override;
|
||||
bool isDMA() override;
|
||||
|
||||
enum eTextureParam : uint8_t {
|
||||
TEXTURE_PAR_WRAP_S = 0,
|
||||
TEXTURE_PAR_WRAP_T,
|
||||
TEXTURE_PAR_MAG_FILTER,
|
||||
TEXTURE_PAR_MIN_FILTER,
|
||||
TEXTURE_PAR_SWIZZLE_R,
|
||||
TEXTURE_PAR_SWIZZLE_B,
|
||||
TEXTURE_PAR_LAST,
|
||||
private:
|
||||
void* m_eglImage = nullptr;
|
||||
|
||||
enum eTextureParam : uint8_t {
|
||||
TEXTURE_PAR_WRAP_S = 0,
|
||||
TEXTURE_PAR_WRAP_T,
|
||||
TEXTURE_PAR_MAG_FILTER,
|
||||
TEXTURE_PAR_MIN_FILTER,
|
||||
TEXTURE_PAR_SWIZZLE_R,
|
||||
TEXTURE_PAR_SWIZZLE_B,
|
||||
TEXTURE_PAR_LAST,
|
||||
};
|
||||
|
||||
GLenum m_target = GL_TEXTURE_2D;
|
||||
|
||||
void swizzle(const std::array<GLint, 4>& colors);
|
||||
constexpr std::optional<size_t> getCacheStateIndex(GLenum pname);
|
||||
|
||||
std::array<std::optional<GLint>, TEXTURE_PAR_LAST> m_cachedStates;
|
||||
};
|
||||
|
||||
GLenum m_target = GL_TEXTURE_2D;
|
||||
|
||||
void swizzle(const std::array<GLint, 4>& colors);
|
||||
constexpr std::optional<size_t> getCacheStateIndex(GLenum pname);
|
||||
|
||||
std::array<std::optional<GLint>, TEXTURE_PAR_LAST> m_cachedStates;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@
|
|||
#include "../../render/Renderer.hpp"
|
||||
#include "../../desktop/state/FocusState.hpp"
|
||||
#include "../../protocols/core/Compositor.hpp"
|
||||
#include "RectPassElement.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "render/pass/ClearPassElement.hpp"
|
||||
|
||||
using namespace Render;
|
||||
|
||||
bool CRenderPass::empty() const {
|
||||
return false;
|
||||
|
|
@ -216,12 +221,12 @@ void CRenderPass::renderDebugData() {
|
|||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = Colors::RED.modifyA(0.1F);
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), rg);
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(data), rg);
|
||||
}
|
||||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = Colors::GREEN.modifyA(0.1F);
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), m_totalLiveBlurRegion);
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(data), m_totalLiveBlurRegion);
|
||||
|
||||
std::unordered_map<CWLSurfaceResource*, float> offsets;
|
||||
|
||||
|
|
@ -249,7 +254,7 @@ void CRenderPass::renderDebugData() {
|
|||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = color;
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), FULL_REGION);
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(data), FULL_REGION);
|
||||
|
||||
if (offsets.contains(surface.get()))
|
||||
box.translate(Vector2D{0.F, offsets[surface.get()]});
|
||||
|
|
@ -261,12 +266,12 @@ void CRenderPass::renderDebugData() {
|
|||
data.box = box;
|
||||
data.color = color;
|
||||
data.round = std::min(5.0, box.size().y);
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data2), FULL_REGION);
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(data2), FULL_REGION);
|
||||
|
||||
CTexPassElement::SRenderData texData;
|
||||
texData.tex = texture;
|
||||
texData.box = box;
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(texData), {});
|
||||
g_pHyprRenderer->draw(makeShared<CTexPassElement>(texData), {});
|
||||
|
||||
offsets[surface.get()] += texture->m_size.y;
|
||||
};
|
||||
|
|
@ -287,7 +292,7 @@ void CRenderPass::renderDebugData() {
|
|||
CRectPassElement::SRectData data;
|
||||
data.box = box;
|
||||
data.color = CHyprColor{0.8F, 0.8F, 0.2F, 0.4F};
|
||||
g_pHyprRenderer->draw(makeUnique<CRectPassElement>(data), region);
|
||||
g_pHyprRenderer->draw(makeShared<CRectPassElement>(data), region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -303,7 +308,7 @@ void CRenderPass::renderDebugData() {
|
|||
CTexPassElement::SRenderData texData;
|
||||
texData.tex = tex;
|
||||
texData.box = box;
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(texData), {});
|
||||
g_pHyprRenderer->draw(makeShared<CTexPassElement>(texData), {});
|
||||
}
|
||||
|
||||
std::string passStructure;
|
||||
|
|
@ -323,7 +328,7 @@ void CRenderPass::renderDebugData() {
|
|||
CTexPassElement::SRenderData texData;
|
||||
texData.tex = tex;
|
||||
texData.box = box;
|
||||
g_pHyprRenderer->draw(makeUnique<CTexPassElement>(texData), {});
|
||||
g_pHyprRenderer->draw(makeShared<CTexPassElement>(texData), {});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
#pragma once
|
||||
#include "PassElement.hpp"
|
||||
#include <optional>
|
||||
#include "../OpenGL.hpp"
|
||||
#include "../types.hpp"
|
||||
|
||||
class CRendererHintsPassElement : public IPassElement {
|
||||
public:
|
||||
struct SData {
|
||||
std::optional<SRenderModifData> renderModif;
|
||||
std::optional<Render::SRenderModifData> renderModif;
|
||||
};
|
||||
|
||||
CRendererHintsPassElement(const SData& data);
|
||||
|
|
|
|||
131
src/render/types.hpp
Normal file
131
src/render/types.hpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#pragma once
|
||||
|
||||
#include "Framebuffer.hpp"
|
||||
#include "../desktop/DesktopTypes.hpp"
|
||||
#include "../helpers/cm/ColorManagement.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include <hyprgraphics/color/Color.hpp>
|
||||
#include <hyprutils/math/Box.hpp>
|
||||
#include <hyprutils/math/Mat3x3.hpp>
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
|
||||
namespace Render {
|
||||
const std::vector<const char*> ASSET_PATHS = {
|
||||
#ifdef DATAROOTDIR
|
||||
DATAROOTDIR,
|
||||
#endif
|
||||
"/usr/share",
|
||||
"/usr/local/share",
|
||||
};
|
||||
|
||||
enum eDamageTrackingModes : int8_t {
|
||||
DAMAGE_TRACKING_INVALID = -1,
|
||||
DAMAGE_TRACKING_NONE = 0,
|
||||
DAMAGE_TRACKING_MONITOR,
|
||||
DAMAGE_TRACKING_FULL,
|
||||
};
|
||||
|
||||
enum eRenderPassMode : uint8_t {
|
||||
RENDER_PASS_ALL = 0,
|
||||
RENDER_PASS_MAIN,
|
||||
RENDER_PASS_POPUP
|
||||
};
|
||||
|
||||
enum eRenderMode : uint8_t {
|
||||
RENDER_MODE_NORMAL = 0,
|
||||
RENDER_MODE_FULL_FAKE = 1,
|
||||
RENDER_MODE_TO_BUFFER = 2,
|
||||
RENDER_MODE_TO_BUFFER_READ_ONLY = 3,
|
||||
};
|
||||
|
||||
struct SRenderWorkspaceUntilData {
|
||||
PHLLS ls;
|
||||
PHLWINDOW w;
|
||||
};
|
||||
|
||||
enum eRenderProjectionType : uint8_t {
|
||||
RPT_MONITOR,
|
||||
RPT_MIRROR,
|
||||
RPT_FB,
|
||||
RPT_EXPORT,
|
||||
};
|
||||
|
||||
struct SRenderModifData {
|
||||
enum eRenderModifType : uint8_t {
|
||||
RMOD_TYPE_SCALE, /* scale by a float */
|
||||
RMOD_TYPE_SCALECENTER, /* scale by a float from the center */
|
||||
RMOD_TYPE_TRANSLATE, /* translate by a Vector2D */
|
||||
RMOD_TYPE_ROTATE, /* rotate by a float in rad from top left */
|
||||
RMOD_TYPE_ROTATECENTER, /* rotate by a float in rad from center */
|
||||
};
|
||||
|
||||
std::vector<std::pair<eRenderModifType, std::any>> modifs;
|
||||
|
||||
void applyToBox(Hyprutils::Math::CBox& box);
|
||||
void applyToRegion(Hyprutils::Math::CRegion& rg);
|
||||
float combinedScale();
|
||||
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
struct SRenderData {
|
||||
// can be private
|
||||
Hyprutils::Math::Mat3x3 targetProjection;
|
||||
|
||||
// ----------------------
|
||||
|
||||
// used by public
|
||||
Hyprutils::Math::Vector2D fbSize = {-1, -1};
|
||||
PHLMONITORREF pMonitor;
|
||||
|
||||
eRenderProjectionType projectionType = RPT_MONITOR;
|
||||
|
||||
SP<IFramebuffer> currentFB = nullptr; // current rendering to
|
||||
SP<IFramebuffer> mainFB = nullptr; // main to render to
|
||||
SP<IFramebuffer> outFB = nullptr; // out to render to (if offloaded, etc)
|
||||
|
||||
CRegion damage;
|
||||
CRegion finalDamage; // damage used for funal off -> main
|
||||
|
||||
SRenderModifData renderModif;
|
||||
float mouseZoomFactor = 1.f;
|
||||
bool mouseZoomUseMouse = true; // true by default
|
||||
bool useNearestNeighbor = false;
|
||||
bool blockScreenShader = false;
|
||||
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
|
||||
// TODO remove and pass directly
|
||||
CBox clipBox = {}; // scaled coordinates
|
||||
PHLWINDOWREF currentWindow;
|
||||
WP<CWLSurfaceResource> surface;
|
||||
|
||||
bool transformDamage = true;
|
||||
bool noSimplify = false;
|
||||
};
|
||||
|
||||
struct STFRange {
|
||||
float min = 0;
|
||||
float max = 80;
|
||||
};
|
||||
|
||||
struct SCMSettings {
|
||||
NColorManagement::eTransferFunction sourceTF = NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22;
|
||||
NColorManagement::eTransferFunction targetTF = NColorManagement::CM_TRANSFER_FUNCTION_GAMMA22;
|
||||
STFRange srcTFRange;
|
||||
STFRange dstTFRange;
|
||||
float srcRefLuminance = 80;
|
||||
float dstRefLuminance = 80;
|
||||
std::array<std::array<double, 3>, 3> convertMatrix;
|
||||
|
||||
bool needsTonemap = false;
|
||||
float maxLuminance = 80;
|
||||
float dstMaxLuminance = 80;
|
||||
std::array<std::array<double, 3>, 3> dstPrimaries2XYZ;
|
||||
bool needsSDRmod = false;
|
||||
float sdrSaturation = 1.0;
|
||||
float sdrBrightnessMultiplier = 1.0;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue