wayland/core: move to new impl (#6268)
* wayland/core/dmabuf: move to new impl it's the final countdown
This commit is contained in:
parent
c31d9ef417
commit
6967a31450
147 changed files with 5388 additions and 2226 deletions
|
|
@ -1,22 +1,26 @@
|
|||
#include "Framebuffer.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
|
||||
CFramebuffer::CFramebuffer() {
|
||||
m_cTex = makeShared<CTexture>();
|
||||
}
|
||||
|
||||
bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
|
||||
bool firstAlloc = false;
|
||||
RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h);
|
||||
|
||||
uint32_t glFormat = drmFormatToGL(drmFormat);
|
||||
uint32_t glType = glFormatToType(glFormat);
|
||||
uint32_t glFormat = FormatUtils::drmFormatToGL(drmFormat);
|
||||
uint32_t glType = FormatUtils::glFormatToType(glFormat);
|
||||
|
||||
if (m_iFb == (uint32_t)-1) {
|
||||
firstAlloc = true;
|
||||
glGenFramebuffers(1, &m_iFb);
|
||||
}
|
||||
|
||||
if (m_cTex.m_iTexID == 0) {
|
||||
if (m_cTex->m_iTexID == 0) {
|
||||
firstAlloc = true;
|
||||
glGenTextures(1, &m_cTex.m_iTexID);
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
|
||||
m_cTex->allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex->m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
|
@ -24,11 +28,11 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
|
|||
}
|
||||
|
||||
if (firstAlloc || m_vSize != Vector2D(w, h)) {
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex->m_iTexID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, w, h, 0, GL_RGBA, glType, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex->m_iTexID, 0);
|
||||
|
||||
// TODO: Allow this with gles2
|
||||
#ifndef GLES2
|
||||
|
|
@ -87,12 +91,9 @@ void CFramebuffer::release() {
|
|||
if (m_iFb != (uint32_t)-1 && m_iFb)
|
||||
glDeleteFramebuffers(1, &m_iFb);
|
||||
|
||||
if (m_cTex.m_iTexID)
|
||||
glDeleteTextures(1, &m_cTex.m_iTexID);
|
||||
|
||||
m_cTex.m_iTexID = 0;
|
||||
m_iFb = -1;
|
||||
m_vSize = Vector2D();
|
||||
m_cTex->destroyTexture();
|
||||
m_iFb = -1;
|
||||
m_vSize = Vector2D();
|
||||
}
|
||||
|
||||
CFramebuffer::~CFramebuffer() {
|
||||
|
|
|
|||
|
|
@ -5,19 +5,20 @@
|
|||
|
||||
class CFramebuffer {
|
||||
public:
|
||||
CFramebuffer();
|
||||
~CFramebuffer();
|
||||
|
||||
bool alloc(int w, int h, uint32_t format = GL_RGBA);
|
||||
void addStencil();
|
||||
void bind();
|
||||
void release();
|
||||
void reset();
|
||||
bool isAllocated();
|
||||
bool alloc(int w, int h, uint32_t format = GL_RGBA);
|
||||
void addStencil();
|
||||
void bind();
|
||||
void release();
|
||||
void reset();
|
||||
bool isAllocated();
|
||||
|
||||
Vector2D m_vSize;
|
||||
Vector2D m_vSize;
|
||||
|
||||
CTexture m_cTex;
|
||||
GLuint m_iFb = -1;
|
||||
SP<CTexture> m_cTex;
|
||||
GLuint m_iFb = -1;
|
||||
|
||||
CTexture* m_pStencilTex = nullptr;
|
||||
SP<CTexture> m_pStencilTex;
|
||||
};
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
#include "../config/ConfigValue.hpp"
|
||||
#include "../desktop/LayerSurface.hpp"
|
||||
#include "../protocols/LayerShell.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include <xf86drm.h>
|
||||
|
||||
inline void loadGLProc(void* pProc, const char* name) {
|
||||
void* proc = (void*)eglGetProcAddress(name);
|
||||
|
|
@ -21,7 +23,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
|||
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)),
|
||||
"Couldn't unset current EGL!");
|
||||
|
||||
auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
|
||||
auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
|
||||
const std::string EGLEXTENSIONS = (const char*)eglQueryString(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_EXTENSIONS);
|
||||
|
||||
RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!");
|
||||
|
||||
|
|
@ -33,12 +36,25 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
|||
Debug::log(LOG, "Using: {}", (char*)glGetString(GL_VERSION));
|
||||
Debug::log(LOG, "Vendor: {}", (char*)glGetString(GL_VENDOR));
|
||||
Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER));
|
||||
Debug::log(LOG, "Supported extensions size: {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '));
|
||||
Debug::log(LOG, "Supported extensions: ({}) {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '), m_szExtensions);
|
||||
|
||||
loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES");
|
||||
loadGLProc(&m_sProc.eglCreateImageKHR, "eglCreateImageKHR");
|
||||
loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR");
|
||||
loadGLProc(&m_sProc.eglQueryDmaBufFormatsEXT, "eglQueryDmaBufFormatsEXT");
|
||||
loadGLProc(&m_sProc.eglQueryDmaBufModifiersEXT, "eglQueryDmaBufModifiersEXT");
|
||||
loadGLProc(&m_sProc.glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
|
||||
|
||||
m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra");
|
||||
m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra");
|
||||
m_sExts.EXT_image_dma_buf_import = EGLEXTENSIONS.contains("EXT_image_dma_buf_import");
|
||||
m_sExts.EXT_image_dma_buf_import_modifiers = EGLEXTENSIONS.contains("EXT_image_dma_buf_import_modifiers");
|
||||
|
||||
RASSERT(m_szExtensions.contains("GL_EXT_texture_format_BGRA8888"), "GL_EXT_texture_format_BGRA8888 support by the GPU driver is required");
|
||||
|
||||
if (!m_sExts.EXT_read_format_bgra)
|
||||
Debug::log(WARN, "Your GPU does not support GL_EXT_read_format_bgra, this may cause issues with texture importing");
|
||||
if (!m_sExts.EXT_image_dma_buf_import || !m_sExts.EXT_image_dma_buf_import_modifiers)
|
||||
Debug::log(WARN, "Your GPU does not support DMABUFs, this will possibly cause issues and will take a hit on the performance.");
|
||||
|
||||
#ifdef USE_TRACY_GPU
|
||||
|
||||
|
|
@ -54,6 +70,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
|||
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
|
||||
#endif
|
||||
|
||||
initDRMFormats();
|
||||
|
||||
static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast<CMonitor*>(data)); });
|
||||
|
||||
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");
|
||||
|
|
@ -61,6 +79,171 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
|||
m_tGlobalTimer.reset();
|
||||
}
|
||||
|
||||
std::vector<uint64_t> CHyprOpenGLImpl::getModsForFormat(EGLint format) {
|
||||
// TODO: return std::expected when clang supports it
|
||||
|
||||
if (!m_sExts.EXT_image_dma_buf_import_modifiers)
|
||||
return {};
|
||||
|
||||
EGLint len = 0;
|
||||
if (!m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, 0, nullptr, nullptr, &len)) {
|
||||
Debug::log(ERR, "EGL: Failed to query mods");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (len <= 0)
|
||||
return {};
|
||||
|
||||
std::vector<uint64_t> mods;
|
||||
std::vector<EGLBoolean> external;
|
||||
|
||||
mods.resize(len);
|
||||
external.resize(len);
|
||||
|
||||
m_sProc.eglQueryDmaBufModifiersEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), format, len, mods.data(), external.data(), &len);
|
||||
|
||||
std::vector<uint64_t> result;
|
||||
for (size_t i = 0; i < mods.size(); ++i) {
|
||||
if (external.at(i))
|
||||
continue;
|
||||
|
||||
result.push_back(mods.at(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::initDRMFormats() {
|
||||
const auto DISABLE_MODS = envEnabled("HYPRLAND_EGL_NO_MODIFIERS");
|
||||
if (DISABLE_MODS)
|
||||
Debug::log(WARN, "HYPRLAND_EGL_NO_MODIFIERS set, disabling modifiers");
|
||||
|
||||
if (!m_sExts.EXT_image_dma_buf_import) {
|
||||
Debug::log(ERR, "EGL: No dmabuf import, DMABufs will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<EGLint> formats;
|
||||
|
||||
if (!m_sExts.EXT_image_dma_buf_import_modifiers || !m_sProc.eglQueryDmaBufFormatsEXT) {
|
||||
formats.push_back(DRM_FORMAT_ARGB8888);
|
||||
formats.push_back(DRM_FORMAT_XRGB8888);
|
||||
Debug::log(WARN, "EGL: No mod support");
|
||||
} else {
|
||||
EGLint len = 0;
|
||||
m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), 0, nullptr, &len);
|
||||
formats.resize(len);
|
||||
m_sProc.eglQueryDmaBufFormatsEXT(wlr_egl_get_display(g_pCompositor->m_sWLREGL), len, formats.data(), &len);
|
||||
}
|
||||
|
||||
if (formats.size() == 0) {
|
||||
Debug::log(ERR, "EGL: Failed to get formats, DMABufs will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "Supported DMA-BUF formats:");
|
||||
|
||||
std::vector<SDRMFormat> dmaFormats;
|
||||
|
||||
for (auto& fmt : formats) {
|
||||
std::vector<uint64_t> mods;
|
||||
if (!DISABLE_MODS)
|
||||
mods = getModsForFormat(fmt);
|
||||
else
|
||||
mods = {DRM_FORMAT_MOD_LINEAR};
|
||||
|
||||
m_bHasModifiers = m_bHasModifiers || mods.size() > 0;
|
||||
|
||||
if (mods.size() == 0)
|
||||
continue;
|
||||
|
||||
dmaFormats.push_back(SDRMFormat{
|
||||
.format = fmt,
|
||||
.mods = mods,
|
||||
});
|
||||
|
||||
std::vector<std::pair<uint64_t, std::string>> modifierData;
|
||||
|
||||
auto fmtName = drmGetFormatName(fmt);
|
||||
Debug::log(LOG, "EGL: GPU Supports Format {} (0x{:x})", fmtName ? fmtName : "?unknown?", fmt);
|
||||
for (auto& mod : mods) {
|
||||
auto modName = drmGetFormatModifierName(mod);
|
||||
modifierData.emplace_back(std::make_pair<>(mod, modName ? modName : "?unknown?"));
|
||||
free(modName);
|
||||
}
|
||||
free(fmtName);
|
||||
|
||||
mods.clear();
|
||||
std::sort(modifierData.begin(), modifierData.end(), [](const auto& a, const auto& b) {
|
||||
if (a.first == 0)
|
||||
return false;
|
||||
if (a.second.contains("DCC"))
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
for (auto& [m, name] : modifierData) {
|
||||
Debug::log(LOG, "EGL: | with modifier {} (0x{:x})", name, m);
|
||||
mods.emplace_back(m);
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(LOG, "EGL: {} formats found in total. Some modifiers may be omitted as they are external-only.", dmaFormats.size());
|
||||
|
||||
drmFormats = dmaFormats;
|
||||
}
|
||||
|
||||
EGLImageKHR CHyprOpenGLImpl::createEGLImage(const SDMABUFAttrs& attrs) {
|
||||
std::vector<uint32_t> attribs;
|
||||
|
||||
attribs.push_back(EGL_WIDTH);
|
||||
attribs.push_back(attrs.size.x);
|
||||
attribs.push_back(EGL_HEIGHT);
|
||||
attribs.push_back(attrs.size.y);
|
||||
attribs.push_back(EGL_LINUX_DRM_FOURCC_EXT);
|
||||
attribs.push_back(attrs.format);
|
||||
|
||||
struct {
|
||||
EGLint fd;
|
||||
EGLint offset;
|
||||
EGLint pitch;
|
||||
EGLint modlo;
|
||||
EGLint modhi;
|
||||
} attrNames[4] = {
|
||||
{EGL_DMA_BUF_PLANE0_FD_EXT, EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE0_PITCH_EXT, EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT},
|
||||
{EGL_DMA_BUF_PLANE1_FD_EXT, EGL_DMA_BUF_PLANE1_OFFSET_EXT, EGL_DMA_BUF_PLANE1_PITCH_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT},
|
||||
{EGL_DMA_BUF_PLANE2_FD_EXT, EGL_DMA_BUF_PLANE2_OFFSET_EXT, EGL_DMA_BUF_PLANE2_PITCH_EXT, EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT},
|
||||
{EGL_DMA_BUF_PLANE3_FD_EXT, EGL_DMA_BUF_PLANE3_OFFSET_EXT, EGL_DMA_BUF_PLANE3_PITCH_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT}};
|
||||
|
||||
for (int i = 0; i < attrs.planes; i++) {
|
||||
attribs.push_back(attrNames[i].fd);
|
||||
attribs.push_back(attrs.fds[i]);
|
||||
attribs.push_back(attrNames[i].offset);
|
||||
attribs.push_back(attrs.offsets[i]);
|
||||
attribs.push_back(attrNames[i].pitch);
|
||||
attribs.push_back(attrs.strides[i]);
|
||||
if (m_bHasModifiers && attrs.modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs.push_back(attrNames[i].modlo);
|
||||
attribs.push_back(attrs.modifier & 0xFFFFFFFF);
|
||||
attribs.push_back(attrNames[i].modhi);
|
||||
attribs.push_back(attrs.modifier >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
attribs.push_back(EGL_IMAGE_PRESERVED_KHR);
|
||||
attribs.push_back(EGL_TRUE);
|
||||
|
||||
attribs.push_back(EGL_NONE);
|
||||
|
||||
EGLImageKHR image = m_sProc.eglCreateImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, (int*)attribs.data());
|
||||
if (image == EGL_NO_IMAGE_KHR) {
|
||||
Debug::log(ERR, "EGL: EGLCreateImageKHR failed: {}", eglGetError());
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::logShaderError(const GLuint& shader, bool program) {
|
||||
GLint maxLength = 0;
|
||||
if (program)
|
||||
|
|
@ -339,12 +522,12 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu
|
|||
|
||||
// ensure a framebuffer for the monitor exists
|
||||
if (m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) {
|
||||
m_RenderData.pCurrentMonData->stencilTex.allocate();
|
||||
m_RenderData.pCurrentMonData->stencilTex->allocate();
|
||||
|
||||
m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
|
|
@ -381,8 +564,8 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, const CRegion& damage_, CFramebu
|
|||
// we can render to the rbo / fbo (fake) directly
|
||||
const auto PFBO = fb ? fb : PRBO->getFB();
|
||||
m_RenderData.currentFB = PFBO;
|
||||
if (PFBO->m_pStencilTex != &m_RenderData.pCurrentMonData->stencilTex) {
|
||||
PFBO->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
if (PFBO->m_pStencilTex != m_RenderData.pCurrentMonData->stencilTex) {
|
||||
PFBO->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
|
||||
PFBO->addStencil();
|
||||
}
|
||||
PFBO->bind();
|
||||
|
|
@ -863,19 +1046,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion
|
|||
scissor((CBox*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, CBox* pBox, float alpha, int round, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureWithDamage(wlr_texture* tex, CBox* pBox, CRegion* damage, float alpha, int round, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTextureWithDamage(CTexture(tex), pBox, damage, alpha, round, false, allowCustomUV);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
||||
void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTextureInternalWithDamage(tex, pBox, alpha, &m_RenderData.damage, round, discardActive, false, allowCustomUV, true);
|
||||
|
|
@ -883,7 +1054,7 @@ void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha
|
|||
scissor((CBox*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureWithDamage(const CTexture& tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
||||
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, CRegion* damage, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true);
|
||||
|
|
@ -891,10 +1062,10 @@ void CHyprOpenGLImpl::renderTextureWithDamage(const CTexture& tex, CBox* pBox, C
|
|||
scissor((CBox*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
|
||||
bool allowDim) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureInternalWithDamage");
|
||||
|
||||
|
|
@ -934,11 +1105,11 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
|
|||
shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA;
|
||||
usingFinalShader = true;
|
||||
} else {
|
||||
switch (tex.m_iType) {
|
||||
switch (tex->m_iType) {
|
||||
case TEXTURE_RGBA: shader = &m_RenderData.pCurrentMonData->m_shRGBA; break;
|
||||
case TEXTURE_RGBX: shader = &m_RenderData.pCurrentMonData->m_shRGBX; break;
|
||||
case TEXTURE_EXTERNAL: shader = &m_RenderData.pCurrentMonData->m_shEXT; break;
|
||||
default: RASSERT(false, "tex.m_iTarget unsupported!");
|
||||
default: RASSERT(false, "tex->m_iTarget unsupported!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -947,14 +1118,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
|
|||
shader = &m_RenderData.pCurrentMonData->m_shRGBX;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(tex.m_iTarget, tex.m_iTexID);
|
||||
glBindTexture(tex->m_iTarget, tex->m_iTexID);
|
||||
|
||||
if (m_RenderData.useNearestNeighbor) {
|
||||
glTexParameteri(tex.m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(tex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(tex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
} else {
|
||||
glTexParameteri(tex.m_iTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(tex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(tex->m_iTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(tex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
glUseProgram(shader->program);
|
||||
|
|
@ -1057,12 +1228,12 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
|
|||
glDisableVertexAttribArray(shader->posAttrib);
|
||||
glDisableVertexAttribArray(shader->texAttrib);
|
||||
|
||||
glBindTexture(tex.m_iTarget, 0);
|
||||
glBindTexture(tex->m_iTarget, 0);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
|
||||
void CHyprOpenGLImpl::renderTexturePrimitive(SP<CTexture> tex, CBox* pBox) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTexturePrimitive");
|
||||
|
||||
|
|
@ -1083,7 +1254,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
|
|||
CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(tex.m_iTarget, tex.m_iTexID);
|
||||
glBindTexture(tex->m_iTarget, tex->m_iTexID);
|
||||
|
||||
glUseProgram(shader->program);
|
||||
|
||||
|
|
@ -1111,12 +1282,12 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
|
|||
glDisableVertexAttribArray(shader->posAttrib);
|
||||
glDisableVertexAttribArray(shader->texAttrib);
|
||||
|
||||
glBindTexture(tex.m_iTarget, 0);
|
||||
glBindTexture(tex->m_iTarget, 0);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte) {
|
||||
void CHyprOpenGLImpl::renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
RASSERT((tex->m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureMatte");
|
||||
|
||||
|
|
@ -1148,10 +1319,10 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame
|
|||
glUniform1i(shader->alphaMatte, 1);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(tex.m_iTarget, tex.m_iTexID);
|
||||
glBindTexture(tex->m_iTarget, tex->m_iTexID);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + 1);
|
||||
glBindTexture(matte.m_cTex.m_iTarget, matte.m_cTex.m_iTexID);
|
||||
glBindTexture(matte.m_cTex->m_iTarget, matte.m_cTex->m_iTexID);
|
||||
|
||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
|
@ -1169,7 +1340,7 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame
|
|||
glDisableVertexAttribArray(shader->posAttrib);
|
||||
glDisableVertexAttribArray(shader->texAttrib);
|
||||
|
||||
glBindTexture(tex.m_iTarget, 0);
|
||||
glBindTexture(tex->m_iTarget, 0);
|
||||
}
|
||||
|
||||
// This probably isn't the fastest
|
||||
|
|
@ -1221,9 +1392,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
|||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glBindTexture(m_RenderData.currentFB->m_cTex.m_iTarget, m_RenderData.currentFB->m_cTex.m_iTexID);
|
||||
glBindTexture(m_RenderData.currentFB->m_cTex->m_iTarget, m_RenderData.currentFB->m_cTex->m_iTexID);
|
||||
|
||||
glTexParameteri(m_RenderData.currentFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(m_RenderData.currentFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program);
|
||||
|
||||
|
|
@ -1265,9 +1436,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
|||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glBindTexture(currentRenderToFB->m_cTex.m_iTarget, currentRenderToFB->m_cTex.m_iTexID);
|
||||
glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID);
|
||||
|
||||
glTexParameteri(currentRenderToFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glUseProgram(pShader->program);
|
||||
|
||||
|
|
@ -1315,7 +1486,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
|||
// draw the things.
|
||||
// first draw is swap -> mirr
|
||||
PMIRRORFB->bind();
|
||||
glBindTexture(PMIRRORSWAPFB->m_cTex.m_iTarget, PMIRRORSWAPFB->m_cTex.m_iTexID);
|
||||
glBindTexture(PMIRRORSWAPFB->m_cTex->m_iTarget, PMIRRORSWAPFB->m_cTex->m_iTexID);
|
||||
|
||||
// damage region will be scaled, make a temp
|
||||
CRegion tempDamage{damage};
|
||||
|
|
@ -1343,9 +1514,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
|||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glBindTexture(currentRenderToFB->m_cTex.m_iTarget, currentRenderToFB->m_cTex.m_iTexID);
|
||||
glBindTexture(currentRenderToFB->m_cTex->m_iTarget, currentRenderToFB->m_cTex->m_iTexID);
|
||||
|
||||
glTexParameteri(currentRenderToFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(currentRenderToFB->m_cTex->m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program);
|
||||
|
||||
|
|
@ -1383,7 +1554,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
|||
}
|
||||
|
||||
// finish
|
||||
glBindTexture(PMIRRORFB->m_cTex.m_iTarget, 0);
|
||||
glBindTexture(PMIRRORFB->m_cTex->m_iTarget, 0);
|
||||
|
||||
blend(BLENDBEFORE);
|
||||
|
||||
|
|
@ -1417,23 +1588,23 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) {
|
|||
if (pWindow->m_sAdditionalConfigData.forceNoBlur)
|
||||
return false;
|
||||
|
||||
if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall)
|
||||
if (pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall)
|
||||
return true;
|
||||
|
||||
const auto PSURFACE = pWindow->m_pWLSurface.wlr();
|
||||
const auto PSURFACE = pWindow->m_pWLSurface->resource();
|
||||
|
||||
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
||||
const float A = pWindow->m_fAlpha.value() * pWindow->m_fActiveInactiveAlpha.value() * PWORKSPACE->m_fAlpha.value();
|
||||
|
||||
if (A >= 1.f) {
|
||||
if (PSURFACE->opaque)
|
||||
return false;
|
||||
// if (PSURFACE->opaque)
|
||||
// return false;
|
||||
|
||||
CRegion inverseOpaque;
|
||||
|
||||
pixman_box32_t surfbox = {0, 0, PSURFACE->current.width, PSURFACE->current.height};
|
||||
CRegion opaqueRegion{&PSURFACE->current.opaque};
|
||||
inverseOpaque.set(opaqueRegion).invert(&surfbox).intersect(0, 0, PSURFACE->current.width, PSURFACE->current.height);
|
||||
pixman_box32_t surfbox = {0, 0, PSURFACE->current.size.x, PSURFACE->current.size.y};
|
||||
CRegion opaqueRegion{PSURFACE->current.opaque};
|
||||
inverseOpaque.set(opaqueRegion).invert(&surfbox).intersect(0, 0, PSURFACE->current.size.x, PSURFACE->current.size.y);
|
||||
|
||||
if (inverseOpaque.empty())
|
||||
return false;
|
||||
|
|
@ -1461,8 +1632,8 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) {
|
|||
if (!ls->layerSurface || ls->xray != 1)
|
||||
continue;
|
||||
|
||||
if (ls->layerSurface->surface->opaque && ls->alpha.value() >= 1.f)
|
||||
continue;
|
||||
// if (ls->layerSurface->surface->opaque && ls->alpha.value() >= 1.f)
|
||||
// continue;
|
||||
|
||||
hasWindows = true;
|
||||
break;
|
||||
|
|
@ -1527,7 +1698,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.m_cTex.m_iTexID)
|
||||
if (!m_RenderData.pCurrentMonData->blurFB.m_cTex->m_iTexID)
|
||||
return false;
|
||||
|
||||
if (pWindow && pWindow->m_sAdditionalConfigData.xray.toUnderlying() == 0)
|
||||
|
|
@ -1545,7 +1716,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin
|
|||
return false;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) {
|
||||
void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float a, SP<CWLSurfaceResource> pSurface, int round, bool blockBlurOptimization, float blurA) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
|
||||
|
||||
static auto PBLURENABLED = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
|
||||
|
|
@ -1570,11 +1741,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo
|
|||
|
||||
// amazing hack: the surface has an opaque region!
|
||||
CRegion inverseOpaque;
|
||||
if (a >= 1.f && std::round(pSurface->current.width * m_RenderData.pMonitor->scale) == pBox->w &&
|
||||
std::round(pSurface->current.height * m_RenderData.pMonitor->scale) == pBox->h) {
|
||||
pixman_box32_t surfbox = {0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale};
|
||||
inverseOpaque = &pSurface->current.opaque;
|
||||
inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale);
|
||||
if (a >= 1.f && std::round(pSurface->current.size.x * m_RenderData.pMonitor->scale) == pBox->w &&
|
||||
std::round(pSurface->current.size.y * m_RenderData.pMonitor->scale) == pBox->h) {
|
||||
pixman_box32_t surfbox = {0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale};
|
||||
inverseOpaque = pSurface->current.opaque;
|
||||
inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale);
|
||||
|
||||
if (inverseOpaque.empty()) {
|
||||
renderTexture(tex, pBox, a, round, false, true);
|
||||
|
|
@ -1765,7 +1936,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFr
|
|||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
pFramebuffer->m_pStencilTex = m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
|
|
@ -1903,7 +2074,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLWINDOW pWindow) {
|
|||
|
||||
const auto FBDATA = &m_mWindowFramebuffers.at(ref);
|
||||
|
||||
if (!FBDATA->m_cTex.m_iTexID)
|
||||
if (!FBDATA->m_cTex->m_iTexID)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
|
@ -1942,7 +2113,7 @@ void CHyprOpenGLImpl::renderSnapshot(PHLLS pLayer) {
|
|||
|
||||
const auto FBDATA = &m_mLayerFramebuffers.at(pLayer);
|
||||
|
||||
if (!FBDATA->m_cTex.m_iTexID)
|
||||
if (!FBDATA->m_cTex->m_iTexID)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pLayer->monitorID);
|
||||
|
|
@ -2077,7 +2248,7 @@ void CHyprOpenGLImpl::renderMirrored() {
|
|||
monbox.y = (monitor->vecTransformedSize.y - monbox.h) / 2;
|
||||
|
||||
const auto PFB = &m_mMonitorRenderResources[mirrored].monitorMirrorFB;
|
||||
if (!PFB->isAllocated() || PFB->m_cTex.m_iTexID <= 0)
|
||||
if (!PFB->isAllocated() || PFB->m_cTex->m_iTexID <= 0)
|
||||
return;
|
||||
|
||||
// replace monitor projection to undo the mirrored monitor's projection
|
||||
|
|
@ -2179,12 +2350,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
|||
}
|
||||
|
||||
// create a new one with cairo
|
||||
CTexture tex;
|
||||
SP<CTexture> tex = makeShared<CTexture>();
|
||||
|
||||
const auto CAIROISURFACE = cairo_image_surface_create_from_png(texPath.c_str());
|
||||
const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROISURFACE);
|
||||
const auto CAIROISURFACE = cairo_image_surface_create_from_png(texPath.c_str());
|
||||
const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROISURFACE);
|
||||
|
||||
tex.allocate();
|
||||
tex->allocate();
|
||||
const Vector2D IMAGESIZE = {cairo_image_surface_get_width(CAIROISURFACE), cairo_image_surface_get_height(CAIROISURFACE)};
|
||||
|
||||
// calc the target box
|
||||
|
|
@ -2220,8 +2391,8 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
|||
|
||||
cairo_surface_flush(CAIROSURFACE);
|
||||
|
||||
CBox box = {origin.x, origin.y, IMAGESIZE.x * scale, IMAGESIZE.y * scale};
|
||||
tex.m_vSize = IMAGESIZE * scale;
|
||||
CBox box = {origin.x, origin.y, IMAGESIZE.x * scale, IMAGESIZE.y * scale};
|
||||
tex->m_vSize = IMAGESIZE * scale;
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ?
|
||||
|
|
@ -2235,7 +2406,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
|||
const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE;
|
||||
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.m_iTexID);
|
||||
glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
#ifndef GLES2
|
||||
|
|
@ -2244,7 +2415,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
}
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex.m_vSize.x, tex.m_vSize.y, 0, glFormat, glType, DATA);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA);
|
||||
|
||||
cairo_surface_destroy(CAIROSURFACE);
|
||||
cairo_surface_destroy(CAIROISURFACE);
|
||||
|
|
@ -2293,7 +2464,7 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
|||
RESIT->second.monitorMirrorFB.release();
|
||||
RESIT->second.blurFB.release();
|
||||
RESIT->second.offMainFB.release();
|
||||
RESIT->second.stencilTex.destroyTexture();
|
||||
RESIT->second.stencilTex->destroyTexture();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources.erase(RESIT);
|
||||
}
|
||||
|
||||
|
|
@ -2343,109 +2514,6 @@ void CHyprOpenGLImpl::setRenderModifEnabled(bool enabled) {
|
|||
m_RenderData.renderModif.enabled = enabled;
|
||||
}
|
||||
|
||||
inline const SGLPixelFormat GLES2_FORMATS[] = {
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ARGB8888,
|
||||
.glFormat = GL_BGRA_EXT,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XRGB8888,
|
||||
.glFormat = GL_BGRA_EXT,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR8888,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR8888,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_BGR888,
|
||||
.glFormat = GL_RGB,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
},
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBX4444,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBA4444,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBX5551,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBA5551,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGB565,
|
||||
.glFormat = GL_RGB,
|
||||
.glType = GL_UNSIGNED_SHORT_5_6_5,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR16161616F,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_HALF_FLOAT_OES,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR16161616F,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_HALF_FLOAT_OES,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR16161616,
|
||||
.glInternalFormat = GL_RGBA16_EXT,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR16161616,
|
||||
.glInternalFormat = GL_RGBA16_EXT,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT,
|
||||
.withAlpha = true,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
|
||||
GLint glf = -1, glt = -1, as = 0;
|
||||
/*glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf);
|
||||
|
|
@ -2453,14 +2521,12 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
|
|||
glGetIntegerv(GL_ALPHA_BITS, &as);*/
|
||||
|
||||
if (glf == 0 || glt == 0) {
|
||||
glf = drmFormatToGL(pMonitor->drmFormat);
|
||||
glt = glFormatToType(glf);
|
||||
glf = FormatUtils::drmFormatToGL(pMonitor->drmFormat);
|
||||
glt = FormatUtils::glFormatToType(glf);
|
||||
}
|
||||
|
||||
for (auto& fmt : GLES2_FORMATS) {
|
||||
if (fmt.glFormat == glf && fmt.glType == glt && fmt.withAlpha == (as > 0))
|
||||
return fmt.drmFormat;
|
||||
}
|
||||
if (const auto FMT = FormatUtils::getPixelFormatFromGL(glf, glt, as > 0); FMT)
|
||||
return FMT->drmFormat;
|
||||
|
||||
if (m_sExts.EXT_read_format_bgra)
|
||||
return DRM_FORMAT_XRGB8888;
|
||||
|
|
@ -2468,13 +2534,8 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
|
|||
return DRM_FORMAT_XBGR8888;
|
||||
}
|
||||
|
||||
const SGLPixelFormat* CHyprOpenGLImpl::getPixelFormatFromDRM(uint32_t drmFormat) {
|
||||
for (auto& fmt : GLES2_FORMATS) {
|
||||
if (fmt.drmFormat == drmFormat)
|
||||
return &fmt;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
std::vector<SDRMFormat> CHyprOpenGLImpl::getDRMFormats() {
|
||||
return drmFormats;
|
||||
}
|
||||
|
||||
void SRenderModifData::applyToBox(CBox& box) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "../helpers/Color.hpp"
|
||||
#include "../helpers/Timer.hpp"
|
||||
#include "../helpers/Region.hpp"
|
||||
#include "../helpers/Format.hpp"
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
|
|
@ -54,14 +55,6 @@ struct SRenderModifData {
|
|||
bool enabled = true;
|
||||
};
|
||||
|
||||
struct SGLPixelFormat {
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
GLint glInternalFormat = 0;
|
||||
GLint glFormat = 0;
|
||||
GLint glType = 0;
|
||||
bool withAlpha = false;
|
||||
};
|
||||
|
||||
struct SMonitorRenderData {
|
||||
CFramebuffer offloadFB;
|
||||
CFramebuffer mirrorFB; // these are used for some effects,
|
||||
|
|
@ -70,7 +63,7 @@ struct SMonitorRenderData {
|
|||
|
||||
CFramebuffer monitorMirrorFB; // used for mirroring outputs, does not contain artifacts like offloadFB
|
||||
|
||||
CTexture stencilTex;
|
||||
SP<CTexture> stencilTex = makeShared<CTexture>();
|
||||
|
||||
CFramebuffer blurFB;
|
||||
bool blurFBDirty = true;
|
||||
|
|
@ -132,74 +125,73 @@ class CHyprOpenGLImpl {
|
|||
public:
|
||||
CHyprOpenGLImpl();
|
||||
|
||||
void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional<CRegion> finalDamage = {});
|
||||
void beginSimple(CMonitor*, const CRegion& damage, CRenderbuffer* rb = nullptr, CFramebuffer* fb = nullptr);
|
||||
void end();
|
||||
void begin(CMonitor*, const CRegion& damage, CFramebuffer* fb = nullptr, std::optional<CRegion> finalDamage = {});
|
||||
void beginSimple(CMonitor*, const CRegion& damage, CRenderbuffer* rb = nullptr, CFramebuffer* fb = nullptr);
|
||||
void end();
|
||||
|
||||
void renderRect(CBox*, const CColor&, int round = 0);
|
||||
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
|
||||
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
|
||||
void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false);
|
||||
void renderTextureWithDamage(wlr_texture*, CBox*, CRegion* damage, float a, int round = 0, bool allowCustomUV = false);
|
||||
void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithDamage(const CTexture&, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
|
||||
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
|
||||
void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte);
|
||||
void renderRect(CBox*, const CColor&, int round = 0);
|
||||
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false);
|
||||
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
|
||||
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithDamage(SP<CTexture>, CBox*, CRegion* damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
|
||||
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
|
||||
void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte);
|
||||
|
||||
void setMonitorTransformEnabled(bool enabled);
|
||||
void setRenderModifEnabled(bool enabled);
|
||||
void setMonitorTransformEnabled(bool enabled);
|
||||
void setRenderModifEnabled(bool enabled);
|
||||
|
||||
void saveMatrix();
|
||||
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
|
||||
void restoreMatrix();
|
||||
void saveMatrix();
|
||||
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
|
||||
void restoreMatrix();
|
||||
|
||||
void blend(bool enabled);
|
||||
void blend(bool enabled);
|
||||
|
||||
void makeWindowSnapshot(PHLWINDOW);
|
||||
void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*);
|
||||
void makeLayerSnapshot(PHLLS);
|
||||
void renderSnapshot(PHLWINDOW);
|
||||
void renderSnapshot(PHLLS);
|
||||
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
|
||||
void makeWindowSnapshot(PHLWINDOW);
|
||||
void makeRawWindowSnapshot(PHLWINDOW, CFramebuffer*);
|
||||
void makeLayerSnapshot(PHLLS);
|
||||
void renderSnapshot(PHLWINDOW);
|
||||
void renderSnapshot(PHLLS);
|
||||
bool shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWindow);
|
||||
|
||||
void clear(const CColor&);
|
||||
void clearWithTex();
|
||||
void scissor(const CBox*, bool transform = true);
|
||||
void scissor(const pixman_box32*, bool transform = true);
|
||||
void scissor(const int x, const int y, const int w, const int h, bool transform = true);
|
||||
void clear(const CColor&);
|
||||
void clearWithTex();
|
||||
void scissor(const CBox*, bool transform = true);
|
||||
void scissor(const pixman_box32*, bool transform = true);
|
||||
void scissor(const int x, const int y, const int w, const int h, bool transform = true);
|
||||
|
||||
void destroyMonitorResources(CMonitor*);
|
||||
void destroyMonitorResources(CMonitor*);
|
||||
|
||||
void markBlurDirtyForMonitor(CMonitor*);
|
||||
void markBlurDirtyForMonitor(CMonitor*);
|
||||
|
||||
void preWindowPass();
|
||||
bool preBlurQueued();
|
||||
void preRender(CMonitor*);
|
||||
void preWindowPass();
|
||||
bool preBlurQueued();
|
||||
void preRender(CMonitor*);
|
||||
|
||||
void saveBufferForMirror(CBox*);
|
||||
void renderMirrored();
|
||||
void saveBufferForMirror(CBox*);
|
||||
void renderMirrored();
|
||||
|
||||
void applyScreenShader(const std::string& path);
|
||||
void applyScreenShader(const std::string& path);
|
||||
|
||||
void bindOffMain();
|
||||
void renderOffToMain(CFramebuffer* off);
|
||||
void bindBackOnMain();
|
||||
void bindOffMain();
|
||||
void renderOffToMain(CFramebuffer* off);
|
||||
void bindBackOnMain();
|
||||
|
||||
void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
|
||||
void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
|
||||
|
||||
uint32_t getPreferredReadFormat(CMonitor* pMonitor);
|
||||
const SGLPixelFormat* getPixelFormatFromDRM(uint32_t drmFormat);
|
||||
uint32_t getPreferredReadFormat(CMonitor* pMonitor);
|
||||
std::vector<SDRMFormat> getDRMFormats();
|
||||
EGLImageKHR createEGLImage(const SDMABUFAttrs& attrs);
|
||||
|
||||
SCurrentRenderData m_RenderData;
|
||||
SCurrentRenderData m_RenderData;
|
||||
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
|
||||
bool m_bReloadScreenShader = true; // at launch it can be set
|
||||
bool m_bReloadScreenShader = true; // at launch it can be set
|
||||
|
||||
PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window
|
||||
PHLLS m_pCurrentLayer; // hack to get the current rendered layer
|
||||
PHLWINDOWREF m_pCurrentWindow; // hack to get the current rendered window
|
||||
PHLLS m_pCurrentLayer; // hack to get the current rendered layer
|
||||
|
||||
std::map<PHLWINDOWREF, CFramebuffer> m_mWindowFramebuffers;
|
||||
std::map<PHLLSREF, CFramebuffer> m_mLayerFramebuffers;
|
||||
|
|
@ -208,41 +200,52 @@ class CHyprOpenGLImpl {
|
|||
|
||||
struct {
|
||||
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
|
||||
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullptr;
|
||||
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = nullptr;
|
||||
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
|
||||
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT = nullptr;
|
||||
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
||||
} m_sProc;
|
||||
|
||||
struct {
|
||||
bool EXT_read_format_bgra = false;
|
||||
bool EXT_read_format_bgra = false;
|
||||
bool EXT_image_dma_buf_import = false;
|
||||
bool EXT_image_dma_buf_import_modifiers = false;
|
||||
} m_sExts;
|
||||
|
||||
private:
|
||||
std::list<GLuint> m_lBuffers;
|
||||
std::list<GLuint> m_lTextures;
|
||||
std::list<GLuint> m_lBuffers;
|
||||
std::list<GLuint> m_lTextures;
|
||||
|
||||
int m_iDRMFD;
|
||||
std::string m_szExtensions;
|
||||
std::vector<SDRMFormat> drmFormats;
|
||||
bool m_bHasModifiers = false;
|
||||
|
||||
bool m_bFakeFrame = false;
|
||||
bool m_bEndFrame = false;
|
||||
bool m_bApplyFinalShader = false;
|
||||
bool m_bBlend = false;
|
||||
bool m_bOffloadedFramebuffer = false;
|
||||
int m_iDRMFD;
|
||||
std::string m_szExtensions;
|
||||
|
||||
CShader m_sFinalScreenShader;
|
||||
CTimer m_tGlobalTimer;
|
||||
bool m_bFakeFrame = false;
|
||||
bool m_bEndFrame = false;
|
||||
bool m_bApplyFinalShader = false;
|
||||
bool m_bBlend = false;
|
||||
bool m_bOffloadedFramebuffer = false;
|
||||
|
||||
void logShaderError(const GLuint&, bool program = false);
|
||||
GLuint createProgram(const std::string&, const std::string&, bool dynamic = false);
|
||||
GLuint compileShader(const GLuint&, std::string, bool dynamic = false);
|
||||
void createBGTextureForMonitor(CMonitor*);
|
||||
void initShaders();
|
||||
CShader m_sFinalScreenShader;
|
||||
CTimer m_tGlobalTimer;
|
||||
|
||||
void logShaderError(const GLuint&, bool program = false);
|
||||
GLuint createProgram(const std::string&, const std::string&, bool dynamic = false);
|
||||
GLuint compileShader(const GLuint&, std::string, bool dynamic = false);
|
||||
void createBGTextureForMonitor(CMonitor*);
|
||||
void initShaders();
|
||||
void initDRMFormats();
|
||||
std::vector<uint64_t> getModsForFormat(EGLint format);
|
||||
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||
|
||||
void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
||||
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
||||
bool allowCustomUV = false, bool allowDim = false);
|
||||
void renderTexturePrimitive(const CTexture& tex, CBox* pBox);
|
||||
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
|
||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);
|
||||
|
||||
void preBlurForCurrentMonitor();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "Renderbuffer.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../protocols/types/Buffer.hpp"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
|
@ -61,6 +62,29 @@ CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer
|
|||
&buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer");
|
||||
}
|
||||
|
||||
CRenderbuffer::CRenderbuffer(SP<IWLBuffer> buffer, uint32_t format) : m_pHLBuffer(buffer), m_uDrmFormat(format) {
|
||||
auto dma = buffer->dmabuf();
|
||||
|
||||
m_iImage = g_pHyprOpenGL->createEGLImage(dma);
|
||||
if (m_iImage == EGL_NO_IMAGE_KHR)
|
||||
throw std::runtime_error("createEGLImage failed");
|
||||
|
||||
glGenRenderbuffers(1, &m_iRBO);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
|
||||
g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glGenFramebuffers(1, &m_sFramebuffer.m_iFb);
|
||||
m_sFramebuffer.m_vSize = buffer->size;
|
||||
m_sFramebuffer.bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
throw std::runtime_error("rbo: glCheckFramebufferStatus failed");
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void CRenderbuffer::bind() {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
|
||||
bindFB();
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
#include "Framebuffer.hpp"
|
||||
|
||||
class CMonitor;
|
||||
class IWLBuffer;
|
||||
|
||||
class CRenderbuffer {
|
||||
public:
|
||||
CRenderbuffer(wlr_buffer* buffer, uint32_t format);
|
||||
CRenderbuffer(SP<IWLBuffer> buffer, uint32_t format);
|
||||
~CRenderbuffer();
|
||||
|
||||
void bind();
|
||||
|
|
@ -16,6 +18,7 @@ class CRenderbuffer {
|
|||
uint32_t getFormat();
|
||||
|
||||
wlr_buffer* m_pWlrBuffer = nullptr;
|
||||
WP<IWLBuffer> m_pHLBuffer = {};
|
||||
|
||||
DYNLISTENER(destroyBuffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "Renderer.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||
#include "../helpers/Region.hpp"
|
||||
#include <algorithm>
|
||||
#include "../config/ConfigValue.hpp"
|
||||
|
|
@ -13,6 +12,7 @@
|
|||
#include "../protocols/XDGShell.hpp"
|
||||
#include "../protocols/PresentationTime.hpp"
|
||||
#include "../protocols/core/DataDevice.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <xf86drm.h>
|
||||
|
|
@ -90,19 +90,24 @@ CHyprRenderer::CHyprRenderer() {
|
|||
wl_event_source_timer_update(m_pCursorTicker, 500);
|
||||
}
|
||||
|
||||
static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
const auto TEXTURE = wlr_surface_get_texture(surface);
|
||||
const auto RDATA = (SRenderData*)data;
|
||||
const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow.lock() == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE;
|
||||
static void renderSurface(SP<CWLSurfaceResource> surface, int x, int y, void* data) {
|
||||
if (!surface->current.buffer || !surface->current.buffer->texture)
|
||||
return;
|
||||
|
||||
if (!TEXTURE)
|
||||
const auto& TEXTURE = surface->current.buffer->texture;
|
||||
const auto RDATA = (SRenderData*)data;
|
||||
const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow.lock() == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE;
|
||||
|
||||
// this is bad, probably has been logged elsewhere. Means the texture failed
|
||||
// uploading to the GPU.
|
||||
if (!TEXTURE->m_iTexID)
|
||||
return;
|
||||
|
||||
TRACY_GPU_ZONE("RenderSurface");
|
||||
|
||||
double outputX = -RDATA->pMonitor->vecPosition.x, outputY = -RDATA->pMonitor->vecPosition.y;
|
||||
|
||||
auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface);
|
||||
auto PSURFACE = CWLSurface::fromResource(surface);
|
||||
|
||||
const float ALPHA = RDATA->alpha * RDATA->fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F);
|
||||
|
||||
|
|
@ -140,7 +145,7 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
|
|||
}
|
||||
|
||||
} else { // here we clamp to 2, these might be some tiny specks
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)};
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max((float)surface->current.size.x, 2.F), std::max((float)surface->current.size.y, 2.F)};
|
||||
if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) {
|
||||
// adjust subsurfaces to the window
|
||||
windowBox.width = (windowBox.width / RDATA->pWindow->m_vReportedSize.x) * RDATA->pWindow->m_vRealSize.value().x;
|
||||
|
|
@ -155,15 +160,23 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
|
|||
windowBox.height = RDATA->h - y;
|
||||
}
|
||||
|
||||
if (windowBox.width <= 1 || windowBox.height <= 1)
|
||||
if (windowBox.width <= 1 || windowBox.height <= 1) {
|
||||
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
|
||||
surface->frame(RDATA->when);
|
||||
auto FEEDBACK = makeShared<CQueuedPresentationData>(surface);
|
||||
FEEDBACK->attachMonitor(RDATA->pMonitor);
|
||||
FEEDBACK->discarded();
|
||||
PROTO::presentation->queueData(FEEDBACK);
|
||||
}
|
||||
return; // invisible
|
||||
}
|
||||
|
||||
windowBox.scale(RDATA->pMonitor->scale);
|
||||
windowBox.round();
|
||||
|
||||
const bool MISALIGNEDFSV1 = std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ &&
|
||||
windowBox.size() != Vector2D{surface->current.buffer_width, surface->current.buffer_height} /* misaligned */ &&
|
||||
DELTALESSTHAN(windowBox.width, surface->current.buffer_width, 3) && DELTALESSTHAN(windowBox.height, surface->current.buffer_height, 3) /* off by one-or-two */ &&
|
||||
windowBox.size() != surface->current.buffer->size /* misaligned */ && DELTALESSTHAN(windowBox.width, surface->current.buffer->size.x, 3) &&
|
||||
DELTALESSTHAN(windowBox.height, surface->current.buffer->size.y, 3) /* off by one-or-two */ &&
|
||||
(!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */;
|
||||
|
||||
g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface, windowBox.size(), MISALIGNEDFSV1);
|
||||
|
|
@ -183,8 +196,8 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
|
|||
if (RDATA->dontRound)
|
||||
rounding = 0;
|
||||
|
||||
const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface.wlr() == surface ? RDATA->pWindow->opaque() : false;
|
||||
const bool CANDISABLEBLEND = ALPHA >= 1.f && rounding == 0 && (WINDOWOPAQUE || surface->opaque);
|
||||
const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface->resource() == surface ? RDATA->pWindow->opaque() : false;
|
||||
const bool CANDISABLEBLEND = ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE;
|
||||
|
||||
if (CANDISABLEBLEND)
|
||||
g_pHyprOpenGL->blend(false);
|
||||
|
|
@ -195,16 +208,16 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data)
|
|||
if (RDATA->blur)
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, RDATA->blockBlurOptimization, RDATA->fadeAlpha);
|
||||
else
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, true);
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding);
|
||||
} else {
|
||||
if (RDATA->blur && RDATA->popup)
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, surface, rounding, true, RDATA->fadeAlpha);
|
||||
else
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding, true);
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA, rounding);
|
||||
}
|
||||
|
||||
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) {
|
||||
wlr_surface_send_frame_done(surface, RDATA->when);
|
||||
surface->frame(RDATA->when);
|
||||
auto FEEDBACK = makeShared<CQueuedPresentationData>(surface);
|
||||
FEEDBACK->attachMonitor(RDATA->pMonitor);
|
||||
FEEDBACK->presented();
|
||||
|
|
@ -506,7 +519,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec
|
|||
if (ignoreAllGeometry)
|
||||
decorate = false;
|
||||
|
||||
renderdata.surface = pWindow->m_pWLSurface.wlr();
|
||||
renderdata.surface = pWindow->m_pWLSurface->resource();
|
||||
renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding);
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.value());
|
||||
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value();
|
||||
|
|
@ -576,7 +589,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec
|
|||
if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying())
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
||||
|
||||
if (!pWindow->m_sAdditionalConfigData.forceNoBlur && pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) {
|
||||
if (!pWindow->m_sAdditionalConfigData.forceNoBlur && pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall && renderdata.blur && *PBLUR) {
|
||||
CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
|
||||
wb.scale(pMonitor->scale).round();
|
||||
g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha,
|
||||
|
|
@ -584,7 +597,8 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec
|
|||
renderdata.blur = false;
|
||||
}
|
||||
|
||||
wlr_surface_for_each_surface(pWindow->m_pWLSurface.wlr(), renderSurface, &renderdata);
|
||||
pWindow->m_pWLSurface->resource()->breadthfirst([](SP<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); },
|
||||
&renderdata);
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||
|
||||
|
|
@ -641,14 +655,15 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, CMonitor* pMonitor, timespec
|
|||
|
||||
pWindow->m_pPopupHead->breadthfirst(
|
||||
[](CPopup* popup, void* data) {
|
||||
if (!popup->m_sWLSurface.wlr())
|
||||
if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource())
|
||||
return;
|
||||
auto pos = popup->coordsRelativeToParent();
|
||||
auto rd = (SRenderData*)data;
|
||||
Vector2D oldPos = {rd->x, rd->y};
|
||||
rd->x += pos.x;
|
||||
rd->y += pos.y;
|
||||
wlr_surface_for_each_surface(popup->m_sWLSurface.wlr(), renderSurface, rd);
|
||||
popup->m_pWLSurface->resource()->breadthfirst([](SP<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); },
|
||||
data);
|
||||
rd->x = oldPos.x;
|
||||
rd->y = oldPos.y;
|
||||
},
|
||||
|
|
@ -698,7 +713,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time
|
|||
SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y};
|
||||
renderdata.fadeAlpha = pLayer->alpha.value();
|
||||
renderdata.blur = pLayer->forceBlur;
|
||||
renderdata.surface = pLayer->layerSurface->surface;
|
||||
renderdata.surface = pLayer->surface->resource();
|
||||
renderdata.decorate = false;
|
||||
renderdata.w = REALSIZ.x;
|
||||
renderdata.h = REALSIZ.y;
|
||||
|
|
@ -717,7 +732,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time
|
|||
}
|
||||
|
||||
if (!popups)
|
||||
wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata);
|
||||
pLayer->surface->resource()->breadthfirst([](SP<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata);
|
||||
|
||||
renderdata.squishOversized = false; // don't squish popups
|
||||
renderdata.dontRound = true;
|
||||
|
|
@ -726,11 +741,11 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, CMonitor* pMonitor, timespec* time
|
|||
if (popups) {
|
||||
pLayer->popupHead->breadthfirst(
|
||||
[](CPopup* popup, void* data) {
|
||||
if (!popup->m_sWLSurface.wlr())
|
||||
if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource())
|
||||
return;
|
||||
|
||||
Vector2D pos = popup->coordsRelativeToParent();
|
||||
renderSurface(popup->m_sWLSurface.wlr(), pos.x, pos.y, data);
|
||||
renderSurface(popup->m_pWLSurface->resource(), pos.x, pos.y, data);
|
||||
},
|
||||
&renderdata);
|
||||
}
|
||||
|
|
@ -746,15 +761,15 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, CMonitor* pMonitor, time
|
|||
|
||||
SRenderData renderdata = {pMonitor, time, POS.x, POS.y};
|
||||
|
||||
const auto SURF = pPopup->getWlrSurface();
|
||||
const auto SURF = pPopup->getSurface();
|
||||
|
||||
renderdata.blur = false;
|
||||
renderdata.surface = SURF;
|
||||
renderdata.decorate = false;
|
||||
renderdata.w = SURF->current.width;
|
||||
renderdata.h = SURF->current.height;
|
||||
renderdata.w = SURF->current.size.x;
|
||||
renderdata.h = SURF->current.size.y;
|
||||
|
||||
wlr_surface_for_each_surface(SURF, renderSurface, &renderdata);
|
||||
SURF->breadthfirst([](SP<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata);
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMonitor* pMonitor, timespec* time) {
|
||||
|
|
@ -766,7 +781,7 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon
|
|||
renderdata.w = pMonitor->vecSize.x;
|
||||
renderdata.h = pMonitor->vecSize.y;
|
||||
|
||||
wlr_surface_for_each_surface(pSurface->surface->surface(), renderSurface, &renderdata);
|
||||
renderdata.surface->breadthfirst([](SP<CWLSurfaceResource> s, const Vector2D& offset, void* data) { renderSurface(s, offset.x, offset.y, data); }, &renderdata);
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) {
|
||||
|
|
@ -966,17 +981,15 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB
|
|||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) {
|
||||
void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) {
|
||||
if (!pWindow || !pWindow->m_bIsX11) {
|
||||
Vector2D uvTL;
|
||||
Vector2D uvBR = Vector2D(1, 1);
|
||||
|
||||
if (pSurface->current.viewport.has_src) {
|
||||
if (pSurface->current.viewport.hasSource) {
|
||||
// we stretch it to dest. if no dest, to 1,1
|
||||
wlr_fbox bufferSource;
|
||||
wlr_surface_get_buffer_source_box(pSurface, &bufferSource);
|
||||
|
||||
Vector2D bufferSize = Vector2D(pSurface->buffer->texture->width, pSurface->buffer->texture->height);
|
||||
Vector2D bufferSize = pSurface->current.buffer->size;
|
||||
auto bufferSource = pSurface->current.viewport.source;
|
||||
|
||||
// calculate UV for the basic src_box. Assume dest == size. Scale to dest later
|
||||
uvTL = Vector2D(bufferSource.x / bufferSize.x, bufferSource.y / bufferSize.y);
|
||||
|
|
@ -991,8 +1004,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa
|
|||
if (projSize != Vector2D{} && fixMisalignedFSV1) {
|
||||
// instead of nearest_neighbor (we will repeat / skip)
|
||||
// just cut off / expand surface
|
||||
const Vector2D PIXELASUV = Vector2D{1, 1} / Vector2D{pSurface->buffer->texture->width, pSurface->buffer->texture->height};
|
||||
const Vector2D MISALIGNMENT = Vector2D{pSurface->buffer->texture->width, pSurface->buffer->texture->height} - projSize;
|
||||
const Vector2D PIXELASUV = Vector2D{1, 1} / pSurface->current.buffer->size;
|
||||
const Vector2D MISALIGNMENT = pSurface->current.buffer->size - projSize;
|
||||
if (MISALIGNMENT != Vector2D{})
|
||||
uvBR -= MISALIGNMENT * PIXELASUV;
|
||||
}
|
||||
|
|
@ -1013,10 +1026,10 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa
|
|||
|
||||
// ignore X and Y, adjust uv
|
||||
if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.value().x || geom.height > pWindow->m_vRealSize.value().y) {
|
||||
const auto XPERC = (double)geom.x / (double)pSurface->current.width;
|
||||
const auto YPERC = (double)geom.y / (double)pSurface->current.height;
|
||||
const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.width;
|
||||
const auto HPERC = (double)(geom.y + geom.height) / (double)pSurface->current.height;
|
||||
const auto XPERC = (double)geom.x / (double)pSurface->current.size.x;
|
||||
const auto YPERC = (double)geom.y / (double)pSurface->current.size.y;
|
||||
const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.size.x;
|
||||
const auto HPERC = (double)(geom.y + geom.height) / (double)pSurface->current.size.y;
|
||||
|
||||
const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y));
|
||||
uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y));
|
||||
|
|
@ -1025,8 +1038,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa
|
|||
// TODO: make this passed to the func. Might break in the future.
|
||||
auto maxSize = pWindow->m_vRealSize.value();
|
||||
|
||||
if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall)
|
||||
maxSize = pWindow->m_pWLSurface.getViewporterCorrectedSize();
|
||||
if (pWindow->m_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall)
|
||||
maxSize = pWindow->m_pWLSurface->getViewporterCorrectedSize();
|
||||
|
||||
if (geom.width > maxSize.x)
|
||||
uvBR.x = uvBR.x * (maxSize.x / geom.width);
|
||||
|
|
@ -1048,53 +1061,51 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, wlr_surface* pSurfa
|
|||
}
|
||||
}
|
||||
|
||||
void countSubsurfacesIter(wlr_surface* pSurface, int x, int y, void* data) {
|
||||
*(int*)data += 1;
|
||||
}
|
||||
|
||||
bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
|
||||
if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked)
|
||||
return false; // do not DS if this monitor is being mirrored. Will break the functionality.
|
||||
return false; // FIXME: fix when we move to new lib for backend.
|
||||
|
||||
if (!wlr_output_is_direct_scanout_allowed(pMonitor->output))
|
||||
return false;
|
||||
// if (!pMonitor->mirrors.empty() || pMonitor->isMirror() || m_bDirectScanoutBlocked)
|
||||
// return false; // do not DS if this monitor is being mirrored. Will break the functionality.
|
||||
|
||||
const auto PCANDIDATE = pMonitor->solitaryClient.lock();
|
||||
// if (!wlr_output_is_direct_scanout_allowed(pMonitor->output))
|
||||
// return false;
|
||||
|
||||
if (!PCANDIDATE)
|
||||
return false;
|
||||
// const auto PCANDIDATE = pMonitor->solitaryClient.lock();
|
||||
|
||||
const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);
|
||||
// if (!PCANDIDATE)
|
||||
// return false;
|
||||
|
||||
if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform)
|
||||
return false;
|
||||
// const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE);
|
||||
|
||||
// finally, we should be GTG.
|
||||
wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base);
|
||||
// if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform)
|
||||
// return false;
|
||||
|
||||
if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr()))
|
||||
return false;
|
||||
// // finally, we should be GTG.
|
||||
// wlr_output_state_set_buffer(pMonitor->state.wlr(), &PSURFACE->buffer->base);
|
||||
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
wlr_surface_send_frame_done(PSURFACE, &now);
|
||||
auto FEEDBACK = makeShared<CQueuedPresentationData>(PSURFACE);
|
||||
FEEDBACK->attachMonitor(pMonitor);
|
||||
FEEDBACK->presented();
|
||||
FEEDBACK->setPresentationType(true);
|
||||
PROTO::presentation->queueData(FEEDBACK);
|
||||
// if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr()))
|
||||
// return false;
|
||||
|
||||
if (pMonitor->state.commit()) {
|
||||
if (m_pLastScanout.expired()) {
|
||||
m_pLastScanout = PCANDIDATE;
|
||||
Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle);
|
||||
}
|
||||
} else {
|
||||
m_pLastScanout.reset();
|
||||
return false;
|
||||
}
|
||||
// timespec now;
|
||||
// clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
// PSURFACE->frame(&now);
|
||||
// auto FEEDBACK = makeShared<CQueuedPresentationData>(PSURFACE);
|
||||
// FEEDBACK->attachMonitor(pMonitor);
|
||||
// FEEDBACK->presented();
|
||||
// FEEDBACK->setPresentationType(true);
|
||||
// PROTO::presentation->queueData(FEEDBACK);
|
||||
|
||||
return true;
|
||||
// if (pMonitor->state.commit()) {
|
||||
// if (m_pLastScanout.expired()) {
|
||||
// m_pLastScanout = PCANDIDATE;
|
||||
// Debug::log(LOG, "Entered a direct scanout to {:x}: \"{}\"", (uintptr_t)PCANDIDATE.get(), PCANDIDATE->m_szTitle);
|
||||
// }
|
||||
// } else {
|
||||
// m_pLastScanout.reset();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// return true;
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
|
|
@ -1430,53 +1441,52 @@ void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace,
|
|||
|
||||
void CHyprRenderer::sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now) {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface.wlr())
|
||||
if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface->resource())
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w, pMonitor))
|
||||
continue;
|
||||
|
||||
wlr_surface_for_each_surface(
|
||||
w->m_pWLSurface.wlr(), [](wlr_surface* s, int x, int y, void* data) { wlr_surface_send_frame_done(s, (timespec*)data); }, now);
|
||||
w->m_pWLSurface->resource()->breadthfirst([now](SP<CWLSurfaceResource> r, const Vector2D& offset, void* d) { r->frame(now); }, nullptr);
|
||||
}
|
||||
|
||||
for (auto& lsl : pMonitor->m_aLayerSurfaceLayers) {
|
||||
for (auto& ls : lsl) {
|
||||
if (ls->fadingOut || !ls->surface.wlr())
|
||||
if (ls->fadingOut || !ls->surface->resource())
|
||||
continue;
|
||||
|
||||
wlr_surface_for_each_surface(
|
||||
ls->surface.wlr(), [](wlr_surface* s, int x, int y, void* data) { wlr_surface_send_frame_done(s, (timespec*)data); }, now);
|
||||
ls->surface->resource()->breadthfirst([now](SP<CWLSurfaceResource> r, const Vector2D& offset, void* d) { r->frame(now); }, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::setWindowScanoutMode(PHLWINDOW pWindow) {
|
||||
if (!g_pCompositor->m_sWLRLinuxDMABuf || g_pSessionLockManager->isSessionLocked())
|
||||
return;
|
||||
// FIXME: fix when moved to new impl
|
||||
// if (!g_pCompositor->m_sWLRLinuxDMABuf || g_pSessionLockManager->isSessionLocked())
|
||||
// return;
|
||||
|
||||
if (!pWindow->m_bIsFullscreen) {
|
||||
wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface.wlr(), nullptr);
|
||||
Debug::log(LOG, "Scanout mode OFF set for {}", pWindow);
|
||||
return;
|
||||
}
|
||||
// if (!pWindow->m_bIsFullscreen) {
|
||||
// wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), nullptr);
|
||||
// Debug::log(LOG, "Scanout mode OFF set for {}", pWindow);
|
||||
// return;
|
||||
// }
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
// const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = {
|
||||
.main_renderer = g_pCompositor->m_sWLRRenderer,
|
||||
.scanout_primary_output = PMONITOR->output,
|
||||
};
|
||||
// const wlr_linux_dmabuf_feedback_v1_init_options INIT_OPTIONS = {
|
||||
// .main_renderer = g_pCompositor->m_sWLRRenderer,
|
||||
// .scanout_primary_output = PMONITOR->output,
|
||||
// };
|
||||
|
||||
wlr_linux_dmabuf_feedback_v1 feedback = {0};
|
||||
// wlr_linux_dmabuf_feedback_v1 feedback = {0};
|
||||
|
||||
if (!wlr_linux_dmabuf_feedback_v1_init_with_options(&feedback, &INIT_OPTIONS))
|
||||
return;
|
||||
// if (!wlr_linux_dmabuf_feedback_v1_init_with_options(&feedback, &INIT_OPTIONS))
|
||||
// return;
|
||||
|
||||
wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface.wlr(), &feedback);
|
||||
wlr_linux_dmabuf_feedback_v1_finish(&feedback);
|
||||
// wlr_linux_dmabuf_v1_set_surface_feedback(g_pCompositor->m_sWLRLinuxDMABuf, pWindow->m_pWLSurface->resource(), &feedback);
|
||||
// wlr_linux_dmabuf_feedback_v1_finish(&feedback);
|
||||
|
||||
Debug::log(LOG, "Scanout mode ON set for {}", pWindow);
|
||||
// Debug::log(LOG, "Scanout mode ON set for {}", pWindow);
|
||||
}
|
||||
|
||||
// taken from Sway.
|
||||
|
|
@ -1662,26 +1672,25 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
|
|||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, double scale) {
|
||||
void CHyprRenderer::damageSurface(SP<CWLSurfaceResource> pSurface, double x, double y, double scale) {
|
||||
if (!pSurface)
|
||||
return; // wut?
|
||||
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
const auto WLSURF = CWLSurface::surfaceFromWlr(pSurface);
|
||||
const auto WLSURF = CWLSurface::fromResource(pSurface);
|
||||
CRegion damageBox = WLSURF ? WLSURF->logicalDamage() : CRegion{};
|
||||
if (!WLSURF) {
|
||||
Debug::log(ERR, "BUG THIS: No CWLSurface for surface in damageSurface!!!");
|
||||
wlr_surface_get_effective_damage(pSurface, damageBox.pixman());
|
||||
return;
|
||||
}
|
||||
|
||||
if (scale != 1.0)
|
||||
damageBox.scale(scale);
|
||||
|
||||
// schedule frame events
|
||||
if (!wl_list_empty(&pSurface->current.frame_callback_list))
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
|
||||
|
||||
if (damageBox.empty())
|
||||
return;
|
||||
|
|
@ -1836,7 +1845,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||
pMonitor->onDisconnect();
|
||||
|
||||
pMonitor->events.modeChanged.emit();
|
||||
pMonitor->updateGlobal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2242,12 +2250,11 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
|||
EMIT_HOOK_EVENT("monitorLayoutChanged", nullptr);
|
||||
|
||||
pMonitor->events.modeChanged.emit();
|
||||
pMonitor->updateGlobal();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHyprRenderer::setCursorSurface(CWLSurface* surf, int hotspotX, int hotspotY, bool force) {
|
||||
void CHyprRenderer::setCursorSurface(SP<CWLSurface> surf, int hotspotX, int hotspotY, bool force) {
|
||||
m_bCursorHasSurface = surf;
|
||||
|
||||
m_sLastCursorData.name = "";
|
||||
|
|
@ -2464,8 +2471,8 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) {
|
|||
continue;
|
||||
|
||||
// TODO: cache maybe?
|
||||
CRegion opaque = &ls->layerSurface->surface->opaque_region;
|
||||
CBox lsbox = {0, 0, ls->layerSurface->surface->current.buffer_width, ls->layerSurface->surface->current.buffer_height};
|
||||
CRegion opaque = ls->layerSurface->surface->current.opaque;
|
||||
CBox lsbox = {{}, ls->layerSurface->surface->current.size};
|
||||
opaque.invert(lsbox);
|
||||
|
||||
if (!opaque.empty())
|
||||
|
|
@ -2544,6 +2551,15 @@ CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32
|
|||
return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
|
||||
}
|
||||
|
||||
CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint32_t fmt) {
|
||||
auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pHLBuffer == buffer; });
|
||||
|
||||
if (it != m_vRenderbuffers.end())
|
||||
return it->get();
|
||||
|
||||
return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
|
||||
}
|
||||
|
||||
void CHyprRenderer::makeEGLCurrent() {
|
||||
if (!g_pCompositor)
|
||||
return;
|
||||
|
|
@ -2556,7 +2572,7 @@ void CHyprRenderer::unsetEGL() {
|
|||
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, wlr_buffer* buffer, CFramebuffer* fb, bool simple) {
|
||||
bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, SP<IWLBuffer> buffer, CFramebuffer* fb, bool simple) {
|
||||
|
||||
makeEGLCurrent();
|
||||
|
||||
|
|
@ -2586,10 +2602,13 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode
|
|||
return false;
|
||||
}
|
||||
} else
|
||||
m_pCurrentWlrBuffer = wlr_buffer_lock(buffer);
|
||||
m_pCurrentHLBuffer = buffer;
|
||||
|
||||
try {
|
||||
m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat);
|
||||
if (m_pCurrentWlrBuffer)
|
||||
m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat);
|
||||
else
|
||||
m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentHLBuffer.lock(), pMonitor->drmFormat);
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "getOrCreateRenderbuffer failed for {}", pMonitor->szName);
|
||||
wlr_buffer_unlock(m_pCurrentWlrBuffer);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ struct SMonitorRule;
|
|||
class CWorkspace;
|
||||
class CWindow;
|
||||
class CInputPopup;
|
||||
class IWLBuffer;
|
||||
|
||||
// TODO: add fuller damage tracking for updating only parts of a window
|
||||
enum DAMAGETRACKINGMODES {
|
||||
|
|
@ -44,7 +45,7 @@ class CHyprRenderer {
|
|||
|
||||
void renderMonitor(CMonitor* pMonitor);
|
||||
void arrangeLayersForMonitor(const int&);
|
||||
void damageSurface(wlr_surface*, double, double, double scale = 1.0);
|
||||
void damageSurface(SP<CWLSurfaceResource>, double, double, double scale = 1.0);
|
||||
void damageWindow(PHLWINDOW, bool forceFull = false);
|
||||
void damageBox(CBox*);
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
|
|
@ -57,14 +58,14 @@ class CHyprRenderer {
|
|||
void ensureCursorRenderingMode();
|
||||
bool shouldRenderCursor();
|
||||
void setCursorHidden(bool hide);
|
||||
void calculateUVForSurface(PHLWINDOW, wlr_surface*, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false);
|
||||
void calculateUVForSurface(PHLWINDOW, SP<CWLSurfaceResource>, bool main = false, const Vector2D& projSize = {}, bool fixMisalignedFSV1 = false);
|
||||
std::tuple<float, float, float> getRenderTimes(CMonitor* pMonitor); // avg max min
|
||||
void renderLockscreen(CMonitor* pMonitor, timespec* now, const CBox& geometry);
|
||||
void setOccludedForBackLayers(CRegion& region, PHLWORKSPACE pWorkspace);
|
||||
void setOccludedForMainWorkspace(CRegion& region, PHLWORKSPACE pWorkspace); // TODO: merge occlusion methods
|
||||
bool canSkipBackBufferClear(CMonitor* pMonitor);
|
||||
void recheckSolitaryForMonitor(CMonitor* pMonitor);
|
||||
void setCursorSurface(CWLSurface* surf, int hotspotX, int hotspotY, bool force = false);
|
||||
void setCursorSurface(SP<CWLSurface> surf, int hotspotX, int hotspotY, bool force = false);
|
||||
void setCursorFromName(const std::string& name, bool force = false);
|
||||
void onRenderbufferDestroy(CRenderbuffer* rb);
|
||||
CRenderbuffer* getCurrentRBO();
|
||||
|
|
@ -74,7 +75,7 @@ class CHyprRenderer {
|
|||
|
||||
// if RENDER_MODE_NORMAL, provided damage will be written to.
|
||||
// otherwise, it will be the one used.
|
||||
bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* buffer = nullptr, CFramebuffer* fb = nullptr, bool simple = false);
|
||||
bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, SP<IWLBuffer> buffer = {}, CFramebuffer* fb = nullptr, bool simple = false);
|
||||
void endRender();
|
||||
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
|
|
@ -98,10 +99,10 @@ class CHyprRenderer {
|
|||
CTimer m_tRenderTimer;
|
||||
|
||||
struct {
|
||||
int hotspotX;
|
||||
int hotspotY;
|
||||
std::optional<CWLSurface*> surf = nullptr;
|
||||
std::string name;
|
||||
int hotspotX;
|
||||
int hotspotY;
|
||||
std::optional<SP<CWLSurface>> surf;
|
||||
std::string name;
|
||||
} m_sLastCursorData;
|
||||
|
||||
private:
|
||||
|
|
@ -121,6 +122,7 @@ class CHyprRenderer {
|
|||
bool m_bCursorHasSurface = false;
|
||||
CRenderbuffer* m_pCurrentRenderbuffer = nullptr;
|
||||
wlr_buffer* m_pCurrentWlrBuffer = nullptr;
|
||||
WP<IWLBuffer> m_pCurrentHLBuffer = {};
|
||||
eRenderMode m_eRenderMode = RENDER_MODE_NORMAL;
|
||||
|
||||
bool m_bNvidia = false;
|
||||
|
|
@ -132,6 +134,7 @@ class CHyprRenderer {
|
|||
} m_sCursorHiddenConditions;
|
||||
|
||||
CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt);
|
||||
CRenderbuffer* getOrCreateRenderbuffer(SP<IWLBuffer> buffer, uint32_t fmt);
|
||||
std::vector<std::unique_ptr<CRenderbuffer>> m_vRenderbuffers;
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,54 @@
|
|||
#include "Texture.hpp"
|
||||
#include "Renderer.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../protocols/types/Buffer.hpp"
|
||||
#include "../helpers/Format.hpp"
|
||||
|
||||
CTexture::CTexture() {
|
||||
// naffin'
|
||||
}
|
||||
|
||||
CTexture::~CTexture() {
|
||||
if (m_bNonOwning)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
destroyTexture();
|
||||
}
|
||||
|
||||
CTexture::CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size_) {
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
ASSERT(format);
|
||||
|
||||
m_iType = format->withAlpha ? TEXTURE_RGBA : TEXTURE_RGBX;
|
||||
m_vSize = size_;
|
||||
allocate();
|
||||
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, m_iTexID));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
#ifndef GLES2
|
||||
if (format->flipRB) {
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
|
||||
}
|
||||
#endif
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
|
||||
GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
}
|
||||
|
||||
CTexture::CTexture(wlr_texture* tex) {
|
||||
RASSERT(wlr_texture_is_gles2(tex), "wlr_texture provided to CTexture that isn't GLES2!");
|
||||
wlr_gles2_texture_attribs attrs;
|
||||
wlr_gles2_texture_get_attribs(tex, &attrs);
|
||||
|
||||
m_iTarget = attrs.target;
|
||||
m_iTexID = attrs.tex;
|
||||
m_iTarget = attrs.target;
|
||||
m_iTexID = attrs.tex;
|
||||
m_bNonOwning = true;
|
||||
|
||||
if (m_iTarget == GL_TEXTURE_2D)
|
||||
m_iType = attrs.has_alpha ? TEXTURE_RGBA : TEXTURE_RGBX;
|
||||
|
|
@ -20,14 +58,72 @@ CTexture::CTexture(wlr_texture* tex) {
|
|||
m_vSize = Vector2D(tex->width, tex->height);
|
||||
}
|
||||
|
||||
CTexture::CTexture(const SDMABUFAttrs& attrs, void* image) {
|
||||
if (!g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES) {
|
||||
Debug::log(ERR, "Cannot create a dmabuf texture: no glEGLImageTargetTexture2DOES");
|
||||
return;
|
||||
}
|
||||
|
||||
m_iTarget = GL_TEXTURE_2D;
|
||||
m_iType = TEXTURE_RGBA;
|
||||
m_vSize = attrs.size;
|
||||
m_iType = FormatUtils::isFormatOpaque(attrs.format) ? TEXTURE_RGBX : TEXTURE_RGBA;
|
||||
allocate();
|
||||
m_pEglImage = image;
|
||||
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, m_iTexID));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
GLCALL(g_pHyprOpenGL->m_sProc.glEGLImageTargetTexture2DOES(m_iTarget, image));
|
||||
GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
}
|
||||
|
||||
void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage) {
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto format = FormatUtils::getPixelFormatFromDRM(drmFormat);
|
||||
ASSERT(format);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_iTexID);
|
||||
|
||||
auto rects = damage.copy().intersect(CBox{{}, m_vSize}).getRects();
|
||||
|
||||
#ifndef GLES2
|
||||
if (format->flipRB) {
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE));
|
||||
GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED));
|
||||
}
|
||||
#endif
|
||||
|
||||
for (auto& rect : rects) {
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock));
|
||||
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));
|
||||
}
|
||||
|
||||
GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0));
|
||||
GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void CTexture::destroyTexture() {
|
||||
if (m_iTexID) {
|
||||
glDeleteTextures(1, &m_iTexID);
|
||||
GLCALL(glDeleteTextures(1, &m_iTexID));
|
||||
m_iTexID = 0;
|
||||
}
|
||||
|
||||
if (m_pEglImage)
|
||||
g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_pEglImage);
|
||||
m_pEglImage = nullptr;
|
||||
}
|
||||
|
||||
void CTexture::allocate() {
|
||||
if (!m_iTexID)
|
||||
glGenTextures(1, &m_iTexID);
|
||||
}
|
||||
GLCALL(glGenTextures(1, &m_iTexID));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include "../defines.hpp"
|
||||
|
||||
class IWLBuffer;
|
||||
struct SDMABUFAttrs;
|
||||
class CRegion;
|
||||
|
||||
enum TEXTURETYPE {
|
||||
TEXTURE_INVALID, // Invalid
|
||||
TEXTURE_RGBA, // 4 channels
|
||||
|
|
@ -12,13 +16,27 @@ enum TEXTURETYPE {
|
|||
class CTexture {
|
||||
public:
|
||||
CTexture();
|
||||
|
||||
CTexture(CTexture&) = delete;
|
||||
CTexture(CTexture&&) = delete;
|
||||
CTexture(const CTexture&&) = delete;
|
||||
CTexture(const CTexture&) = delete;
|
||||
|
||||
CTexture(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const Vector2D& size);
|
||||
CTexture(wlr_texture*);
|
||||
|
||||
// this ctor takes ownership of the eglImage.
|
||||
CTexture(const SDMABUFAttrs&, void* image);
|
||||
~CTexture();
|
||||
|
||||
void destroyTexture();
|
||||
void allocate();
|
||||
void update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, const CRegion& damage);
|
||||
|
||||
TEXTURETYPE m_iType = TEXTURE_RGBA;
|
||||
GLenum m_iTarget = GL_TEXTURE_2D;
|
||||
GLuint m_iTexID = 0;
|
||||
Vector2D m_vSize;
|
||||
void* m_pEglImage = nullptr;
|
||||
bool m_bNonOwning = false; // wlr
|
||||
};
|
||||
|
|
@ -6,23 +6,23 @@
|
|||
#include <pango/pangocairo.h>
|
||||
|
||||
// shared things to conserve VRAM
|
||||
static CTexture m_tGradientActive;
|
||||
static CTexture m_tGradientInactive;
|
||||
static CTexture m_tGradientLockedActive;
|
||||
static CTexture m_tGradientLockedInactive;
|
||||
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>();
|
||||
|
||||
constexpr int BAR_INDICATOR_HEIGHT = 3;
|
||||
constexpr int BAR_PADDING_OUTER_VERT = 2;
|
||||
constexpr int BAR_PADDING_OUTER_HORZ = 2;
|
||||
constexpr int BAR_TEXT_PAD = 2;
|
||||
constexpr int BAR_HORIZONTAL_PADDING = 2;
|
||||
constexpr int BAR_INDICATOR_HEIGHT = 3;
|
||||
constexpr int BAR_PADDING_OUTER_VERT = 2;
|
||||
constexpr int BAR_PADDING_OUTER_HORZ = 2;
|
||||
constexpr int BAR_TEXT_PAD = 2;
|
||||
constexpr int BAR_HORIZONTAL_PADDING = 2;
|
||||
|
||||
CHyprGroupBarDecoration::CHyprGroupBarDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow) {
|
||||
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:enabled");
|
||||
static auto PENABLED = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
|
||||
m_pWindow = pWindow;
|
||||
|
||||
if (m_tGradientActive.m_iTexID == 0 && *PENABLED && *PGRADIENTS)
|
||||
if (m_tGradientActive->m_iTexID == 0 && *PENABLED && *PGRADIENTS)
|
||||
refreshGroupBarGradients();
|
||||
}
|
||||
|
||||
|
|
@ -157,10 +157,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
|
|||
rect.scale(pMonitor->scale);
|
||||
|
||||
if (*PGRADIENTS) {
|
||||
const auto& GRADIENTTEX =
|
||||
(m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
||||
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
||||
if (GRADIENTTEX.m_iTexID != 0)
|
||||
const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
||||
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
||||
if (GRADIENTTEX->m_iTexID != 0)
|
||||
g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0);
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +203,7 @@ void CHyprGroupBarDecoration::invalidateTextures() {
|
|||
}
|
||||
|
||||
CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) {
|
||||
tex = makeShared<CTexture>();
|
||||
szContent = pWindow->m_szTitle;
|
||||
pWindowOwner = pWindow;
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y);
|
||||
|
|
@ -254,8 +254,8 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float
|
|||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
tex.allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, tex.m_iTexID);
|
||||
tex->allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
|
|
@ -272,10 +272,10 @@ CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float
|
|||
}
|
||||
|
||||
CTitleTex::~CTitleTex() {
|
||||
tex.destroyTexture();
|
||||
tex->destroyTexture();
|
||||
}
|
||||
|
||||
void renderGradientTo(CTexture& tex, CGradientValueData* grad) {
|
||||
void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return;
|
||||
|
|
@ -308,8 +308,8 @@ void renderGradientTo(CTexture& tex, CGradientValueData* grad) {
|
|||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
tex.allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, tex.m_iTexID);
|
||||
tex->allocate();
|
||||
glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
|
|
@ -340,11 +340,11 @@ void refreshGroupBarGradients() {
|
|||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
if (m_tGradientActive.m_iTexID != 0) {
|
||||
m_tGradientActive.destroyTexture();
|
||||
m_tGradientInactive.destroyTexture();
|
||||
m_tGradientLockedActive.destroyTexture();
|
||||
m_tGradientLockedInactive.destroyTexture();
|
||||
if (m_tGradientActive->m_iTexID != 0) {
|
||||
m_tGradientActive->destroyTexture();
|
||||
m_tGradientInactive->destroyTexture();
|
||||
m_tGradientLockedActive->destroyTexture();
|
||||
m_tGradientLockedInactive->destroyTexture();
|
||||
}
|
||||
|
||||
if (!*PENABLED || !*PGRADIENTS)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class CTitleTex {
|
|||
CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale);
|
||||
~CTitleTex();
|
||||
|
||||
CTexture tex;
|
||||
SP<CTexture> tex;
|
||||
std::string szContent;
|
||||
PHLWINDOWREF pWindowOwner;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue