Changeset 45768 in vbox
- Timestamp:
- Apr 26, 2013 8:24:55 AM (12 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/xpdm
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/xpdm/VBoxDispVRDP.cpp
r44529 r45768 6 6 7 7 /* 8 * Copyright (C) 2011-201 2Oracle Corporation8 * Copyright (C) 2011-2013 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 1461 1461 int cacheResult; 1462 1462 1463 LOG(("MEMBLT ."));1463 LOG(("MEMBLT: bitmap %dx%d.", psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy)); 1464 1464 if ( (psoSrc->fjBitmap & BMF_DONTCACHE) != 0 1465 1465 || psoSrc->iUniq == 0 … … 1470 1470 && !(psoSrc->iBitmapFormat == BMF_24BPP || psoSrc->iBitmapFormat == BMF_32BPP) 1471 1471 ) 1472 /* Do not try to cache large bitmaps. The cache should be mostly used for icons, etc. 1473 * Computing a bitmap hash increases CPU load. Up to 384K pixels (~620x620) 1474 */ 1475 || psoSrc->sizlBitmap.cx * psoSrc->sizlBitmap.cy > 384 * _1K 1472 1476 ) 1473 1477 { … … 1477 1481 else 1478 1482 { 1479 LOG(("going to cache.")); 1480 cacheResult = vrdpbmpCacheSurface(&pDev->vrdpCache, psoSrc, &hash, &hashDeleted); 1481 } 1482 1483 LOG(("MEMBLT: cacheResult 0x%08X. trg %d,%d %dx%d src %dx%d from %d,%d", 1484 cacheResult, 1485 rclTrg.left, rclTrg.top, 1486 rclTrg.right - rclTrg.left, 1487 rclTrg.bottom - rclTrg.top, 1488 psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy, 1489 pptlSrc->x, pptlSrc->y)); 1483 LOG(("MEMBLT: going to cache.")); 1484 cacheResult = vrdpbmpCacheSurface(&pDev->vrdpCache, psoSrc, &hash, &hashDeleted, FALSE); 1485 } 1486 1487 LOG(("MEMBLT: cacheResult 0x%08X", cacheResult)); 1490 1488 1491 1489 if (cacheResult & VRDPBMP_RC_F_DELETED) … … 1500 1498 case VRDPBMP_RC_CACHED: 1501 1499 vrdpReportCachedBitmap(pDev, psoSrc, &hash); 1500 LOG(("MEMBLT: cached add %dx%d", 1501 psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy)); 1502 1502 /* Continue and report MEMBLT order. */ 1503 1503 1504 1504 case VRDPBMP_RC_ALREADY_CACHED: 1505 1505 vrdpReportMemBlt(pDev, &clipRects, pptlSrc, (uint8_t)rop4, &hash); 1506 LOG(("MEMBLT: cached use %dx%d from %d,%d %dx%d", 1507 psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy, 1508 pptlSrc->x, pptlSrc->y, 1509 rclTrg.right - rclTrg.left, 1510 rclTrg.bottom - rclTrg.top)); 1506 1511 LOG((" %08X %08X %08X %08X", 1507 1512 *(uint32_t *)&((uint8_t *)&hash)[0], … … 1514 1519 default: 1515 1520 /* The surface was not cached. Fallback to dirty rects. */ 1516 LOG(("MEMBLT: bitmap not cached.")); 1521 LOG(("MEMBLT: not cached %dx%d from %d,%d %dx%d", 1522 psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy, 1523 pptlSrc->x, pptlSrc->y, 1524 rclTrg.right - rclTrg.left, 1525 rclTrg.bottom - rclTrg.top)); 1517 1526 VBoxDispDumpPSO(psoSrc, "psoSrc"); 1518 1527 vrdpReportDirtyRects(pDev, &clipRects); -
trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/xpdm/VBoxDispVrdpBmp.cpp
r36867 r45768 6 6 7 7 /* 8 * Copyright (C) 2011 Oracle Corporation8 * Copyright (C) 2011-2013 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 22 22 23 23 /* 24 * Cache has a fixed number of preallocated entries. Entries are linked in the MRU 25 * list. The list contains both used and free entries. Free entries are at the end. 26 * The most recently used entry is in the head. 24 * Cache has a fixed number of preallocated entries. Entries are linked in the MRU lists. 25 * 26 * A new bitmap hash is added to the "temporary" list, and the caller is told that the 27 * bitmap was not cached. If the hash is used again, then it is moved to the "cached" list. 28 * This protects against "cache, memblt, cache, memblt, ..." sequences. 29 * 30 * "Temporary" list contains free and temporary entries. Temporary entries are at the head, 31 * free entries are at the tail. New temporary entries are inserted in the head. 32 * 33 * "Cached" list contains cached entries. When a entry is used, it is moved to the head. 27 34 * 28 35 * The purpose of the cache is to answer whether the bitmap was already encountered … … 75 82 } 76 83 77 /* Meves an entry to the head of MRU list. */ 78 static void bcMoveToHead (VRDPBC *pCache, VRDPBCENTRY *pEntry) 84 static void bcRemoveFromCached(VRDPBC *pCache, VRDPBCENTRY *pEntry) 79 85 { 80 86 if (pEntry->prev) 81 87 { 88 pEntry->prev->next = pEntry->next; 89 } 90 else 91 { 92 pCache->headCached = pEntry->next; 93 } 94 95 if (pEntry->next) 96 { 97 pEntry->next->prev = pEntry->prev; 98 } 99 else 100 { 101 pCache->tailCached = pEntry->prev; 102 } 103 } 104 105 static void bcRemoveFromTmp(VRDPBC *pCache, VRDPBCENTRY *pEntry) 106 { 107 if (pEntry->prev) 108 { 109 pEntry->prev->next = pEntry->next; 110 } 111 else 112 { 113 pCache->headTmp = pEntry->next; 114 } 115 116 if (pEntry->next) 117 { 118 pEntry->next->prev = pEntry->prev; 119 } 120 else 121 { 122 pCache->tailTmp = pEntry->prev; 123 } 124 } 125 126 static void bcInsertHeadCached(VRDPBC *pCache, VRDPBCENTRY *pEntry) 127 { 128 pEntry->prev = NULL; 129 pEntry->next = pCache->headCached; 130 131 if (pCache->headCached) 132 { 133 pCache->headCached->prev = pEntry; 134 } 135 else 136 { 137 pCache->tailCached = pEntry; 138 } 139 140 pCache->headCached = pEntry; 141 } 142 143 static void bcInsertHeadTmp(VRDPBC *pCache, VRDPBCENTRY *pEntry) 144 { 145 pEntry->prev = NULL; 146 pEntry->next = pCache->headTmp; 147 148 if (pCache->headTmp) 149 { 150 pCache->headTmp->prev = pEntry; 151 } 152 else 153 { 154 pCache->tailTmp = pEntry; 155 } 156 157 pCache->headTmp = pEntry; 158 } 159 160 /* Moves an entry to the head of MRU list. */ 161 static void bcMoveToHeadCached(VRDPBC *pCache, VRDPBCENTRY *pEntry) 162 { 163 if (pEntry->prev) 164 { 82 165 /* The entry is not yet in the head. Exclude from list. */ 83 pEntry->prev->next = pEntry->next; 84 85 if (pEntry->next) 86 { 87 pEntry->next->prev = pEntry->prev; 88 } 89 else 90 { 91 pCache->tail = pEntry->prev; 92 } 166 bcRemoveFromCached(pCache, pEntry); 93 167 94 168 /* Insert the entry at the head of MRU list. */ 95 pEntry->prev = NULL; 96 pEntry->next = pCache->head; 97 98 Assert(pCache->head); 99 100 pCache->head->prev = pEntry; 101 pCache->head = pEntry; 102 } 103 } 104 105 /* Returns TRUE if the hash already presents in the cache. 106 * Moves the found entry to the head of MRU list. 107 */ 108 static BOOL bcFindHash (VRDPBC *pCache, const VRDPBCHASH *phash) 109 { 110 /* Search the MRU list. */ 111 VRDPBCENTRY *pEntry = pCache->head; 112 113 while (pEntry && pEntry->fUsed) 169 bcInsertHeadCached(pCache, pEntry); 170 } 171 } 172 173 static void bcMoveToHeadTmp(VRDPBC *pCache, VRDPBCENTRY *pEntry) 174 { 175 if (pEntry->prev) 176 { 177 /* The entry is not yet in the head. Exclude from list. */ 178 bcRemoveFromTmp(pCache, pEntry); 179 180 /* Insert the entry at the head of MRU list. */ 181 bcInsertHeadTmp(pCache, pEntry); 182 } 183 } 184 185 static void bcMoveTmpToCached(VRDPBC *pCache, VRDPBCENTRY *pEntry) 186 { 187 /* Remove from Tmp list. */ 188 bcRemoveFromTmp(pCache, pEntry); 189 190 /* Insert the entry at the head of Cached list. */ 191 bcInsertHeadCached(pCache, pEntry); 192 } 193 194 static void bcMoveCachedToTmp(VRDPBC *pCache, VRDPBCENTRY *pEntry) 195 { 196 /* Remove from cached list. */ 197 bcRemoveFromCached(pCache, pEntry); 198 199 /* Insert the entry at the head of Tmp list. */ 200 bcInsertHeadTmp(pCache, pEntry); 201 } 202 203 204 /* Returns pointer to the entry if the hash already presents in the cache. 205 * Moves the found entry to the head of cached MRU list. 206 */ 207 static VRDPBCENTRY *bcFindHash (VRDPBC *pCache, const VRDPBCHASH *phash) 208 { 209 /* Search the "Cached" MRU list. */ 210 VRDPBCENTRY *pEntry = pCache->headCached; 211 212 while (pEntry) 114 213 { 115 214 if (memcmp (&pEntry->hash, phash, sizeof (VRDPBCHASH)) == 0) 116 215 { 117 /* Found the entry. Move it to the head of MRU list. */118 bcMoveToHead 119 120 return TRUE;216 /* Found the entry. Move it to the head of Cached MRU list. */ 217 bcMoveToHeadCached(pCache, pEntry); 218 219 return pEntry; 121 220 } 122 221 … … 124 223 } 125 224 126 return FALSE; 127 } 128 129 /* Returns TRUE is a entry was also deleted to nake room for new entry. */ 130 static BOOL bcInsertHash (VRDPBC *pCache, const VRDPBCHASH *phash, VRDPBCHASH *phashDeleted) 131 { 132 BOOL bRc = FALSE; 133 VRDPBCENTRY *pEntry; 134 135 LOG(("insert hash cache %p, tail %p.", pCache, pCache->tail)); 136 137 /* Get the free entry to be used. Try tail, that should be */ 138 pEntry = pCache->tail; 139 140 if (pEntry == NULL) 141 { 142 return bRc; 143 } 144 145 if (pEntry->fUsed) 146 { 147 /* The cache is full. Remove the tail. */ 225 /* Search the "Temporary" MRU list. */ 226 pEntry = pCache->headTmp; 227 228 while ( pEntry 229 && pEntry->u32Status != VRDP_BC_ENTRY_STATUS_EMPTY) 230 { 231 if (memcmp (&pEntry->hash, phash, sizeof (VRDPBCHASH)) == 0) 232 { 233 /* Found the entry. It will be removed from the list by the caller. */ 234 return pEntry; 235 } 236 237 pEntry = pEntry->next; 238 } 239 240 return NULL; 241 } 242 243 /* Returns TRUE is a entry was also deleted to make room for new entry. */ 244 static int bcInsertHash (VRDPBC *pCache, const VRDPBCHASH *phash, VRDPBCHASH *phashDeleted, BOOL bForce) 245 { 246 LOG(("bcInsertHash %p, tmp tail %p, cached tail %p.", pCache, pCache->tailTmp, pCache->tailCached)); 247 248 /* Get the free entry to be used. Try Tmp list, then the tail of the Cached list. */ 249 VRDPBCENTRY *pEntry = pCache->tailTmp; 250 251 if (pEntry != NULL) 252 { 253 /* Insert to the head of Tmp list. */ 254 bcMoveToHeadTmp(pCache, pEntry); 255 LOG(("bcInsertHash %p, use tmp tail %p.", pCache, pEntry)); 256 } 257 else 258 { 259 pEntry = pCache->tailCached; 260 LOG(("bcInsertHash %p, reuse cached tail %p.", pCache, pEntry, pEntry? pEntry->u32Status: 0)); 261 262 if (pEntry != NULL) 263 { 264 bcMoveCachedToTmp(pCache, pEntry); 265 } 266 } 267 268 if (!pEntry) 269 { 270 LOG(("bcInsertHash %p, failed to find an entry!!!", pCache)); 271 return VRDPBMP_RC_NOT_CACHED; 272 } 273 274 BOOL bHashDeleted; 275 if (pEntry->u32Status == VRDP_BC_ENTRY_STATUS_CACHED) 276 { 277 /* The cache is full. Remove the tail hash. */ 148 278 memcpy (phashDeleted, &pEntry->hash, sizeof (VRDPBCHASH)); 149 bRc = TRUE; 150 } 151 152 bcMoveToHead (pCache, pEntry); 153 279 bHashDeleted = TRUE; 280 } 281 else 282 { 283 bHashDeleted = FALSE; 284 } 285 286 /* The just inserted entry is at the head of Tmp list, so the temporary 287 * entries will be deleted when there is no room in the cache. 288 */ 154 289 memcpy (&pEntry->hash, phash, sizeof (VRDPBCHASH)); 155 pEntry->fUsed = TRUE; 156 157 return bRc; 290 291 int rc; 292 if (bForce) 293 { 294 LOG(("Force cache")); 295 bcMoveTmpToCached(pCache, pEntry); 296 pEntry->u32Status = VRDP_BC_ENTRY_STATUS_CACHED; 297 rc = VRDPBMP_RC_CACHED; 298 } 299 else 300 { 301 pEntry->u32Status = VRDP_BC_ENTRY_STATUS_TEMPORARY; 302 rc = VRDPBMP_RC_NOT_CACHED; 303 } 304 305 if (bHashDeleted) 306 { 307 rc |= VRDPBMP_RC_F_DELETED; 308 } 309 310 return rc; 158 311 } 159 312 160 313 /* Find out whether the surface already in the cache. 161 314 * Insert in the cache if not. 162 */ 163 int vrdpbmpCacheSurface(VRDPBC *pCache, const SURFOBJ *pso, VRDPBCHASH *phash, VRDPBCHASH *phashDeleted) 164 { 165 int rc; 166 315 * Protection against "cache, memblt, cache, memblt, ..." sequence: 316 * first time just append the bitmap hash and mark it as "temporary"; 317 * if the hash is used again, mark as cached and tell the caller to cache the bitmap; 318 * remove "temporary" entries before any other. 319 * 320 */ 321 int vrdpbmpCacheSurface(VRDPBC *pCache, const SURFOBJ *pso, VRDPBCHASH *phash, VRDPBCHASH *phashDeleted, BOOL bForce) 322 { 167 323 VRDPBCHASH hash; 168 324 169 325 BOOL bResult = bcComputeHash (pso, &hash); 170 171 326 LOG(("vrdpbmpCacheSurface: compute hash %d.", bResult)); 327 172 328 if (!bResult) 173 329 { … … 176 332 } 177 333 178 bResult = bcFindHash (pCache, &hash);179 180 LOG(("vrdpbmpCacheSurface: find hash %d.", bResult));181 334 *phash = hash; 182 335 183 if (bResult) 184 { 185 return VRDPBMP_RC_ALREADY_CACHED; 186 } 187 188 rc = VRDPBMP_RC_CACHED; 189 190 bResult = bcInsertHash (pCache, &hash, phashDeleted); 191 192 LOG(("vrdpbmpCacheSurface: insert hash %d.", bResult)); 193 if (bResult) 194 { 195 rc |= VRDPBMP_RC_F_DELETED; 196 } 336 VRDPBCENTRY *pEntry = bcFindHash (pCache, &hash); 337 LOG(("vrdpbmpCacheSurface: find hash %d.", pEntry? pEntry->u32Status: 0)); 338 339 if (pEntry) 340 { 341 if (pEntry->u32Status == VRDP_BC_ENTRY_STATUS_CACHED) 342 { 343 return VRDPBMP_RC_ALREADY_CACHED; 344 } 345 346 /* The status must be VRDP_BC_ENTRY_STATUS_TEMPORARY here. 347 * Update it to *_CACHED. 348 */ 349 if (pEntry->u32Status != VRDP_BC_ENTRY_STATUS_TEMPORARY) 350 { 351 LOG(("MEMBLT: vrdpbmpCacheSurface: unexpected status %d.", pEntry->u32Status)); 352 return VRDPBMP_RC_NOT_CACHED; 353 } 354 355 bcMoveTmpToCached(pCache, pEntry); 356 357 pEntry->u32Status = VRDP_BC_ENTRY_STATUS_CACHED; 358 return VRDPBMP_RC_CACHED; 359 } 360 361 int rc = bcInsertHash (pCache, &hash, phashDeleted, bForce); 362 LOG(("vrdpbmpCacheSurface: insert hash %x.", rc)); 197 363 198 364 return rc; … … 206 372 Assert(sizeof (VRDPBCHASH) == sizeof (VRDEBITMAPHASH)); 207 373 374 LOG(("vrdpbmpReset: %p.", pCache)); 375 208 376 /* Reinitialize the cache structure. */ 209 377 memset(pCache, 0, sizeof (VRDPBC)); 210 378 211 pCache->head = &pCache->aEntries[0];212 pCache->tail = &pCache->aEntries[RT_ELEMENTS(pCache->aEntries) - 1];379 pCache->headTmp = &pCache->aEntries[0]; 380 pCache->tailTmp = &pCache->aEntries[RT_ELEMENTS(pCache->aEntries) - 1]; 213 381 214 382 for (i = 0; i < RT_ELEMENTS(pCache->aEntries); i++) … … 216 384 VRDPBCENTRY *pEntry = &pCache->aEntries[i]; 217 385 218 if (pEntry != pCache->tail )386 if (pEntry != pCache->tailTmp) 219 387 { 220 388 pEntry->next = &pCache->aEntries[i + 1]; 221 389 } 222 390 223 if (pEntry != pCache->head )391 if (pEntry != pCache->headTmp) 224 392 { 225 393 pEntry->prev = &pCache->aEntries[i - 1]; 226 394 } 227 395 } 228 } 396 397 pCache->headCached = NULL; 398 pCache->tailCached = NULL; 399 } -
trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/xpdm/VBoxDispVrdpBmp.h
r36867 r45768 6 6 7 7 /* 8 * Copyright (C) 2011 Oracle Corporation8 * Copyright (C) 2011-2013 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 56 56 #pragma pack () 57 57 58 #define VRDP_BC_ENTRY_STATUS_EMPTY 0 59 #define VRDP_BC_ENTRY_STATUS_TEMPORARY 1 60 #define VRDP_BC_ENTRY_STATUS_CACHED 2 61 58 62 typedef struct _VRDPBCENTRY 59 63 { 60 bool fUsed;61 64 struct _VRDPBCENTRY *next; 62 65 struct _VRDPBCENTRY *prev; 63 66 VRDPBCHASH hash; 67 uint32_t u32Status; 64 68 } VRDPBCENTRY; 65 69 66 70 typedef struct _VRDPBC 67 71 { 68 VRDPBCENTRY *head; 69 VRDPBCENTRY *tail; 72 VRDPBCENTRY *headTmp; 73 VRDPBCENTRY *tailTmp; 74 VRDPBCENTRY *headCached; 75 VRDPBCENTRY *tailCached; 70 76 VRDPBCENTRY aEntries[VRDPBMP_N_CACHED_BITMAPS]; 71 77 } VRDPBC; 72 78 73 79 void vrdpbmpReset (VRDPBC *pCache); 74 int vrdpbmpCacheSurface (VRDPBC *pCache, const SURFOBJ *pso, VRDPBCHASH *phash, VRDPBCHASH *phashDeleted );80 int vrdpbmpCacheSurface (VRDPBC *pCache, const SURFOBJ *pso, VRDPBCHASH *phash, VRDPBCHASH *phashDeleted, BOOL bForce); 75 81 76 82 #endif /*VBOXDISPVRDPBMP_H*/
Note:
See TracChangeset
for help on using the changeset viewer.