1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // PixmapCache.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2005 Sean 'Shaleh' Perry <shaleh@debian.org>
4 // Copyright (c) 1997 - 2000, 2002 - 2005
5 // Bradley T Hughes <bhughes at trolltech.com>
7 // Permission is hereby granted, free of charge, to any person obtaining a
8 // copy of this software and associated documentation files (the "Software"),
9 // to deal in the Software without restriction, including without limitation
10 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 // and/or sell copies of the Software, and to permit persons to whom the
12 // Software is furnished to do so, subject to the following conditions:
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 // DEALINGS IN THE SOFTWARE.
26 #include "PixmapCache.hh"
38 // #define PIXMAPCACHE_DEBUG
43 class RealPixmapCache
{
45 RealPixmapCache(const Display
&display
);
46 ~RealPixmapCache(void);
48 Pixmap
find(unsigned int screen
,
49 const Texture
&texture
,
50 unsigned int width
, unsigned int height
,
51 Pixmap old_pixmap
= 0ul);
52 void release(Pixmap pixmap
);
54 void clear(bool force
);
57 const Texture texture
;
58 const unsigned int screen
;
59 const unsigned int width
;
60 const unsigned int height
;
64 inline CacheItem(void)
65 : screen(~0u), width(0u), height(0u),
66 pixmap(0ul), count(0u)
68 inline CacheItem(const unsigned int s
, const Texture
&t
,
69 const unsigned int w
, const unsigned int h
)
70 : texture(t
), screen(s
), width(w
), height(h
),
71 pixmap(0ul), count(1u)
74 inline bool operator==(const CacheItem
&x
) const {
75 return texture
== x
.texture
&&
83 inline PixmapMatch(Pixmap p
)
86 inline bool operator()(const RealPixmapCache::CacheItem
& item
) const
87 { return item
.pixmap
== pixmap
; }
92 const Display
&_display
;
94 typedef std::list
<CacheItem
> Cache
;
99 static RealPixmapCache
*realpixmapcache
= 0;
100 static unsigned long maxmem_usage
= 2ul*1024ul*1024ul; // 2mb default
101 static unsigned long mem_usage
= 0ul;
104 void createPixmapCache(const Display
&display
) {
105 assert(realpixmapcache
== 0);
106 realpixmapcache
= new RealPixmapCache(display
);
110 void destroyPixmapCache(void) {
111 delete realpixmapcache
;
114 assert(mem_usage
== 0ul);
120 bt::RealPixmapCache::RealPixmapCache(const Display
&display
)
125 bt::RealPixmapCache::~RealPixmapCache(void)
129 Pixmap
bt::RealPixmapCache::find(unsigned int screen
,
130 const Texture
&texture
,
131 unsigned int width
, unsigned int height
,
135 if (texture
.texture() == (Texture::Flat
| Texture::Solid
))
138 if (texture
.texture() == Texture::Parent_Relative
)
139 return ParentRelative
;
142 // find one in the cache
143 CacheItem
item(screen
, texture
, width
, height
);
144 Cache::iterator it
= std::find(cache
.begin(), cache
.end(), item
);
146 if (it
!= cache
.end()) {
152 #ifdef PIXMAPCACHE_DEBUG
153 fprintf(stderr
, "bt::PixmapCache: use %08lx %4ux%4u, count %4u\n",
154 it
->pixmap
, width
, height
, it
->count
);
155 #endif // PIXMAPCACHE_DEBUG
157 Image
image(width
, height
);
158 p
= image
.render(_display
, screen
, texture
);
163 #ifdef PIXMAPCACHE_DEBUG
165 "bt::PixmapCache: add %08lx %4ux%4u\n"
166 " mem %8lu max %8lu\n",
167 p
, width
, height
, mem_usage
, maxmem_usage
);
168 #endif // PIXMAPCACHE_DEBUG
170 cache
.push_front(item
);
172 // keep track of memory usage server side
173 const unsigned long mem
=
174 ( ( width
* height
) * (_display
.screenInfo(screen
).depth() / 8 ) );
176 if (mem_usage
> maxmem_usage
)
179 if (mem_usage
> maxmem_usage
) {
181 "bt::PixmapCache: maximum size (%lu kb) exceeded\n"
182 "bt::PixmapCache: current size: %lu kb\n",
183 maxmem_usage
/ 1024, mem_usage
/ 1024);
192 void bt::RealPixmapCache::release(Pixmap pixmap
) {
193 if (!pixmap
|| pixmap
== ParentRelative
)
196 Cache::iterator it
= std::find_if(cache
.begin(), cache
.end(),
197 PixmapMatch(pixmap
));
198 assert(it
!= cache
.end() && it
->count
> 0);
200 // decrement the refcount
203 #ifdef PIXMAPCACHE_DEBUG
204 fprintf(stderr
, "bt::PixmapCache: rel %08lx %4ux%4u, count %4u\n",
205 it
->pixmap
, it
->width
, it
->height
, it
->count
);
206 #endif // PIXMAPCACHE_DEBUG
210 void bt::RealPixmapCache::clear(bool force
) {
212 return; // nothing to do
214 #ifdef PIXMAPCACHE_DEBUG
215 fprintf(stderr
, "bt::PixmapCache: clearing cache, %u entries\n",
217 #endif // PIXMAPCACHE_DEBUG
219 Cache::iterator it
= cache
.begin();
220 while (it
!= cache
.end()) {
221 if (it
->count
!= 0 && !force
) {
222 #ifdef PIXMAPCACHE_DEBUG
223 fprintf(stderr
, "bt::PixmapCache: skp %08lx %4ux%4u, count %4u\n",
224 it
->pixmap
, it
->width
, it
->height
, it
->count
);
225 #endif // PIXMAPCACHE_DEBUG
231 #ifdef PIXMAPCACHE_DEBUG
232 fprintf(stderr
, "bt::PixmapCache: fre %08lx %4ux%4u\n",
233 it
->pixmap
, it
->width
, it
->height
);
234 #endif // PIXMAPCACHE_DEBUG
236 // keep track of memory usage server side
237 const unsigned long mem
=
238 ( ( it
->width
* it
->height
) *
239 (_display
.screenInfo(it
->screen
).depth() / 8 ) );
240 assert(mem
<= mem_usage
);
244 XFreePixmap(_display
.XDisplay(), it
->pixmap
);
247 it
= cache
.erase(it
);
250 #ifdef PIXMAPCACHE_DEBUG
252 "bt::PixmapCache: cleared, %u entries remain\n"
253 " mem %8lu max %8lu\n",
254 cache
.size(), mem_usage
, maxmem_usage
);
255 #endif // PIXMAPCACHE_DEBUG
259 unsigned long bt::PixmapCache::cacheLimit(void)
260 { return maxmem_usage
/ 1024; }
263 void bt::PixmapCache::setCacheLimit(unsigned long limit
)
264 { maxmem_usage
= limit
* 1024; }
267 unsigned long bt::PixmapCache::memoryUsage(void)
268 { return mem_usage
/ 1024; }
271 Pixmap
bt::PixmapCache::find(unsigned int screen
,
272 const Texture
&texture
,
273 unsigned int width
, unsigned int height
,
275 { return realpixmapcache
->find(screen
, texture
, width
, height
, old_pixmap
); }
278 void bt::PixmapCache::release(Pixmap pixmap
)
279 { realpixmapcache
->release(pixmap
); }
282 void bt::PixmapCache::clearCache(void)
283 { realpixmapcache
->clear(false); }