/[rdesktop]/sourceforge.net/trunk/rdesktop/cache.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/cache.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 10 by matty, Tue Aug 15 10:23:24 2000 UTC revision 1364 by jsorg71, Thu Jan 4 04:55:56 2007 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Cache routines     Cache routines
4     Copyright (C) Matthew Chapman 1999-2000     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     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     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     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.     (at your option) any later version.
11      
12     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.     GNU General Public License for more details.
16      
17     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 20  Line 21 
21    
22  #include "rdesktop.h"  #include "rdesktop.h"
23    
24    /* BITMAP CACHE */
25    extern int g_pstcache_fd[];
26    
27  #define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))  #define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
28    #define IS_PERSISTENT(id) (g_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  /* BITMAP CACHE */  struct bmpcache_entry
42  static HBITMAP bmpcache[3][600];  {
43            RD_HBITMAP bitmap;
44            sint16 previous;
45            sint16 next;
46    };
47    
48    static struct bmpcache_entry g_bmpcache[3][0xa00];
49    static RD_HBITMAP g_volatile_bc[3];
50    
51    static int g_bmpcache_lru[3] = { NOT_SET, NOT_SET, NOT_SET };
52    static int g_bmpcache_mru[3] = { NOT_SET, NOT_SET, NOT_SET };
53    static int g_bmpcache_count[3];
54    
55    /* Setup the bitmap cache lru/mru linked list */
56    void
57    cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count)
58    {
59            int n = count, c = 0;
60            sint16 n_idx;
61    
62            /* find top, skip evicted bitmaps */
63            while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
64            if (n < 0)
65            {
66                    g_bmpcache_mru[id] = g_bmpcache_lru[id] = NOT_SET;
67                    return;
68            }
69    
70            g_bmpcache_mru[id] = idx[n];
71            g_bmpcache[id][idx[n]].next = NOT_SET;
72            n_idx = idx[n];
73            c++;
74    
75            /* link list */
76            while (n >= 0)
77            {
78                    /* skip evicted bitmaps */
79                    while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
80    
81                    if (n < 0)
82                            break;
83    
84                    g_bmpcache[id][n_idx].previous = idx[n];
85                    g_bmpcache[id][idx[n]].next = n_idx;
86                    n_idx = idx[n];
87                    c++;
88            }
89    
90            g_bmpcache[id][n_idx].previous = NOT_SET;
91            g_bmpcache_lru[id] = n_idx;
92    
93            if (c != g_bmpcache_count[id])
94            {
95                    error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c,
96                          g_bmpcache_count[id]);
97                    exit(1);
98            }
99    }
100    
101    /* Move a bitmap to a new position in the linked list. */
102    void
103    cache_bump_bitmap(uint8 id, uint16 idx, int bump)
104    {
105            int p_idx, n_idx, n;
106    
107            if (!IS_PERSISTENT(id))
108                    return;
109    
110            if (g_bmpcache_mru[id] == idx)
111                    return;
112    
113            DEBUG_RDP5(("bump bitmap: id=%d, idx=%d, bump=%d\n", id, idx, bump));
114    
115            n_idx = g_bmpcache[id][idx].next;
116            p_idx = g_bmpcache[id][idx].previous;
117    
118            if (IS_SET(n_idx))
119            {
120                    /* remove */
121                    --g_bmpcache_count[id];
122                    if (IS_SET(p_idx))
123                            g_bmpcache[id][p_idx].next = n_idx;
124                    else
125                            g_bmpcache_lru[id] = n_idx;
126                    if (IS_SET(n_idx))
127                            g_bmpcache[id][n_idx].previous = p_idx;
128                    else
129                            g_bmpcache_mru[id] = p_idx;
130            }
131            else
132            {
133                    p_idx = NOT_SET;
134                    n_idx = g_bmpcache_lru[id];
135            }
136    
137            if (bump >= 0)
138            {
139                    for (n = 0; n < bump && IS_SET(n_idx); n++)
140                    {
141                            p_idx = n_idx;
142                            n_idx = g_bmpcache[id][p_idx].next;
143                    }
144            }
145            else
146            {
147                    p_idx = g_bmpcache_mru[id];
148                    n_idx = NOT_SET;
149            }
150    
151            /* insert */
152            ++g_bmpcache_count[id];
153            g_bmpcache[id][idx].previous = p_idx;
154            g_bmpcache[id][idx].next = n_idx;
155    
156            if (p_idx >= 0)
157                    g_bmpcache[id][p_idx].next = idx;
158            else
159                    g_bmpcache_lru[id] = idx;
160    
161            if (n_idx >= 0)
162                    g_bmpcache[id][n_idx].previous = idx;
163            else
164                    g_bmpcache_mru[id] = idx;
165    }
166    
167    /* Evict the least-recently used bitmap from the cache */
168    void
169    cache_evict_bitmap(uint8 id)
170    {
171            uint16 idx;
172            int n_idx;
173    
174            if (!IS_PERSISTENT(id))
175                    return;
176    
177            idx = g_bmpcache_lru[id];
178            n_idx = g_bmpcache[id][idx].next;
179            DEBUG_RDP5(("evict bitmap: id=%d idx=%d n_idx=%d bmp=0x%x\n", id, idx, n_idx,
180                        g_bmpcache[id][idx].bitmap));
181    
182            ui_destroy_bitmap(g_bmpcache[id][idx].bitmap);
183            --g_bmpcache_count[id];
184            g_bmpcache[id][idx].bitmap = 0;
185    
186            g_bmpcache_lru[id] = n_idx;
187            g_bmpcache[id][n_idx].previous = NOT_SET;
188    
189            pstcache_touch_bitmap(id, idx, 0);
190    }
191    
192  /* Retrieve a bitmap from the cache */  /* Retrieve a bitmap from the cache */
193  HBITMAP cache_get_bitmap(uint8 cache_id, uint16 cache_idx)  RD_HBITMAP
194    cache_get_bitmap(uint8 id, uint16 idx)
195  {  {
196          HBITMAP bitmap;          if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
197            {
198                    if (g_bmpcache[id][idx].bitmap || pstcache_load_bitmap(id, idx))
199                    {
200                            if (IS_PERSISTENT(id))
201                                    cache_bump_bitmap(id, idx, BUMP_COUNT);
202    
203          if ((cache_id < NUM_ELEMENTS(bmpcache))                          return g_bmpcache[id][idx].bitmap;
204                          && (cache_idx < NUM_ELEMENTS(bmpcache[0])))                  }
205            }
206            else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
207          {          {
208                  bitmap = bmpcache[cache_id][cache_idx];                  return g_volatile_bc[id];
                 if (bitmap != NULL)  
                         return bitmap;  
209          }          }
210    
211          ERROR("get bitmap %d:%d\n", cache_id, cache_idx);          error("get bitmap %d:%d\n", id, idx);
212          return NULL;          return NULL;
213  }  }
214    
215  /* Store a bitmap in the cache */  /* Store a bitmap in the cache */
216  void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap)  void
217    cache_put_bitmap(uint8 id, uint16 idx, RD_HBITMAP bitmap)
218  {  {
219          HBITMAP old;          RD_HBITMAP old;
220    
221          if ((cache_id < NUM_ELEMENTS(bmpcache))          if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
                         && (cache_idx < NUM_ELEMENTS(bmpcache[0])))  
222          {          {
223                  old = bmpcache[cache_id][cache_idx];                  old = g_bmpcache[id][idx].bitmap;
224                  if (old != NULL)                  if (old != NULL)
225                          ui_destroy_bitmap(old);                          ui_destroy_bitmap(old);
226                    g_bmpcache[id][idx].bitmap = bitmap;
227    
228                  bmpcache[cache_id][cache_idx] = bitmap;                  if (IS_PERSISTENT(id))
229                    {
230                            if (old == NULL)
231                                    g_bmpcache[id][idx].previous = g_bmpcache[id][idx].next = NOT_SET;
232    
233                            cache_bump_bitmap(id, idx, TO_TOP);
234                            if (g_bmpcache_count[id] > BMPCACHE2_C2_CELLS)
235                                    cache_evict_bitmap(id);
236                    }
237            }
238            else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
239            {
240                    old = g_volatile_bc[id];
241                    if (old != NULL)
242                            ui_destroy_bitmap(old);
243                    g_volatile_bc[id] = bitmap;
244          }          }
245          else          else
246          {          {
247                  ERROR("put bitmap %d:%d\n", cache_id, cache_idx);                  error("put bitmap %d:%d\n", id, idx);
248          }          }
249  }  }
250    
251    /* Updates the persistent bitmap cache MRU information on exit */
252    void
253    cache_save_state(void)
254    {
255            uint32 id = 0, t = 0;
256            int idx;
257    
258            for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++)
259                    if (IS_PERSISTENT(id))
260                    {
261                            DEBUG_RDP5(("Saving cache state for bitmap cache %d...", id));
262                            idx = g_bmpcache_lru[id];
263                            while (idx >= 0)
264                            {
265                                    pstcache_touch_bitmap(id, idx, ++t);
266                                    idx = g_bmpcache[id][idx].next;
267                            }
268                            DEBUG_RDP5((" %d stamps written.\n", t));
269                    }
270    }
271    
272    
273  /* FONT CACHE */  /* FONT CACHE */
274  static FONTGLYPH fontcache[12][256];  static FONTGLYPH g_fontcache[12][256];
275    
276  /* Retrieve a glyph from the font cache */  /* Retrieve a glyph from the font cache */
277  FONTGLYPH *cache_get_font(uint8 font, uint16 character)  FONTGLYPH *
278    cache_get_font(uint8 font, uint16 character)
279  {  {
280          FONTGLYPH *glyph;          FONTGLYPH *glyph;
281    
282          if ((font < NUM_ELEMENTS(fontcache))          if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0])))
                         && (character < NUM_ELEMENTS(fontcache[0])))  
283          {          {
284                  glyph = &fontcache[font][character];                  glyph = &g_fontcache[font][character];
285                  if (glyph->pixmap != NULL)                  if (glyph->pixmap != NULL)
286                          return glyph;                          return glyph;
287          }          }
288    
289          ERROR("get font %d:%d\n", font, character);          error("get font %d:%d\n", font, character);
290          return NULL;          return NULL;
291  }  }
292    
293  /* Store a glyph in the font cache */  /* Store a glyph in the font cache */
294  void cache_put_font(uint8 font, uint32 character, uint16 baseline,  void
295                      uint16 width, uint16 height, HGLYPH pixmap)  cache_put_font(uint8 font, uint16 character, uint16 offset,
296                   uint16 baseline, uint16 width, uint16 height, RD_HGLYPH pixmap)
297  {  {
298          FONTGLYPH *glyph;          FONTGLYPH *glyph;
299    
300          if ((font < NUM_ELEMENTS(fontcache))          if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0])))
                         && (character < NUM_ELEMENTS(fontcache[0])))  
301          {          {
302                  glyph = &fontcache[font][character];                  glyph = &g_fontcache[font][character];
303                  if (glyph->pixmap != NULL)                  if (glyph->pixmap != NULL)
304                          ui_destroy_glyph(glyph->pixmap);                          ui_destroy_glyph(glyph->pixmap);
305    
306                    glyph->offset = offset;
307                  glyph->baseline = baseline;                  glyph->baseline = baseline;
308                  glyph->width = width;                  glyph->width = width;
309                  glyph->height = height;                  glyph->height = height;
# Line 104  void cache_put_font(uint8 font, uint32 c Line 311  void cache_put_font(uint8 font, uint32 c
311          }          }
312          else          else
313          {          {
314                  ERROR("put font %d:%d\n", font, character);                  error("put font %d:%d\n", font, character);
315          }          }
316  }  }
317    
318    
319  /* TEXT CACHE */  /* TEXT CACHE */
320  static DATABLOB textcache[256];  static DATABLOB g_textcache[256];
321    
322  /* Retrieve a text item from the cache */  /* Retrieve a text item from the cache */
323  DATABLOB *cache_get_text(uint8 cache_id)  DATABLOB *
324    cache_get_text(uint8 cache_id)
325    {
326            DATABLOB *text;
327    
328            text = &g_textcache[cache_id];
329            return text;
330    }
331    
332    /* Store a text item in the cache */
333    void
334    cache_put_text(uint8 cache_id, void *data, int length)
335  {  {
336          DATABLOB *text;          DATABLOB *text;
337    
338          if (cache_id < NUM_ELEMENTS(textcache))          text = &g_textcache[cache_id];
339            if (text->data != NULL)
340                    xfree(text->data);
341            text->data = xmalloc(length);
342            text->size = length;
343            memcpy(text->data, data, length);
344    }
345    
346    
347    /* DESKTOP CACHE */
348    static uint8 g_deskcache[0x38400 * 4];
349    
350    /* Retrieve desktop data from the cache */
351    uint8 *
352    cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel)
353    {
354            int length = cx * cy * bytes_per_pixel;
355    
356            if (offset > sizeof(g_deskcache))
357                    offset = 0;
358    
359            if ((offset + length) <= sizeof(g_deskcache))
360          {          {
361                  text = &textcache[cache_id];                  return &g_deskcache[offset];
                 if (text->data != NULL)  
                         return text;  
362          }          }
363    
364          ERROR("get text %d\n", cache_id);          error("get desktop %d:%d\n", offset, length);
365          return NULL;          return NULL;
366  }  }
367    
368  /* Store a text item in the cache */  /* Store desktop data in the cache */
369  void cache_put_text(uint8 cache_id, void *data, int length)  void
370    cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 * data)
371  {  {
372          DATABLOB *text;          int length = cx * cy * bytes_per_pixel;
373    
374          if (cache_id < NUM_ELEMENTS(textcache))          if (offset > sizeof(g_deskcache))
375          {                  offset = 0;
                 text = &textcache[cache_id];  
                 if (text->data != NULL)  
                         xfree(text->data);  
376    
377                  text->data = xmalloc(length);          if ((offset + length) <= sizeof(g_deskcache))
378                  text->size = length;          {
379                  memcpy(text->data, data, length);                  cx *= bytes_per_pixel;
380                    while (cy--)
381                    {
382                            memcpy(&g_deskcache[offset], data, cx);
383                            data += scanline;
384                            offset += cx;
385                    }
386          }          }
387          else          else
388          {          {
389                  ERROR("put text %d\n", cache_id);                  error("put desktop %d:%d\n", offset, length);
390          }          }
391  }  }
392    
393    
394  /* DESKTOP CACHE */  /* CURSOR CACHE */
395  static uint8 deskcache[0x38400];  static RD_HCURSOR g_cursorcache[0x20];
396    
397  /* Retrieve desktop data from the cache */  /* Retrieve cursor from cache */
398  uint8 *cache_get_desktop(uint32 offset, uint32 length)  RD_HCURSOR
399    cache_get_cursor(uint16 cache_idx)
400  {  {
401          if ((offset + length) <= sizeof(deskcache))          RD_HCURSOR cursor;
402    
403            if (cache_idx < NUM_ELEMENTS(g_cursorcache))
404          {          {
405                  return &deskcache[offset];                  cursor = g_cursorcache[cache_idx];
406                    if (cursor != NULL)
407                            return cursor;
408          }          }
409    
410          ERROR("get desktop %d:%d\n", offset, length);          error("get cursor %d\n", cache_idx);
411          return NULL;          return NULL;
412  }  }
413    
414  /* Store desktop data in the cache */  /* Store cursor in cache */
415  void cache_put_desktop(uint32 offset, uint32 length, uint8 *data)  void
416    cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor)
417  {  {
418          if ((offset + length) <= sizeof(deskcache))          RD_HCURSOR old;
419    
420            if (cache_idx < NUM_ELEMENTS(g_cursorcache))
421          {          {
422                  memcpy(&deskcache[offset], data, length);                  old = g_cursorcache[cache_idx];
423                    if (old != NULL)
424                            ui_destroy_cursor(old);
425    
426                    g_cursorcache[cache_idx] = cursor;
427          }          }
428          else          else
429          {          {
430                  ERROR("put desktop %d:%d\n", offset, length);                  error("put cursor %d\n", cache_idx);
431          }          }
432  }  }
   

Legend:
Removed from v.10  
changed lines
  Added in v.1364

  ViewVC Help
Powered by ViewVC 1.1.26