1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2 // GCCache.cc for Blackbox - an X11 Window manager
3 // Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org>
4 // Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com>
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the "Software"),
8 // to deal in the Software without restriction, including without limitation
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 // and/or sell copies of the Software, and to permit persons to whom the
11 // Software is furnished to do so, subject to the following conditions:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 // DEALINGS IN THE SOFTWARE.
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
33 #include "BaseDisplay.hh"
38 void BGCCacheContext::set(const BColor &_color,
39 const XFontStruct * const _font,
40 const int _function, const int _subwindow) {
42 pixel = gcv.foreground = _color.pixel();
43 function = gcv.function = _function;
44 subwindow = gcv.subwindow_mode = _subwindow;
45 unsigned long mask = GCForeground | GCFunction | GCSubwindowMode;
48 fontid = gcv.font = _font->fid;
54 XChangeGC(display->getXDisplay(), gc, mask, &gcv);
58 void BGCCacheContext::set(const XFontStruct * const _font) {
65 fontid = gcv.font = _font->fid;
66 XChangeGC(display->getXDisplay(), gc, GCFont, &gcv);
70 BGCCache::BGCCache(const BaseDisplay * const _display)
71 : display(_display), context_count(128u),
72 cache_size(16u), cache_buckets(8u),
73 cache_total_size(cache_size * cache_buckets) {
75 contexts = new BGCCacheContext*[context_count];
77 for (i = 0; i < context_count; i++) {
78 contexts[i] = new BGCCacheContext(display);
81 cache = new BGCCacheItem*[cache_total_size];
82 for (i = 0; i < cache_total_size; ++i) {
83 cache[i] = new BGCCacheItem;
88 BGCCache::~BGCCache(void) {
89 std::for_each(contexts, contexts + context_count, PointerAssassin());
90 std::for_each(cache, cache + cache_total_size, PointerAssassin());
98 BGCCacheContext *BGCCache::nextContext(unsigned int scr) {
99 Window hd = display->getScreenInfo(scr)->getRootWindow();
103 for (unsigned int i = 0; i < context_count; ++i) {
107 c->gc = XCreateGC(display->getXDisplay(), hd, 0, 0);
111 if (! c->used && c->screen == scr) {
117 fprintf(stderr, "BGCCache: context fault!\n");
122 void BGCCache::release(BGCCacheContext *ctx) {
127 BGCCacheItem *BGCCache::find(const BColor &_color,
128 const XFontStruct * const _font,
129 int _function, int _subwindow) {
130 const unsigned long pixel = _color.pixel();
131 const unsigned int screen = _color.screen();
132 const int key = _color.red() ^ _color.green() ^ _color.blue();
133 int k = (key % cache_size) * cache_buckets;
134 int i = 0; // loop variable
135 BGCCacheItem *c = cache[ k ], *prev = 0;
137 // this will either loop 8 times then return/abort or it will stop matching
139 (c->ctx->pixel != pixel || c->ctx->function != _function ||
140 c->ctx->subwindow != _subwindow || c->ctx->screen != screen)) {
147 if (c->count == 0 && c->ctx->screen == screen) {
148 // use this cache item
149 c->ctx->set(_color, _font, _function, _subwindow);
156 fprintf(stderr, "BGCCache: cache fault\n");
160 const unsigned long fontid = _font ? _font->fid : 0;
162 // reuse existing context
163 if (fontid && fontid != c->ctx->fontid)
167 if (prev && c->hits > prev->hits) {
172 c->ctx = nextContext(screen);
173 c->ctx->set(_color, _font, _function, _subwindow);
183 void BGCCache::release(BGCCacheItem *_item) {
188 void BGCCache::purge(void) {
189 for (unsigned int i = 0; i < cache_total_size; ++i) {
190 BGCCacheItem *d = cache[ i ];
192 if (d->ctx && d->count == 0) {