2023-11-24 11:54:21 +01:00
|
|
|
#include "Renderbuffer.hpp"
|
|
|
|
#include "OpenGL.hpp"
|
|
|
|
#include "../Compositor.hpp"
|
2024-06-08 10:07:59 +02:00
|
|
|
#include "../protocols/types/Buffer.hpp"
|
2023-11-24 11:54:21 +01:00
|
|
|
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
|
|
|
CRenderbuffer::~CRenderbuffer() {
|
2024-06-28 22:24:32 +02:00
|
|
|
if (!g_pCompositor || g_pCompositor->m_bIsShuttingDown || !g_pHyprRenderer)
|
2023-12-06 15:46:18 +01:00
|
|
|
return;
|
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
g_pHyprRenderer->makeEGLCurrent();
|
2023-11-24 11:54:21 +01:00
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
unbind();
|
2023-11-24 11:54:21 +01:00
|
|
|
m_sFramebuffer.release();
|
|
|
|
glDeleteRenderbuffers(1, &m_iRBO);
|
|
|
|
|
|
|
|
g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_iImage);
|
|
|
|
}
|
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer(buffer), m_uDrmFormat(format) {
|
2023-11-24 11:54:21 +01:00
|
|
|
|
|
|
|
// EVIL, but we can't include a hidden header because nixos is fucking special
|
|
|
|
static EGLImageKHR (*PWLREGLCREATEIMAGEFROMDMABUF)(wlr_egl*, wlr_dmabuf_attributes*, bool*);
|
|
|
|
static bool symbolFound = false;
|
|
|
|
if (!symbolFound) {
|
|
|
|
PWLREGLCREATEIMAGEFROMDMABUF = reinterpret_cast<EGLImageKHR (*)(wlr_egl*, wlr_dmabuf_attributes*, bool*)>(dlsym(RTLD_DEFAULT, "wlr_egl_create_image_from_dmabuf"));
|
|
|
|
|
|
|
|
symbolFound = true;
|
|
|
|
|
|
|
|
RASSERT(PWLREGLCREATEIMAGEFROMDMABUF, "wlr_egl_create_image_from_dmabuf was not found in wlroots!");
|
|
|
|
|
|
|
|
Debug::log(LOG, "CRenderbuffer: wlr_egl_create_image_from_dmabuf found at {:x}", (uintptr_t)PWLREGLCREATEIMAGEFROMDMABUF);
|
|
|
|
}
|
|
|
|
// end evil hack
|
|
|
|
|
|
|
|
struct wlr_dmabuf_attributes dmabuf = {0};
|
|
|
|
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf))
|
|
|
|
throw std::runtime_error("wlr_buffer_get_dmabuf failed");
|
|
|
|
|
|
|
|
bool externalOnly;
|
|
|
|
m_iImage = PWLREGLCREATEIMAGEFROMDMABUF(g_pCompositor->m_sWLREGL, &dmabuf, &externalOnly);
|
|
|
|
if (m_iImage == EGL_NO_IMAGE_KHR)
|
|
|
|
throw std::runtime_error("wlr_egl_create_image_from_dmabuf 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->width, buffer->height};
|
|
|
|
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);
|
|
|
|
|
2024-07-13 12:36:29 +02:00
|
|
|
hyprListener_destroyBuffer.initCallback(&buffer->events.destroy, [this](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy(this); }, this, "CRenderbuffer");
|
2023-11-24 11:54:21 +01:00
|
|
|
}
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-11-24 11:54:21 +01:00
|
|
|
void CRenderbuffer::bind() {
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
|
|
|
|
bindFB();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRenderbuffer::bindFB() {
|
|
|
|
m_sFramebuffer.bind();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CRenderbuffer::unbind() {
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
|
|
#ifndef GLES2
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
#else
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
CFramebuffer* CRenderbuffer::getFB() {
|
|
|
|
return &m_sFramebuffer;
|
|
|
|
}
|