summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2024-06-08 10:07:59 +0200
committerGitHub <noreply@github.com>2024-06-08 10:07:59 +0200
commit6967a31450441fc5605c05db6f65505dace4b263 (patch)
tree255a3cff7f3e2eb8a50c952eab9b270a7937561d /src/render
parentc31d9ef4172452f6f219f91d9b87a24d91f0cf3a (diff)
wayland/core: move to new impl (#6268)
* wayland/core/dmabuf: move to new impl it's the final countdown
Diffstat (limited to 'src/render')
-rw-r--r--src/render/Framebuffer.cpp27
-rw-r--r--src/render/Framebuffer.hpp21
-rw-r--r--src/render/OpenGL.cpp453
-rw-r--r--src/render/OpenGL.hpp159
-rw-r--r--src/render/Renderbuffer.cpp24
-rw-r--r--src/render/Renderbuffer.hpp3
-rw-r--r--src/render/Renderer.cpp255
-rw-r--r--src/render/Renderer.hpp19
-rw-r--r--src/render/Texture.cpp106
-rw-r--r--src/render/Texture.hpp18
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.cpp50
-rw-r--r--src/render/decorations/CHyprGroupBarDecoration.hpp2
12 files changed, 683 insertions, 454 deletions
diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp
index 83325dd7..67629e23 100644
--- a/src/render/Framebuffer.cpp
+++ b/src/render/Framebuffer.cpp
@@ -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() {
diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp
index 22809158..a46a4859 100644
--- a/src/render/Framebuffer.hpp
+++ b/src/render/Framebuffer.hpp
@@ -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;
}; \ No newline at end of file
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index a1e6f73e..d4e8faa6 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -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) {
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index ca9eecc6..db0f8ea1 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -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;
+
+ std::vector<SDRMFormat> drmFormats;
+ bool m_bHasModifiers = false;
- int m_iDRMFD;
- std::string m_szExtensions;
+ int m_iDRMFD;
+ std::string m_szExtensions;
- bool m_bFakeFrame = false;
- bool m_bEndFrame = false;
- bool m_bApplyFinalShader = false;
- bool m_bBlend = false;
- bool m_bOffloadedFramebuffer = false;
+ bool m_bFakeFrame = false;
+ bool m_bEndFrame = false;
+ bool m_bApplyFinalShader = false;
+ bool m_bBlend = false;
+ bool m_bOffloadedFramebuffer = false;
- CShader m_sFinalScreenShader;
- CTimer m_tGlobalTimer;
+ 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 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();
diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp
index 5003f600..694485c2 100644
--- a/src/render/Renderbuffer.cpp
+++ b/src/render/Renderbuffer.cpp
@@ -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();
diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp
index 2a8bf250..ed7050c5 100644
--- a/src/render/Renderbuffer.hpp
+++ b/src/render/Renderbuffer.hpp
@@ -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);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 40ae953e..2a6cbb3b 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -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;
+
+ 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;
- if (!TEXTURE)
+ // 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 (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;
- }
+ // if (!wlr_output_test_state(pMonitor->output, pMonitor->state.wlr()))
+ // return false;
- return true;
+ // 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);
+
+ // 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);
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index da38fed2..f88bfebf 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -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;
diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp
index 1820d0fb..aef8e4ac 100644
--- a/src/render/Texture.cpp
+++ b/src/render/Texture.cpp
@@ -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);
-} \ No newline at end of file
+ GLCALL(glGenTextures(1, &m_iTexID));
+}
diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp
index 93a6aa5f..fa1ca4fe 100644
--- a/src/render/Texture.hpp
+++ b/src/render/Texture.hpp
@@ -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
}; \ No newline at end of file
diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp
index 04f69aaa..d96f2c3c 100644
--- a/src/render/decorations/CHyprGroupBarDecoration.cpp
+++ b/src/render/decorations/CHyprGroupBarDecoration.cpp
@@ -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)
diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp
index e3f553c5..64870d45 100644
--- a/src/render/decorations/CHyprGroupBarDecoration.hpp
+++ b/src/render/decorations/CHyprGroupBarDecoration.hpp
@@ -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;
};