2024-02-18 23:08:03 +00:00
|
|
|
#include "LockSurface.hpp"
|
|
|
|
|
#include "hyprlock.hpp"
|
|
|
|
|
#include "Egl.hpp"
|
2025-01-06 12:34:21 +00:00
|
|
|
#include "../config/ConfigManager.hpp"
|
|
|
|
|
#include "../core/AnimationManager.hpp"
|
|
|
|
|
#include "../helpers/Log.hpp"
|
2024-02-18 23:08:03 +00:00
|
|
|
#include "../renderer/Renderer.hpp"
|
|
|
|
|
|
|
|
|
|
CSessionLockSurface::~CSessionLockSurface() {
|
2024-04-19 19:48:11 +01:00
|
|
|
if (eglWindow)
|
|
|
|
|
wl_egl_window_destroy(eglWindow);
|
2024-02-18 23:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
2025-03-05 08:35:43 +01:00
|
|
|
CSessionLockSurface::CSessionLockSurface(const SP<COutput>& pOutput) : m_outputRef(pOutput), m_outputID(pOutput->m_ID) {
|
2024-12-29 18:36:08 +00:00
|
|
|
surface = makeShared<CCWlSurface>(g_pHyprlock->getCompositor()->sendCreateSurface());
|
2025-03-05 08:35:43 +01:00
|
|
|
RASSERT(surface, "Couldn't create wl_surface");
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2025-01-29 22:10:27 +00:00
|
|
|
static const auto FRACTIONALSCALING = g_pConfigManager->getValue<Hyprlang::INT>("general:fractional_scaling");
|
|
|
|
|
const auto ENABLE_FSV1 = *FRACTIONALSCALING == 1 || /* auto enable */ (*FRACTIONALSCALING == 2);
|
|
|
|
|
const auto PFRACTIONALMGR = g_pHyprlock->getFractionalMgr();
|
|
|
|
|
const auto PVIEWPORTER = g_pHyprlock->getViewporter();
|
2024-08-05 20:22:01 +02:00
|
|
|
|
|
|
|
|
if (ENABLE_FSV1 && PFRACTIONALMGR && PVIEWPORTER) {
|
2024-12-29 18:36:08 +00:00
|
|
|
fractional = makeShared<CCWpFractionalScaleV1>(PFRACTIONALMGR->sendGetFractionalScale(surface->resource()));
|
|
|
|
|
|
|
|
|
|
fractional->setPreferredScale([this](CCWpFractionalScaleV1*, uint32_t scale) {
|
|
|
|
|
const bool SAMESCALE = fractionalScale == scale / 120.0;
|
|
|
|
|
fractionalScale = scale / 120.0;
|
|
|
|
|
|
|
|
|
|
Debug::log(LOG, "Got fractional scale: {:.1f}%", fractionalScale * 100.F);
|
|
|
|
|
|
|
|
|
|
if (!SAMESCALE && readyForFrame)
|
|
|
|
|
onScaleUpdate();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
viewport = makeShared<CCWpViewport>(PVIEWPORTER->sendGetViewport(surface->resource()));
|
2024-07-07 21:44:53 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-05 20:22:01 +02:00
|
|
|
if (!PFRACTIONALMGR)
|
2024-02-18 23:08:03 +00:00
|
|
|
Debug::log(LOG, "No fractional-scale support! Oops, won't be able to scale!");
|
2024-07-07 21:44:53 +02:00
|
|
|
if (!PVIEWPORTER)
|
|
|
|
|
Debug::log(LOG, "No viewporter support! Oops, won't be able to scale!");
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2025-03-05 08:35:43 +01:00
|
|
|
lockSurface = makeShared<CCExtSessionLockSurfaceV1>(g_pHyprlock->getSessionLock()->sendGetLockSurface(surface->resource(), pOutput->m_wlOutput->resource()));
|
2025-03-30 01:33:34 +01:00
|
|
|
RASSERT(lockSurface, "Couldn't create ext_session_lock_surface_v1");
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2024-12-29 18:36:08 +00:00
|
|
|
lockSurface->setConfigure([this](CCExtSessionLockSurfaceV1* r, uint32_t serial, uint32_t width, uint32_t height) { configure({(double)width, (double)height}, serial); });
|
2024-02-18 23:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) {
|
2024-02-19 02:39:57 +00:00
|
|
|
Debug::log(LOG, "configure with serial {}", serial_);
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2024-08-05 20:22:01 +02:00
|
|
|
const bool SAMESERIAL = serial == serial_;
|
2024-08-18 07:19:56 +00:00
|
|
|
const bool SAMESIZE = logicalSize == size_;
|
|
|
|
|
const bool SAMESCALE = appliedScale == fractionalScale;
|
2024-05-02 15:18:17 +01:00
|
|
|
|
2025-03-05 08:35:43 +01:00
|
|
|
const auto POUTPUT = m_outputRef.lock();
|
|
|
|
|
|
2024-08-18 07:19:56 +00:00
|
|
|
serial = serial_;
|
|
|
|
|
logicalSize = size_;
|
|
|
|
|
appliedScale = fractionalScale;
|
2024-02-20 16:16:40 +00:00
|
|
|
|
2024-07-07 11:55:59 -04:00
|
|
|
if (fractional) {
|
|
|
|
|
size = (size_ * fractionalScale).floor();
|
2024-12-29 18:36:08 +00:00
|
|
|
viewport->sendSetDestination(logicalSize.x, logicalSize.y);
|
|
|
|
|
surface->sendSetBufferScale(1);
|
2024-07-07 11:55:59 -04:00
|
|
|
} else {
|
2025-03-05 08:35:43 +01:00
|
|
|
size = size_ * POUTPUT->scale;
|
|
|
|
|
surface->sendSetBufferScale(POUTPUT->scale);
|
2024-07-07 11:55:59 -04:00
|
|
|
}
|
|
|
|
|
|
2024-08-05 20:22:01 +02:00
|
|
|
if (!SAMESERIAL)
|
2024-12-29 18:36:08 +00:00
|
|
|
lockSurface->sendAckConfigure(serial);
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2024-08-05 20:22:01 +02:00
|
|
|
Debug::log(LOG, "Configuring surface for logical {} and pixel {}", logicalSize, size);
|
|
|
|
|
|
2024-12-29 18:36:08 +00:00
|
|
|
surface->sendDamageBuffer(0, 0, 0xFFFF, 0xFFFF);
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2024-07-07 11:55:59 -04:00
|
|
|
if (!eglWindow) {
|
2024-12-29 18:36:08 +00:00
|
|
|
eglWindow = wl_egl_window_create((wl_surface*)surface->resource(), size.x, size.y);
|
2025-03-30 01:33:34 +01:00
|
|
|
RASSERT(eglWindow, "Couldn't create eglWindow");
|
2024-07-07 11:55:59 -04:00
|
|
|
} else
|
2024-02-18 23:08:03 +00:00
|
|
|
wl_egl_window_resize(eglWindow, size.x, size.y, 0, 0);
|
|
|
|
|
|
|
|
|
|
if (!eglSurface) {
|
2024-07-07 11:55:59 -04:00
|
|
|
eglSurface = g_pEGL->eglCreatePlatformWindowSurfaceEXT(g_pEGL->eglDisplay, g_pEGL->eglConfig, eglWindow, nullptr);
|
2025-03-30 01:33:34 +01:00
|
|
|
RASSERT(eglSurface, "Couldn't create eglSurface");
|
2024-02-18 23:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-18 07:19:56 +00:00
|
|
|
if (readyForFrame && !(SAMESIZE && SAMESCALE)) {
|
2025-03-05 08:35:43 +01:00
|
|
|
Debug::log(LOG, "output {} changed, reloading widgets!", POUTPUT->stringPort);
|
|
|
|
|
g_pRenderer->reconfigureWidgetsFor(POUTPUT->m_ID);
|
2024-08-18 07:19:56 +00:00
|
|
|
}
|
|
|
|
|
|
2024-02-18 23:08:03 +00:00
|
|
|
readyForFrame = true;
|
|
|
|
|
|
2024-02-21 16:56:25 +00:00
|
|
|
render();
|
2024-02-18 23:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-02 15:17:04 +01:00
|
|
|
void CSessionLockSurface::onScaleUpdate() {
|
2024-05-03 13:21:51 +01:00
|
|
|
configure(logicalSize, serial);
|
2024-05-02 15:17:04 +01:00
|
|
|
}
|
|
|
|
|
|
2024-02-18 23:08:03 +00:00
|
|
|
void CSessionLockSurface::render() {
|
2024-06-26 20:31:15 +02:00
|
|
|
if (frameCallback || !readyForFrame) {
|
|
|
|
|
needsFrame = true;
|
2024-02-26 18:25:52 +00:00
|
|
|
return;
|
2024-06-26 20:31:15 +02:00
|
|
|
}
|
2024-02-26 18:25:52 +00:00
|
|
|
|
2025-01-06 12:34:21 +00:00
|
|
|
g_pAnimationManager->tick();
|
2024-02-18 23:08:03 +00:00
|
|
|
const auto FEEDBACK = g_pRenderer->renderLock(*this);
|
2024-12-29 18:36:08 +00:00
|
|
|
frameCallback = makeShared<CCWlCallback>(surface->sendFrame());
|
2025-01-21 13:42:11 +00:00
|
|
|
frameCallback->setDone([this](CCWlCallback* r, uint32_t frameTime) {
|
2024-12-29 18:36:08 +00:00
|
|
|
if (g_pHyprlock->m_bTerminate)
|
|
|
|
|
return;
|
|
|
|
|
|
2025-03-05 08:35:43 +01:00
|
|
|
if (Debug::verbose) {
|
|
|
|
|
const auto POUTPUT = m_outputRef.lock();
|
|
|
|
|
Debug::log(TRACE, "[{}] frame {}, Current fps: {:.2f}", POUTPUT->stringPort, m_frames, 1000.f / (frameTime - m_lastFrameTime));
|
|
|
|
|
}
|
2025-01-21 13:42:11 +00:00
|
|
|
|
|
|
|
|
m_lastFrameTime = frameTime;
|
|
|
|
|
|
|
|
|
|
m_frames++;
|
|
|
|
|
|
2024-12-29 18:36:08 +00:00
|
|
|
onCallback();
|
|
|
|
|
});
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2024-02-21 16:56:25 +00:00
|
|
|
eglSwapBuffers(g_pEGL->eglDisplay, eglSurface);
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2025-01-06 12:34:21 +00:00
|
|
|
needsFrame = FEEDBACK.needsFrame || g_pAnimationManager->shouldTickForNext();
|
2024-02-18 23:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CSessionLockSurface::onCallback() {
|
2024-12-29 18:36:08 +00:00
|
|
|
frameCallback.reset();
|
2024-02-18 23:08:03 +00:00
|
|
|
|
2024-07-07 11:55:59 -04:00
|
|
|
if (needsFrame && !g_pHyprlock->m_bTerminate && g_pEGL) {
|
|
|
|
|
needsFrame = false;
|
2024-02-18 23:08:03 +00:00
|
|
|
render();
|
2024-07-07 11:55:59 -04:00
|
|
|
}
|
2025-02-06 16:36:08 +05:00
|
|
|
}
|