diff --git a/src/renderer/AsyncResourceGatherer.cpp b/src/renderer/AsyncResourceGatherer.cpp index 8ccf864f..58a13820 100644 --- a/src/renderer/AsyncResourceGatherer.cpp +++ b/src/renderer/AsyncResourceGatherer.cpp @@ -5,6 +5,7 @@ #include #include #include "../core/hyprlock.hpp" +#include "../helpers/Log.hpp" std::mutex cvmtx; @@ -63,22 +64,37 @@ void CAsyncResourceGatherer::gather() { std::string id = std::string{"background:"} + path; + const auto TARGET = &preloadTargets.emplace_back(CAsyncResourceGatherer::SPreloadTarget{}); + + TARGET->type = TARGET_IMAGE; + TARGET->id = id; + // preload bg img const auto CAIROISURFACE = cairo_image_surface_create_from_png(path.c_str()); - const auto CAIRO = cairo_create(CAIROISURFACE); - cairo_scale(CAIRO, 1, 1); + // Make sure the img was actually loaded before generating the preload asset + if (cairo_surface_status(CAIROISURFACE) == CAIRO_STATUS_SUCCESS) { + const auto CAIRO = cairo_create(CAIROISURFACE); + cairo_scale(CAIRO, 1, 1); - const auto TARGET = &preloadTargets.emplace_back(CAsyncResourceGatherer::SPreloadTarget{}); + TARGET->size = {cairo_image_surface_get_width(CAIROISURFACE), cairo_image_surface_get_height(CAIROISURFACE)}; - TARGET->size = {cairo_image_surface_get_width(CAIROISURFACE), cairo_image_surface_get_height(CAIROISURFACE)}; - TARGET->type = TARGET_IMAGE; - TARGET->id = id; + const auto DATA = cairo_image_surface_get_data(CAIROISURFACE); + TARGET->cairo = CAIRO; + TARGET->cairosurface = CAIROISURFACE; + TARGET->data = DATA; - const auto DATA = cairo_image_surface_get_data(CAIROISURFACE); - TARGET->cairo = CAIRO; - TARGET->cairosurface = CAIROISURFACE; - TARGET->data = DATA; + TARGET->valid = true; + } else { + Debug::log(WARN, "Background image could not be loaded: {}", path); + + TARGET->size = {0, 0}; + TARGET->cairo = nullptr; + TARGET->cairosurface = nullptr; + TARGET->data = nullptr; + + TARGET->valid = false; + } } } @@ -92,10 +108,17 @@ void CAsyncResourceGatherer::apply() { std::lock_guard lg(asyncLoopState.assetsMutex); const auto ASSET = &assets[t.id]; - const auto CAIROFORMAT = cairo_image_surface_get_format((cairo_surface_t*)t.cairosurface); - 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; + // Cairo wasn't able to generate a surface for this asset during resource + // gathering. Invalidate this asset and skip generating a GL texture + if (!t.valid) { + ASSET->valid = false; + continue; + } + + const auto CAIROFORMAT = cairo_image_surface_get_format((cairo_surface_t*)t.cairosurface); + 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; ASSET->texture.m_vSize = t.size; ASSET->texture.allocate(); @@ -190,6 +213,7 @@ void CAsyncResourceGatherer::renderText(const SPreloadRequest& rq) { target.cairosurface = CAIROSURFACE; target.data = cairo_image_surface_get_data(CAIROSURFACE); target.size = {layoutWidth / PANGO_SCALE, layoutHeight / PANGO_SCALE}; + target.valid = true; preloadTargets.push_back(target); } diff --git a/src/renderer/AsyncResourceGatherer.hpp b/src/renderer/AsyncResourceGatherer.hpp index de7cf225..ed1f5339 100644 --- a/src/renderer/AsyncResourceGatherer.hpp +++ b/src/renderer/AsyncResourceGatherer.hpp @@ -13,6 +13,7 @@ struct SPreloadedAsset { CTexture texture; + bool valid; }; class CAsyncResourceGatherer { @@ -69,6 +70,7 @@ class CAsyncResourceGatherer { struct SPreloadTarget { eTargetType type = TARGET_IMAGE; std::string id = ""; + bool valid; void* data; void* cairo; @@ -81,4 +83,4 @@ class CAsyncResourceGatherer { std::unordered_map assets; void gather(); -}; \ No newline at end of file +}; diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index 11c82471..f9a276a4 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -9,6 +9,7 @@ #include #include +#include #include "Shaders.hpp" @@ -255,8 +256,8 @@ std::vector>* CRenderer::getOrCreateWidgetsFor(const CS // by type if (c.type == "background") { const std::string PATH = std::any_cast(c.values.at("path")); - widgets[surf].emplace_back( - std::make_unique(surf->size, PATH.empty() ? "" : std::string{"background:"} + PATH, std::any_cast(c.values.at("color")))); + widgets[surf].emplace_back(std::make_unique(surf->size, PATH.empty() || !std::filesystem::exists(PATH) ? "" : std::string{"background:"} + PATH, + std::any_cast(c.values.at("color")))); } else if (c.type == "input-field") { widgets[surf].emplace_back(std::make_unique(surf->size, c.values)); } else if (c.type == "label") { diff --git a/src/renderer/widgets/Background.cpp b/src/renderer/widgets/Background.cpp index fab24d3f..0895355b 100644 --- a/src/renderer/widgets/Background.cpp +++ b/src/renderer/widgets/Background.cpp @@ -7,19 +7,17 @@ CBackground::CBackground(const Vector2D& viewport_, const std::string& resourceI bool CBackground::draw(const SRenderData& data) { + // Early fallback to background color if image does not exist if (resourceID.empty()) { - CBox monbox = {0, 0, viewport.x, viewport.y}; - CColor col = color; - col.a *= data.opacity; - g_pRenderer->renderRect(monbox, col, 0); - return data.opacity < 1.0; + return draw_color_bg(data); } if (!asset) asset = g_pRenderer->asyncResourceGatherer->getAssetByID(resourceID); - if (!asset) - return false; + // Fallback to background color if texture is invalid + if (!asset || asset->valid) + return draw_color_bg(data); CBox texbox = {{}, asset->texture.m_vSize}; @@ -38,4 +36,12 @@ bool CBackground::draw(const SRenderData& data) { g_pRenderer->renderTexture(texbox, asset->texture, data.opacity); return data.opacity < 1.0; -} \ No newline at end of file +} + +bool CBackground::draw_color_bg(const SRenderData& data) { + CBox monbox = {0, 0, viewport.x, viewport.y}; + CColor col = color; + col.a *= data.opacity; + g_pRenderer->renderRect(monbox, col, 0); + return data.opacity < 1.0; +} diff --git a/src/renderer/widgets/Background.hpp b/src/renderer/widgets/Background.hpp index b736aa9e..63fca819 100644 --- a/src/renderer/widgets/Background.hpp +++ b/src/renderer/widgets/Background.hpp @@ -18,4 +18,6 @@ class CBackground : public IWidget { std::string resourceID; CColor color; SPreloadedAsset* asset = nullptr; -}; \ No newline at end of file + + bool draw_color_bg(const SRenderData& data); +};