renderer: asynchronously load background tex (#11749)
Bumps required hyprgraphics to 0.1.6 --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
parent
91f592a875
commit
4fc95d646d
16 changed files with 252 additions and 87 deletions
|
|
@ -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)));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue