55#include " ../../core/InternalBackend.hpp"
66#include " ../../window/ToolkitWindow.hpp"
77#include " ../../system/Icons.hpp"
8+ #include " ../../resource/assetCache/AssetCache.hpp"
9+ #include " ../../renderer/RendererTexture.hpp"
810
911#include " ../Element.hpp"
1012
@@ -25,12 +27,12 @@ void CImageElement::paint() {
2527 if (m_impl->failed )
2628 return ;
2729
28- SP<IRendererTexture> textureToUse = m_impl->tex ;
30+ auto assetToUse = m_impl->cacheEntry ;
2931
30- if (!m_impl ->tex )
31- textureToUse = m_impl->oldTex ;
32+ if (!assetToUse || !assetToUse ->tex () )
33+ assetToUse = m_impl->oldCacheEntry ;
3234
33- if (!textureToUse ) {
35+ if (!assetToUse || !assetToUse-> tex () ) {
3436 if (!m_impl->waitingForTex )
3537 renderTex ();
3638 return ;
@@ -41,15 +43,15 @@ void CImageElement::paint() {
4143
4244 if (m_impl->data .icon && m_impl->preferredSvgSize () != m_impl->size && !m_impl->waitingForTex ) {
4345 renderTex ();
44- textureToUse = m_impl->oldTex ;
46+ assetToUse = m_impl->oldCacheEntry ;
4547 }
4648
47- if (!textureToUse )
49+ if (!assetToUse || !assetToUse-> tex () )
4850 return ; // ???
4951
5052 g_renderer->renderTexture ({
5153 .box = impl->position ,
52- .texture = textureToUse ,
54+ .texture = assetToUse-> tex () ,
5355 .a = 1 .F ,
5456 .rounding = 0 ,
5557 });
@@ -59,13 +61,27 @@ void CImageElement::renderTex() {
5961 if (m_impl->waitingForTex )
6062 return ;
6163
62- // TODO: this happens in hyprpaper's case, but if we have two or more wallpapers of the same
63- // image we duplicate VRAM. Maybe keep an asset ref table?
64- // ofc this won't work for svg but rasters of course.
65-
6664 m_impl->resource .reset ();
67- m_impl->oldTex = m_impl->tex ;
68- m_impl->tex .reset ();
65+ m_impl->oldCacheEntry = m_impl->cacheEntry ;
66+ m_impl->cacheEntry .reset ();
67+
68+ const auto CACHE_STR = m_impl->getCacheString ();
69+
70+ const auto ASSET = Asset::assetCache ()->get (CACHE_STR);
71+ if (ASSET) {
72+ g_logger->log (HT_LOG_DEBUG, " CImageElement: path {} was already cached, reusing entry" , m_impl->data .path );
73+ m_impl->failed = false ;
74+ m_impl->cacheEntry = ASSET;
75+ if (ASSET->status () == Asset::CACHE_ENTRY_DONE)
76+ m_impl->postImageScheduleRecalc ();
77+ else {
78+ m_impl->listeners .cacheEntryDone = ASSET->m_events .done .listen ([this ] {
79+ m_impl->postImageScheduleRecalc ();
80+ m_impl->listeners .cacheEntryDone .reset ();
81+ });
82+ }
83+ return ;
84+ }
6985
7086 if (!m_impl->data .icon ) {
7187 m_impl->resource = makeAtomicShared<CImageResource>(m_impl->data .path );
@@ -79,6 +95,9 @@ void CImageElement::renderTex() {
7995 return ;
8096 }
8197
98+ m_impl->cacheEntry = makeShared<Asset::CAssetCacheEntry>(CACHE_STR);
99+ Asset::assetCache ()->cache (m_impl->cacheEntry );
100+
82101 m_impl->waitingForTex = true ;
83102
84103 ASP<IAsyncResource> resourceGeneric (m_impl->resource );
@@ -104,28 +123,41 @@ void CImageElement::renderTex() {
104123}
105124
106125void SImageImpl::postImageLoad () {
107- if (!resource)
126+ if (!resource || !cacheEntry )
108127 return ;
109128
110129 if (resource->m_asset .cairoSurface ) {
111130 ASP<IAsyncResource> resourceGeneric (resource);
112131 size = resource->m_asset .pixelSize ;
113- tex = g_renderer->uploadTexture ({.resource = resourceGeneric, .fitMode = data.fitMode });
132+ cacheEntry-> texDone ( g_renderer->uploadTexture ({.resource = resourceGeneric, .fitMode = data.fitMode }) );
114133 } else {
115134 failed = true ;
116135 g_logger->log (HT_LOG_ERROR, " Image: failed loading, hyprgraphics couldn't load asset {}" , lastPath);
117136 }
118137
119- oldTex .reset ();
138+ oldCacheEntry .reset ();
120139 resource.reset ();
121140
141+ postImageScheduleRecalc ();
142+ }
143+
144+ void SImageImpl::postImageScheduleRecalc () {
122145 waitingForTex = false ;
123146 if (!failed) {
147+ if (cacheEntry)
148+ size = cacheEntry->tex ()->size ();
124149 self->impl ->damageEntire ();
125150 self->impl ->window ->scheduleReposition (self);
126151 }
127152}
128153
154+ std::string SImageImpl::getCacheString () {
155+ if (!data.icon )
156+ return data.path .ends_with (" .svg" ) ? std::format (" {}-{}x{}" , data.path , preferredSvgSize ().x , preferredSvgSize ().y ) : data.path ;
157+ else
158+ return std::format (" icon-{}-{}x{}" , reinterpretPointerCast<CSystemIconDescription>(data.icon )->m_bestPath , preferredSvgSize ().x , preferredSvgSize ().y );
159+ }
160+
129161SP<CImageBuilder> CImageElement::rebuild () {
130162 auto p = SP<CImageBuilder>(new CImageBuilder ());
131163 p->m_self = p;
0 commit comments