mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-26 20:05:59 +01:00
Major blur rework: optimization & fixes
Blur should be considerably faster now and work on full damage tracking
This commit is contained in:
parent
b5b78f3836
commit
43fc7662cc
4 changed files with 205 additions and 111 deletions
|
@ -30,6 +30,8 @@ void CConfigManager::setDefaultVars() {
|
||||||
configValues["general:col.active_border"].intValue = 0xffffffff;
|
configValues["general:col.active_border"].intValue = 0xffffffff;
|
||||||
configValues["general:col.inactive_border"].intValue = 0xff444444;
|
configValues["general:col.inactive_border"].intValue = 0xff444444;
|
||||||
|
|
||||||
|
configValues["debug:int"].intValue = 0;
|
||||||
|
|
||||||
configValues["decoration:rounding"].intValue = 1;
|
configValues["decoration:rounding"].intValue = 1;
|
||||||
configValues["decoration:blur"].intValue = 1;
|
configValues["decoration:blur"].intValue = 1;
|
||||||
configValues["decoration:blur_size"].intValue = 8;
|
configValues["decoration:blur_size"].intValue = 8;
|
||||||
|
|
|
@ -140,9 +140,11 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage) {
|
||||||
|
|
||||||
m_mMonitorRenderResources[pMonitor].primaryFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
m_mMonitorRenderResources[pMonitor].primaryFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
||||||
m_mMonitorRenderResources[pMonitor].mirrorFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
m_mMonitorRenderResources[pMonitor].mirrorFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
||||||
|
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
||||||
|
|
||||||
m_mMonitorRenderResources[pMonitor].primaryFB.alloc(pMonitor->vecSize.x * pMonitor->scale, pMonitor->vecSize.y * pMonitor->scale);
|
m_mMonitorRenderResources[pMonitor].primaryFB.alloc(pMonitor->vecSize.x * pMonitor->scale, pMonitor->vecSize.y * pMonitor->scale);
|
||||||
m_mMonitorRenderResources[pMonitor].mirrorFB.alloc(pMonitor->vecSize.x * pMonitor->scale, pMonitor->vecSize.y * pMonitor->scale);
|
m_mMonitorRenderResources[pMonitor].mirrorFB.alloc(pMonitor->vecSize.x * pMonitor->scale, pMonitor->vecSize.y * pMonitor->scale);
|
||||||
|
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.alloc(pMonitor->vecSize.x * pMonitor->scale, pMonitor->vecSize.y * pMonitor->scale);
|
||||||
|
|
||||||
createBGTextureForMonitor(pMonitor);
|
createBGTextureForMonitor(pMonitor);
|
||||||
}
|
}
|
||||||
|
@ -212,6 +214,11 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) {
|
||||||
|
wlr_box box = {x,y,w,h};
|
||||||
|
scissor(&box);
|
||||||
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col) {
|
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col) {
|
||||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
||||||
|
@ -344,6 +351,133 @@ void CHyprOpenGLImpl::renderTextureInternal(const CTexture& tex, wlr_box* pBox,
|
||||||
// but it works... well, I guess?
|
// but it works... well, I guess?
|
||||||
//
|
//
|
||||||
// Dual (or more) kawase blur
|
// Dual (or more) kawase blur
|
||||||
|
CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* pBox) {
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
|
||||||
|
// get transforms for the full monitor
|
||||||
|
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
float matrix[9];
|
||||||
|
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
||||||
|
wlr_matrix_project_box(matrix, &MONITORBOX, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||||
|
|
||||||
|
float glMatrix[9];
|
||||||
|
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||||
|
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
|
||||||
|
wlr_matrix_transpose(glMatrix, glMatrix);
|
||||||
|
|
||||||
|
// get the config settings
|
||||||
|
const auto BLURSIZE = g_pConfigManager->getInt("decoration:blur_size");
|
||||||
|
const auto BLURPASSES = g_pConfigManager->getInt("decoration:blur_passes");
|
||||||
|
|
||||||
|
const auto BLURRADIUS = BLURSIZE * BLURPASSES;
|
||||||
|
|
||||||
|
// now, prep the damage, get the extended damage region
|
||||||
|
pixman_region32_t damage;
|
||||||
|
pixman_region32_init(&damage);
|
||||||
|
pixman_region32_intersect_rect(&damage, m_RenderData.pDamage, pBox->x, pBox->y, pBox->width, pBox->height); // clip it to the box
|
||||||
|
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
|
||||||
|
pixman_region32_intersect_rect(&damage, &damage, 0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y); // clip it to the monitor
|
||||||
|
|
||||||
|
// helper
|
||||||
|
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
|
||||||
|
const auto PMIRRORSWAPFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorSwapFB;
|
||||||
|
|
||||||
|
CFramebuffer* currentRenderToFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB;
|
||||||
|
|
||||||
|
Vector2D sample = m_RenderData.pMonitor->vecSize;
|
||||||
|
|
||||||
|
// declare the draw func
|
||||||
|
auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) {
|
||||||
|
if (currentRenderToFB == PMIRRORFB)
|
||||||
|
PMIRRORSWAPFB->bind();
|
||||||
|
else
|
||||||
|
PMIRRORFB->bind();
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
glBindTexture(currentRenderToFB->m_cTex.m_iTarget, currentRenderToFB->m_cTex.m_iTexID);
|
||||||
|
|
||||||
|
glTexParameteri(currentRenderToFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
glUseProgram(pShader->program);
|
||||||
|
|
||||||
|
// prep two shaders
|
||||||
|
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
|
||||||
|
glUniform1f(glGetUniformLocation(pShader->program, "radius"), BLURSIZE * (a / 255.f)); // this makes the blursize change with a
|
||||||
|
if (pShader == &m_shBLUR1)
|
||||||
|
glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (sample.x / 2.f), 0.5f / (sample.y / 2.f));
|
||||||
|
else
|
||||||
|
glUniform2f(glGetUniformLocation(m_shBLUR2.program, "halfpixel"), 0.5f / (sample.x * 2.f), 0.5f / (sample.y * 2.f));
|
||||||
|
glUniform1i(pShader->tex, 0);
|
||||||
|
|
||||||
|
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
glVertexAttribPointer(pShader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(pShader->posAttrib);
|
||||||
|
glEnableVertexAttribArray(pShader->texAttrib);
|
||||||
|
|
||||||
|
if (pixman_region32_not_empty(pDamage)) {
|
||||||
|
PIXMAN_DAMAGE_FOREACH(pDamage) {
|
||||||
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(pShader->posAttrib);
|
||||||
|
glDisableVertexAttribArray(pShader->texAttrib);
|
||||||
|
|
||||||
|
if (currentRenderToFB != PMIRRORFB)
|
||||||
|
currentRenderToFB = PMIRRORFB;
|
||||||
|
else
|
||||||
|
currentRenderToFB = PMIRRORSWAPFB;
|
||||||
|
};
|
||||||
|
|
||||||
|
// draw the things.
|
||||||
|
// first draw is prim -> mirr
|
||||||
|
PMIRRORSWAPFB->bind();
|
||||||
|
clear(CColor(0, 0, 0, 0));
|
||||||
|
PMIRRORFB->bind();
|
||||||
|
clear(CColor(0, 0, 0, 0));
|
||||||
|
glBindTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTarget, m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTexID);
|
||||||
|
|
||||||
|
// damage region will be scaled, make a temp
|
||||||
|
pixman_region32_t tempDamage;
|
||||||
|
pixman_region32_init(&tempDamage);
|
||||||
|
wlr_region_scale(&tempDamage, &damage, 1.f / 2.f); // when DOWNscaling, we make the region twice as small because it's the TARGET
|
||||||
|
|
||||||
|
drawPass(&m_shBLUR1, &tempDamage);
|
||||||
|
|
||||||
|
// and draw
|
||||||
|
for (int i = 1; i < BLURPASSES; ++i) {
|
||||||
|
sample = m_RenderData.pMonitor->vecSize / (1 << i);
|
||||||
|
|
||||||
|
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1)));
|
||||||
|
drawPass(&m_shBLUR1, &tempDamage); // down
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = BLURPASSES - 1; i >= 0; --i) {
|
||||||
|
sample = m_RenderData.pMonitor->vecSize / (1 << i);
|
||||||
|
|
||||||
|
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big
|
||||||
|
drawPass(&m_shBLUR2, &tempDamage); // up
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish
|
||||||
|
pixman_region32_fini(&tempDamage);
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
glBindTexture(PMIRRORFB->m_cTex.m_iTarget, 0);
|
||||||
|
|
||||||
|
return currentRenderToFB;
|
||||||
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, int round) {
|
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, int round) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
|
||||||
|
|
||||||
|
@ -352,82 +486,16 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: only blur selected regions when damaged
|
if (!pixman_region32_not_empty(m_RenderData.pDamage))
|
||||||
// blur region + pad (blur size)
|
return;
|
||||||
|
|
||||||
// basics
|
// blur the main FB, it will be rendered onto the mirror
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
const auto POUTFB = blurMainFramebufferWithDamage(a, pBox);
|
||||||
float matrix[9];
|
|
||||||
wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
|
||||||
|
|
||||||
// blur the primary FB into the mirrored one
|
// bind primary
|
||||||
m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.bind();
|
m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.bind();
|
||||||
clear(CColor(0, 0, 0, 0));
|
|
||||||
|
|
||||||
// matrix
|
// make a stencil for rounded corners to work with blur
|
||||||
float matrixFull[9];
|
|
||||||
wlr_box fullMonBox = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
|
||||||
wlr_matrix_project_box(matrixFull, &fullMonBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
|
||||||
|
|
||||||
float glMatrix[9];
|
|
||||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrixFull);
|
|
||||||
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
|
|
||||||
|
|
||||||
wlr_matrix_transpose(glMatrix, glMatrix);
|
|
||||||
|
|
||||||
const auto BLURSIZE = g_pConfigManager->getInt("decoration:blur_size");
|
|
||||||
const auto BLURPASSES = g_pConfigManager->getInt("decoration:blur_passes");
|
|
||||||
|
|
||||||
auto drawWithShader = [&](CShader* pShader, Vector2D halfpixel) {
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
glTexParameteri(tex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
glUseProgram(pShader->program);
|
|
||||||
|
|
||||||
// glUniform2f(glGetUniformLocation(pShader->program, "resolution"), m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y);
|
|
||||||
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
|
|
||||||
glUniform1i(pShader->tex, 0);
|
|
||||||
glUniform1f(glGetUniformLocation(pShader->program, "radius"), BLURSIZE * (a / 255.f) /* nice effect: less blur when less a */);
|
|
||||||
glUniform2f(glGetUniformLocation(pShader->program, "halfpixel"), halfpixel.x, halfpixel.y);
|
|
||||||
|
|
||||||
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
|
||||||
glVertexAttribPointer(pShader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(pShader->posAttrib);
|
|
||||||
glEnableVertexAttribArray(pShader->texAttrib);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
|
|
||||||
glDisableVertexAttribArray(pShader->posAttrib);
|
|
||||||
glDisableVertexAttribArray(pShader->texAttrib);
|
|
||||||
};
|
|
||||||
|
|
||||||
int sampleW = 0, sampleH = 0;
|
|
||||||
|
|
||||||
glBindTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTarget, m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTexID);
|
|
||||||
|
|
||||||
sampleW = m_RenderData.pMonitor->vecSize.x / 2.f;
|
|
||||||
sampleH = m_RenderData.pMonitor->vecSize.y / 2.f;
|
|
||||||
|
|
||||||
drawWithShader(&m_shBLUR1, Vector2D(0.5f / sampleW, 0.5f / sampleH)); // down
|
|
||||||
|
|
||||||
glBindTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.m_cTex.m_iTarget, m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.m_cTex.m_iTexID);
|
|
||||||
|
|
||||||
for (int i = 1; i < BLURPASSES; ++i) {
|
|
||||||
drawWithShader(&m_shBLUR1, Vector2D(0.5f / sampleW, 0.5f / sampleH)); // down
|
|
||||||
}
|
|
||||||
|
|
||||||
sampleW = m_RenderData.pMonitor->vecSize.x * 2.f;
|
|
||||||
sampleH = m_RenderData.pMonitor->vecSize.y * 2.f;
|
|
||||||
|
|
||||||
for (int i = BLURPASSES - 1; i >= 0; --i) {
|
|
||||||
drawWithShader(&m_shBLUR2, Vector2D(0.5f / sampleW, 0.5f / sampleH)); // up
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(tex.m_iTarget, 0);
|
|
||||||
|
|
||||||
// ok, now we can make a stencil for our window to affect the draw of the copy
|
|
||||||
glClearStencil(0);
|
glClearStencil(0);
|
||||||
glClear(GL_STENCIL_BUFFER_BIT);
|
glClear(GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
|
@ -437,38 +505,48 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||||
|
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
renderTextureInternal(tex, pBox, a, round, true); // discard opaque
|
renderTextureInternal(tex, pBox, a, round, true); // discard opaque
|
||||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
glStencilFunc(GL_EQUAL, 1, -1);
|
glStencilFunc(GL_EQUAL, 1, -1);
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||||
|
|
||||||
// Now we have a stencil and we need to scissor the updated regions
|
// make a damage region for this window
|
||||||
|
pixman_region32_t damage;
|
||||||
|
pixman_region32_init(&damage);
|
||||||
|
pixman_region32_intersect_rect(&damage, m_RenderData.pDamage, pBox->x, pBox->y, pBox->width, pBox->height); // clip it to the box
|
||||||
|
|
||||||
// bind the primary fb again for final drawing
|
// stencil done. Render everything.
|
||||||
m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.bind();
|
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
||||||
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
if (pixman_region32_not_empty(&damage)) {
|
||||||
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
{
|
||||||
const auto RECT = RECTSARR[i];
|
PIXMAN_DAMAGE_FOREACH(&damage) {
|
||||||
scissor(&RECT);
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
|
||||||
// render our great blurred FB
|
// render our great blurred FB
|
||||||
renderTextureInternal(m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.m_cTex, &fullMonBox, 255.f); // 255.f because we adjusted blur strength to a
|
renderTextureInternal(POUTFB->m_cTex, &MONITORBOX, 255.f); // 255.f because we adjusted blur strength to a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// render the window, but disable stencil for it
|
// render the window, but disable stencil for it
|
||||||
// because stencil has ignoreopaque
|
// because stencil has ignoreopaque
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
glEnable(GL_BLEND);
|
|
||||||
renderTextureInternal(tex, pBox, a, round);
|
{
|
||||||
glEnable(GL_STENCIL_TEST);
|
PIXMAN_DAMAGE_FOREACH(&damage) {
|
||||||
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
renderTextureInternal(tex, pBox, a, round);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable the stencil
|
// disable the stencil, finalize everything
|
||||||
glStencilMask(-1);
|
glStencilMask(-1);
|
||||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
scissor((wlr_box*)nullptr);
|
scissor((wlr_box*)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,12 @@ inline const float fullVerts[] = {
|
||||||
1, 1, // bottom right
|
1, 1, // bottom right
|
||||||
0, 1, // bottom left
|
0, 1, // bottom left
|
||||||
};
|
};
|
||||||
|
inline const float fanVertsFull[] = {
|
||||||
|
-1.0f, -1.0f,
|
||||||
|
1.0f, -1.0f,
|
||||||
|
1.0f, 1.0f,
|
||||||
|
-1.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
struct SCurrentRenderData {
|
struct SCurrentRenderData {
|
||||||
SMonitor* pMonitor = nullptr;
|
SMonitor* pMonitor = nullptr;
|
||||||
|
@ -34,6 +40,7 @@ struct SCurrentRenderData {
|
||||||
struct SMonitorRenderData {
|
struct SMonitorRenderData {
|
||||||
CFramebuffer primaryFB;
|
CFramebuffer primaryFB;
|
||||||
CFramebuffer mirrorFB;
|
CFramebuffer mirrorFB;
|
||||||
|
CFramebuffer mirrorSwapFB;
|
||||||
|
|
||||||
CTexture stencilTex;
|
CTexture stencilTex;
|
||||||
};
|
};
|
||||||
|
@ -59,6 +66,7 @@ public:
|
||||||
void clearWithTex();
|
void clearWithTex();
|
||||||
void scissor(const wlr_box*);
|
void scissor(const wlr_box*);
|
||||||
void scissor(const pixman_box32*);
|
void scissor(const pixman_box32*);
|
||||||
|
void scissor(const int x, const int y, const int w, const int h);
|
||||||
|
|
||||||
void destroyMonitorResources(SMonitor*);
|
void destroyMonitorResources(SMonitor*);
|
||||||
|
|
||||||
|
@ -91,6 +99,9 @@ private:
|
||||||
GLuint compileShader(const GLuint&, std::string);
|
GLuint compileShader(const GLuint&, std::string);
|
||||||
void createBGTextureForMonitor(SMonitor*);
|
void createBGTextureForMonitor(SMonitor*);
|
||||||
|
|
||||||
|
// returns the out FB, can be either Mirror or MirrorSwap
|
||||||
|
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox);
|
||||||
|
|
||||||
void renderTextureInternal(const CTexture&, wlr_box* pBox, float a, int round = 0, bool discardOpaque = false);
|
void renderTextureInternal(const CTexture&, wlr_box* pBox, float a, int round = 0, bool discardOpaque = false);
|
||||||
void renderTextureWithBlurInternal(const CTexture&, wlr_box*, float a, int round = 0);
|
void renderTextureWithBlurInternal(const CTexture&, wlr_box*, float a, int round = 0);
|
||||||
|
|
||||||
|
|
|
@ -154,46 +154,49 @@ void main() {
|
||||||
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha;
|
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha;
|
||||||
})#";
|
})#";
|
||||||
|
|
||||||
// thanks to Loadus
|
|
||||||
// https://www.shadertoy.com/view/Mtl3Rj
|
|
||||||
// for this pseudo-gaussian blur!
|
|
||||||
inline const std::string FRAGBLUR1 = R"#(
|
inline const std::string FRAGBLUR1 = R"#(
|
||||||
|
#version 100
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
varying vec2 v_texcoord; // is in 0-1
|
varying mediump vec2 v_texcoord; // is in 0-1
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
|
|
||||||
uniform float radius;
|
uniform float radius;
|
||||||
uniform vec2 resolution;
|
|
||||||
uniform vec2 halfpixel;
|
uniform vec2 halfpixel;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 sum = texture2D(tex, v_texcoord) * 4.0;
|
vec2 uv = v_texcoord * 2.0;
|
||||||
sum += texture2D(tex, v_texcoord - halfpixel.xy * radius);
|
|
||||||
sum += texture2D(tex, v_texcoord + halfpixel.xy * radius);
|
vec4 sum = texture2D(tex, uv) * 4.0;
|
||||||
sum += texture2D(tex, v_texcoord + vec2(halfpixel.x, -halfpixel.y) * radius);
|
sum += texture2D(tex, uv - halfpixel.xy * radius);
|
||||||
sum += texture2D(tex, v_texcoord - vec2(halfpixel.x, -halfpixel.y) * radius);
|
sum += texture2D(tex, uv + halfpixel.xy * radius);
|
||||||
|
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
|
||||||
|
sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
|
||||||
gl_FragColor = sum / 8.0;
|
gl_FragColor = sum / 8.0;
|
||||||
}
|
}
|
||||||
)#";
|
)#";
|
||||||
|
|
||||||
inline const std::string FRAGBLUR2 = R"#(
|
inline const std::string FRAGBLUR2 = R"#(
|
||||||
|
#version 100
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
varying vec2 v_texcoord; // is in 0-1
|
varying mediump vec2 v_texcoord; // is in 0-1
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
|
|
||||||
uniform float radius;
|
uniform float radius;
|
||||||
uniform vec2 resolution;
|
|
||||||
uniform vec2 halfpixel;
|
uniform vec2 halfpixel;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 sum = texture2D(tex, v_texcoord + vec2(-halfpixel.x * 2.0, 0.0) * radius);
|
vec2 uv = v_texcoord / 2.0;
|
||||||
sum += texture2D(tex, v_texcoord + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
|
|
||||||
sum += texture2D(tex, v_texcoord + vec2(0.0, halfpixel.y * 2.0) * radius);
|
vec4 sum = texture2D(tex, uv + vec2(-halfpixel.x * 2.0, 0.0) * radius);
|
||||||
sum += texture2D(tex, v_texcoord + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
|
|
||||||
sum += texture2D(tex, v_texcoord + vec2(halfpixel.x * 2.0, 0.0) * radius);
|
sum += texture2D(tex, uv + vec2(-halfpixel.x, halfpixel.y) * radius) * 2.0;
|
||||||
sum += texture2D(tex, v_texcoord + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
sum += texture2D(tex, uv + vec2(0.0, halfpixel.y * 2.0) * radius);
|
||||||
sum += texture2D(tex, v_texcoord + vec2(0.0, -halfpixel.y * 2.0) * radius);
|
sum += texture2D(tex, uv + vec2(halfpixel.x, halfpixel.y) * radius) * 2.0;
|
||||||
sum += texture2D(tex, v_texcoord + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
sum += texture2D(tex, uv + vec2(halfpixel.x * 2.0, 0.0) * radius);
|
||||||
|
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
||||||
|
sum += texture2D(tex, uv + vec2(0.0, -halfpixel.y * 2.0) * radius);
|
||||||
|
sum += texture2D(tex, uv + vec2(-halfpixel.x, -halfpixel.y) * radius) * 2.0;
|
||||||
|
|
||||||
gl_FragColor = sum / 12.0;
|
gl_FragColor = sum / 12.0;
|
||||||
}
|
}
|
||||||
)#";
|
)#";
|
||||||
|
|
Loading…
Reference in a new issue