ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cache.c
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 8 -*-
00002    rdesktop: A Remote Desktop Protocol client.
00003    Cache routines
00004    Copyright (C) Matthew Chapman 1999-2005
00005    Copyright (C) Jeroen Meijer 2005
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License along
00018    with this program; if not, write to the Free Software Foundation, Inc.,
00019    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00020 */
00021 
00022 #include <precomp.h>
00023 
00024 /* BITMAP CACHE */
00025 extern int g_pstcache_fd[];
00026 
00027 #define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
00028 //#define IS_PERSISTENT(id) (g_pstcache_fd[id] > 0)
00029 #define TO_TOP -1
00030 #define NOT_SET -1
00031 #define IS_SET(idx) (idx >= 0)
00032 
00033 /*
00034  * TODO: Test for optimal value of BUMP_COUNT. TO_TOP gives lowest cpu utilisation but using
00035  * a positive value will hopefully result in less frequently used bitmaps having a greater chance
00036  * of being evicted from the cache, and therby reducing the need to load bitmaps from disk.
00037  * (Jeroen)
00038  */
00039 #define BUMP_COUNT 40
00040 
00041 struct bmpcache_entry
00042 {
00043     RD_HBITMAP bitmap;
00044     sint16 previous;
00045     sint16 next;
00046 };
00047 
00048 static struct bmpcache_entry g_bmpcache[3][0xa00];
00049 static RD_HBITMAP g_volatile_bc[3];
00050 
00051 static int g_bmpcache_lru[3] = { NOT_SET, NOT_SET, NOT_SET };
00052 static int g_bmpcache_mru[3] = { NOT_SET, NOT_SET, NOT_SET };
00053 static int g_bmpcache_count[3];
00054 
00055 /* Setup the bitmap cache lru/mru linked list */
00056 void
00057 cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count)
00058 {
00059     int n = count, c = 0;
00060     sint16 n_idx;
00061 
00062     /* find top, skip evicted bitmaps */
00063     while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
00064     if (n < 0)
00065     {
00066         g_bmpcache_mru[id] = g_bmpcache_lru[id] = NOT_SET;
00067         return;
00068     }
00069 
00070     g_bmpcache_mru[id] = idx[n];
00071     g_bmpcache[id][idx[n]].next = NOT_SET;
00072     n_idx = idx[n];
00073     c++;
00074 
00075     /* link list */
00076     while (n >= 0)
00077     {
00078         /* skip evicted bitmaps */
00079         while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
00080 
00081         if (n < 0)
00082             break;
00083 
00084         g_bmpcache[id][n_idx].previous = idx[n];
00085         g_bmpcache[id][idx[n]].next = n_idx;
00086         n_idx = idx[n];
00087         c++;
00088     }
00089 
00090     g_bmpcache[id][n_idx].previous = NOT_SET;
00091     g_bmpcache_lru[id] = n_idx;
00092 
00093     if (c != g_bmpcache_count[id])
00094     {
00095         error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c,
00096               g_bmpcache_count[id]);
00097         exit(1);
00098     }
00099 }
00100 
00101 /* Move a bitmap to a new position in the linked list. */
00102 void
00103 cache_bump_bitmap(uint8 id, uint16 idx, int bump)
00104 {
00105     int p_idx, n_idx, n;
00106 
00107     if (!IS_PERSISTENT(id))
00108         return;
00109 
00110     if (g_bmpcache_mru[id] == idx)
00111         return;
00112 
00113     DEBUG_RDP5(("bump bitmap: id=%d, idx=%d, bump=%d\n", id, idx, bump));
00114 
00115     n_idx = g_bmpcache[id][idx].next;
00116     p_idx = g_bmpcache[id][idx].previous;
00117 
00118     if (IS_SET(n_idx))
00119     {
00120         /* remove */
00121         --g_bmpcache_count[id];
00122         if (IS_SET(p_idx))
00123             g_bmpcache[id][p_idx].next = n_idx;
00124         else
00125             g_bmpcache_lru[id] = n_idx;
00126         if (IS_SET(n_idx))
00127             g_bmpcache[id][n_idx].previous = p_idx;
00128         else
00129             g_bmpcache_mru[id] = p_idx;
00130     }
00131     else
00132     {
00133         p_idx = NOT_SET;
00134         n_idx = g_bmpcache_lru[id];
00135     }
00136 
00137     if (bump >= 0)
00138     {
00139         for (n = 0; n < bump && IS_SET(n_idx); n++)
00140         {
00141             p_idx = n_idx;
00142             n_idx = g_bmpcache[id][p_idx].next;
00143         }
00144     }
00145     else
00146     {
00147         p_idx = g_bmpcache_mru[id];
00148         n_idx = NOT_SET;
00149     }
00150 
00151     /* insert */
00152     ++g_bmpcache_count[id];
00153     g_bmpcache[id][idx].previous = p_idx;
00154     g_bmpcache[id][idx].next = n_idx;
00155 
00156     if (p_idx >= 0)
00157         g_bmpcache[id][p_idx].next = idx;
00158     else
00159         g_bmpcache_lru[id] = idx;
00160 
00161     if (n_idx >= 0)
00162         g_bmpcache[id][n_idx].previous = idx;
00163     else
00164         g_bmpcache_mru[id] = idx;
00165 }
00166 
00167 /* Evict the least-recently used bitmap from the cache */
00168 void
00169 cache_evict_bitmap(uint8 id)
00170 {
00171     uint16 idx;
00172     int n_idx;
00173 
00174     if (!IS_PERSISTENT(id))
00175         return;
00176 
00177     idx = g_bmpcache_lru[id];
00178     n_idx = g_bmpcache[id][idx].next;
00179     DEBUG_RDP5(("evict bitmap: id=%d idx=%d n_idx=%d bmp=0x%x\n", id, idx, n_idx,
00180             g_bmpcache[id][idx].bitmap));
00181 
00182     ui_destroy_bitmap(g_bmpcache[id][idx].bitmap);
00183     --g_bmpcache_count[id];
00184     g_bmpcache[id][idx].bitmap = 0;
00185 
00186     g_bmpcache_lru[id] = n_idx;
00187     g_bmpcache[id][n_idx].previous = NOT_SET;
00188 
00189     pstcache_touch_bitmap(id, idx, 0);
00190 }
00191 
00192 /* Retrieve a bitmap from the cache */
00193 RD_HBITMAP
00194 cache_get_bitmap(uint8 id, uint16 idx)
00195 {
00196     if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
00197     {
00198         if (g_bmpcache[id][idx].bitmap || pstcache_load_bitmap(id, idx))
00199         {
00200             if (IS_PERSISTENT(id))
00201                 cache_bump_bitmap(id, idx, BUMP_COUNT);
00202 
00203             return g_bmpcache[id][idx].bitmap;
00204         }
00205     }
00206     else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
00207     {
00208         return g_volatile_bc[id];
00209     }
00210 
00211     error("get bitmap %d:%d\n", id, idx);
00212     return NULL;
00213 }
00214 
00215 /* Store a bitmap in the cache */
00216 void
00217 cache_put_bitmap(uint8 id, uint16 idx, RD_HBITMAP bitmap)
00218 {
00219     RD_HBITMAP old;
00220 
00221     if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
00222     {
00223         old = g_bmpcache[id][idx].bitmap;
00224         if (old != NULL)
00225             ui_destroy_bitmap(old);
00226         g_bmpcache[id][idx].bitmap = bitmap;
00227 
00228         if (IS_PERSISTENT(id))
00229         {
00230             if (old == NULL)
00231                 g_bmpcache[id][idx].previous = g_bmpcache[id][idx].next = NOT_SET;
00232 
00233             cache_bump_bitmap(id, idx, TO_TOP);
00234             if (g_bmpcache_count[id] > BMPCACHE2_C2_CELLS)
00235                 cache_evict_bitmap(id);
00236         }
00237     }
00238     else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
00239     {
00240         old = g_volatile_bc[id];
00241         if (old != NULL)
00242             ui_destroy_bitmap(old);
00243         g_volatile_bc[id] = bitmap;
00244     }
00245     else
00246     {
00247         error("put bitmap %d:%d\n", id, idx);
00248     }
00249 }
00250 
00251 /* Updates the persistent bitmap cache MRU information on exit */
00252 void
00253 cache_save_state(void)
00254 {
00255     uint32 id = 0, t = 0;
00256     int idx;
00257 
00258     for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++)
00259         if (IS_PERSISTENT(id))
00260         {
00261             DEBUG_RDP5(("Saving cache state for bitmap cache %d...", id));
00262             idx = g_bmpcache_lru[id];
00263             while (idx >= 0)
00264             {
00265                 pstcache_touch_bitmap((uint8) id, (uint16) idx, ++t);
00266                 idx = g_bmpcache[id][idx].next;
00267             }
00268             DEBUG_RDP5((" %d stamps written.\n", t));
00269         }
00270 }
00271 
00272 
00273 /* FONT CACHE */
00274 static FONTGLYPH g_fontcache[12][256];
00275 
00276 /* Retrieve a glyph from the font cache */
00277 FONTGLYPH *
00278 cache_get_font(uint8 font, uint16 character)
00279 {
00280     FONTGLYPH *glyph;
00281 
00282     if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0])))
00283     {
00284         glyph = &g_fontcache[font][character];
00285         if (glyph->pixmap != NULL)
00286             return glyph;
00287     }
00288 
00289     error("get font %d:%d\n", font, character);
00290     return NULL;
00291 }
00292 
00293 /* Store a glyph in the font cache */
00294 void
00295 cache_put_font(uint8 font, uint16 character, uint16 offset,
00296            uint16 baseline, uint16 width, uint16 height, RD_HGLYPH pixmap)
00297 {
00298     FONTGLYPH *glyph;
00299 
00300     if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0])))
00301     {
00302         glyph = &g_fontcache[font][character];
00303         if (glyph->pixmap != NULL)
00304             ui_destroy_glyph(glyph->pixmap);
00305 
00306         glyph->offset = offset;
00307         glyph->baseline = baseline;
00308         glyph->width = width;
00309         glyph->height = height;
00310         glyph->pixmap = pixmap;
00311     }
00312     else
00313     {
00314         error("put font %d:%d\n", font, character);
00315     }
00316 }
00317 
00318 
00319 /* TEXT CACHE */
00320 static DATABLOB g_textcache[256];
00321 
00322 /* Retrieve a text item from the cache */
00323 DATABLOB *
00324 cache_get_text(uint8 cache_id)
00325 {
00326     DATABLOB *text;
00327 
00328     text = &g_textcache[cache_id];
00329     return text;
00330 }
00331 
00332 /* Store a text item in the cache */
00333 void
00334 cache_put_text(uint8 cache_id, void *data, int length)
00335 {
00336     DATABLOB *text;
00337 
00338     text = &g_textcache[cache_id];
00339     if (text->data != NULL)
00340         xfree(text->data);
00341     text->data = xmalloc(length);
00342     text->size = length;
00343     memcpy(text->data, data, length);
00344 }
00345 
00346 
00347 /* DESKTOP CACHE */
00348 static uint8 g_deskcache[0x38400 * 4];
00349 
00350 /* Retrieve desktop data from the cache */
00351 uint8 *
00352 cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel)
00353 {
00354     int length = cx * cy * bytes_per_pixel;
00355 
00356     if (offset > sizeof(g_deskcache))
00357         offset = 0;
00358 
00359     if ((offset + length) <= sizeof(g_deskcache))
00360     {
00361         return &g_deskcache[offset];
00362     }
00363 
00364     error("get desktop %d:%d\n", offset, length);
00365     return NULL;
00366 }
00367 
00368 /* Store desktop data in the cache */
00369 void
00370 cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 * data)
00371 {
00372     int length = cx * cy * bytes_per_pixel;
00373 
00374     if (offset > sizeof(g_deskcache))
00375         offset = 0;
00376 
00377     if ((offset + length) <= sizeof(g_deskcache))
00378     {
00379         cx *= bytes_per_pixel;
00380         while (cy--)
00381         {
00382             memcpy(&g_deskcache[offset], data, cx);
00383             data += scanline;
00384             offset += cx;
00385         }
00386     }
00387     else
00388     {
00389         error("put desktop %d:%d\n", offset, length);
00390     }
00391 }
00392 
00393 
00394 /* CURSOR CACHE */
00395 static RD_HCURSOR g_cursorcache[0x20];
00396 
00397 /* Retrieve cursor from cache */
00398 RD_HCURSOR
00399 cache_get_cursor(uint16 cache_idx)
00400 {
00401     RD_HCURSOR cursor;
00402 
00403     if (cache_idx < NUM_ELEMENTS(g_cursorcache))
00404     {
00405         cursor = g_cursorcache[cache_idx];
00406         if (cursor != NULL)
00407             return cursor;
00408     }
00409 
00410     error("get cursor %d\n", cache_idx);
00411     return NULL;
00412 }
00413 
00414 /* Store cursor in cache */
00415 void
00416 cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor)
00417 {
00418     RD_HCURSOR old;
00419 
00420     if (cache_idx < NUM_ELEMENTS(g_cursorcache))
00421     {
00422         old = g_cursorcache[cache_idx];
00423         if (old != NULL)
00424             ui_destroy_cursor(old);
00425 
00426         g_cursorcache[cache_idx] = cursor;
00427     }
00428     else
00429     {
00430         error("put cursor %d\n", cache_idx);
00431     }
00432 }

Generated on Fri May 25 2012 04:15:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.