Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2644 lines
99 KiB

  1. /****************************************************************************/
  2. // nsbcdisp.c
  3. //
  4. // RDP Send Bitmap Cache display driver code
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <precmpdd.h>
  9. #define hdrstop
  10. #define TRC_FILE "nsbcdisp"
  11. #include <adcg.h>
  12. #include <atrcapi.h>
  13. #define DC_INCLUDE_DATA
  14. #include <ndddata.c>
  15. #include <noedata.c>
  16. #undef DC_INCLUDE_DATA
  17. #include <asbcapi.h>
  18. #include <nsbcdisp.h>
  19. #include <noadisp.h>
  20. #include <abcapi.h>
  21. #include <nprcount.h>
  22. #include <nschdisp.h>
  23. #include <nchdisp.h>
  24. #include <noedisp.h>
  25. #include <nsbcinl.h>
  26. #include <nsbcddat.c>
  27. #ifdef DC_DEBUG
  28. BOOL SBC_VerifyBitmapBits(PBYTE pBitmapData, unsigned cbBitmapSize, UINT iCacheID, UINT iCacheIndex);
  29. #endif
  30. /****************************************************************************/
  31. // SBC_DDInit: SBC display driver initialization function.
  32. /****************************************************************************/
  33. void RDPCALL SBC_DDInit(PDD_PDEV pPDev)
  34. {
  35. DC_BEGIN_FN("SBC_DDInit");
  36. // Initializes all the global data for this component.
  37. #define DC_INIT_DATA
  38. #include <nsbcddat.c>
  39. #undef DC_INIT_DATA
  40. #ifndef DC_HICOLOR
  41. sbcClientBitsPerPel = pPDev->cClientBitsPerPel;
  42. #endif
  43. TRC_NRM((TB, "Completed SBC_DDInit"));
  44. DC_END_FN();
  45. }
  46. /****************************************************************************/
  47. // SBC_InitShm(): Inits the SBC shm component on connect/reconnect.
  48. /****************************************************************************/
  49. void RDPCALL SBC_InitShm(void)
  50. {
  51. DC_BEGIN_FN("SBC_InitShm");
  52. // Zero only the parts which need to be zeroed.
  53. memset(&pddShm->sbc, 0, sizeof(SBC_SHARED_DATA));
  54. DC_END_FN();
  55. }
  56. /****************************************************************************/
  57. // SBCProcessBitmapKeyDatabase
  58. //
  59. // Given persistent bitmap key database, populates caches.
  60. /****************************************************************************/
  61. __inline void RDPCALL SBCProcessBitmapKeyDatabase(
  62. SBC_BITMAP_CACHE_KEY_INFO *pKeyDatabase)
  63. {
  64. unsigned i, j;
  65. #ifdef DC_DEBUG
  66. unsigned BitmapHdrSize;
  67. SBC_BITMAP_CACHE_EXTRA_INFO *pBitmapHdr;
  68. #endif
  69. DC_BEGIN_FN("SBCProcessBitmapKeyDatabase");
  70. // This call should not be made if the database ptr is NULL.
  71. TRC_ASSERT((pKeyDatabase != NULL), (TB,"NULL pKeyDatabase"));
  72. for (i = 0; i < pddShm->sbc.NumBitmapCaches; i++) {
  73. TRC_NRM((TB,"Cache %d: %d keys", i, pKeyDatabase->NumKeys[i]));
  74. // Place each persistent key in its corresponding index
  75. // in the cache. Note that the MRU sequence is implicit in the
  76. // order in the database -- CH_ForceCacheKeyAtIndex() appends the
  77. // entry to the MRU.
  78. for (j = 0; j < pKeyDatabase->NumKeys[i]; j++) {
  79. if ((&(pKeyDatabase->Keys[pKeyDatabase->KeyStart[i]]))[j].Key1 !=
  80. TS_BITMAPCACHE_NULL_KEY ||
  81. (&(pKeyDatabase->Keys[pKeyDatabase->KeyStart[i]]))[j].Key2 !=
  82. TS_BITMAPCACHE_NULL_KEY) {
  83. #ifdef DC_DEBUG
  84. // We have no cache bits, so set the header data size to zero
  85. // on debug.
  86. BitmapHdrSize = sizeof(SBC_BITMAP_CACHE_EXTRA_INFO) +
  87. SBC_CellSizeFromCacheID(i);
  88. if (pddShm->sbc.bitmapCacheInfo[i].pExtraEntryInfo != NULL) {
  89. pBitmapHdr = (SBC_BITMAP_CACHE_EXTRA_INFO *)(pddShm->sbc.
  90. bitmapCacheInfo[i].pExtraEntryInfo +
  91. (&(pKeyDatabase->Keys[pKeyDatabase->KeyStart[i]]))[j].CacheIndex *
  92. BitmapHdrSize);
  93. pBitmapHdr->DataSize = 0;
  94. }
  95. #endif
  96. // We have to set the UserDefined to NULL since we have no
  97. // associated fast-path cache entry pointer.
  98. CH_ForceCacheKeyAtIndex(
  99. pddShm->sbc.bitmapCacheInfo[i].cacheHandle,
  100. (&(pKeyDatabase->Keys[pKeyDatabase->KeyStart[i]]))[j].CacheIndex,
  101. (&(pKeyDatabase->Keys[pKeyDatabase->KeyStart[i]]))[j].Key1,
  102. (&(pKeyDatabase->Keys[pKeyDatabase->KeyStart[i]]))[j].Key2,
  103. NULL);
  104. }
  105. }
  106. }
  107. DC_END_FN();
  108. }
  109. /****************************************************************************/
  110. // SBCAllocBitmapCache; Allocates bitmap cache data buffers according to the
  111. // current negotiated capabilities.
  112. //
  113. // Returns: SBC_BITMAP_CACHE_ENABLED if successful, 0 otherwise.
  114. /****************************************************************************/
  115. unsigned RDPCALL SBCAllocBitmapCache(PCHCACHEHANDLE pCacheHandle)
  116. {
  117. SIZEL TileSize;
  118. BOOLEAN rc;
  119. unsigned i, j;
  120. unsigned TotalCacheEntries;
  121. unsigned iFormat;
  122. PSBC_BITMAP_CACHE_INFO pInfo;
  123. PCHCACHEDATA pCacheData;
  124. #if DC_DEBUG
  125. unsigned BitmapHdrSize;
  126. #endif
  127. DC_BEGIN_FN("SBCAllocBitmapCache");
  128. TRC_NRM((TB, "Alloc bitmap cache data and work bitmaps"));
  129. rc = FALSE;
  130. i = j = 0;
  131. // Cell caching is disabled if NumCellCaches is zero. It is set to
  132. // zero by the WD caps negotiation code if the client indicated zero,
  133. // if any of the requested cell cache NumEntries is zero, or if the rev1
  134. // caps returned a CacheNMaximumCellSize that was not the required tile
  135. // size.
  136. if (pddShm->sbc.NumBitmapCaches > 0) {
  137. // Work tile bitmap format type, and translation buffer for 4bpp to
  138. // 8bpp conversions. The translation buffer must be as large as the
  139. // largest tile size.
  140. if (sbcClientBitsPerPel != 4) {
  141. #ifdef DC_HICOLOR
  142. if (sbcClientBitsPerPel == 24)
  143. {
  144. iFormat = BMF_24BPP;
  145. }
  146. else if ((sbcClientBitsPerPel == 16) || (sbcClientBitsPerPel == 15))
  147. {
  148. iFormat = BMF_16BPP;
  149. }
  150. else
  151. {
  152. iFormat = BMF_8BPP;
  153. }
  154. #else
  155. iFormat = BMF_8BPP;
  156. #endif
  157. }
  158. else {
  159. iFormat = BMF_4BPP;
  160. sbcXlateBuf = EngAllocMem(0, SBC_CellSizeFromCacheID(
  161. pddShm->sbc.NumBitmapCaches - 1), DD_ALLOC_TAG);
  162. if (sbcXlateBuf == NULL) {
  163. TRC_ERR((TB,"Failed to create 4bpp to 8bpp translate buf"));
  164. DC_QUIT;
  165. }
  166. }
  167. TotalCacheEntries = 0;
  168. for (i = 0; i < pddShm->sbc.NumBitmapCaches; i++) {
  169. pInfo = &(pddShm->sbc.bitmapCacheInfo[i]);
  170. // Create a square work tile bitmap.
  171. // We set the last parameter to NULL, to allow GDI to allocate
  172. // memory for the bits. We can get a pointer to the bits later
  173. // when we have a SURFOBJ for the bitmap.
  174. TileSize.cx = TileSize.cy = (SBC_CACHE_0_DIMENSION << i);
  175. pddShm->sbc.bitmapCacheInfo[i].hWorkBitmap = (HSURF)
  176. EngCreateBitmap(TileSize,
  177. TS_BYTES_IN_SCANLINE(TileSize.cx, sbcClientBitsPerPel),
  178. iFormat, 0, NULL);
  179. if (pddShm->sbc.bitmapCacheInfo[i].hWorkBitmap == NULL) {
  180. TRC_ERR((TB, "Failed to create work bitmap %d", i));
  181. DC_QUIT;
  182. }
  183. #ifdef DC_DEBUG
  184. // Alloc set of SBC_BITMAP_DATA_HEADERs and space for bitmap
  185. // bits to be kept for comparison in debug builds.
  186. BitmapHdrSize = sizeof(SBC_BITMAP_CACHE_EXTRA_INFO) +
  187. SBC_CellSizeFromCacheID(i);
  188. pInfo->pExtraEntryInfo = EngAllocMem(0,
  189. pInfo->Info.NumEntries * BitmapHdrSize, DD_ALLOC_TAG);
  190. // If persistent cache is enabled and in high-color, we will ask for big memory (~20MB)
  191. // from session space and memory allocation will fail.
  192. // We don't quit here if memory allocation fails since this memory is only for
  193. // comparison use in debug build. We'll check the NULL pointer in every usage of this memory (not many)
  194. if (pInfo->pExtraEntryInfo == NULL) {
  195. TRC_ERR((TB, "Failed to alloc save-bitmap-data memory "
  196. "(cell cache %u)", i));
  197. //DC_QUIT;
  198. }
  199. #endif
  200. // We create the bitmap caches with their indices (cache IDs) in
  201. // the pContext value so we can backtrack the cache ID when
  202. // using the fast-path cache.
  203. if (pInfo->Info.NumEntries) {
  204. pCacheData = (PCHCACHEDATA)(*pCacheHandle);
  205. // Bitmap cache list handle
  206. CH_InitCache(pCacheData, pInfo->Info.NumEntries,
  207. (void *)ULongToPtr(i), TRUE, FALSE, SBCBitmapCacheCallback);
  208. pInfo->cacheHandle = pCacheData;
  209. (BYTE *)(*pCacheHandle) += CH_CalculateCacheSize(
  210. pInfo->Info.NumEntries);
  211. TRC_NRM((TB, "Created cell cache %u: hCache=%p, NumEntries=%u", i,
  212. pInfo->cacheHandle, pInfo->Info.NumEntries));
  213. TotalCacheEntries += pInfo->Info.NumEntries;
  214. // Waiting list cache handle
  215. if (pddShm->sbc.fAllowCacheWaitingList) {
  216. pCacheData = (PCHCACHEDATA)(*pCacheHandle);
  217. CH_InitCache(pCacheData, pInfo->Info.NumEntries,
  218. (void *)ULongToPtr(i), FALSE, FALSE, NULL);
  219. pInfo->waitingListHandle = pCacheData;
  220. (BYTE *)(*pCacheHandle) += CH_CalculateCacheSize(
  221. pInfo->Info.NumEntries);
  222. }
  223. else {
  224. pInfo->waitingListHandle = NULL;
  225. }
  226. }
  227. else {
  228. TRC_ERR((TB, "Zero entry Cache %d", i));
  229. DC_QUIT;
  230. }
  231. }
  232. // Allocate fast path cache.
  233. pCacheData = (PCHCACHEDATA)(*pCacheHandle);
  234. CH_InitCache(pCacheData, TotalCacheEntries,
  235. NULL, TRUE, FALSE, SBCFastPathCacheCallback);
  236. pddShm->sbc.hFastPathCache = pCacheData;
  237. TRC_NRM((TB, "Fast Path Cache created(%p) entries(%u)",
  238. pddShm->sbc.hFastPathCache, TotalCacheEntries));
  239. (BYTE*)(*pCacheHandle) += CH_CalculateCacheSize(TotalCacheEntries);
  240. //
  241. // Color table cache is only required for lo color sessions
  242. // But we need to allocate for shadow case, when a 256 color
  243. // client shadows a high color client or console.
  244. //
  245. // Allocate color table cache. This is required for bitmap caching.
  246. pCacheData = (PCHCACHEDATA)(*pCacheHandle);
  247. CH_InitCache(pCacheData,
  248. SBC_NUM_COLOR_TABLE_CACHE_ENTRIES, NULL, FALSE, FALSE, NULL);
  249. sbcColorTableCacheHandle = pCacheData;
  250. (BYTE *)(*pCacheHandle) += CH_CalculateCacheSize(
  251. SBC_NUM_COLOR_TABLE_CACHE_ENTRIES);
  252. //
  253. // This is only needed for 256 client case.
  254. //
  255. if (sbcClientBitsPerPel <= 8)
  256. {
  257. // Make sure we send a first color table to the client. This is important
  258. // to do here because on a server-initiated sync we no longer force
  259. // the color table to be sent again to save bandwidth. On 8-bit clients
  260. // this is not a problem since the palette is always set with
  261. // DrvSetPalette. However, on 4-bit clients, the client's color tables
  262. // are never initialized until we send one across.
  263. sbcPaletteChanged = TRUE;
  264. }
  265. rc = TRUE;
  266. }
  267. DC_EXIT_POINT:
  268. // If we failed to allocate some or all of the required resources then
  269. // free up any that we did allocate before we return the failure code.
  270. if (rc == FALSE) {
  271. SBCFreeBitmapCacheData();
  272. // Don't waste space for bitmap cache. back it up
  273. for (j = 0; j < i; j++) {
  274. pInfo = &(pddShm->sbc.bitmapCacheInfo[j]);
  275. (BYTE *)(*pCacheHandle) -= CH_CalculateCacheSize(
  276. pInfo->Info.NumEntries);
  277. }
  278. }
  279. DC_END_FN();
  280. return (rc ? SBC_BITMAP_CACHE_ENABLED : 0);
  281. }
  282. /****************************************************************************/
  283. // SBCCreateGlyphCache
  284. //
  285. // Creates a single bitmap cache of a given size. Returns FALSE on failure.
  286. /****************************************************************************/
  287. __inline BOOLEAN RDPCALL SBCCreateGlyphCache(
  288. unsigned cEntries,
  289. unsigned cbCellSize,
  290. PCHCACHEDATA pCacheData)
  291. {
  292. BOOLEAN rc;
  293. DC_BEGIN_FN("SBC_CreateGlyphCache");
  294. if (cEntries != 0 && cbCellSize != 0) {
  295. // Allocate glyph cache.
  296. CH_InitCache(pCacheData, cEntries, NULL, FALSE, TRUE,
  297. SBCGlyphCallback);
  298. rc = TRUE;
  299. }
  300. else {
  301. TRC_ERR((TB, "Zero: cEntries(%u) cbCellSize(%u)", cEntries,
  302. cbCellSize));
  303. rc = FALSE;
  304. }
  305. TRC_NRM((TB, "Created glyph cache: pCacheData(%p), cEntries(%u) "
  306. "cbCellSize(%u)", pCacheData, cEntries, cbCellSize));
  307. DC_END_FN();
  308. return rc;
  309. }
  310. /****************************************************************************/
  311. // SBCCreateFragCache
  312. //
  313. // Creates a single bitmap cache of a given size. Returns FALSE on failure.
  314. /****************************************************************************/
  315. __inline BOOLEAN RDPCALL SBCCreateFragCache(
  316. unsigned cEntries,
  317. unsigned cbCellSize,
  318. PCHCACHEDATA pCacheData)
  319. {
  320. BOOLEAN rc;
  321. DC_BEGIN_FN("SBCCreateFragCache");
  322. if (cEntries != 0 && cbCellSize != 0) {
  323. CH_InitCache(pCacheData, cEntries, NULL, FALSE, FALSE, NULL);
  324. rc = TRUE;
  325. }
  326. else {
  327. TRC_ERR((TB, "Zero: cEntries(%u) cbCellSize(%u)", cEntries,
  328. cbCellSize));
  329. rc = FALSE;
  330. }
  331. TRC_NRM((TB, "Created frag cache: pCacheData(%p), cEntries(%u) "
  332. "cbCellSize(%u)", pCacheData, cEntries, cbCellSize));
  333. DC_END_FN();
  334. return rc;
  335. }
  336. /****************************************************************************/
  337. // SBCAllocGlyphCache: Allocates glyph cache data buffers according to the
  338. // current negotiated capabilities.
  339. //
  340. // Returns: SBC_GLYPH_CACHE_ENABLED if successful, 0 otherwise.
  341. /****************************************************************************/
  342. unsigned RDPCALL SBCAllocGlyphCache(PCHCACHEHANDLE pCacheHandle)
  343. {
  344. BOOLEAN rc;
  345. unsigned i;
  346. PSBC_GLYPH_CACHE_INFO pGlyphCacheInfo;
  347. PSBC_FRAG_CACHE_INFO pFragCacheInfo;
  348. PCHCACHEDATA pCacheData;
  349. DC_BEGIN_FN("SBCAllocGlyphCache");
  350. TRC_NRM((TB, "Alloc glyph cache data"));
  351. rc = FALSE;
  352. // Create glyph cache(s).
  353. if (pddShm->sbc.caps.GlyphSupportLevel > 0) {
  354. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++) {
  355. pGlyphCacheInfo = &(pddShm->sbc.glyphCacheInfo[i]);
  356. pCacheData = (PCHCACHEDATA)(*pCacheHandle);
  357. if (SBCCreateGlyphCache(
  358. pddShm->sbc.caps.glyphCacheSize[i].cEntries,
  359. pddShm->sbc.caps.glyphCacheSize[i].cbCellSize,
  360. pCacheData)) {
  361. TRC_NRM((TB,
  362. "Created glyph cache %u: cEntries(%u), cbCellSize(%u)",
  363. i,
  364. pddShm->sbc.caps.glyphCacheSize[i].cEntries,
  365. pddShm->sbc.caps.glyphCacheSize[i].cbCellSize));
  366. pGlyphCacheInfo->cbCellSize =
  367. pddShm->sbc.caps.glyphCacheSize[i].cbCellSize;
  368. pGlyphCacheInfo->cacheHandle = pCacheData;
  369. (BYTE *)(*pCacheHandle) += CH_CalculateCacheSize(
  370. pddShm->sbc.caps.glyphCacheSize[i].cEntries);
  371. sbcFontCacheInfoListSize += pddShm->sbc.caps.glyphCacheSize[i].cEntries;
  372. rc = TRUE;
  373. }
  374. else {
  375. TRC_ERR((TB,
  376. "Failed to create glyph cache %u: cEntries(%u), cbCellSize(%u)",
  377. i,
  378. pddShm->sbc.caps.glyphCacheSize[i].cEntries,
  379. pddShm->sbc.caps.glyphCacheSize[i].cbCellSize));
  380. pGlyphCacheInfo->cbCellSize = 0;
  381. }
  382. }
  383. // Create fragment cache.
  384. if (rc) {
  385. pFragCacheInfo = pddShm->sbc.fragCacheInfo;
  386. pCacheData = (PCHCACHEDATA)(*pCacheHandle);
  387. if (SBCCreateFragCache(pddShm->sbc.caps.fragCacheSize[0].cEntries,
  388. pddShm->sbc.caps.fragCacheSize[0].cbCellSize,
  389. pCacheData)) {
  390. pFragCacheInfo->cbCellSize = pddShm->sbc.caps.fragCacheSize[0].
  391. cbCellSize;
  392. pFragCacheInfo->cacheHandle = pCacheData;
  393. (BYTE*)(*pCacheHandle) += CH_CalculateCacheSize(
  394. pddShm->sbc.caps.fragCacheSize[0].cEntries);
  395. }
  396. else {
  397. pFragCacheInfo->cbCellSize = 0;
  398. }
  399. }
  400. // Create the list to store font context info data
  401. if (rc ) {
  402. sbcFontCacheInfoList = (PFONTCACHEINFO *) EngAllocMem(0,
  403. sizeof(PFONTCACHEINFO) * sbcFontCacheInfoListSize,
  404. DD_ALLOC_TAG);
  405. }
  406. }
  407. DC_END_FN();
  408. return (rc ? SBC_GLYPH_CACHE_ENABLED : 0);
  409. }
  410. /****************************************************************************/
  411. /* Name: SBCAllocBrushCache */
  412. /* */
  413. /* Purpose: Allocates brush cache data buffers according to the */
  414. /* current negotiated capabilities. */
  415. /* */
  416. /* Returns: TRUE if successful, FALSE otherwise. */
  417. /****************************************************************************/
  418. unsigned RDPCALL SBCAllocBrushCache(PCHCACHEHANDLE pCacheHandle)
  419. {
  420. BOOLEAN rc = FALSE;
  421. PCHCACHEDATA pCacheData;
  422. DC_BEGIN_FN("SBCAllocBrushCache");
  423. TRC_NRM((TB, "Alloc brush cache data"));
  424. if (pddShm->sbc.caps.brushSupportLevel > TS_BRUSH_DEFAULT)
  425. {
  426. /********************************************************************/
  427. /* Allocate brush caches */
  428. /********************************************************************/
  429. // small brush cache
  430. pCacheData = (PCHCACHEDATA) (*pCacheHandle);
  431. CH_InitCache(pCacheData, SBC_NUM_BRUSH_CACHE_ENTRIES, NULL,
  432. FALSE, FALSE, NULL);
  433. sbcSmallBrushCacheHandle = pCacheData;
  434. (BYTE *)(*pCacheHandle) += CH_CalculateCacheSize(SBC_NUM_BRUSH_CACHE_ENTRIES);
  435. // large brush cache
  436. pCacheData = (PCHCACHEDATA) (*pCacheHandle);
  437. CH_InitCache(pCacheData, SBC_NUM_BRUSH_CACHE_ENTRIES, NULL,
  438. FALSE, FALSE, NULL);
  439. sbcLargeBrushCacheHandle = pCacheData;
  440. (BYTE *)(*pCacheHandle) += CH_CalculateCacheSize(SBC_NUM_BRUSH_CACHE_ENTRIES);
  441. rc = TRUE;
  442. }
  443. DC_END_FN();
  444. return (rc ? SBC_BRUSH_CACHE_ENABLED : 0);
  445. }
  446. /****************************************************************************/
  447. // SBCAllocOffscreenBitmapCache
  448. /****************************************************************************/
  449. unsigned RDPCALL SBCAllocOffscreenBitmapCache(PCHCACHEHANDLE pCacheHandle)
  450. {
  451. BOOLEAN rc = FALSE;
  452. PCHCACHEDATA pCacheData;
  453. DC_BEGIN_FN("SBCAllocOffscreenBitmapCache");
  454. if (pddShm->sbc.offscreenCacheInfo.supportLevel > TS_OFFSCREEN_DEFAULT) {
  455. // Allocate memory for offscreen bitmap delete list
  456. sbcOffscrBitmapsDelList = (PSBC_OFFSCR_BITMAP_DEL_INFO) EngAllocMem(0,
  457. sizeof(SBC_OFFSCR_BITMAP_DEL_INFO) *
  458. pddShm->sbc.offscreenCacheInfo.cacheEntries,
  459. DD_ALLOC_TAG);
  460. if (sbcOffscrBitmapsDelList) {
  461. pCacheData = (PCHCACHEDATA) (*pCacheHandle);
  462. CH_InitCache(pCacheData, pddShm->sbc.offscreenCacheInfo.cacheEntries, NULL,
  463. TRUE, FALSE, SBCOffscreenCallback);
  464. sbcOffscreenBitmapCacheHandle = pCacheData;
  465. (BYTE *)(*pCacheHandle) +=
  466. CH_CalculateCacheSize(pddShm->sbc.offscreenCacheInfo.cacheEntries);
  467. rc = TRUE;
  468. } else {
  469. rc = FALSE;
  470. }
  471. }
  472. DC_END_FN();
  473. return (rc ? SBC_OFFSCREEN_CACHE_ENABLED : 0);
  474. }
  475. #ifdef DRAW_NINEGRID
  476. /****************************************************************************/
  477. // SBCAllocDrawNineGridBitmapCache
  478. /****************************************************************************/
  479. unsigned RDPCALL SBCAllocDrawNineGridBitmapCache(PCHCACHEHANDLE pCacheHandle)
  480. {
  481. BOOLEAN rc = FALSE;
  482. PCHCACHEDATA pCacheData;
  483. DC_BEGIN_FN("SBCAllocDrawNineGridBitmapCache");
  484. if (pddShm->sbc.drawNineGridCacheInfo.supportLevel > TS_DRAW_NINEGRID_DEFAULT) {
  485. pCacheData = (PCHCACHEDATA) (*pCacheHandle);
  486. CH_InitCache(pCacheData, pddShm->sbc.drawNineGridCacheInfo.cacheEntries, NULL,
  487. FALSE, FALSE, NULL);
  488. sbcDrawNineGridBitmapCacheHandle = pCacheData;
  489. (BYTE *)(*pCacheHandle) +=
  490. CH_CalculateCacheSize(pddShm->sbc.drawNineGridCacheInfo.cacheEntries);
  491. rc = TRUE;
  492. }
  493. DC_END_FN();
  494. return (rc ? SBC_DRAWNINEGRID_CACHE_ENABLED : 0);
  495. }
  496. #endif
  497. #ifdef DRAW_GDIPLUS
  498. /****************************************************************************/
  499. // SBCAllocDrawGdiplusCache
  500. /****************************************************************************/
  501. unsigned RDPCALL SBCAllocDrawGdiplusCache(PCHCACHEHANDLE pCacheHandle)
  502. {
  503. BOOLEAN rc = FALSE;
  504. PCHCACHEDATA pCacheData;
  505. DC_BEGIN_FN("SBCAllocDrawGdiplusCache");
  506. if ((pddShm->sbc.drawGdiplusInfo.supportLevel > TS_DRAW_GDIPLUS_DEFAULT) &&
  507. (pddShm->sbc.drawGdiplusInfo.GdipCacheLevel > TS_DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT)) {
  508. pCacheData = (PCHCACHEDATA) (*pCacheHandle);
  509. sbcGdipGraphicsCacheHandle = (PCHCACHEDATA) (*pCacheHandle);
  510. CH_InitCache(sbcGdipGraphicsCacheHandle, pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries, NULL,
  511. FALSE, FALSE, NULL);
  512. (BYTE *)(*pCacheHandle) +=
  513. CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries);
  514. sbcGdipObjectBrushCacheHandle = (PCHCACHEDATA) (*pCacheHandle);
  515. CH_InitCache(sbcGdipObjectBrushCacheHandle, pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries, NULL,
  516. FALSE, FALSE, NULL);
  517. (BYTE *)(*pCacheHandle) +=
  518. CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries);
  519. sbcGdipObjectPenCacheHandle = (PCHCACHEDATA) (*pCacheHandle);
  520. CH_InitCache(sbcGdipObjectPenCacheHandle, pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries, NULL,
  521. FALSE, FALSE, NULL);
  522. (BYTE *)(*pCacheHandle) +=
  523. CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries);
  524. sbcGdipObjectImageCacheHandle = (PCHCACHEDATA) (*pCacheHandle);
  525. CH_InitCache(sbcGdipObjectImageCacheHandle, pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries, NULL,
  526. FALSE, FALSE, NULL);
  527. (BYTE *)(*pCacheHandle) +=
  528. CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries);
  529. sbcGdipObjectImageAttributesCacheHandle = (PCHCACHEDATA) (*pCacheHandle);
  530. CH_InitCache(sbcGdipObjectImageAttributesCacheHandle, pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries, NULL,
  531. FALSE, FALSE, NULL);
  532. (BYTE *)(*pCacheHandle) +=
  533. CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries);
  534. sbcGdipGraphicsCacheChunkSize = pddShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipGraphicsCacheChunkSize;
  535. sbcGdipObjectBrushCacheChunkSize = pddShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipObjectBrushCacheChunkSize;
  536. sbcGdipObjectPenCacheChunkSize = pddShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipObjectPenCacheChunkSize;
  537. sbcGdipObjectImageAttributesCacheChunkSize = pddShm->sbc.drawGdiplusInfo.GdipCacheChunkSize.GdipObjectImageAttributesCacheChunkSize;
  538. sbcGdipObjectImageCacheChunkSize = pddShm->sbc.drawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheChunkSize;
  539. sbcGdipObjectImageCacheMaxSize = pddShm->sbc.drawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheMaxSize;
  540. sbcGdipObjectImageCacheTotalSize = pddShm->sbc.drawGdiplusInfo.GdipImageCacheProperties.GdipObjectImageCacheTotalSize;
  541. sbcGdipObjectImageCacheSizeUsed = 0;
  542. sbcGdipObjectImageCacheSizeList = (UINT16 *)EngAllocMem(0,
  543. pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries * sizeof(UINT16), DD_ALLOC_TAG);
  544. if (sbcGdipObjectImageCacheSizeList == NULL) {
  545. rc = FALSE;
  546. DC_QUIT;
  547. }
  548. rc = TRUE;
  549. }
  550. DC_END_FN();
  551. DC_EXIT_POINT:
  552. return (rc ? SBC_DRAWGDIPLUS_CACHE_ENABLED : 0);
  553. }
  554. #endif // DRAW_GDIPLUS
  555. void RDPCALL SBCAllocCaches(void)
  556. {
  557. UINT i;
  558. ULONG cacheSize;
  559. PCHCACHEDATA pCacheData;
  560. DC_BEGIN_FN("SBCAllocCaches");
  561. TRC_NRM((TB, "Alloc SBC cache data"));
  562. // Initialize cacheSize;
  563. cacheSize = 0;
  564. // Calculate glyph fragment cache sizes.
  565. if (pddShm->sbc.caps.GlyphSupportLevel > 0) {
  566. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++)
  567. cacheSize += CH_CalculateCacheSize(
  568. pddShm->sbc.caps.glyphCacheSize[i].cEntries);
  569. cacheSize += CH_CalculateCacheSize(
  570. pddShm->sbc.caps.fragCacheSize[0].cEntries);
  571. }
  572. if (pddShm->sbc.NumBitmapCaches > 0) {
  573. UINT totalEntries = 0;
  574. // Calculate bitmap cache sizes
  575. for (i = 0; i < pddShm->sbc.NumBitmapCaches; i++) {
  576. // one for the cache, another for the waiting list
  577. if (pddShm->sbc.fAllowCacheWaitingList) {
  578. cacheSize += CH_CalculateCacheSize(
  579. pddShm->sbc.bitmapCacheInfo[i].Info.NumEntries) * 2;
  580. }
  581. else {
  582. cacheSize += CH_CalculateCacheSize(
  583. pddShm->sbc.bitmapCacheInfo[i].Info.NumEntries);
  584. }
  585. totalEntries += pddShm->sbc.bitmapCacheInfo[i].Info.NumEntries;
  586. }
  587. // fast path cache
  588. cacheSize += CH_CalculateCacheSize(totalEntries);
  589. // Calculate color table cache
  590. cacheSize += CH_CalculateCacheSize(
  591. SBC_NUM_COLOR_TABLE_CACHE_ENTRIES);
  592. }
  593. // Calculate brush cache size
  594. if (pddShm->sbc.caps.brushSupportLevel > TS_BRUSH_DEFAULT) {
  595. // both large brush cache and small brush cache
  596. cacheSize += CH_CalculateCacheSize(SBC_NUM_BRUSH_CACHE_ENTRIES) * 2;
  597. }
  598. // Calculate offscreen cache size
  599. if (pddShm->sbc.offscreenCacheInfo.supportLevel > TS_OFFSCREEN_DEFAULT) {
  600. cacheSize += CH_CalculateCacheSize(pddShm->sbc.offscreenCacheInfo.cacheEntries);
  601. }
  602. #ifdef DRAW_NINEGRID
  603. // Calculate drawstream cache size
  604. if (pddShm->sbc.drawNineGridCacheInfo.supportLevel > TS_DRAW_NINEGRID_DEFAULT) {
  605. cacheSize += CH_CalculateCacheSize(pddShm->sbc.drawNineGridCacheInfo.cacheEntries);
  606. }
  607. #endif
  608. #ifdef DRAW_GDIPLUS
  609. // Calculate drawgdiplus cache size
  610. if ((pddShm->sbc.drawGdiplusInfo.supportLevel > TS_DRAW_GDIPLUS_DEFAULT) &&
  611. (pddShm->sbc.drawGdiplusInfo.GdipCacheLevel > TS_DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT)) {
  612. cacheSize += CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipGraphicsCacheEntries);
  613. cacheSize += CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectBrushCacheEntries);
  614. cacheSize += CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectPenCacheEntries);
  615. cacheSize += CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageCacheEntries);
  616. cacheSize += CH_CalculateCacheSize(pddShm->sbc.drawGdiplusInfo.GdipCacheEntries.GdipObjectImageAttributesCacheEntries);
  617. }
  618. #endif
  619. // Allocate memory for the cache
  620. if (cacheSize)
  621. sbcCacheData = (PCHCACHEDATA)EngAllocMem(0, cacheSize, DD_ALLOC_TAG);
  622. DC_END_FN();
  623. }
  624. /****************************************************************************/
  625. // SBC_Update: Allocate and initialize data structures according to the
  626. // current negotiated capabilities.
  627. /****************************************************************************/
  628. void RDPCALL SBC_Update(SBC_BITMAP_CACHE_KEY_INFO *pKeyDatabase)
  629. {
  630. PCHCACHEDATA pCacheData;
  631. DC_BEGIN_FN("SBC_Update");
  632. SBCFreeCacheData();
  633. #ifdef DC_HICOLOR
  634. // Update the client bits per pel
  635. sbcClientBitsPerPel = pddShm->sbc.clientBitsPerPel;
  636. switch (sbcClientBitsPerPel)
  637. {
  638. case 24:
  639. {
  640. sbcCacheFlags = TS_CacheBitmapRev2_24BitsPerPel;
  641. }
  642. break;
  643. case 15:
  644. case 16:
  645. {
  646. sbcCacheFlags = TS_CacheBitmapRev2_16BitsPerPel;
  647. }
  648. break;
  649. default:
  650. {
  651. sbcCacheFlags = TS_CacheBitmapRev2_8BitsPerPel;
  652. }
  653. break;
  654. }
  655. #endif
  656. if (pddShm->sbc.fCachingEnabled) {
  657. TRC_NRM((TB, "Alloc cache data"));
  658. sbcEnabled = SBC_NO_CACHE_ENABLED;
  659. SBCAllocCaches();
  660. if (sbcCacheData) {
  661. pCacheData = sbcCacheData;
  662. // Create glyph and fragment cache(s).
  663. sbcEnabled |= SBCAllocGlyphCache(&pCacheData);
  664. // Create bitmap cache(s), work bitmaps, and color table cache.
  665. sbcEnabled |= SBCAllocBitmapCache(&pCacheData);
  666. // We expect the key database to have come to us by the time we get
  667. // here.
  668. if (sbcEnabled & SBC_BITMAP_CACHE_ENABLED) {
  669. if (pKeyDatabase != NULL)
  670. SBCProcessBitmapKeyDatabase(pKeyDatabase);
  671. }
  672. // Create brush cache.
  673. sbcEnabled |= SBCAllocBrushCache(&pCacheData);
  674. if (!(sbcEnabled & SBC_BRUSH_CACHE_ENABLED))
  675. pddShm->sbc.caps.brushSupportLevel = TS_BRUSH_DEFAULT;
  676. sbcEnabled |= SBCAllocOffscreenBitmapCache(&pCacheData);
  677. if (!(sbcEnabled & SBC_OFFSCREEN_CACHE_ENABLED)) {
  678. pddShm->sbc.offscreenCacheInfo.supportLevel =
  679. TS_OFFSCREEN_DEFAULT;
  680. }
  681. #ifdef DRAW_NINEGRID
  682. sbcEnabled |= SBCAllocDrawNineGridBitmapCache(&pCacheData);
  683. if (!(sbcEnabled & SBC_DRAWNINEGRID_CACHE_ENABLED)) {
  684. pddShm->sbc.drawNineGridCacheInfo.supportLevel =
  685. TS_DRAW_NINEGRID_DEFAULT;
  686. }
  687. #endif
  688. #ifdef DRAW_GDIPLUS
  689. sbcEnabled |= SBCAllocDrawGdiplusCache(&pCacheData);
  690. if (!(sbcEnabled & SBC_DRAWGDIPLUS_CACHE_ENABLED)) {
  691. pddShm->sbc.drawGdiplusInfo.GdipCacheLevel = TS_DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT;
  692. }
  693. #endif
  694. }
  695. else {
  696. // Force brush cache disabled to prevent use of the caches.
  697. pddShm->sbc.caps.brushSupportLevel = TS_BRUSH_DEFAULT;
  698. // Force offscreen cache disabled
  699. pddShm->sbc.offscreenCacheInfo.supportLevel =
  700. TS_OFFSCREEN_DEFAULT;
  701. #ifdef DRAW_NINEGRID
  702. // Force drawstream cache disabled
  703. pddShm->sbc.drawNineGridCacheInfo.supportLevel =
  704. TS_DRAW_NINEGRID_DEFAULT;
  705. #endif
  706. }
  707. }
  708. else {
  709. // Force brush cache disabled to prevent use of the caches.
  710. pddShm->sbc.caps.brushSupportLevel = TS_BRUSH_DEFAULT;
  711. // Force offscreen cache disabled
  712. pddShm->sbc.offscreenCacheInfo.supportLevel =
  713. TS_OFFSCREEN_DEFAULT;
  714. #ifdef DRAW_NINEGRID
  715. // Force drawstream cache disabled
  716. pddShm->sbc.drawNineGridCacheInfo.supportLevel =
  717. TS_DRAW_NINEGRID_DEFAULT;
  718. #endif
  719. }
  720. pddShm->sbc.newCapsData = FALSE;
  721. DC_END_FN();
  722. }
  723. /****************************************************************************/
  724. // SBCFreeGlyphCacheData: Free glyph cache data buffers.
  725. /****************************************************************************/
  726. __inline void RDPCALL SBCFreeGlyphCacheData(void)
  727. {
  728. unsigned i;
  729. PSBC_GLYPH_CACHE_INFO pGlyphCacheInfo;
  730. PSBC_FRAG_CACHE_INFO pFragCacheInfo;
  731. DC_BEGIN_FN("SBCFreeGlyphCacheData");
  732. TRC_NRM((TB, "Free glyph cache data"));
  733. // Free glyph cache(s).
  734. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++) {
  735. pGlyphCacheInfo = &(pddShm->sbc.glyphCacheInfo[i]);
  736. if (pGlyphCacheInfo->cacheHandle != NULL) {
  737. CH_ClearCache(pGlyphCacheInfo->cacheHandle);
  738. pGlyphCacheInfo->cacheHandle = NULL;
  739. pGlyphCacheInfo->cbCellSize = 0;
  740. }
  741. }
  742. // Free fragment cache.
  743. pFragCacheInfo = pddShm->sbc.fragCacheInfo;
  744. if (pFragCacheInfo->cacheHandle != NULL) {
  745. CH_ClearCache(pFragCacheInfo->cacheHandle);
  746. pFragCacheInfo->cacheHandle = NULL;
  747. pFragCacheInfo->cbCellSize = 0;
  748. }
  749. // Free the font cache info list
  750. if (sbcFontCacheInfoList != 0) {
  751. // Reset all the font cache info to 0.
  752. for (i = 0; i < sbcFontCacheInfoListIndex; i++) {
  753. if (sbcFontCacheInfoList[i] != 0) {
  754. memset(sbcFontCacheInfoList[i], 0, sizeof(FONTCACHEINFO));
  755. }
  756. }
  757. // Free the font cache info list
  758. EngFreeMem(sbcFontCacheInfoList);
  759. sbcFontCacheInfoList = 0;
  760. sbcFontCacheInfoListSize = 0;
  761. sbcFontCacheInfoListIndex = 0;
  762. }
  763. sbcEnabled &= ~SBC_GLYPH_CACHE_ENABLED;
  764. DC_END_FN();
  765. }
  766. /****************************************************************************/
  767. /* Name: SBCFreeBrushCacheData */
  768. /* */
  769. /* Purpose: Free brush cache data buffers. */
  770. /****************************************************************************/
  771. void RDPCALL SBCFreeBrushCacheData(void)
  772. {
  773. DC_BEGIN_FN("SBCFreeBrushCacheData");
  774. TRC_NRM((TB, "Free brush cache data"));
  775. /************************************************************************/
  776. /* Free brush cache */
  777. /************************************************************************/
  778. if (sbcSmallBrushCacheHandle != 0)
  779. {
  780. CH_ClearCache(sbcSmallBrushCacheHandle);
  781. sbcSmallBrushCacheHandle = 0;
  782. }
  783. if (sbcLargeBrushCacheHandle != 0)
  784. {
  785. CH_ClearCache(sbcLargeBrushCacheHandle);
  786. sbcLargeBrushCacheHandle = 0;
  787. }
  788. sbcEnabled &= ~SBC_BRUSH_CACHE_ENABLED;
  789. DC_END_FN();
  790. }
  791. /****************************************************************************/
  792. // SBCFreeOffscreenBitmapCacheData
  793. /****************************************************************************/
  794. void RDPCALL SBCFreeOffscreenBitmapCacheData(void)
  795. {
  796. DC_BEGIN_FN("SBCFreeOffscreenBitmapCacheData");
  797. TRC_NRM((TB, "Free offscreen Bitmap cache data"));
  798. /************************************************************************/
  799. /* Free Offscreen cache */
  800. /************************************************************************/
  801. if (pddShm->sbc.offscreenCacheInfo.supportLevel > TS_OFFSCREEN_DEFAULT)
  802. {
  803. CH_ClearCache(sbcOffscreenBitmapCacheHandle);
  804. }
  805. sbcOffscreenBitmapCacheHandle = 0;
  806. // Free the offscreen bitmap delete list
  807. if (sbcOffscrBitmapsDelList != 0) {
  808. EngFreeMem(sbcOffscrBitmapsDelList);
  809. sbcOffscrBitmapsDelList = 0;
  810. sbcNumOffscrBitmapsToDelete = 0;
  811. sbcOffscrBitmapsToDeleteSize = 0;
  812. }
  813. sbcEnabled &= ~SBC_OFFSCREEN_CACHE_ENABLED;
  814. DC_END_FN();
  815. }
  816. #ifdef DRAW_NINEGRID
  817. /****************************************************************************/
  818. // SBCFreeDrawNineGridBitmapCacheData
  819. /****************************************************************************/
  820. void RDPCALL SBCFreeDrawNineGridBitmapCacheData(void)
  821. {
  822. DC_BEGIN_FN("SBCFreeDrawNineGridBitmapCacheData");
  823. TRC_NRM((TB, "Free drawsninegrid Bitmap cache data"));
  824. /************************************************************************/
  825. // Free DrawNineGrid cache
  826. /************************************************************************/
  827. if (pddShm->sbc.drawNineGridCacheInfo.supportLevel > TS_DRAW_NINEGRID_DEFAULT)
  828. {
  829. CH_ClearCache(sbcDrawNineGridBitmapCacheHandle);
  830. }
  831. sbcDrawNineGridBitmapCacheHandle = 0;
  832. sbcEnabled &= ~SBC_DRAWNINEGRID_CACHE_ENABLED;
  833. DC_END_FN();
  834. }
  835. #endif
  836. #ifdef DRAW_GDIPLUS
  837. /****************************************************************************/
  838. // SBCFreeDrawGdiplusCacheData
  839. /****************************************************************************/
  840. void RDPCALL SBCFreeDrawGdiplusCacheData(void)
  841. {
  842. DC_BEGIN_FN("SBCFreeDrawGdiplusCacheData");
  843. TRC_NRM((TB, "Free drawgdiplus cache data"));
  844. /************************************************************************/
  845. // Free DrawGdiplus cache
  846. /************************************************************************/
  847. if ((pddShm->sbc.drawGdiplusInfo.supportLevel > TS_DRAW_GDIPLUS_DEFAULT) &&
  848. (pddShm->sbc.drawGdiplusInfo.GdipCacheLevel > TS_DRAW_GDIPLUS_CACHE_LEVEL_DEFAULT))
  849. {
  850. CH_ClearCache(sbcGdipGraphicsCacheHandle);
  851. CH_ClearCache(sbcGdipObjectBrushCacheHandle);
  852. CH_ClearCache(sbcGdipObjectPenCacheHandle);
  853. CH_ClearCache(sbcGdipObjectImageCacheHandle);
  854. CH_ClearCache(sbcGdipObjectImageAttributesCacheHandle);
  855. EngFreeMem(sbcGdipObjectImageCacheSizeList);
  856. }
  857. sbcGdipGraphicsCacheHandle = 0;
  858. sbcEnabled &= ~SBC_DRAWGDIPLUS_CACHE_ENABLED;
  859. DC_END_FN();
  860. }
  861. #endif // DRAW_GDIPLUS
  862. /****************************************************************************/
  863. // SBCFreeBitmapCacheData: Free bitmap cache data buffers.
  864. /****************************************************************************/
  865. __inline void RDPCALL SBCFreeBitmapCacheData(void)
  866. {
  867. unsigned i;
  868. PSBC_BITMAP_CACHE_INFO pBitmapCacheInfo;
  869. DC_BEGIN_FN("SBCFreeBitmapCacheData");
  870. TRC_NRM((TB, "Free bitmap cache data"));
  871. // Free cell caches.
  872. for (i = 0; i < pddShm->sbc.NumBitmapCaches; i++) {
  873. pBitmapCacheInfo = &(pddShm->sbc.bitmapCacheInfo[i]);
  874. // Destroy the work bitmap.
  875. if (pBitmapCacheInfo->hWorkBitmap != NULL) {
  876. // The bitmap has been created, so now destroy it. Despite its
  877. // name, EngDeleteSurface is the correct function to do this.
  878. if (EngDeleteSurface(pBitmapCacheInfo->hWorkBitmap))
  879. {
  880. TRC_NRM((TB, "Deleted work bitmap %d", i));
  881. }
  882. else
  883. {
  884. TRC_ERR((TB, "Failed to delete work bitmap %d", i));
  885. }
  886. pBitmapCacheInfo->hWorkBitmap = NULL;
  887. }
  888. if (pBitmapCacheInfo->cacheHandle != NULL) {
  889. CH_ClearCache(pBitmapCacheInfo->cacheHandle);
  890. pBitmapCacheInfo->cacheHandle = NULL;
  891. }
  892. if (pBitmapCacheInfo->waitingListHandle != NULL) {
  893. CH_ClearCache(pBitmapCacheInfo->waitingListHandle);
  894. pBitmapCacheInfo->waitingListHandle = NULL;
  895. }
  896. #ifdef DC_DEBUG
  897. // Free the bitmap header buffer.
  898. if (pBitmapCacheInfo->pExtraEntryInfo != NULL) {
  899. EngFreeMem(pBitmapCacheInfo->pExtraEntryInfo);
  900. pBitmapCacheInfo->pExtraEntryInfo = NULL;
  901. }
  902. #endif
  903. }
  904. if (pddShm->sbc.hFastPathCache != NULL) {
  905. CH_ClearCache(pddShm->sbc.hFastPathCache);
  906. pddShm->sbc.hFastPathCache = NULL;
  907. }
  908. // Free colortable cache.
  909. if (sbcColorTableCacheHandle != NULL) {
  910. CH_ClearCache(sbcColorTableCacheHandle);
  911. sbcColorTableCacheHandle = NULL;
  912. }
  913. // Destroy the 4bpp to 8bpp translation buffer, if present.
  914. if (sbcXlateBuf != NULL) {
  915. EngFreeMem(sbcXlateBuf);
  916. sbcXlateBuf = NULL;
  917. }
  918. sbcEnabled &= ~SBC_BITMAP_CACHE_ENABLED;
  919. DC_END_FN();
  920. }
  921. /****************************************************************************/
  922. // SBCFreeCacheData: Free cache data buffers.
  923. /****************************************************************************/
  924. void RDPCALL SBCFreeCacheData(void)
  925. {
  926. DC_BEGIN_FN("SBCFreeCacheData");
  927. TRC_NRM((TB, "Free cache data"));
  928. if (sbcEnabled != SBC_NO_CACHE_ENABLED) {
  929. // Free glyph and fragment caches.
  930. if (sbcEnabled & SBC_GLYPH_CACHE_ENABLED)
  931. SBCFreeGlyphCacheData();
  932. // Free bitmap cache(s) and color table cache.
  933. if (sbcEnabled & SBC_BITMAP_CACHE_ENABLED)
  934. SBCFreeBitmapCacheData();
  935. // Free brush caches.
  936. if (sbcEnabled & SBC_BRUSH_CACHE_ENABLED) {
  937. SBCFreeBrushCacheData();
  938. }
  939. // Free offscreen cache
  940. if (sbcEnabled & SBC_OFFSCREEN_CACHE_ENABLED) {
  941. SBCFreeOffscreenBitmapCacheData();
  942. }
  943. #ifdef DRAW_NINEGRID
  944. // Free drawstream cache
  945. if (sbcEnabled & SBC_DRAWNINEGRID_CACHE_ENABLED) {
  946. SBCFreeDrawNineGridBitmapCacheData();
  947. }
  948. #endif
  949. #ifdef DRAW_GDIPLUS
  950. // Free drawgdiplus cache
  951. if (sbcEnabled & SBC_DRAWGDIPLUS_CACHE_ENABLED) {
  952. SBCFreeDrawGdiplusCacheData();
  953. }
  954. #endif
  955. if (sbcCacheData) {
  956. EngFreeMem(sbcCacheData);
  957. sbcCacheData = NULL;
  958. }
  959. TRC_ASSERT((sbcEnabled == SBC_NO_CACHE_ENABLED),
  960. (TB, "sbcEnabled should be disabled: %lx", sbcEnabled));
  961. }
  962. DC_END_FN();
  963. }
  964. /****************************************************************************/
  965. // SBC_DDSync
  966. //
  967. // Performs a server-initiated sync, which occurs during the client connection
  968. // sequence after the client responds with a ConfirmActivePDU, the persistent
  969. // bitmap keys, and the font list PDUs. In RDP 4.0 a server-side sync would
  970. // have reset all the caches. In this version we have to be more careful since
  971. // we absolutely do not want to lose any of the current bitmap cache
  972. // information, which includes persistent as well as new keys added since
  973. // connection time.
  974. //
  975. // bMustSync is currently used by DrvShadowConnect() only
  976. /****************************************************************************/
  977. void RDPCALL SBC_DDSync(BOOLEAN bMustSync)
  978. {
  979. unsigned i;
  980. DC_BEGIN_FN("SBC_DDSync");
  981. if ((sbcEnabled != SBC_NO_CACHE_ENABLED) && bMustSync) {
  982. TRC_ALT((TB, "Sync: resetting caches"));
  983. // Reset the glyph and fragment caches.
  984. if (sbcEnabled & SBC_GLYPH_CACHE_ENABLED) {
  985. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++) {
  986. if (pddShm->sbc.glyphCacheInfo[i].cacheHandle != NULL)
  987. CH_ClearCache(pddShm->sbc.glyphCacheInfo[i].cacheHandle);
  988. }
  989. TRC_NRM((TB, "Sync: reset glyph info caches"));
  990. if (pddShm->sbc.fragCacheInfo[0].cacheHandle != NULL) {
  991. CH_ClearCache(pddShm->sbc.fragCacheInfo[0].cacheHandle);
  992. TRC_NRM((TB, "Sync: reset glyph fragment cache"));
  993. }
  994. }
  995. // Reset the brush caches.
  996. if (sbcEnabled & SBC_BRUSH_CACHE_ENABLED)
  997. {
  998. if (sbcSmallBrushCacheHandle) {
  999. TRC_NRM((TB, "Sync: reset small brush cache"));
  1000. CH_ClearCache(sbcSmallBrushCacheHandle);
  1001. }
  1002. if (sbcLargeBrushCacheHandle) {
  1003. TRC_NRM((TB, "Sync: reset large brush cache"));
  1004. CH_ClearCache(sbcLargeBrushCacheHandle);
  1005. }
  1006. }
  1007. // Reset the bitmap, fastpath, and color table caches.
  1008. if (sbcEnabled & SBC_BITMAP_CACHE_ENABLED) {
  1009. for (i = 0; i < pddShm->sbc.NumBitmapCaches; i++)
  1010. if (pddShm->sbc.bitmapCacheInfo[i].cacheHandle != NULL) {
  1011. TRC_NRM((TB, "Sync: reset bitmap cache[%ld]", i));
  1012. CH_ClearCache(pddShm->sbc.bitmapCacheInfo[i].cacheHandle);
  1013. }
  1014. if (pddShm->sbc.hFastPathCache != NULL) {
  1015. TRC_NRM((TB, "Sync: reset fast path bitmap"));
  1016. CH_ClearCache(pddShm->sbc.hFastPathCache);
  1017. }
  1018. // Reset the color table cache.
  1019. if (sbcColorTableCacheHandle != NULL) {
  1020. CH_ClearCache(sbcColorTableCacheHandle);
  1021. TRC_NRM((TB, "Sync: reset color table cache"));
  1022. }
  1023. }
  1024. // Pretend that the palette has changed, so we send a color table
  1025. // before our next MemBlt.
  1026. SBC_PaletteChanged();
  1027. }
  1028. else {
  1029. TRC_NRM((TB, "Nothing to do sbcEnabled(%lx), bMustSync(%ld)",
  1030. sbcEnabled, bMustSync));
  1031. }
  1032. // Reset the sync flag.
  1033. pddShm->sbc.syncRequired = FALSE;
  1034. DC_END_FN();
  1035. }
  1036. /****************************************************************************/
  1037. // SBCSelectGlyphCache: Decides which cache a given max font glyph size
  1038. // should go in.
  1039. //
  1040. // Returns: TRUE if the glyph size can be cached
  1041. // *pCache is updated with the index of the selected cache
  1042. //
  1043. // FALSE if the glyph size cannot be cached
  1044. // *pCache is -1
  1045. //
  1046. // Params: cbSize - size in bytes of the data to be cached
  1047. //
  1048. // pCache - pointer to variable that receives the cache index
  1049. // to use
  1050. /****************************************************************************/
  1051. BOOLEAN RDPCALL SBCSelectGlyphCache(unsigned cbSize, PINT32 pCache)
  1052. {
  1053. int i;
  1054. INT32 cacheId;
  1055. BOOLEAN rc;
  1056. unsigned cbCellSize;
  1057. unsigned cbUseCount;
  1058. DC_BEGIN_FN("SBCSelectGlyphCache");
  1059. *pCache = -1;
  1060. cbUseCount = 0;
  1061. cbCellSize = 65535;
  1062. for (i = 0; i < SBC_NUM_GLYPH_CACHES; i++) {
  1063. if (pddShm->sbc.glyphCacheInfo[i].cbCellSize >= cbSize) {
  1064. if (pddShm->sbc.glyphCacheInfo[i].cbCellSize < cbCellSize) {
  1065. *pCache = i;
  1066. cbCellSize = pddShm->sbc.glyphCacheInfo[i].cbCellSize;
  1067. cbUseCount = pddShm->sbc.glyphCacheInfo[i].cbUseCount;
  1068. }
  1069. else if (pddShm->sbc.glyphCacheInfo[i].cbCellSize == cbCellSize) {
  1070. if (pddShm->sbc.glyphCacheInfo[i].cbUseCount <= cbUseCount) {
  1071. *pCache = i;
  1072. cbCellSize = pddShm->sbc.glyphCacheInfo[i].cbCellSize;
  1073. cbUseCount = pddShm->sbc.glyphCacheInfo[i].cbUseCount;
  1074. }
  1075. }
  1076. }
  1077. }
  1078. if (*pCache != -1) {
  1079. rc = TRUE;
  1080. }
  1081. else {
  1082. TRC_ALT((TB, "Failed to find cache for cbSize(%u)", cbSize));
  1083. rc = FALSE;
  1084. }
  1085. DC_END_FN();
  1086. return rc;
  1087. }
  1088. /****************************************************************************/
  1089. // SBCDDGetTickCount: Get a system tick count.
  1090. //
  1091. // Returns: The number of centi-seconds since the system was started.
  1092. // This number will wrap after approximately 497 days!
  1093. /****************************************************************************/
  1094. __inline UINT32 RDPCALL SBCDDGetTickCount(void)
  1095. {
  1096. LONGLONG perfTickCount;
  1097. /************************************************************************/
  1098. /* Get the number of system ticks since the system was started. */
  1099. /************************************************************************/
  1100. EngQueryPerformanceCounter(&perfTickCount);
  1101. /************************************************************************/
  1102. /* Now convert this into a number of centi-seconds. sbcPerfFrequency */
  1103. /* contains the number of system ticks per second. */
  1104. /************************************************************************/
  1105. return (UINT32)(perfTickCount & 0xFFFFFFFF);
  1106. }
  1107. /****************************************************************************/
  1108. // SBCBitmapCacheCallback
  1109. //
  1110. // Called whenever an entry is evicted from the bitmap cache.
  1111. //
  1112. // Params: hCache - cache handle
  1113. //
  1114. // event - the cache event that has occurred.
  1115. //
  1116. // iCacheEntry - index of the cache entry that the event is affecting
  1117. //
  1118. // pData - pointer to the cache data associated with the given
  1119. // cache entry
  1120. //
  1121. // UserDefined - user-supplied value from CH_CacheKey
  1122. /****************************************************************************/
  1123. BOOLEAN __fastcall SBCBitmapCacheCallback(
  1124. CHCACHEHANDLE hCache,
  1125. unsigned Event,
  1126. unsigned iCacheEntry,
  1127. void *UserDefined)
  1128. {
  1129. DC_BEGIN_FN("SBCBitmapCacheCallback");
  1130. if (Event == CH_EVT_ENTRYREMOVED) {
  1131. TRC_NRM((TB, "Cache entry removed hCache(%p) iCacheEntry(%u)",
  1132. hCache, iCacheEntry));
  1133. // Keep the fast path cache in sync by removing the
  1134. // corresponding fast path entry.
  1135. if (UserDefined != NULL) {
  1136. CH_SetNodeUserDefined((CHNODE *)UserDefined, NULL);
  1137. CH_RemoveCacheEntry(pddShm->sbc.hFastPathCache,
  1138. CH_GetCacheIndexFromNode((CHNODE *)UserDefined));
  1139. TRC_NRM((TB, "Remove fastpath entry %u",
  1140. CH_GetCacheIndexFromNode((CHNODE *)UserDefined)));
  1141. }
  1142. }
  1143. DC_END_FN();
  1144. return TRUE;
  1145. }
  1146. /****************************************************************************/
  1147. // SBCFastPathCacheCallback
  1148. //
  1149. // Called whenever an entry is evicted from the cache.
  1150. //
  1151. // Params: hCache - cache handle
  1152. //
  1153. // Event - the cache event that has occured
  1154. //
  1155. // iCacheEntry - index of the cache entry that the event is affecting
  1156. //
  1157. // UserDefined - value passed in when entry was placed in cache.
  1158. /****************************************************************************/
  1159. BOOLEAN __fastcall SBCFastPathCacheCallback(
  1160. CHCACHEHANDLE hCache,
  1161. unsigned Event,
  1162. unsigned iCacheEntry,
  1163. void *UserDefined)
  1164. {
  1165. DC_BEGIN_FN("SBCFastPathCacheCallback");
  1166. if (Event == CH_EVT_ENTRYREMOVED) {
  1167. TRC_NRM((TB, "Fastpath cache entry removed hCache(%p) "
  1168. "iCacheEntry(%u)", hCache, iCacheEntry));
  1169. if (UserDefined != NULL) {
  1170. // We are losing a fast-path cache entry. UserDefined is a
  1171. // pointer to the node in the main cache corresponding to this
  1172. // fast path entry. Update the main cache entry with a NULL
  1173. // UserDefined to indicate there is no longer an associated
  1174. // fast-path entry.
  1175. CH_SetNodeUserDefined((CHNODE *)UserDefined, NULL);
  1176. }
  1177. }
  1178. DC_END_FN();
  1179. return TRUE;
  1180. }
  1181. /****************************************************************************/
  1182. // SBCGlyphCallback
  1183. //
  1184. // Called whenever an entry is to be evicted from the cache.
  1185. //
  1186. // Params: hCache - cache handle
  1187. //
  1188. // Event - the cache event that has occured
  1189. //
  1190. // iCacheEntry - index of the cache entry that the event is affecting
  1191. //
  1192. // UserDefined - value passed in when entry was placed in cache.
  1193. /****************************************************************************/
  1194. BOOLEAN __fastcall SBCGlyphCallback(
  1195. CHCACHEHANDLE hCache,
  1196. unsigned event,
  1197. unsigned iCacheEntry,
  1198. void *UserDefined)
  1199. {
  1200. BOOLEAN rc;
  1201. unsigned i;
  1202. PGLYPHCONTEXT pglc;
  1203. DC_BEGIN_FN("SBCGlyphCallback");
  1204. rc = TRUE;
  1205. switch (event) {
  1206. /********************************************************************/
  1207. /* We are being asked if the given entry can be evicted from the */
  1208. /* cache. */
  1209. /********************************************************************/
  1210. case CH_EVT_QUERYREMOVEENTRY:
  1211. pglc = (PGLYPHCONTEXT)CH_GetCacheContext(hCache);
  1212. if (pglc != NULL && (UINT_PTR)UserDefined == pglc->cacheTag)
  1213. rc = FALSE;
  1214. break;
  1215. }
  1216. DC_END_FN();
  1217. return rc;
  1218. }
  1219. /****************************************************************************/
  1220. // SBCOffscreenCallback
  1221. //
  1222. // Called whenever an entry is to be evicted from the cache.
  1223. //
  1224. // Params: hCache - cache handle
  1225. //
  1226. // Event - the cache event that has occured
  1227. //
  1228. // iCacheEntry - index of the cache entry that the event is affecting
  1229. //
  1230. // UserDefined - value passed in when entry was placed in cache.
  1231. /****************************************************************************/
  1232. BOOLEAN __fastcall SBCOffscreenCallback(
  1233. CHCACHEHANDLE hCache,
  1234. unsigned event,
  1235. unsigned iCacheEntry,
  1236. void *UserDefined)
  1237. {
  1238. BOOLEAN rc;
  1239. unsigned bitmapSize;
  1240. PGLYPHCONTEXT pglc;
  1241. DC_BEGIN_FN("SBCOffscreenCallback");
  1242. if (event == CH_EVT_ENTRYREMOVED) {
  1243. TRC_NRM((TB, "Offscreen cache entry removed hCache(%p) "
  1244. "iCacheEntry(%u)", hCache, iCacheEntry));
  1245. if (UserDefined != NULL) {
  1246. // We are losing an offscreen cache entry. UserDefined is a
  1247. // handle to the offscreen bitmap that's going to be evicted.
  1248. // We need to set the flag to noOffscreen for this bitmap
  1249. ((PDD_DSURF)UserDefined)->flags |= DD_NO_OFFSCREEN;
  1250. // Get the bitmap size
  1251. // The assumption here is that iFormat is > 1BPP, i << iFormat
  1252. // gives the actual bits per pel. bitmapSize is in bytes.
  1253. if (((PDD_DSURF)UserDefined)->iBitmapFormat < 5) {
  1254. bitmapSize = ((PDD_DSURF)UserDefined)->sizl.cx *
  1255. ((PDD_DSURF)UserDefined)->sizl.cy *
  1256. (1 << ((PDD_DSURF)UserDefined)->iBitmapFormat) / 8;
  1257. }
  1258. else if (((PDD_DSURF)UserDefined)->iBitmapFormat == 5) {
  1259. bitmapSize = ((PDD_DSURF)UserDefined)->sizl.cx *
  1260. ((PDD_DSURF)UserDefined)->sizl.cy * 24 / 8;
  1261. }
  1262. else {
  1263. bitmapSize = ((PDD_DSURF)UserDefined)->sizl.cx *
  1264. ((PDD_DSURF)UserDefined)->sizl.cy * 32 / 8;
  1265. }
  1266. // Current cache size
  1267. oeCurrentOffscreenCacheSize -= bitmapSize;
  1268. // Add this bitmap to the offscreen bitmap delete list
  1269. sbcOffscrBitmapsDelList[sbcNumOffscrBitmapsToDelete].bitmapId = iCacheEntry;
  1270. sbcOffscrBitmapsDelList[sbcNumOffscrBitmapsToDelete].bitmapSize = bitmapSize;
  1271. // Update the delete list data
  1272. sbcNumOffscrBitmapsToDelete++;
  1273. sbcOffscrBitmapsToDeleteSize += bitmapSize;
  1274. }
  1275. }
  1276. DC_END_FN();
  1277. return TRUE;
  1278. }
  1279. BOOLEAN RDPCALL SBC_CopyToWorkBitmap(
  1280. SURFOBJ *pWorkSurf,
  1281. PMEMBLT_ORDER_EXTRA_INFO pMemBltInfo,
  1282. unsigned cxSubBitmapWidth,
  1283. unsigned cySubBitmapHeight,
  1284. PPOINTL ptileOrigin,
  1285. RECTL *pDestRect)
  1286. {
  1287. BOOLEAN rc = FALSE;
  1288. RECTL destRectl;
  1289. unsigned yLastSrcRow;
  1290. DC_BEGIN_FN("SBC_CopyToWorkBitmap");
  1291. // Do the Blt to our work bitmap to perform any color/format
  1292. // conversions to get to screen format.
  1293. //
  1294. // We fiddle with the coords so that the data we want begins at
  1295. // the first byte of the work bitmap (which is the BOTTOM, as the
  1296. // bitmap is stored in bottom-up format).
  1297. //
  1298. // Note that destRectl is in exclusive coords.
  1299. destRectl.top = pMemBltInfo->TileSize - cySubBitmapHeight;
  1300. destRectl.left = 0;
  1301. destRectl.right = cxSubBitmapWidth;
  1302. destRectl.bottom = pMemBltInfo->TileSize;
  1303. // Clip the operation so that EngBitBlt does not try to copy any
  1304. // data from outside the source bitmap (it crashes if you try it!).
  1305. TRC_ASSERT((ptileOrigin->y <
  1306. pMemBltInfo->pSource->sizlBitmap.cy),
  1307. (TB, "Invalid tileOrigin.y(%d) sizlBitmap.cy(%d)",
  1308. ptileOrigin->y, pMemBltInfo->pSource->sizlBitmap.cy));
  1309. yLastSrcRow = ptileOrigin->y + (cySubBitmapHeight - 1);
  1310. if ((int)yLastSrcRow > (pMemBltInfo->pSource->sizlBitmap.cy - 1)) {
  1311. destRectl.bottom -= ((int)yLastSrcRow -
  1312. (pMemBltInfo->pSource->sizlBitmap.cy - 1));
  1313. TRC_ALT((TB, "Clip source from (%d) to (%d)",
  1314. cySubBitmapHeight, destRectl.bottom));
  1315. }
  1316. TRC_NRM((TB, "Blt to work bitmap from src point (%d,%d)",
  1317. ptileOrigin->x, ptileOrigin->y));
  1318. // Reset the work bitmap bits that we will be using if the copied
  1319. // data will not completely fill the area that we are going to
  1320. // cache (there may be some empty space to the right of the bitmap).
  1321. // This ensures that every time a bitmap is cached it has the
  1322. // same (zero) pad bytes and will match previously cached entries.
  1323. // It also aids compression (if enabled).
  1324. if ((destRectl.right - destRectl.left) < (int)pMemBltInfo->TileSize) {
  1325. unsigned cbResetBytes;
  1326. // The lDelta field in the SURFOBJ is negative because the
  1327. // bitmap is a "bottom-up" DIB.
  1328. cbResetBytes = (unsigned)((-pWorkSurf->lDelta) *
  1329. (destRectl.bottom - destRectl.top));
  1330. TRC_NRM((TB, "Reset %u bytes in work bitmap", cbResetBytes));
  1331. TRC_ASSERT((cbResetBytes <= pWorkSurf->cjBits),
  1332. (TB, "cbResetBytes(%u) too big (> %u) lDelta(%d)",
  1333. cbResetBytes, pWorkSurf->cjBits, pWorkSurf->lDelta));
  1334. memset(pWorkSurf->pvBits, 0, cbResetBytes);
  1335. }
  1336. TRC_ASSERT(((destRectl.left >= 0) &&
  1337. (destRectl.top >= 0) &&
  1338. (destRectl.right <= pWorkSurf->sizlBitmap.cx) &&
  1339. (destRectl.bottom <= pWorkSurf->sizlBitmap.cy)),
  1340. (TB, "destRect(%d, %d, %d, %d) exceeds bitmap(%d, %d)",
  1341. destRectl.left, destRectl.top, destRectl.right,
  1342. destRectl.bottom, pWorkSurf->sizlBitmap.cx,
  1343. pWorkSurf->sizlBitmap.cy));
  1344. // Now we have to fill in the backdrop bits for delta RLE bitmaps.
  1345. // We just grab screen bits from the screen bitmap to fill in the
  1346. // extents of the incoming bitmap.
  1347. if (pMemBltInfo->bDeltaRLE) {
  1348. POINTL ScrOrigin;
  1349. ScrOrigin.x = pDestRect->left;
  1350. ScrOrigin.y = pDestRect->top;
  1351. // Need to adjust the coordinates
  1352. if (ScrOrigin.y < 0) {
  1353. destRectl.top += (0 - ScrOrigin.y);
  1354. ScrOrigin.y = 0;
  1355. }
  1356. destRectl.bottom = min(destRectl.bottom,
  1357. (pMemBltInfo->pDest->sizlBitmap.cy -
  1358. ScrOrigin.y + destRectl.top));
  1359. // SRCCOPY screen to work bitmap. Note we use no XlateObj since
  1360. // the color schemes should be the same.
  1361. if (EngCopyBits(pWorkSurf, pMemBltInfo->pDest, NULL, NULL,
  1362. &destRectl, &ScrOrigin)) {
  1363. TRC_NRM((TB,"Blt screen->tile for RLE delta backdrop, "
  1364. "scr src=(%d,%d)", pDestRect->left,
  1365. pDestRect->top));
  1366. }
  1367. else {
  1368. TRC_ERR((TB,"Failed to blt screen data for RLE delta"));
  1369. DC_QUIT;
  1370. }
  1371. }
  1372. // SRCCOPY the final bits to the work bitmap.
  1373. if (!EngCopyBits(pWorkSurf, pMemBltInfo->pSource, NULL,
  1374. pMemBltInfo->pXlateObj, &destRectl, ptileOrigin)) {
  1375. TRC_ERR((TB, "Failed to Blt to work bitmap"));
  1376. DC_QUIT;
  1377. }
  1378. TRC_DBG((TB, "Completed CopyBits"));
  1379. rc = TRUE;
  1380. DC_EXIT_POINT:
  1381. DC_END_FN();
  1382. return rc;
  1383. }
  1384. /****************************************************************************/
  1385. // SBC_CacheBitmapTile
  1386. //
  1387. // Caches the tiled bitmap data for the provided blt info. Returns: TRUE if
  1388. // the data is already cached, or successfully cached and a Cache Bitmap order
  1389. // sent. SrcRect and DestRect are in exclusive coordinates. Returns FALSE
  1390. // if the Cache Bitmap order allocation fails.
  1391. /****************************************************************************/
  1392. BOOLEAN RDPCALL SBC_CacheBitmapTile(
  1393. PDD_PDEV ppdev,
  1394. PMEMBLT_ORDER_EXTRA_INFO pMemBltInfo,
  1395. RECTL *pSrcRect,
  1396. RECTL *pDestRect)
  1397. {
  1398. BOOLEAN rc = FALSE;
  1399. BOOLEAN fSearchFastPath;
  1400. BOOLEAN fFastPathMatch;
  1401. POINTL tileOrigin;
  1402. unsigned cxSubBitmapWidth, cySubBitmapHeight;
  1403. unsigned fastPathIndex;
  1404. SURFOBJ *pWorkSurf = NULL;
  1405. void *UserDefined;
  1406. CHDataKeyContext CHContext;
  1407. DC_BEGIN_FN("SBC_CacheBitmapTile");
  1408. pddCacheStats[BITMAP].CacheReads++;
  1409. TRC_NRM((TB, "Request to cache MemBlt (%d, %d), %d x %d -> (%d, %d), "
  1410. "src %p", pSrcRect->left, pSrcRect->top,
  1411. pSrcRect->right - pSrcRect->left,
  1412. pSrcRect->bottom - pSrcRect->top,
  1413. pDestRect->left, pDestRect->top,
  1414. pMemBltInfo->pSource->hsurf));
  1415. TRC_NRM((TB, "bmpWidth(%u) bmpHeight(%u) TileSize(%u)",
  1416. pMemBltInfo->pSource->sizlBitmap.cx,
  1417. pMemBltInfo->pSource->sizlBitmap.cy,
  1418. pMemBltInfo->TileSize));
  1419. // In stress, we have seen cases where fCachingEnabled is NULL when called
  1420. // in this code path from OEEncodeMemBlt
  1421. if (!pddShm->sbc.fCachingEnabled) {
  1422. DC_QUIT;
  1423. }
  1424. // Calculate the tile origin within the source bitmap coordinates and
  1425. // the size of the remaining bitmap. Origin is rounded down to the
  1426. // nearest tile. Actual size of bitmap to cache may be smaller than
  1427. // tile size if the tile runs off the right/bottom of the bitmap.
  1428. // Note that since TileSize is a power of 2, we can accelerate the
  1429. // modulo operation.
  1430. tileOrigin.x = pSrcRect->left - (pSrcRect->left &
  1431. (pMemBltInfo->TileSize - 1));
  1432. tileOrigin.y = pSrcRect->top - (pSrcRect->top &
  1433. (pMemBltInfo->TileSize - 1));
  1434. // Actual size of bitmap to cache may be smaller than tile size if the
  1435. // tile runs off the right/bottom of the bitmap. To see why this
  1436. // calculation is correct, realize that (bmpWidth - tileOrigin.x) is
  1437. // the remaining width of the bitmap after the start of this tile.
  1438. cxSubBitmapWidth = min(pMemBltInfo->TileSize,
  1439. (unsigned)(pMemBltInfo->pSource->sizlBitmap.cx - tileOrigin.x));
  1440. cySubBitmapHeight = min(pMemBltInfo->TileSize,
  1441. (unsigned)(pMemBltInfo->pSource->sizlBitmap.cy - tileOrigin.y));
  1442. // We need not search the fast-path cache if we've forced fastpath off.
  1443. fSearchFastPath = !pMemBltInfo->bNoFastPathCaching;
  1444. fFastPathMatch = FALSE;
  1445. // The BMF_DONTCACHE flag indicates that the source surface is an
  1446. // application-controlled DIB. The iUniq flag can therefore not be
  1447. // used to determine if/when the bitmap is updated, and we
  1448. // cannot use fastpathing to handle this surface.
  1449. if (pMemBltInfo->pSource->iType == STYPE_BITMAP &&
  1450. pMemBltInfo->pSource->fjBitmap & BMF_DONTCACHE) {
  1451. TRC_NRM((TB, "Source hsurf(%p) has BMF_DONTCACHE set",
  1452. pMemBltInfo->pSource->hsurf));
  1453. fSearchFastPath = FALSE;
  1454. }
  1455. if (fSearchFastPath) {
  1456. SBC_FAST_PATH_INFO fastPathInfo;
  1457. fastPathInfo.hsurf = pMemBltInfo->pSource->hsurf;
  1458. fastPathInfo.iUniq = pMemBltInfo->pSource->iUniq;
  1459. fastPathInfo.iDeviceUniq = pMemBltInfo->iDeviceUniq;
  1460. fastPathInfo.pXlateObj = pMemBltInfo->pXlateObj;
  1461. fastPathInfo.iUniqXlate = ((pMemBltInfo->pXlateObj != NULL) ?
  1462. pMemBltInfo->pXlateObj->iUniq : 0);
  1463. fastPathInfo.tileOrigin = tileOrigin;
  1464. fastPathInfo.TileSize = pMemBltInfo->TileSize;
  1465. fastPathInfo.bDeltaRLE = pMemBltInfo->bDeltaRLE;
  1466. CH_CreateKeyFromFirstData(&CHContext, &fastPathInfo,
  1467. sizeof(fastPathInfo));
  1468. if (CH_SearchCache(pddShm->sbc.hFastPathCache, CHContext.Key1,
  1469. CHContext.Key2, &UserDefined, &fastPathIndex)) {
  1470. CHCACHEHANDLE hCache;
  1471. // Found match in fast path. UserDefined is a pointer to the
  1472. // real CHNODE for the bitmap.
  1473. hCache = CH_GetCacheHandleFromNode((CHNODE *)UserDefined);
  1474. pMemBltInfo->CacheID = (unsigned)(UINT_PTR)CH_GetCacheContext(
  1475. hCache);
  1476. pMemBltInfo->CacheIndex = CH_GetCacheIndexFromNode(
  1477. (CHNODE *)UserDefined);
  1478. TRC_NRM((TB, "FP hit: cacheId(%u) cacheIndex(%u) FPIndex(%u)"
  1479. "hsurf(%p) iUniq(%u) pXlate(%p) iUniqX(%u) "
  1480. "tileOrigin.x(%d) tileOrigin.y(%d) "
  1481. "TileSize(%d), bDeltaRLE(%u)",
  1482. pMemBltInfo->CacheID, pMemBltInfo->CacheIndex,
  1483. fastPathIndex, fastPathInfo.hsurf,
  1484. fastPathInfo.iUniq, fastPathInfo.pXlateObj,
  1485. fastPathInfo.iUniqXlate,
  1486. fastPathInfo.tileOrigin.x, fastPathInfo.tileOrigin.y,
  1487. fastPathInfo.TileSize, fastPathInfo.bDeltaRLE));
  1488. fFastPathMatch = TRUE;
  1489. #ifdef DC_DEBUG
  1490. // Verify that the bits for this are identical to the real bits
  1491. pWorkSurf = EngLockSurface(pddShm->sbc.bitmapCacheInfo[
  1492. pMemBltInfo->TileID].hWorkBitmap);
  1493. if (pWorkSurf)
  1494. {
  1495. if (SBC_CopyToWorkBitmap(pWorkSurf, pMemBltInfo, cxSubBitmapWidth,
  1496. cySubBitmapHeight, &tileOrigin, pDestRect))
  1497. {
  1498. SBC_VerifyBitmapBits(pWorkSurf->pvBits,
  1499. TS_BYTES_IN_BITMAP(pMemBltInfo->TileSize, cySubBitmapHeight, sbcClientBitsPerPel),
  1500. pMemBltInfo->CacheID,
  1501. pMemBltInfo->CacheIndex);
  1502. }
  1503. EngUnlockSurface(pWorkSurf);
  1504. pWorkSurf = NULL;
  1505. }
  1506. #endif //DC_DEBUG
  1507. pddCacheStats[BITMAP].CacheHits++;
  1508. }
  1509. else {
  1510. TRC_NRM((TB, "FP miss: hsurf(%p) iUniq(%u) pXlate(%p) "
  1511. "iUniqX(%u) tileOrigin.x(%d) tileOrigin.y(%d) "
  1512. "TileSize(%d), bDeltaRLE(%u)",
  1513. fastPathInfo.hsurf, fastPathInfo.iUniq,
  1514. fastPathInfo.pXlateObj, fastPathInfo.iUniqXlate,
  1515. fastPathInfo.tileOrigin.x, fastPathInfo.tileOrigin.y,
  1516. fastPathInfo.TileSize, fastPathInfo.bDeltaRLE));
  1517. }
  1518. }
  1519. if (!fFastPathMatch) {
  1520. // We know how large a tile we have - we now have to Blt it into
  1521. // the work bitmap corresponding to the TileID.
  1522. // Lock the work bitmap to get a surface to pass to EngBitBlt.
  1523. pWorkSurf = EngLockSurface(pddShm->sbc.bitmapCacheInfo[
  1524. pMemBltInfo->TileID].hWorkBitmap);
  1525. if (pWorkSurf == NULL) {
  1526. TRC_ERR((TB, "Failed to lock work surface"));
  1527. DC_QUIT;
  1528. }
  1529. TRC_DBG((TB, "Locked surface"));
  1530. if (!SBC_CopyToWorkBitmap(pWorkSurf, pMemBltInfo, cxSubBitmapWidth,
  1531. cySubBitmapHeight, &tileOrigin, pDestRect))
  1532. {
  1533. TRC_ERR((TB, "Failed to copy bitmap to work surface"));
  1534. DC_QUIT;
  1535. }
  1536. // Cache the bits in the main cache, including sending a Cache
  1537. // Bitmap seondary order if need be.
  1538. if (!SBCCacheBits(ppdev, pWorkSurf->pvBits, cxSubBitmapWidth,
  1539. pMemBltInfo->TileSize, cySubBitmapHeight,
  1540. TS_BYTES_IN_BITMAP(pMemBltInfo->TileSize,
  1541. cySubBitmapHeight, sbcClientBitsPerPel),
  1542. pMemBltInfo->TileID,
  1543. #ifdef PERF_SPOILING
  1544. &pMemBltInfo->CacheID, &pMemBltInfo->CacheIndex,
  1545. pMemBltInfo->bIsPrimarySurface)) {
  1546. #else
  1547. &pMemBltInfo->CacheID, &pMemBltInfo->CacheIndex)) {
  1548. #endif
  1549. TRC_ERR((TB, "Failed to cache bits"));
  1550. DC_QUIT;
  1551. }
  1552. // If we could search for this bitmap in the fast-path cache, add
  1553. // it to the fast-path.
  1554. // However, skip this step if the bitmap is in the waiting list only
  1555. if (fSearchFastPath &&
  1556. pMemBltInfo->CacheIndex != BITMAPCACHE_WAITING_LIST_INDEX) {
  1557. CHNODE *pFastPathNode;
  1558. CHCACHEHANDLE hCache;
  1559. // Get the handle of the cache into which we just placed the
  1560. // bitmap.
  1561. hCache = pddShm->sbc.bitmapCacheInfo[pMemBltInfo->CacheID].
  1562. cacheHandle;
  1563. // Check if there is already a fast-path cache entry for this
  1564. // node. If so, we need to remove it before adding this new
  1565. // fast path entry. We maintain a one-to-one correspondence to
  1566. // save memory and time, and because the old fast-path entry is
  1567. // probably stale and won't be seen again.
  1568. //
  1569. // UserDefined in free builds is a pointer to the CHNODE in the
  1570. // real bitmap cache; otherwise it is an indirect pointer
  1571. // to the CHNODE contained in a blob of memory used to hold the
  1572. // bitmap data corresponding to the key to verify that the key
  1573. // generation algorithm is working okay.
  1574. pFastPathNode = (CHNODE *)CH_GetUserDefined(hCache,
  1575. pMemBltInfo->CacheIndex);
  1576. if (pFastPathNode != NULL)
  1577. CH_RemoveCacheEntry(pddShm->sbc.hFastPathCache,
  1578. CH_GetCacheIndexFromNode(pFastPathNode));
  1579. // Reuse the key created before for fast search.
  1580. // We do not care if we evict a fast-path cache entry
  1581. // when adding a new one -- the cache callbacks ensure that
  1582. // both sets of cache entries are updated with respect to each
  1583. // other.
  1584. fastPathIndex = CH_CacheKey(pddShm->sbc.hFastPathCache,
  1585. CHContext.Key1, CHContext.Key2,
  1586. (void *)CH_GetNodeFromCacheIndex(hCache,
  1587. pMemBltInfo->CacheIndex));
  1588. // Now change the UserDefined for the entry in the main cache.
  1589. // This allows us to remove the fast-path entry when main cache
  1590. // entry goes away.
  1591. CH_SetUserDefined(hCache, pMemBltInfo->CacheIndex,
  1592. CH_GetNodeFromCacheIndex(pddShm->sbc.hFastPathCache,
  1593. fastPathIndex));
  1594. TRC_NRM((TB, "FP add: cacheId(%u) cacheIndex(%u) FPIndex(%u)"
  1595. "hsurf(%p) iUniq(%u) pXlate(%p) iUniqX(%u) "
  1596. "tileOrigin.x(%d) tileOrigin.y(%d) TileSize(%d) "
  1597. "bDeltaRLE(%u)",
  1598. pMemBltInfo->CacheID, pMemBltInfo->CacheIndex,
  1599. fastPathIndex, pMemBltInfo->pSource->hsurf,
  1600. pMemBltInfo->pSource->iUniq, pMemBltInfo->pXlateObj,
  1601. ((pMemBltInfo->pXlateObj != NULL) ?
  1602. pMemBltInfo->pXlateObj->iUniq : 0),
  1603. tileOrigin.x, tileOrigin.y,
  1604. pMemBltInfo->TileSize, pMemBltInfo->bDeltaRLE));
  1605. }
  1606. }
  1607. TRC_ASSERT((pMemBltInfo->CacheID < pddShm->sbc.NumBitmapCaches),
  1608. (TB, "Invalid bm cacheid %u (max %u)", pMemBltInfo->CacheID,
  1609. pddShm->sbc.NumBitmapCaches - 1));
  1610. TRC_NRM((TB, "cacheId(%u) cacheIndex(%u)", pMemBltInfo->CacheID,
  1611. pMemBltInfo->CacheIndex));
  1612. rc = TRUE;
  1613. DC_EXIT_POINT:
  1614. if (NULL != pWorkSurf)
  1615. {
  1616. EngUnlockSurface(pWorkSurf);
  1617. TRC_DBG((TB, "Unlocked surface"));
  1618. }
  1619. DC_END_FN();
  1620. return rc;
  1621. }
  1622. /****************************************************************************/
  1623. // SBCSelectBitmapCache
  1624. //
  1625. // Determines the destination cell for a tiled bitmap based on the size and
  1626. // the TileID. Since all bitmaps are derived from tiles, this function cannot
  1627. // fail -- at worst we have to use the same CacheID as the TileID.
  1628. /****************************************************************************/
  1629. __inline unsigned RDPCALL SBCSelectBitmapCache(
  1630. unsigned BitmapSize,
  1631. unsigned TileID)
  1632. {
  1633. unsigned CacheID;
  1634. DC_BEGIN_FN("SBCSelectBitmapCache");
  1635. // We scan from the smallest tile size to the TileID size to try to find
  1636. // the smallest possible size that will hold the bitmap.
  1637. for (CacheID = 0; CacheID < TileID; CacheID++) {
  1638. if (BitmapSize <= (unsigned)SBC_CellSizeFromCacheID(CacheID)) {
  1639. TRC_DBG((TB,"Selected CacheID %u for BitmapSize %u", CacheID,
  1640. BitmapSize));
  1641. break;
  1642. }
  1643. }
  1644. DC_END_FN();
  1645. return CacheID;
  1646. }
  1647. /****************************************************************************/
  1648. // SBCCacheBits: This function ensures that on return the supplied bitmap is
  1649. // in the bitmap cache. If the data is not already in the cache it is added
  1650. // (possibly evicting another entry).
  1651. //
  1652. // Returns: TRUE if the bits have been cached OK, FALSE otherwise
  1653. //
  1654. // Params: IN pOrder - A pointer to a BMC order.
  1655. // IN destBitsSize - The number of bytes available in
  1656. // pOrder to store the bitmap data.
  1657. // IN pDIBits - A pointer to the bits to be cached.
  1658. // IN bitmapWidth - The "in use" width of the bitmap
  1659. // IN fixedBitmapWidth - The actual width of the bitmap
  1660. // IN bitmapHeight - The height of the bitmap
  1661. // IN numBytes - The number of bytes in the bitmap.
  1662. // OUT pCache - The cache that we put the bits into.
  1663. // OUT pCacheIndex - The cache index within *pCache at
  1664. // which we cached the data.
  1665. /****************************************************************************/
  1666. // Encode a value in one or two bytes. The high bit of the first byte is 0 if
  1667. // there is only one byte, 1 if there are 2 (with the 7 low bits of the first
  1668. // byte being most significant).
  1669. __inline void Encode2ByteField(
  1670. BYTE *pEncode,
  1671. unsigned Val,
  1672. unsigned *pOrderSize)
  1673. {
  1674. if (Val <= 127) {
  1675. *pEncode = (BYTE)Val;
  1676. (*pOrderSize)++;
  1677. }
  1678. else {
  1679. *pEncode = (BYTE)(((Val & 0x7F00) >> 8) | 0x80);
  1680. *(pEncode + 1) = (BYTE)(Val & 0x00FF);
  1681. (*pOrderSize) += 2;
  1682. }
  1683. }
  1684. // Encode a value in up to 4 bytes. The high 2 bits of the first byte indicate
  1685. // the length of the encoding -- 00 is 1 byte, 01 is 2 bytes, 10 is 3 bytes,
  1686. // 11 is 4 bytes. The bytes are encoded with the most significant bits in the
  1687. // low 6 bits of the first byte, the least signifiant bits in the last byte.
  1688. __inline void Encode4ByteField(
  1689. BYTE *pEncode,
  1690. unsigned Val,
  1691. unsigned *pOrderSize)
  1692. {
  1693. if (Val <= 0x3F) {
  1694. *pEncode = (BYTE)Val;
  1695. (*pOrderSize)++;
  1696. }
  1697. else if (Val <= 0x3FFF) {
  1698. *pEncode = (BYTE)(((Val & 0x3F00) >> 8) | 0x40);
  1699. *(pEncode + 1) = (BYTE)(Val & 0x00FF);
  1700. (*pOrderSize) += 2;
  1701. }
  1702. else if (Val <= 0x3FFFFF) {
  1703. *pEncode = (BYTE)(((Val & 0x3F0000) >> 16) | 0x80);
  1704. *(pEncode + 1) = (BYTE)((Val & 0x00FF00) >> 8);
  1705. *(pEncode + 2) = (BYTE)(Val & 0x0000FF);
  1706. (*pOrderSize) += 3;
  1707. }
  1708. else {
  1709. *pEncode = (BYTE)(((Val & 0x3F000000) >> 24) | 0xC0);
  1710. *(pEncode + 1) = (BYTE)((Val & 0x00FF0000) >> 16);
  1711. *(pEncode + 2) = (BYTE)((Val & 0x0000FF00) >> 8);
  1712. *(pEncode + 3) = (BYTE)(Val & 0x000000FF);
  1713. (*pOrderSize) += 4;
  1714. }
  1715. }
  1716. #ifdef DC_DEBUG
  1717. BOOL SBC_VerifyBitmapBits(PBYTE pBitmapData, unsigned cbBitmapSize, UINT iCacheID, UINT iCacheIndex)
  1718. {
  1719. BOOL fRetVal = TRUE;
  1720. SBC_BITMAP_CACHE_EXTRA_INFO *pBitmapHdr;
  1721. unsigned BitmapHdrSize;
  1722. BYTE *pStoredBitmapData;
  1723. DC_BEGIN_FN("SBC_VerifyBitmapBits");
  1724. // In debug builds we look for a collision after checking the key
  1725. // and checksum, by comparing the bitmap bits.
  1726. BitmapHdrSize = sizeof(SBC_BITMAP_CACHE_EXTRA_INFO) +
  1727. SBC_CellSizeFromCacheID(iCacheID);
  1728. if (pddShm->sbc.bitmapCacheInfo[iCacheID].pExtraEntryInfo != NULL) {
  1729. pBitmapHdr = (SBC_BITMAP_CACHE_EXTRA_INFO *)(pddShm->sbc.
  1730. bitmapCacheInfo[iCacheID].pExtraEntryInfo +
  1731. BitmapHdrSize * iCacheIndex);
  1732. pStoredBitmapData = (BYTE *)pBitmapHdr +
  1733. sizeof(SBC_BITMAP_CACHE_EXTRA_INFO);
  1734. if (pBitmapHdr->DataSize != 0) {
  1735. TRC_NRM((TB,"Hit non-persistent cell entry, cache=%d, "
  1736. "index=%d", iCacheID, iCacheIndex));
  1737. if (pBitmapHdr->DataSize != cbBitmapSize)
  1738. {
  1739. TRC_ERR((TB,"Size mismatch between stored and new bitmap "
  1740. "data! (stored=0x%X, new=0x%X)", pBitmapHdr->DataSize,
  1741. cbBitmapSize));
  1742. fRetVal = FALSE;
  1743. }
  1744. else
  1745. {
  1746. if (memcmp(pStoredBitmapData, pBitmapData, cbBitmapSize))
  1747. {
  1748. TRC_ERR((TB,"Key-data mismatch - pStoredData=%p, "
  1749. "pNewData=%p, size=0x%X", pStoredBitmapData,
  1750. pBitmapData, cbBitmapSize));
  1751. fRetVal = FALSE;
  1752. }
  1753. }
  1754. }
  1755. else {
  1756. TRC_NRM((TB,"Persistent cell bitmap entry hit, cache=%d, "
  1757. "index=%d", *pCacheID, *pCacheIndex));
  1758. }
  1759. }
  1760. DC_END_FN();
  1761. return fRetVal;
  1762. }
  1763. #endif //DC_DEBUG
  1764. BOOLEAN RDPCALL SBCCacheBits(
  1765. PDD_PDEV ppdev,
  1766. PBYTE pBitmapData,
  1767. unsigned bitmapWidth,
  1768. unsigned paddedBitmapWidth,
  1769. unsigned bitmapHeight,
  1770. unsigned cbBitmapSize,
  1771. unsigned TileID,
  1772. PUINT pCacheID,
  1773. #ifdef PERF_SPOILING
  1774. PUINT pCacheIndex,
  1775. BOOL bIsPrimarySurface)
  1776. #else
  1777. PUINT pCacheIndex)
  1778. #endif
  1779. {
  1780. BOOLEAN rc = TRUE;
  1781. BOOLEAN bOnWaitingList = FALSE;
  1782. unsigned compressedSize;
  1783. PSBC_BITMAP_CACHE_INFO pCacheInfo;
  1784. INT_ORDER *pOrder;
  1785. unsigned BitmapSpace;
  1786. unsigned OrderSize;
  1787. PTS_SECONDARY_ORDER_HEADER pHdr;
  1788. unsigned cbActualOrderSize;
  1789. unsigned waitingListCacheEntry;
  1790. BYTE *pRev2BitmapSizeField;
  1791. void *UserDefined, *UserDefined2;
  1792. CHDataKeyContext CHContext;
  1793. UINT32 ExtraKeyInfo[2];
  1794. #ifdef DC_DEBUG
  1795. SBC_BITMAP_CACHE_EXTRA_INFO *pBitmapHdr;
  1796. unsigned BitmapHdrSize;
  1797. BYTE *pStoredBitmapData;
  1798. #endif
  1799. DC_BEGIN_FN("SBCCacheBits");
  1800. // Select the cache based on the data size. Note that for 4bpp bitmaps
  1801. // the size is doubled because we split the colors into individual 8bpp
  1802. // bytes indexed on a 16-color palette.
  1803. #ifdef DC_HICOLOR
  1804. // The logic regarding 4bpp holds for high color as the supplied bitmap
  1805. // size already correctly takes into account higher color depths.
  1806. *pCacheID = SBCSelectBitmapCache(
  1807. (sbcClientBitsPerPel == 4 ?
  1808. (2 * cbBitmapSize) : cbBitmapSize),
  1809. TileID);
  1810. #else
  1811. *pCacheID = SBCSelectBitmapCache((sbcClientBitsPerPel == 8 ? cbBitmapSize :
  1812. (2 * cbBitmapSize)), TileID);
  1813. #endif
  1814. TRC_NRM((TB, "Selected cache %u", *pCacheID));
  1815. pCacheInfo = &(pddShm->sbc.bitmapCacheInfo[*pCacheID]);
  1816. // Generate a key for the bitmap data. Add in the width and height of the
  1817. // blt as extra keyed data, since we don't want to collide when
  1818. // displaying blts of different dimensions but the same number of bytes
  1819. // and same contents. Also add in the checksum gathered from the bitmap
  1820. // bits to decrease the fail rate.
  1821. CH_CreateKeyFromFirstData(&CHContext, pBitmapData, cbBitmapSize);
  1822. ExtraKeyInfo[0] = (paddedBitmapWidth << 16) | bitmapHeight;
  1823. ExtraKeyInfo[1] = CHContext.Checksum;
  1824. CH_CreateKeyFromNextData(&CHContext, ExtraKeyInfo, sizeof(ExtraKeyInfo));
  1825. // If the key is already present, and its extra checksum matches,
  1826. // no need to cache.
  1827. if (CH_SearchCache(pCacheInfo->cacheHandle, CHContext.Key1,
  1828. CHContext.Key2, &UserDefined, pCacheIndex)) {
  1829. TRC_NRM((TB, "Bitmap already cached %u:%u cx(%u) cy(%u)",
  1830. *pCacheID, *pCacheIndex, bitmapWidth, bitmapHeight));
  1831. pddCacheStats[BITMAP].CacheHits++;
  1832. #ifdef DC_DEBUG
  1833. SBC_VerifyBitmapBits(pBitmapData, cbBitmapSize, *pCacheID, *pCacheIndex);
  1834. #endif
  1835. DC_QUIT;
  1836. }
  1837. // The bitmap is not in the cache list, check if it's in the waiting list
  1838. // First check if the client supports waiting list cache
  1839. if (pddShm->sbc.fAllowCacheWaitingList) {
  1840. // The bitmap is in the waiting list, so cache it now, first remove
  1841. // it from the waiting list
  1842. if (CH_SearchCache(pCacheInfo->waitingListHandle, CHContext.Key1,
  1843. CHContext.Key2, &UserDefined2, &waitingListCacheEntry)) {
  1844. CH_RemoveCacheEntry(pCacheInfo->waitingListHandle, waitingListCacheEntry);
  1845. goto CacheBitmap;
  1846. }
  1847. else {
  1848. // The bitmap is not in the waiting list, put it in the waiting list
  1849. // don't cache for this round, if we see it again, then we'll cache it
  1850. waitingListCacheEntry = CH_CacheKey(pCacheInfo->waitingListHandle,
  1851. CHContext.Key1, CHContext.Key2, NULL);
  1852. *pCacheIndex = BITMAPCACHE_WAITING_LIST_INDEX;
  1853. #ifdef PERF_SPOILING
  1854. // We waitlisted this tile. We don't need to send it as
  1855. // cache order. We will try to send it as screen data.
  1856. if (bIsPrimarySurface) {
  1857. rc = FALSE;
  1858. DC_QUIT;
  1859. }
  1860. #endif
  1861. bOnWaitingList = TRUE;
  1862. }
  1863. }
  1864. else {
  1865. goto CacheBitmap;
  1866. }
  1867. CacheBitmap:
  1868. // Allocate an order in the order heap big enough to hold the entire
  1869. // tile. We will relinquish any extra space we don't use because of
  1870. // compression. Size is also dependent on the color depth of the client
  1871. // since for 4bpp we unpack the colors into 8 bits for the protocol.
  1872. #ifdef DC_HICOLOR
  1873. // Again, the logic holds for high color as the supplied bitmap size
  1874. // already correctly takes into account higher color depths.
  1875. BitmapSpace = cbBitmapSize * (sbcClientBitsPerPel == 4 ? 2 : 1);
  1876. TRC_DBG((TB, "Bitmap is %ux%u, size %u bytes",
  1877. paddedBitmapWidth, bitmapHeight, BitmapSpace));
  1878. #else
  1879. BitmapSpace = cbBitmapSize * (sbcClientBitsPerPel == 8 ? 1 : 2);
  1880. #endif
  1881. OrderSize = max(TS_CACHE_BITMAP_ORDER_REV2_MAX_SIZE,
  1882. (sizeof(TS_CACHE_BITMAP_ORDER) -
  1883. FIELDSIZE(TS_CACHE_BITMAP_ORDER, bitmapData))) +
  1884. BitmapSpace;
  1885. pOrder = OA_AllocOrderMem(ppdev, OrderSize);
  1886. if (pOrder != NULL) {
  1887. // We have to add the key to the cache. Note we use NULL for the
  1888. // UserDefined until we know the cache index to get the
  1889. // BITMAP_DATA_HEADER.
  1890. if (!bOnWaitingList) {
  1891. *pCacheIndex = CH_CacheKey(pCacheInfo->cacheHandle,
  1892. CHContext.Key1, CHContext.Key2, NULL);
  1893. #ifdef DC_DEBUG
  1894. // We need to store the bitmap data after the BITMAP_DATA_HEADER.
  1895. BitmapHdrSize = sizeof(SBC_BITMAP_CACHE_EXTRA_INFO) +
  1896. SBC_CellSizeFromCacheID(*pCacheID);
  1897. if (pddShm->sbc.bitmapCacheInfo[*pCacheID].pExtraEntryInfo != NULL) {
  1898. pBitmapHdr = (SBC_BITMAP_CACHE_EXTRA_INFO *)(pddShm->sbc.
  1899. bitmapCacheInfo[*pCacheID].pExtraEntryInfo +
  1900. BitmapHdrSize * *pCacheIndex);
  1901. pStoredBitmapData = (BYTE *)pBitmapHdr +
  1902. sizeof(SBC_BITMAP_CACHE_EXTRA_INFO);
  1903. pBitmapHdr->DataSize = cbBitmapSize;
  1904. memcpy(pStoredBitmapData, pBitmapData, cbBitmapSize);
  1905. }
  1906. #endif //DC_DEBUG
  1907. }
  1908. TRC_NRM((TB,"Creating new cache entry, cache=%d, index=%d\n",
  1909. *pCacheID, *pCacheIndex));
  1910. // Fill in cache bitmap order. Differentiate based on the
  1911. // order revision.
  1912. pHdr = (TS_SECONDARY_ORDER_HEADER *)pOrder->OrderData;
  1913. pHdr->orderHdr.controlFlags = TS_STANDARD | TS_SECONDARY;
  1914. // Fill in pHdr->orderType when we know it below.
  1915. if (pddShm->sbc.bUseRev2CacheBitmapOrder) {
  1916. TS_CACHE_BITMAP_ORDER_REV2_HEADER *pCacheOrderHdr;
  1917. // Revision 2 order.
  1918. pCacheOrderHdr = (TS_CACHE_BITMAP_ORDER_REV2_HEADER *)
  1919. pOrder->OrderData;
  1920. // Set up the CacheID and BitsPerPelID in header.extraFlags.
  1921. // If the client supports noBitmapCompression Header, we have to
  1922. // turn on the no-compression-header flag to indicate that
  1923. // this order doesn't contain the header. This is necessary in
  1924. // addition to capability negotiation because shadow can turn
  1925. // this cap off.
  1926. #ifdef DC_HICOLOR
  1927. if (!bOnWaitingList) {
  1928. pCacheOrderHdr->header.extraFlags = *pCacheID | sbcCacheFlags |
  1929. pddShm->bc.noBitmapCompressionHdr;
  1930. }
  1931. else {
  1932. pCacheOrderHdr->header.extraFlags = *pCacheID | sbcCacheFlags |
  1933. pddShm->bc.noBitmapCompressionHdr |
  1934. TS_CacheBitmapRev2_bNotCacheFlag;
  1935. }
  1936. #else
  1937. pCacheOrderHdr->header.extraFlags = *pCacheID |
  1938. TS_CacheBitmapRev2_8BitsPerPel |
  1939. pddShm->bc.noBitmapCompressionHdr;
  1940. #endif
  1941. // We'll write over the key values if the cache is tagged
  1942. // as non-persistent.
  1943. pCacheOrderHdr->Key1 = CHContext.Key1;
  1944. pCacheOrderHdr->Key2 = CHContext.Key2;
  1945. // Now add the variable-sized fields.
  1946. // Bitmap key.
  1947. if (pCacheInfo->Info.bSendBitmapKeys) {
  1948. cbActualOrderSize =
  1949. sizeof(TS_CACHE_BITMAP_ORDER_REV2_HEADER);
  1950. pCacheOrderHdr->header.extraFlags |=
  1951. TS_CacheBitmapRev2_bKeyPresent_Mask;
  1952. }
  1953. else {
  1954. cbActualOrderSize =
  1955. sizeof(TS_CACHE_BITMAP_ORDER_REV2_HEADER) -
  1956. 2 * sizeof(UINT32);
  1957. }
  1958. // Real width of the bits in this tile.
  1959. Encode2ByteField((BYTE *)pCacheOrderHdr + cbActualOrderSize,
  1960. paddedBitmapWidth, &cbActualOrderSize);
  1961. // Height, if not same as width.
  1962. if (paddedBitmapWidth == bitmapHeight) {
  1963. pCacheOrderHdr->header.extraFlags |=
  1964. TS_CacheBitmapRev2_bHeightSameAsWidth_Mask;
  1965. }
  1966. else {
  1967. Encode2ByteField((BYTE *)pCacheOrderHdr + cbActualOrderSize,
  1968. bitmapHeight, &cbActualOrderSize);
  1969. }
  1970. // Bitmap size: Here we have to lose a bit of performance.
  1971. // We have not yet compressed the bitmap and so cannot determine
  1972. // size of this field (see Encode4ByteField() above). Since we
  1973. // know that the size is never bigger than 4K (64x64 tile), we
  1974. // can just set up to always encode a 2-byte size even if the
  1975. // compressed size is less than 128 (this can cause a bit of a
  1976. // wire performance hit).
  1977. //TODO: If we add tile sizes above 64x64 we will need to modify this logic to
  1978. // handle the potential 3-byte sizes.
  1979. pRev2BitmapSizeField = (BYTE *)pCacheOrderHdr + cbActualOrderSize;
  1980. cbActualOrderSize += 2;
  1981. //TODO: Not encoding the streaming bitmap size field here, needs to be added if
  1982. // bitmap streaming is enabled.
  1983. Encode2ByteField((BYTE *)pCacheOrderHdr + cbActualOrderSize,
  1984. *pCacheIndex, &cbActualOrderSize);
  1985. }
  1986. else {
  1987. PTS_CACHE_BITMAP_ORDER pCacheOrder;
  1988. // Revision 1 order.
  1989. pCacheOrder = (PTS_CACHE_BITMAP_ORDER)pOrder->OrderData;
  1990. // If the client supports noBitmapCompression Header, we have to
  1991. // turn on the no-compression-header flag to indicate that
  1992. // this order doesn't contain the header. This is necessary in
  1993. // addition to capability negotiation because shadow can turn
  1994. // this cap off
  1995. pCacheOrder->header.extraFlags = pddShm->bc.noBitmapCompressionHdr;
  1996. pCacheOrder->cacheId = (BYTE)*pCacheID;
  1997. pCacheOrder->pad1octet = 0;
  1998. pCacheOrder->bitmapWidth = (BYTE)paddedBitmapWidth;
  1999. pCacheOrder->bitmapHeight = (BYTE)bitmapHeight;
  2000. #ifdef DC_HICOLOR
  2001. pCacheOrder->bitmapBitsPerPel = (BYTE)sbcClientBitsPerPel;
  2002. #else
  2003. pCacheOrder->bitmapBitsPerPel = (BYTE)SBC_PROTOCOL_BPP;
  2004. #endif
  2005. // We fill in pCacheOrder->bitmapLength when we have it below.
  2006. pCacheOrder->cacheIndex = (UINT16)*pCacheIndex;
  2007. cbActualOrderSize = sizeof(TS_CACHE_BITMAP_ORDER) -
  2008. FIELDSIZE(TS_CACHE_BITMAP_ORDER, bitmapData);
  2009. }
  2010. #ifdef DC_HICOLOR
  2011. if (sbcClientBitsPerPel != 4)
  2012. #else
  2013. if (sbcClientBitsPerPel == 8)
  2014. #endif
  2015. {
  2016. compressedSize = cbBitmapSize;
  2017. }
  2018. else {
  2019. BYTE *pEnd, *pSrc, *pDst;
  2020. compressedSize = cbBitmapSize * 2;
  2021. // Expand the 4bpp packing into full bytes -- protocol is 8bpp
  2022. // and we need to have these bits before compressing.
  2023. pEnd = pBitmapData + cbBitmapSize;
  2024. pSrc = pBitmapData;
  2025. pDst = sbcXlateBuf;
  2026. while (pSrc < pEnd) {
  2027. *pDst = (*pSrc >> 4) & 0xF;
  2028. pDst++;
  2029. *pDst = *pSrc & 0xF;
  2030. pDst++;
  2031. pSrc++;
  2032. }
  2033. pBitmapData = sbcXlateBuf;
  2034. }
  2035. // Try to compress the bitmap data, or copy it if the
  2036. // compression will do no good.
  2037. #ifdef DC_HICOLOR
  2038. if (BC_CompressBitmap(pBitmapData,
  2039. pOrder->OrderData + cbActualOrderSize,
  2040. NULL,
  2041. compressedSize,
  2042. &compressedSize,
  2043. paddedBitmapWidth,
  2044. bitmapHeight,
  2045. sbcClientBitsPerPel))
  2046. #else
  2047. if (BC_CompressBitmap(pBitmapData, pOrder->OrderData +
  2048. cbActualOrderSize, compressedSize,
  2049. &compressedSize, paddedBitmapWidth, bitmapHeight))
  2050. #endif
  2051. {
  2052. TRC_NRM((TB, "Compressed to %u bytes", compressedSize));
  2053. if (pddShm->sbc.bUseRev2CacheBitmapOrder) {
  2054. pHdr->orderType = TS_CACHE_BITMAP_COMPRESSED_REV2;
  2055. // Encode 2 bytes for size within 4-byte encoding.
  2056. TRC_ASSERT((compressedSize <= 0x3FFF),
  2057. (TB,"compressedSize too large for 2 bytes!"));
  2058. *pRev2BitmapSizeField = (BYTE)(compressedSize >> 8) | 0x40;
  2059. *(pRev2BitmapSizeField + 1) = (BYTE)(compressedSize &
  2060. 0x00FF);
  2061. }
  2062. else {
  2063. pHdr->orderType = TS_CACHE_BITMAP_COMPRESSED;
  2064. ((PTS_CACHE_BITMAP_ORDER)pOrder->OrderData)->
  2065. bitmapLength = (UINT16)compressedSize;
  2066. }
  2067. }
  2068. else {
  2069. // Failed to compress bitmap data, so just copy it
  2070. // uncompressed.
  2071. TRC_NRM((TB, "Failed to compress %u bytes, copying",
  2072. compressedSize));
  2073. memcpy(pOrder->OrderData + cbActualOrderSize,
  2074. pBitmapData, compressedSize);
  2075. if (pddShm->sbc.bUseRev2CacheBitmapOrder) {
  2076. pHdr->orderType = TS_CACHE_BITMAP_UNCOMPRESSED_REV2;
  2077. // Encode 2 bytes for size within 4-byte encoding.
  2078. TRC_ASSERT((compressedSize <= 0x3FFF),
  2079. (TB,"compressedSize too large for 2 bytes!"));
  2080. *pRev2BitmapSizeField = (BYTE)(compressedSize >> 8) | 0x40;
  2081. *(pRev2BitmapSizeField + 1) = (BYTE)(compressedSize &
  2082. 0x00FF);
  2083. }
  2084. else {
  2085. pHdr->orderType = TS_CACHE_BITMAP_UNCOMPRESSED;
  2086. ((PTS_CACHE_BITMAP_ORDER)pOrder->OrderData)->
  2087. bitmapLength = (UINT16)compressedSize;
  2088. }
  2089. }
  2090. pHdr->orderLength = (UINT16)
  2091. TS_CALCULATE_SECONDARY_ORDER_ORDERLENGTH(
  2092. cbActualOrderSize + compressedSize);
  2093. // Return any extra space to the order heap.
  2094. OA_TruncateAllocatedOrder(pOrder, cbActualOrderSize +
  2095. compressedSize);
  2096. // Add the order.
  2097. OA_AppendToOrderList(pOrder);
  2098. INC_OUTCOUNTER(OUT_CACHEBITMAP);
  2099. ADD_OUTCOUNTER(OUT_CACHEBITMAP_BYTES, cbActualOrderSize +
  2100. compressedSize);
  2101. }
  2102. else {
  2103. TRC_ALT((TB, "Failed to alloc cache bitmap order size %d", OrderSize));
  2104. INC_OUTCOUNTER(OUT_CACHEBITMAP_FAILALLOC);
  2105. rc = FALSE;
  2106. }
  2107. DC_EXIT_POINT:
  2108. DC_END_FN();
  2109. return rc;
  2110. }
  2111. /****************************************************************************/
  2112. // SBC_SendCacheColorTableOrder
  2113. //
  2114. // Queues a color table order if the palette has
  2115. // changed since the last call to this function.
  2116. //
  2117. // Returns: TRUE if no action required, or color table successfully
  2118. // queued. FALSE otherwise.
  2119. //
  2120. // Params: pPDev - pointer to PDev
  2121. // pCacheIndex - pointer to variable that receives cache index
  2122. /****************************************************************************/
  2123. BOOLEAN RDPCALL SBC_SendCacheColorTableOrder(
  2124. PDD_PDEV pPDev,
  2125. unsigned *pCacheIndex)
  2126. {
  2127. int orderSize;
  2128. void *UserDefined;
  2129. CHDataKeyContext CHContext;
  2130. BOOLEAN rc = TRUE;
  2131. unsigned numColors;
  2132. unsigned i;
  2133. PINT_ORDER pOrder;
  2134. PTS_CACHE_COLOR_TABLE_ORDER pColorTableOrder;
  2135. DC_BEGIN_FN("SBC_SendCacheColorTableOrder");
  2136. // Currently only support 8bpp protocol.
  2137. TRC_ASSERT((pPDev->cProtocolBitsPerPel == SBC_PROTOCOL_BPP),
  2138. (TB, "Unexpected bpp: %u", pPDev->cProtocolBitsPerPel));
  2139. numColors = SBC_NUM_8BPP_COLORS;
  2140. // Check the boolean in our PDEV to see if the palette has changed
  2141. // since the last time we sent a color table order.
  2142. // In high color case, no color table is needed
  2143. if (!sbcPaletteChanged || (sbcClientBitsPerPel > 8)) {
  2144. *pCacheIndex = sbcCurrentColorTableCacheIndex;
  2145. DC_QUIT;
  2146. }
  2147. // If the key is already present (very often the case), no need to cache.
  2148. CH_CreateKeyFromFirstData(&CHContext, (BYTE *)(pPDev->Palette),
  2149. numColors * sizeof(PALETTEENTRY));
  2150. if (CH_SearchCache(sbcColorTableCacheHandle, CHContext.Key1,
  2151. CHContext.Key2, &UserDefined, pCacheIndex)) {
  2152. TRC_NRM((TB, "Color table matched cache entry %u", *pCacheIndex));
  2153. DC_QUIT;
  2154. }
  2155. // We have to add the key to the cache.
  2156. *pCacheIndex = CH_CacheKey(sbcColorTableCacheHandle, CHContext.Key1,
  2157. CHContext.Key2, NULL);
  2158. // The palette has changed and is not currently in the color table
  2159. // cache. Allocate order memory to queue a color table order. The
  2160. // order size depends on the bpp of our device. Note that the
  2161. // allocation can fail if the order buffer is full.
  2162. orderSize = sizeof(TS_CACHE_COLOR_TABLE_ORDER) -
  2163. FIELDSIZE(TS_CACHE_COLOR_TABLE_ORDER, colorTable) +
  2164. (numColors * sizeof(TS_COLOR_QUAD));
  2165. pOrder = OA_AllocOrderMem(pPDev, orderSize);
  2166. if (pOrder != NULL) {
  2167. TRC_DBG((TB, "Allocate %u bytes for color table order", orderSize));
  2168. // We've successfully allocated the order, so fill in the details.
  2169. pColorTableOrder = (PTS_CACHE_COLOR_TABLE_ORDER)pOrder->OrderData;
  2170. pColorTableOrder->header.orderHdr.controlFlags = TS_STANDARD |
  2171. TS_SECONDARY;
  2172. pColorTableOrder->header.orderLength = (USHORT)
  2173. TS_CALCULATE_SECONDARY_ORDER_ORDERLENGTH(orderSize);
  2174. pColorTableOrder->header.extraFlags = 0;
  2175. pColorTableOrder->header.orderType = TS_CACHE_COLOR_TABLE;
  2176. pColorTableOrder->cacheIndex = (BYTE)*pCacheIndex;
  2177. pColorTableOrder->numberColors = (UINT16)numColors;
  2178. // Unfortunately we can't just copy the palette from the PDEV into the
  2179. // color table order because the PDEV has an array of PALETTEENTRY
  2180. // structures which are RGBs whereas the order has an array of
  2181. // RGBQUADs which are BGRs...
  2182. for (i = 0; i < numColors; i++) {
  2183. pColorTableOrder->colorTable[i].blue = pPDev->Palette[i].peRed;
  2184. pColorTableOrder->colorTable[i].green = pPDev->Palette[i].peGreen;
  2185. pColorTableOrder->colorTable[i].red = pPDev->Palette[i].peBlue;
  2186. pColorTableOrder->colorTable[i].pad1octet = 0;
  2187. }
  2188. // Add the order.
  2189. OA_AppendToOrderList(pOrder);
  2190. INC_OUTCOUNTER(OUT_CACHECOLORTABLE);
  2191. ADD_OUTCOUNTER(OUT_CACHECOLORTABLE_BYTES, orderSize);
  2192. TRC_NRM((TB, "Added internal color table order, size %u", orderSize));
  2193. // Reset the flag which indicates that the palette needs to be sent.
  2194. sbcPaletteChanged = FALSE;
  2195. sbcCurrentColorTableCacheIndex = *pCacheIndex;
  2196. TRC_NRM((TB, "Added new color table at index(%u)", *pCacheIndex));
  2197. #ifdef DC_HICOLOR
  2198. TRC_ASSERT((sbcCurrentColorTableCacheIndex <
  2199. SBC_NUM_COLOR_TABLE_CACHE_ENTRIES),
  2200. (TB, "Invalid ColorTableIndex(%u)",
  2201. sbcCurrentColorTableCacheIndex));
  2202. #endif
  2203. }
  2204. else {
  2205. rc = FALSE;
  2206. TRC_ERR((TB, "Failed to allocate %d bytes for color table order",
  2207. orderSize));
  2208. }
  2209. DC_EXIT_POINT:
  2210. DC_END_FN();
  2211. return rc;
  2212. }