diff options
Diffstat (limited to 'src/render/OpenGL.cpp')
| -rw-r--r-- | src/render/OpenGL.cpp | 124 |
1 files changed, 92 insertions, 32 deletions
diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 66bdfa7a..3cb810e1 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -21,6 +21,7 @@ #include "../managers/input/InputManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp" #include "../helpers/fs/FsUtils.hpp" +#include "../helpers/MainLoopExecutor.hpp" #include "debug/HyprNotificationOverlay.hpp" #include "hyprerror/HyprError.hpp" #include "pass/TexPassElement.hpp" @@ -28,6 +29,7 @@ #include "pass/PreBlurElement.hpp" #include "pass/ClearPassElement.hpp" #include "render/Shader.hpp" +#include "AsyncResourceGatherer.hpp" #include <string> #include <xf86drm.h> #include <fcntl.h> @@ -2660,8 +2662,7 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const cairo_surface_flush(CAIROSURFACE); } -SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) { - +std::string CHyprOpenGLImpl::resolveAssetPath(const std::string& filename) { std::string fullPath; for (auto& e : ASSET_PATHS) { std::string p = std::string{e} + "/hypr/" + filename; @@ -2670,15 +2671,25 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) { fullPath = p; break; } else - Debug::log(LOG, "loadAsset: looking at {} unsuccessful: ec {}", filename, ec.message()); + Debug::log(LOG, "resolveAssetPath: looking at {} unsuccessful: ec {}", filename, ec.message()); } if (fullPath.empty()) { m_failedAssetsNo++; - Debug::log(ERR, "loadAsset: looking for {} failed (no provider found)", filename); - return m_missingAssetTexture; + Debug::log(ERR, "resolveAssetPath: looking for {} failed (no provider found)", filename); + return ""; } + return fullPath; +} + +SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) { + + const std::string fullPath = resolveAssetPath(filename); + + if (fullPath.empty()) + return m_missingAssetTexture; + const auto CAIROSURFACE = cairo_image_surface_create_from_png(fullPath.c_str()); if (!CAIROSURFACE) { @@ -2687,17 +2698,25 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) { return m_missingAssetTexture; } - const auto CAIROFORMAT = cairo_image_surface_get_format(CAIROSURFACE); + auto tex = texFromCairo(CAIROSURFACE); + + cairo_surface_destroy(CAIROSURFACE); + + return tex; +} + +SP<CTexture> CHyprOpenGLImpl::texFromCairo(cairo_surface_t* cairo) { + const auto CAIROFORMAT = cairo_image_surface_get_format(cairo); auto tex = makeShared<CTexture>(); tex->allocate(); - tex->m_size = {cairo_image_surface_get_width(CAIROSURFACE), cairo_image_surface_get_height(CAIROSURFACE)}; + tex->m_size = {cairo_image_surface_get_width(cairo), cairo_image_surface_get_height(cairo)}; const GLint glIFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB32F : GL_RGBA; const GLint glFormat = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_RGB : GL_RGBA; const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; - const auto DATA = cairo_image_surface_get_data(CAIROSURFACE); + const auto DATA = cairo_image_surface_get_data(cairo); tex->bind(); tex->setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR); tex->setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -2709,8 +2728,6 @@ SP<CTexture> CHyprOpenGLImpl::loadAsset(const std::string& filename) { glTexImage2D(GL_TEXTURE_2D, 0, glIFormat, tex->m_size.x, tex->m_size.y, 0, glFormat, glType, DATA); - cairo_surface_destroy(CAIROSURFACE); - return tex; } @@ -2847,8 +2864,6 @@ void CHyprOpenGLImpl::initAssets() { initMissingAssetTexture(); m_screencopyDeniedTexture = renderText("Permission denied to share screen", Colors::WHITE, 20); - - ensureBackgroundTexturePresence(); } void CHyprOpenGLImpl::ensureLockTexturesRendered(bool load) { @@ -2874,18 +2889,22 @@ void CHyprOpenGLImpl::ensureLockTexturesRendered(bool load) { } } -void CHyprOpenGLImpl::ensureBackgroundTexturePresence() { +void CHyprOpenGLImpl::requestBackgroundResource() { + if (m_backgroundResource) + return; + static auto PNOWALLPAPER = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_logo"); static auto PFORCEWALLPAPER = CConfigValue<Hyprlang::INT>("misc:force_default_wallpaper"); const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, sc<int64_t>(-1), sc<int64_t>(2)); if (*PNOWALLPAPER) - m_backgroundTexture.reset(); - else if (!m_backgroundTexture) { - // create the default background texture - std::string texPath = "wall"; + return; + static bool once = true; + static std::string texPath = "wall"; + + if (once) { // get the adequate tex if (FORCEWALLPAPER == -1) { std::mt19937_64 engine(time(nullptr)); @@ -2897,8 +2916,31 @@ void CHyprOpenGLImpl::ensureBackgroundTexturePresence() { texPath += ".png"; - m_backgroundTexture = loadAsset(texPath); + texPath = resolveAssetPath(texPath); + + once = false; + } + + if (texPath.empty()) { + m_backgroundResourceFailed = true; + return; } + + m_backgroundResource = makeAtomicShared<Hyprgraphics::CImageResource>(texPath); + + // doesn't have to be ASP as it's passed + SP<CMainLoopExecutor> executor = makeShared<CMainLoopExecutor>([] { + for (const auto& m : g_pCompositor->m_monitors) { + g_pHyprRenderer->damageMonitor(m); + } + }); + + m_backgroundResource->m_events.finished.listenStatic([executor] { + // this is in the worker thread. + executor->signal(); + }); + + g_pAsyncResourceGatherer->enqueue(m_backgroundResource); } void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { @@ -2909,7 +2951,16 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { static auto PRENDERTEX = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_logo"); static auto PNOSPLASH = CConfigValue<Hyprlang::INT>("misc:disable_splash_rendering"); - if (*PRENDERTEX) + if (*PRENDERTEX || m_backgroundResourceFailed) + return; + + if (!m_backgroundResource) { + // queue the asset to be created + requestBackgroundResource(); + return; + } + + if (!m_backgroundResource->m_ready) return; // release the last tex if exists @@ -2918,9 +2969,6 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { PFB->alloc(pMonitor->m_pixelSize.x, pMonitor->m_pixelSize.y, pMonitor->m_output->state->state().drmFormat); - if (!m_backgroundTexture) // ?!?!?! - return; - // create a new one with cairo SP<CTexture> tex = makeShared<CTexture>(); @@ -2966,23 +3014,25 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { blend(true); clear(CHyprColor{0, 0, 0, 1}); + SP<CTexture> backgroundTexture = texFromCairo(m_backgroundResource->m_asset.cairoSurface->cairo()); + // first render the background - if (m_backgroundTexture) { + if (backgroundTexture) { const double MONRATIO = m_renderData.pMonitor->m_transformedSize.x / m_renderData.pMonitor->m_transformedSize.y; - const double WPRATIO = m_backgroundTexture->m_size.x / m_backgroundTexture->m_size.y; + const double WPRATIO = backgroundTexture->m_size.x / backgroundTexture->m_size.y; Vector2D origin; double scale = 1.0; if (MONRATIO > WPRATIO) { - scale = m_renderData.pMonitor->m_transformedSize.x / m_backgroundTexture->m_size.x; - origin.y = (m_renderData.pMonitor->m_transformedSize.y - m_backgroundTexture->m_size.y * scale) / 2.0; + scale = m_renderData.pMonitor->m_transformedSize.x / backgroundTexture->m_size.x; + origin.y = (m_renderData.pMonitor->m_transformedSize.y - backgroundTexture->m_size.y * scale) / 2.0; } else { - scale = m_renderData.pMonitor->m_transformedSize.y / m_backgroundTexture->m_size.y; - origin.x = (m_renderData.pMonitor->m_transformedSize.x - m_backgroundTexture->m_size.x * scale) / 2.0; + scale = m_renderData.pMonitor->m_transformedSize.y / backgroundTexture->m_size.y; + origin.x = (m_renderData.pMonitor->m_transformedSize.x - backgroundTexture->m_size.x * scale) / 2.0; } - CBox texbox = CBox{origin, m_backgroundTexture->m_size * scale}; - renderTextureInternal(m_backgroundTexture, texbox, {.damage = &fakeDamage, .a = 1.0}); + CBox texbox = CBox{origin, backgroundTexture->m_size * scale}; + renderTextureInternal(backgroundTexture, texbox, {.damage = &fakeDamage, .a = 1.0}); } CBox monbox = {{}, pMonitor->m_pixelSize}; @@ -2993,21 +3043,31 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(PHLMONITOR pMonitor) { m_renderData.currentFB->bind(); Debug::log(LOG, "Background created for monitor {}", pMonitor->m_name); + + // clear the resource after we're done using it + g_pEventLoopManager->doLater([this] { m_backgroundResource.reset(); }); + + // set the animation to start for fading this background in nicely + pMonitor->m_backgroundOpacity->setValueAndWarp(0.F); + *pMonitor->m_backgroundOpacity = 1.F; } void CHyprOpenGLImpl::clearWithTex() { RASSERT(m_renderData.pMonitor, "Tried to render BGtex without begin()!"); - auto TEXIT = m_monitorBGFBs.find(m_renderData.pMonitor); + static auto PBACKGROUNDCOLOR = CConfigValue<Hyprlang::INT>("misc:background_color"); + + auto TEXIT = m_monitorBGFBs.find(m_renderData.pMonitor); if (TEXIT == m_monitorBGFBs.end()) { createBGTextureForMonitor(m_renderData.pMonitor.lock()); - TEXIT = m_monitorBGFBs.find(m_renderData.pMonitor); + g_pHyprRenderer->m_renderPass.add(makeUnique<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(*PBACKGROUNDCOLOR)})); } if (TEXIT != m_monitorBGFBs.end()) { CTexPassElement::SRenderData data; data.box = {0, 0, m_renderData.pMonitor->m_transformedSize.x, m_renderData.pMonitor->m_transformedSize.y}; + data.a = m_renderData.pMonitor->m_backgroundOpacity->value(); data.flipEndFrame = true; data.tex = TEXIT->second.getTexture(); g_pHyprRenderer->m_renderPass.add(makeUnique<CTexPassElement>(std::move(data))); |
