1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
4 # include "../config.h"
5 #endif // HAVE_CONFIG_H
15 #include "assassin.hh"
16 #include "screeninfo.hh"
20 BGCCacheContext::~BGCCacheContext(void) {
22 XFreeGC(OBDisplay::display, gc);
26 void BGCCacheContext::set(const BColor &_color,
27 const XFontStruct * const _font,
28 const int _function, const int _subwindow,
31 pixel = gcv.foreground = _color.pixel();
32 function = gcv.function = _function;
33 subwindow = gcv.subwindow_mode = _subwindow;
34 linewidth = gcv.line_width = _linewidth;
35 gcv.cap_style = CapProjecting;
37 unsigned long mask = GCForeground | GCFunction | GCSubwindowMode |
38 GCLineWidth | GCCapStyle;
41 fontid = gcv.font = _font->fid;
47 XChangeGC(OBDisplay::display, gc, mask, &gcv);
51 void BGCCacheContext::set(const XFontStruct * const _font) {
58 fontid = gcv.font = _font->fid;
59 XChangeGC(OBDisplay::display, gc, GCFont, &gcv);
63 BGCCache::BGCCache(unsigned int screen_count)
64 : context_count(128u), cache_size(16u), cache_buckets(8u * screen_count),
65 cache_total_size(cache_size * cache_buckets) {
67 contexts = new BGCCacheContext*[context_count];
69 for (i = 0; i < context_count; i++) {
70 contexts[i] = new BGCCacheContext();
73 cache = new BGCCacheItem*[cache_total_size];
74 for (i = 0; i < cache_total_size; ++i) {
75 cache[i] = new BGCCacheItem;
80 BGCCache::~BGCCache(void) {
81 std::for_each(contexts, contexts + context_count, PointerAssassin());
82 std::for_each(cache, cache + cache_total_size, PointerAssassin());
88 BGCCacheContext *BGCCache::nextContext(unsigned int scr) {
89 Window hd = OBDisplay::screenInfo(scr)->getRootWindow();
93 for (unsigned int i = 0; i < context_count; ++i) {
97 c->gc = XCreateGC(OBDisplay::display, hd, 0, 0);
101 if (! c->used && c->screen == scr)
105 fprintf(stderr, "BGCCache: context fault!\n");
107 return (BGCCacheContext*) 0; // not reached
111 void BGCCache::release(BGCCacheContext *ctx) {
116 BGCCacheItem *BGCCache::find(const BColor &_color,
117 const XFontStruct * const _font,
118 int _function, int _subwindow, int _linewidth) {
119 const unsigned long pixel = _color.pixel();
120 const unsigned int screen = _color.screen();
121 const int key = _color.red() ^ _color.green() ^ _color.blue();
122 int k = (key % cache_size) * cache_buckets;
123 unsigned int i = 0; // loop variable
124 BGCCacheItem *c = cache[ k ], *prev = 0;
127 this will either loop cache_buckets times then return/abort or
128 it will stop matching
131 (c->ctx->pixel != pixel || c->ctx->function != _function ||
132 c->ctx->subwindow != _subwindow || c->ctx->screen != screen ||
133 c->ctx->linewidth != _linewidth)) {
134 if (i < (cache_buckets - 1)) {
140 if (c->count == 0 && c->ctx->screen == screen) {
141 // use this cache item
142 c->ctx->set(_color, _font, _function, _subwindow, _linewidth);
149 fprintf(stderr, "BGCCache: cache fault, count: %d, screen: %d, item screen: %d\n", c->count, screen, c->ctx->screen);
154 // reuse existing context
155 if (_font && _font->fid && _font->fid != c->ctx->fontid)
159 if (prev && c->hits > prev->hits) {
164 c->ctx = nextContext(screen);
165 c->ctx->set(_color, _font, _function, _subwindow, _linewidth);
175 void BGCCache::release(BGCCacheItem *_item) {
180 void BGCCache::purge(void) {
181 for (unsigned int i = 0; i < cache_total_size; ++i) {
182 BGCCacheItem *d = cache[ i ];
184 if (d->ctx && d->count == 0) {