aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/render
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-08-29 23:30:12 +0200
committerGitHub <[email protected]>2024-08-29 23:30:12 +0200
commit604eb21a7e55d85ec7f6cb8cba39fc4c20a07a9d (patch)
tree7b31fb7e21d779fee2911aa7430feed1ec3774d6 /src/render
parent92a0dd164e9cc74060b63abae67b0204b6b6074c (diff)
downloadHyprland-604eb21a7e55d85ec7f6cb8cba39fc4c20a07a9d.tar.gz
Hyprland-604eb21a7e55d85ec7f6cb8cba39fc4c20a07a9d.zip
renderer: better lockscreen dead behavior (#7574)
--------- Co-authored-by: Mihai Fufezan <[email protected]>
Diffstat (limited to 'src/render')
-rw-r--r--src/render/OpenGL.cpp119
-rw-r--r--src/render/OpenGL.hpp6
-rw-r--r--src/render/Renderer.cpp53
-rw-r--r--src/render/Renderer.hpp1
4 files changed, 152 insertions, 27 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp
index 67c11c23..91849701 100644
--- a/src/render/OpenGL.cpp
+++ b/src/render/OpenGL.cpp
@@ -338,6 +338,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
initDRMFormats();
+ initAssets();
+
static auto P = g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast<CMonitor*>(data)); });
RASSERT(eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");
@@ -2614,14 +2616,17 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const
cairo_surface_flush(CAIROSURFACE);
}
-void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) {
- const auto CAIROSURFACE = cairo_image_surface_create_from_png(texPath.c_str());
- const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE);
+SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& file) {
+ const auto CAIROSURFACE = cairo_image_surface_create_from_png(file.c_str());
- m_pBackgroundTexture = makeShared<CTexture>();
+ if (!CAIROSURFACE)
+ return nullptr;
- m_pBackgroundTexture->allocate();
- m_pBackgroundTexture->m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)};
+ const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE);
+ auto tex = makeShared<CTexture>();
+
+ tex->allocate();
+ tex->m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)};
const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ?
#ifdef GLES2
@@ -2634,7 +2639,7 @@ void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) {
const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE;
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
- glBindTexture(GL_TEXTURE_2D, m_pBackgroundTexture->m_iTexID);
+ glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#ifndef GLES2
@@ -2643,9 +2648,105 @@ void CHyprOpenGLImpl::createBackgroundTexture(const std::string& texPath) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
}
#endif
- glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, m_pBackgroundTexture->m_vSize.x, m_pBackgroundTexture->m_vSize.y, 0, glFormat, glType, DATA);
+ glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_vSize.x, tex->m_vSize.y, 0, glFormat, glType, DATA);
+
+ cairo_surface_destroy(CAIROSURFACE);
+
+ return tex;
+}
+
+SP<CTexture> CHyprOpenGLImpl::renderText(const std::string& text, CColor col, int pt, bool italic) {
+ SP<CTexture> tex = makeShared<CTexture>();
+
+ static auto FONT = CConfigValue<std::string>("misc:font_family");
+
+ const auto FONTFAMILY = *FONT;
+ const auto FONTSIZE = pt;
+ const auto COLOR = col;
+
+ auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1920, 1080 /* arbitrary, just for size */);
+ auto CAIRO = cairo_create(CAIROSURFACE);
+
+ PangoLayout* layoutText = pango_cairo_create_layout(CAIRO);
+ PangoFontDescription* pangoFD = pango_font_description_new();
+
+ pango_font_description_set_family_static(pangoFD, FONTFAMILY.c_str());
+ pango_font_description_set_absolute_size(pangoFD, FONTSIZE * PANGO_SCALE);
+ pango_font_description_set_style(pangoFD, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight(pangoFD, PANGO_WEIGHT_NORMAL);
+ pango_layout_set_font_description(layoutText, pangoFD);
+
+ cairo_set_source_rgba(CAIRO, COLOR.r, COLOR.g, COLOR.b, COLOR.a);
+
+ int textW = 0, textH = 0;
+ pango_layout_set_text(layoutText, text.c_str(), -1);
+ pango_layout_get_size(layoutText, &textW, &textH);
+ textW /= PANGO_SCALE;
+ textH /= PANGO_SCALE;
+
+ pango_font_description_free(pangoFD);
+ g_object_unref(layoutText);
+ cairo_destroy(CAIRO);
+ cairo_surface_destroy(CAIROSURFACE);
+
+ CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, textW, textH);
+ CAIRO = cairo_create(CAIROSURFACE);
+
+ layoutText = pango_cairo_create_layout(CAIRO);
+ pangoFD = pango_font_description_new();
+
+ pango_font_description_set_family_static(pangoFD, FONTFAMILY.c_str());
+ pango_font_description_set_absolute_size(pangoFD, FONTSIZE * PANGO_SCALE);
+ pango_font_description_set_style(pangoFD, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ pango_font_description_set_weight(pangoFD, PANGO_WEIGHT_NORMAL);
+ pango_layout_set_font_description(layoutText, pangoFD);
+ pango_layout_set_text(layoutText, text.c_str(), -1);
+
+ cairo_set_source_rgba(CAIRO, COLOR.r, COLOR.g, COLOR.b, COLOR.a);
+
+ cairo_move_to(CAIRO, 0, 0);
+ pango_cairo_show_layout(CAIRO, layoutText);
+
+ pango_font_description_free(pangoFD);
+ g_object_unref(layoutText);
+
+ cairo_surface_flush(CAIROSURFACE);
+
+ tex->allocate();
+ tex->m_vSize = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)};
+
+ const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
+ glBindTexture(GL_TEXTURE_2D, tex->m_iTexID);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+#ifndef GLES2
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->m_vSize.x, tex->m_vSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
+ cairo_destroy(CAIRO);
cairo_surface_destroy(CAIROSURFACE);
+
+ return tex;
+}
+
+void CHyprOpenGLImpl::initAssets() {
+ std::string assetsPath = "";
+#ifndef DATAROOTDIR
+ assetsPath = "/usr/share/hypr/";
+#else
+ assetsPath = std::format("{}{}", DATAROOTDIR, "/hypr/");
+#endif
+
+ m_pLockDeadTexture = loadAsset(assetsPath + "lockdead.png");
+ m_pLockDead2Texture = loadAsset(assetsPath + "lockdead2.png");
+
+ m_pLockTtyTextTexture = renderText(std::format("Running on tty {}",
+ g_pCompositor->m_pAqBackend->hasSession() && g_pCompositor->m_pAqBackend->session->vt > 0 ?
+ std::to_string(g_pCompositor->m_pAqBackend->session->vt) :
+ "unknown"),
+ CColor{0.9F, 0.9F, 0.9F, 0.7F}, 20, true);
}
void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
@@ -2694,7 +2795,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
return; // the texture will be empty, oh well. We'll clear with a solid color anyways.
}
- createBackgroundTexture(texPath);
+ m_pBackgroundTexture = loadAsset(texPath);
}
// create a new one with cairo
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index f405cb7c..06078a00 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -277,7 +277,7 @@ class CHyprOpenGLImpl {
CShader m_sFinalScreenShader;
CTimer m_tGlobalTimer;
- SP<CTexture> m_pBackgroundTexture;
+ SP<CTexture> m_pBackgroundTexture, m_pLockDeadTexture, m_pLockDead2Texture, m_pLockTtyTextTexture;
void logShaderError(const GLuint&, bool program = false);
GLuint createProgram(const std::string&, const std::string&, bool dynamic = false);
@@ -287,7 +287,9 @@ class CHyprOpenGLImpl {
void initDRMFormats();
void initEGL(bool gbm);
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
- void createBackgroundTexture(const std::string& path);
+ SP<CTexture> loadAsset(const std::string& file);
+ SP<CTexture> renderText(const std::string& text, CColor col, int pt, bool italic = false);
+ void initAssets();
//
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 33679731..2854a973 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -839,9 +839,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSessionLockPresent()) {
// locked with no exclusive, draw only red
- CBox boxe = {0, 0, INT16_MAX, INT16_MAX};
- const float A = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID);
- g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, A));
+ renderSessionLockMissing(pMonitor);
return;
}
@@ -1001,27 +999,50 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB
if (g_pSessionLockManager->isSessionLocked()) {
Vector2D translate = {geometry.x, geometry.y};
- float scale = (float)geometry.width / pMonitor->vecPixelSize.x;
const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID);
- if (!PSLS) {
- // locked with no surface, fill with red
- const auto ALPHA = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID);
-
- CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
- g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA));
-
- if (ALPHA < 1.f) /* animate */
- damageMonitor(pMonitor);
- else
- g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID);
- } else {
+ if (!PSLS)
+ renderSessionLockMissing(pMonitor);
+ else {
renderSessionLockSurface(PSLS, pMonitor, now);
g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID);
}
}
}
+void CHyprRenderer::renderSessionLockMissing(CMonitor* pMonitor) {
+ const auto ALPHA = g_pSessionLockManager->getRedScreenAlphaForMonitor(pMonitor->ID);
+
+ CBox monbox = {{}, pMonitor->vecPixelSize};
+
+ const bool ANY_PRESENT = g_pSessionLockManager->anySessionLockSurfacesPresent();
+
+ if (ANY_PRESENT) {
+ // render image2, without instructions. Lock still "alive", unless texture dead
+ if (g_pHyprOpenGL->m_pLockDead2Texture)
+ g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDead2Texture, &monbox, ALPHA);
+ else
+ g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA));
+ } else {
+ // render image, with instructions. Lock is gone.
+ if (g_pHyprOpenGL->m_pLockDeadTexture) {
+ g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockDeadTexture, &monbox, ALPHA);
+
+ // also render text for the tty number
+ if (g_pHyprOpenGL->m_pLockTtyTextTexture) {
+ CBox texbox = {{}, g_pHyprOpenGL->m_pLockTtyTextTexture->m_vSize};
+ g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pLockTtyTextTexture, &texbox, 1.F);
+ }
+ } else
+ g_pHyprOpenGL->renderRect(&monbox, CColor(1.0, 0.2, 0.2, ALPHA));
+ }
+
+ if (ALPHA < 1.f) /* animate */
+ damageMonitor(pMonitor);
+ else
+ g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID);
+}
+
void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface, bool main, const Vector2D& projSize, bool fixMisalignedFSV1) {
if (!pWindow || !pWindow->m_bIsX11) {
Vector2D uvTL;
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index 0b16efea..d00c0a17 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -123,6 +123,7 @@ class CHyprRenderer {
void renderWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry);
void sendFrameEventsToWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything
void renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
+ void renderSessionLockMissing(CMonitor* pMonitor);
bool commitPendingAndDoExplicitSync(CMonitor* pMonitor);