renderer: fix uv calculations once and for all (#11770)
fixes synchronization of ackd sizes, fixes wrong xdg stuff
This commit is contained in:
parent
41dad38177
commit
26cbc67385
8 changed files with 85 additions and 48 deletions
|
|
@ -62,9 +62,10 @@ bool CWLSurface::small() const {
|
|||
if (!m_resource->m_current.texture)
|
||||
return false;
|
||||
|
||||
const auto O = m_windowOwner.lock();
|
||||
const auto O = m_windowOwner.lock();
|
||||
const auto REPORTED_SIZE = O->getReportedSize();
|
||||
|
||||
return O->m_reportedSize.x > m_resource->m_current.size.x + 1 || O->m_reportedSize.y > m_resource->m_current.size.y + 1;
|
||||
return REPORTED_SIZE.x > m_resource->m_current.size.x + 1 || REPORTED_SIZE.y > m_resource->m_current.size.y + 1;
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVec() const {
|
||||
|
|
@ -73,8 +74,9 @@ Vector2D CWLSurface::correctSmallVec() const {
|
|||
|
||||
const auto SIZE = getViewporterCorrectedSize();
|
||||
const auto O = m_windowOwner.lock();
|
||||
const auto REP = O->getReportedSize();
|
||||
|
||||
return Vector2D{(O->m_reportedSize.x - SIZE.x) / 2, (O->m_reportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_realSize->value() / O->m_reportedSize);
|
||||
return Vector2D{(REP.x - SIZE.x) / 2, (REP.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_realSize->value() / REP);
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVecBuf() const {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "../managers/TokenManager.hpp"
|
||||
#include "../managers/animation/AnimationManager.hpp"
|
||||
#include "../managers/ANRManager.hpp"
|
||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "../protocols/XDGShell.hpp"
|
||||
#include "../protocols/core/Compositor.hpp"
|
||||
#include "../protocols/core/Subcompositor.hpp"
|
||||
|
|
@ -576,7 +577,12 @@ void CWindow::onMap() {
|
|||
if (!m_isMapped || isX11OverrideRedirect())
|
||||
return;
|
||||
|
||||
sendWindowSize();
|
||||
g_pEventLoopManager->doLater([this, self = m_self] {
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
sendWindowSize();
|
||||
});
|
||||
},
|
||||
false);
|
||||
|
||||
|
|
@ -1549,13 +1555,20 @@ std::string CWindow::fetchClass() {
|
|||
}
|
||||
|
||||
void CWindow::onAck(uint32_t serial) {
|
||||
const auto SERIAL = std::ranges::find_if(m_pendingSizeAcks | std::views::reverse, [serial](const auto& e) { return e.first == serial; });
|
||||
const auto SERIAL = std::ranges::find_if(m_pendingSizeAcks | std::views::reverse, [serial](const auto& e) { return e.first <= serial; });
|
||||
|
||||
if (SERIAL == m_pendingSizeAcks.rend())
|
||||
return;
|
||||
|
||||
m_pendingSizeAck = *SERIAL;
|
||||
std::erase_if(m_pendingSizeAcks, [&](const auto& el) { return el.first <= SERIAL->first; });
|
||||
|
||||
if (m_isX11)
|
||||
return;
|
||||
|
||||
m_wlSurface->resource()->m_pending.ackedSize = m_pendingSizeAck->second; // apply pending size. We pinged, the window ponged.
|
||||
m_wlSurface->resource()->m_pending.updated.bits.acked = true;
|
||||
m_pendingSizeAck.reset();
|
||||
}
|
||||
|
||||
void CWindow::onResourceChangeX11() {
|
||||
|
|
@ -1805,7 +1818,7 @@ void CWindow::sendWindowSize(bool force) {
|
|||
if (m_isX11 && m_xwaylandSurface)
|
||||
m_xwaylandSurface->configure({REPORTPOS, REPORTSIZE});
|
||||
else if (m_xdgSurface && m_xdgSurface->m_toplevel)
|
||||
m_pendingSizeAcks.emplace_back(m_xdgSurface->m_toplevel->setSize(REPORTSIZE), REPORTPOS.floor());
|
||||
m_pendingSizeAcks.emplace_back(m_xdgSurface->m_toplevel->setSize(REPORTSIZE), REPORTSIZE.floor());
|
||||
}
|
||||
|
||||
NContentType::eContentType CWindow::getContentType() {
|
||||
|
|
@ -1910,3 +1923,11 @@ SP<CWLSurfaceResource> CWindow::getSolitaryResource() {
|
|||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Vector2D CWindow::getReportedSize() {
|
||||
if (m_isX11)
|
||||
return m_reportedSize;
|
||||
if (m_wlSurface && m_wlSurface->resource())
|
||||
return m_wlSurface->resource()->m_current.ackedSize;
|
||||
return m_reportedSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -416,6 +416,7 @@ class CWindow {
|
|||
PHLWINDOW parent();
|
||||
bool priorityFocus();
|
||||
SP<CWLSurfaceResource> getSolitaryResource();
|
||||
Vector2D getReportedSize();
|
||||
|
||||
CBox getWindowMainSurfaceBox() const {
|
||||
return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y};
|
||||
|
|
|
|||
|
|
@ -868,7 +868,8 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
|||
if (!PWINDOW->m_isMapped || PWINDOW->isHidden())
|
||||
return;
|
||||
|
||||
PWINDOW->m_reportedSize = PWINDOW->m_pendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||
if (PWINDOW->m_isX11)
|
||||
PWINDOW->m_reportedSize = PWINDOW->m_pendingReportedSize;
|
||||
|
||||
if (!PWINDOW->m_isX11 && !PWINDOW->isFullscreen() && PWINDOW->m_isFloating) {
|
||||
const auto MINSIZE = PWINDOW->m_xdgSurface->m_toplevel->layoutMinSize();
|
||||
|
|
|
|||
|
|
@ -97,4 +97,7 @@ void SSurfaceState::updateFrom(SSurfaceState& ref) {
|
|||
|
||||
if (ref.updated.bits.acquire)
|
||||
acquire = ref.acquire;
|
||||
|
||||
if (ref.updated.bits.acked)
|
||||
ackedSize = ref.ackedSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ struct SSurfaceState {
|
|||
bool offset : 1;
|
||||
bool viewport : 1;
|
||||
bool acquire : 1;
|
||||
bool acked : 1;
|
||||
} bits;
|
||||
} updated;
|
||||
|
||||
|
|
@ -37,6 +38,9 @@ struct SSurfaceState {
|
|||
Vector2D size, bufferSize;
|
||||
Vector2D offset;
|
||||
|
||||
// for xdg_shell resizing
|
||||
Vector2D ackedSize;
|
||||
|
||||
// viewporter protocol surface state
|
||||
struct {
|
||||
bool hasDestination = false;
|
||||
|
|
|
|||
|
|
@ -1126,15 +1126,25 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResour
|
|||
if (*PEXPANDEDGES) {
|
||||
const auto MONITOR_WL_SCALE = std::ceil(pMonitor->m_scale);
|
||||
const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->m_current.scale && !pSurface->m_current.viewport.hasDestination;
|
||||
const auto EXPECTED_SIZE =
|
||||
((pSurface->m_current.viewport.hasDestination ? pSurface->m_current.viewport.destination : pSurface->m_current.bufferSize / pSurface->m_current.scale) *
|
||||
pMonitor->m_scale)
|
||||
.round();
|
||||
if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) {
|
||||
// this will not work with shm AFAIK, idk why.
|
||||
// NOTE: this math is wrong if we have a source... or geom updates later, but I don't think we can do much
|
||||
const auto FIX = (projSize / EXPECTED_SIZE).clamp(Vector2D{1, 1}, Vector2D{1000000, 1000000});
|
||||
uvBR = uvBR * FIX;
|
||||
const auto EXPECTED_SIZE = ((pSurface->m_current.viewport.hasDestination ?
|
||||
pSurface->m_current.viewport.destination :
|
||||
(pSurface->m_current.viewport.hasSource ? pSurface->m_current.viewport.source.size() / pSurface->m_current.scale : projSize)) *
|
||||
pMonitor->m_scale)
|
||||
.round();
|
||||
|
||||
const auto RATIO = projSize / EXPECTED_SIZE;
|
||||
if (!SCALE_UNAWARE) {
|
||||
if (*PEXPANDEDGES && !SCALE_UNAWARE && (RATIO.x > 1 || RATIO.y > 1)) {
|
||||
const auto FIX = RATIO.clamp(Vector2D{1, 1}, Vector2D{1000000, 1000000});
|
||||
uvBR = uvBR * FIX;
|
||||
}
|
||||
|
||||
// FIXME: probably do this for in anims on all views...
|
||||
const auto SHOULD_SKIP = !pWindow || pWindow->m_animatingIn;
|
||||
if (!SHOULD_SKIP && (RATIO.x < 1 || RATIO.y < 1)) {
|
||||
const auto FIX = RATIO.clamp(Vector2D{0.0001, 0.0001}, Vector2D{1, 1});
|
||||
uvBR = uvBR * FIX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1150,32 +1160,21 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResour
|
|||
if (!main || !pWindow)
|
||||
return;
|
||||
|
||||
CBox geom = pWindow->m_xdgSurface->m_current.geometry;
|
||||
// FIXME: this doesn't work. We always set MAXIMIZED anyways, so this doesn't need to work, but it's problematic.
|
||||
|
||||
// Adjust UV based on the xdg_surface geometry
|
||||
if (geom.x != 0 || geom.y != 0 || geom.w != 0 || geom.h != 0) {
|
||||
const auto XPERC = geom.x / pSurface->m_current.size.x;
|
||||
const auto YPERC = geom.y / pSurface->m_current.size.y;
|
||||
const auto WPERC = (geom.x + geom.w ? geom.w : pSurface->m_current.size.x) / pSurface->m_current.size.x;
|
||||
const auto HPERC = (geom.y + geom.h ? geom.h : pSurface->m_current.size.y) / pSurface->m_current.size.y;
|
||||
// CBox geom = pWindow->m_xdgSurface->m_current.geometry;
|
||||
|
||||
const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y));
|
||||
uvBR = uvBR - Vector2D((1.0 - WPERC) * (uvBR.x - uvTL.x), (1.0 - HPERC) * (uvBR.y - uvTL.y));
|
||||
uvTL = uvTL + TOADDTL;
|
||||
}
|
||||
// // Adjust UV based on the xdg_surface geometry
|
||||
// if (geom.x != 0 || geom.y != 0 || geom.w != 0 || geom.h != 0) {
|
||||
// const auto XPERC = geom.x / pSurface->m_current.size.x;
|
||||
// const auto YPERC = geom.y / pSurface->m_current.size.y;
|
||||
// const auto WPERC = (geom.x + geom.w ? geom.w : pSurface->m_current.size.x) / pSurface->m_current.size.x;
|
||||
// const auto HPERC = (geom.y + geom.h ? geom.h : pSurface->m_current.size.y) / pSurface->m_current.size.y;
|
||||
|
||||
// Adjust UV based on our animation progress
|
||||
if (pSurface->m_current.size.x > projSizeUnscaled.x || pSurface->m_current.size.y > projSizeUnscaled.y) {
|
||||
auto maxSize = projSizeUnscaled;
|
||||
|
||||
if (pWindow->m_wlSurface->small() && !pWindow->m_wlSurface->m_fillIgnoreSmall)
|
||||
maxSize = pWindow->m_wlSurface->getViewporterCorrectedSize();
|
||||
|
||||
if (pSurface->m_current.size.x > maxSize.x)
|
||||
uvBR.x = uvBR.x * (maxSize.x / pSurface->m_current.size.x);
|
||||
if (pSurface->m_current.size.y > maxSize.y)
|
||||
uvBR.y = uvBR.y * (maxSize.y / pSurface->m_current.size.y);
|
||||
}
|
||||
// const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y));
|
||||
// uvBR = uvBR - Vector2D((1.0 - WPERC) * (uvBR.x - uvTL.x), (1.0 - HPERC) * (uvBR.y - uvTL.y));
|
||||
// uvTL = uvTL + TOADDTL;
|
||||
// }
|
||||
|
||||
g_pHyprOpenGL->m_renderData.primarySurfaceUVTopLeft = uvTL;
|
||||
g_pHyprOpenGL->m_renderData.primarySurfaceUVBottomRight = uvBR;
|
||||
|
|
|
|||
|
|
@ -174,27 +174,33 @@ CBox CSurfacePassElement::getTexBox() {
|
|||
|
||||
// center the surface if it's smaller than the viewport we assign it
|
||||
if (PSURFACE && !PSURFACE->m_fillIgnoreSmall && PSURFACE->small() /* guarantees PWINDOW */) {
|
||||
const auto CORRECT = PSURFACE->correctSmallVec();
|
||||
const auto SIZE = PSURFACE->getViewporterCorrectedSize();
|
||||
const auto CORRECT = PSURFACE->correctSmallVec();
|
||||
const auto SIZE = PSURFACE->getViewporterCorrectedSize();
|
||||
const auto REPORTED = PWINDOW->getReportedSize();
|
||||
|
||||
if (!INTERACTIVERESIZEINPROGRESS) {
|
||||
windowBox.translate(CORRECT);
|
||||
|
||||
windowBox.width = SIZE.x * (PWINDOW->m_realSize->value().x / PWINDOW->m_reportedSize.x);
|
||||
windowBox.height = SIZE.y * (PWINDOW->m_realSize->value().y / PWINDOW->m_reportedSize.y);
|
||||
windowBox.width = SIZE.x * (PWINDOW->m_realSize->value().x / REPORTED.x);
|
||||
windowBox.height = SIZE.y * (PWINDOW->m_realSize->value().y / REPORTED.y);
|
||||
} else {
|
||||
windowBox.width = SIZE.x;
|
||||
windowBox.height = SIZE.y;
|
||||
}
|
||||
}
|
||||
|
||||
} else { // here we clamp to 2, these might be some tiny specks
|
||||
windowBox = {sc<int>(outputX) + m_data.pos.x + m_data.localPos.x, sc<int>(outputY) + m_data.pos.y + m_data.localPos.y,
|
||||
std::max(sc<float>(m_data.surface->m_current.size.x), 2.F), std::max(sc<float>(m_data.surface->m_current.size.y), 2.F)};
|
||||
|
||||
const auto SURFSIZE = m_data.surface->m_current.size;
|
||||
|
||||
windowBox = {sc<int>(outputX) + m_data.pos.x + m_data.localPos.x, sc<int>(outputY) + m_data.pos.y + m_data.localPos.y, std::max(sc<float>(SURFSIZE.x), 2.F),
|
||||
std::max(sc<float>(SURFSIZE.y), 2.F)};
|
||||
if (m_data.pWindow && m_data.pWindow->m_realSize->isBeingAnimated() && m_data.surface && !m_data.mainSurface && m_data.squishOversized /* subsurface */) {
|
||||
// adjust subsurfaces to the window
|
||||
windowBox.width = (windowBox.width / m_data.pWindow->m_reportedSize.x) * m_data.pWindow->m_realSize->value().x;
|
||||
windowBox.height = (windowBox.height / m_data.pWindow->m_reportedSize.y) * m_data.pWindow->m_realSize->value().y;
|
||||
const auto REPORTED = m_data.pWindow->getReportedSize();
|
||||
if (REPORTED.x != 0 && REPORTED.y != 0) {
|
||||
windowBox.width = (windowBox.width / REPORTED.x) * m_data.pWindow->m_realSize->value().x;
|
||||
windowBox.height = (windowBox.height / REPORTED.y) * m_data.pWindow->m_realSize->value().y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue