summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/render')
-rw-r--r--src/render/AsyncResourceGatherer.hpp8
-rw-r--r--src/render/OpenGL.cpp124
-rw-r--r--src/render/OpenGL.hpp71
-rw-r--r--src/render/Renderer.cpp23
-rw-r--r--src/render/Renderer.hpp1
5 files changed, 151 insertions, 76 deletions
diff --git a/src/render/AsyncResourceGatherer.hpp b/src/render/AsyncResourceGatherer.hpp
new file mode 100644
index 00000000..98f7525e
--- /dev/null
+++ b/src/render/AsyncResourceGatherer.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <hyprgraphics/resource/AsyncResourceGatherer.hpp>
+#include <hyprgraphics/resource/resources/ImageResource.hpp>
+
+#include "../helpers/memory/Memory.hpp"
+
+inline UP<Hyprgraphics::CAsyncResourceGatherer> g_pAsyncResourceGatherer; \ No newline at end of file
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)));
diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp
index 9e61106b..a69ebbfe 100644
--- a/src/render/OpenGL.hpp
+++ b/src/render/OpenGL.hpp
@@ -28,6 +28,7 @@
#include <GLES2/gl2ext.h>
#include <aquamarine/buffer/Buffer.hpp>
#include <hyprutils/os/FileDescriptor.hpp>
+#include <hyprgraphics/resource/resources/ImageResource.hpp>
#include "../debug/TracyDefines.hpp"
#include "../protocols/core/Compositor.hpp"
@@ -261,13 +262,13 @@ class CHyprOpenGLImpl {
void renderOffToMain(CFramebuffer* off);
void bindBackOnMain();
+ std::string resolveAssetPath(const std::string& file);
SP<CTexture> loadAsset(const std::string& file);
+ SP<CTexture> texFromCairo(cairo_surface_t* cairo);
SP<CTexture> renderText(const std::string& text, CHyprColor col, int pt, bool italic = false, const std::string& fontFamily = "", int maxWidth = 0, int weight = 400);
void setDamage(const CRegion& damage, std::optional<CRegion> finalDamage = {});
- void ensureBackgroundTexturePresence();
-
uint32_t getPreferredReadFormat(PHLMONITOR pMonitor);
std::vector<SDRMFormat> getDRMFormats();
EGLImageKHR createEGLImage(const Aquamarine::SDMABUFAttrs& attrs);
@@ -348,38 +349,40 @@ class CHyprOpenGLImpl {
GLsizei height = 0;
} m_lastViewport;
- std::unordered_map<int, bool> m_capStatus;
-
- std::vector<SDRMFormat> m_drmFormats;
- bool m_hasModifiers = false;
-
- int m_drmFD = -1;
- std::string m_extensions;
-
- bool m_fakeFrame = false;
- bool m_applyFinalShader = false;
- bool m_blend = false;
- bool m_offloadedFramebuffer = false;
- bool m_cmSupported = true;
-
- bool m_monitorTransformEnabled = false; // do not modify directly
- std::stack<bool> m_monitorTransformStack;
- SP<CTexture> m_missingAssetTexture;
- SP<CTexture> m_backgroundTexture;
- SP<CTexture> m_lockDeadTexture;
- SP<CTexture> m_lockDead2Texture;
- SP<CTexture> m_lockTtyTextTexture;
- SShader m_finalScreenShader;
- CTimer m_globalTimer;
- GLuint m_currentProgram;
-
- void logShaderError(const GLuint&, bool program = false, bool silent = false);
- void createBGTextureForMonitor(PHLMONITOR);
- void initDRMFormats();
- void initEGL(bool gbm);
- EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
- void initAssets();
- void initMissingAssetTexture();
+ std::unordered_map<int, bool> m_capStatus;
+
+ std::vector<SDRMFormat> m_drmFormats;
+ bool m_hasModifiers = false;
+
+ int m_drmFD = -1;
+ std::string m_extensions;
+
+ bool m_fakeFrame = false;
+ bool m_applyFinalShader = false;
+ bool m_blend = false;
+ bool m_offloadedFramebuffer = false;
+ bool m_cmSupported = true;
+
+ bool m_monitorTransformEnabled = false; // do not modify directly
+ std::stack<bool> m_monitorTransformStack;
+ SP<CTexture> m_missingAssetTexture;
+ SP<CTexture> m_lockDeadTexture;
+ SP<CTexture> m_lockDead2Texture;
+ SP<CTexture> m_lockTtyTextTexture;
+ SShader m_finalScreenShader;
+ CTimer m_globalTimer;
+ GLuint m_currentProgram;
+ ASP<Hyprgraphics::CImageResource> m_backgroundResource;
+ bool m_backgroundResourceFailed = false;
+
+ void logShaderError(const GLuint&, bool program = false, bool silent = false);
+ void createBGTextureForMonitor(PHLMONITOR);
+ void initDRMFormats();
+ void initEGL(bool gbm);
+ EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
+ void initAssets();
+ void initMissingAssetTexture();
+ void requestBackgroundResource();
//
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 7efaed0e..32b571b1 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -846,8 +846,6 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
static auto PDIMSPECIAL = CConfigValue<Hyprlang::FLOAT>("decoration:dim_special");
static auto PBLURSPECIAL = CConfigValue<Hyprlang::INT>("decoration:blur:special");
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
- static auto PRENDERTEX = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_logo");
- static auto PBACKGROUNDCOLOR = CConfigValue<Hyprlang::INT>("misc:background_color");
static auto PXPMODE = CConfigValue<Hyprlang::INT>("render:xp_mode");
static auto PSESSIONLOCKXRAY = CConfigValue<Hyprlang::INT>("misc:session_lock_xray");
@@ -883,10 +881,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
if (!pWorkspace) {
// allow rendering without a workspace. In this case, just render layers.
- if (*PRENDERTEX /* inverted cfg flag */)
- m_renderPass.add(makeUnique<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(*PBACKGROUNDCOLOR)}));
- else
- g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
+ renderBackground(pMonitor);
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
renderLayer(ls.lock(), pMonitor, time);
@@ -910,10 +905,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
}
if (!*PXPMODE) {
- if (*PRENDERTEX /* inverted cfg flag */)
- m_renderPass.add(makeUnique<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(*PBACKGROUNDCOLOR)}));
- else
- g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
+ renderBackground(pMonitor);
for (auto const& ls : pMonitor->m_layerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
renderLayer(ls.lock(), pMonitor, time);
@@ -1011,6 +1003,17 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
//g_pHyprOpenGL->restoreMatrix();
}
+void CHyprRenderer::renderBackground(PHLMONITOR pMonitor) {
+ static auto PRENDERTEX = CConfigValue<Hyprlang::INT>("misc:disable_hyprland_logo");
+ static auto PBACKGROUNDCOLOR = CConfigValue<Hyprlang::INT>("misc:background_color");
+
+ if (*PRENDERTEX /* inverted cfg flag */ || pMonitor->m_backgroundOpacity->isBeingAnimated())
+ m_renderPass.add(makeUnique<CClearPassElement>(CClearPassElement::SClearData{CHyprColor(*PBACKGROUNDCOLOR)}));
+
+ if (!*PRENDERTEX)
+ g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
+}
+
void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, const Time::steady_tp& now, const CBox& geometry) {
TRACY_GPU_ZONE("RenderLockscreen");
diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp
index b1e514f3..511eeb9b 100644
--- a/src/render/Renderer.hpp
+++ b/src/render/Renderer.hpp
@@ -130,6 +130,7 @@ class CHyprRenderer {
void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything
void renderSessionLockPrimer(PHLMONITOR pMonitor);
void renderSessionLockMissing(PHLMONITOR pMonitor);
+ void renderBackground(PHLMONITOR pMonitor);
bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor);