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 #ifdef PIXMAPCACHE_DEBUG
180 if (mem_usage
> maxmem_usage
) {
182 "bt::PixmapCache: maximum size (%lu kb) exceeded\n"
183 "bt::PixmapCache: current size: %lu kb\n",
184 maxmem_usage
/ 1024, mem_usage
/ 1024);
186 #endif // PIXMAPCACHE_DEBUG
194 void bt::RealPixmapCache::release(Pixmap pixmap
) {
195 if (!pixmap
|| pixmap
== ParentRelative
)
198 Cache::iterator it
= std::find_if(cache
.begin(), cache
.end(),
199 PixmapMatch(pixmap
));
200 assert(it
!= cache
.end() && it
->count
> 0);
202 // decrement the refcount
205 #ifdef PIXMAPCACHE_DEBUG
206 fprintf(stderr
, "bt::PixmapCache: rel %08lx %4ux%4u, count %4u\n",
207 it
->pixmap
, it
->width
, it
->height
, it
->count
);
208 #endif // PIXMAPCACHE_DEBUG
212 void bt::RealPixmapCache::clear(bool force
) {
214 return; // nothing to do
216 #ifdef PIXMAPCACHE_DEBUG
217 fprintf(stderr
, "bt::PixmapCache: clearing cache, %u entries\n",
219 #endif // PIXMAPCACHE_DEBUG
221 Cache::iterator it
= cache
.begin();
222 while (it
!= cache
.end()) {
223 if (it
->count
!= 0 && !force
) {
224 #ifdef PIXMAPCACHE_DEBUG
225 fprintf(stderr
, "bt::PixmapCache: skp %08lx %4ux%4u, count %4u\n",
226 it
->pixmap
, it
->width
, it
->height
, it
->count
);
227 #endif // PIXMAPCACHE_DEBUG
233 #ifdef PIXMAPCACHE_DEBUG
234 fprintf(stderr
, "bt::PixmapCache: fre %08lx %4ux%4u\n",
235 it
->pixmap
, it
->width
, it
->height
);
236 #endif // PIXMAPCACHE_DEBUG
238 // keep track of memory usage server side
239 const unsigned long mem
=
240 ( ( it
->width
* it
->height
) *
241 (_display
.screenInfo(it
->screen
).depth() / 8 ) );
242 assert(mem
<= mem_usage
);
246 XFreePixmap(_display
.XDisplay(), it
->pixmap
);
249 it
= cache
.erase(it
);
252 #ifdef PIXMAPCACHE_DEBUG
254 "bt::PixmapCache: cleared, %u entries remain\n"
255 " mem %8lu max %8lu\n",
256 cache
.size(), mem_usage
, maxmem_usage
);
257 #endif // PIXMAPCACHE_DEBUG
261 unsigned long bt::PixmapCache::cacheLimit(void)
262 { return maxmem_usage
/ 1024; }
265 void bt::PixmapCache::setCacheLimit(unsigned long limit
)
266 { maxmem_usage
= limit
* 1024; }
269 unsigned long bt::PixmapCache::memoryUsage(void)
270 { return mem_usage
/ 1024; }
273 Pixmap
bt::PixmapCache::find(unsigned int screen
,
274 const Texture
&texture
,
275 unsigned int width
, unsigned int height
,
277 { return realpixmapcache
->find(screen
, texture
, width
, height
, old_pixmap
); }
280 void bt::PixmapCache::release(Pixmap pixmap
)
281 { realpixmapcache
->release(pixmap
); }
284 void bt::PixmapCache::clearCache(void)
285 { realpixmapcache
->clear(false); }