diff options
| author | Dana Jansens <danakj@orodu.net> | 2002-05-25 00:29:44 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2002-05-25 00:29:44 +0000 |
| commit | 8794d357e67abddf9fda9db77b235e294d0ec590 (patch) | |
| tree | 97e618433ff557b2b2d0842498d8464d4fba8717 /src/GCCache.cc | |
| parent | e640ee15ad19f24e0ad8351933fea5bafe98d380 (diff) | |
import from bb-cvs
added slit and enable-clobber defines back in Makefile.am
Diffstat (limited to 'src/GCCache.cc')
| -rw-r--r-- | src/GCCache.cc | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/src/GCCache.cc b/src/GCCache.cc new file mode 100644 index 00000000..941d67ef --- /dev/null +++ b/src/GCCache.cc @@ -0,0 +1,197 @@ +// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- +// GCCache.cc for Blackbox - an X11 Window manager +// Copyright (c) 2001 - 2002 Sean 'Shaleh' Perry <shaleh at debian.org> +// Copyright (c) 1997 - 2000, 2002 Bradley T Hughes <bhughes at trolltech.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifdef HAVE_CONFIG_H +# include "../config.h" +#endif // HAVE_CONFIG_H + +extern "C" { +#include <stdio.h> +} + +#include "GCCache.hh" +#include "BaseDisplay.hh" +#include "Color.hh" +#include "Util.hh" + + +void BGCCacheContext::set(const BColor &_color, + const XFontStruct * const _font, + const int _function, const int _subwindow) { + XGCValues gcv; + pixel = gcv.foreground = _color.pixel(); + function = gcv.function = _function; + subwindow = gcv.subwindow_mode = _subwindow; + unsigned long mask = GCForeground | GCFunction | GCSubwindowMode; + + if (_font) { + fontid = gcv.font = _font->fid; + mask |= GCFont; + } else { + fontid = 0; + } + + XChangeGC(display->getXDisplay(), gc, mask, &gcv); +} + + +void BGCCacheContext::set(const XFontStruct * const _font) { + if (! _font) { + fontid = 0; + return; + } + + XGCValues gcv; + fontid = gcv.font = _font->fid; + XChangeGC(display->getXDisplay(), gc, GCFont, &gcv); +} + + +BGCCache::BGCCache(const BaseDisplay * const _display) + : display(_display), context_count(128u), + cache_size(16u), cache_buckets(8u), + cache_total_size(cache_size * cache_buckets) { + + contexts = new BGCCacheContext*[context_count]; + unsigned int i; + for (i = 0; i < context_count; i++) { + contexts[i] = new BGCCacheContext(display); + } + + cache = new BGCCacheItem*[cache_total_size]; + for (i = 0; i < cache_total_size; ++i) { + cache[i] = new BGCCacheItem; + } +} + + +BGCCache::~BGCCache(void) { + std::for_each(contexts, contexts + context_count, PointerAssassin()); + std::for_each(cache, cache + cache_total_size, PointerAssassin()); + delete [] cache; + delete [] contexts; + cache = 0; + contexts = 0; +} + + +BGCCacheContext *BGCCache::nextContext(unsigned int scr) { + Window hd = display->getScreenInfo(scr)->getRootWindow(); + + BGCCacheContext *c; + + for (unsigned int i = 0; i < context_count; ++i) { + c = contexts[i]; + + if (! c->gc) { + c->gc = XCreateGC(display->getXDisplay(), hd, 0, 0); + c->used = false; + c->screen = scr; + } + if (! c->used && c->screen == scr) { + c->used = true; + return c; + } + } + + fprintf(stderr, "BGCCache: context fault!\n"); + abort(); +} + + +void BGCCache::release(BGCCacheContext *ctx) { + ctx->used = false; +} + + +BGCCacheItem *BGCCache::find(const BColor &_color, + const XFontStruct * const _font, + int _function, int _subwindow) { + const unsigned long pixel = _color.pixel(); + const unsigned int screen = _color.screen(); + const int key = _color.red() ^ _color.green() ^ _color.blue(); + int k = (key % cache_size) * cache_buckets; + int i = 0; // loop variable + BGCCacheItem *c = cache[ k ], *prev = 0; + + // this will either loop 8 times then return/abort or it will stop matching + while (c->ctx && + (c->ctx->pixel != pixel || c->ctx->function != _function || + c->ctx->subwindow != _subwindow || c->ctx->screen != screen)) { + if (i < 7) { + prev = c; + c = cache[ ++k ]; + ++i; + continue; + } + if (c->count == 0 && c->ctx->screen == screen) { + // use this cache item + c->ctx->set(_color, _font, _function, _subwindow); + c->ctx->used = true; + c->count = 1; + c->hits = 1; + return c; + } + // cache fault! + fprintf(stderr, "BGCCache: cache fault\n"); + abort(); + } + + const unsigned long fontid = _font ? _font->fid : 0; + if (c->ctx) { + // reuse existing context + if (fontid && fontid != c->ctx->fontid) + c->ctx->set(_font); + c->count++; + c->hits++; + if (prev && c->hits > prev->hits) { + cache[ k ] = prev; + cache[ k - 1 ] = c; + } + } else { + c->ctx = nextContext(screen); + c->ctx->set(_color, _font, _function, _subwindow); + c->ctx->used = true; + c->count = 1; + c->hits = 1; + } + + return c; +} + + +void BGCCache::release(BGCCacheItem *_item) { + _item->count--; +} + + +void BGCCache::purge(void) { + for (unsigned int i = 0; i < cache_total_size; ++i) { + BGCCacheItem *d = cache[ i ]; + + if (d->ctx && d->count == 0) { + release(d->ctx); + d->ctx = 0; + } + } +} |
