Mercurial > hg > xemacs-beta
comparison src/xgccache.c @ 185:3d6bfa290dbd r20-3b19
Import from CVS: tag r20-3b19
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:55:28 +0200 |
parents | 376386a54a3c |
children | c5d627a313b1 |
comparison
equal
deleted
inserted
replaced
184:bcd2674570bf | 185:3d6bfa290dbd |
---|---|
24 /* Emacs uses a lot of different display attributes; for example, assume | 24 /* Emacs uses a lot of different display attributes; for example, assume |
25 that only four fonts are in use (normal, bold, italic, and bold-italic). | 25 that only four fonts are in use (normal, bold, italic, and bold-italic). |
26 Then assume that one stipple or background is used for text selections, | 26 Then assume that one stipple or background is used for text selections, |
27 and another is used for highlighting mousable regions. That makes 16 | 27 and another is used for highlighting mousable regions. That makes 16 |
28 GCs already. Add in the fact that another GC may be needed to display | 28 GCs already. Add in the fact that another GC may be needed to display |
29 the text cursor in any of those regions, and you've got 32. Add in | 29 the text cursor in any of those regions, and you've got 32. Add in |
30 more fonts, and it keeps increasing exponentially. | 30 more fonts, and it keeps increasing exponentially. |
31 | 31 |
32 We used to keep these GCs in a cache of merged (fully qualified) faces. | 32 We used to keep these GCs in a cache of merged (fully qualified) faces. |
33 However, a lot of other code in xterm.c used XChangeGC of existing GCs, | 33 However, a lot of other code in xterm.c used XChangeGC of existing GCs, |
34 which is kind of slow and kind of random. Also, managing the face cache | 34 which is kind of slow and kind of random. Also, managing the face cache |
35 was tricky because it was hard to know when a face was no longer visible | 35 was tricky because it was hard to know when a face was no longer visible |
36 on the frame -- we had to mark all frames as garbaged whenever a face | 36 on the frame -- we had to mark all frames as garbaged whenever a face |
37 was changed, which caused an unpleasant amount of flicker (since faces are | 37 was changed, which caused an unpleasant amount of flicker (since faces are |
38 created/destroyed (= changed) whenever a frame is created/destroyed. | 38 created/destroyed (= changed) whenever a frame is created/destroyed. |
39 | 39 |
40 So this code maintains a cache at the GC level instead of at the face | 40 So this code maintains a cache at the GC level instead of at the face |
41 level. There is an upper limit on the size of the cache, after which we | 41 level. There is an upper limit on the size of the cache, after which we |
42 will stop creating GCs and start reusing them (reusing the least-recently- | 42 will stop creating GCs and start reusing them (reusing the least-recently- |
43 used ones first). So if faces get changed, their GCs will eventually be | 43 used ones first). So if faces get changed, their GCs will eventually be |
44 recycled. Also more sharing of GCs is possible. | 44 recycled. Also more sharing of GCs is possible. |
45 | 45 |
90 int create_count; | 90 int create_count; |
91 int delete_count; | 91 int delete_count; |
92 }; | 92 }; |
93 | 93 |
94 #ifdef GCCACHE_HASH | 94 #ifdef GCCACHE_HASH |
95 static unsigned long | 95 static unsigned long |
96 gc_cache_hash (CONST void *arg) | 96 gc_cache_hash (CONST void *arg) |
97 { | 97 { |
98 CONST struct gcv_and_mask *gcvm = (CONST struct gcv_and_mask *) arg; | 98 CONST struct gcv_and_mask *gcvm = (CONST struct gcv_and_mask *) arg; |
99 unsigned long *longs = (unsigned long *) &gcvm->gcv; | 99 unsigned long *longs = (unsigned long *) &gcvm->gcv; |
100 unsigned long hash = gcvm->mask; | 100 unsigned long hash = gcvm->mask; |
109 return hash; | 109 return hash; |
110 } | 110 } |
111 | 111 |
112 #endif /* GCCACHE_HASH */ | 112 #endif /* GCCACHE_HASH */ |
113 | 113 |
114 static int | 114 static int |
115 gc_cache_eql (CONST void *arg1, CONST void *arg2) | 115 gc_cache_eql (CONST void *arg1, CONST void *arg2) |
116 { | 116 { |
117 /* See comment in gc_cache_hash */ | 117 /* See comment in gc_cache_hash */ |
118 return (!memcmp (arg1, arg2, sizeof (struct gcv_and_mask))); | 118 return !memcmp (arg1, arg2, sizeof (struct gcv_and_mask)); |
119 } | 119 } |
120 | 120 |
121 struct gc_cache * | 121 struct gc_cache * |
122 make_gc_cache (Display *dpy, Window window) | 122 make_gc_cache (Display *dpy, Window window) |
123 { | 123 { |
124 struct gc_cache *cache = | 124 struct gc_cache *cache = xnew (struct gc_cache); |
125 (struct gc_cache *) xmalloc (sizeof (struct gc_cache)); | |
126 cache->dpy = dpy; | 125 cache->dpy = dpy; |
127 cache->window = window; | 126 cache->window = window; |
128 cache->size = 0; | 127 cache->size = 0; |
129 cache->head = cache->tail = 0; | 128 cache->head = cache->tail = 0; |
130 cache->create_count = cache->delete_count = 0; | 129 cache->create_count = cache->delete_count = 0; |
165 gcvm.mask = mask; | 164 gcvm.mask = mask; |
166 gcvm.gcv = *gcv; /* this copies... */ | 165 gcvm.gcv = *gcv; /* this copies... */ |
167 | 166 |
168 #ifdef GCCACHE_HASH | 167 #ifdef GCCACHE_HASH |
169 | 168 |
170 if (gethash (&gcvm, cache->table, (void *) &cell)) | 169 if (gethash (&gcvm, cache->table, (void **) &cell)) |
171 | 170 |
172 #else /* !GCCACHE_HASH */ | 171 #else /* !GCCACHE_HASH */ |
173 | 172 |
174 cell = cache->tail; /* start at the end (most recently used) */ | 173 cell = cache->tail; /* start at the end (most recently used) */ |
175 while (cell) | 174 while (cell) |
233 } | 232 } |
234 else if (cache->size > GC_CACHE_SIZE) | 233 else if (cache->size > GC_CACHE_SIZE) |
235 abort (); | 234 abort (); |
236 else | 235 else |
237 { | 236 { |
238 /* Allocate a new cell (don't put it in the list or table yet). | 237 /* Allocate a new cell (don't put it in the list or table yet). */ |
239 */ | 238 cell = xnew (struct gc_cache_cell); |
240 cell = (struct gc_cache_cell *) xmalloc (sizeof (struct gc_cache_cell)); | |
241 cache->size++; | 239 cache->size++; |
242 } | 240 } |
243 | 241 |
244 /* Now we've got a cell (new or reused). Fill it in. */ | 242 /* Now we've got a cell (new or reused). Fill it in. */ |
245 memcpy (&cell->gcvm.gcv, gcv, sizeof (XGCValues)); | 243 memcpy (&cell->gcvm.gcv, gcv, sizeof (XGCValues)); |