summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorvaxerski <43317083+vaxerski@users.noreply.github.com>2022-04-05 20:49:15 +0200
committervaxerski <43317083+vaxerski@users.noreply.github.com>2022-04-05 20:49:15 +0200
commita49bbf450881581e27696405ebaefef63f7bde7a (patch)
tree2c5cd3ecc24b9138f5f8f087350fe9e71a6b6e90 /src
parentf8e0b0b448b8b68f65ee1c3eebdd4eb3e3382138 (diff)
fadeout done 🎉
Diffstat (limited to 'src')
-rw-r--r--src/Compositor.cpp2
-rw-r--r--src/defines.hpp2
-rw-r--r--src/events/Windows.cpp3
-rw-r--r--src/layout/DwindleLayout.cpp4
-rw-r--r--src/render/Framebuffer.cpp62
-rw-r--r--src/render/Framebuffer.hpp22
-rw-r--r--src/render/OpenGL.cpp56
-rw-r--r--src/render/OpenGL.hpp9
-rw-r--r--src/render/Renderer.cpp9
-rw-r--r--src/render/Renderer.hpp4
10 files changed, 168 insertions, 5 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 7fdd65bc..601cf114 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -559,6 +559,8 @@ void CCompositor::cleanupWindows() {
if (!w->m_bFadingOut || w->m_fAlpha == 0.f) {
m_lWindows.remove(*w);
m_lWindowsFadingOut.remove(w);
+ g_pHyprOpenGL->m_mWindowFramebuffers[w].release();
+ g_pHyprOpenGL->m_mWindowFramebuffers.erase(w);
Debug::log(LOG, "Cleanup: cleaned up a window");
return;
}
diff --git a/src/defines.hpp b/src/defines.hpp
index 7eb1b56a..4bd886e7 100644
--- a/src/defines.hpp
+++ b/src/defines.hpp
@@ -32,7 +32,7 @@
#ifndef __INTELLISENSE__
#define RASSERT(expr, reason, ...) \
- if (!expr) { \
+ if (!(expr)) { \
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \
RIP("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
}
diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp
index 3a00041d..4ce53697 100644
--- a/src/events/Windows.cpp
+++ b/src/events/Windows.cpp
@@ -171,6 +171,9 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pCompositor->m_pLastFocus = nullptr;
}
+ // Allow the renderer to catch the last frame.
+ g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
+
PWINDOW->m_bMappedX11 = false;
// remove the fullscreen window status from workspace if we closed it
diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp
index 23b76073..86bca5de 100644
--- a/src/layout/DwindleLayout.cpp
+++ b/src/layout/DwindleLayout.cpp
@@ -261,8 +261,8 @@ void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) {
m_lDwindleNodesData.remove(*PNODE);
// jump back like it jumps in
- pWindow->m_vEffectivePosition = pWindow->m_vEffectivePosition + ((pWindow->m_vEffectiveSize - Vector2D(5, 5)) * 0.5f);
- pWindow->m_vEffectiveSize = Vector2D(5, 5);
+ //pWindow->m_vEffectivePosition = pWindow->m_vEffectivePosition + ((pWindow->m_vEffectiveSize - Vector2D(5, 5)) * 0.5f);
+ // pWindow->m_vEffectiveSize = Vector2D(5, 5);
}
void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp
new file mode 100644
index 00000000..8ab03776
--- /dev/null
+++ b/src/render/Framebuffer.cpp
@@ -0,0 +1,62 @@
+#include "Framebuffer.hpp"
+#include "OpenGL.hpp"
+
+bool CFramebuffer::alloc(int w, int h) {
+ bool firstAlloc = false;
+ if (m_iFb == (uint32_t)-1)
+ {
+ firstAlloc = true;
+ glGenFramebuffers(1, &m_iFb);
+ }
+
+ if (m_cTex.m_iTexID == 0)
+ {
+ firstAlloc = true;
+ glGenTextures(1, &m_cTex.m_iTexID);
+ 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);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+
+ if (firstAlloc)
+ {
+ glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
+ glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
+
+ auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Framebuffer incomplete, couldn't create! (FB status: %i)", status);
+
+ Debug::log(LOG, "Framebuffer created, status %i", status);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb);
+
+ m_Size = Vector2D(w, h);
+
+ return true;
+}
+
+void CFramebuffer::bind() {
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iFb);
+ glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y);
+}
+
+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;
+}
diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp
new file mode 100644
index 00000000..5c76b9a6
--- /dev/null
+++ b/src/render/Framebuffer.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "../defines.hpp"
+#include "Texture.hpp"
+
+class CFramebuffer {
+public:
+
+ bool alloc(int w, int h);
+ void bind();
+ void release();
+ void reset();
+
+ Vector2D m_Position;
+ Vector2D m_Size;
+ float m_fScale = 1;
+
+ CTexture m_cTex;
+ GLuint m_iFb = -1;
+
+ wl_output_transform m_tTransform; // for saving state
+}; \ No newline at end of file
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 1e5ec07d..f46302ab 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -106,6 +106,8 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor) {
wlr_matrix_projection(m_RenderData.projection, pMonitor->vecSize.x, pMonitor->vecSize.y, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: this is deprecated
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb);
}
void CHyprOpenGLImpl::end() {
@@ -323,4 +325,58 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, i
glDrawArrays(GL_LINE_STRIP, 0, 41);
glDisableVertexAttribArray(m_shQUAD.posAttrib);
+}
+
+void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
+ // we trust the window is valid.
+ const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
+ wlr_output_attach_render(PMONITOR->output, nullptr);
+
+ begin(PMONITOR);
+
+ const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
+
+ PFRAMEBUFFER->m_tTransform = g_pXWaylandManager->getWindowSurface(pWindow)->current.transform;
+
+ PFRAMEBUFFER->alloc(PMONITOR->vecSize.x, PMONITOR->vecSize.y);
+
+ PFRAMEBUFFER->bind();
+
+ clear(CColor(0,0,0,0)); // JIC
+
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders);
+
+ // restore original fb
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
+ glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y);
+
+ end();
+
+ wlr_output_rollback(PMONITOR->output);
+}
+
+void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
+ const auto PWINDOW = *pWindow;
+
+ auto it = m_mWindowFramebuffers.begin();
+ for (;it != m_mWindowFramebuffers.end(); it++) {
+ if (it->first == PWINDOW) {
+ break;
+ }
+ }
+
+ if (it == m_mWindowFramebuffers.end() || !it->second.m_cTex.m_iTexID)
+ return;
+
+ const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
+
+ const auto TRANSFORM = wlr_output_transform_invert(it->second.m_tTransform);
+ float matrix[9];
+ wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
+ wlr_matrix_project_box(matrix, &windowBox, TRANSFORM, 0, PMONITOR->output->transform_matrix);
+
+ renderTexture(it->second.m_cTex, matrix, PWINDOW->m_fAlpha, 0);
} \ No newline at end of file
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 43fa6c6c..7d938c15 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -5,10 +5,12 @@
#include "../helpers/Color.hpp"
#include <wlr/render/egl.h>
#include <list>
+#include <unordered_map>
#include "Shaders.hpp"
#include "Shader.hpp"
#include "Texture.hpp"
+#include "Framebuffer.hpp"
inline const float matrixFlip180[] = {
1.0f, 0.0f, 0.0f,
@@ -40,11 +42,18 @@ public:
void renderTexture(const CTexture&, float matrix[9], float a, int round = 0);
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
+ void makeWindowSnapshot(CWindow*);
+ void renderSnapshot(CWindow**);
+
void clear(const CColor&);
void scissor(const wlr_box*);
SCurrentRenderData m_RenderData;
+ GLint m_iCurrentOutputFb = 0;
+
+ std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
+
private:
std::list<GLuint> m_lBuffers;
std::list<GLuint> m_lTextures;
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index d34d6897..fa62b5fd 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -82,6 +82,11 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, SWor
}
void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate) {
+ if (pWindow->m_bFadingOut) {
+ g_pHyprOpenGL->renderSnapshot(&pWindow);
+ return;
+ }
+
const auto REALPOS = pWindow->m_vRealPosition;
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
@@ -134,7 +139,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// Non-floating
for (auto& w : g_pCompositor->m_lWindows) {
- if (!g_pCompositor->windowValidMapped(&w))
+ if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue;
if (w.m_bIsFloating)
@@ -149,7 +154,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// floating on top
for (auto& w : g_pCompositor->m_lWindows) {
- if (!g_pCompositor->windowValidMapped(&w))
+ if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue;
if (!w.m_bIsFloating)
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index cd0b5d01..ec1597f8 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -5,6 +5,7 @@
#include "../helpers/Monitor.hpp"
#include "../helpers/Workspace.hpp"
#include "../Window.hpp"
+#include "OpenGL.hpp"
class CHyprRenderer {
public:
@@ -20,6 +21,9 @@ private:
void renderWorkspaceWithFullscreenWindow(SMonitor*, SWorkspace*, timespec*);
void renderWindow(CWindow*, SMonitor*, timespec*, bool);
void renderDragIcon(SMonitor*, timespec*);
+
+
+ friend class CHyprOpenGLImpl;
};
inline std::unique_ptr<CHyprRenderer> g_pHyprRenderer;