]> Dogcows Code - chaz/openbox/blob - src/GCCache.cc
75c7252a80d74ef39f3f972ae5678bb9b768e755
[chaz/openbox] / src / GCCache.cc
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>
5 //
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:
12 //
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
15 //
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.
23
24 #ifdef HAVE_CONFIG_H
25 # include "../config.h"
26 #endif // HAVE_CONFIG_H
27
28 extern "C" {
29 #include <stdio.h>
30 }
31
32 #include "GCCache.hh"
33 #include "BaseDisplay.hh"
34 #include "Color.hh"
35 #include "Util.hh"
36
37
38 BGCCacheContext::~BGCCacheContext(void) {
39 if (gc)
40 XFreeGC(display->getXDisplay(), gc);
41 }
42
43
44 void BGCCacheContext::set(const BColor &_color,
45 const XFontStruct * const _font,
46 const int _function, const int _subwindow,
47 int _linewidth) {
48 XGCValues gcv;
49 pixel = gcv.foreground = _color.pixel();
50 function = gcv.function = _function;
51 subwindow = gcv.subwindow_mode = _subwindow;
52 linewidth = gcv.line_width = _linewidth;
53 gcv.cap_style = CapProjecting;
54
55 unsigned long mask = GCForeground | GCFunction | GCSubwindowMode |
56 GCLineWidth | GCCapStyle;
57
58 if (_font) {
59 fontid = gcv.font = _font->fid;
60 mask |= GCFont;
61 } else {
62 fontid = 0;
63 }
64
65 XChangeGC(display->getXDisplay(), gc, mask, &gcv);
66 }
67
68
69 void BGCCacheContext::set(const XFontStruct * const _font) {
70 if (! _font) {
71 fontid = 0;
72 return;
73 }
74
75 XGCValues gcv;
76 fontid = gcv.font = _font->fid;
77 XChangeGC(display->getXDisplay(), gc, GCFont, &gcv);
78 }
79
80
81 BGCCache::BGCCache(const BaseDisplay * const _display)
82 : display(_display), context_count(128u),
83 cache_size(16u), cache_buckets(8u),
84 cache_total_size(cache_size * cache_buckets) {
85
86 contexts = new BGCCacheContext*[context_count];
87 unsigned int i;
88 for (i = 0; i < context_count; i++) {
89 contexts[i] = new BGCCacheContext(display);
90 }
91
92 cache = new BGCCacheItem*[cache_total_size];
93 for (i = 0; i < cache_total_size; ++i) {
94 cache[i] = new BGCCacheItem;
95 }
96 }
97
98
99 BGCCache::~BGCCache(void) {
100 std::for_each(contexts, contexts + context_count, PointerAssassin());
101 std::for_each(cache, cache + cache_total_size, PointerAssassin());
102 delete [] cache;
103 delete [] contexts;
104 }
105
106
107 BGCCacheContext *BGCCache::nextContext(unsigned int scr) {
108 Window hd = display->getScreenInfo(scr)->getRootWindow();
109
110 BGCCacheContext *c;
111
112 for (unsigned int i = 0; i < context_count; ++i) {
113 c = contexts[i];
114
115 if (! c->gc) {
116 c->gc = XCreateGC(display->getXDisplay(), hd, 0, 0);
117 c->used = false;
118 c->screen = scr;
119 }
120 if (! c->used && c->screen == scr) {
121 c->used = true;
122 return c;
123 }
124 }
125
126 fprintf(stderr, "BGCCache: context fault!\n");
127 abort();
128 return (BGCCacheContext*) 0; // not reached
129 }
130
131
132 void BGCCache::release(BGCCacheContext *ctx) {
133 ctx->used = false;
134 }
135
136
137 BGCCacheItem *BGCCache::find(const BColor &_color,
138 const XFontStruct * const _font,
139 int _function, int _subwindow, int _linewidth) {
140 const unsigned long pixel = _color.pixel();
141 const unsigned int screen = _color.screen();
142 const int key = _color.red() ^ _color.green() ^ _color.blue();
143 int k = (key % cache_size) * cache_buckets;
144 int i = 0; // loop variable
145 BGCCacheItem *c = cache[ k ], *prev = 0;
146
147 // this will either loop 8 times then return/abort or it will stop matching
148 while (c->ctx &&
149 (c->ctx->pixel != pixel || c->ctx->function != _function ||
150 c->ctx->subwindow != _subwindow || c->ctx->screen != screen ||
151 c->ctx->linewidth != _linewidth)) {
152 if (i < 7) {
153 prev = c;
154 c = cache[ ++k ];
155 ++i;
156 continue;
157 }
158 if (c->count == 0 && c->ctx->screen == screen) {
159 // use this cache item
160 c->ctx->set(_color, _font, _function, _subwindow, _linewidth);
161 c->ctx->used = true;
162 c->count = 1;
163 c->hits = 1;
164 return c;
165 }
166 // cache fault!
167 fprintf(stderr, "BGCCache: cache fault\n");
168 abort();
169 }
170
171 const unsigned long fontid = _font ? _font->fid : 0;
172 if (c->ctx) {
173 // reuse existing context
174 if (fontid && fontid != c->ctx->fontid)
175 c->ctx->set(_font);
176 c->count++;
177 c->hits++;
178 if (prev && c->hits > prev->hits) {
179 cache[ k ] = prev;
180 cache[ k - 1 ] = c;
181 }
182 } else {
183 c->ctx = nextContext(screen);
184 c->ctx->set(_color, _font, _function, _subwindow, _linewidth);
185 c->ctx->used = true;
186 c->count = 1;
187 c->hits = 1;
188 }
189
190 return c;
191 }
192
193
194 void BGCCache::release(BGCCacheItem *_item) {
195 _item->count--;
196 }
197
198
199 void BGCCache::purge(void) {
200 for (unsigned int i = 0; i < cache_total_size; ++i) {
201 BGCCacheItem *d = cache[ i ];
202
203 if (d->ctx && d->count == 0) {
204 release(d->ctx);
205 d->ctx = 0;
206 }
207 }
208 }
This page took 0.039101 seconds and 3 git commands to generate.