mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-26 00:45:57 +01:00
Merge pull request #39 from vaxerski/damage-tracking
Added damage tracking
This commit is contained in:
commit
74dbf196c1
17 changed files with 302 additions and 86 deletions
|
@ -28,6 +28,7 @@ Hyprland needs testers! Try it out and report bugs or suggestions!
|
||||||
- Rounded corners
|
- Rounded corners
|
||||||
- Window blur
|
- Window blur
|
||||||
- Workspaces Protocol support
|
- Workspaces Protocol support
|
||||||
|
- Damage tracking (experimental)
|
||||||
- Fade in/out
|
- Fade in/out
|
||||||
- Support for docks/whatever
|
- Support for docks/whatever
|
||||||
- Window rules
|
- Window rules
|
||||||
|
@ -37,7 +38,6 @@ Hyprland needs testers! Try it out and report bugs or suggestions!
|
||||||
- Moving/resizing windows
|
- Moving/resizing windows
|
||||||
|
|
||||||
# Major to-dos
|
# Major to-dos
|
||||||
- Damage tracking
|
|
||||||
- Input Methods (wlr_input_method_v2)
|
- Input Methods (wlr_input_method_v2)
|
||||||
- Animations (some new, like workspace)
|
- Animations (some new, like workspace)
|
||||||
- Fix electron rendering issues
|
- Fix electron rendering issues
|
||||||
|
|
|
@ -26,6 +26,8 @@ general {
|
||||||
border_size=2
|
border_size=2
|
||||||
col.active_border=0x66ee1111
|
col.active_border=0x66ee1111
|
||||||
col.inactive_border=0x66333333
|
col.inactive_border=0x66333333
|
||||||
|
|
||||||
|
damage_tracking=none # experimental, might have bugs!
|
||||||
}
|
}
|
||||||
|
|
||||||
decoration {
|
decoration {
|
||||||
|
|
|
@ -16,6 +16,9 @@ CConfigManager::CConfigManager() {
|
||||||
configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring
|
configValues["general:main_mod"].strValue = "SUPER"; // exposed to the user for easier configuring
|
||||||
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated
|
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask("SUPER"); // actually used and automatically calculated
|
||||||
|
|
||||||
|
configValues["general:damage_tracking"].strValue = "none";
|
||||||
|
configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_NONE;
|
||||||
|
|
||||||
configValues["general:border_size"].intValue = 1;
|
configValues["general:border_size"].intValue = 1;
|
||||||
configValues["general:gaps_in"].intValue = 5;
|
configValues["general:gaps_in"].intValue = 5;
|
||||||
configValues["general:gaps_out"].intValue = 20;
|
configValues["general:gaps_out"].intValue = 20;
|
||||||
|
@ -365,8 +368,15 @@ void CConfigManager::loadConfigLoadVars() {
|
||||||
if (!isFirstLaunch)
|
if (!isFirstLaunch)
|
||||||
g_pInputManager->setKeyboardLayout();
|
g_pInputManager->setKeyboardLayout();
|
||||||
|
|
||||||
// Calculate the mod mask for main_mod
|
// Calculate the internal vars
|
||||||
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue);
|
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue);
|
||||||
|
const auto DAMAGETRACKINGMODE = g_pHyprRenderer->damageTrackingModeFromStr(configValues["general:damage_tracking"].strValue);
|
||||||
|
if (DAMAGETRACKINGMODE != DAMAGE_TRACKING_INVALID)
|
||||||
|
configValues["general:damage_tracking_internal"].intValue = DAMAGETRACKINGMODE;
|
||||||
|
else {
|
||||||
|
parseError = "invalid value for general:damage_tracking, supported: full, monitor, none";
|
||||||
|
configValues["general:damage_tracking_internal"].intValue = DAMAGE_TRACKING_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
// parseError will be displayed next frame
|
// parseError will be displayed next frame
|
||||||
if (parseError != "")
|
if (parseError != "")
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
|
|
||||||
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < delta)
|
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < delta)
|
||||||
|
|
||||||
|
#define PIXMAN_DAMAGE_FOREACH(region) int rectsNum = 0; \
|
||||||
|
const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \
|
||||||
|
for (int i = 0; i < rectsNum; ++i)
|
||||||
|
|
||||||
|
|
||||||
#define interface class
|
#define interface class
|
||||||
|
|
||||||
#define STICKS(a, b) abs((a) - (b)) < 2
|
#define STICKS(a, b) abs((a) - (b)) < 2
|
||||||
|
|
|
@ -158,4 +158,6 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageBox(&layersurface->geometry);
|
||||||
}
|
}
|
|
@ -141,6 +141,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||||
// add a WLR workspace group
|
// add a WLR workspace group
|
||||||
PNEWMONITOR->pWLRWorkspaceGroupHandle = wlr_ext_workspace_group_handle_v1_create(g_pCompositor->m_sWLREXTWorkspaceMgr);
|
PNEWMONITOR->pWLRWorkspaceGroupHandle = wlr_ext_workspace_group_handle_v1_create(g_pCompositor->m_sWLREXTWorkspaceMgr);
|
||||||
|
|
||||||
|
// add damage
|
||||||
|
PNEWMONITOR->damage = wlr_output_damage_create(OUTPUT);
|
||||||
|
|
||||||
// Workspace
|
// Workspace
|
||||||
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
|
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
|
||||||
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
||||||
|
@ -176,10 +179,39 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
timespec now;
|
timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
if (!wlr_output_attach_render(PMONITOR->output, nullptr))
|
// check the damage
|
||||||
return;
|
pixman_region32_t damage;
|
||||||
|
bool hasChanged;
|
||||||
|
pixman_region32_init(&damage);
|
||||||
|
|
||||||
g_pHyprOpenGL->begin(PMONITOR);
|
const auto DTMODE = g_pConfigManager->getInt("general:damage_tracking_internal");
|
||||||
|
|
||||||
|
if (DTMODE == -1) {
|
||||||
|
Debug::log(CRIT, "Damage tracking mode -1 ????");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)){
|
||||||
|
Debug::log(ERR, "Couldn't attach render to display %s ???", PMONITOR->szName.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasChanged && DTMODE != DAMAGE_TRACKING_NONE) {
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
wlr_output_rollback(PMONITOR->output);
|
||||||
|
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have no tracking or full tracking, invalidate the entire monitor
|
||||||
|
if (DTMODE == DAMAGE_TRACKING_NONE || DTMODE == DAMAGE_TRACKING_MONITOR) {
|
||||||
|
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this is getting called with extents being 0,0,0,0 should it be?
|
||||||
|
// potentially can save on resources.
|
||||||
|
|
||||||
|
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
||||||
g_pHyprOpenGL->clear(CColor(11, 11, 11, 255));
|
g_pHyprOpenGL->clear(CColor(11, 11, 11, 255));
|
||||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||||
|
|
||||||
|
@ -193,7 +225,20 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||||
|
|
||||||
g_pHyprOpenGL->end();
|
g_pHyprOpenGL->end();
|
||||||
|
|
||||||
|
// calc frame damage
|
||||||
|
pixman_region32_t frameDamage;
|
||||||
|
pixman_region32_init(&frameDamage);
|
||||||
|
|
||||||
|
const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
|
||||||
|
wlr_region_transform(&frameDamage, &PMONITOR->damage->current, TRANSFORM, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y);
|
||||||
|
|
||||||
|
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||||
|
pixman_region32_fini(&frameDamage);
|
||||||
|
pixman_region32_fini(&damage);
|
||||||
|
|
||||||
wlr_output_commit(PMONITOR->output);
|
wlr_output_commit(PMONITOR->output);
|
||||||
|
|
||||||
|
wlr_output_schedule_frame(PMONITOR->output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_monitorDestroy(void* owner, void* data) {
|
void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||||
|
|
|
@ -200,6 +200,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_bFadingOut = true;
|
PWINDOW->m_bFadingOut = true;
|
||||||
|
|
||||||
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
|
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_commitWindow(void* owner, void* data) {
|
void Events::listener_commitWindow(void* owner, void* data) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "SubsurfaceTree.hpp"
|
#include "SubsurfaceTree.hpp"
|
||||||
#include "../events/Events.hpp"
|
#include "../events/Events.hpp"
|
||||||
|
#include "../Compositor.hpp"
|
||||||
|
|
||||||
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
||||||
*lx += node->pSurface->sx;
|
*lx += node->pSurface->sx;
|
||||||
|
@ -164,6 +165,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||||
int lx = 0, ly = 0;
|
int lx = 0, ly = 0;
|
||||||
|
|
||||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageSurface(pNode->pSurface, lx, ly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
void Events::listener_destroySubsurface(void* owner, void* data) {
|
||||||
|
|
|
@ -101,12 +101,9 @@ void CHyprError::draw() {
|
||||||
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
|
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
|
||||||
return; // wrong mon
|
return; // wrong mon
|
||||||
|
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
|
||||||
float matrix[9];
|
|
||||||
wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||||
wlr_matrix_project_box(matrix, &windowBox, TRANSFORM, 0, PMONITOR->output->transform_matrix);
|
|
||||||
|
|
||||||
g_pHyprOpenGL->renderTexture(m_tTexture, matrix, 255.f, 0);
|
g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 255.f, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprError::destroy() {
|
void CHyprError::destroy() {
|
||||||
|
|
|
@ -412,6 +412,8 @@ void CHyprDwindleLayout::onBeginDragWindow() {
|
||||||
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition;
|
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition;
|
||||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize;
|
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize;
|
||||||
m_vLastDragXY = m_vBeginDragXY;
|
m_vLastDragXY = m_vBeginDragXY;
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::onEndDragWindow() {
|
void CHyprDwindleLayout::onEndDragWindow() {
|
||||||
|
@ -422,6 +424,7 @@ void CHyprDwindleLayout::onEndDragWindow() {
|
||||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
|
@ -433,8 +436,14 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
|
|
||||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||||
|
|
||||||
|
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
|
||||||
|
return;
|
||||||
|
|
||||||
m_vLastDragXY = mousePos;
|
m_vLastDragXY = mousePos;
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||||
|
|
||||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||||
DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA;
|
DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA;
|
||||||
DRAGGINGWINDOW->m_vEffectivePosition = DRAGGINGWINDOW->m_vRealPosition;
|
DRAGGINGWINDOW->m_vEffectivePosition = DRAGGINGWINDOW->m_vRealPosition;
|
||||||
|
@ -515,6 +524,8 @@ void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
|
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||||
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
|
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||||
|
|
|
@ -21,8 +21,14 @@ void CAnimationManager::tick() {
|
||||||
const auto BORDERACTIVECOL = CColor(g_pConfigManager->getInt("general:col.active_border"));
|
const auto BORDERACTIVECOL = CColor(g_pConfigManager->getInt("general:col.active_border"));
|
||||||
const auto BORDERINACTIVECOL = CColor(g_pConfigManager->getInt("general:col.inactive_border"));
|
const auto BORDERINACTIVECOL = CColor(g_pConfigManager->getInt("general:col.inactive_border"));
|
||||||
|
|
||||||
|
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||||
|
|
||||||
for (auto& w : g_pCompositor->m_lWindows) {
|
for (auto& w : g_pCompositor->m_lWindows) {
|
||||||
|
|
||||||
|
// get the box before transforms, for damage tracking later
|
||||||
|
wlr_box WLRBOXPREV = { w.m_vRealPosition.x - BORDERSIZE - 1, w.m_vRealPosition.y - BORDERSIZE - 1, w.m_vRealSize.x + 2 * BORDERSIZE + 2, w.m_vRealSize.y + 2 * BORDERSIZE + 2};
|
||||||
|
bool needsDamage = false;
|
||||||
|
|
||||||
// process fadeinout
|
// process fadeinout
|
||||||
if (FADEENABLED) {
|
if (FADEENABLED) {
|
||||||
const auto GOALALPHA = w.m_bIsMapped ? 255.f : 0.f;
|
const auto GOALALPHA = w.m_bIsMapped ? 255.f : 0.f;
|
||||||
|
@ -36,21 +42,34 @@ void CAnimationManager::tick() {
|
||||||
w.m_bFadingOut = true;
|
w.m_bFadingOut = true;
|
||||||
w.m_fAlpha = parabolic(w.m_fAlpha, GOALALPHA, FADESPEED);
|
w.m_fAlpha = parabolic(w.m_fAlpha, GOALALPHA, FADESPEED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
needsDamage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (w.m_bIsMapped)
|
const auto GOALALPHA = w.m_bIsMapped ? 255.f : 0.f;
|
||||||
w.m_fAlpha = 255.f;
|
|
||||||
else {
|
if (!deltazero(GOALALPHA, w.m_fAlpha)) {
|
||||||
w.m_fAlpha = 0.f;
|
if (w.m_bIsMapped)
|
||||||
w.m_bFadingOut = false;
|
w.m_fAlpha = 255.f;
|
||||||
|
else {
|
||||||
|
w.m_fAlpha = 0.f;
|
||||||
|
w.m_bFadingOut = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
needsDamage = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// process fadein/out for unmapped windows, but nothing else.
|
// process fadein/out for unmapped windows, but nothing else.
|
||||||
// we can't use windowValidMapped because we want to animate hidden windows too.
|
// we can't use windowValidMapped because we want to animate hidden windows too.
|
||||||
if (!g_pCompositor->windowExists(&w) || !w.m_bIsMapped || !g_pXWaylandManager->getWindowSurface(&w))
|
if (!g_pCompositor->windowExists(&w) || !w.m_bIsMapped || !g_pXWaylandManager->getWindowSurface(&w)){
|
||||||
|
if (needsDamage) {
|
||||||
|
g_pHyprRenderer->damageWindow(&w); // only window, it didnt move cuz its unmappy
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// process the borders
|
// process the borders
|
||||||
const auto RENDERHINTS = g_pLayoutManager->getCurrentLayout()->requestRenderHints(&w);
|
const auto RENDERHINTS = g_pLayoutManager->getCurrentLayout()->requestRenderHints(&w);
|
||||||
|
@ -64,8 +83,11 @@ void CAnimationManager::tick() {
|
||||||
} else {
|
} else {
|
||||||
w.m_cRealBorderColor = parabolic(BORDERSPEED, w.m_cRealBorderColor, COLOR);
|
w.m_cRealBorderColor = parabolic(BORDERSPEED, w.m_cRealBorderColor, COLOR);
|
||||||
}
|
}
|
||||||
|
needsDamage = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (!deltazero(w.m_cRealBorderColor, COLOR))
|
||||||
|
needsDamage = true;
|
||||||
w.m_cRealBorderColor = COLOR;
|
w.m_cRealBorderColor = COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,11 +103,21 @@ void CAnimationManager::tick() {
|
||||||
w.m_vRealPosition = Vector2D(parabolic(w.m_vRealPosition.x, w.m_vEffectivePosition.x, WINDOWSPEED), parabolic(w.m_vRealPosition.y, w.m_vEffectivePosition.y, WINDOWSPEED));
|
w.m_vRealPosition = Vector2D(parabolic(w.m_vRealPosition.x, w.m_vEffectivePosition.x, WINDOWSPEED), parabolic(w.m_vRealPosition.y, w.m_vEffectivePosition.y, WINDOWSPEED));
|
||||||
w.m_vRealSize = Vector2D(parabolic(w.m_vRealSize.x, w.m_vEffectiveSize.x, WINDOWSPEED), parabolic(w.m_vRealSize.y, w.m_vEffectiveSize.y, WINDOWSPEED));
|
w.m_vRealSize = Vector2D(parabolic(w.m_vRealSize.x, w.m_vEffectiveSize.x, WINDOWSPEED), parabolic(w.m_vRealSize.y, w.m_vEffectiveSize.y, WINDOWSPEED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
needsDamage = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (!deltazero(w.m_vRealPosition, w.m_vEffectivePosition) || !deltazero(w.m_vRealSize, w.m_vEffectiveSize))
|
||||||
|
needsDamage = true;
|
||||||
|
|
||||||
w.m_vRealPosition = w.m_vEffectivePosition;
|
w.m_vRealPosition = w.m_vEffectivePosition;
|
||||||
w.m_vRealSize = w.m_vEffectiveSize;
|
w.m_vRealSize = w.m_vEffectiveSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (needsDamage) {
|
||||||
|
g_pHyprRenderer->damageBox(&WLRBOXPREV);
|
||||||
|
g_pHyprRenderer->damageWindow(&w);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,10 +129,18 @@ bool CAnimationManager::deltaSmallToFlip(const CColor& a, const CColor& b) {
|
||||||
return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f;
|
return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CAnimationManager::deltaSmallToFlip(const float& a, const float& b) {
|
||||||
|
return std::abs(a - b) < 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
bool CAnimationManager::deltazero(const Vector2D& a, const Vector2D& b) {
|
bool CAnimationManager::deltazero(const Vector2D& a, const Vector2D& b) {
|
||||||
return a.x == b.x && a.y == b.y;
|
return a.x == b.x && a.y == b.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CAnimationManager::deltazero(const float& a, const float& b) {
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
|
bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
|
||||||
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,10 @@ public:
|
||||||
private:
|
private:
|
||||||
bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
|
bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
|
||||||
bool deltaSmallToFlip(const CColor& a, const CColor& b);
|
bool deltaSmallToFlip(const CColor& a, const CColor& b);
|
||||||
|
bool deltaSmallToFlip(const float& a, const float& b);
|
||||||
bool deltazero(const Vector2D& a, const Vector2D& b);
|
bool deltazero(const Vector2D& a, const Vector2D& b);
|
||||||
bool deltazero(const CColor& a, const CColor& b);
|
bool deltazero(const CColor& a, const CColor& b);
|
||||||
|
bool deltazero(const float& a, const float& b);
|
||||||
double parabolic(const double, const double, const double);
|
double parabolic(const double, const double, const double);
|
||||||
CColor parabolic(const double, const CColor&, const CColor&);
|
CColor parabolic(const double, const CColor&, const CColor&);
|
||||||
};
|
};
|
||||||
|
|
|
@ -222,6 +222,9 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||||
g_pCompositor->deactivateAllWLRWorkspaces();
|
g_pCompositor->deactivateAllWLRWorkspaces();
|
||||||
wlr_ext_workspace_handle_v1_set_active(PWORKSPACE->m_pWlrHandle, true);
|
wlr_ext_workspace_handle_v1_set_active(PWORKSPACE->m_pWlrHandle, true);
|
||||||
|
|
||||||
|
// mark the monitor dirty
|
||||||
|
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||||
|
|
||||||
// focus (clears the last)
|
// focus (clears the last)
|
||||||
g_pInputManager->refocus();
|
g_pInputManager->refocus();
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src) {
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::begin(SMonitor* pMonitor) {
|
void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage) {
|
||||||
m_RenderData.pMonitor = pMonitor;
|
m_RenderData.pMonitor = pMonitor;
|
||||||
|
|
||||||
glViewport(0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y);
|
glViewport(0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y);
|
||||||
|
@ -145,20 +145,21 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor) {
|
||||||
|
|
||||||
// bind the primary Hypr Framebuffer
|
// bind the primary Hypr Framebuffer
|
||||||
m_mMonitorRenderResources[pMonitor].primaryFB.bind();
|
m_mMonitorRenderResources[pMonitor].primaryFB.bind();
|
||||||
|
|
||||||
|
m_RenderData.pDamage = pDamage;
|
||||||
|
|
||||||
|
// clear
|
||||||
clear(CColor(11, 11, 11, 255));
|
clear(CColor(11, 11, 11, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::end() {
|
void CHyprOpenGLImpl::end() {
|
||||||
// end the render, copy the data to the WLR framebuffer
|
// end the render, copy the data to the WLR framebuffer
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
|
||||||
float matrix[9];
|
|
||||||
wlr_box windowBox = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
wlr_box windowBox = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
||||||
wlr_matrix_project_box(matrix, &windowBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
|
||||||
|
|
||||||
clear(CColor(11, 11, 11, 255));
|
clear(CColor(11, 11, 11, 255));
|
||||||
|
|
||||||
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, matrix, 255.f, 0);
|
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &windowBox, 255.f, 0);
|
||||||
|
|
||||||
// reset our data
|
// reset our data
|
||||||
m_RenderData.pMonitor = nullptr;
|
m_RenderData.pMonitor = nullptr;
|
||||||
|
@ -169,7 +170,17 @@ void CHyprOpenGLImpl::clear(const CColor& color) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
|
||||||
|
|
||||||
glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||||
|
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||||
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scissor((wlr_box*)nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
|
void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
|
||||||
|
@ -184,10 +195,24 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
|
||||||
|
RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!");
|
||||||
|
|
||||||
|
if (!pBox) {
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glScissor(pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
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()!");
|
||||||
|
|
||||||
|
// TODO: respect damage
|
||||||
|
|
||||||
float matrix[9];
|
float matrix[9];
|
||||||
wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||||
|
|
||||||
|
@ -216,16 +241,37 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col) {
|
||||||
glDisableVertexAttribArray(m_shQUAD.posAttrib);
|
glDisableVertexAttribArray(m_shQUAD.posAttrib);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex,float matrix[9], float alpha, int round) {
|
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
|
|
||||||
renderTexture(CTexture(tex), matrix, alpha, round);
|
renderTexture(CTexture(tex), pBox, alpha, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, float matrix[9], float alpha, int round) {
|
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round) {
|
||||||
|
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||||
|
|
||||||
|
// TODO: optimize this, this is bad
|
||||||
|
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||||
|
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||||
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
|
||||||
|
renderTextureInternal(tex, pBox, alpha, round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scissor((wlr_box*)nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprOpenGLImpl::renderTextureInternal(const CTexture& tex, wlr_box* pBox, float alpha, int round) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
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!");
|
||||||
|
|
||||||
|
// get transform
|
||||||
|
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
float matrix[9];
|
||||||
|
wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||||
|
|
||||||
float glMatrix[9];
|
float glMatrix[9];
|
||||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||||
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
|
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
|
||||||
|
@ -288,21 +334,42 @@ void CHyprOpenGLImpl::renderTexture(const CTexture& tex, float matrix[9], float
|
||||||
glBindTexture(tex.m_iTarget, 0);
|
glBindTexture(tex.m_iTarget, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()!");
|
||||||
|
|
||||||
|
// TODO: optimize this, this is bad
|
||||||
|
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
|
||||||
|
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
|
||||||
|
const auto RECT = RECTSARR[i];
|
||||||
|
scissor(&RECT);
|
||||||
|
|
||||||
|
renderTextureWithBlurInternal(tex, pBox, a, round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scissor((wlr_box*)nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
// This is probably not the quickest method possible,
|
// This is probably not the quickest method possible,
|
||||||
// feel free to contribute if you have a better method.
|
// feel free to contribute if you have a better method.
|
||||||
// cheers.
|
// cheers.
|
||||||
|
|
||||||
// 2-pass pseudo-gaussian blur
|
// 2-pass pseudo-gaussian blur
|
||||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, float matrix[9], float a, int round) {
|
void CHyprOpenGLImpl::renderTextureWithBlurInternal(const CTexture& tex, wlr_box* pBox, float a, int round) {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
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!");
|
||||||
|
|
||||||
// if blur disabled, just render the texture
|
// if blur disabled, just render the texture
|
||||||
if (g_pConfigManager->getInt("decoration:blur") == 0) {
|
if (g_pConfigManager->getInt("decoration:blur") == 0) {
|
||||||
renderTexture(tex, matrix, a, round);
|
renderTextureInternal(tex, pBox, a, round);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get transform
|
||||||
|
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
|
float matrix[9];
|
||||||
|
wlr_matrix_project_box(matrix, pBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||||
|
|
||||||
// bind the mirror FB and clear it.
|
// bind the mirror FB and clear it.
|
||||||
m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.bind();
|
m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.bind();
|
||||||
clear(CColor(0, 0, 0, 0));
|
clear(CColor(0, 0, 0, 0));
|
||||||
|
@ -317,7 +384,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, float matrix[9]
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||||
|
|
||||||
// render our window to the mirror FB while also writing to the stencil
|
// render our window to the mirror FB while also writing to the stencil
|
||||||
renderTexture(tex, matrix, a, round);
|
renderTextureInternal(tex, pBox, a, round);
|
||||||
|
|
||||||
// then we disable writing to the mask and ONLY accept writing within the stencil
|
// then we disable writing to the mask and ONLY accept writing within the stencil
|
||||||
glStencilFunc(GL_EQUAL, 1, -1);
|
glStencilFunc(GL_EQUAL, 1, -1);
|
||||||
|
@ -332,7 +399,6 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, float matrix[9]
|
||||||
// now we make the blur by blurring the main framebuffer (it will only affect the stencil)
|
// now we make the blur by blurring the main framebuffer (it will only affect the stencil)
|
||||||
|
|
||||||
// matrix
|
// matrix
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
|
||||||
float matrixFull[9];
|
float matrixFull[9];
|
||||||
wlr_box fullMonBox = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
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);
|
wlr_matrix_project_box(matrixFull, &fullMonBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||||
|
@ -382,7 +448,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, float matrix[9]
|
||||||
|
|
||||||
// when the blur is done, let's render the window itself
|
// when the blur is done, let's render the window itself
|
||||||
// we get it from the mirrored FB full because it's the FB 255 alpha cuz we rendered with a before, same for rounding
|
// we get it from the mirrored FB full because it's the FB 255 alpha cuz we rendered with a before, same for rounding
|
||||||
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.m_cTex, matrixFull, 255.f, 0);
|
renderTextureInternal(m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB.m_cTex, &fullMonBox, 255.f, 0);
|
||||||
|
|
||||||
// and disable the stencil
|
// and disable the stencil
|
||||||
glStencilMask(-1);
|
glStencilMask(-1);
|
||||||
|
@ -485,7 +551,16 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||||
wlr_output_attach_render(PMONITOR->output, nullptr);
|
wlr_output_attach_render(PMONITOR->output, nullptr);
|
||||||
|
|
||||||
begin(PMONITOR);
|
// 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->vecSize.x, (int)PMONITOR->vecSize.y);
|
||||||
|
|
||||||
|
begin(PMONITOR, &fakeDamage);
|
||||||
|
|
||||||
|
pixman_region32_fini(&fakeDamage);
|
||||||
|
|
||||||
const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
|
const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
|
||||||
|
|
||||||
|
@ -541,12 +616,9 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
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_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);
|
renderTextureInternal(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||||
|
@ -603,10 +675,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||||
void CHyprOpenGLImpl::clearWithTex() {
|
void CHyprOpenGLImpl::clearWithTex() {
|
||||||
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
||||||
|
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
|
|
||||||
float matrix[9];
|
|
||||||
wlr_box box = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
wlr_box box = {0, 0, m_RenderData.pMonitor->vecSize.x, m_RenderData.pMonitor->vecSize.y};
|
||||||
wlr_matrix_project_box(matrix, &box, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
|
||||||
|
|
||||||
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], matrix, 255, 0);
|
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
|
||||||
}
|
}
|
|
@ -27,6 +27,8 @@ inline const float fullVerts[] = {
|
||||||
struct SCurrentRenderData {
|
struct SCurrentRenderData {
|
||||||
SMonitor* pMonitor = nullptr;
|
SMonitor* pMonitor = nullptr;
|
||||||
float projection[9];
|
float projection[9];
|
||||||
|
|
||||||
|
pixman_region32_t* pDamage = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SMonitorRenderData {
|
struct SMonitorRenderData {
|
||||||
|
@ -41,13 +43,13 @@ public:
|
||||||
|
|
||||||
CHyprOpenGLImpl();
|
CHyprOpenGLImpl();
|
||||||
|
|
||||||
void begin(SMonitor*);
|
void begin(SMonitor*, pixman_region32_t*);
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
void renderRect(wlr_box*, const CColor&);
|
void renderRect(wlr_box*, const CColor&);
|
||||||
void renderTexture(wlr_texture*, float matrix[9], float a, int round = 0);
|
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
|
||||||
void renderTexture(const CTexture&, float matrix[9], float a, int round = 0);
|
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0);
|
||||||
void renderTextureWithBlur(const CTexture&, float matrix[9], float a, int round = 0);
|
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, int round = 0);
|
||||||
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
||||||
|
|
||||||
void makeWindowSnapshot(CWindow*);
|
void makeWindowSnapshot(CWindow*);
|
||||||
|
@ -56,6 +58,7 @@ public:
|
||||||
void clear(const CColor&);
|
void clear(const CColor&);
|
||||||
void clearWithTex();
|
void clearWithTex();
|
||||||
void scissor(const wlr_box*);
|
void scissor(const wlr_box*);
|
||||||
|
void scissor(const pixman_box32*);
|
||||||
|
|
||||||
SCurrentRenderData m_RenderData;
|
SCurrentRenderData m_RenderData;
|
||||||
|
|
||||||
|
@ -85,6 +88,10 @@ private:
|
||||||
GLuint createProgram(const std::string&, const std::string&);
|
GLuint createProgram(const std::string&, const std::string&);
|
||||||
GLuint compileShader(const GLuint&, std::string);
|
GLuint compileShader(const GLuint&, std::string);
|
||||||
void createBGTextureForMonitor(SMonitor*);
|
void createBGTextureForMonitor(SMonitor*);
|
||||||
|
|
||||||
|
void renderTextureInternal(const CTexture&, wlr_box* pBox, float a, int round = 0);
|
||||||
|
void renderTextureWithBlurInternal(const CTexture&, wlr_box*, float a, int round = 0);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
|
@ -21,26 +21,19 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||||
wlr_box windowBox;
|
wlr_box windowBox;
|
||||||
if (RDATA->surface && surface == RDATA->surface) {
|
if (RDATA->surface && surface == RDATA->surface) {
|
||||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
||||||
g_pHyprOpenGL->scissor(&windowBox);
|
|
||||||
} else {
|
} else {
|
||||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, surface->current.width, surface->current.height};
|
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, surface->current.width, surface->current.height};
|
||||||
}
|
}
|
||||||
scaleBox(&windowBox, RDATA->output->scale);
|
scaleBox(&windowBox, RDATA->output->scale);
|
||||||
|
|
||||||
const auto TRANSFORM = wlr_output_transform_invert(surface->current.transform);
|
|
||||||
float matrix[9];
|
|
||||||
wlr_matrix_project_box(matrix, &windowBox, TRANSFORM, 0, RDATA->output->transform_matrix);
|
|
||||||
|
|
||||||
if (RDATA->surface && surface == RDATA->surface)
|
if (RDATA->surface && surface == RDATA->surface)
|
||||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, matrix, RDATA->fadeAlpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"));
|
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"));
|
||||||
else
|
else
|
||||||
g_pHyprOpenGL->renderTexture(TEXTURE, matrix, RDATA->fadeAlpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"));
|
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha, RDATA->dontRound ? 0 : g_pConfigManager->getInt("decoration:rounding"));
|
||||||
|
|
||||||
wlr_surface_send_frame_done(surface, RDATA->when);
|
wlr_surface_send_frame_done(surface, RDATA->when);
|
||||||
|
|
||||||
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output);
|
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output);
|
||||||
|
|
||||||
g_pHyprOpenGL->scissor(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
||||||
|
@ -432,51 +425,52 @@ void CHyprRenderer::drawBorderForWindow(CWindow* pWindow, SMonitor* pMonitor, fl
|
||||||
g_pHyprOpenGL->renderBorder(&border, BORDERCOL, BORDERSIZE, g_pConfigManager->getInt("decoration:rounding"));
|
g_pHyprOpenGL->renderBorder(&border, BORDERCOL, BORDERSIZE, g_pConfigManager->getInt("decoration:rounding"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void damageSurfaceIter(struct wlr_surface* surface, int x, int y, void* data) {
|
void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
|
||||||
auto* renderdata = (SRenderData*)data;
|
if (!pSurface)
|
||||||
bool entire = (bool*)renderdata->data;
|
return; // wut?
|
||||||
|
|
||||||
wlr_box box = {.x = renderdata->x, .y = renderdata->y, .width = renderdata->w, .height = renderdata->h};
|
pixman_region32_t damageBox;
|
||||||
scaleBox(&box, renderdata->output->scale);
|
pixman_region32_init(&damageBox);
|
||||||
|
wlr_surface_get_effective_damage(pSurface, &damageBox);
|
||||||
|
|
||||||
pixman_region32_t damageRegion;
|
pixman_region32_translate(&damageBox, x, y);
|
||||||
pixman_region32_init(&damageRegion);
|
|
||||||
wlr_surface_get_effective_damage(renderdata->surface, &damageRegion);
|
|
||||||
wlr_region_scale(&damageRegion, &damageRegion, renderdata->output->scale);
|
|
||||||
|
|
||||||
if (std::ceil(renderdata->output->scale) > renderdata->surface->current.scale) {
|
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||||
wlr_region_expand(&damageRegion, &damageRegion, std::ceil(renderdata->output->scale) - renderdata->surface->current.scale);
|
double lx = 0, ly = 0;
|
||||||
|
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m.output, &lx, &ly);
|
||||||
|
pixman_region32_translate(&damageBox, lx, ly);
|
||||||
|
wlr_output_damage_add(m.damage, &damageBox);
|
||||||
|
pixman_region32_translate(&damageBox, -lx, -ly);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(renderdata->output);
|
pixman_region32_fini(&damageBox);
|
||||||
|
}
|
||||||
|
|
||||||
pixman_region32_translate(&damageRegion, box.x, box.y);
|
void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||||
wlr_output_damage_add(PMONITOR->damage, &damageRegion);
|
if (!pWindow->m_bIsFloating) {
|
||||||
pixman_region32_fini(&damageRegion);
|
// damage by size & pos
|
||||||
|
// TODO TEMP: revise when added shadows/etc
|
||||||
|
|
||||||
if (entire)
|
wlr_box damageBox = {pWindow->m_vPosition.x, pWindow->m_vPosition.y, pWindow->m_vSize.x, pWindow->m_vSize.y};
|
||||||
wlr_output_damage_add_box(PMONITOR->damage, &box);
|
for (auto& m : g_pCompositor->m_lMonitors)
|
||||||
|
wlr_output_damage_add_box(m.damage, &damageBox);
|
||||||
if (!wl_list_empty(&surface->current.frame_callback_list)) {
|
} else {
|
||||||
wlr_output_schedule_frame(renderdata->output);
|
// damage by real size & pos + border size * 2 (JIC)
|
||||||
|
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||||
|
wlr_box damageBox = { pWindow->m_vRealPosition.x - BORDERSIZE - 1, pWindow->m_vRealPosition.y - BORDERSIZE - 1, pWindow->m_vRealSize.x + 2 * BORDERSIZE + 2, pWindow->m_vRealSize.y + 2 * BORDERSIZE + 2};
|
||||||
|
for (auto& m : g_pCompositor->m_lMonitors)
|
||||||
|
wlr_output_damage_add_box(m.damage, &damageBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::damageSurface(SMonitor* pMonitor, double x, double y, wlr_surface* pSurface, void* data) {
|
void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
|
||||||
if (!pSurface || !pMonitor)
|
wlr_box damageBox = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
|
||||||
return; // wut?
|
wlr_output_damage_add_box(pMonitor->damage, &damageBox);
|
||||||
|
}
|
||||||
|
|
||||||
SRenderData renderData = {
|
void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||||
.output = pMonitor->output,
|
for (auto& m : g_pCompositor->m_lMonitors)
|
||||||
.x = x,
|
wlr_output_damage_add_box(m.damage, pBox);
|
||||||
.y = y,
|
|
||||||
.data = data,
|
|
||||||
.surface = pSurface,
|
|
||||||
.w = pSurface->current.width,
|
|
||||||
.h = pSurface->current.height
|
|
||||||
};
|
|
||||||
|
|
||||||
wlr_surface_for_each_surface(pSurface, damageSurfaceIter, &renderData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
|
void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
|
||||||
|
@ -489,4 +483,15 @@ void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
|
||||||
renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;
|
renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;
|
||||||
|
|
||||||
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata);
|
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& mode) {
|
||||||
|
if (mode == "full")
|
||||||
|
return DAMAGE_TRACKING_FULL;
|
||||||
|
if (mode == "monitor")
|
||||||
|
return DAMAGE_TRACKING_MONITOR;
|
||||||
|
if (mode == "none")
|
||||||
|
return DAMAGE_TRACKING_NONE;
|
||||||
|
|
||||||
|
return DAMAGE_TRACKING_INVALID;
|
||||||
}
|
}
|
|
@ -7,13 +7,26 @@
|
||||||
#include "../Window.hpp"
|
#include "../Window.hpp"
|
||||||
#include "OpenGL.hpp"
|
#include "OpenGL.hpp"
|
||||||
|
|
||||||
|
// TODO: add fuller damage tracking for updating only parts of a window
|
||||||
|
enum DAMAGETRACKINGMODES {
|
||||||
|
DAMAGE_TRACKING_INVALID = -1,
|
||||||
|
DAMAGE_TRACKING_NONE = 0,
|
||||||
|
DAMAGE_TRACKING_MONITOR,
|
||||||
|
DAMAGE_TRACKING_FULL
|
||||||
|
};
|
||||||
|
|
||||||
class CHyprRenderer {
|
class CHyprRenderer {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void renderAllClientsForMonitor(const int&, timespec*);
|
void renderAllClientsForMonitor(const int&, timespec*);
|
||||||
void outputMgrApplyTest(wlr_output_configuration_v1*, bool);
|
void outputMgrApplyTest(wlr_output_configuration_v1*, bool);
|
||||||
void arrangeLayersForMonitor(const int&);
|
void arrangeLayersForMonitor(const int&);
|
||||||
void damageSurface(SMonitor*, double, double, wlr_surface*, void*);
|
void damageSurface(wlr_surface*, double, double);
|
||||||
|
void damageWindow(CWindow*);
|
||||||
|
void damageBox(wlr_box*);
|
||||||
|
void damageMonitor(SMonitor*);
|
||||||
|
|
||||||
|
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*);
|
void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*);
|
||||||
|
|
Loading…
Reference in a new issue