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.

679 lines
24 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *********************
  4. * * DDraw SAMPLE CODE *
  5. * *********************
  6. *
  7. * Module Name: ddcpyblt.c
  8. *
  9. * Content: several copy and clear blits for Permedia 2
  10. *
  11. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "directx.h"
  16. #include "dd.h"
  17. //-----------------------------------------------------------------------------
  18. //
  19. // PermediaPackedCopyBlt
  20. //
  21. // Does a packed blit, allowing for different source and destination
  22. // partial products.
  23. //
  24. // ppdev----------- the ppdev
  25. // dwDestPitch----- pitch of destination surface
  26. // dwSourcePitch--- pitch of source surface
  27. // pDest----------- pointer to private data structure of dest. surface
  28. // pSource--------- pointer to private data structure of source surface
  29. // *rDest---------- dest. rectangle of blit
  30. // *rSrc----------- source rectangle of blit
  31. // dwWindowBase---- offset of dest. window in frame buffer
  32. // lWindowOffset--- offset of source window in frame buffer
  33. //
  34. //-----------------------------------------------------------------------------
  35. VOID
  36. PermediaPackedCopyBlt( PPDev ppdev, // ppdev
  37. DWORD dwDestPitch, // pitch of dest
  38. DWORD dwSourcePitch,
  39. PermediaSurfaceData* pDest,
  40. PermediaSurfaceData* pSource,
  41. RECTL *rDest,
  42. RECTL *rSrc,
  43. DWORD dwWindowBase,
  44. LONG lWindowOffset
  45. )
  46. {
  47. PERMEDIA_DEFS(ppdev);
  48. LONG lOffset;
  49. LONG lSourceOffset;
  50. LONG lPixelSize=pDest->SurfaceFormat.PixelSize;
  51. LONG lPixelMask=3>>pDest->SurfaceFormat.PixelShift;
  52. LONG lPixelShift=2-pDest->SurfaceFormat.PixelShift;
  53. DBG_DD(( 5, "DDraw:PermediaPackedCopyBlt "
  54. "From %08lx %08lx %08lx %08lx %08lx %08lx %08lx "
  55. "To %08lx %08lx %08lx %08lx %08lx %08lx %08lx",
  56. dwSourcePitch,pSource,rSrc->bottom,rSrc->left,
  57. rSrc->right,rSrc->top,lWindowOffset,
  58. dwDestPitch,pDest,rDest->bottom,rDest->left,
  59. rDest->right,rDest->top,dwWindowBase));
  60. ASSERTDD(!(rSrc->top<0) && !(rSrc->left<0),
  61. "PermediaPackedCopyBlt: cannot handle neg. src coordinates");
  62. ASSERTDD(!(rDest->top<0) && !(rDest->left<0),
  63. "PermediaPackedCopyBlt: cannot handle neg. src coordinates");
  64. lOffset = (((rDest->left & lPixelMask)-(rSrc->left & lPixelMask)) & 7);
  65. lSourceOffset = lWindowOffset +
  66. RECTS_PIXEL_OFFSET(rSrc, rDest,
  67. dwSourcePitch, dwDestPitch,
  68. lPixelMask ) +
  69. LINEAR_FUDGE(dwSourcePitch, dwDestPitch, rDest);
  70. RESERVEDMAPTR(14);
  71. SEND_PERMEDIA_DATA( FBPixelOffset, 0x0);
  72. SEND_PERMEDIA_DATA( FBReadPixel, pDest->SurfaceFormat.FBReadPixel);
  73. // set packed with offset
  74. SEND_PERMEDIA_DATA( FBWindowBase, dwWindowBase);
  75. SEND_PERMEDIA_DATA( FBReadMode,
  76. PM_FBREADMODE_PARTIAL(pSource->ulPackedPP) |
  77. PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) |
  78. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) |
  79. PM_FBREADMODE_RELATIVEOFFSET(lOffset));
  80. SEND_PERMEDIA_DATA( FBWriteConfig,
  81. PM_FBREADMODE_PARTIAL(pDest->ulPackedPP) |
  82. PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) |
  83. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) |
  84. PM_FBREADMODE_RELATIVEOFFSET(lOffset));
  85. SEND_PERMEDIA_DATA( LogicalOpMode, __PERMEDIA_DISABLE);
  86. SEND_PERMEDIA_DATA( FBSourceOffset, lSourceOffset);
  87. // Render the rectangle
  88. if (lSourceOffset >= 0) {
  89. // Use left to right and top to bottom
  90. SEND_PERMEDIA_DATA( StartXDom,
  91. INTtoFIXED(rDest->left >> lPixelShift));
  92. SEND_PERMEDIA_DATA( StartXSub,
  93. INTtoFIXED((rDest->right >> lPixelShift) + lPixelMask));
  94. SEND_PERMEDIA_DATA( PackedDataLimits,
  95. PM_PACKEDDATALIMITS_OFFSET(lOffset) |
  96. PM_PACKEDDATALIMITS_XSTART(rDest->left) |
  97. PM_PACKEDDATALIMITS_XEND(rDest->right));
  98. SEND_PERMEDIA_DATA( StartY, INTtoFIXED(rDest->top));
  99. SEND_PERMEDIA_DATA( dY, INTtoFIXED(1));
  100. }
  101. else {
  102. // Use right to left and bottom to top
  103. SEND_PERMEDIA_DATA( StartXDom,
  104. INTtoFIXED(((rDest->right) >> lPixelShift) + lPixelMask));
  105. SEND_PERMEDIA_DATA( StartXSub,
  106. INTtoFIXED(rDest->left >> lPixelShift));
  107. SEND_PERMEDIA_DATA( PackedDataLimits,
  108. PM_PACKEDDATALIMITS_OFFSET(lOffset) |
  109. PM_PACKEDDATALIMITS_XSTART(rDest->right) |
  110. PM_PACKEDDATALIMITS_XEND(rDest->left));
  111. SEND_PERMEDIA_DATA( StartY, INTtoFIXED(rDest->bottom - 1));
  112. SEND_PERMEDIA_DATA( dY, (DWORD)INTtoFIXED(-1));
  113. }
  114. SEND_PERMEDIA_DATA( Count, rDest->bottom - rDest->top);
  115. SEND_PERMEDIA_DATA( Render, __RENDER_TRAPEZOID_PRIMITIVE);
  116. COMMITDMAPTR();
  117. FLUSHDMA();
  118. } // PermediaPackedCopyBlt
  119. //-----------------------------------------------------------------------------
  120. //
  121. // PermediaPatchedCopyBlt
  122. //
  123. // Does a patched blit, i.e. blits from source to destination and
  124. // turns on patching. Note that this method cannot use packed blits.
  125. //
  126. // ppdev----------- the ppdev
  127. // dwDestPitch----- pitch of destination surface
  128. // dwSourcePitch--- pitch of source surface
  129. // pDest----------- pointer to private data structure of dest. surface
  130. // pSource--------- pointer to private data structure of source surface
  131. // *rDest---------- dest. rectangle of blit
  132. // *rSrc----------- source rectangle of blit
  133. // dwWindowBase---- offset of dest. window in frame buffer
  134. // lWindowOffset--- offset of source window in frame buffer
  135. //
  136. //-----------------------------------------------------------------------------
  137. VOID
  138. PermediaPatchedCopyBlt( PPDev ppdev,
  139. DWORD dwDestPitch,
  140. DWORD dwSourcePitch,
  141. PermediaSurfaceData* pDest,
  142. PermediaSurfaceData* pSource,
  143. RECTL *rDest,
  144. RECTL *rSrc,
  145. DWORD dwWindowBase,
  146. LONG lWindowOffset
  147. )
  148. {
  149. PERMEDIA_DEFS(ppdev);
  150. LONG lSourceOffset;
  151. LONG lPixelSize=pDest->SurfaceFormat.PixelSize;
  152. LONG lPixelMask=pDest->SurfaceFormat.PixelMask;
  153. LONG lPixelShift=pDest->SurfaceFormat.PixelShift;
  154. ASSERTDD(!(rSrc->top<0) && !(rSrc->left<0),
  155. "PermediaPackedCopyBlt: cannot handle neg. src coordinates");
  156. ASSERTDD(!(rDest->top<0) && !(rDest->left<0),
  157. "PermediaPackedCopyBlt: cannot handle neg. src coordinates");
  158. DBG_DD(( 5, "DDraw:PermediaPatchedCopyBlt"));
  159. lSourceOffset = lWindowOffset +
  160. RECTS_PIXEL_OFFSET(rSrc, rDest,
  161. dwSourcePitch, dwDestPitch, lPixelMask) +
  162. LINEAR_FUDGE(dwSourcePitch, dwDestPitch, rDest);
  163. RESERVEDMAPTR(13);
  164. SEND_PERMEDIA_DATA( FBPixelOffset, 0x0);
  165. SEND_PERMEDIA_DATA( FBReadPixel, pDest->SurfaceFormat.FBReadPixel);
  166. // Patching isn't symetric, so we need to reverse the patch code depending
  167. // on the direction of the patch
  168. SEND_PERMEDIA_DATA( FBWindowBase, dwWindowBase);
  169. if (pDest->dwFlags & P2_CANPATCH)
  170. {
  171. pDest->dwFlags |= P2_ISPATCHED;
  172. SEND_PERMEDIA_DATA( FBReadMode,
  173. pSource->ulPackedPP |
  174. __FB_READ_SOURCE);
  175. SEND_PERMEDIA_DATA( FBWriteConfig,
  176. pDest->ulPackedPP |
  177. PM_FBREADMODE_PATCHENABLE(__PERMEDIA_ENABLE) |
  178. PM_FBREADMODE_PATCHMODE(__PERMEDIA_SUBPATCH));
  179. } else
  180. {
  181. pDest->dwFlags &= ~P2_ISPATCHED;
  182. SEND_PERMEDIA_DATA( FBReadMode,
  183. pSource->ulPackedPP |
  184. __FB_READ_SOURCE |
  185. PM_FBREADMODE_PATCHENABLE(__PERMEDIA_ENABLE) |
  186. PM_FBREADMODE_PATCHMODE(__PERMEDIA_SUBPATCH) );
  187. SEND_PERMEDIA_DATA(FBWriteConfig, (pDest->ulPackedPP ));
  188. }
  189. SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  190. SEND_PERMEDIA_DATA(FBSourceOffset, lSourceOffset);
  191. // Render the rectangle
  192. if (lSourceOffset >= 0)
  193. {
  194. // Use left to right and top to bottom
  195. SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(rDest->left));
  196. SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(rDest->right));
  197. SEND_PERMEDIA_DATA(StartY, INTtoFIXED(rDest->top));
  198. SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
  199. } else
  200. {
  201. // Use right to left and bottom to top
  202. SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(rDest->right));
  203. SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(rDest->left));
  204. SEND_PERMEDIA_DATA(StartY, INTtoFIXED(rDest->bottom - 1));
  205. SEND_PERMEDIA_DATA(dY, (DWORD)INTtoFIXED(-1));
  206. }
  207. SEND_PERMEDIA_DATA(Count, rDest->bottom - rDest->top);
  208. SEND_PERMEDIA_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE);
  209. COMMITDMAPTR();
  210. FLUSHDMA();
  211. } // PermediaPatchedCopyBlt
  212. //-----------------------------------------------------------------------------
  213. //
  214. // PermediaFastClear
  215. //
  216. // Does a fast clear of a surface. Supports all color depths
  217. // Can clear depth or Frame buffer.
  218. //
  219. // ppdev---------the ppdev
  220. // pPrivateData--pointer to private data structure of dest. surface
  221. // rDest---------rectangle for colorfill in dest. surface
  222. // dwWindowBase--offset of dest. surface in frame buffer
  223. // dwColor-------color for fill
  224. //
  225. //-----------------------------------------------------------------------------
  226. VOID
  227. PermediaFastClear(PPDev ppdev,
  228. PermediaSurfaceData* pPrivateData,
  229. RECTL *rDest,
  230. DWORD dwWindowBase,
  231. DWORD dwColor)
  232. {
  233. PERMEDIA_DEFS(ppdev);
  234. ULONG ulRenderBits;
  235. BOOL bFastFill=TRUE;
  236. LONG lPixelSize=pPrivateData->SurfaceFormat.PixelSize;
  237. DBG_DD(( 5, "DDraw:PermediaFastClear"));
  238. ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData),
  239. "Private Surface data not valid in clear");
  240. ASSERTDD((pPrivateData->dwFlags & P2_PPVALID),
  241. "PermediaFastClear called with invalid PP codes");
  242. ulRenderBits = __RENDER_FAST_FILL_ENABLE
  243. | __RENDER_TRAPEZOID_PRIMITIVE;
  244. // Clear depending on depth
  245. switch (lPixelSize)
  246. {
  247. case __PERMEDIA_4BITPIXEL:
  248. dwColor &= 0xF;
  249. dwColor |= dwColor << 4;
  250. // fall through...
  251. case __PERMEDIA_8BITPIXEL:
  252. dwColor &= 0xFF;
  253. dwColor |= dwColor << 8;
  254. // fall through
  255. case __PERMEDIA_16BITPIXEL:
  256. dwColor &= 0xFFFF;
  257. dwColor |= (dwColor << 16);
  258. break;
  259. case __PERMEDIA_24BITPIXEL:
  260. dwColor &= 0xFFFFFF;
  261. dwColor |= ((dwColor & 0xFF) << 24);
  262. // Can't use SGRAM fast block fills on any color, only on grey.
  263. if (((dwColor & 0xFF) == ((dwColor & 0xFF00) >> 8)) &&
  264. ((dwColor & 0xFF) == ((dwColor & 0xFF0000) >> 16))) {
  265. bFastFill = TRUE;
  266. } else {
  267. bFastFill = FALSE;
  268. }
  269. break;
  270. default:
  271. break;
  272. }
  273. RESERVEDMAPTR(15);
  274. SEND_PERMEDIA_DATA( dXDom, 0x0);
  275. SEND_PERMEDIA_DATA( dXSub, 0x0);
  276. SEND_PERMEDIA_DATA( FBPixelOffset, 0);
  277. SEND_PERMEDIA_DATA( FBReadPixel,
  278. pPrivateData->SurfaceFormat.FBReadPixel);
  279. if (bFastFill)
  280. {
  281. SEND_PERMEDIA_DATA(FBBlockColor, dwColor);
  282. } else
  283. {
  284. ulRenderBits &= ~__RENDER_FAST_FILL_ENABLE;
  285. SEND_PERMEDIA_DATA(FBWriteData, dwColor);
  286. }
  287. SEND_PERMEDIA_DATA(FBReadMode,
  288. PM_FBREADMODE_PARTIAL(pPrivateData->ulPackedPP)|
  289. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE));
  290. SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_CONSTANT_FB_WRITE);
  291. SEND_PERMEDIA_DATA(FBWindowBase, dwWindowBase);
  292. // Render the rectangle
  293. SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(rDest->left));
  294. SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(rDest->right));
  295. SEND_PERMEDIA_DATA(StartY, INTtoFIXED(rDest->top));
  296. SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
  297. SEND_PERMEDIA_DATA(Count, rDest->bottom - rDest->top);
  298. SEND_PERMEDIA_DATA(Render, ulRenderBits);
  299. // Reset our pixel values.
  300. SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
  301. COMMITDMAPTR();
  302. FLUSHDMA();
  303. } //PermediaFastClear
  304. //-----------------------------------------------------------------------------
  305. //
  306. // PermediaClearManagedSurface
  307. //
  308. // Does a clear of a managed surface. Supports all color depths
  309. //
  310. // PixelSize-----surface color depth
  311. // rDest---------rectangle for colorfill in dest. surface
  312. // fpVidMem------pointer to fill
  313. // lPitch--------Surface Pitch
  314. // dwColor-------color for fill
  315. //
  316. //-----------------------------------------------------------------------------
  317. VOID
  318. PermediaClearManagedSurface(DWORD PixelSize,
  319. RECTL *rDest,
  320. FLATPTR fpVidMem,
  321. LONG lPitch,
  322. DWORD dwColor)
  323. {
  324. BYTE* pDestStart;
  325. LONG i;
  326. DBG_DD(( 5, "DDraw:PermediaClearManagedSurface"));
  327. LONG lByteWidth = rDest->right - rDest->left;
  328. LONG lHeight = rDest->bottom - rDest->top;
  329. // Calculate the start pointer for the dest
  330. pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
  331. // Clear depending on depth
  332. switch (PixelSize)
  333. {
  334. case __PERMEDIA_4BITPIXEL:
  335. {
  336. DWORD right=rDest->right,left=rDest->left;
  337. dwColor &= 0x0F;
  338. dwColor |= dwColor << 4;
  339. if (right & 1)
  340. {
  341. pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
  342. pDestStart += right/2;
  343. for (i=0;i<lHeight;i++)
  344. {
  345. pDestStart[i*lPitch] = (pDestStart[i*lPitch] & 0xF0) |
  346. (BYTE)(dwColor & 0x0F);
  347. }
  348. right--;
  349. }
  350. if (left & 1)
  351. {
  352. pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
  353. pDestStart += left/2;
  354. for (i=0;i<lHeight;i++)
  355. {
  356. pDestStart[i*lPitch] = (pDestStart[i*lPitch] & 0x0F) |
  357. (BYTE)(dwColor << 4);
  358. }
  359. left++;
  360. }
  361. pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
  362. while (--lHeight >= 0)
  363. {
  364. while (left<right)
  365. {
  366. pDestStart[left/2]=(BYTE)dwColor;
  367. left +=2;
  368. }
  369. pDestStart += lPitch;
  370. }
  371. }
  372. break;
  373. case __PERMEDIA_8BITPIXEL:
  374. pDestStart += rDest->left;
  375. while (--lHeight >= 0)
  376. {
  377. for (i=0;i<lByteWidth;i++)
  378. pDestStart[i]=(BYTE)dwColor;
  379. pDestStart += lPitch;
  380. }
  381. break;
  382. // fall through
  383. case __PERMEDIA_16BITPIXEL:
  384. pDestStart += rDest->left*2;
  385. while (--lHeight >= 0)
  386. {
  387. LPWORD lpWord=(LPWORD)pDestStart;
  388. for (i=0;i<lByteWidth;i++)
  389. lpWord[i]=(WORD)dwColor;
  390. pDestStart += lPitch;
  391. }
  392. break;
  393. case __PERMEDIA_24BITPIXEL:
  394. dwColor &= 0xFFFFFF;
  395. dwColor |= ((dwColor & 0xFF) << 24);
  396. default:
  397. pDestStart += rDest->left*4;
  398. while (--lHeight >= 0)
  399. {
  400. LPDWORD lpDWord=(LPDWORD)pDestStart;
  401. for (i=0;i<lByteWidth;i++)
  402. lpDWord[i]=(WORD)dwColor;
  403. pDestStart += lPitch;
  404. }
  405. break;
  406. }
  407. }
  408. //-----------------------------------------------------------------------------
  409. //
  410. // PermediaFastLBClear
  411. //
  412. // Does a fast clear of the Permedia Z (local) Buffer. The Permedia Z Buffer
  413. // is always 16 bit wide...
  414. //
  415. // ppdev---------the ppdev
  416. // pPrivateData--pointer to private data structure of dest. surface
  417. // rDest---------rectangle for colorfill in dest. surface
  418. // dwWindowBase--offset of dest. surface in frame buffer
  419. // dwColor-------color for fill
  420. //
  421. //-----------------------------------------------------------------------------
  422. VOID
  423. PermediaFastLBClear(PPDev ppdev,
  424. PermediaSurfaceData* pPrivateData,
  425. RECTL *rDest,
  426. DWORD dwWindowBase,
  427. DWORD dwColor)
  428. {
  429. PERMEDIA_DEFS(ppdev);
  430. DBG_DD(( 5, "DDraw:PermediaFastLBClear"));
  431. ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData),
  432. "Private Surface data not valid in clear");
  433. ASSERTDD((pPrivateData->dwFlags & P2_PPVALID),
  434. "PermediaFastClear called with invalid PP codes");
  435. // Clear according to Z-Buffer depth
  436. dwColor &= 0xFFFF;
  437. dwColor |= dwColor << 16;
  438. RESERVEDMAPTR(15);
  439. SEND_PERMEDIA_DATA( dXDom, 0x0);
  440. SEND_PERMEDIA_DATA( dXSub, 0x0);
  441. SEND_PERMEDIA_DATA( FBPixelOffset, 0);
  442. SEND_PERMEDIA_DATA( FBReadPixel, __PERMEDIA_16BITPIXEL);
  443. SEND_PERMEDIA_DATA( FBBlockColor, dwColor);
  444. SEND_PERMEDIA_DATA( FBReadMode,
  445. PM_FBREADMODE_PARTIAL(pPrivateData->ulPackedPP) |
  446. PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE));
  447. SEND_PERMEDIA_DATA( LogicalOpMode, __PERMEDIA_CONSTANT_FB_WRITE);
  448. SEND_PERMEDIA_DATA( FBWindowBase, dwWindowBase);
  449. SEND_PERMEDIA_DATA( StartXDom, INTtoFIXED(rDest->left));
  450. SEND_PERMEDIA_DATA( StartXSub, INTtoFIXED(rDest->right));
  451. SEND_PERMEDIA_DATA( StartY, INTtoFIXED(rDest->top));
  452. SEND_PERMEDIA_DATA( dY, INTtoFIXED(1));
  453. SEND_PERMEDIA_DATA( Count, rDest->bottom - rDest->top);
  454. SEND_PERMEDIA_DATA( Render, __RENDER_FAST_FILL_ENABLE
  455. |__RENDER_TRAPEZOID_PRIMITIVE);
  456. // Reset our pixel values.
  457. SEND_PERMEDIA_DATA( LogicalOpMode, __PERMEDIA_DISABLE);
  458. COMMITDMAPTR();
  459. FLUSHDMA();
  460. } // PermediaFastLBClear
  461. //-----------------------------------------------------------------------------
  462. //
  463. // SysMemToSysMemSurfaceCopy
  464. //
  465. // Does a copy from System memory to System memory (either from or to an
  466. // AGP surface, or any other system memory surface)
  467. //
  468. //-----------------------------------------------------------------------------
  469. VOID
  470. SysMemToSysMemSurfaceCopy(FLATPTR fpSrcVidMem,
  471. LONG lSrcPitch,
  472. DWORD dwSrcBitCount,
  473. FLATPTR fpDstVidMem,
  474. LONG lDstPitch,
  475. DWORD dwDstBitCount,
  476. RECTL* rSource,
  477. RECTL* rDest)
  478. {
  479. BYTE* pSourceStart;
  480. BYTE* pDestStart;
  481. BYTE pixSource;
  482. BYTE* pNewDest;
  483. BYTE* pNewSource;
  484. DBG_DD(( 5, "DDraw:SysMemToSysMemSurfaceCopy"));
  485. LONG lByteWidth = rSource->right - rSource->left;
  486. LONG lHeight = rSource->bottom - rSource->top;
  487. if (NULL == fpSrcVidMem || NULL == fpDstVidMem)
  488. {
  489. DBG_DD(( 0, "DDraw:SysMemToSysMemSurfaceCopy unexpected 0 fpVidMem"));
  490. return;
  491. }
  492. // Calculate the start pointer for the source and the dest
  493. pSourceStart = (BYTE*)(fpSrcVidMem + (rSource->top * lSrcPitch));
  494. pDestStart = (BYTE*)(fpDstVidMem + (rDest->top * lDstPitch));
  495. // Be careful if the source is 4 bits deep.
  496. if(4 == dwSrcBitCount)
  497. {
  498. // May have to handle horrible single pixel edges. Check if we need to
  499. if (!((1 & (rSource->left ^ rDest->left)) == 1))
  500. {
  501. pSourceStart += rSource->left / 2;
  502. pDestStart += rDest->left / 2;
  503. lByteWidth /= 2;
  504. // Do we have to account for the odd pixel at the start?
  505. if (rSource->left & 0x1)
  506. {
  507. lByteWidth--;
  508. }
  509. // If the end is odd then miss of the last nibble (do it later).
  510. if (rSource->right & 0x1)
  511. {
  512. lByteWidth--;
  513. }
  514. while (--lHeight >= 0)
  515. {
  516. // Potentially copy the left hand pixel
  517. if (rSource->left & 0x1) {
  518. *pDestStart &= 0x0F;
  519. *pDestStart |= (*pSourceStart & 0xF0);
  520. pNewDest = pDestStart + 1;
  521. pNewSource = pSourceStart + 1;
  522. } else {
  523. pNewDest = pDestStart;
  524. pNewSource = pSourceStart;
  525. }
  526. // Byte copy the rest of the field
  527. memcpy(pNewDest, pNewSource, lByteWidth);
  528. // Potentially copy the right hand pixel
  529. if (rSource->right & 0x1) {
  530. *(pNewDest + lByteWidth) &= 0xF0;
  531. *(pNewDest + lByteWidth) |=
  532. (*(pNewSource + lByteWidth) & 0xF);
  533. }
  534. pDestStart += lDstPitch;
  535. pSourceStart += lSrcPitch;
  536. }
  537. } else
  538. {
  539. // Do it the hard way - copy single pixels one at a time
  540. pSourceStart += rSource->left / 2;
  541. pDestStart += rDest->left / 2;
  542. while (--lHeight >= 0)
  543. {
  544. BOOL bOddSource = rSource->left & 0x1;
  545. BOOL bOddDest = rDest->left & 0x1;
  546. pNewDest = pDestStart;
  547. pNewSource = pSourceStart;
  548. for (INT i = 0; i < lByteWidth; i++)
  549. {
  550. if (bOddSource) {
  551. pixSource = (*pNewSource & 0xF0) >> 4;
  552. pNewSource++;
  553. } else {
  554. pixSource = (*pNewSource & 0x0F);
  555. }
  556. if (bOddDest) {
  557. *pNewDest &= 0x0F;
  558. *pNewDest |= pixSource << 4;
  559. pNewDest++;
  560. } else {
  561. *pNewDest &= 0xF0;
  562. *pNewDest |= pixSource;
  563. }
  564. bOddSource = !bOddSource;
  565. bOddDest = !bOddDest;
  566. }
  567. // Step onto the next line
  568. pDestStart += lDstPitch;
  569. pSourceStart += lSrcPitch;
  570. }
  571. }
  572. }
  573. else // The simple 8, 16 or 24 bit copy
  574. {
  575. pSourceStart += rSource->left * (dwSrcBitCount >> 3);
  576. pDestStart += rDest->left * (dwDstBitCount >> 3);
  577. lByteWidth *= (dwSrcBitCount >> 3);
  578. while (--lHeight >= 0)
  579. {
  580. memcpy(pDestStart, pSourceStart, lByteWidth);
  581. pDestStart += lDstPitch;
  582. pSourceStart += lSrcPitch;
  583. };
  584. }
  585. } // SysMemToSysMemSurfaceCopy