Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencache.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
1.7.6.1
|