summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorvaxerski <43317083+vaxerski@users.noreply.github.com>2022-11-06 17:52:09 +0000
committervaxerski <43317083+vaxerski@users.noreply.github.com>2022-11-06 17:52:09 +0000
commit57817f7252e3acbe48620b6764a77fecb6bb0ec1 (patch)
tree90235b12f926d50c0f3c1250e0aff8641f29614c /src/render
parentb4c45aa2e3af0e595a6276986290c78d11465746 (diff)
Added resize transitions
Diffstat (limited to 'src/render')
-rw-r--r--src/render/Framebuffer.cpp5
-rw-r--r--src/render/Framebuffer.hpp1
-rw-r--r--src/render/OpenGL.cpp96
-rw-r--r--src/render/OpenGL.hpp5
-rw-r--r--src/render/Renderer.cpp27
-rw-r--r--src/render/Renderer.hpp2
6 files changed, 124 insertions, 12 deletions
diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp
index 33bf321b..a1b45fc8 100644
--- a/src/render/Framebuffer.cpp
+++ b/src/render/Framebuffer.cpp
@@ -27,7 +27,6 @@ bool CFramebuffer::alloc(int w, int h) {
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
-
// TODO: Allow this with gles2
#ifndef GLES2
if (m_pStencilTex) {
@@ -80,3 +79,7 @@ void CFramebuffer::release() {
CFramebuffer::~CFramebuffer() {
release();
}
+
+bool CFramebuffer::isAllocated() {
+ return m_iFb != (GLuint)-1;
+} \ No newline at end of file
diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp
index 6af59ca2..2d1e621c 100644
--- a/src/render/Framebuffer.hpp
+++ b/src/render/Framebuffer.hpp
@@ -12,6 +12,7 @@ public:
void bind();
void release();
void reset();
+ bool isAllocated();
Vector2D m_Position;
Vector2D m_Size;
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 7d3ac39e..bcf91258 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -905,6 +905,61 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
+void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFramebuffer) {
+ // we trust the window is valid.
+ const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
+ wlr_output_attach_render(PMONITOR->output, nullptr);
+
+ // we need to "damage" the entire monitor
+ // so that we render the entire window
+ // this is temporary, doesnt mess with the actual wlr damage
+ pixman_region32_t fakeDamage;
+ pixman_region32_init(&fakeDamage);
+ pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
+
+ begin(PMONITOR, &fakeDamage, true);
+
+ clear(CColor(0, 0, 0, 0)); // JIC
+
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+
+ // this is a hack but it works :P
+ // we need to disable blur or else we will get a black background, as the shader
+ // will try to copy the bg to apply blur.
+ // this isn't entirely correct, but like, oh well.
+ // small todo: maybe make this correct? :P
+ const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
+ g_pConfigManager->setInt("decoration:blur", 0);
+
+ // TODO: how can we make this the size of the window? setting it to window's size makes the entire screen render with the wrong res forever more. odd.
+ glViewport(0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
+
+ pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
+
+ pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
+
+ pFramebuffer->bind();
+
+ clear(CColor(0, 0, 0, 0)); // JIC
+
+ g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true);
+
+ g_pConfigManager->setInt("decoration:blur", BLURVAL);
+
+// restore original fb
+#ifndef GLES2
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
+#else
+ glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
+#endif
+ end();
+
+ pixman_region32_fini(&fakeDamage);
+
+ wlr_output_rollback(PMONITOR->output);
+}
+
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
// we trust the window is valid.
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
@@ -919,7 +974,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
begin(PMONITOR, &fakeDamage, true);
- clear(CColor(0,0,0,0)); // JIC
+ clear(CColor(0, 0, 0, 0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -932,10 +987,9 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
g_pConfigManager->setInt("decoration:blur", 0);
- // render onto the window fb
- const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
+ glViewport(0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y);
- glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y);
+ const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
PFRAMEBUFFER->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
@@ -949,12 +1003,12 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
g_pConfigManager->setInt("decoration:blur", BLURVAL);
- // restore original fb
- #ifndef GLES2
+// restore original fb
+#ifndef GLES2
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
- #else
+#else
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
- #endif
+#endif
end();
pixman_region32_fini(&fakeDamage);
@@ -1014,6 +1068,32 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
wlr_output_rollback(PMONITOR->output);
}
+void CHyprOpenGLImpl::onWindowResizeStart(CWindow* pWindow) {
+ static auto *const PTRANSITIONS = &g_pConfigManager->getConfigValuePtr("animations:use_resize_transitions")->intValue;
+ static auto *const PENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
+
+ if (!*PTRANSITIONS || !*PENABLED)
+ return;
+
+ if (pWindow->m_vRealSize.vec().x < 5 || pWindow->m_vRealSize.vec().y < 5)
+ return;
+
+ // make a fb and render a snapshot
+ const auto PFRAMEBUFFER = &m_mWindowResizeFramebuffers[pWindow];
+ makeRawWindowSnapshot(pWindow, PFRAMEBUFFER);
+}
+
+void CHyprOpenGLImpl::onWindowResizeEnd(CWindow* pWindow) {
+ static auto *const PTRANSITIONS = &g_pConfigManager->getConfigValuePtr("animations:use_resize_transitions")->intValue;
+ static auto *const PENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
+
+ if (!*PTRANSITIONS || !*PENABLED)
+ return;
+
+ // remove the fb
+ m_mWindowResizeFramebuffers.erase(pWindow);
+}
+
void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
RASSERT(m_RenderData.pMonitor, "Tried to render snapshot rect without begin()!");
const auto PWINDOW = *pWindow;
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index b62732f6..dbc2977c 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -83,6 +83,7 @@ public:
void renderBorder(wlr_box*, const CColor&, int round);
void makeWindowSnapshot(CWindow*);
+ void makeRawWindowSnapshot(CWindow*, CFramebuffer*);
void makeLayerSnapshot(SLayerSurface*);
void renderSnapshot(CWindow**);
void renderSnapshot(SLayerSurface**);
@@ -103,6 +104,9 @@ public:
void saveBufferForMirror();
void renderMirrored();
+ void onWindowResizeStart(CWindow*);
+ void onWindowResizeEnd(CWindow*);
+
SCurrentRenderData m_RenderData;
GLint m_iCurrentOutputFb = 0;
@@ -113,6 +117,7 @@ public:
pixman_region32_t m_rOriginalDamageRegion; // used for storing the pre-expanded region
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
+ std::unordered_map<CWindow*, CFramebuffer> m_mWindowResizeFramebuffers;
std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;
std::unordered_map<CMonitor*, SMonitorRenderData> m_mMonitorRenderResources;
std::unordered_map<CMonitor*, CTexture> m_mMonitorBGTextures;
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 420b45be..60238144 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -215,7 +215,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
g_pHyprError->draw();
}
-void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode) {
+void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition) {
if (pWindow->isHidden())
return;
@@ -227,9 +227,15 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec());
- static const auto PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
+ static auto *const PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
+ static auto *const PTRANSITIONS = &g_pConfigManager->getConfigValuePtr("animations:use_resize_transitions")->intValue;
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
+ if (ignorePosition) {
+ renderdata.x = 0;
+ renderdata.y = 0;
+ }
+
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
renderdata.w = std::max(pWindow->m_vRealSize.vec().x, 5.0); // clamp the size to min 5,
renderdata.h = std::max(pWindow->m_vRealSize.vec().y, 5.0); // otherwise we'll have issues later with invalid boxes
@@ -288,6 +294,23 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
+ if (*PTRANSITIONS && !ignorePosition /* ignorePosition probably means we are rendering the snapshot rn */) {
+ const auto PFB = g_pHyprOpenGL->m_mWindowResizeFramebuffers.find(pWindow);
+
+ if (PFB != g_pHyprOpenGL->m_mWindowResizeFramebuffers.end() && PFB->second.isAllocated()) {
+ wlr_box box = {renderdata.x, renderdata.y, renderdata.w, renderdata.h};
+
+ // adjust UV (remove when I figure out how to change the size of the fb)
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = {0, 0};
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = { pWindow->m_vRealSize.m_vBegun.x / pMonitor->vecPixelSize.x, pWindow->m_vRealSize.m_vBegun.y / pMonitor->vecPixelSize.y};
+
+ g_pHyprOpenGL->renderTexture(PFB->second.m_cTex, &box, (1.f - pWindow->m_vRealSize.getPercent()) * 84.f, 0, false, true);
+
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
+ g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
+ }
+ }
+
if (renderdata.decorate && pWindow->m_sSpecialRenderData.border) {
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index 74fc0a9a..8bd65418 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -54,7 +54,7 @@ public:
private:
void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*);
void renderWorkspaceWithFullscreenWindow(CMonitor*, CWorkspace*, timespec*);
- void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode);
+ void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false);
void renderLayer(SLayerSurface*, CMonitor*, timespec*);
void renderDragIcon(CMonitor*, timespec*);
void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*);