renderer: refactor Texture, Framebuffer and Renderbuffer (#13437)
Some checks are pending
Build Hyprland / Build Hyprland (Arch) (push) Waiting to run
Build Hyprland / Code Style (push) Waiting to run
Nix / update-inputs (push) Waiting to run
Nix / hyprland (push) Waiting to run
Nix / xdph (push) Blocked by required conditions
Nix / test (push) Waiting to run
Security Checks / Flawfinder Checks (push) Waiting to run
Some checks are pending
Build Hyprland / Build Hyprland (Arch) (push) Waiting to run
Build Hyprland / Code Style (push) Waiting to run
Nix / update-inputs (push) Waiting to run
Nix / hyprland (push) Waiting to run
Nix / xdph (push) Blocked by required conditions
Nix / test (push) Waiting to run
Security Checks / Flawfinder Checks (push) Waiting to run
Part 1 of the renderer refactors
This commit is contained in:
parent
a5858018d8
commit
4152ac76d0
46 changed files with 1154 additions and 843 deletions
|
|
@ -8,7 +8,7 @@
|
|||
#include "../desktop/state/FocusState.hpp"
|
||||
|
||||
CHyprDebugOverlay::CHyprDebugOverlay() {
|
||||
m_texture = makeShared<CTexture>();
|
||||
m_texture = g_pHyprRenderer->createTexture();
|
||||
}
|
||||
|
||||
void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) {
|
||||
|
|
@ -259,15 +259,7 @@ void CHyprDebugOverlay::draw() {
|
|||
cairo_surface_flush(m_cairoSurface);
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(m_cairoSurface);
|
||||
m_texture->allocate();
|
||||
m_texture->bind();
|
||||
m_texture->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
m_texture->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
m_texture->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
m_texture->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
m_texture = g_pHyprRenderer->createTexture(m_cairoSurface);
|
||||
|
||||
CTexPassElement::SRenderData data;
|
||||
data.tex = m_texture;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class CHyprDebugOverlay {
|
|||
cairo_surface_t* m_cairoSurface = nullptr;
|
||||
cairo_t* m_cairo = nullptr;
|
||||
|
||||
SP<CTexture> m_texture;
|
||||
SP<ITexture> m_texture;
|
||||
|
||||
friend class CHyprMonitorDebugOverlay;
|
||||
friend class CHyprRenderer;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@ CHyprNotificationOverlay::CHyprNotificationOverlay() {
|
|||
|
||||
g_pHyprRenderer->damageBox(m_lastDamage);
|
||||
});
|
||||
|
||||
m_texture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
CHyprNotificationOverlay::~CHyprNotificationOverlay() {
|
||||
|
|
@ -232,16 +230,7 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
|
|||
|
||||
m_lastDamage = damage;
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(m_cairoSurface);
|
||||
m_texture->allocate();
|
||||
m_texture->bind();
|
||||
m_texture->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
m_texture->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
m_texture->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
m_texture->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
m_texture = g_pHyprRenderer->createTexture(m_cairoSurface);
|
||||
|
||||
CTexPassElement::SRenderData data;
|
||||
data.tex = m_texture;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ enum eIconBackend : uint8_t {
|
|||
static const std::array<std::array<std::string, ICON_NONE + 1>, 3 /* backends */> ICONS_ARRAY = {
|
||||
std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""},
|
||||
std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}};
|
||||
static const std::array<CHyprColor, ICON_NONE + 1> ICONS_COLORS = {CHyprColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
|
||||
static const std::array<CHyprColor, ICON_NONE + 1> ICONS_COLORS = {CHyprColor{1.0, 204 / 255.0, 102 / 255.0, 1.0},
|
||||
CHyprColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
|
||||
CHyprColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
|
||||
CHyprColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0},
|
||||
|
|
@ -57,7 +57,7 @@ class CHyprNotificationOverlay {
|
|||
PHLMONITORREF m_lastMonitor;
|
||||
Vector2D m_lastSize = Vector2D(-1, -1);
|
||||
|
||||
SP<CTexture> m_texture;
|
||||
SP<ITexture> m_texture;
|
||||
};
|
||||
|
||||
inline UP<CHyprNotificationOverlay> g_pHyprNotificationOverlay;
|
||||
|
|
|
|||
|
|
@ -1879,7 +1879,7 @@ uint16_t CMonitor::isDSBlocked(bool full) {
|
|||
|
||||
// we can't scanout shm buffers.
|
||||
const auto params = PSURFACE->m_current.buffer->dmabuf();
|
||||
if (!params.success || !PSURFACE->m_current.texture->m_eglImage /* dmabuf */) {
|
||||
if (!params.success || !PSURFACE->m_current.texture->isDMA() /* dmabuf */) {
|
||||
reasons |= DS_BLOCK_DMA;
|
||||
if (!full)
|
||||
return reasons;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#define HDR_REF_LUMINANCE 203.0
|
||||
#define HLG_MAX_LUMINANCE 1000.0
|
||||
|
||||
class CTexture;
|
||||
class ITexture;
|
||||
|
||||
namespace NColorManagement {
|
||||
enum eNoShader : uint8_t {
|
||||
|
|
@ -219,7 +219,7 @@ namespace NColorManagement {
|
|||
bool present = false;
|
||||
size_t lutSize = 33;
|
||||
std::vector<float> lutDataPacked;
|
||||
SP<CTexture> lutTexture;
|
||||
SP<ITexture> lutTexture;
|
||||
std::optional<SVCGTTable16> vcgt;
|
||||
} icc;
|
||||
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ static std::expected<void, std::string> buildIcc3DLut(cmsHPROFILE profile, SImag
|
|||
Log::logger->log(Log::DEBUG, "3D LUT constructed, size {}", image.icc.lutDataPacked.size());
|
||||
|
||||
// upload
|
||||
image.icc.lutTexture = makeShared<CTexture>(image.icc.lutDataPacked, image.icc.lutSize);
|
||||
image.icc.lutTexture = g_pHyprRenderer->createTexture(image.icc.lutDataPacked, image.icc.lutSize);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ CHyprError::CHyprError() {
|
|||
if (m_fadeOpacity->isBeingAnimated() || m_monitorChanged)
|
||||
g_pHyprRenderer->damageBox(m_damageBox);
|
||||
});
|
||||
|
||||
m_texture = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
void CHyprError::queueCreate(std::string message, const CHyprColor& color) {
|
||||
|
|
@ -40,8 +38,8 @@ void CHyprError::queueCreate(std::string message, const CHyprColor& color) {
|
|||
}
|
||||
|
||||
void CHyprError::createQueued() {
|
||||
if (m_isCreated)
|
||||
m_texture->destroyTexture();
|
||||
if (m_isCreated && m_texture)
|
||||
m_texture.reset();
|
||||
|
||||
m_fadeOpacity->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
|
||||
|
||||
|
|
@ -145,12 +143,13 @@ void CHyprError::createQueued() {
|
|||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
m_texture->allocate();
|
||||
m_texture->bind();
|
||||
m_texture->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
m_texture->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
m_texture->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
m_texture->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
auto tex = texture();
|
||||
tex->allocate(PMONITOR->m_pixelSize);
|
||||
tex->bind();
|
||||
tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
|
|
@ -187,7 +186,8 @@ void CHyprError::draw() {
|
|||
if (!m_fadeOpacity->isBeingAnimated()) {
|
||||
if (m_fadeOpacity->value() == 0.f) {
|
||||
m_queuedDestroy = false;
|
||||
m_texture->destroyTexture();
|
||||
if (m_texture)
|
||||
m_texture.reset();
|
||||
m_isCreated = false;
|
||||
m_queued = "";
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ void CHyprError::draw() {
|
|||
m_monitorChanged = false;
|
||||
|
||||
CTexPassElement::SRenderData data;
|
||||
data.tex = m_texture;
|
||||
data.tex = texture();
|
||||
data.box = monbox;
|
||||
data.a = m_fadeOpacity->value();
|
||||
|
||||
|
|
@ -239,3 +239,9 @@ bool CHyprError::active() {
|
|||
float CHyprError::height() {
|
||||
return m_lastHeight;
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprError::texture() {
|
||||
if (!m_texture)
|
||||
m_texture = g_pHyprRenderer->createTexture();
|
||||
return m_texture;
|
||||
}
|
||||
|
|
@ -18,13 +18,16 @@ class CHyprError {
|
|||
bool active();
|
||||
float height(); // logical
|
||||
|
||||
//
|
||||
SP<ITexture> texture();
|
||||
|
||||
private:
|
||||
void createQueued();
|
||||
std::string m_queued = "";
|
||||
CHyprColor m_queuedColor;
|
||||
bool m_queuedDestroy = false;
|
||||
bool m_isCreated = false;
|
||||
SP<CTexture> m_texture;
|
||||
SP<ITexture> m_texture;
|
||||
PHLANIMVAR<float> m_fadeOpacity;
|
||||
CBox m_damageBox = {0, 0, 0, 0};
|
||||
float m_lastHeight = 0.F;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "../protocols/IdleNotify.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../protocols/core/Seat.hpp"
|
||||
#include "debug/log/Logger.hpp"
|
||||
#include "eventLoop/EventLoopManager.hpp"
|
||||
#include "../render/pass/TexPassElement.hpp"
|
||||
#include "../managers/input/InputManager.hpp"
|
||||
|
|
@ -22,6 +23,8 @@
|
|||
#include <cstring>
|
||||
#include <gbm.h>
|
||||
#include <cairo/cairo.h>
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
|
||||
using namespace Hyprutils::Utils;
|
||||
|
|
@ -407,7 +410,7 @@ bool CPointerManager::setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquam
|
|||
return true;
|
||||
}
|
||||
|
||||
SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
|
||||
SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager::SMonitorPointerState> state, SP<ITexture> texture) {
|
||||
auto maxSize = state->monitor->m_output->cursorPlaneSize();
|
||||
auto const& cursorSize = m_currentCursorImage.size;
|
||||
|
||||
|
|
@ -900,13 +903,13 @@ const CPointerManager::SCursorImage& CPointerManager::currentCursorImage() {
|
|||
return m_currentCursorImage;
|
||||
}
|
||||
|
||||
SP<CTexture> CPointerManager::getCurrentCursorTexture() {
|
||||
SP<ITexture> CPointerManager::getCurrentCursorTexture() {
|
||||
if (!m_currentCursorImage.pBuffer && (!m_currentCursorImage.surface || !m_currentCursorImage.surface->resource()->m_current.texture))
|
||||
return nullptr;
|
||||
|
||||
if (m_currentCursorImage.pBuffer) {
|
||||
if (!m_currentCursorImage.bufferTex)
|
||||
m_currentCursorImage.bufferTex = makeShared<CTexture>(m_currentCursorImage.pBuffer, true);
|
||||
m_currentCursorImage.bufferTex = g_pHyprRenderer->createTexture(m_currentCursorImage.pBuffer, true);
|
||||
return m_currentCursorImage.bufferTex;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
class CMonitor;
|
||||
class IHID;
|
||||
class CTexture;
|
||||
class ITexture;
|
||||
|
||||
AQUAMARINE_FORWARD(IBuffer);
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ class CPointerManager {
|
|||
|
||||
struct SCursorImage {
|
||||
SP<Aquamarine::IBuffer> pBuffer;
|
||||
SP<CTexture> bufferTex;
|
||||
SP<ITexture> bufferTex;
|
||||
WP<Desktop::View::CWLSurface> surface;
|
||||
|
||||
Vector2D hotspot;
|
||||
|
|
@ -83,7 +83,7 @@ class CPointerManager {
|
|||
};
|
||||
|
||||
const SCursorImage& currentCursorImage();
|
||||
SP<CTexture> getCurrentCursorTexture();
|
||||
SP<ITexture> getCurrentCursorTexture();
|
||||
|
||||
struct {
|
||||
CSignalT<> cursorChanged;
|
||||
|
|
@ -181,7 +181,7 @@ class CPointerManager {
|
|||
std::vector<SP<SMonitorPointerState>> m_monitorStates;
|
||||
SP<SMonitorPointerState> stateFor(PHLMONITOR mon);
|
||||
bool attemptHardwareCursor(SP<SMonitorPointerState> state);
|
||||
SP<Aquamarine::IBuffer> renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<CTexture> texture);
|
||||
SP<Aquamarine::IBuffer> renderHWCursorBuffer(SP<SMonitorPointerState> state, SP<ITexture> texture);
|
||||
bool setHWCursorBuffer(SP<SMonitorPointerState> state, SP<Aquamarine::IBuffer> buf);
|
||||
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -169,10 +169,10 @@ bool CCursorshareSession::copy() {
|
|||
return false;
|
||||
}
|
||||
|
||||
CFramebuffer outFB;
|
||||
outFB.alloc(m_bufferSize.x, m_bufferSize.y, m_format);
|
||||
auto outFB = g_pHyprRenderer->createFB();
|
||||
outFB->alloc(m_bufferSize.x, m_bufferSize.y, m_format);
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(m_pendingFrame.monitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB, true)) {
|
||||
if (!g_pHyprRenderer->beginRender(m_pendingFrame.monitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, outFB, true)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering to shm");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -182,8 +182,8 @@ bool CCursorshareSession::copy() {
|
|||
g_pHyprRenderer->endRender();
|
||||
|
||||
g_pHyprOpenGL->m_renderData.pMonitor = m_pendingFrame.monitor;
|
||||
outFB.bind();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID());
|
||||
outFB->bind();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, GLFB(outFB)->getFBID());
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ bool CCursorshareSession::copy() {
|
|||
g_pHyprOpenGL->m_renderData.pMonitor.reset();
|
||||
|
||||
m_pendingFrame.buffer->endDataPtr();
|
||||
outFB.unbind();
|
||||
GLFB(outFB)->unbind();
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "../../helpers/Monitor.hpp"
|
||||
#include "../../desktop/view/Window.hpp"
|
||||
#include "../../desktop/state/FocusState.hpp"
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
|
||||
using namespace Screenshare;
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ void CScreenshareFrame::copy() {
|
|||
// store a snapshot before the permission popup so we don't break screenshots
|
||||
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_session->m_client, PERMISSION_TYPE_SCREENCOPY);
|
||||
if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) {
|
||||
if (!m_session->m_tempFB.isAllocated())
|
||||
if (!m_session->m_tempFB || !m_session->m_tempFB->isAllocated())
|
||||
storeTempFB();
|
||||
|
||||
// don't copy a frame while allow is pending because screenshot tools will only take the first frame we give, which is empty
|
||||
|
|
@ -159,10 +160,7 @@ void CScreenshareFrame::renderMonitor() {
|
|||
|
||||
const auto PMONITOR = m_session->monitor();
|
||||
|
||||
if (!g_pHyprOpenGL->m_monitorRenderResources.contains(PMONITOR))
|
||||
return; // wtf?
|
||||
|
||||
auto TEXTURE = g_pHyprOpenGL->m_monitorRenderResources[PMONITOR].monitorMirrorFB.getTexture();
|
||||
auto TEXTURE = g_pHyprRenderer->createTexture(PMONITOR->m_output->state->state().buffer);
|
||||
|
||||
const bool IS_CM_AWARE = PROTO::colorManagement && PROTO::colorManagement->isClientCMAware(m_session->m_client);
|
||||
g_pHyprOpenGL->m_renderData.transformDamage = false;
|
||||
|
|
@ -328,10 +326,10 @@ void CScreenshareFrame::render() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_session->m_tempFB.isAllocated()) {
|
||||
if (m_session->m_tempFB && m_session->m_tempFB->isAllocated()) {
|
||||
CBox texbox = {{}, m_bufferSize};
|
||||
g_pHyprOpenGL->renderTexture(m_session->m_tempFB.getTexture(), texbox, {});
|
||||
m_session->m_tempFB.release();
|
||||
g_pHyprOpenGL->renderTexture(m_session->m_tempFB->getTexture(), texbox, {});
|
||||
m_session->m_tempFB->release();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -384,12 +382,12 @@ bool CScreenshareFrame::copyShm() {
|
|||
return false;
|
||||
}
|
||||
|
||||
const auto PMONITOR = m_session->monitor();
|
||||
const auto PMONITOR = m_session->monitor();
|
||||
|
||||
CFramebuffer outFB;
|
||||
outFB.alloc(m_bufferSize.x, m_bufferSize.y, shm.format);
|
||||
auto outFB = g_pHyprRenderer->createFB();
|
||||
outFB->alloc(m_bufferSize.x, m_bufferSize.y, shm.format);
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(PMONITOR, m_damage, RENDER_MODE_FULL_FAKE, nullptr, &outFB, true)) {
|
||||
if (!g_pHyprRenderer->beginRender(PMONITOR, m_damage, RENDER_MODE_FULL_FAKE, nullptr, outFB, true)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -401,8 +399,8 @@ bool CScreenshareFrame::copyShm() {
|
|||
g_pHyprRenderer->endRender();
|
||||
|
||||
g_pHyprOpenGL->m_renderData.pMonitor = PMONITOR;
|
||||
outFB.bind();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.getFBID());
|
||||
outFB->bind();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, GLFB(outFB)->getFBID());
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
|
|
@ -444,7 +442,7 @@ bool CScreenshareFrame::copyShm() {
|
|||
});
|
||||
}
|
||||
|
||||
outFB.unbind();
|
||||
GLFB(outFB)->unbind();
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
|
|
@ -459,13 +457,13 @@ bool CScreenshareFrame::copyShm() {
|
|||
}
|
||||
|
||||
void CScreenshareFrame::storeTempFB() {
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
m_session->m_tempFB.alloc(m_bufferSize.x, m_bufferSize.y);
|
||||
if (!m_session->m_tempFB)
|
||||
m_session->m_tempFB = g_pHyprRenderer->createFB();
|
||||
m_session->m_tempFB->alloc(m_bufferSize.x, m_bufferSize.y);
|
||||
|
||||
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(m_session->monitor(), fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &m_session->m_tempFB, true)) {
|
||||
if (!g_pHyprRenderer->beginRender(m_session->monitor(), fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, m_session->m_tempFB, true)) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to begin rendering to temp fb");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace Screenshare {
|
|||
std::vector<DRMFormat> m_formats;
|
||||
Vector2D m_bufferSize = Vector2D(0, 0);
|
||||
|
||||
CFramebuffer m_tempFB;
|
||||
SP<IFramebuffer> m_tempFB;
|
||||
|
||||
SP<CEventLoopTimer> m_shareStopTimer;
|
||||
bool m_sharing = false;
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ CSinglePixelBuffer::CSinglePixelBuffer(uint32_t id, wl_client* client, CHyprColo
|
|||
|
||||
m_opaque = col_.a >= 1.F;
|
||||
|
||||
m_texture = makeShared<CTexture>(DRM_FORMAT_ARGB8888, rc<uint8_t*>(&m_color), 4, Vector2D{1, 1});
|
||||
m_texture = g_pHyprRenderer->createTexture(DRM_FORMAT_ARGB8888, rc<uint8_t*>(&m_color), 4, Vector2D{1, 1});
|
||||
|
||||
m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));
|
||||
|
||||
m_success = m_texture->m_texID;
|
||||
m_success = m_texture->ok();
|
||||
|
||||
size = {1, 1};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class IHLBuffer : public Aquamarine::IBuffer {
|
|||
void onBackendRelease(const std::function<void()>& fn);
|
||||
void addReleasePoint(CDRMSyncPointState& point);
|
||||
|
||||
SP<CTexture> m_texture;
|
||||
SP<ITexture> m_texture;
|
||||
bool m_opaque = false;
|
||||
SP<CWLBufferResource> m_resource;
|
||||
std::vector<UP<CSyncReleaser>> m_syncReleasers;
|
||||
|
|
|
|||
|
|
@ -13,31 +13,28 @@
|
|||
using namespace Hyprutils::OS;
|
||||
|
||||
CDMABuffer::CDMABuffer(uint32_t id, wl_client* client, Aquamarine::SDMABUFAttrs const& attrs_) : m_attrs(attrs_) {
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
m_listeners.resourceDestroy = events.destroy.listen([this] {
|
||||
closeFDs();
|
||||
m_listeners.resourceDestroy.reset();
|
||||
});
|
||||
|
||||
size = m_attrs.size;
|
||||
m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));
|
||||
auto eglImage = g_pHyprOpenGL->createEGLImage(m_attrs);
|
||||
size = m_attrs.size;
|
||||
m_resource = CWLBufferResource::create(makeShared<CWlBuffer>(client, 1, id));
|
||||
m_opaque = NFormatUtils::isFormatOpaque(m_attrs.format);
|
||||
m_texture = g_pHyprRenderer->createTexture(m_attrs, m_opaque); // texture takes ownership of the eglImage
|
||||
|
||||
if UNLIKELY (!eglImage) {
|
||||
if UNLIKELY (!m_texture) {
|
||||
Log::logger->log(Log::ERR, "CDMABuffer: failed to import EGLImage, retrying as implicit");
|
||||
m_attrs.modifier = DRM_FORMAT_MOD_INVALID;
|
||||
eglImage = g_pHyprOpenGL->createEGLImage(m_attrs);
|
||||
m_texture = g_pHyprRenderer->createTexture(m_attrs, m_opaque);
|
||||
|
||||
if UNLIKELY (!eglImage) {
|
||||
if UNLIKELY (!m_texture) {
|
||||
Log::logger->log(Log::ERR, "CDMABuffer: failed to import EGLImage");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_texture = makeShared<CTexture>(m_attrs, eglImage); // texture takes ownership of the eglImage
|
||||
m_opaque = NFormatUtils::isFormatOpaque(m_attrs.format);
|
||||
m_success = m_texture->m_texID;
|
||||
m_success = m_texture->ok();
|
||||
|
||||
if UNLIKELY (!m_success)
|
||||
Log::logger->log(Log::ERR, "Failed to create a dmabuf: texture is null");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "SurfaceState.hpp"
|
||||
#include "helpers/Format.hpp"
|
||||
#include "protocols/types/Buffer.hpp"
|
||||
#include "render/Renderer.hpp"
|
||||
#include "render/Texture.hpp"
|
||||
|
||||
Vector2D SSurfaceState::sourceSize() {
|
||||
|
|
@ -34,7 +35,7 @@ CRegion SSurfaceState::accumulateBufferDamage() {
|
|||
return bufferDamage;
|
||||
}
|
||||
|
||||
void SSurfaceState::updateSynchronousTexture(SP<CTexture> lastTexture) {
|
||||
void SSurfaceState::updateSynchronousTexture(SP<ITexture> lastTexture) {
|
||||
auto [dataPtr, fmt, size] = buffer->beginDataPtr(0);
|
||||
if (dataPtr) {
|
||||
auto drmFmt = NFormatUtils::shmToDRM(fmt);
|
||||
|
|
@ -43,7 +44,7 @@ void SSurfaceState::updateSynchronousTexture(SP<CTexture> lastTexture) {
|
|||
texture = lastTexture;
|
||||
texture->update(drmFmt, dataPtr, stride, accumulateBufferDamage());
|
||||
} else
|
||||
texture = makeShared<CTexture>(drmFmt, dataPtr, stride, bufferSize);
|
||||
texture = g_pHyprRenderer->createTexture(drmFmt, dataPtr, stride, bufferSize);
|
||||
}
|
||||
buffer->endDataPtr();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include "../WaylandProtocol.hpp"
|
||||
#include "./Buffer.hpp"
|
||||
|
||||
class CTexture;
|
||||
class ITexture;
|
||||
class CDRMSyncPointState;
|
||||
class CWLCallbackResource;
|
||||
|
||||
|
|
@ -88,8 +88,8 @@ struct SSurfaceState {
|
|||
eLockReason lockMask = LOCK_REASON_NONE;
|
||||
|
||||
// texture of surface content, used for rendering
|
||||
SP<CTexture> texture;
|
||||
void updateSynchronousTexture(SP<CTexture> lastTexture);
|
||||
SP<ITexture> texture;
|
||||
void updateSynchronousTexture(SP<ITexture> lastTexture);
|
||||
|
||||
// fifo
|
||||
bool barrierSet = false;
|
||||
|
|
|
|||
|
|
@ -1,140 +1,30 @@
|
|||
#include "Framebuffer.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
|
||||
CFramebuffer::CFramebuffer() {
|
||||
;
|
||||
}
|
||||
IFramebuffer::IFramebuffer(const std::string& name) : m_name(name) {}
|
||||
|
||||
bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
|
||||
bool firstAlloc = false;
|
||||
bool IFramebuffer::alloc(int w, int h, uint32_t format) {
|
||||
RASSERT((w > 0 && h > 0), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h);
|
||||
|
||||
const bool sizeChanged = (m_size != Vector2D(w, h));
|
||||
const bool formatChanged = (drmFormat != m_drmFormat);
|
||||
const bool formatChanged = (format != m_drmFormat);
|
||||
|
||||
if (!m_tex) {
|
||||
m_tex = makeShared<CTexture>();
|
||||
m_tex->allocate();
|
||||
m_tex->bind();
|
||||
m_tex->setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
m_tex->setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
m_tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
m_tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
firstAlloc = true;
|
||||
}
|
||||
if (m_fbAllocated && !sizeChanged && !formatChanged)
|
||||
return true;
|
||||
|
||||
if (!m_fbAllocated) {
|
||||
glGenFramebuffers(1, &m_fb);
|
||||
m_fbAllocated = true;
|
||||
firstAlloc = true;
|
||||
}
|
||||
|
||||
if (firstAlloc || sizeChanged || formatChanged) {
|
||||
const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
m_tex->bind();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, w, h, 0, format->glFormat, format->glType, nullptr);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex->m_texID, 0);
|
||||
|
||||
if (m_stencilTex) {
|
||||
m_stencilTex->bind();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_stencilTex->m_texID, 0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Framebuffer incomplete, couldn't create! (FB status: {}, GL Error: 0x{:x})", status, sc<int>(glGetError()));
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Framebuffer created, status {}", status);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
m_drmFormat = drmFormat;
|
||||
m_size = Vector2D(w, h);
|
||||
|
||||
return true;
|
||||
m_size = {w, h};
|
||||
m_drmFormat = format;
|
||||
m_fbAllocated = internalAlloc(w, h, format);
|
||||
return m_fbAllocated;
|
||||
}
|
||||
|
||||
void CFramebuffer::addStencil(SP<CTexture> tex) {
|
||||
if (m_stencilTex == tex)
|
||||
return;
|
||||
|
||||
m_stencilTex = tex;
|
||||
m_stencilTex->bind();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_size.x, m_size.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_stencilTex->m_texID, 0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Failed adding a stencil to fbo!", status);
|
||||
|
||||
m_stencilTex->unbind();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void CFramebuffer::bind() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb);
|
||||
|
||||
if (g_pHyprOpenGL)
|
||||
g_pHyprOpenGL->setViewport(0, 0, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.x, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.y);
|
||||
else
|
||||
glViewport(0, 0, m_size.x, m_size.y);
|
||||
}
|
||||
|
||||
void CFramebuffer::unbind() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void CFramebuffer::release() {
|
||||
if (m_fbAllocated) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glDeleteFramebuffers(1, &m_fb);
|
||||
m_fbAllocated = false;
|
||||
m_fb = 0;
|
||||
}
|
||||
|
||||
if (m_tex)
|
||||
m_tex.reset();
|
||||
|
||||
m_size = Vector2D();
|
||||
}
|
||||
|
||||
CFramebuffer::~CFramebuffer() {
|
||||
release();
|
||||
}
|
||||
|
||||
bool CFramebuffer::isAllocated() {
|
||||
bool IFramebuffer::isAllocated() {
|
||||
return m_fbAllocated && m_tex;
|
||||
}
|
||||
|
||||
SP<CTexture> CFramebuffer::getTexture() {
|
||||
SP<ITexture> IFramebuffer::getTexture() {
|
||||
return m_tex;
|
||||
}
|
||||
|
||||
GLuint CFramebuffer::getFBID() {
|
||||
return m_fbAllocated ? m_fb : 0;
|
||||
}
|
||||
|
||||
SP<CTexture> CFramebuffer::getStencilTex() {
|
||||
SP<ITexture> IFramebuffer::getStencilTex() {
|
||||
return m_stencilTex;
|
||||
}
|
||||
|
||||
void CFramebuffer::invalidate(const std::vector<GLenum>& attachments) {
|
||||
if (!isAllocated())
|
||||
return;
|
||||
|
||||
glInvalidateFramebuffer(GL_FRAMEBUFFER, attachments.size(), attachments.data());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,34 +3,38 @@
|
|||
#include "../defines.hpp"
|
||||
#include "../helpers/Format.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include <cstdint>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
class CFramebuffer {
|
||||
public:
|
||||
CFramebuffer();
|
||||
~CFramebuffer();
|
||||
class CHLBufferReference;
|
||||
|
||||
class IFramebuffer {
|
||||
public:
|
||||
IFramebuffer() = default;
|
||||
IFramebuffer(const std::string& name);
|
||||
virtual ~IFramebuffer() = default;
|
||||
|
||||
virtual bool alloc(int w, int h, uint32_t format = DRM_FORMAT_ARGB8888);
|
||||
virtual void release() = 0;
|
||||
virtual bool readPixels(CHLBufferReference buffer, uint32_t offsetX = 0, uint32_t offsetY = 0, uint32_t width = 0, uint32_t height = 0) = 0;
|
||||
|
||||
virtual void bind() = 0;
|
||||
|
||||
bool alloc(int w, int h, uint32_t format = DRM_FORMAT_ARGB8888);
|
||||
void addStencil(SP<CTexture> tex);
|
||||
void bind();
|
||||
void unbind();
|
||||
void release();
|
||||
void reset();
|
||||
bool isAllocated();
|
||||
SP<CTexture> getTexture();
|
||||
SP<CTexture> getStencilTex();
|
||||
GLuint getFBID();
|
||||
void invalidate(const std::vector<GLenum>& attachments);
|
||||
SP<ITexture> getTexture();
|
||||
SP<ITexture> getStencilTex();
|
||||
|
||||
virtual void addStencil(SP<ITexture> tex) = 0;
|
||||
|
||||
Vector2D m_size;
|
||||
DRMFormat m_drmFormat = 0 /* DRM_FORMAT_INVALID */;
|
||||
DRMFormat m_drmFormat = DRM_FORMAT_INVALID;
|
||||
|
||||
private:
|
||||
SP<CTexture> m_tex;
|
||||
GLuint m_fb = -1;
|
||||
protected:
|
||||
virtual bool internalAlloc(int w, int h, uint32_t format = DRM_FORMAT_ARGB8888) = 0;
|
||||
|
||||
SP<ITexture> m_tex;
|
||||
bool m_fbAllocated = false;
|
||||
|
||||
SP<CTexture> m_stencilTex;
|
||||
|
||||
friend class CRenderbuffer;
|
||||
SP<ITexture> m_stencilTex;
|
||||
std::string m_name; // name for logging
|
||||
};
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@
|
|||
#include "ShaderLoader.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include <filesystem>
|
||||
#include "gl/GLFramebuffer.hpp"
|
||||
#include "gl/GLTexture.hpp"
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
using namespace NColorManagement;
|
||||
|
|
@ -644,7 +646,7 @@ EGLImageKHR CHyprOpenGLImpl::createEGLImage(const Aquamarine::SDMABUFAttrs& attr
|
|||
return image;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP<CRenderbuffer> rb, CFramebuffer* fb) {
|
||||
void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP<IRenderbuffer> rb, SP<IFramebuffer> fb) {
|
||||
m_renderData.pMonitor = pMonitor;
|
||||
|
||||
const GLenum RESETSTATUS = glGetGraphicsResetStatus();
|
||||
|
|
@ -697,7 +699,7 @@ void CHyprOpenGLImpl::beginSimple(PHLMONITOR pMonitor, const CRegion& damage, SP
|
|||
pushMonitorTransformEnabled(false);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFramebuffer* fb, std::optional<CRegion> finalDamage) {
|
||||
void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, SP<IFramebuffer> fb, std::optional<CRegion> finalDamage) {
|
||||
m_renderData.pMonitor = pMonitor;
|
||||
|
||||
const GLenum RESETSTATUS = glGetGraphicsResetStatus();
|
||||
|
|
@ -721,7 +723,8 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
|
|||
|
||||
m_renderData.monitorProjection = pMonitor->m_projMatrix;
|
||||
|
||||
if (m_monitorRenderResources.contains(pMonitor) && m_monitorRenderResources.at(pMonitor).offloadFB.m_size != pMonitor->m_pixelSize)
|
||||
if (m_monitorRenderResources.contains(pMonitor) &&
|
||||
(!m_monitorRenderResources.at(pMonitor).offloadFB || m_monitorRenderResources.at(pMonitor).offloadFB->m_size != pMonitor->m_pixelSize))
|
||||
destroyMonitorResources(pMonitor);
|
||||
|
||||
m_renderData.pCurrentMonData = &m_monitorRenderResources[pMonitor];
|
||||
|
|
@ -732,26 +735,30 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
|
|||
const auto DRM_FORMAT = fb ? fb->m_drmFormat : pMonitor->m_output->state->state().drmFormat;
|
||||
|
||||
// ensure a framebuffer for the monitor exists
|
||||
if (m_renderData.pCurrentMonData->offloadFB.m_size != pMonitor->m_pixelSize || DRM_FORMAT != m_renderData.pCurrentMonData->offloadFB.m_drmFormat) {
|
||||
m_renderData.pCurrentMonData->stencilTex->allocate();
|
||||
if (!m_renderData.pCurrentMonData->offloadFB || m_renderData.pCurrentMonData->offloadFB->m_size != pMonitor->m_pixelSize ||
|
||||
DRM_FORMAT != m_renderData.pCurrentMonData->offloadFB->m_drmFormat) {
|
||||
m_renderData.pCurrentMonData->stencilTex = g_pHyprRenderer->createStencilTexture(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y);
|
||||
m_renderData.pCurrentMonData->offloadFB = g_pHyprRenderer->createFB();
|
||||
m_renderData.pCurrentMonData->mirrorFB = g_pHyprRenderer->createFB();
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB = g_pHyprRenderer->createFB();
|
||||
|
||||
m_renderData.pCurrentMonData->offloadFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
|
||||
m_renderData.pCurrentMonData->mirrorFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
|
||||
m_renderData.pCurrentMonData->offloadFB->addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
m_renderData.pCurrentMonData->mirrorFB->addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB->addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
|
||||
m_renderData.pCurrentMonData->offloadFB.addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
m_renderData.pCurrentMonData->mirrorFB.addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB.addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
m_renderData.pCurrentMonData->offloadFB->alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
|
||||
m_renderData.pCurrentMonData->mirrorFB->alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB->alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, DRM_FORMAT);
|
||||
}
|
||||
|
||||
const bool HAS_MIRROR_FB = m_renderData.pCurrentMonData->monitorMirrorFB.isAllocated();
|
||||
const bool HAS_MIRROR_FB = m_renderData.pCurrentMonData->monitorMirrorFB && m_renderData.pCurrentMonData->monitorMirrorFB->isAllocated();
|
||||
const bool NEEDS_COPY_FB = needsACopyFB(m_renderData.pMonitor.lock());
|
||||
|
||||
if (HAS_MIRROR_FB && !NEEDS_COPY_FB)
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB.release();
|
||||
else if (!HAS_MIRROR_FB && NEEDS_COPY_FB)
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB.alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y,
|
||||
m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB->release();
|
||||
else if (!HAS_MIRROR_FB && NEEDS_COPY_FB && m_renderData.pCurrentMonData->monitorMirrorFB)
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB->alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y,
|
||||
m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
|
||||
m_renderData.transformDamage = true;
|
||||
if (HAS_MIRROR_FB != NEEDS_COPY_FB) {
|
||||
|
|
@ -771,8 +778,8 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
|
|||
applyScreenShader(*PSHADER);
|
||||
}
|
||||
|
||||
m_renderData.pCurrentMonData->offloadFB.bind();
|
||||
m_renderData.currentFB = &m_renderData.pCurrentMonData->offloadFB;
|
||||
m_renderData.pCurrentMonData->offloadFB->bind();
|
||||
m_renderData.currentFB = m_renderData.pCurrentMonData->offloadFB;
|
||||
m_offloadedFramebuffer = true;
|
||||
|
||||
m_renderData.mainFB = m_renderData.currentFB;
|
||||
|
|
@ -819,9 +826,9 @@ void CHyprOpenGLImpl::end() {
|
|||
m_finalScreenShader->program() >= 1 || g_pHyprRenderer->m_crashingInProgress || m_renderData.pMonitor->m_imageDescription->value() != SImageDescription{};
|
||||
|
||||
if LIKELY (!PRIMITIVE_BLOCKED || g_pHyprRenderer->m_renderMode != RENDER_MODE_NORMAL)
|
||||
renderTexturePrimitive(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox);
|
||||
renderTexturePrimitive(m_renderData.pCurrentMonData->offloadFB->getTexture(), monbox);
|
||||
else // we need to use renderTexture if we do any CM whatsoever.
|
||||
renderTexture(m_renderData.pCurrentMonData->offloadFB.getTexture(), monbox, {.finalMonitorCM = true});
|
||||
renderTexture(m_renderData.pCurrentMonData->offloadFB->getTexture(), monbox, {.finalMonitorCM = true});
|
||||
|
||||
blend(true);
|
||||
|
||||
|
|
@ -831,14 +838,22 @@ void CHyprOpenGLImpl::end() {
|
|||
}
|
||||
|
||||
// invalidate our render FBs to signal to the driver we don't need them anymore
|
||||
m_renderData.pCurrentMonData->mirrorFB.bind();
|
||||
m_renderData.pCurrentMonData->mirrorFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB.bind();
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
m_renderData.pCurrentMonData->offloadFB.bind();
|
||||
m_renderData.pCurrentMonData->offloadFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
m_renderData.pCurrentMonData->offMainFB.bind();
|
||||
m_renderData.pCurrentMonData->offMainFB.invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
if (m_renderData.pCurrentMonData->mirrorFB) {
|
||||
m_renderData.pCurrentMonData->mirrorFB->bind();
|
||||
GLFB(m_renderData.pCurrentMonData->mirrorFB)->invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
}
|
||||
if (m_renderData.pCurrentMonData->mirrorSwapFB) {
|
||||
m_renderData.pCurrentMonData->mirrorSwapFB->bind();
|
||||
GLFB(m_renderData.pCurrentMonData->mirrorSwapFB)->invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
}
|
||||
if (m_renderData.pCurrentMonData->offloadFB) {
|
||||
m_renderData.pCurrentMonData->offloadFB->bind();
|
||||
GLFB(m_renderData.pCurrentMonData->offloadFB)->invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
}
|
||||
if (m_renderData.pCurrentMonData->offMainFB) {
|
||||
m_renderData.pCurrentMonData->offMainFB->bind();
|
||||
GLFB(m_renderData.pCurrentMonData->offMainFB)->invalidate({GL_STENCIL_ATTACHMENT, GL_COLOR_ATTACHMENT0});
|
||||
}
|
||||
|
||||
// reset our data
|
||||
m_renderData.pMonitor.reset();
|
||||
|
|
@ -853,8 +868,8 @@ void CHyprOpenGLImpl::end() {
|
|||
// if we dropped to offMain, release it now.
|
||||
// if there is a plugin constantly using it, this might be a bit slow,
|
||||
// but I haven't seen a single plugin yet use these, so it's better to drop a bit of vram.
|
||||
if UNLIKELY (m_renderData.pCurrentMonData->offMainFB.isAllocated())
|
||||
m_renderData.pCurrentMonData->offMainFB.release();
|
||||
if UNLIKELY (m_renderData.pCurrentMonData->offMainFB && m_renderData.pCurrentMonData->offMainFB->isAllocated())
|
||||
m_renderData.pCurrentMonData->offMainFB->release();
|
||||
|
||||
static const auto GLDEBUG = CConfigValue<Hyprlang::INT>("debug:gl_debugging");
|
||||
|
||||
|
|
@ -1064,7 +1079,7 @@ void CHyprOpenGLImpl::renderRectWithBlurInternal(const CBox& box, const CHyprCol
|
|||
CRegion damage{m_renderData.damage};
|
||||
damage.intersect(box);
|
||||
|
||||
CFramebuffer* POUTFB = data.xray ? &m_renderData.pCurrentMonData->blurFB : blurMainFramebufferWithDamage(data.blurA, &damage);
|
||||
auto POUTFB = data.xray ? m_renderData.pCurrentMonData->blurFB : blurMainFramebufferWithDamage(data.blurA, &damage);
|
||||
|
||||
m_renderData.currentFB->bind();
|
||||
|
||||
|
|
@ -1135,7 +1150,7 @@ void CHyprOpenGLImpl::renderRectWithDamageInternal(const CBox& box, const CHyprC
|
|||
scissor(nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, const CBox& box, STextureRenderData data) {
|
||||
void CHyprOpenGLImpl::renderTexture(SP<ITexture> tex, const CBox& box, STextureRenderData data) {
|
||||
RASSERT(m_renderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
if (!data.damage) {
|
||||
|
|
@ -1460,9 +1475,9 @@ WP<CShader> CHyprOpenGLImpl::renderToFBInternal(const STextureRenderData& data,
|
|||
return shader;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureInternal(SP<CTexture> tex, const CBox& box, const STextureRenderData& data) {
|
||||
void CHyprOpenGLImpl::renderTextureInternal(SP<ITexture> tex, const CBox& box, const STextureRenderData& data) {
|
||||
RASSERT(m_renderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex->m_texID > 0), "Attempted to draw nullptr texture!");
|
||||
RASSERT((tex->ok()), "Attempted to draw nullptr texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureInternalWithDamage");
|
||||
|
||||
|
|
@ -1558,9 +1573,9 @@ void CHyprOpenGLImpl::renderTextureInternal(SP<CTexture> tex, const CBox& box, c
|
|||
tex->unbind();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, const CBox& box) {
|
||||
void CHyprOpenGLImpl::renderTexturePrimitive(SP<ITexture> tex, const CBox& box) {
|
||||
RASSERT(m_renderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex->m_texID > 0), "Attempted to draw nullptr texture!");
|
||||
RASSERT((tex->ok()), "Attempted to draw nullptr texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTexturePrimitive");
|
||||
|
||||
|
|
@ -1603,9 +1618,9 @@ void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, const CBox& box)
|
|||
tex->unbind();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFramebuffer& matte) {
|
||||
void CHyprOpenGLImpl::renderTextureMatte(SP<ITexture> tex, const CBox& box, SP<IFramebuffer> matte) {
|
||||
RASSERT(m_renderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex->m_texID > 0), "Attempted to draw nullptr texture!");
|
||||
RASSERT((tex->ok()), "Attempted to draw nullptr texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureMatte");
|
||||
|
||||
|
|
@ -1629,7 +1644,7 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
|
|||
tex->bind();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + 1);
|
||||
auto matteTex = matte.getTexture();
|
||||
auto matteTex = matte->getTexture();
|
||||
matteTex->bind();
|
||||
|
||||
glBindVertexArray(shader->getUniformLocation(SHADER_SHADER_VAO));
|
||||
|
|
@ -1648,16 +1663,16 @@ void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, const CBox& box, CFra
|
|||
// but it works... well, I guess?
|
||||
//
|
||||
// Dual (or more) kawase blur
|
||||
CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) {
|
||||
SP<IFramebuffer> CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* originalDamage) {
|
||||
if (!m_renderData.currentFB->getTexture()) {
|
||||
Log::logger->log(Log::ERR, "BUG THIS: null fb texture while attempting to blur main fb?! (introspection off?!)");
|
||||
return &m_renderData.pCurrentMonData->mirrorFB; // return something to sample from at least
|
||||
return m_renderData.pCurrentMonData->mirrorFB; // return something to sample from at least
|
||||
}
|
||||
|
||||
return blurFramebufferWithDamage(a, originalDamage, *m_renderData.currentFB);
|
||||
return blurFramebufferWithDamage(a, originalDamage, *GLFB(m_renderData.currentFB));
|
||||
}
|
||||
|
||||
CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* originalDamage, CFramebuffer& source) {
|
||||
SP<IFramebuffer> CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* originalDamage, CGLFramebuffer& source) {
|
||||
TRACY_GPU_ZONE("RenderBlurFramebufferWithDamage");
|
||||
|
||||
const auto BLENDBEFORE = m_blend;
|
||||
|
|
@ -1685,10 +1700,10 @@ CFramebuffer* CHyprOpenGLImpl::blurFramebufferWithDamage(float a, CRegion* origi
|
|||
damage.expand(std::clamp(*PBLURSIZE, sc<int64_t>(1), sc<int64_t>(40)) * pow(2, BLUR_PASSES));
|
||||
|
||||
// helper
|
||||
const auto PMIRRORFB = &m_renderData.pCurrentMonData->mirrorFB;
|
||||
const auto PMIRRORSWAPFB = &m_renderData.pCurrentMonData->mirrorSwapFB;
|
||||
const auto PMIRRORFB = m_renderData.pCurrentMonData->mirrorFB;
|
||||
const auto PMIRRORSWAPFB = m_renderData.pCurrentMonData->mirrorSwapFB;
|
||||
|
||||
CFramebuffer* currentRenderToFB = PMIRRORFB;
|
||||
auto currentRenderToFB = PMIRRORFB;
|
||||
|
||||
// Begin with base color adjustments - global brightness and contrast
|
||||
// TODO: make this a part of the first pass maybe to save on a drawcall?
|
||||
|
|
@ -1960,9 +1975,12 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
|
|||
const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage);
|
||||
|
||||
// render onto blurFB
|
||||
m_renderData.pCurrentMonData->blurFB.alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y,
|
||||
m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
m_renderData.pCurrentMonData->blurFB.bind();
|
||||
if (!m_renderData.pCurrentMonData->blurFB)
|
||||
m_renderData.pCurrentMonData->blurFB = g_pHyprRenderer->createFB();
|
||||
|
||||
m_renderData.pCurrentMonData->blurFB->alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y,
|
||||
m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
m_renderData.pCurrentMonData->blurFB->bind();
|
||||
|
||||
clear(CHyprColor(0, 0, 0, 0));
|
||||
|
||||
|
|
@ -1998,7 +2016,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin
|
|||
static auto PBLURNEWOPTIMIZE = CConfigValue<Hyprlang::INT>("decoration:blur:new_optimizations");
|
||||
static auto PBLURXRAY = CConfigValue<Hyprlang::INT>("decoration:blur:xray");
|
||||
|
||||
if (!m_renderData.pCurrentMonData->blurFB.getTexture())
|
||||
if (!m_renderData.pCurrentMonData->blurFB || !m_renderData.pCurrentMonData->blurFB->getTexture())
|
||||
return false;
|
||||
|
||||
if (pWindow && pWindow->m_ruleApplicator->xray().hasValue() && !pWindow->m_ruleApplicator->xray().valueOrDefault())
|
||||
|
|
@ -2016,7 +2034,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin
|
|||
return false;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP<CTexture> tex, const CBox& box, const STextureRenderData& data) {
|
||||
void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP<ITexture> tex, const CBox& box, const STextureRenderData& data) {
|
||||
RASSERT(m_renderData.pMonitor, "Tried to render texture with blur without begin()!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureWithBlur");
|
||||
|
|
@ -2056,16 +2074,16 @@ void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP<CTexture> tex, const CBox
|
|||
inverseOpaque.scale(m_renderData.pMonitor->m_scale);
|
||||
|
||||
// vvv TODO: layered blur fbs?
|
||||
const bool USENEWOPTIMIZE = shouldUseNewBlurOptimizations(m_renderData.currentLS.lock(), m_renderData.currentWindow.lock()) && !data.blockBlurOptimization;
|
||||
const bool USENEWOPTIMIZE = shouldUseNewBlurOptimizations(m_renderData.currentLS.lock(), m_renderData.currentWindow.lock()) && !data.blockBlurOptimization;
|
||||
|
||||
CFramebuffer* POUTFB = nullptr;
|
||||
SP<IFramebuffer> POUTFB = nullptr;
|
||||
if (!USENEWOPTIMIZE) {
|
||||
inverseOpaque.translate(box.pos());
|
||||
m_renderData.renderModif.applyToRegion(inverseOpaque);
|
||||
inverseOpaque.intersect(texDamage);
|
||||
POUTFB = blurMainFramebufferWithDamage(data.a, &inverseOpaque);
|
||||
} else
|
||||
POUTFB = &m_renderData.pCurrentMonData->blurFB;
|
||||
POUTFB = m_renderData.pCurrentMonData->blurFB;
|
||||
|
||||
m_renderData.currentFB->bind();
|
||||
|
||||
|
|
@ -2161,7 +2179,7 @@ void CHyprOpenGLImpl::renderTextureWithBlurInternal(SP<CTexture> tex, const CBox
|
|||
.blurredBG = blurredBG,
|
||||
});
|
||||
|
||||
m_renderData.currentFB->invalidate({GL_STENCIL_ATTACHMENT});
|
||||
GLFB(m_renderData.currentFB)->invalidate({GL_STENCIL_ATTACHMENT});
|
||||
scissor(nullptr);
|
||||
}
|
||||
|
||||
|
|
@ -2410,7 +2428,14 @@ void CHyprOpenGLImpl::renderRoundedShadow(const CBox& box, int round, float roun
|
|||
}
|
||||
|
||||
void CHyprOpenGLImpl::saveBufferForMirror(const CBox& box) {
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB.bind();
|
||||
if (!m_renderData.pCurrentMonData->monitorMirrorFB)
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB = g_pHyprRenderer->createFB();
|
||||
|
||||
if (!m_renderData.pCurrentMonData->monitorMirrorFB->isAllocated())
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB->alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y,
|
||||
m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
|
||||
m_renderData.pCurrentMonData->monitorMirrorFB->bind();
|
||||
|
||||
blend(false);
|
||||
|
||||
|
|
@ -2443,7 +2468,7 @@ void CHyprOpenGLImpl::renderMirrored() {
|
|||
monbox.x = (monitor->m_transformedSize.x - monbox.w) / 2;
|
||||
monbox.y = (monitor->m_transformedSize.y - monbox.h) / 2;
|
||||
|
||||
const auto PFB = &m_monitorRenderResources[mirrored].monitorMirrorFB;
|
||||
auto PFB = m_monitorRenderResources[mirrored].monitorMirrorFB;
|
||||
if (!PFB->isAllocated() || !PFB->getTexture())
|
||||
return;
|
||||
|
||||
|
|
@ -2517,7 +2542,7 @@ std::string CHyprOpenGLImpl::resolveAssetPath(const std::string& filename) {
|
|||
return fullPath;
|
||||
}
|
||||
|
||||
SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
|
||||
SP<ITexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
|
||||
|
||||
const std::string fullPath = resolveAssetPath(filename);
|
||||
|
||||
|
|
@ -2539,12 +2564,11 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) {
|
|||
return tex;
|
||||
}
|
||||
|
||||
SP<CTexture> CHyprOpenGLImpl::texFromCairo(cairo_surface_t* cairo) {
|
||||
SP<ITexture> CHyprOpenGLImpl::texFromCairo(cairo_surface_t* cairo) {
|
||||
const auto CAIROFORMAT = cairo_image_surface_get_format(cairo);
|
||||
auto tex = makeShared<CTexture>();
|
||||
auto tex = makeShared<CGLTexture>();
|
||||
|
||||
tex->allocate();
|
||||
tex->m_size = {cairo_image_surface_get_width(cairo), cairo_image_surface_get_height(cairo)};
|
||||
tex->allocate({cairo_image_surface_get_width(cairo), cairo_image_surface_get_height(cairo)});
|
||||
|
||||
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : GL_RGBA;
|
||||
const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA;
|
||||
|
|
@ -2565,8 +2589,8 @@ SP<CTexture> CHyprOpenGLImpl::texFromCairo(cairo_surface_t* cairo) {
|
|||
return tex;
|
||||
}
|
||||
|
||||
SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic, const std::string& fontFamily, int maxWidth, int weight) {
|
||||
SP<CTexture> tex = makeShared<CTexture>();
|
||||
SP<ITexture> CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col, int pt, bool italic, const std::string& fontFamily, int maxWidth, int weight) {
|
||||
SP<ITexture> tex = makeShared<CGLTexture>();
|
||||
|
||||
static auto FONT = CConfigValue<std::string>("misc:font_family");
|
||||
|
||||
|
|
@ -2628,8 +2652,7 @@ SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col
|
|||
|
||||
cairo_surface_flush(CAIROSURFACE);
|
||||
|
||||
tex->allocate();
|
||||
tex->m_size = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)};
|
||||
tex->allocate({cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)});
|
||||
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
tex->bind();
|
||||
|
|
@ -2646,8 +2669,8 @@ SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CHyprColor col
|
|||
}
|
||||
|
||||
void CHyprOpenGLImpl::initMissingAssetTexture() {
|
||||
SP<CTexture> tex = makeShared<CTexture>();
|
||||
tex->allocate();
|
||||
SP<ITexture> tex = makeShared<CGLTexture>();
|
||||
tex->allocate({512, 512});
|
||||
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 512, 512);
|
||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||
|
|
@ -2799,16 +2822,19 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
|
|||
if (!m_backgroundResource->m_ready)
|
||||
return;
|
||||
|
||||
if (!m_monitorBGFBs.contains(pMonitor))
|
||||
m_monitorBGFBs[pMonitor] = g_pHyprRenderer->createFB();
|
||||
|
||||
// release the last tex if exists
|
||||
const auto PFB = &m_monitorBGFBs[pMonitor];
|
||||
auto PFB = m_monitorBGFBs[pMonitor];
|
||||
PFB->release();
|
||||
|
||||
PFB->alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, pMonitor->m_output->state->state().drmFormat);
|
||||
|
||||
// create a new one with cairo
|
||||
SP<CTexture> tex = makeShared<CTexture>();
|
||||
SP<ITexture> tex = makeShared<CGLTexture>();
|
||||
|
||||
tex->allocate();
|
||||
tex->allocate(pMonitor->m_pixelSize);
|
||||
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y);
|
||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||
|
|
@ -2850,7 +2876,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) {
|
|||
blend(true);
|
||||
clear(CHyprColor{0, 0, 0, 1});
|
||||
|
||||
SP<CTexture> backgroundTexture = texFromCairo(m_backgroundResource->m_asset.cairoSurface->cairo());
|
||||
SP<ITexture> backgroundTexture = texFromCairo(m_backgroundResource->m_asset.cairoSurface->cairo());
|
||||
|
||||
// first render the background
|
||||
if (backgroundTexture) {
|
||||
|
|
@ -2905,7 +2931,7 @@ void CHyprOpenGLImpl::clearWithTex() {
|
|||
data.box = {0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y};
|
||||
data.a = m_renderData.pMonitor->m_backgroundOpacity->value();
|
||||
data.flipEndFrame = true;
|
||||
data.tex = TEXIT->second.getTexture();
|
||||
data.tex = TEXIT->second->getTexture();
|
||||
g_pHyprRenderer->m_renderPass.add(makeUnique<CTexPassElement>(std::move(data)));
|
||||
}
|
||||
}
|
||||
|
|
@ -2918,19 +2944,19 @@ void CHyprOpenGLImpl::destroyMonitorResources(PHLMONITORREF pMonitor) {
|
|||
|
||||
auto RESIT = g_pHyprOpenGL->m_monitorRenderResources.find(pMonitor);
|
||||
if (RESIT != g_pHyprOpenGL->m_monitorRenderResources.end()) {
|
||||
RESIT->second.mirrorFB.release();
|
||||
RESIT->second.offloadFB.release();
|
||||
RESIT->second.mirrorSwapFB.release();
|
||||
RESIT->second.monitorMirrorFB.release();
|
||||
RESIT->second.blurFB.release();
|
||||
RESIT->second.offMainFB.release();
|
||||
RESIT->second.stencilTex->destroyTexture();
|
||||
RESIT->second.mirrorFB.reset();
|
||||
RESIT->second.offloadFB.reset();
|
||||
RESIT->second.mirrorSwapFB.reset();
|
||||
RESIT->second.monitorMirrorFB.reset();
|
||||
RESIT->second.blurFB.reset();
|
||||
RESIT->second.offMainFB.reset();
|
||||
RESIT->second.stencilTex.reset();
|
||||
g_pHyprOpenGL->m_monitorRenderResources.erase(RESIT);
|
||||
}
|
||||
|
||||
auto TEXIT = g_pHyprOpenGL->m_monitorBGFBs.find(pMonitor);
|
||||
if (TEXIT != g_pHyprOpenGL->m_monitorBGFBs.end()) {
|
||||
TEXIT->second.release();
|
||||
TEXIT->second.reset();
|
||||
g_pHyprOpenGL->m_monitorBGFBs.erase(TEXIT);
|
||||
}
|
||||
|
||||
|
|
@ -2951,19 +2977,21 @@ void CHyprOpenGLImpl::restoreMatrix() {
|
|||
}
|
||||
|
||||
void CHyprOpenGLImpl::bindOffMain() {
|
||||
if (!m_renderData.pCurrentMonData->offMainFB.isAllocated()) {
|
||||
m_renderData.pCurrentMonData->offMainFB.alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y,
|
||||
m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
if (!m_renderData.pCurrentMonData->offMainFB)
|
||||
m_renderData.pCurrentMonData->offMainFB = g_pHyprRenderer->createFB();
|
||||
|
||||
m_renderData.pCurrentMonData->offMainFB.addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
if (!m_renderData.pCurrentMonData->offMainFB->isAllocated()) {
|
||||
m_renderData.pCurrentMonData->offMainFB->addStencil(m_renderData.pCurrentMonData->stencilTex);
|
||||
m_renderData.pCurrentMonData->offMainFB->alloc(m_renderData.pMonitor->m_pixelSize.x, m_renderData.pMonitor->m_pixelSize.y,
|
||||
m_renderData.pMonitor->m_output->state->state().drmFormat);
|
||||
}
|
||||
|
||||
m_renderData.pCurrentMonData->offMainFB.bind();
|
||||
m_renderData.pCurrentMonData->offMainFB->bind();
|
||||
clear(CHyprColor(0, 0, 0, 0));
|
||||
m_renderData.currentFB = &m_renderData.pCurrentMonData->offMainFB;
|
||||
m_renderData.currentFB = m_renderData.pCurrentMonData->offMainFB;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) {
|
||||
void CHyprOpenGLImpl::renderOffToMain(CGLFramebuffer* off) {
|
||||
CBox monbox = {0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y};
|
||||
renderTexturePrimitive(off->getTexture(), monbox);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "Texture.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
#include "Renderbuffer.hpp"
|
||||
#include "desktop/DesktopTypes.hpp"
|
||||
#include "pass/Pass.hpp"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
|
@ -32,9 +33,14 @@
|
|||
#include "../debug/TracyDefines.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "render/ShaderLoader.hpp"
|
||||
#include "render/gl/GLFramebuffer.hpp"
|
||||
#include "render/gl/GLRenderbuffer.hpp"
|
||||
#include "render/gl/GLTexture.hpp"
|
||||
|
||||
#define GLFB(ifb) dc<CGLFramebuffer*>(ifb.get())
|
||||
|
||||
struct gbm_device;
|
||||
class CHyprRenderer;
|
||||
class IHyprRenderer;
|
||||
|
||||
struct SVertex {
|
||||
float x, y; // position
|
||||
|
|
@ -108,17 +114,17 @@ struct SPreparedShaders {
|
|||
};
|
||||
|
||||
struct SMonitorRenderData {
|
||||
CFramebuffer offloadFB;
|
||||
CFramebuffer mirrorFB; // these are used for some effects,
|
||||
CFramebuffer mirrorSwapFB; // etc
|
||||
CFramebuffer offMainFB;
|
||||
CFramebuffer monitorMirrorFB; // used for mirroring outputs / screencopy, does not contain artifacts like offloadFB and is in sRGB
|
||||
CFramebuffer blurFB;
|
||||
SP<IFramebuffer> offloadFB;
|
||||
SP<IFramebuffer> mirrorFB; // these are used for some effects,
|
||||
SP<IFramebuffer> mirrorSwapFB; // etc
|
||||
SP<IFramebuffer> offMainFB;
|
||||
SP<IFramebuffer> monitorMirrorFB; // used for mirroring outputs, does not contain artifacts like offloadFB
|
||||
SP<IFramebuffer> blurFB;
|
||||
|
||||
SP<CTexture> stencilTex = makeShared<CTexture>();
|
||||
SP<ITexture> stencilTex = makeShared<CGLTexture>();
|
||||
|
||||
bool blurFBDirty = true;
|
||||
bool blurFBShouldRender = false;
|
||||
bool blurFBDirty = true;
|
||||
bool blurFBShouldRender = false;
|
||||
};
|
||||
|
||||
struct SCurrentRenderData {
|
||||
|
|
@ -129,9 +135,9 @@ struct SCurrentRenderData {
|
|||
|
||||
// FIXME: raw pointer galore!
|
||||
SMonitorRenderData* pCurrentMonData = nullptr;
|
||||
CFramebuffer* currentFB = nullptr; // current rendering to
|
||||
CFramebuffer* mainFB = nullptr; // main to render to
|
||||
CFramebuffer* outFB = nullptr; // out to render to (if offloaded, etc)
|
||||
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
|
||||
|
|
@ -213,7 +219,7 @@ class CHyprOpenGLImpl {
|
|||
bool noCM = false;
|
||||
bool finalMonitorCM = false;
|
||||
SP<CMonitor> cmBackToSRGBSource;
|
||||
SP<CTexture> blurredBG;
|
||||
SP<ITexture> blurredBG;
|
||||
};
|
||||
|
||||
struct SBorderRenderData {
|
||||
|
|
@ -224,17 +230,17 @@ class CHyprOpenGLImpl {
|
|||
int outerRound = -1; /* use round */
|
||||
};
|
||||
|
||||
void begin(PHLMONITOR, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional<CRegion> finalDamage = {});
|
||||
void beginSimple(PHLMONITOR, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr);
|
||||
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<CTexture>, const CBox&, STextureRenderData 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<CTexture> tex, const CBox& pBox, CFramebuffer& matte);
|
||||
void renderTexturePrimitive(SP<CTexture> tex, const CBox& box);
|
||||
void renderTextureMatte(SP<ITexture> tex, const CBox& pBox, SP<IFramebuffer> matte);
|
||||
void renderTexturePrimitive(SP<ITexture> tex, const CBox& box);
|
||||
|
||||
void pushMonitorTransformEnabled(bool enabled);
|
||||
void popMonitorTransformEnabled();
|
||||
|
|
@ -271,49 +277,49 @@ class CHyprOpenGLImpl {
|
|||
void applyScreenShader(const std::string& path);
|
||||
|
||||
void bindOffMain();
|
||||
void renderOffToMain(CFramebuffer* off);
|
||||
void renderOffToMain(CGLFramebuffer* off);
|
||||
void bindBackOnMain();
|
||||
|
||||
bool needsACopyFB(PHLMONITOR mon);
|
||||
|
||||
std::string resolveAssetPath(const std::string& file);
|
||||
SP<CTexture> loadAsset(const std::string& file);
|
||||
SP<CTexture> texFromCairo(cairo_surface_t* cairo);
|
||||
SP<CTexture> 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& file);
|
||||
SP<ITexture> texFromCairo(cairo_surface_t* cairo);
|
||||
SP<ITexture> renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0, int weight = 400);
|
||||
|
||||
void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
|
||||
|
||||
DRMFormat getPreferredReadFormat(PHLMONITOR pMonitor);
|
||||
std::vector<SDRMFormat> getDRMFormats();
|
||||
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
|
||||
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
||||
std::vector<SDRMFormat> getDRMFormats();
|
||||
std::vector<uint64_t> getDRMFormatModifiers(DRMFormat format);
|
||||
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
|
||||
|
||||
bool initShaders(const std::string& path = "");
|
||||
bool initShaders(const std::string& path = "");
|
||||
|
||||
WP<CShader> useShader(WP<CShader> prog);
|
||||
WP<CShader> useShader(WP<CShader> prog);
|
||||
|
||||
bool explicitSyncSupported();
|
||||
WP<CShader> getShaderVariant(Render::ePreparedFragmentShader frag, Render::ShaderFeatureFlags features = 0);
|
||||
bool explicitSyncSupported();
|
||||
WP<CShader> getShaderVariant(Render::ePreparedFragmentShader frag, Render::ShaderFeatureFlags features = 0);
|
||||
|
||||
bool m_shadersInitialized = false;
|
||||
SP<SPreparedShaders> m_shaders;
|
||||
bool m_shadersInitialized = false;
|
||||
SP<SPreparedShaders> m_shaders;
|
||||
|
||||
SCurrentRenderData m_renderData;
|
||||
SCurrentRenderData m_renderData;
|
||||
|
||||
Hyprutils::OS::CFileDescriptor m_gbmFD;
|
||||
gbm_device* m_gbmDevice = nullptr;
|
||||
EGLContext m_eglContext = nullptr;
|
||||
EGLDisplay m_eglDisplay = nullptr;
|
||||
EGLDeviceEXT m_eglDevice = nullptr;
|
||||
uint m_failedAssetsNo = 0;
|
||||
Hyprutils::OS::CFileDescriptor m_gbmFD;
|
||||
gbm_device* m_gbmDevice = nullptr;
|
||||
EGLContext m_eglContext = nullptr;
|
||||
EGLDisplay m_eglDisplay = nullptr;
|
||||
EGLDeviceEXT m_eglDevice = nullptr;
|
||||
uint m_failedAssetsNo = 0;
|
||||
|
||||
bool m_reloadScreenShader = true; // at launch it can be set
|
||||
bool m_reloadScreenShader = true; // at launch it can be set
|
||||
|
||||
std::map<PHLWINDOWREF, CFramebuffer> m_windowFramebuffers;
|
||||
std::map<PHLLSREF, CFramebuffer> m_layerFramebuffers;
|
||||
std::map<WP<Desktop::View::CPopup>, CFramebuffer> m_popupFramebuffers;
|
||||
std::map<PHLMONITORREF, SMonitorRenderData> m_monitorRenderResources;
|
||||
std::map<PHLMONITORREF, CFramebuffer> m_monitorBGFBs;
|
||||
std::map<PHLWINDOWREF, SP<IFramebuffer>> m_windowFramebuffers;
|
||||
std::map<PHLLSREF, SP<IFramebuffer>> m_layerFramebuffers;
|
||||
std::map<WP<Desktop::View::CPopup>, SP<IFramebuffer>> m_popupFramebuffers;
|
||||
std::map<PHLMONITORREF, SMonitorRenderData> m_monitorRenderResources;
|
||||
std::map<PHLMONITORREF, SP<IFramebuffer>> m_monitorBGFBs;
|
||||
|
||||
struct {
|
||||
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
|
||||
|
|
@ -344,7 +350,7 @@ class CHyprOpenGLImpl {
|
|||
bool EGL_ANDROID_native_fence_sync_ext = false;
|
||||
} m_exts;
|
||||
|
||||
SP<CTexture> m_screencopyDeniedTexture;
|
||||
SP<ITexture> m_screencopyDeniedTexture;
|
||||
|
||||
enum eEGLContextVersion : uint8_t {
|
||||
EGL_CONTEXT_GLES_2_0 = 0,
|
||||
|
|
@ -385,10 +391,10 @@ class CHyprOpenGLImpl {
|
|||
|
||||
bool m_monitorTransformEnabled = false; // do not modify directly
|
||||
std::stack<bool> m_monitorTransformStack;
|
||||
SP<CTexture> m_missingAssetTexture;
|
||||
SP<CTexture> m_lockDeadTexture;
|
||||
SP<CTexture> m_lockDead2Texture;
|
||||
SP<CTexture> m_lockTtyTextTexture;
|
||||
SP<ITexture> m_missingAssetTexture;
|
||||
SP<ITexture> m_lockDeadTexture;
|
||||
SP<ITexture> m_lockDead2Texture;
|
||||
SP<ITexture> m_lockTtyTextTexture;
|
||||
SP<CShader> m_finalScreenShader;
|
||||
CTimer m_globalTimer;
|
||||
GLuint m_currentProgram;
|
||||
|
|
@ -414,22 +420,22 @@ class CHyprOpenGLImpl {
|
|||
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
|
||||
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||
CFramebuffer* blurFramebufferWithDamage(float a, CRegion* damage, CFramebuffer& source);
|
||||
SP<IFramebuffer> blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||
SP<IFramebuffer> blurFramebufferWithDamage(float a, CRegion* damage, CGLFramebuffer& source);
|
||||
|
||||
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
||||
bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
||||
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription);
|
||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
||||
void renderRectInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
void renderRectWithBlurInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
void renderRectWithDamageInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
WP<CShader> renderToOutputInternal();
|
||||
WP<CShader> renderToFBInternal(const STextureRenderData& data, eTextureType texType, const CBox& newBox);
|
||||
void renderTextureInternal(SP<CTexture>, const CBox&, const STextureRenderData& data);
|
||||
void renderTextureWithBlurInternal(SP<CTexture>, const CBox&, const STextureRenderData& data);
|
||||
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
||||
bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
||||
void passCMUniforms(WP<CShader>, const NColorManagement::PImageDescription imageDescription);
|
||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
||||
void renderRectInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
void renderRectWithBlurInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
void renderRectWithDamageInternal(const CBox&, const CHyprColor&, const SRectRenderData& data);
|
||||
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);
|
||||
|
||||
void preBlurForCurrentMonitor();
|
||||
void preBlurForCurrentMonitor();
|
||||
|
||||
friend class CHyprRenderer;
|
||||
friend class CTexPassElement;
|
||||
|
|
|
|||
|
|
@ -1,74 +1,21 @@
|
|||
#include "Renderbuffer.hpp"
|
||||
#include "Renderer.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../protocols/types/Buffer.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
#include "render/Renderer.hpp"
|
||||
#include "render/gl/GLRenderbuffer.hpp"
|
||||
#include <hyprutils/memory/SharedPtr.hpp>
|
||||
#include <hyprutils/signal/Listener.hpp>
|
||||
#include <hyprutils/signal/Signal.hpp>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
CRenderbuffer::~CRenderbuffer() {
|
||||
if (!g_pCompositor || g_pCompositor->m_isShuttingDown || !g_pHyprRenderer)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
unbind();
|
||||
m_framebuffer.release();
|
||||
|
||||
if (m_rbo)
|
||||
glDeleteRenderbuffers(1, &m_rbo);
|
||||
|
||||
if (m_image != EGL_NO_IMAGE_KHR)
|
||||
g_pHyprOpenGL->m_proc.eglDestroyImageKHR(g_pHyprOpenGL->m_eglDisplay, m_image);
|
||||
IRenderbuffer::IRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format) : m_hlBuffer(buffer) {
|
||||
m_listeners.destroyBuffer = buffer->events.destroy.listen([this] { g_pHyprRenderer->onRenderbufferDestroy(dc<CGLRenderbuffer*>(this)); });
|
||||
}
|
||||
|
||||
CRenderbuffer::CRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format) : m_hlBuffer(buffer), m_drmFormat(format) {
|
||||
auto dma = buffer->dmabuf();
|
||||
|
||||
m_image = g_pHyprOpenGL->createEGLImage(dma);
|
||||
if (m_image == EGL_NO_IMAGE_KHR) {
|
||||
Log::logger->log(Log::ERR, "rb: createEGLImage failed");
|
||||
return;
|
||||
}
|
||||
|
||||
glGenRenderbuffers(1, &m_rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_rbo);
|
||||
g_pHyprOpenGL->m_proc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, m_image);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glGenFramebuffers(1, &m_framebuffer.m_fb);
|
||||
m_framebuffer.m_fbAllocated = true;
|
||||
m_framebuffer.m_size = buffer->size;
|
||||
m_framebuffer.m_drmFormat = dma.format;
|
||||
m_framebuffer.bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
Log::logger->log(Log::ERR, "rbo: glCheckFramebufferStatus failed");
|
||||
return;
|
||||
}
|
||||
|
||||
m_framebuffer.unbind();
|
||||
|
||||
m_listeners.destroyBuffer = buffer->events.destroy.listen([this] { g_pHyprRenderer->onRenderbufferDestroy(this); });
|
||||
|
||||
m_good = true;
|
||||
}
|
||||
|
||||
bool CRenderbuffer::good() {
|
||||
bool IRenderbuffer::good() {
|
||||
return m_good;
|
||||
}
|
||||
|
||||
void CRenderbuffer::bind() {
|
||||
m_framebuffer.bind();
|
||||
}
|
||||
|
||||
void CRenderbuffer::unbind() {
|
||||
m_framebuffer.unbind();
|
||||
}
|
||||
|
||||
CFramebuffer* CRenderbuffer::getFB() {
|
||||
return &m_framebuffer;
|
||||
SP<IFramebuffer> IRenderbuffer::getFB() {
|
||||
return m_framebuffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,27 +5,22 @@
|
|||
#include "Framebuffer.hpp"
|
||||
#include <aquamarine/buffer/Buffer.hpp>
|
||||
|
||||
class CMonitor;
|
||||
|
||||
class CRenderbuffer {
|
||||
class IRenderbuffer {
|
||||
public:
|
||||
CRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format);
|
||||
~CRenderbuffer();
|
||||
IRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format);
|
||||
virtual ~IRenderbuffer() = default;
|
||||
|
||||
bool good();
|
||||
void bind();
|
||||
void unbind();
|
||||
CFramebuffer* getFB();
|
||||
uint32_t getFormat();
|
||||
SP<IFramebuffer> getFB();
|
||||
|
||||
virtual void bind() = 0;
|
||||
virtual void unbind() = 0;
|
||||
|
||||
WP<Aquamarine::IBuffer> m_hlBuffer;
|
||||
|
||||
private:
|
||||
void* m_image = nullptr;
|
||||
GLuint m_rbo = 0;
|
||||
CFramebuffer m_framebuffer;
|
||||
uint32_t m_drmFormat = 0;
|
||||
bool m_good = false;
|
||||
protected:
|
||||
SP<IFramebuffer> m_framebuffer;
|
||||
bool m_good = false;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener destroyBuffer;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "../helpers/math/Math.hpp"
|
||||
#include <algorithm>
|
||||
#include <aquamarine/output/Output.hpp>
|
||||
#include <cmath>
|
||||
#include <filesystem>
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
|
|
@ -29,10 +30,12 @@
|
|||
#include "../layout/LayoutManager.hpp"
|
||||
#include "../layout/space/Space.hpp"
|
||||
#include "../i18n/Engine.hpp"
|
||||
#include "desktop/DesktopTypes.hpp"
|
||||
#include "../event/EventBus.hpp"
|
||||
#include "helpers/CursorShapes.hpp"
|
||||
#include "helpers/MainLoopExecutor.hpp"
|
||||
#include "helpers/Monitor.hpp"
|
||||
#include "helpers/cm/ColorManagement.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "pass/TexPassElement.hpp"
|
||||
#include "pass/ClearPassElement.hpp"
|
||||
#include "pass/RectPassElement.hpp"
|
||||
|
|
@ -42,7 +45,18 @@
|
|||
#include "../protocols/ColorManagement.hpp"
|
||||
#include "../protocols/types/ContentType.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
#include "render/AsyncResourceGatherer.hpp"
|
||||
#include "render/Framebuffer.hpp"
|
||||
#include "render/OpenGL.hpp"
|
||||
#include "render/Texture.hpp"
|
||||
#include "render/gl/GLFramebuffer.hpp"
|
||||
#include "render/gl/GLTexture.hpp"
|
||||
#include <hyprutils/math/Mat3x3.hpp>
|
||||
#include <hyprutils/math/Region.hpp>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
#include <hyprutils/memory/SharedPtr.hpp>
|
||||
#include <optional>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||
using namespace Hyprutils::Utils;
|
||||
|
|
@ -643,13 +657,13 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T
|
|||
}
|
||||
|
||||
if (TRANSFORMERSPRESENT) {
|
||||
CFramebuffer* last = g_pHyprOpenGL->m_renderData.currentFB;
|
||||
IFramebuffer* last = g_pHyprOpenGL->m_renderData.currentFB.get();
|
||||
for (auto const& t : pWindow->m_transformers) {
|
||||
last = t->transform(last);
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->bindBackOnMain();
|
||||
g_pHyprOpenGL->renderOffToMain(last);
|
||||
g_pHyprOpenGL->renderOffToMain(dc<CGLFramebuffer*>(last));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -733,6 +747,36 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const T
|
|||
g_pHyprOpenGL->m_renderData.currentWindow.reset();
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy) {
|
||||
if (!buffer)
|
||||
return createTexture();
|
||||
|
||||
auto attrs = buffer->dmabuf();
|
||||
|
||||
if (!attrs.success) {
|
||||
// attempt shm
|
||||
auto shm = buffer->shm();
|
||||
|
||||
if (!shm.success) {
|
||||
Log::logger->log(Log::ERR, "Cannot create a texture: buffer has no dmabuf or shm");
|
||||
return createTexture(buffer->opaque);
|
||||
}
|
||||
|
||||
auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0);
|
||||
|
||||
return createTexture(fmt, pixelData, bufLen, shm.size, keepDataCopy, buffer->opaque);
|
||||
}
|
||||
|
||||
auto tex = createTexture(attrs, buffer->opaque);
|
||||
|
||||
if (!tex) {
|
||||
Log::logger->log(Log::ERR, "Cannot create a texture: failed to create an Image");
|
||||
return createTexture(buffer->opaque);
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, const Time::steady_tp& time, bool popups, bool lockscreen) {
|
||||
if (!pLayer)
|
||||
return;
|
||||
|
|
@ -2313,13 +2357,13 @@ void CHyprRenderer::initiateManualCrash() {
|
|||
**PDT = 0;
|
||||
}
|
||||
|
||||
SP<CRenderbuffer> CHyprRenderer::getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
|
||||
SP<IRenderbuffer> CHyprRenderer::getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt) {
|
||||
auto it = std::ranges::find_if(m_renderbuffers, [&](const auto& other) { return other->m_hlBuffer == buffer; });
|
||||
|
||||
if (it != m_renderbuffers.end())
|
||||
return *it;
|
||||
|
||||
auto buf = makeShared<CRenderbuffer>(buffer, fmt);
|
||||
auto buf = makeShared<CGLRenderbuffer>(buffer, fmt);
|
||||
|
||||
if (!buf->good())
|
||||
return nullptr;
|
||||
|
|
@ -2343,7 +2387,7 @@ void CHyprRenderer::unsetEGL() {
|
|||
eglMakeCurrent(g_pHyprOpenGL->m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
bool CHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode, SP<IHLBuffer> buffer, CFramebuffer* fb, bool simple) {
|
||||
bool CHyprRenderer::beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode, SP<IHLBuffer> buffer, SP<IFramebuffer> fb, bool simple) {
|
||||
|
||||
makeEGLCurrent();
|
||||
|
||||
|
|
@ -2475,11 +2519,11 @@ void CHyprRenderer::endRender(const std::function<void()>& renderingDoneCallback
|
|||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) {
|
||||
void CHyprRenderer::onRenderbufferDestroy(CGLRenderbuffer* rb) {
|
||||
std::erase_if(m_renderbuffers, [&](const auto& rbo) { return rbo.get() == rb; });
|
||||
}
|
||||
|
||||
SP<CRenderbuffer> CHyprRenderer::getCurrentRBO() {
|
||||
SP<IRenderbuffer> CHyprRenderer::getCurrentRBO() {
|
||||
return m_currentRenderbuffer;
|
||||
}
|
||||
|
||||
|
|
@ -2532,7 +2576,10 @@ void CHyprRenderer::makeSnapshot(PHLWINDOW pWindow) {
|
|||
|
||||
makeEGLCurrent();
|
||||
|
||||
const auto PFRAMEBUFFER = &g_pHyprOpenGL->m_windowFramebuffers[ref];
|
||||
if (!g_pHyprOpenGL->m_windowFramebuffers.contains(ref))
|
||||
g_pHyprOpenGL->m_windowFramebuffers[ref] = g_pHyprRenderer->createFB();
|
||||
|
||||
const auto PFRAMEBUFFER = g_pHyprOpenGL->m_windowFramebuffers[ref];
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
|
||||
|
||||
|
|
@ -2565,7 +2612,10 @@ void CHyprRenderer::makeSnapshot(PHLLS pLayer) {
|
|||
|
||||
makeEGLCurrent();
|
||||
|
||||
const auto PFRAMEBUFFER = &g_pHyprOpenGL->m_layerFramebuffers[pLayer];
|
||||
if (!g_pHyprOpenGL->m_layerFramebuffers.contains(pLayer))
|
||||
g_pHyprOpenGL->m_layerFramebuffers[pLayer] = g_pHyprRenderer->createFB();
|
||||
|
||||
const auto PFRAMEBUFFER = g_pHyprOpenGL->m_layerFramebuffers[pLayer];
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
|
||||
|
||||
|
|
@ -2599,7 +2649,10 @@ void CHyprRenderer::makeSnapshot(WP<Desktop::View::CPopup> popup) {
|
|||
|
||||
makeEGLCurrent();
|
||||
|
||||
const auto PFRAMEBUFFER = &g_pHyprOpenGL->m_popupFramebuffers[popup];
|
||||
if (!g_pHyprOpenGL->m_popupFramebuffers.contains(popup))
|
||||
g_pHyprOpenGL->m_popupFramebuffers[popup] = g_pHyprRenderer->createFB();
|
||||
|
||||
const auto PFRAMEBUFFER = g_pHyprOpenGL->m_popupFramebuffers[popup];
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->m_pixelSize.x, PMONITOR->m_pixelSize.y, DRM_FORMAT_ABGR8888);
|
||||
|
||||
|
|
@ -2648,7 +2701,7 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) {
|
|||
if (!g_pHyprOpenGL->m_windowFramebuffers.contains(ref))
|
||||
return;
|
||||
|
||||
const auto FBDATA = &g_pHyprOpenGL->m_windowFramebuffers.at(ref);
|
||||
const auto FBDATA = g_pHyprOpenGL->m_windowFramebuffers.at(ref);
|
||||
|
||||
if (!FBDATA->getTexture())
|
||||
return;
|
||||
|
|
@ -2704,7 +2757,7 @@ void CHyprRenderer::renderSnapshot(PHLLS pLayer) {
|
|||
if (!g_pHyprOpenGL->m_layerFramebuffers.contains(pLayer))
|
||||
return;
|
||||
|
||||
const auto FBDATA = &g_pHyprOpenGL->m_layerFramebuffers.at(pLayer);
|
||||
const auto FBDATA = g_pHyprOpenGL->m_layerFramebuffers.at(pLayer);
|
||||
|
||||
if (!FBDATA->getTexture())
|
||||
return;
|
||||
|
|
@ -2748,7 +2801,7 @@ void CHyprRenderer::renderSnapshot(WP<Desktop::View::CPopup> popup) {
|
|||
|
||||
static CConfigValue PBLURIGNOREA = CConfigValue<Hyprlang::FLOAT>("decoration:blur:popups_ignorealpha");
|
||||
|
||||
const auto FBDATA = &g_pHyprOpenGL->m_popupFramebuffers.at(popup);
|
||||
const auto FBDATA = g_pHyprOpenGL->m_popupFramebuffers.at(popup);
|
||||
|
||||
if (!FBDATA->getTexture())
|
||||
return;
|
||||
|
|
@ -2813,4 +2866,89 @@ bool CHyprRenderer::shouldBlur(WP<Desktop::View::CPopup> p) {
|
|||
|
||||
bool CHyprRenderer::reloadShaders(const std::string& path) {
|
||||
return g_pHyprOpenGL->initShaders(path);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createStencilTexture(const int width, const int height) {
|
||||
makeEGLCurrent();
|
||||
auto tex = makeShared<CGLTexture>();
|
||||
tex->allocate({width, height});
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createTexture(bool opaque) {
|
||||
makeEGLCurrent();
|
||||
return makeShared<CGLTexture>(opaque);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy, bool opaque) {
|
||||
makeEGLCurrent();
|
||||
return makeShared<CGLTexture>(drmFormat, pixels, stride, size, keepDataCopy, opaque);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createTexture(const Aquamarine::SDMABUFAttrs& attrs, bool opaque) {
|
||||
makeEGLCurrent();
|
||||
const auto image = g_pHyprOpenGL->createEGLImage(attrs);
|
||||
if (!image)
|
||||
return nullptr;
|
||||
return makeShared<CGLTexture>(attrs, image, opaque);
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createTexture(const int width, const int height, unsigned char* const data) {
|
||||
makeEGLCurrent();
|
||||
SP<ITexture> tex = makeShared<CGLTexture>();
|
||||
|
||||
tex->allocate({width, height});
|
||||
|
||||
tex->m_size = {width, height};
|
||||
// copy the data to an OpenGL texture we have
|
||||
const GLint glFormat = GL_RGBA;
|
||||
const GLint glType = GL_UNSIGNED_BYTE;
|
||||
|
||||
tex->bind();
|
||||
tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, data);
|
||||
tex->unbind();
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createTexture(cairo_surface_t* cairo) {
|
||||
makeEGLCurrent();
|
||||
const auto CAIROFORMAT = cairo_image_surface_get_format(cairo);
|
||||
auto tex = makeShared<CGLTexture>();
|
||||
|
||||
tex->allocate({cairo_image_surface_get_width(cairo), cairo_image_surface_get_height(cairo)});
|
||||
|
||||
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : GL_RGBA;
|
||||
const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA;
|
||||
const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE;
|
||||
|
||||
const auto DATA = cairo_image_surface_get_data(cairo);
|
||||
tex->bind();
|
||||
tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
if (CAIROFORMAT != CAIRO_FORMAT_RGB96F) {
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
SP<ITexture> CHyprRenderer::createTexture(std::span<const float> lut3D, size_t N) {
|
||||
makeEGLCurrent();
|
||||
return makeShared<CGLTexture>(lut3D, N);
|
||||
}
|
||||
|
||||
SP<IFramebuffer> CHyprRenderer::createFB(const std::string& name) {
|
||||
makeEGLCurrent();
|
||||
return makeShared<CGLFramebuffer>(name);
|
||||
}
|
||||
|
|
@ -13,7 +13,8 @@
|
|||
#include "../helpers/math/Math.hpp"
|
||||
#include "../helpers/time/Time.hpp"
|
||||
#include "../../protocols/cursor-shape-v1.hpp"
|
||||
#include "helpers/cm/ColorManagement.hpp"
|
||||
#include "render/Framebuffer.hpp"
|
||||
#include "render/Texture.hpp"
|
||||
|
||||
struct SMonitorRule;
|
||||
class CWorkspace;
|
||||
|
|
@ -108,8 +109,8 @@ class CHyprRenderer {
|
|||
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(CRenderbuffer* rb);
|
||||
SP<CRenderbuffer> getCurrentRBO();
|
||||
void onRenderbufferDestroy(CGLRenderbuffer* rb);
|
||||
SP<IRenderbuffer> getCurrentRBO();
|
||||
bool isNvidia();
|
||||
bool isIntel();
|
||||
bool isSoftware();
|
||||
|
|
@ -129,7 +130,7 @@ class CHyprRenderer {
|
|||
|
||||
// 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 = {}, CFramebuffer* fb = nullptr, bool simple = false);
|
||||
bool beginRender(PHLMONITOR pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IHLBuffer> buffer = {}, SP<IFramebuffer> fb = nullptr, bool simple = false);
|
||||
void endRender(const std::function<void()>& renderingDoneCallback = {});
|
||||
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
|
|
@ -157,11 +158,21 @@ class CHyprRenderer {
|
|||
std::string name;
|
||||
} m_lastCursorData;
|
||||
|
||||
CRenderPass m_renderPass = {};
|
||||
CRenderPass m_renderPass = {};
|
||||
|
||||
SCMSettings getCMSettings(const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
||||
SP<CWLSurfaceResource> surface = nullptr, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
||||
bool reloadShaders(const std::string& path = "");
|
||||
SP<ITexture> createStencilTexture(const int width, const int height);
|
||||
SP<ITexture> createTexture(bool opaque = false);
|
||||
SP<ITexture> createTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false);
|
||||
SP<ITexture> createTexture(const Aquamarine::SDMABUFAttrs&, bool opaque = false);
|
||||
SP<ITexture> createTexture(const int width, const int height, unsigned char* const);
|
||||
SP<ITexture> createTexture(cairo_surface_t* cairo);
|
||||
SP<ITexture> createTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy = false);
|
||||
SP<ITexture> createTexture(std::span<const float> lut3D, size_t N);
|
||||
SP<IFramebuffer> createFB(const std::string& name = "");
|
||||
|
||||
SCMSettings getCMSettings(const NColorManagement::PImageDescription imageDescription, const NColorManagement::PImageDescription targetImageDescription,
|
||||
SP<CWLSurfaceResource> surface = nullptr, bool modifySDR = false, float sdrMinLuminance = -1.0f, int sdrMaxLuminance = -1);
|
||||
bool reloadShaders(const std::string& path = "");
|
||||
|
||||
private:
|
||||
void arrangeLayerArray(PHLMONITOR, const std::vector<PHLLSREF>&, bool, CBox*);
|
||||
|
|
@ -188,7 +199,7 @@ class CHyprRenderer {
|
|||
bool m_cursorHidden = false;
|
||||
bool m_cursorHiddenByCondition = false;
|
||||
bool m_cursorHasSurface = false;
|
||||
SP<CRenderbuffer> m_currentRenderbuffer = nullptr;
|
||||
SP<IRenderbuffer> m_currentRenderbuffer = nullptr;
|
||||
SP<Aquamarine::IBuffer> m_currentBuffer = nullptr;
|
||||
eRenderMode m_renderMode = RENDER_MODE_NORMAL;
|
||||
bool m_nvidia = false;
|
||||
|
|
@ -203,8 +214,8 @@ class CHyprRenderer {
|
|||
bool hiddenOnKeyboard = false;
|
||||
} m_cursorHiddenConditions;
|
||||
|
||||
SP<CRenderbuffer> getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt);
|
||||
std::vector<SP<CRenderbuffer>> m_renderbuffers;
|
||||
SP<IRenderbuffer> getOrCreateRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t fmt);
|
||||
std::vector<SP<IRenderbuffer>> m_renderbuffers;
|
||||
std::vector<PHLWINDOWREF> m_renderUnfocused;
|
||||
SP<CEventLoopTimer> m_renderUnfocusedTimer;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,265 +1,24 @@
|
|||
#include "Texture.hpp"
|
||||
#include "Renderer.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../protocols/types/Buffer.hpp"
|
||||
#include "../helpers/Format.hpp"
|
||||
#include <cstring>
|
||||
|
||||
CTexture::CTexture() = default;
|
||||
|
||||
CTexture::~CTexture() {
|
||||
if (!g_pCompositor || g_pCompositor->m_isShuttingDown || !g_pHyprRenderer)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
destroyTexture();
|
||||
}
|
||||
|
||||
CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_, bool keepDataCopy) : m_drmFormat(drmFormat), m_keepDataCopy(keepDataCopy) {
|
||||
createFromShm(drmFormat, pixels, stride, size_);
|
||||
}
|
||||
|
||||
CTexture::CTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image) {
|
||||
createFromDma(attrs, image);
|
||||
}
|
||||
|
||||
CTexture::CTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy) : m_keepDataCopy(keepDataCopy) {
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
m_opaque = buffer->opaque;
|
||||
|
||||
auto attrs = buffer->dmabuf();
|
||||
|
||||
if (!attrs.success) {
|
||||
// attempt shm
|
||||
auto shm = buffer->shm();
|
||||
|
||||
if (!shm.success) {
|
||||
Log::logger->log(Log::ERR, "Cannot create a texture: buffer has no dmabuf or shm");
|
||||
return;
|
||||
}
|
||||
|
||||
auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0);
|
||||
|
||||
m_drmFormat = fmt;
|
||||
|
||||
createFromShm(fmt, pixelData, bufLen, shm.size);
|
||||
return;
|
||||
}
|
||||
|
||||
auto image = g_pHyprOpenGL->createEGLImage(buffer->dmabuf());
|
||||
|
||||
if (!image) {
|
||||
Log::logger->log(Log::ERR, "Cannot create a texture: failed to create an EGLImage");
|
||||
return;
|
||||
}
|
||||
|
||||
createFromDma(attrs, image);
|
||||
}
|
||||
|
||||
CTexture::CTexture(std::span<const float> lut3D, size_t N) : m_type(TEXTURE_3D_LUT), m_target(GL_TEXTURE_3D), m_size(lut3D.size() / 3, 1), m_isSynchronous(true) {
|
||||
allocate();
|
||||
bind();
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// Expand RGB->RGBA on upload (alpha=1)
|
||||
std::vector<float> rgba;
|
||||
rgba.resize(N * N * N * 4);
|
||||
for (size_t i = 0, j = 0; i < N * N * N; ++i, j += 3) {
|
||||
rgba[i * 4 + 0] = lut3D[j + 0];
|
||||
rgba[i * 4 + 1] = lut3D[j + 1];
|
||||
rgba[i * 4 + 2] = lut3D[j + 2];
|
||||
rgba[i * 4 + 3] = 1.F;
|
||||
}
|
||||
|
||||
GLCALL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, N, N, N, 0, GL_RGBA, GL_FLOAT, rgba.data()));
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) {
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
ASSERT(format);
|
||||
|
||||
m_type = format->withAlpha ? TEXTURE_RGBA : TEXTURE_RGBX;
|
||||
m_size = size_;
|
||||
m_isSynchronous = true;
|
||||
m_target = GL_TEXTURE_2D;
|
||||
allocate();
|
||||
bind();
|
||||
setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (format->swizzle.has_value())
|
||||
swizzle(format->swizzle.value());
|
||||
|
||||
bool alignmentChanged = false;
|
||||
if (format->bytesPerBlock != 4) {
|
||||
const GLint alignment = (stride % 4 == 0) ? 4 : 1;
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, alignment));
|
||||
alignmentChanged = true;
|
||||
}
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
|
||||
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
||||
if (alignmentChanged)
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
|
||||
|
||||
unbind();
|
||||
|
||||
if (m_keepDataCopy) {
|
||||
m_dataCopy.resize(stride * size_.y);
|
||||
memcpy(m_dataCopy.data(), pixels, stride * size_.y);
|
||||
ITexture::ITexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy, bool opaque) :
|
||||
m_size(size), m_opaque(opaque), m_drmFormat(drmFormat), m_keepDataCopy(keepDataCopy) {
|
||||
if (m_keepDataCopy && stride && pixels) {
|
||||
m_dataCopy.resize(stride * size.y);
|
||||
memcpy(m_dataCopy.data(), pixels, stride * size.y);
|
||||
}
|
||||
}
|
||||
|
||||
void CTexture::createFromDma(const Aquamarine::SDMABUFAttrs& attrs, void* image) {
|
||||
if (!g_pHyprOpenGL->m_proc.glEGLImageTargetTexture2DOES) {
|
||||
Log::logger->log(Log::ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES");
|
||||
return;
|
||||
}
|
||||
ITexture::ITexture(std::span<const float> lut3D, size_t N) : m_type(TEXTURE_3D_LUT), m_size(lut3D.size() / 3, 1), m_isSynchronous(true) {}
|
||||
|
||||
m_opaque = NFormatUtils::isFormatOpaque(attrs.format);
|
||||
|
||||
// #TODO external only formats should be external aswell.
|
||||
// also needs a seperate color shader.
|
||||
/*if (NFormatUtils::isFormatYUV(attrs.format)) {
|
||||
m_target = GL_TEXTURE_EXTERNAL_OES;
|
||||
m_type = TEXTURE_EXTERNAL;
|
||||
} else {*/
|
||||
m_target = GL_TEXTURE_2D;
|
||||
m_type = NFormatUtils::isFormatOpaque(attrs.format) ? TEXTURE_RGBX : TEXTURE_RGBA;
|
||||
//}
|
||||
|
||||
m_size = attrs.size;
|
||||
allocate();
|
||||
m_eglImage = image;
|
||||
|
||||
bind();
|
||||
setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
GLCALL(g_pHyprOpenGL->m_proc.glEGLImageTargetTexture2DOES(m_target, image));
|
||||
unbind();
|
||||
bool ITexture::ok() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) {
|
||||
if (damage.empty())
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
ASSERT(format);
|
||||
|
||||
bind();
|
||||
|
||||
if (format->swizzle.has_value())
|
||||
swizzle(format->swizzle.value());
|
||||
|
||||
bool alignmentChanged = false;
|
||||
if (format->bytesPerBlock != 4) {
|
||||
const GLint alignment = (stride % 4 == 0) ? 4 : 1;
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, alignment));
|
||||
alignmentChanged = true;
|
||||
}
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
|
||||
|
||||
damage.copy().intersect(CBox{{}, m_size}).forEachRect([&format, &pixels](const auto& rect) {
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1));
|
||||
|
||||
int width = rect.x2 - rect.x1;
|
||||
int height = rect.y2 - rect.y1;
|
||||
GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height, format->glFormat, format->glType, pixels));
|
||||
});
|
||||
|
||||
if (alignmentChanged)
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
|
||||
|
||||
unbind();
|
||||
|
||||
if (m_keepDataCopy) {
|
||||
m_dataCopy.resize(stride * m_size.y);
|
||||
memcpy(m_dataCopy.data(), pixels, stride * m_size.y);
|
||||
}
|
||||
bool ITexture::isDMA() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTexture::destroyTexture() {
|
||||
if (m_texID) {
|
||||
GLCALL(glDeleteTextures(1, &m_texID));
|
||||
m_texID = 0;
|
||||
}
|
||||
|
||||
if (m_eglImage)
|
||||
g_pHyprOpenGL->m_proc.eglDestroyImageKHR(g_pHyprOpenGL->m_eglDisplay, m_eglImage);
|
||||
m_eglImage = nullptr;
|
||||
m_cachedStates.fill(std::nullopt);
|
||||
}
|
||||
|
||||
void CTexture::allocate() {
|
||||
if (!m_texID)
|
||||
GLCALL(glGenTextures(1, &m_texID));
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& CTexture::dataCopy() {
|
||||
const std::vector<uint8_t>& ITexture::dataCopy() {
|
||||
return m_dataCopy;
|
||||
}
|
||||
|
||||
void CTexture::bind() {
|
||||
GLCALL(glBindTexture(m_target, m_texID));
|
||||
}
|
||||
|
||||
void CTexture::unbind() {
|
||||
GLCALL(glBindTexture(m_target, 0));
|
||||
}
|
||||
|
||||
constexpr std::optional<size_t> CTexture::getCacheStateIndex(GLenum pname) {
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_WRAP_S: return TEXTURE_PAR_WRAP_S;
|
||||
case GL_TEXTURE_WRAP_T: return TEXTURE_PAR_WRAP_T;
|
||||
case GL_TEXTURE_MAG_FILTER: return TEXTURE_PAR_MAG_FILTER;
|
||||
case GL_TEXTURE_MIN_FILTER: return TEXTURE_PAR_MIN_FILTER;
|
||||
case GL_TEXTURE_SWIZZLE_R: return TEXTURE_PAR_SWIZZLE_R;
|
||||
case GL_TEXTURE_SWIZZLE_B: return TEXTURE_PAR_SWIZZLE_B;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void CTexture::setTexParameter(GLenum pname, GLint param) {
|
||||
const auto cacheIndex = getCacheStateIndex(pname);
|
||||
|
||||
if (!cacheIndex) {
|
||||
GLCALL(glTexParameteri(m_target, pname, param));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto idx = cacheIndex.value();
|
||||
|
||||
if (m_cachedStates[idx] == param)
|
||||
return;
|
||||
|
||||
m_cachedStates[idx] = param;
|
||||
GLCALL(glTexParameteri(m_target, pname, param));
|
||||
}
|
||||
|
||||
void CTexture::swizzle(const std::array<GLint, 4>& colors) {
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_R, colors.at(0));
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_G, colors.at(1));
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_B, colors.at(2));
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_A, colors.at(3));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,61 +16,43 @@ enum eTextureType : int8_t {
|
|||
TEXTURE_EXTERNAL, // EGLImage
|
||||
};
|
||||
|
||||
class CTexture {
|
||||
class ITexture {
|
||||
public:
|
||||
CTexture();
|
||||
ITexture(ITexture&) = delete;
|
||||
ITexture(ITexture&&) = delete;
|
||||
ITexture(const ITexture&&) = delete;
|
||||
ITexture(const ITexture&) = delete;
|
||||
|
||||
CTexture(CTexture&) = delete;
|
||||
CTexture(CTexture&&) = delete;
|
||||
CTexture(const CTexture&&) = delete;
|
||||
CTexture(const CTexture&) = delete;
|
||||
virtual ~ITexture() = default;
|
||||
|
||||
CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false);
|
||||
CTexture(std::span<const float> lut3D, size_t N);
|
||||
virtual void setTexParameter(GLenum pname, GLint param) = 0;
|
||||
virtual void allocate(const Vector2D& size, uint32_t drmFormat = 0) = 0;
|
||||
virtual void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) = 0;
|
||||
virtual void bind() {};
|
||||
virtual void unbind() {};
|
||||
virtual bool ok();
|
||||
virtual bool isDMA();
|
||||
|
||||
CTexture(const SP<Aquamarine::IBuffer> buffer, bool keepDataCopy = false);
|
||||
// this ctor takes ownership of the eglImage.
|
||||
CTexture(const Aquamarine::SDMABUFAttrs&, void* image);
|
||||
~CTexture();
|
||||
|
||||
void destroyTexture();
|
||||
void allocate();
|
||||
void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage);
|
||||
const std::vector<uint8_t>& dataCopy();
|
||||
void bind();
|
||||
void unbind();
|
||||
void setTexParameter(GLenum pname, GLint param);
|
||||
void swizzle(const std::array<GLint, 4>& colors);
|
||||
|
||||
eTextureType m_type = TEXTURE_RGBA;
|
||||
GLenum m_target = GL_TEXTURE_2D;
|
||||
GLuint m_texID = 0;
|
||||
Vector2D m_size = {};
|
||||
void* m_eglImage = nullptr;
|
||||
eTransform m_transform = HYPRUTILS_TRANSFORM_NORMAL;
|
||||
bool m_opaque = false;
|
||||
eTextureType m_type = TEXTURE_RGBA;
|
||||
Vector2D m_size = {};
|
||||
eTransform m_transform = HYPRUTILS_TRANSFORM_NORMAL;
|
||||
bool m_opaque = false;
|
||||
|
||||
uint32_t m_drmFormat = 0; // for shm
|
||||
bool m_isSynchronous = false;
|
||||
|
||||
GLenum magFilter = GL_LINEAR; // useNearestNeighbor overwrites these
|
||||
GLenum minFilter = GL_LINEAR;
|
||||
// TODO move to GLTexture
|
||||
GLuint m_texID = 0;
|
||||
GLenum magFilter = GL_LINEAR; // useNearestNeighbor overwrites these
|
||||
GLenum minFilter = GL_LINEAR;
|
||||
|
||||
private:
|
||||
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,
|
||||
};
|
||||
protected:
|
||||
ITexture() = default;
|
||||
ITexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size, bool keepDataCopy = false, bool opaque = false);
|
||||
ITexture(std::span<const float> lut3D, size_t N);
|
||||
|
||||
void createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
||||
void createFromDma(const Aquamarine::SDMABUFAttrs&, void* image);
|
||||
inline constexpr std::optional<size_t> getCacheStateIndex(GLenum pname);
|
||||
|
||||
bool m_keepDataCopy = false;
|
||||
std::vector<uint8_t> m_dataCopy;
|
||||
std::array<std::optional<GLint>, TEXTURE_PAR_LAST> m_cachedStates;
|
||||
bool m_keepDataCopy = false;
|
||||
std::vector<uint8_t> m_dataCopy;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class IWindowTransformer {
|
|||
|
||||
// called by Hyprland. For more data about what is being rendered, inspect render data.
|
||||
// returns the out fb.
|
||||
virtual CFramebuffer* transform(CFramebuffer* in) = 0;
|
||||
virtual IFramebuffer* transform(IFramebuffer* in) = 0;
|
||||
|
||||
// called by Hyprland before a window main pass is started.
|
||||
virtual void preWindowRender(CSurfacePassElement::SRenderData* pRenderData);
|
||||
|
|
|
|||
|
|
@ -155,9 +155,9 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
g_pHyprOpenGL->m_renderData.currentWindow = m_window;
|
||||
|
||||
// we'll take the liberty of using this as it should not be used rn
|
||||
CFramebuffer& alphaFB = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorFB;
|
||||
CFramebuffer& alphaSwapFB = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorSwapFB;
|
||||
auto* LASTFB = g_pHyprOpenGL->m_renderData.currentFB;
|
||||
auto alphaFB = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorFB;
|
||||
auto alphaSwapFB = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorSwapFB;
|
||||
auto LASTFB = g_pHyprOpenGL->m_renderData.currentFB;
|
||||
|
||||
fullBox.scale(pMonitor->m_scale).round();
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
g_pHyprOpenGL->m_renderData.damage.subtract(windowBox.copy().expand(-ROUNDING * pMonitor->m_scale)).intersect(saveDamage);
|
||||
g_pHyprOpenGL->m_renderData.renderModif.applyToRegion(g_pHyprOpenGL->m_renderData.damage);
|
||||
|
||||
alphaFB.bind();
|
||||
alphaFB->bind();
|
||||
|
||||
// build the matte
|
||||
// 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest.
|
||||
|
|
@ -202,7 +202,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
g_pHyprOpenGL->renderRect(windowBox, CHyprColor(0, 0, 0, 1.0),
|
||||
{.round = (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->m_scale, .roundingPower = ROUNDINGPOWER});
|
||||
|
||||
alphaSwapFB.bind();
|
||||
alphaSwapFB->bind();
|
||||
|
||||
// alpha swap just has the shadow color. It will be the "texture" to render.
|
||||
g_pHyprOpenGL->renderRect(fullBox, PWINDOW->m_realShadowColor->value().stripA(), {.round = 0});
|
||||
|
|
@ -213,7 +213,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
|
|||
|
||||
g_pHyprOpenGL->pushMonitorTransformEnabled(true);
|
||||
g_pHyprOpenGL->setRenderModifEnabled(false);
|
||||
g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.getTexture(), monbox, alphaFB);
|
||||
g_pHyprOpenGL->renderTextureMatte(alphaSwapFB->getTexture(), monbox, alphaFB);
|
||||
g_pHyprOpenGL->setRenderModifEnabled(true);
|
||||
g_pHyprOpenGL->popMonitorTransformEnabled();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@
|
|||
#include "../../layout/supplementary/DragController.hpp"
|
||||
|
||||
// shared things to conserve VRAM
|
||||
static SP<CTexture> m_tGradientActive = makeShared<CTexture>();
|
||||
static SP<CTexture> m_tGradientInactive = makeShared<CTexture>();
|
||||
static SP<CTexture> m_tGradientLockedActive = makeShared<CTexture>();
|
||||
static SP<CTexture> m_tGradientLockedInactive = makeShared<CTexture>();
|
||||
static SP<ITexture> m_tGradientActive;
|
||||
static SP<ITexture> m_tGradientInactive;
|
||||
static SP<ITexture> m_tGradientLockedActive;
|
||||
static SP<ITexture> m_tGradientLockedInactive;
|
||||
|
||||
constexpr int BAR_TEXT_PAD = 2;
|
||||
|
||||
|
|
@ -24,7 +24,16 @@ CHyprGroupBarDecoration::CHyprGroupBarDecoration(PHLWINDOW pWindow) : IHyprWindo
|
|||
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:enabled");
|
||||
static auto PENABLED = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
|
||||
|
||||
if (m_tGradientActive->m_texID == 0 && *PENABLED && *PGRADIENTS)
|
||||
if (!m_tGradientActive)
|
||||
m_tGradientActive = g_pHyprRenderer->createTexture();
|
||||
if (!m_tGradientInactive)
|
||||
m_tGradientInactive = g_pHyprRenderer->createTexture();
|
||||
if (!m_tGradientLockedActive)
|
||||
m_tGradientLockedActive = g_pHyprRenderer->createTexture();
|
||||
if (!m_tGradientLockedInactive)
|
||||
m_tGradientLockedInactive = g_pHyprRenderer->createTexture();
|
||||
|
||||
if (!m_tGradientActive->ok() && *PENABLED && *PGRADIENTS)
|
||||
refreshGroupBarGradients();
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +205,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
|||
if (*PGRADIENTS) {
|
||||
const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == Desktop::focusState()->window() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
||||
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
||||
if (GRADIENTTEX->m_texID) {
|
||||
if (GRADIENTTEX->ok()) {
|
||||
CTexPassElement::SRenderData data;
|
||||
data.tex = GRADIENTTEX;
|
||||
data.blur = blur;
|
||||
|
|
@ -234,7 +243,7 @@ void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
|||
Vector2D{(m_barWidth - (*PTEXTPADDING * 2)) * pMonitor->m_scale, (*PTITLEFONTSIZE + 2L * BAR_TEXT_PAD) * pMonitor->m_scale}, pMonitor->m_scale))
|
||||
.get();
|
||||
|
||||
SP<CTexture> titleTex;
|
||||
SP<ITexture> titleTex;
|
||||
if (m_dwGroupMembers[WINDOWINDEX] == Desktop::focusState()->window())
|
||||
titleTex = GROUPLOCKED ? pTitleTex->m_texLockedActive : pTitleTex->m_texActive;
|
||||
else
|
||||
|
|
@ -307,7 +316,7 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float
|
|||
#undef RENDER_TEXT
|
||||
}
|
||||
|
||||
static void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
|
||||
static void renderGradientTo(SP<ITexture> tex, CGradientValueData* grad) {
|
||||
|
||||
if (!Desktop::focusState()->monitor())
|
||||
return;
|
||||
|
|
@ -339,15 +348,7 @@ static void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
|
|||
cairo_surface_flush(CAIROSURFACE);
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
tex->allocate();
|
||||
tex->bind();
|
||||
tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
||||
tex->setTexParameter(GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferSize.x, bufferSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
tex = g_pHyprRenderer->createTexture(CAIROSURFACE);
|
||||
|
||||
// delete cairo
|
||||
cairo_destroy(CAIRO);
|
||||
|
|
@ -367,13 +368,11 @@ void refreshGroupBarGradients() {
|
|||
auto* const GROUPCOLACTIVELOCKED = sc<CGradientValueData*>((PGROUPCOLACTIVELOCKED.ptr())->getData());
|
||||
auto* const GROUPCOLINACTIVELOCKED = sc<CGradientValueData*>((PGROUPCOLINACTIVELOCKED.ptr())->getData());
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
if (m_tGradientActive->m_texID != 0) {
|
||||
m_tGradientActive->destroyTexture();
|
||||
m_tGradientInactive->destroyTexture();
|
||||
m_tGradientLockedActive->destroyTexture();
|
||||
m_tGradientLockedInactive->destroyTexture();
|
||||
if (m_tGradientActive && m_tGradientActive->ok()) {
|
||||
m_tGradientActive.reset();
|
||||
m_tGradientInactive.reset();
|
||||
m_tGradientLockedActive.reset();
|
||||
m_tGradientLockedInactive.reset();
|
||||
}
|
||||
|
||||
if (!*PENABLED || !*PGRADIENTS)
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ class CTitleTex {
|
|||
CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale);
|
||||
~CTitleTex() = default;
|
||||
|
||||
SP<CTexture> m_texActive;
|
||||
SP<CTexture> m_texInactive;
|
||||
SP<CTexture> m_texLockedActive;
|
||||
SP<CTexture> m_texLockedInactive;
|
||||
SP<ITexture> m_texActive;
|
||||
SP<ITexture> m_texInactive;
|
||||
SP<ITexture> m_texLockedActive;
|
||||
SP<ITexture> m_texLockedInactive;
|
||||
std::string m_content;
|
||||
|
||||
PHLWINDOWREF m_windowOwner;
|
||||
|
|
|
|||
170
src/render/gl/GLFramebuffer.cpp
Normal file
170
src/render/gl/GLFramebuffer.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#include "GLFramebuffer.hpp"
|
||||
#include "../OpenGL.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "macros.hpp"
|
||||
#include "render/Framebuffer.hpp"
|
||||
|
||||
CGLFramebuffer::CGLFramebuffer() : IFramebuffer() {}
|
||||
CGLFramebuffer::CGLFramebuffer(const std::string& name) : IFramebuffer(name) {}
|
||||
|
||||
bool CGLFramebuffer::internalAlloc(int w, int h, uint32_t drmFormat) {
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
bool firstAlloc = false;
|
||||
|
||||
if (!m_tex) {
|
||||
m_tex = g_pHyprRenderer->createTexture();
|
||||
m_tex->allocate({w, h});
|
||||
m_tex->bind();
|
||||
m_tex->setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
m_tex->setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
m_tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
m_tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
firstAlloc = true;
|
||||
}
|
||||
|
||||
if (!m_fbAllocated) {
|
||||
glGenFramebuffers(1, &m_fb);
|
||||
m_fbAllocated = true;
|
||||
firstAlloc = true;
|
||||
}
|
||||
|
||||
if (firstAlloc) {
|
||||
const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
m_tex->bind();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, w, h, 0, format->glFormat, format->glType, nullptr);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex->m_texID, 0);
|
||||
|
||||
if (m_stencilTex && m_stencilTex->ok()) {
|
||||
m_stencilTex->bind();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_stencilTex->m_texID, 0);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Framebuffer incomplete, couldn't create! (FB status: {}, GL Error: 0x{:x})", status, sc<int>(glGetError()));
|
||||
|
||||
if (m_stencilTex && m_stencilTex->ok())
|
||||
m_stencilTex->unbind();
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Framebuffer created, status {}", status);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CGLFramebuffer::addStencil(SP<ITexture> tex) {
|
||||
if (m_stencilTex == tex)
|
||||
return;
|
||||
|
||||
RASSERT(!m_fbAllocated, "Should add stencil tex prior to FB allocation")
|
||||
m_stencilTex = tex;
|
||||
}
|
||||
|
||||
void CGLFramebuffer::bind() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb);
|
||||
|
||||
if (g_pHyprOpenGL)
|
||||
g_pHyprOpenGL->setViewport(0, 0, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.x, g_pHyprOpenGL->m_renderData.pMonitor->m_pixelSize.y);
|
||||
else
|
||||
glViewport(0, 0, m_size.x, m_size.y);
|
||||
}
|
||||
|
||||
void CGLFramebuffer::unbind() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void CGLFramebuffer::release() {
|
||||
if (m_fbAllocated) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fb);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glDeleteFramebuffers(1, &m_fb);
|
||||
m_fbAllocated = false;
|
||||
m_fb = 0;
|
||||
}
|
||||
|
||||
if (m_tex)
|
||||
m_tex.reset();
|
||||
|
||||
m_size = Vector2D();
|
||||
}
|
||||
|
||||
bool CGLFramebuffer::readPixels(CHLBufferReference buffer, uint32_t offsetX, uint32_t offsetY, uint32_t width, uint32_t height) {
|
||||
auto shm = buffer->shm();
|
||||
auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm
|
||||
|
||||
const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format);
|
||||
if (!PFORMAT) {
|
||||
LOGM(Log::ERR, "Can't copy: failed to find a pixel format");
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, getFBID());
|
||||
bind();
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
uint32_t packStride = NFormatUtils::minStride(PFORMAT, m_size.x);
|
||||
int glFormat = PFORMAT->glFormat;
|
||||
|
||||
if (glFormat == GL_RGBA)
|
||||
glFormat = GL_BGRA_EXT;
|
||||
|
||||
if (glFormat != GL_BGRA_EXT && glFormat != GL_RGB) {
|
||||
if (PFORMAT->swizzle.has_value()) {
|
||||
std::array<GLint, 4> RGBA = SWIZZLE_RGBA;
|
||||
std::array<GLint, 4> BGRA = SWIZZLE_BGRA;
|
||||
if (PFORMAT->swizzle == RGBA)
|
||||
glFormat = GL_RGBA;
|
||||
else if (PFORMAT->swizzle == BGRA)
|
||||
glFormat = GL_BGRA_EXT;
|
||||
else {
|
||||
LOGM(Log::ERR, "Copied frame via shm might be broken or color flipped");
|
||||
glFormat = GL_RGBA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This could be optimized by using a pixel buffer object to make this async,
|
||||
// but really clients should just use a dma buffer anyways.
|
||||
if (packStride == sc<uint32_t>(shm.stride)) {
|
||||
glReadPixels(offsetX, offsetY, width > 0 ? width : m_size.x, height > 0 ? height : m_size.y, glFormat, PFORMAT->glType, pixelData);
|
||||
} else {
|
||||
const auto h = height > 0 ? height : m_size.y;
|
||||
for (size_t i = 0; i < h; ++i) {
|
||||
uint32_t y = i;
|
||||
glReadPixels(offsetX, offsetY + y, width > 0 ? width : m_size.x, 1, glFormat, PFORMAT->glType, pixelData + i * shm.stride);
|
||||
}
|
||||
}
|
||||
|
||||
unbind();
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
CGLFramebuffer::~CGLFramebuffer() {
|
||||
release();
|
||||
}
|
||||
|
||||
GLuint CGLFramebuffer::getFBID() {
|
||||
return m_fbAllocated ? m_fb : 0;
|
||||
}
|
||||
|
||||
void CGLFramebuffer::invalidate(const std::vector<GLenum>& attachments) {
|
||||
if (!isAllocated())
|
||||
return;
|
||||
|
||||
glInvalidateFramebuffer(GL_FRAMEBUFFER, attachments.size(), attachments.data());
|
||||
}
|
||||
30
src/render/gl/GLFramebuffer.hpp
Normal file
30
src/render/gl/GLFramebuffer.hpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../defines.hpp"
|
||||
#include "../Texture.hpp"
|
||||
#include "../Framebuffer.hpp"
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
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 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;
|
||||
|
||||
private:
|
||||
GLuint m_fb = -1;
|
||||
|
||||
friend class CGLRenderbuffer;
|
||||
};
|
||||
71
src/render/gl/GLRenderbuffer.cpp
Normal file
71
src/render/gl/GLRenderbuffer.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#include "GLRenderbuffer.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "../OpenGL.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
#include "../Framebuffer.hpp"
|
||||
#include "GLFramebuffer.hpp"
|
||||
#include "render/Renderbuffer.hpp"
|
||||
#include <hyprutils/memory/SharedPtr.hpp>
|
||||
#include <hyprutils/signal/Listener.hpp>
|
||||
#include <hyprutils/signal/Signal.hpp>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
CGLRenderbuffer::~CGLRenderbuffer() {
|
||||
if (!g_pCompositor || g_pCompositor->m_isShuttingDown || !g_pHyprRenderer)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
unbind();
|
||||
m_framebuffer->release();
|
||||
|
||||
if (m_rbo)
|
||||
glDeleteRenderbuffers(1, &m_rbo);
|
||||
|
||||
if (m_image != EGL_NO_IMAGE_KHR)
|
||||
g_pHyprOpenGL->m_proc.eglDestroyImageKHR(g_pHyprOpenGL->m_eglDisplay, m_image);
|
||||
}
|
||||
|
||||
CGLRenderbuffer::CGLRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format) : IRenderbuffer(buffer, format) {
|
||||
auto dma = buffer->dmabuf();
|
||||
|
||||
m_image = g_pHyprOpenGL->createEGLImage(dma);
|
||||
if (m_image == EGL_NO_IMAGE_KHR) {
|
||||
Log::logger->log(Log::ERR, "rb: createEGLImage failed");
|
||||
return;
|
||||
}
|
||||
|
||||
glGenRenderbuffers(1, &m_rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_rbo);
|
||||
g_pHyprOpenGL->m_proc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, m_image);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
m_framebuffer = makeShared<CGLFramebuffer>();
|
||||
glGenFramebuffers(1, &GLFB(m_framebuffer)->m_fb);
|
||||
GLFB(m_framebuffer)->m_fbAllocated = true;
|
||||
m_framebuffer->m_size = buffer->size;
|
||||
m_framebuffer->m_drmFormat = dma.format;
|
||||
m_framebuffer->bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
Log::logger->log(Log::ERR, "rbo: glCheckFramebufferStatus failed");
|
||||
return;
|
||||
}
|
||||
|
||||
GLFB(m_framebuffer)->unbind();
|
||||
|
||||
m_listeners.destroyBuffer = buffer->events.destroy.listen([this] { g_pHyprRenderer->onRenderbufferDestroy(this); });
|
||||
|
||||
m_good = true;
|
||||
}
|
||||
|
||||
void CGLRenderbuffer::bind() {
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
m_framebuffer->bind();
|
||||
}
|
||||
|
||||
void CGLRenderbuffer::unbind() {
|
||||
GLFB(m_framebuffer)->unbind();
|
||||
}
|
||||
20
src/render/gl/GLRenderbuffer.hpp
Normal file
20
src/render/gl/GLRenderbuffer.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../helpers/memory/Memory.hpp"
|
||||
#include "../Renderbuffer.hpp"
|
||||
#include <aquamarine/buffer/Buffer.hpp>
|
||||
|
||||
class CMonitor;
|
||||
|
||||
class CGLRenderbuffer : public IRenderbuffer {
|
||||
public:
|
||||
CGLRenderbuffer(SP<Aquamarine::IBuffer> buffer, uint32_t format);
|
||||
~CGLRenderbuffer();
|
||||
|
||||
void bind() override;
|
||||
void unbind() override;
|
||||
|
||||
private:
|
||||
void* m_image = nullptr;
|
||||
GLuint m_rbo = 0;
|
||||
};
|
||||
223
src/render/gl/GLTexture.cpp
Normal file
223
src/render/gl/GLTexture.cpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
#include "GLTexture.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
#include "../../helpers/Format.hpp"
|
||||
#include "render/Texture.hpp"
|
||||
#include <cstring>
|
||||
|
||||
CGLTexture::CGLTexture(bool opaque) {
|
||||
m_opaque = opaque;
|
||||
}
|
||||
|
||||
CGLTexture::~CGLTexture() {
|
||||
if (!g_pCompositor || g_pCompositor->m_isShuttingDown || !g_pHyprRenderer)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
if (m_texID) {
|
||||
GLCALL(glDeleteTextures(1, &m_texID));
|
||||
m_texID = 0;
|
||||
}
|
||||
|
||||
if (m_eglImage)
|
||||
g_pHyprOpenGL->m_proc.eglDestroyImageKHR(g_pHyprOpenGL->m_eglDisplay, m_eglImage);
|
||||
m_eglImage = nullptr;
|
||||
m_cachedStates.fill(std::nullopt);
|
||||
}
|
||||
|
||||
CGLTexture::CGLTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_, bool keepDataCopy, bool opaque) :
|
||||
ITexture(drmFormat, pixels, stride, size_, keepDataCopy, opaque) {
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
ASSERT(format);
|
||||
|
||||
m_type = format->withAlpha ? TEXTURE_RGBA : TEXTURE_RGBX;
|
||||
m_size = size_;
|
||||
m_isSynchronous = true;
|
||||
m_target = GL_TEXTURE_2D;
|
||||
allocate(size_);
|
||||
bind();
|
||||
setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (format->swizzle.has_value())
|
||||
swizzle(format->swizzle.value());
|
||||
|
||||
bool alignmentChanged = false;
|
||||
if (format->bytesPerBlock != 4) {
|
||||
const GLint alignment = (stride % 4 == 0) ? 4 : 1;
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, alignment));
|
||||
alignmentChanged = true;
|
||||
}
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
|
||||
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
||||
if (alignmentChanged)
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
CGLTexture::CGLTexture(const Aquamarine::SDMABUFAttrs& attrs, void* image, bool opaque) {
|
||||
m_opaque = opaque;
|
||||
if (!g_pHyprOpenGL->m_proc.glEGLImageTargetTexture2DOES) {
|
||||
Log::logger->log(Log::ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES");
|
||||
return;
|
||||
}
|
||||
|
||||
m_opaque = NFormatUtils::isFormatOpaque(attrs.format);
|
||||
|
||||
// #TODO external only formats should be external aswell.
|
||||
// also needs a seperate color shader.
|
||||
/*if (NFormatUtils::isFormatYUV(attrs.format)) {
|
||||
m_target = GL_TEXTURE_EXTERNAL_OES;
|
||||
m_type = TEXTURE_EXTERNAL;
|
||||
} else {*/
|
||||
m_target = GL_TEXTURE_2D;
|
||||
m_type = NFormatUtils::isFormatOpaque(attrs.format) ? TEXTURE_RGBX : TEXTURE_RGBA;
|
||||
//}
|
||||
|
||||
allocate(attrs.size);
|
||||
m_eglImage = image;
|
||||
|
||||
bind();
|
||||
setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
GLCALL(g_pHyprOpenGL->m_proc.glEGLImageTargetTexture2DOES(m_target, image));
|
||||
unbind();
|
||||
}
|
||||
|
||||
CGLTexture::CGLTexture(std::span<const float> lut3D, size_t N) : ITexture(lut3D, N), m_target(GL_TEXTURE_3D) {
|
||||
allocate({});
|
||||
bind();
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
||||
setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
setTexParameter(GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// Expand RGB->RGBA on upload (alpha=1)
|
||||
std::vector<float> rgba;
|
||||
rgba.resize(N * N * N * 4);
|
||||
for (size_t i = 0, j = 0; i < N * N * N; ++i, j += 3) {
|
||||
rgba[i * 4 + 0] = lut3D[j + 0];
|
||||
rgba[i * 4 + 1] = lut3D[j + 1];
|
||||
rgba[i * 4 + 2] = lut3D[j + 2];
|
||||
rgba[i * 4 + 3] = 1.F;
|
||||
}
|
||||
|
||||
GLCALL(glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, N, N, N, 0, GL_RGBA, GL_FLOAT, rgba.data()));
|
||||
|
||||
unbind();
|
||||
}
|
||||
|
||||
void CGLTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) {
|
||||
if (damage.empty())
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto format = NFormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
ASSERT(format);
|
||||
|
||||
bind();
|
||||
|
||||
if (format->swizzle.has_value())
|
||||
swizzle(format->swizzle.value());
|
||||
|
||||
bool alignmentChanged = false;
|
||||
if (format->bytesPerBlock != 4) {
|
||||
const GLint alignment = (stride % 4 == 0) ? 4 : 1;
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, alignment));
|
||||
alignmentChanged = true;
|
||||
}
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
|
||||
|
||||
damage.copy().intersect(CBox{{}, m_size}).forEachRect([&format, &pixels](const auto& rect) {
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1));
|
||||
|
||||
int width = rect.x2 - rect.x1;
|
||||
int height = rect.y2 - rect.y1;
|
||||
GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height, format->glFormat, format->glType, pixels));
|
||||
});
|
||||
|
||||
if (alignmentChanged)
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
|
||||
|
||||
unbind();
|
||||
|
||||
if (m_keepDataCopy) {
|
||||
m_dataCopy.resize(stride * m_size.y);
|
||||
memcpy(m_dataCopy.data(), pixels, stride * m_size.y);
|
||||
}
|
||||
}
|
||||
|
||||
void CGLTexture::allocate(const Vector2D& size, uint32_t drmFormat) {
|
||||
if (!m_texID)
|
||||
GLCALL(glGenTextures(1, &m_texID));
|
||||
m_size = size;
|
||||
m_drmFormat = drmFormat;
|
||||
}
|
||||
|
||||
void CGLTexture::bind() {
|
||||
GLCALL(glBindTexture(m_target, m_texID));
|
||||
}
|
||||
|
||||
void CGLTexture::unbind() {
|
||||
GLCALL(glBindTexture(m_target, 0));
|
||||
}
|
||||
|
||||
bool CGLTexture::ok() {
|
||||
return m_texID > 0;
|
||||
}
|
||||
|
||||
bool CGLTexture::isDMA() {
|
||||
return m_eglImage;
|
||||
}
|
||||
|
||||
constexpr std::optional<size_t> CGLTexture::getCacheStateIndex(GLenum pname) {
|
||||
switch (pname) {
|
||||
case GL_TEXTURE_WRAP_S: return TEXTURE_PAR_WRAP_S;
|
||||
case GL_TEXTURE_WRAP_T: return TEXTURE_PAR_WRAP_T;
|
||||
case GL_TEXTURE_MAG_FILTER: return TEXTURE_PAR_MAG_FILTER;
|
||||
case GL_TEXTURE_MIN_FILTER: return TEXTURE_PAR_MIN_FILTER;
|
||||
case GL_TEXTURE_SWIZZLE_R: return TEXTURE_PAR_SWIZZLE_R;
|
||||
case GL_TEXTURE_SWIZZLE_B: return TEXTURE_PAR_SWIZZLE_B;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void CGLTexture::setTexParameter(GLenum pname, GLint param) {
|
||||
const auto cacheIndex = getCacheStateIndex(pname);
|
||||
|
||||
if (!cacheIndex) {
|
||||
GLCALL(glTexParameteri(m_target, pname, param));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto idx = cacheIndex.value();
|
||||
|
||||
if (m_cachedStates[idx] == param)
|
||||
return;
|
||||
|
||||
m_cachedStates[idx] = param;
|
||||
GLCALL(glTexParameteri(m_target, pname, param));
|
||||
}
|
||||
|
||||
void CGLTexture::swizzle(const std::array<GLint, 4>& colors) {
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_R, colors.at(0));
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_G, colors.at(1));
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_B, colors.at(2));
|
||||
setTexParameter(GL_TEXTURE_SWIZZLE_A, colors.at(3));
|
||||
}
|
||||
49
src/render/gl/GLTexture.hpp
Normal file
49
src/render/gl/GLTexture.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Texture.hpp"
|
||||
#include <aquamarine/buffer/Buffer.hpp>
|
||||
#include <hyprutils/math/Misc.hpp>
|
||||
|
||||
class CGLTexture : public ITexture {
|
||||
public:
|
||||
using ITexture::ITexture;
|
||||
|
||||
CGLTexture(CGLTexture&) = delete;
|
||||
CGLTexture(CGLTexture&&) = delete;
|
||||
CGLTexture(const CGLTexture&&) = delete;
|
||||
CGLTexture(const CGLTexture&) = delete;
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
};
|
||||
|
|
@ -6,7 +6,7 @@ CFramebufferElement::CFramebufferElement(const CFramebufferElement::SFramebuffer
|
|||
}
|
||||
|
||||
void CFramebufferElement::draw(const CRegion& damage) {
|
||||
CFramebuffer* fb = nullptr;
|
||||
SP<IFramebuffer> fb = nullptr;
|
||||
|
||||
if (m_data.main) {
|
||||
switch (m_data.framebufferID) {
|
||||
|
|
@ -22,12 +22,12 @@ void CFramebufferElement::draw(const CRegion& damage) {
|
|||
|
||||
} else {
|
||||
switch (m_data.framebufferID) {
|
||||
case FB_MONITOR_RENDER_EXTRA_OFFLOAD: fb = &g_pHyprOpenGL->m_renderData.pCurrentMonData->offloadFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MIRROR: fb = &g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP: fb = &g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorSwapFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_OFF_MAIN: fb = &g_pHyprOpenGL->m_renderData.pCurrentMonData->offMainFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR: fb = &g_pHyprOpenGL->m_renderData.pCurrentMonData->monitorMirrorFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_BLUR: fb = &g_pHyprOpenGL->m_renderData.pCurrentMonData->blurFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_OFFLOAD: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->offloadFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MIRROR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MIRROR_SWAP: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->mirrorSwapFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_OFF_MAIN: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->offMainFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_MONITOR_MIRROR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->monitorMirrorFB; break;
|
||||
case FB_MONITOR_RENDER_EXTRA_BLUR: fb = g_pHyprOpenGL->m_renderData.pCurrentMonData->blurFB; break;
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ void CRenderPass::renderDebugData() {
|
|||
std::unordered_map<CWLSurfaceResource*, float> offsets;
|
||||
|
||||
// render focus stuff
|
||||
auto renderHLSurface = [&offsets](SP<CTexture> texture, SP<CWLSurfaceResource> surface, const CHyprColor& color) {
|
||||
auto renderHLSurface = [&offsets](SP<ITexture> texture, SP<CWLSurfaceResource> surface, const CHyprColor& color) {
|
||||
if (!surface || !texture)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "PassElement.hpp"
|
||||
|
||||
class CGradientValueData;
|
||||
class CTexture;
|
||||
class ITexture;
|
||||
|
||||
class CRenderPass {
|
||||
public:
|
||||
|
|
@ -36,7 +36,7 @@ class CRenderPass {
|
|||
|
||||
struct {
|
||||
bool present = false;
|
||||
SP<CTexture> keyboardFocusText, pointerFocusText, lastWindowText;
|
||||
SP<ITexture> keyboardFocusText, pointerFocusText, lastWindowText;
|
||||
} m_debugData;
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "../../helpers/time/Time.hpp"
|
||||
|
||||
class CWLSurfaceResource;
|
||||
class CTexture;
|
||||
class ITexture;
|
||||
class CSyncTimeline;
|
||||
|
||||
class CSurfacePassElement : public IPassElement {
|
||||
|
|
@ -16,7 +16,7 @@ class CSurfacePassElement : public IPassElement {
|
|||
|
||||
void* data = nullptr;
|
||||
SP<CWLSurfaceResource> surface = nullptr;
|
||||
SP<CTexture> texture = nullptr;
|
||||
SP<ITexture> texture = nullptr;
|
||||
bool mainSurface = true;
|
||||
double w = 0, h = 0;
|
||||
int rounding = 0;
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
#include <optional>
|
||||
|
||||
class CWLSurfaceResource;
|
||||
class CTexture;
|
||||
class ITexture;
|
||||
class CSyncTimeline;
|
||||
|
||||
class CTexPassElement : public IPassElement {
|
||||
public:
|
||||
struct SRenderData {
|
||||
SP<CTexture> tex;
|
||||
SP<ITexture> tex;
|
||||
CBox box;
|
||||
float a = 1.F;
|
||||
float blurA = 1.F;
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ void CTextureMatteElement::draw(const CRegion& damage) {
|
|||
if (m_data.disableTransformAndModify) {
|
||||
g_pHyprOpenGL->pushMonitorTransformEnabled(true);
|
||||
g_pHyprOpenGL->setRenderModifEnabled(false);
|
||||
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, *m_data.fb);
|
||||
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb);
|
||||
g_pHyprOpenGL->setRenderModifEnabled(true);
|
||||
g_pHyprOpenGL->popMonitorTransformEnabled();
|
||||
} else
|
||||
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, *m_data.fb);
|
||||
g_pHyprOpenGL->renderTextureMatte(m_data.tex, m_data.box, m_data.fb);
|
||||
}
|
||||
|
||||
bool CTextureMatteElement::needsLiveBlur() {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
#include "PassElement.hpp"
|
||||
#include "../Framebuffer.hpp"
|
||||
|
||||
class CTexture;
|
||||
class ITexture;
|
||||
|
||||
class CTextureMatteElement : public IPassElement {
|
||||
public:
|
||||
struct STextureMatteData {
|
||||
CBox box;
|
||||
SP<CTexture> tex;
|
||||
SP<CFramebuffer> fb;
|
||||
SP<ITexture> tex;
|
||||
SP<IFramebuffer> fb;
|
||||
bool disableTransformAndModify = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue