ReactOS 0.4.15-dev-7958-gcd0bb1a
cache.c
Go to the documentation of this file.
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Cache routines
4 Copyright (C) Matthew Chapman 1999-2005
5 Copyright (C) Jeroen Meijer 2005
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20*/
21
22#include "rdesktop.h"
23
24#undef IS_SET // !!!FIXME!!!
25
26/* BITMAP CACHE */
27#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
28#define IS_PERSISTENT(id) (This->pstcache_fd[id] > 0)
29#define TO_TOP -1
30#define NOT_SET -1
31#define IS_SET(idx) (idx >= 0)
32
33/*
34 * TODO: Test for optimal value of BUMP_COUNT. TO_TOP gives lowest cpu utilisation but using
35 * a positive value will hopefully result in less frequently used bitmaps having a greater chance
36 * of being evicted from the cache, and therby reducing the need to load bitmaps from disk.
37 * (Jeroen)
38 */
39#define BUMP_COUNT 40
40
41/* Setup the bitmap cache lru/mru linked list */
42void
44{
45 int n = count, c = 0;
46 sint16 n_idx;
47
48 /* find top, skip evicted bitmaps */
49 while (--n >= 0 && This->cache.bmpcache[id][idx[n]].bitmap == NULL);
50 if (n < 0)
51 {
52 This->cache.bmpcache_mru[id] = This->cache.bmpcache_lru[id] = NOT_SET;
53 return;
54 }
55
56 This->cache.bmpcache_mru[id] = idx[n];
57 This->cache.bmpcache[id][idx[n]].next = NOT_SET;
58 n_idx = idx[n];
59 c++;
60
61 /* link list */
62 while (n >= 0)
63 {
64 /* skip evicted bitmaps */
65 while (--n >= 0 && This->cache.bmpcache[id][idx[n]].bitmap == NULL);
66
67 if (n < 0)
68 break;
69
70 This->cache.bmpcache[id][n_idx].previous = idx[n];
71 This->cache.bmpcache[id][idx[n]].next = n_idx;
72 n_idx = idx[n];
73 c++;
74 }
75
76 This->cache.bmpcache[id][n_idx].previous = NOT_SET;
77 This->cache.bmpcache_lru[id] = n_idx;
78
79 if (c != This->cache.bmpcache_count[id])
80 {
81 error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c,
82 This->cache.bmpcache_count[id]);
83 exit(1);
84 }
85}
86
87/* Move a bitmap to a new position in the linked list. */
88void
90{
91 int p_idx, n_idx, n;
92
93 if (!IS_PERSISTENT(id))
94 return;
95
96 if (This->cache.bmpcache_mru[id] == idx)
97 return;
98
99 DEBUG_RDP5(("bump bitmap: id=%d, idx=%d, bump=%d\n", id, idx, bump));
100
101 n_idx = This->cache.bmpcache[id][idx].next;
102 p_idx = This->cache.bmpcache[id][idx].previous;
103
104 if (IS_SET(n_idx))
105 {
106 /* remove */
107 --This->cache.bmpcache_count[id];
108 if (IS_SET(p_idx))
109 This->cache.bmpcache[id][p_idx].next = n_idx;
110 else
111 This->cache.bmpcache_lru[id] = n_idx;
112 if (IS_SET(n_idx))
113 This->cache.bmpcache[id][n_idx].previous = p_idx;
114 else
115 This->cache.bmpcache_mru[id] = p_idx;
116 }
117 else
118 {
119 p_idx = NOT_SET;
120 n_idx = This->cache.bmpcache_lru[id];
121 }
122
123 if (bump >= 0)
124 {
125 for (n = 0; n < bump && IS_SET(n_idx); n++)
126 {
127 p_idx = n_idx;
128 n_idx = This->cache.bmpcache[id][p_idx].next;
129 }
130 }
131 else
132 {
133 p_idx = This->cache.bmpcache_mru[id];
134 n_idx = NOT_SET;
135 }
136
137 /* insert */
138 ++This->cache.bmpcache_count[id];
139 This->cache.bmpcache[id][idx].previous = p_idx;
140 This->cache.bmpcache[id][idx].next = n_idx;
141
142 if (p_idx >= 0)
143 This->cache.bmpcache[id][p_idx].next = idx;
144 else
145 This->cache.bmpcache_lru[id] = idx;
146
147 if (n_idx >= 0)
148 This->cache.bmpcache[id][n_idx].previous = idx;
149 else
150 This->cache.bmpcache_mru[id] = idx;
151}
152
153/* Evict the least-recently used bitmap from the cache */
154void
156{
157 uint16 idx;
158 int n_idx;
159
160 if (!IS_PERSISTENT(id))
161 return;
162
163 idx = This->cache.bmpcache_lru[id];
164 n_idx = This->cache.bmpcache[id][idx].next;
165 DEBUG_RDP5(("evict bitmap: id=%d idx=%d n_idx=%d bmp=0x%x\n", id, idx, n_idx,
166 This->cache.bmpcache[id][idx].bitmap));
167
168 ui_destroy_bitmap(This, This->cache.bmpcache[id][idx].bitmap);
169 --This->cache.bmpcache_count[id];
170 This->cache.bmpcache[id][idx].bitmap = 0;
171
172 This->cache.bmpcache_lru[id] = n_idx;
173 This->cache.bmpcache[id][n_idx].previous = NOT_SET;
174
176}
177
178/* Retrieve a bitmap from the cache */
181{
182 if ((id < NUM_ELEMENTS(This->cache.bmpcache)) && (idx < NUM_ELEMENTS(This->cache.bmpcache[0])))
183 {
184 if (This->cache.bmpcache[id][idx].bitmap || pstcache_load_bitmap(This, id, idx))
185 {
186 if (IS_PERSISTENT(id))
188
189 return This->cache.bmpcache[id][idx].bitmap;
190 }
191 }
192 else if ((id < NUM_ELEMENTS(This->cache.volatile_bc)) && (idx == 0x7fff))
193 {
194 return This->cache.volatile_bc[id];
195 }
196
197 error("get bitmap %d:%d\n", id, idx);
198 return NULL;
199}
200
201/* Store a bitmap in the cache */
202void
204{
205 HBITMAP old;
206
207 if ((id < NUM_ELEMENTS(This->cache.bmpcache)) && (idx < NUM_ELEMENTS(This->cache.bmpcache[0])))
208 {
209 old = This->cache.bmpcache[id][idx].bitmap;
210 if (old != NULL)
212 This->cache.bmpcache[id][idx].bitmap = bitmap;
213
214 if (IS_PERSISTENT(id))
215 {
216 if (old == NULL)
217 This->cache.bmpcache[id][idx].previous = This->cache.bmpcache[id][idx].next = NOT_SET;
218
220 if (This->cache.bmpcache_count[id] > BMPCACHE2_C2_CELLS)
222 }
223 }
224 else if ((id < NUM_ELEMENTS(This->cache.volatile_bc)) && (idx == 0x7fff))
225 {
226 old = This->cache.volatile_bc[id];
227 if (old != NULL)
229 This->cache.volatile_bc[id] = bitmap;
230 }
231 else
232 {
233 error("put bitmap %d:%d\n", id, idx);
234 }
235}
236
237/* Updates the persistent bitmap cache MRU information on exit */
238void
240{
241 uint32 id = 0, t = 0;
242 int idx;
243
244 for (id = 0; id < NUM_ELEMENTS(This->cache.bmpcache); id++)
245 if (IS_PERSISTENT(id))
246 {
247 DEBUG_RDP5(("Saving cache state for bitmap cache %d...", id));
248 idx = This->cache.bmpcache_lru[id];
249 while (idx >= 0)
250 {
252 idx = This->cache.bmpcache[id][idx].next;
253 }
254 DEBUG_RDP5((" %d stamps written.\n", t));
255 }
256}
257
258
259/* FONT CACHE */
260/* Retrieve a glyph from the font cache */
261FONTGLYPH *
263{
264 FONTGLYPH *glyph;
265
266 if ((font < NUM_ELEMENTS(This->cache.fontcache)) && (character < NUM_ELEMENTS(This->cache.fontcache[0])))
267 {
268 glyph = &This->cache.fontcache[font][character];
269 if (glyph->pixmap != NULL)
270 return glyph;
271 }
272
273 error("get font %d:%d\n", font, character);
274 return NULL;
275}
276
277/* Store a glyph in the font cache */
278void
280 uint16 baseline, uint16 width, uint16 height, HGLYPH pixmap)
281{
282 FONTGLYPH *glyph;
283
284 if ((font < NUM_ELEMENTS(This->cache.fontcache)) && (character < NUM_ELEMENTS(This->cache.fontcache[0])))
285 {
286 glyph = &This->cache.fontcache[font][character];
287 if (glyph->pixmap != NULL)
289
290 glyph->offset = offset;
291 glyph->baseline = baseline;
292 glyph->width = width;
293 glyph->height = height;
294 glyph->pixmap = pixmap;
295 }
296 else
297 {
298 error("put font %d:%d\n", font, character);
299 }
300}
301
302
303/* TEXT CACHE */
304/* Retrieve a text item from the cache */
305DATABLOB *
307{
308 DATABLOB *text;
309
310 text = &This->cache.textcache[cache_id];
311 return text;
312}
313
314/* Store a text item in the cache */
315void
317{
318 DATABLOB *text;
319 void * p = malloc(length);
320
321 if(p == NULL)
322 return;
323
324 text = &This->cache.textcache[cache_id];
325 if (text->data != NULL)
326 free(text->data);
327 text->data = p;
328 text->size = length;
329 memcpy(text->data, data, length);
330}
331
332
333/* DESKTOP CACHE */
334/* Retrieve desktop data from the cache */
335uint8 *
336cache_get_desktop(RDPCLIENT * This, uint32 offset, int cx, int cy, int bytes_per_pixel)
337{
338 int length = cx * cy * bytes_per_pixel;
339
340 if (offset > sizeof(This->cache.deskcache))
341 offset = 0;
342
343 if ((offset + length) <= sizeof(This->cache.deskcache))
344 {
345 return &This->cache.deskcache[offset];
346 }
347
348 error("get desktop %d:%d\n", offset, length);
349 return NULL;
350}
351
352/* Store desktop data in the cache */
353void
354cache_put_desktop(RDPCLIENT * This, uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 * data)
355{
356 int length = cx * cy * bytes_per_pixel;
357
358 if (offset > sizeof(This->cache.deskcache))
359 offset = 0;
360
361 if ((offset + length) <= sizeof(This->cache.deskcache))
362 {
363 cx *= bytes_per_pixel;
364 while (cy--)
365 {
366 memcpy(&This->cache.deskcache[offset], data, cx);
367 data += scanline;
368 offset += cx;
369 }
370 }
371 else
372 {
373 error("put desktop %d:%d\n", offset, length);
374 }
375}
376
377
378/* CURSOR CACHE */
379/* Retrieve cursor from cache */
382{
384
385 if (cache_idx < NUM_ELEMENTS(This->cache.cursorcache))
386 {
387 cursor = This->cache.cursorcache[cache_idx];
388 if (cursor != NULL)
389 return cursor;
390 }
391
392 error("get cursor %d\n", cache_idx);
393 return NULL;
394}
395
396/* Store cursor in cache */
397void
399{
400 HCURSOR old;
401
402 if (cache_idx < NUM_ELEMENTS(This->cache.cursorcache))
403 {
404 old = This->cache.cursorcache[cache_idx];
405 if (old != NULL)
407
408 This->cache.cursorcache[cache_idx] = cursor;
409 }
410 else
411 {
412 error("put cursor %d\n", cache_idx);
413 }
414}
#define IS_SET(idx)
Definition: cache.c:31
void cache_put_font(uint8 font, uint16 character, uint16 offset, uint16 baseline, uint16 width, uint16 height, RD_HGLYPH pixmap)
Definition: cache.c:296
#define BUMP_COUNT
Definition: cache.c:39
RD_HCURSOR cache_get_cursor(uint16 cache_idx)
Definition: cache.c:400
void cache_put_text(uint8 cache_id, void *data, int length)
Definition: cache.c:335
#define NOT_SET
Definition: cache.c:30
RD_HBITMAP cache_get_bitmap(uint8 id, uint16 idx)
Definition: cache.c:195
FONTGLYPH * cache_get_font(uint8 font, uint16 character)
Definition: cache.c:279
void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 *data)
Definition: cache.c:371
void cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor)
Definition: cache.c:417
#define TO_TOP
Definition: cache.c:29
void cache_bump_bitmap(uint8 id, uint16 idx, int bump)
Definition: cache.c:104
#define NUM_ELEMENTS(array)
Definition: cache.c:27
void cache_put_bitmap(uint8 id, uint16 idx, RD_HBITMAP bitmap)
Definition: cache.c:218
DATABLOB * cache_get_text(uint8 cache_id)
Definition: cache.c:325
void cache_rebuild_bmpcache_linked_list(uint8 id, sint16 *idx, int count)
Definition: cache.c:58
void cache_evict_bitmap(uint8 id)
Definition: cache.c:170
void cache_save_state(void)
Definition: cache.c:254
uint8 * cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel)
Definition: cache.c:353
#define BMPCACHE2_C2_CELLS
Definition: constants.h:284
#define IS_PERSISTENT(id)
Definition: precomp.h:26
void ui_destroy_bitmap(RD_HBITMAP bmp)
void pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp)
Definition: pstcache.c:39
RD_BOOL pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx)
Definition: pstcache.c:53
void ui_destroy_cursor(RD_HCURSOR cursor)
void ui_destroy_glyph(RD_HGLYPH glyph)
Definition: qtewin.cpp:1424
#define DEBUG_RDP5(args)
Definition: rdesktop.h:141
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
signed short sint16
Definition: types.h:31
unsigned char uint8
Definition: types.h:28
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
unsigned int idx
Definition: utils.c:41
const WCHAR * text
Definition: package.c:1799
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble t
Definition: gl.h:2047
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble n
Definition: glext.h:7729
const GLubyte * c
Definition: glext.h:8905
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLuint id
Definition: glext.h:5910
GLintptr offset
Definition: glext.h:5920
const char cursor[]
Definition: icontest.c:13
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HBITMAP
Definition: button.c:44
Definition: mk_font.cpp:20
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
#define exit(n)
Definition: config.h:202
uint16 width
Definition: types.h:114
sint16 baseline
Definition: types.h:113
uint16 height
Definition: types.h:115
sint16 offset
Definition: types.h:112
RD_HBITMAP pixmap
Definition: types.h:116
Definition: uimain.c:89
HICON HCURSOR
Definition: windef.h:299