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.

629 lines
25 KiB

  1. /****************************************************************************/
  2. // nsdgint.cpp
  3. //
  4. // RDP Screen Data Grabber internal functions
  5. //
  6. // Copyright (C) 1996-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <precomp.h>
  9. #pragma hdrstop
  10. #define TRC_FILE "nsdgint"
  11. #include <as_conf.hpp>
  12. #include <nprcount.h>
  13. /****************************************************************************/
  14. /* Name: SDGSendSDARect */
  15. /* */
  16. /* Purpose: Attempts to send the given rectangle of Screen Data */
  17. /* in one or more BitmapPDUs */
  18. /* */
  19. /* Returns: TRUE if whole rectangle sucessfully sent, FALSE otherwise. */
  20. /* The supplied rectangle is always updated to remove the area */
  21. /* that was successfully sent i.e. upon return the rectangle */
  22. /* contains the area that was NOT sent. */
  23. /* */
  24. /* Params: IN: pFrameBuf - pointer to the Frame Buffer */
  25. /* IN/OUT: pRect - pointer to rectangle to send. Updated to */
  26. /* contain the rectangle that was not sent. */
  27. /* IN: mustSend - set if the PDU must be sent (last rectangle) */
  28. /* IN: pPkgInfo - PDU package to use */
  29. /****************************************************************************/
  30. BOOL RDPCALL SHCLASS SDGSendSDARect(
  31. BYTE *pFrameBuf,
  32. unsigned frameBufferWidth,
  33. PRECTL pRect,
  34. BOOL mustSend,
  35. PPDU_PACKAGE_INFO pPkgInfo,
  36. SDG_ENCODE_CONTEXT *pContext)
  37. {
  38. BOOL rc = FALSE;
  39. int rectWidth;
  40. int rectHeight;
  41. int paddedWidthInPels;
  42. // DC_HICOLOR
  43. int paddedWidthInBytes;
  44. unsigned padByte;
  45. unsigned maxRowsLeft;
  46. BYTE *pSrc;
  47. BYTE *pPrevSrc;
  48. unsigned uncompressedBitmapSize;
  49. unsigned compressedBitmapSize = 0;
  50. unsigned transferHeight;
  51. unsigned pduSize;
  52. unsigned compEst;
  53. unsigned cbAdded;
  54. unsigned compRowsLeft;
  55. unsigned dataLeft;
  56. unsigned buffSpaceLeft;
  57. BOOL compRc;
  58. // Macro to calculate remaining space in the BitmapPDU, allowing for
  59. // any current rectangles.
  60. #define SDG_SPACE_LEFT \
  61. ((pContext->pPackageSpace + pContext->BitmapPDUSize) - \
  62. ((BYTE *)pContext->pSDARect + \
  63. FIELDOFFSET(TS_BITMAP_DATA, bitmapData[0])))
  64. DC_BEGIN_FN("SDGSendSDARect");
  65. TRC_NRM((TB, "SDA rect: (%d,%d)(%d,%d)", pRect->left, pRect->top,
  66. pRect->right, pRect->bottom));
  67. #ifdef DC_HICOLOR
  68. // For simplicity on 4bpp, round left down to an even number.
  69. if (m_pTSWd->desktopBpp == 4)
  70. pRect->left &= (~0x1);
  71. // Get the rectangle width and height, remembering that the supplied
  72. // coords are inclusive.
  73. rectWidth = pRect->right - pRect->left;
  74. rectHeight = pRect->bottom - pRect->top;
  75. // Pad rect width so that each row is dword aligned.
  76. paddedWidthInPels = (rectWidth + 3) & (~0x03);
  77. // Set up a pointer to the first byte to fetch from the Frame Buffer,
  78. // alowing for the color depth.
  79. if (m_pTSWd->desktopBpp == 24) {
  80. pSrc = pFrameBuf + 3 * (pRect->top * frameBufferWidth + pRect->left);
  81. paddedWidthInBytes = paddedWidthInPels * 3;
  82. }
  83. else if ((m_pTSWd->desktopBpp == 16) || (m_pTSWd->desktopBpp == 15)) {
  84. pSrc = pFrameBuf + 2 * (pRect->top * frameBufferWidth + pRect->left);
  85. paddedWidthInBytes = paddedWidthInPels * 2;
  86. }
  87. else if (m_pTSWd->desktopBpp == 8) {
  88. pSrc = pFrameBuf + (pRect->top * frameBufferWidth) + pRect->left;
  89. paddedWidthInBytes = paddedWidthInPels;
  90. }
  91. else {
  92. pSrc = pFrameBuf +
  93. (((pRect->top * frameBufferWidth) + pRect->left) >> 1);
  94. paddedWidthInBytes = paddedWidthInPels;
  95. }
  96. #else
  97. // Set up a pointer to the first byte to fetch from the Frame Buffer.
  98. if (m_pTSWd->desktopBpp == 8) {
  99. // Get the rectangle width and height, remembering that the
  100. // supplied coords are exclusive.
  101. rectWidth = pRect->right - pRect->left;
  102. rectHeight = pRect->bottom - pRect->top;
  103. pSrc = pFrameBuf + (pRect->top * frameBufferWidth) + pRect->left;
  104. // DC_HICOLOR
  105. paddedWidthInBytes = (rectWidth + 3) & (~0x03);
  106. }
  107. else {
  108. // Get the rectangle width and height, remembering that the
  109. // supplied coords are exclusive.
  110. // For simplicity on 4bpp, round left down to an even number.
  111. pRect->left &= (~0x1);
  112. rectWidth = pRect->right - pRect->left;
  113. rectHeight = pRect->bottom - pRect->top;
  114. pSrc = pFrameBuf + (((pRect->top * frameBufferWidth) +
  115. pRect->left) >> 1);
  116. // DC_HICOLOR
  117. paddedWidthInBytes = (rectWidth + 3) & (~0x03);
  118. }
  119. #endif
  120. TRC_NRM((TB, "%dbpp: pSrc %p, bytes/row %d",
  121. m_pTSWd->desktopBpp, pSrc, paddedWidthInBytes));
  122. #ifndef DC_HICOLOR
  123. // Pad rect width so that each row is dword aligned.
  124. paddedWidthInPels = (rectWidth + 3) & (~0x03);
  125. #endif
  126. while ((rectHeight > 0) || mustSend) {
  127. // Have we filled the current PDU? Yes, if:
  128. // - there is no room for more data; or
  129. // - the last rectangle has been completely added; or
  130. // - multiple rects per PDU are not supported.
  131. if ((pContext->pBitmapPDU != NULL) &&
  132. ((SDG_SPACE_LEFT < paddedWidthInBytes) ||
  133. (rectHeight == 0)))
  134. {
  135. pduSize = (unsigned)((BYTE *)pContext->pSDARect -
  136. pContext->pPackageSpace);
  137. TRC_NRM((TB, "Send PDU size %u, numrects=%u", pduSize,
  138. pContext->pBitmapPDU->numberRectangles));
  139. // Add the PDU to the package.
  140. SC_AddToPackage(pPkgInfo, pduSize, TRUE);
  141. INC_INCOUNTER(IN_SND_SDA_PDUS);
  142. // Just used up an entire PDU. Quit if the entire rectangle
  143. // was consumed OR we are in the middle of accumulating a
  144. // shadow buffer.
  145. pContext->pPackageSpace = NULL;
  146. pContext->pBitmapPDU = NULL;
  147. pContext->pSDARect = NULL;
  148. TRC_DBG((TB, "Reset pSDARect and pBitmapPDU"));
  149. if ((rectHeight == 0) || m_pTSWd->shadowState) {
  150. // There is no new data. Break out of while loop.
  151. // mustSend must be set.
  152. TRC_NRM((TB, "Finished processing rectangle"));
  153. break;
  154. }
  155. }
  156. // Set up a new PDU if required.
  157. if (pContext->pBitmapPDU == NULL) {
  158. // Find space needed for headers plus one TS_BITMAP_DATA hdr plus
  159. // the size of the header, throttled by the large packing size.
  160. dataLeft = rectHeight * paddedWidthInBytes + scUpdatePDUHeaderSpace +
  161. (unsigned)FIELDOFFSET(TS_UPDATE_BITMAP_PDU_DATA,
  162. rectangle[0]) +
  163. (unsigned)FIELDOFFSET(TS_BITMAP_DATA, bitmapData[0]);
  164. dataLeft = min(dataLeft, m_pShm->sch.LargePackingSize);
  165. TRC_NRM((TB, "Getting PDU, min size %d", dataLeft));
  166. pContext->pPackageSpace = SC_GetSpaceInPackage(pPkgInfo,
  167. dataLeft);
  168. if (pContext->pPackageSpace != NULL) {
  169. // Set up the current PDU size. Throttle to the large
  170. // packing size.
  171. pContext->BitmapPDUSize = min(
  172. (pPkgInfo->cbLen - pPkgInfo->cbInUse),
  173. m_pShm->sch.LargePackingSize);
  174. TRC_NRM((TB, "Got PDU size %d", pContext->BitmapPDUSize));
  175. // Fill in PDU header.
  176. if (scUseFastPathOutput) {
  177. pContext->pPackageSpace[0] = TS_UPDATETYPE_BITMAP |
  178. scCompressionUsedValue;
  179. }
  180. else {
  181. ((TS_UPDATE_BITMAP_PDU UNALIGNED *)
  182. pContext->pPackageSpace)->shareDataHeader.pduType2 =
  183. TS_PDUTYPE2_UPDATE;
  184. }
  185. pContext->pBitmapPDU = (TS_UPDATE_BITMAP_PDU_DATA UNALIGNED *)
  186. (pContext->pPackageSpace + scUpdatePDUHeaderSpace);
  187. pContext->pBitmapPDU->updateType = TS_UPDATETYPE_BITMAP;
  188. pContext->pBitmapPDU->numberRectangles = 0;
  189. // Set up a pointer to the rectangles.
  190. pContext->pSDARect = &(pContext->pBitmapPDU->rectangle[0]);
  191. }
  192. else {
  193. TRC_ALT((TB, "Failed to allocate buffer"));
  194. DC_QUIT;
  195. }
  196. }
  197. // Now copy as many lines as possible into the PDU. Code above
  198. // means there must be room for a line.
  199. TRC_ASSERT((paddedWidthInBytes > 0), (TB, "zero paddedRectWidth"));
  200. maxRowsLeft = (unsigned)SDG_SPACE_LEFT / paddedWidthInBytes;
  201. TRC_ASSERT((maxRowsLeft > 0),
  202. (TB, "Internal error: no room for a row, space %u, width %u",
  203. SDG_SPACE_LEFT, paddedWidthInBytes));
  204. // This figure does not allow for the compression we are about to
  205. // apply - lets revise it accordingly.
  206. compRowsLeft = maxRowsLeft * SCH_UNCOMP_BYTES /
  207. SCH_GetBACompressionEst();
  208. transferHeight = min((unsigned)rectHeight, compRowsLeft);
  209. uncompressedBitmapSize = transferHeight * paddedWidthInBytes;
  210. // Check that this won't blow the compression algorithm.
  211. if (uncompressedBitmapSize > MAX_UNCOMPRESSED_DATA_SIZE) {
  212. TRC_NRM((TB, "Rect size %u too big to compress in one go",
  213. uncompressedBitmapSize));
  214. transferHeight = MAX_UNCOMPRESSED_DATA_SIZE / paddedWidthInBytes;
  215. uncompressedBitmapSize = transferHeight * paddedWidthInBytes;
  216. TRC_NRM((TB, "Reduced size to %u (%u rows)",
  217. uncompressedBitmapSize, transferHeight));
  218. }
  219. // Fill in the common header fields for this rectangle.
  220. // Convert the rect to inclusive for the wire protocol.
  221. pContext->pBitmapPDU->numberRectangles++;
  222. pContext->pSDARect->destLeft = (INT16)(pRect->left);
  223. pContext->pSDARect->destRight = (INT16)(pRect->right - 1);
  224. pContext->pSDARect->destTop = (INT16)(pRect->top);
  225. pContext->pSDARect->width = (UINT16)paddedWidthInPels;
  226. #ifdef DC_HICOLOR
  227. pContext->pSDARect->bitsPerPixel = (UINT16)m_pTSWd->desktopBpp;
  228. if (pContext->pSDARect->bitsPerPixel < 8) {
  229. pContext->pSDARect->bitsPerPixel = 8;
  230. }
  231. #else
  232. pContext->pSDARect->bitsPerPixel = 8;
  233. #endif
  234. // Set up the data in the transfer buffer.
  235. pPrevSrc = pSrc;
  236. SDGPrepareData(&pSrc, rectWidth, paddedWidthInBytes,
  237. transferHeight, frameBufferWidth);
  238. // The compression algorithm does not deal well with very small
  239. // buffers.
  240. if (transferHeight > 1 || paddedWidthInPels > 12) {
  241. // Try to compress the bitmap directly into the network packet.
  242. // First we try to compress with the data size based on how well
  243. // we expect it to compress.
  244. buffSpaceLeft = min((unsigned)SDG_SPACE_LEFT,
  245. uncompressedBitmapSize);
  246. #ifdef DC_HICOLOR
  247. compRc = BC_CompressBitmap(
  248. m_pShm->sdgTransferBuffer,
  249. pContext->pSDARect->bitmapData,
  250. NULL,
  251. buffSpaceLeft,
  252. &compressedBitmapSize,
  253. paddedWidthInPels,
  254. transferHeight,
  255. m_pTSWd->desktopBpp);
  256. #else
  257. compRc = BC_CompressBitmap(m_pShm->sdgTransferBuffer,
  258. pContext->pSDARect->bitmapData, buffSpaceLeft,
  259. &compressedBitmapSize, paddedWidthInPels,
  260. transferHeight);
  261. #endif
  262. if (compRc) {
  263. // We have successfully compressed the bitmap data.
  264. pContext->pSDARect->compressedFlag = TRUE;
  265. // Indicates if this SDA data includes BC header or not.
  266. pContext->pSDARect->compressedFlag |=
  267. m_pShm->bc.noBitmapCompressionHdr;
  268. TRC_NRM((TB, "1st pass compr of %u x %u, size %u -> %u",
  269. transferHeight, paddedWidthInPels,
  270. uncompressedBitmapSize, compressedBitmapSize));
  271. goto COMPRESSION_DONE;
  272. }
  273. // Compression failed - may be because the data didn't compress
  274. // quite as well as we thought it would and hence didn't fit into
  275. // the buffer, so we'll try again.
  276. // Copy as many lines as possible into the PDU. Code above means
  277. // there must be room for a line.
  278. TRC_NRM((TB, "Failed compress bitmap size %u (%u rows) - " \
  279. "try smaller chunk", uncompressedBitmapSize,
  280. transferHeight));
  281. maxRowsLeft = (unsigned)SDG_SPACE_LEFT / paddedWidthInBytes;
  282. TRC_ASSERT((maxRowsLeft > 0),
  283. (TB, "No room for a row, space %u, width %u",
  284. SDG_SPACE_LEFT, paddedWidthInBytes));
  285. transferHeight = min((unsigned)rectHeight, maxRowsLeft);
  286. uncompressedBitmapSize = transferHeight * paddedWidthInBytes;
  287. TRC_DBG((TB, "Retry with %u rows", transferHeight));
  288. // Set up the new data in the transfer buffer.
  289. pSrc = pPrevSrc;
  290. SDGPrepareData(&pSrc, rectWidth, paddedWidthInBytes,
  291. transferHeight, frameBufferWidth);
  292. // Try to compress the bitmap directly into the network packet.
  293. buffSpaceLeft = min((unsigned)SDG_SPACE_LEFT,
  294. uncompressedBitmapSize);
  295. #ifdef DC_HICOLOR
  296. compRc = BC_CompressBitmap(m_pShm->sdgTransferBuffer,
  297. pContext->pSDARect->bitmapData, NULL, buffSpaceLeft,
  298. &compressedBitmapSize, paddedWidthInPels,
  299. transferHeight, m_pTSWd->desktopBpp);
  300. #else
  301. compRc = BC_CompressBitmap(m_pShm->sdgTransferBuffer,
  302. pContext->pSDARect->bitmapData, buffSpaceLeft,
  303. &compressedBitmapSize, paddedWidthInPels, transferHeight);
  304. #endif
  305. if (compRc) {
  306. TRC_NRM((TB,
  307. "2nd pass compr %u x %u, size %u -> %u",
  308. transferHeight, paddedWidthInPels,
  309. uncompressedBitmapSize, compressedBitmapSize));
  310. pContext->pSDARect->compressedFlag = TRUE;
  311. // Indicates if this SDA data includes BC header or not.
  312. pContext->pSDARect->compressedFlag |=
  313. m_pShm->bc.noBitmapCompressionHdr;
  314. goto COMPRESSION_DONE;
  315. }
  316. // The compression really really failed so just copy the
  317. // uncompressed data from the sdgTransferBuffer to the packet and
  318. // send it uncompressed.
  319. TRC_NRM((TB, "Really failed to compress bitmap size(%u)",
  320. uncompressedBitmapSize));
  321. TRC_NRM((TB, "Copy %u x %u, size %u",
  322. transferHeight, paddedWidthInPels, uncompressedBitmapSize));
  323. goto NoCompression;
  324. }
  325. else {
  326. // Small buffer, no compression applied.
  327. // So we just copy the uncompressed data from the sdgTransferBuffer
  328. // to the packet and send it uncompressed.
  329. TRC_NRM((TB, "first time copy of %u rows by %u columns, size %u",
  330. transferHeight, paddedWidthInPels, uncompressedBitmapSize));
  331. NoCompression:
  332. pContext->pSDARect->compressedFlag = FALSE;
  333. memcpy(pContext->pSDARect->bitmapData,
  334. m_pShm->sdgTransferBuffer,
  335. uncompressedBitmapSize);
  336. // Init the compressed data size to the uncompressed size.
  337. compressedBitmapSize = uncompressedBitmapSize;
  338. }
  339. COMPRESSION_DONE:
  340. // Write the size of the data into the header. Be sure compressedSize
  341. // has been set up, even if uncompressed.
  342. pContext->pSDARect->bitmapLength = (UINT16)compressedBitmapSize;
  343. // Now we know the height actually used, we can fill in the rest of
  344. // the SDA header.
  345. pContext->pSDARect->height = (UINT16)transferHeight;
  346. pContext->pSDARect->destBottom =
  347. (INT16)(pRect->top + (transferHeight - 1));
  348. TRC_NRM((TB, "Add rect %d: (%d,%d)(%d,%d) %u(%u->%u bytes)",
  349. pContext->pBitmapPDU->numberRectangles,
  350. pContext->pSDARect->destLeft,
  351. pContext->pSDARect->destTop,
  352. pContext->pSDARect->destRight,
  353. pContext->pSDARect->destBottom,
  354. pContext->pSDARect->compressedFlag,
  355. uncompressedBitmapSize,
  356. compressedBitmapSize));
  357. // Update the compression statistics.
  358. sdgUncompTotal += uncompressedBitmapSize;
  359. sdgCompTotal += compressedBitmapSize;
  360. if (sdgUncompTotal >= SDG_SAMPLE_SIZE) {
  361. // Compression estimate is average # of bytes that
  362. // SCH_UNCOMP_BYTES bytes of uncomp data compress to.
  363. compEst = SCH_UNCOMP_BYTES * sdgCompTotal / sdgUncompTotal;
  364. TRC_ASSERT((compEst <= 1024),(TB,"Screen data compression "
  365. "estimate out of range - %u", compEst));
  366. sdgCompTotal = 0;
  367. sdgUncompTotal = 0;
  368. if (compEst < SCH_COMP_LIMIT)
  369. compEst = SCH_COMP_LIMIT;
  370. SCH_UpdateBACompressionEst(compEst);
  371. TRC_NRM((TB, "New BA compression estimate %lu", compEst));
  372. }
  373. // Update variables to reflect the chunk of data we successfully sent.
  374. rectHeight -= transferHeight;
  375. pRect->top += transferHeight;
  376. // Update the SDA pointer. Add the TS_BITMAP_DATA header plus the
  377. // actual bitmap bits.
  378. cbAdded = (unsigned)FIELDOFFSET(TS_BITMAP_DATA, bitmapData[0]) +
  379. pContext->pSDARect->bitmapLength;
  380. pContext->pSDARect = (TS_BITMAP_DATA UNALIGNED *)
  381. ((BYTE *)pContext->pSDARect + cbAdded);
  382. TRC_DBG((TB, "pSDARect = %p", pContext->pSDARect));
  383. } /* ... while (rectHeight > 0) */
  384. // The entire rectangle was consumed if we managed to pack in all the rows.
  385. // For shadowing, we want to indicate if more work is required to finish
  386. rc = (rectHeight == 0);
  387. DC_EXIT_POINT:
  388. DC_END_FN();
  389. return rc;
  390. }
  391. /****************************************************************************/
  392. // SDGPrepareData
  393. //
  394. // Copies a bitmap rectangle from the screen buffer to sdgTransferBuffer.
  395. /****************************************************************************/
  396. void RDPCALL SHCLASS SDGPrepareData(
  397. BYTE **ppSrc,
  398. int rectWidth,
  399. int paddedRectWidth,
  400. unsigned transferHeight,
  401. unsigned frameBufferWidth)
  402. {
  403. PBYTE pDst;
  404. PBYTE pEnd4, pDst4, pSrc4;
  405. unsigned row;
  406. unsigned numPadBytes;
  407. unsigned lineWidth;
  408. PBYTE pSrc = *ppSrc;
  409. DC_BEGIN_FN("SDGPrepareData");
  410. // We need to copy the data from the Frame Buffer into the
  411. // sdgTransferBuffer so that each of the rectangle rows to be sent are
  412. // contiguous in memory.
  413. // However, we also need to flip the bitmap vertically to convert from
  414. // the top-down format of the frame buffer to the bottom-up format of
  415. // the PDU bitmap data. We therefore set pDst to point to the address
  416. // of the beginning of the last row (in memory) of the bitmap within
  417. // the Transfer Buffer and the code below moves it back through memory
  418. // as we copy each row of source data.
  419. #ifdef DC_HICOLOR
  420. pDst = m_pShm->sdgTransferBuffer + paddedRectWidth * (transferHeight - 1);
  421. if (m_pTSWd->desktopBpp == 8)
  422. lineWidth = frameBufferWidth;
  423. else if (m_pTSWd->desktopBpp == 24)
  424. lineWidth = frameBufferWidth * 3;
  425. else if ((m_pTSWd->desktopBpp == 16) || (m_pTSWd->desktopBpp == 15))
  426. lineWidth = frameBufferWidth * 2;
  427. else if (m_pTSWd->desktopBpp == 4)
  428. lineWidth = frameBufferWidth / 2;
  429. #else
  430. pDst = m_pShm->sdgTransferBuffer + (paddedRectWidth * (transferHeight-1));
  431. lineWidth = (m_pTSWd->desktopBpp == 4) ? (frameBufferWidth / 2)
  432. : frameBufferWidth;
  433. #endif
  434. TRC_NRM((TB, "FB width %d, line width %d, Bpp %d",
  435. frameBufferWidth, lineWidth, m_pTSWd->desktopBpp));
  436. // Copy the data into the Transfer Buffer, reformatting it as we go.
  437. if (m_pTSWd->desktopBpp == 8) {
  438. for (row = 0; row < transferHeight; row++) {
  439. memcpy(pDst, pSrc, rectWidth);
  440. pSrc += lineWidth;
  441. pDst -= paddedRectWidth;
  442. }
  443. }
  444. #ifdef DC_HICOLOR
  445. else if (m_pTSWd->desktopBpp == 24) {
  446. TRC_NRM((TB, "Copy %d rows of %d pels, line w %d, prw %d",
  447. transferHeight, rectWidth, lineWidth, paddedRectWidth));
  448. for (row = 0; row < transferHeight; row++)
  449. {
  450. memcpy(pDst, pSrc, 3 * rectWidth);
  451. pSrc += lineWidth;
  452. pDst -= paddedRectWidth;
  453. }
  454. }
  455. else if ((m_pTSWd->desktopBpp == 15) || (m_pTSWd->desktopBpp == 16)) {
  456. TRC_NRM((TB, "Copy %d rows of %d pels, line w %d, prw %d",
  457. transferHeight, rectWidth, lineWidth, paddedRectWidth));
  458. for (row = 0; row < transferHeight; row++)
  459. {
  460. memcpy(pDst, pSrc, 2 * rectWidth);
  461. pSrc += lineWidth;
  462. pDst -= paddedRectWidth;
  463. }
  464. }
  465. #endif
  466. else {
  467. for (row = 0; row < transferHeight; row++) {
  468. pEnd4 = pDst + rectWidth;
  469. for (pDst4 = pDst, pSrc4 = pSrc; pDst4 < pEnd4; pDst4++, pSrc4++) {
  470. *pDst4 = (*pSrc4 >> 4) & 0xf;
  471. pDst4++;
  472. *pDst4 = *pSrc4 & 0xf;
  473. }
  474. pSrc += lineWidth;
  475. pDst -= paddedRectWidth;
  476. }
  477. }
  478. // Zero the pad bytes on the end of each row (this aids compression).
  479. // Split each case out separately to aid performance (rather than the
  480. // alternative of testing numPadBytes within every iteration of a for
  481. // loop). Set pDst to the first pad byte in the first row.
  482. #ifdef DC_HICOLOR
  483. pDst = m_pShm->sdgTransferBuffer +
  484. (rectWidth * ((m_pTSWd->desktopBpp + 7) / 8));
  485. numPadBytes = (unsigned)(paddedRectWidth -
  486. (rectWidth * ((m_pTSWd->desktopBpp + 7) / 8)));
  487. #else
  488. pDst = m_pShm->sdgTransferBuffer + rectWidth;
  489. numPadBytes = (unsigned)(paddedRectWidth - rectWidth);
  490. #endif
  491. switch (numPadBytes) {
  492. case 0:
  493. // No padding required.
  494. break;
  495. case 1:
  496. // 1 byte padding per row required.
  497. for (row = 0; row < transferHeight; row++) {
  498. *pDst = 0;
  499. pDst += paddedRectWidth;
  500. }
  501. break;
  502. case 2:
  503. // 2 bytes padding per row required.
  504. for (row = 0; row < transferHeight; row++) {
  505. *((PUINT16_UA)pDst) = 0;
  506. pDst += paddedRectWidth;
  507. }
  508. break;
  509. case 3:
  510. // 3 bytes padding per row required.
  511. for (row = 0; row < transferHeight; row++) {
  512. *((PUINT16_UA)pDst) = 0;
  513. *(pDst + 2) = 0;
  514. pDst += paddedRectWidth;
  515. }
  516. break;
  517. #ifdef DC_HICOLOR
  518. case 4:
  519. // 4 bytes padding per row required.
  520. for (row = 0; row < transferHeight; row++) {
  521. *((PUINT32_UA)pDst) = 0;
  522. pDst += paddedRectWidth;
  523. }
  524. break;
  525. case 6:
  526. // 6 bytes padding per row required.
  527. for (row = 0; row < transferHeight; row++) {
  528. *((PUINT32_UA)pDst) = 0;
  529. *((PUINT16_UA)(pDst + 4)) = 0;
  530. pDst += paddedRectWidth;
  531. }
  532. break;
  533. case 9:
  534. // 9 bytes padding per row required.
  535. for (row = 0; row < transferHeight; row++) {
  536. *((PUINT32_UA)pDst) = 0;
  537. *((PUINT32_UA)(pDst+4)) = 0;
  538. *(pDst + 8) = 0;
  539. pDst += paddedRectWidth;
  540. }
  541. break;
  542. #endif
  543. default:
  544. #ifdef DC_HICOLOR
  545. TRC_ALT((TB, "Invalid numPadBytes %u, rect %u, p/rect %u",
  546. numPadBytes, rectWidth, paddedRectWidth));
  547. #else
  548. TRC_ABORT((TB, "Invalid numPadBytes: %u", numPadBytes));
  549. #endif
  550. break;
  551. }
  552. // All done - update the supplied source pointer.
  553. *ppSrc = pSrc;
  554. DC_END_FN();
  555. }