mirror of
https://github.com/hyprwm/hyprlock.git
synced 2026-01-06 01:00:11 +01:00
don't render within onAssetUpdate to avoid duplicate renders
another much improvement for multi monitor setups. allows updating within the same frame for most labels.
This commit is contained in:
parent
4734f8bcd4
commit
b4b6eb7718
12 changed files with 57 additions and 55 deletions
|
|
@ -44,14 +44,14 @@ ResourceID CAsyncResourceManager::resourceIDForScreencopy(const std::string& por
|
|||
ResourceID CAsyncResourceManager::requestText(const CTextResource::STextResourceData& params, const AWP<IWidget>& widget) {
|
||||
const auto RESOURCEID = resourceIDForTextRequest(params);
|
||||
if (request(RESOURCEID, widget)) {
|
||||
Debug::log(TRACE, "Reusing text resource \"{}\" (resourceID: {}, widget: 0x{})", params.text, RESOURCEID, (uintptr_t)widget.get());
|
||||
Debug::log(TRACE, "Reusing text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get());
|
||||
return RESOURCEID;
|
||||
}
|
||||
|
||||
auto resource = makeAtomicShared<CTextResource>(CTextResource::STextResourceData{params});
|
||||
CAtomicSharedPointer<IAsyncResource> resourceGeneric{resource};
|
||||
|
||||
Debug::log(TRACE, "Requesting text resource \"{}\" (resourceID: {}, widget: 0x{})", params.text, RESOURCEID, (uintptr_t)widget.get());
|
||||
Debug::log(TRACE, "Requesting text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get());
|
||||
enqueue(RESOURCEID, resourceGeneric, widget);
|
||||
return RESOURCEID;
|
||||
}
|
||||
|
|
@ -59,14 +59,14 @@ ResourceID CAsyncResourceManager::requestText(const CTextResource::STextResource
|
|||
ResourceID CAsyncResourceManager::requestTextCmd(const CTextResource::STextResourceData& params, size_t revision, const AWP<IWidget>& widget) {
|
||||
const auto RESOURCEID = resourceIDForTextCmdRequest(params, revision);
|
||||
if (request(RESOURCEID, widget)) {
|
||||
Debug::log(TRACE, "Reusing text cmd resource \"{}\" revision {} (resourceID: {}, widget: 0x{})", params.text, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
Debug::log(TRACE, "Reusing text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
return RESOURCEID;
|
||||
}
|
||||
|
||||
auto resource = makeAtomicShared<CTextCmdResource>(CTextResource::STextResourceData{params});
|
||||
CAtomicSharedPointer<IAsyncResource> resourceGeneric{resource};
|
||||
|
||||
Debug::log(TRACE, "Requesting text cmd resource \"{}\" revision {} (resourceID: {}, widget: 0x{})", params.text, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
Debug::log(TRACE, "Requesting text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
enqueue(RESOURCEID, resourceGeneric, widget);
|
||||
return RESOURCEID;
|
||||
}
|
||||
|
|
@ -74,14 +74,14 @@ ResourceID CAsyncResourceManager::requestTextCmd(const CTextResource::STextResou
|
|||
ResourceID CAsyncResourceManager::requestImage(const std::string& path, size_t revision, const AWP<IWidget>& widget) {
|
||||
const auto RESOURCEID = resourceIDForImageRequest(path, revision);
|
||||
if (request(RESOURCEID, widget)) {
|
||||
Debug::log(TRACE, "Reusing image resource {} revision {} (resourceID: {}, widget: 0x{})", path, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
Debug::log(TRACE, "Reusing image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
return RESOURCEID;
|
||||
}
|
||||
|
||||
auto resource = makeAtomicShared<CImageResource>(absolutePath(path, ""));
|
||||
CAtomicSharedPointer<IAsyncResource> resourceGeneric{resource};
|
||||
|
||||
Debug::log(TRACE, "Requesting image resource {} revision {} (resourceID: {}, widget: 0x{})", path, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
Debug::log(TRACE, "Requesting image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get());
|
||||
enqueue(RESOURCEID, resourceGeneric, widget);
|
||||
return RESOURCEID;
|
||||
}
|
||||
|
|
@ -248,14 +248,12 @@ bool CAsyncResourceManager::request(ResourceID id, const AWP<IWidget>& widget) {
|
|||
if (m_assets[id].texture) {
|
||||
// Asset already present. Dispatch the asset callback function.
|
||||
const auto& TEXTURE = m_assets[id].texture;
|
||||
Debug::log(LOG, "onAssetUpdate {}", id);
|
||||
if (widget)
|
||||
g_pHyprlock->addTimer(
|
||||
std::chrono::milliseconds(0),
|
||||
[widget, TEXTURE](auto, auto) {
|
||||
if (const auto WIDGET = widget.lock(); WIDGET)
|
||||
WIDGET->onAssetUpdate(TEXTURE);
|
||||
},
|
||||
nullptr);
|
||||
widget->onAssetUpdate(id, TEXTURE);
|
||||
|
||||
// TODO: add a centalized mechanism to render in one place in the event loop to avoid duplicate render calls
|
||||
g_pHyprlock->addTimer(std::chrono::milliseconds(0), [](auto, auto) { g_pHyprlock->renderAllOutputs(); }, nullptr);
|
||||
} else if (widget) {
|
||||
// Asset currently in-flight. Add the widget reference to in order for the callback to get dispatched later.
|
||||
m_resourcesMutex.lock();
|
||||
|
|
@ -335,9 +333,11 @@ void CAsyncResourceManager::onResourceFinished(ResourceID id) {
|
|||
|
||||
for (const auto& widget : WIDGETS) {
|
||||
if (widget)
|
||||
widget->onAssetUpdate(texture);
|
||||
widget->onAssetUpdate(id, texture);
|
||||
}
|
||||
|
||||
g_pHyprlock->renderAllOutputs();
|
||||
|
||||
if (!m_gathered && !g_pHyprlock->m_bImmediateRender) {
|
||||
m_resourcesMutex.lock();
|
||||
if (m_resources.empty()) {
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ bool CBackground::draw(const SRenderData& data) {
|
|||
return crossFadeProgress->isBeingAnimated() || data.opacity < 1.0;
|
||||
}
|
||||
|
||||
void CBackground::onAssetUpdate(ASP<CTexture> newAsset) {
|
||||
void CBackground::onAssetUpdate(ResourceID id, ASP<CTexture> newAsset) {
|
||||
pendingResourceID = 0;
|
||||
|
||||
if (!newAsset)
|
||||
|
|
@ -278,8 +278,6 @@ void CBackground::onAssetUpdate(ASP<CTexture> newAsset) {
|
|||
}
|
||||
},
|
||||
true);
|
||||
|
||||
g_pHyprlock->renderOutput(outputPort);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class CBackground : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual void onAssetUpdate(ASP<CTexture> newAsset);
|
||||
virtual void onAssetUpdate(ResourceID id, ASP<CTexture> newAsset);
|
||||
|
||||
void reset(); // Unload assets, remove timers, etc.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ class IWidget {
|
|||
|
||||
virtual ~IWidget() = default;
|
||||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput) = 0;
|
||||
virtual bool draw(const SRenderData& data) = 0;
|
||||
virtual void onAssetUpdate(ASP<CTexture> newAsset) = 0;
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput) = 0;
|
||||
virtual bool draw(const SRenderData& data) = 0;
|
||||
// Never render within onAssetUpdate!
|
||||
virtual void onAssetUpdate(ResourceID id, ASP<CTexture> newAsset) = 0;
|
||||
|
||||
static Vector2D posFromHVAlign(const Vector2D& viewport, const Vector2D& size, const Vector2D& offset, const std::string& halign, const std::string& valign,
|
||||
const double& ang = 0);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ static void onTimer(AWP<CImage> ref) {
|
|||
}
|
||||
|
||||
void CImage::onTimerUpdate() {
|
||||
if (m_pendingResource) {
|
||||
Debug::log(WARN, "Trying to update image, but a resource is still pending! Skipping update.");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string OLDPATH = path;
|
||||
|
||||
if (!reloadCommand.empty()) {
|
||||
|
|
@ -56,11 +61,10 @@ void CImage::onTimerUpdate() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (pendingResourceID > 0)
|
||||
return;
|
||||
m_pendingResource = true;
|
||||
|
||||
AWP<IWidget> widget(m_self);
|
||||
pendingResourceID = g_asyncResourceManager->requestImage(path, m_imageRevision, widget);
|
||||
g_asyncResourceManager->requestImage(path, m_imageRevision, widget);
|
||||
}
|
||||
|
||||
void CImage::plantTimer() {
|
||||
|
|
@ -126,7 +130,7 @@ void CImage::reset() {
|
|||
g_asyncResourceManager->unload(asset);
|
||||
|
||||
asset = nullptr;
|
||||
pendingResourceID = 0;
|
||||
m_pendingResource = false;
|
||||
resourceID = 0;
|
||||
}
|
||||
|
||||
|
|
@ -205,11 +209,11 @@ bool CImage::draw(const SRenderData& data) {
|
|||
return data.opacity < 1.0;
|
||||
}
|
||||
|
||||
void CImage::onAssetUpdate(ASP<CTexture> newAsset) {
|
||||
pendingResourceID = 0;
|
||||
void CImage::onAssetUpdate(ResourceID id, ASP<CTexture> newAsset) {
|
||||
m_pendingResource = false;
|
||||
|
||||
if (!newAsset)
|
||||
Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", pendingResourceID);
|
||||
Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", id);
|
||||
else if (newAsset->m_iType == TEXTURE_INVALID) {
|
||||
g_asyncResourceManager->unload(newAsset);
|
||||
Debug::log(ERR, "New image asset has an invalid texture!");
|
||||
|
|
@ -218,10 +222,8 @@ void CImage::onAssetUpdate(ASP<CTexture> newAsset) {
|
|||
imageFB.destroyBuffer();
|
||||
|
||||
asset = newAsset;
|
||||
resourceID = pendingResourceID;
|
||||
resourceID = id;
|
||||
firstRender = true;
|
||||
|
||||
g_pHyprlock->renderOutput(stringPort);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class CImage : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual void onAssetUpdate(ASP<CTexture> newAsset);
|
||||
virtual void onAssetUpdate(ResourceID id, ASP<CTexture> newAsset);
|
||||
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
|
||||
|
|
@ -66,7 +66,7 @@ class CImage : public IWidget {
|
|||
std::string stringPort;
|
||||
|
||||
ResourceID resourceID = 0;
|
||||
ResourceID pendingResourceID = 0;
|
||||
bool m_pendingResource = false;
|
||||
|
||||
ASP<CTexture> asset = nullptr;
|
||||
CShadowable shadow;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "../../helpers/Color.hpp"
|
||||
#include "../../helpers/MiscFunctions.hpp"
|
||||
#include "../../config/ConfigDataValues.hpp"
|
||||
#include "src/defines.hpp"
|
||||
#include <hyprlang.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
|
|
@ -27,6 +28,11 @@ static void onTimer(AWP<CLabel> ref) {
|
|||
}
|
||||
|
||||
void CLabel::onTimerUpdate() {
|
||||
if (m_pendingResource) {
|
||||
Debug::log(WARN, "Trying to update label, but a resource is still pending! Skipping update.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string oldFormatted = label.formatted;
|
||||
|
||||
label = formatString(labelPreFormat);
|
||||
|
|
@ -34,21 +40,17 @@ void CLabel::onTimerUpdate() {
|
|||
if (label.formatted == oldFormatted && !label.alwaysUpdate)
|
||||
return;
|
||||
|
||||
if (pendingResourceID > 0) {
|
||||
Debug::log(WARN, "Trying to update label, but resource {} is still pending! Skipping update.", pendingResourceID);
|
||||
return;
|
||||
}
|
||||
|
||||
// request new
|
||||
request.text = label.formatted;
|
||||
request.text = label.formatted;
|
||||
m_pendingResource = true;
|
||||
|
||||
AWP<IWidget> widget(m_self);
|
||||
if (label.cmd) {
|
||||
// Don't increment by one to avoid clashes with multiple widget using the same label command.
|
||||
m_dynamicRevision += label.updateEveryMs;
|
||||
pendingResourceID = g_asyncResourceManager->requestTextCmd(request, m_dynamicRevision, widget.lock());
|
||||
g_asyncResourceManager->requestTextCmd(request, m_dynamicRevision, widget.lock());
|
||||
} else
|
||||
pendingResourceID = g_asyncResourceManager->requestText(request, widget.lock());
|
||||
g_asyncResourceManager->requestText(request, widget.lock());
|
||||
}
|
||||
|
||||
void CLabel::plantTimer() {
|
||||
|
|
@ -120,7 +122,7 @@ void CLabel::reset() {
|
|||
g_asyncResourceManager->unload(asset);
|
||||
|
||||
asset = nullptr;
|
||||
pendingResourceID = 0;
|
||||
m_pendingResource = false;
|
||||
resourceID = 0;
|
||||
}
|
||||
|
||||
|
|
@ -149,11 +151,12 @@ bool CLabel::draw(const SRenderData& data) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void CLabel::onAssetUpdate(ASP<CTexture> newAsset) {
|
||||
pendingResourceID = 0;
|
||||
void CLabel::onAssetUpdate(ResourceID id, ASP<CTexture> newAsset) {
|
||||
Debug::log(LOG, "Label update for resourceID {}", id);
|
||||
m_pendingResource = false;
|
||||
|
||||
if (!newAsset)
|
||||
Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", pendingResourceID);
|
||||
Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", id);
|
||||
else if (newAsset->m_iType == TEXTURE_INVALID) {
|
||||
g_asyncResourceManager->unload(newAsset);
|
||||
Debug::log(ERR, "New image asset has an invalid texture!");
|
||||
|
|
@ -161,10 +164,8 @@ void CLabel::onAssetUpdate(ASP<CTexture> newAsset) {
|
|||
// new asset is ready :D
|
||||
g_asyncResourceManager->unload(asset);
|
||||
asset = newAsset;
|
||||
resourceID = pendingResourceID;
|
||||
resourceID = id;
|
||||
updateShadow = true;
|
||||
|
||||
g_pHyprlock->renderOutput(outputStringPort);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class CLabel : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual void onAssetUpdate(ASP<CTexture> newAsset);
|
||||
virtual void onAssetUpdate(ResourceID id, ASP<CTexture> newAsset);
|
||||
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
|
||||
|
|
@ -49,7 +49,7 @@ class CLabel : public IWidget {
|
|||
double angle;
|
||||
|
||||
ResourceID resourceID = 0;
|
||||
ResourceID pendingResourceID = 0;
|
||||
bool m_pendingResource = false;
|
||||
|
||||
size_t m_dynamicRevision = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -363,8 +363,8 @@ void CPasswordInputField::updatePlaceholder() {
|
|||
placeholder.resourceID = g_asyncResourceManager->requestText(request, widget);
|
||||
}
|
||||
|
||||
void CPasswordInputField::onAssetUpdate(ASP<CTexture> newAsset) {
|
||||
g_pHyprlock->renderOutput(outputStringPort);
|
||||
void CPasswordInputField::onAssetUpdate(ResourceID id, ASP<CTexture> newAsset) {
|
||||
;
|
||||
}
|
||||
|
||||
void CPasswordInputField::updateWidth() {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class CPasswordInputField : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual void onAssetUpdate(ASP<CTexture> newAsset);
|
||||
virtual void onAssetUpdate(ResourceID id, ASP<CTexture> newAsset);
|
||||
|
||||
virtual void onHover(const Vector2D& pos);
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ bool CShape::draw(const SRenderData& data) {
|
|||
return data.opacity < 1.0;
|
||||
}
|
||||
|
||||
void CShape::onAssetUpdate(ASP<CTexture> newAsset) {
|
||||
void CShape::onAssetUpdate(ResourceID id, ASP<CTexture> newAsset) {
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class CShape : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual void onAssetUpdate(ASP<CTexture> newAsset);
|
||||
virtual void onAssetUpdate(ResourceID id, ASP<CTexture> newAsset);
|
||||
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue