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.

2519 lines
71 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name:
  3. *
  4. * bltlnk.cxx
  5. *
  6. * Abstract
  7. *
  8. * This module does general bit blt functions for 1,4,8,16,24,and 32 bpp
  9. * DIB format bitmaps. SrcBltxx routines are used to align and copy data.
  10. *
  11. * Author:
  12. *
  13. * Mark Enstrom (marke) 9-27-93
  14. *
  15. * Copyright (c) 1993-1999 Microsoft Corporation
  16. \**************************************************************************/
  17. #include "precomp.hxx"
  18. PVOID pvGetEngRbrush(BRUSHOBJ *pbo);
  19. extern PFN_SRCCPY SrcCopyFunctionTable[];
  20. PFN_BLTLNKROP RopFunctionTable[] = {
  21. vRop2Function0,vRop2Function1,vRop2Function2,vRop2Function3,
  22. vRop2Function4,vRop2Function5,vRop2Function6,vRop2Function7,
  23. vRop2Function8,vRop2Function9,vRop2FunctionA,vRop2FunctionB,
  24. vRop2FunctionC,vRop2FunctionD,vRop2FunctionE,vRop2FunctionF
  25. };
  26. #define DBG_BLTLNK 0
  27. #if DBG_BLTLNK
  28. ULONG DbgBltLnk = 0;
  29. #endif
  30. #define SCAN_LINE_BUFFER_LENGTH 64
  31. /******************************Public*Routine******************************\
  32. *
  33. * Routine Name
  34. *
  35. * BltLnk
  36. *
  37. * Routine Description:
  38. *
  39. * BltLnk prepares all parameters then breaks the BitBlt region into
  40. * rectangles based on clip information. Each rect is sent to BltLnkRect
  41. * for operation.
  42. *
  43. * Arguments:
  44. *
  45. * pdioDst - Destination surface information
  46. * pdioSrc - Source surface information
  47. * pdioMsk - Mask information
  48. * pco - Clip Object
  49. * pxlo - Color translation object
  50. * prclDst - Destination rectangle
  51. * pptlSrc - Source Starting offset point
  52. * pptlMsk - Mask Starting offset point
  53. * pdbrush - Brush Information
  54. * pptlBrush - Brush Starting offset point
  55. * rop4 - Logical Raster Operation
  56. *
  57. * Return Value:
  58. *
  59. * BOOLEAN Status
  60. *
  61. \**************************************************************************/
  62. BOOL
  63. BltLnk(
  64. SURFACE *pdioDst, // Target surface
  65. SURFACE *pdioSrc, // Source surface
  66. SURFACE *pdioMsk, // Msk
  67. ECLIPOBJ *pco, // Clip through this
  68. XLATE *pxlo, // Color translation
  69. RECTL *prclDst, // Target offset and extent
  70. POINTL *pptlSrc, // Source offset
  71. POINTL *pptlMsk, // Msk offset
  72. BRUSHOBJ *pdbrush, // Brush data (from cbRealizeBrush)
  73. POINTL *pptlBrush, // Brush offset (origin)
  74. ROP4 rop4) // Raster operation
  75. {
  76. BOOL bMore;
  77. ULONG ircl;
  78. LONG MaxWidth;
  79. BLTLNKINFO bltInfo;
  80. CLIPENUMRECT clenr;
  81. BYTE Rop3Low;
  82. BYTE Rop3High;
  83. BYTE RopSrcLow;
  84. BYTE RopSrcHigh;
  85. BYTE RopDstLow;
  86. BYTE RopDstHigh;
  87. BOOL bNeedMsk = FALSE;
  88. BOOL bNeedPat = FALSE;
  89. BOOL bNeedSrc = FALSE;
  90. BOOL bNeedDst = FALSE;
  91. BOOL bNeedPatLow = FALSE;
  92. BOOL bNeedSrcLow = FALSE;
  93. BOOL bNeedDstLow = FALSE;
  94. BOOL bNeedPatHigh = FALSE;
  95. BOOL bNeedSrcHigh = FALSE;
  96. BOOL bNeedDstHigh = FALSE;
  97. BOOL bLocalAlloc = FALSE;
  98. SURFMEM SurfDimo;
  99. PENGBRUSH pBrush = NULL;
  100. #if DBG_BLTLNK
  101. if (DbgBltLnk >= 1)
  102. {
  103. DbgPrint("BltLnk: rop4 = %lx\n",rop4);
  104. DbgPrint("pdioDst = 0x%p\n",pdioDst);
  105. DbgPrint("pdioSrc = 0x%p\n",pdioSrc);
  106. DbgPrint(" Destination Format = %li\n",pdioDst->iFormat());
  107. DbgPrint(" prclDst = %li,%li to %li,%li\n",
  108. prclDst->left,
  109. prclDst->top,
  110. prclDst->right,
  111. prclDst->bottom);
  112. }
  113. #endif
  114. //
  115. // make sure destination format is not a device format or
  116. // unknown format
  117. //
  118. ASSERTGDI(pdioDst->iFormat() != 0, "ERROR device dst format in BltLnk\n");
  119. ASSERTGDI(pdioDst->iFormat() <= 7, "ERROR invalid dst format in BltLnk\n");
  120. //
  121. // check rectangle bounds
  122. //
  123. ASSERTGDI(prclDst->left < prclDst->right, "ERROR prclDst->left < right");
  124. ASSERTGDI(prclDst->top < prclDst->bottom, "ERROR prclDst->top < bottom");
  125. //
  126. // calculate the widest blt using based on the width of scan line storage
  127. //
  128. // These numbers assume worst case unaligned transfers
  129. //
  130. switch(pdioDst->iFormat())
  131. {
  132. case BMF_1BPP:
  133. MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 5) -62;
  134. break;
  135. case BMF_4BPP:
  136. MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 3) -14;
  137. break;
  138. case BMF_8BPP:
  139. MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 2) -6;
  140. break;
  141. case BMF_16BPP:
  142. MaxWidth = (SCAN_LINE_BUFFER_LENGTH << 1) -2;
  143. break;
  144. case BMF_24BPP:
  145. MaxWidth = ((SCAN_LINE_BUFFER_LENGTH * 4) / 3) - 2;
  146. break;
  147. case BMF_32BPP:
  148. MaxWidth = SCAN_LINE_BUFFER_LENGTH;
  149. break;
  150. }
  151. //
  152. // set bltInfo params
  153. //
  154. if (pxlo == NULL)
  155. {
  156. bltInfo.pxlo = &xloIdent;
  157. }
  158. else
  159. {
  160. bltInfo.pxlo = pxlo;
  161. }
  162. bltInfo.pdioDst = pdioDst;
  163. bltInfo.pdioSrc = pdioSrc;
  164. bltInfo.pco = (ECLIPOBJ *)pco;
  165. bltInfo.rclDst = *prclDst;
  166. bltInfo.pdbrush = (EBRUSHOBJ *) pdbrush;
  167. //
  168. // rop4 is a logical combination of Src,Dst,Pattern,Mask
  169. //
  170. // rop4[15:08] represents the rop3 used when Mask is high
  171. // rop4[07:00] represents the rop3 used when Mask is low
  172. //
  173. // When rop4[15:08] == rop4[07:00], this indicates that no mask
  174. // is needed for the operation.
  175. //
  176. // rop3 [07:04] represents the rop2 to be used is pattern is high
  177. // rop3 [03:00] represents the rop2 to be used is pattern is low
  178. //
  179. // when rop3[07:04] == rop3[03:00], this indicates that no pattern
  180. // is needed for the operation.
  181. //
  182. // By exchanging Src and Dst with Pattern and Mask, it is possible
  183. // to compare rop4s to also determine is Src and Dst are needed for
  184. // the logical operation. BltLnk does this below.
  185. //
  186. // A rop2 represents 16 different ways 2 variables may be combined, this
  187. // is the basic logic element used in BltLnk.
  188. //
  189. // As an example of logic reduction rop4 = B8B8 would
  190. // immediatly reduce to a rop3 because rop4[15:08] == rop4[07:00]. This
  191. // leaves rop3 = B8. This is expressed as a Karnaugh map as:
  192. //
  193. //
  194. // PS 00 01 11 10
  195. // �����������Ŀ
  196. // D 0� 0� 0� 0� 1�
  197. // �����������Ĵ
  198. // 1� 0� 1� 1� 1�
  199. // �������������
  200. // This reduces to a logic operation of Dst = (Pat & ~Src) | (Dst & Src)
  201. //
  202. // This is a special case rop handled by unique functions, but in gereral BltLnk
  203. // will handle a rop like this by reducing it to functions of rop2s, in this case
  204. //
  205. // Pat and (Src and Dst) OR ~pat and (~Src or Dst)
  206. //
  207. // BltLnk will always try to manipulate the variables so that a rop2
  208. // function may be performed directly. If this is not possible, a rop3
  209. // functions is broken into 2 rop2 functions, one for pat=high and one
  210. // for pat = low. (or mask in a rop3 in which pat is not needed but mask is)
  211. // For a full rop4, two rop 3 passes are made, one for mask = high and
  212. // one for mask = low.
  213. //
  214. // Actual Mask Blt, rop4 = AACC is handled by a special case accelerator.
  215. //
  216. // Masked Solid fill (Src = 1bpp mask), rop4 = B8B8 is also handled by a
  217. // special case accelerator.
  218. //
  219. Rop3Low = (BYTE)(rop4 & 0xff);
  220. Rop3High = (BYTE)(rop4 >> 8);
  221. RopSrcLow = (Rop3Low & 0xC3) | ((Rop3Low & 0x0C) << 2) | ((Rop3Low & 0x30) >> 2);
  222. RopDstLow = (Rop3Low & 0xA5) | ((Rop3Low & 0x0A) << 3) | ((Rop3Low & 0x50) >> 3);
  223. RopSrcHigh = (Rop3High & 0xC3)|((Rop3High & 0x0C) << 2)|((Rop3High & 0x30) >> 2);
  224. RopDstHigh = (Rop3High & 0xA5)|((Rop3High & 0x0A) << 3)|((Rop3High & 0x50) >> 3);
  225. #if DBG_BLTLNK
  226. if (DbgBltLnk >= 2)
  227. {
  228. DbgPrint (" RopSrcLow = %lx, RopDstLow = %lx\n",
  229. RopSrcLow,RopDstLow);
  230. DbgPrint (" RopSrcHigh = %lx, RopDstHigh = %lx\n",
  231. RopSrcHigh,RopDstHigh);
  232. }
  233. #endif
  234. //
  235. // if rop4[15:08] = rop4[07:00] then no mask is needed
  236. //
  237. if ((rop4 & 0xff) != ((rop4) >> 8))
  238. {
  239. bNeedMsk = TRUE;
  240. }
  241. //
  242. // if Rop3Low[7:4] = Rop3Low[3:0] and
  243. // if Rop3High[7:4] = Rop3High[3:0] Then no pat is needed
  244. //
  245. if ((Rop3Low & 0x0f) != ((Rop3Low & 0xf0) >> 4))
  246. {
  247. bNeedPatLow = TRUE;
  248. }
  249. if ((Rop3High & 0x0f) != ((Rop3High & 0xf0) >> 4))
  250. {
  251. bNeedPatHigh = TRUE;
  252. }
  253. bNeedPat = bNeedPatLow || bNeedPatHigh;
  254. //
  255. // if RopSrcLow[7:4] = RopSrcLow[3:0] and
  256. // if RopSrcHigh[7:4] = RopSrcHigh[3:0] Then no src is needed
  257. //
  258. if ((RopSrcLow & 0x0F) != ((RopSrcLow & 0xF0) >> 4))
  259. {
  260. bNeedSrcLow = TRUE;
  261. }
  262. if ((RopSrcHigh & 0x0F) != ((RopSrcHigh & 0xF0) >> 4))
  263. {
  264. bNeedSrcHigh = TRUE;
  265. }
  266. bNeedSrc = bNeedSrcLow || bNeedSrcHigh;
  267. //
  268. // if RopDstLow[7:4] = RopDstLow[3:0] and
  269. // if RopDstHigh[7:4] = RopDstHigh[3:0] Then no Dst is needed
  270. //
  271. if (((RopDstLow & 0x0f) != ((RopDstLow & 0xF0) >> 4)))
  272. {
  273. bNeedDstLow = TRUE;
  274. }
  275. if (((RopDstHigh & 0x0f) != ((RopDstHigh & 0xF0) >> 4)))
  276. {
  277. bNeedDstHigh = TRUE;
  278. }
  279. bNeedDst = bNeedDstHigh || bNeedDstLow;
  280. //
  281. // get the brush realization if we'll need it. This is either
  282. // when the rop specifies a pattern is needed or when the rop specifies
  283. // that a mask is needed but no mask is passed in, meaning the mask
  284. // must be taken from the brush
  285. //
  286. if ((bNeedPat) || (bNeedMsk && (pdioMsk == (SURFACE*) NULL)))
  287. {
  288. if ((pdbrush != NULL) && (pdbrush->iSolidColor == -1))
  289. {
  290. pBrush = (PENGBRUSH) pvGetEngRbrush(pdbrush);
  291. }
  292. else
  293. {
  294. pBrush = (PENGBRUSH) pdbrush;
  295. }
  296. }
  297. #if DBG_BLTLNK
  298. if (DbgBltLnk >= 2)
  299. {
  300. DbgPrint(" pBrush = %p\n",pBrush);
  301. DbgPrint(" bNeedMsk = %x\n",bNeedMsk);
  302. DbgPrint(" bNeedPat = %x\n",bNeedPat);
  303. DbgPrint(" bNeedSrc = %x\n",bNeedSrc);
  304. DbgPrint(" bNeedDst = %x\n",bNeedDst);
  305. }
  306. #endif
  307. //
  308. // Compute the direction of clipping enumeration
  309. //
  310. bltInfo.xDir = bltInfo.yDir = 1L;
  311. bltInfo.iDir = CD_ANY;
  312. //
  313. // Get clip rectangle enumeration and directions set up. BltLnkRect
  314. // always performs blt operations left to right using a temp
  315. // scan line buffer.
  316. // xDir is set to 1 or -1 as a flag
  317. // for accelerators to not accelerate a special case if xDir < 0
  318. //
  319. if (bNeedSrc)
  320. {
  321. ASSERTGDI(pdioSrc != (SURFACE*) NULL, "ERROR: Bltlnk: no pdioSrc");
  322. //
  323. // fill out bltinfo for calls to BltLnkRect
  324. //
  325. bltInfo.pjSrc = (PBYTE) pdioSrc->pvScan0();
  326. bltInfo.lDeltaSrc = pdioSrc->lDelta();
  327. bltInfo.xSrcOrg = pptlSrc->x;
  328. bltInfo.ySrcOrg = pptlSrc->y;
  329. #if DBG_BLTLNK
  330. if (DbgBltLnk >= 1) {
  331. DbgPrint(" Src Format = %li\n",pdioSrc->iFormat());
  332. DbgPrint(" Src Point = %li,%li\n",pptlSrc->x,pptlSrc->y);
  333. }
  334. if (DbgBltLnk >= 2)
  335. {
  336. DbgPrint(" pjSrc = %p, lDeltaSrc = %li\n",
  337. bltInfo.pjSrc,bltInfo.lDeltaSrc);
  338. DbgPrint(" xSrcOrg = %li, ySrcOrg = %li\n",
  339. bltInfo.xSrcOrg,bltInfo.ySrcOrg);
  340. }
  341. #endif
  342. //
  343. // Only BLT bottom to top if the source and destination are on the
  344. // same surface and the Dst is below the Src.
  345. //
  346. // �������Ŀ
  347. // ����ijSrc �
  348. // �Dst � �
  349. // � � �
  350. // � ���������
  351. // ���������
  352. //
  353. // Also check if it is the same surface for BLTs that must be
  354. // done right to left. This is a case where the starting scan
  355. // lines for Src and Dst are the same and the Src is to the
  356. // left of the dst. We do this by comparing the pvScan0 pointers.
  357. // The reason is that if we were to compare surface pointers or
  358. // handles this won't work on some drivers that punt this call
  359. // to GDI but pass us different SURFOBJs for the source and
  360. // destination even when they're really the same surface.
  361. //
  362. // ������������Ŀ
  363. // �Src �Dst �
  364. // � � �
  365. // � � �
  366. // ��������������
  367. //
  368. if (pdioSrc->pvScan0() == pdioDst->pvScan0())
  369. {
  370. if (pptlSrc->y < prclDst->top)
  371. {
  372. bltInfo.yDir = -1;
  373. bltInfo.iDir = CD_RIGHTUP;
  374. }
  375. //
  376. // check if:
  377. //
  378. // Src scan line = Dst Scan line AND Src < Dst
  379. // and width > Scan line buffer
  380. // OR
  381. // MaskBlt needing Src for RopHigh and RopLow
  382. // AND Src and Dst rect intersect
  383. //
  384. if ((pptlSrc->y == prclDst->top) &&
  385. (pptlSrc->x < prclDst->left))
  386. {
  387. //
  388. // This blt requires right to left operation. This will
  389. // disable special accelerators in BltLnkRect.
  390. //
  391. bltInfo.xDir = -1;
  392. }
  393. //
  394. // cases requiring temp Src:
  395. //
  396. if (
  397. (bNeedMsk && bNeedSrcLow && bNeedSrcHigh) ||
  398. (
  399. ((bltInfo.xDir == -1) || (bltInfo.yDir == -1)) &&
  400. ((prclDst->right - prclDst->left) > MaxWidth)
  401. )
  402. )
  403. {
  404. //
  405. // create a temp src surface of width prclDst->right - prclDst->left
  406. // and height prclDst->bottom - prclDst->top
  407. //
  408. DEVBITMAPINFO dbmi;
  409. dbmi.iFormat = pdioSrc->iFormat();
  410. dbmi.cxBitmap = prclDst->right - prclDst->left;
  411. dbmi.cyBitmap = prclDst->bottom - prclDst->top;
  412. dbmi.hpal = (HPALETTE) 0;
  413. dbmi.fl = BMF_TOPDOWN;
  414. SurfDimo.bCreateDIB(&dbmi, (PVOID) NULL);
  415. if (!SurfDimo.bValid())
  416. {
  417. //
  418. // (common return?)
  419. //
  420. return(FALSE);
  421. }
  422. //
  423. // fill DIB with data from actual Src
  424. //
  425. POINTL ptlSrc;
  426. ptlSrc.x = pptlSrc->x;
  427. ptlSrc.y = pptlSrc->y;
  428. RECTL rclDst;
  429. rclDst.left = 0;
  430. rclDst.right = dbmi.cxBitmap;
  431. rclDst.top = 0;
  432. rclDst.bottom = dbmi.cyBitmap;
  433. if (!EngCopyBits(SurfDimo.pSurfobj(),
  434. pdioSrc->pSurfobj(),
  435. (CLIPOBJ *)NULL,
  436. &xloIdent,
  437. &rclDst,
  438. &ptlSrc)
  439. )
  440. {
  441. //
  442. // return error
  443. //
  444. return(FALSE);
  445. }
  446. //
  447. // fill in new Src info for BltLnkRect
  448. //
  449. bltInfo.pjSrc = (PBYTE) SurfDimo.ps->pvScan0();
  450. bltInfo.lDeltaSrc = SurfDimo.ps->lDelta();
  451. bltInfo.xSrcOrg = 0;
  452. bltInfo.ySrcOrg = 0;
  453. #if DBG_BLTLNK
  454. if (DbgBltLnk >= 1) {
  455. DbgPrint(" Allocate temp buffer: pjSrc = 0x%p\n",bltInfo.pjSrc);
  456. DbgPrint(" lDeltaSrc = 0x%lx, SrcOrg = (0,0)\n",bltInfo.lDeltaSrc);
  457. }
  458. #endif
  459. }
  460. }
  461. //
  462. // set DeltaSrcDir based on yDir
  463. //
  464. if (bltInfo.yDir == 1)
  465. {
  466. bltInfo.lDeltaSrcDir = bltInfo.lDeltaSrc;
  467. } else {
  468. bltInfo.lDeltaSrcDir = -bltInfo.lDeltaSrc;
  469. }
  470. } else {
  471. //
  472. // no src to worry about
  473. //
  474. bltInfo.pjSrc = (PBYTE) NULL;
  475. }
  476. //
  477. // Set up the destination information in bltInfo based on +/- yDir
  478. //
  479. // pjDst points to the upper left corner of the dest bitmap
  480. //
  481. // lDeltaDst is the number of (bytes) from one scan line to the next
  482. //
  483. bltInfo.pjDst = (PBYTE) pdioDst->pvScan0();
  484. bltInfo.lDeltaDst = pdioDst->lDelta();
  485. if (bltInfo.yDir == 1)
  486. {
  487. bltInfo.lDeltaDstDir = bltInfo.lDeltaDst;
  488. } else {
  489. bltInfo.lDeltaDstDir = -bltInfo.lDeltaDst;
  490. }
  491. #if DBG_BLTLNK
  492. if (DbgBltLnk >= 2)
  493. {
  494. DbgPrint(" pjDst = %p, lDeltaDst = %li\n",bltInfo.pjDst,bltInfo.lDeltaDst);
  495. }
  496. #endif
  497. //
  498. // Set up the Mask
  499. //
  500. if (!bNeedMsk || (pdioMsk == (SURFACE*) NULL))
  501. {
  502. //
  503. // no mask to deal with
  504. //
  505. bltInfo.pdioMsk = (SURFACE*) NULL;
  506. bltInfo.pjMsk = (PBYTE) NULL;
  507. } else {
  508. ASSERTGDI(pdioMsk->iType() == STYPE_BITMAP, "ERROR: BltLnk: Mask is not STYPE_BITMAP\n");
  509. ASSERTGDI(pdioMsk->iFormat() == BMF_1BPP, "ERROR: BltLnk: Mask not 1Bpp\n");
  510. ASSERTGDI(pptlMsk->x >= 0, "Illegal mask offset x\n");
  511. ASSERTGDI(pptlMsk->y >= 0, "Illegal mask offset y\n");
  512. //
  513. // info for BltLnkRect
  514. //
  515. bltInfo.pdioMsk = pdioMsk;
  516. bltInfo.pjMsk = (PBYTE) pdioMsk->pvScan0();
  517. bltInfo.cxMsk = (pdioMsk->sizl()).cx;
  518. bltInfo.cyMsk = (pdioMsk->sizl()).cy;
  519. bltInfo.xMskOrg = pptlMsk->x;
  520. bltInfo.yMskOrg = pptlMsk->y;
  521. //
  522. // Normalize mask x
  523. //
  524. if (bltInfo.xMskOrg >= (LONG)bltInfo.cxMsk)
  525. {
  526. bltInfo.xMskOrg %= bltInfo.cxMsk;
  527. } else {
  528. if (bltInfo.xMskOrg < 0)
  529. {
  530. bltInfo.xMskOrg = (bltInfo.cxMsk - 1) -
  531. ((-bltInfo.xMskOrg - 1) % bltInfo.cxMsk);
  532. }
  533. }
  534. //
  535. // Normalize Mask y
  536. //
  537. if (bltInfo.yMskOrg >= (LONG)bltInfo.cyMsk)
  538. {
  539. bltInfo.yMskOrg %= bltInfo.cyMsk;
  540. } else {
  541. if (bltInfo.yMskOrg < 0)
  542. {
  543. bltInfo.yMskOrg = (bltInfo.cyMsk - 1) -
  544. ((-bltInfo.yMskOrg - 1) % bltInfo.cyMsk);
  545. }
  546. }
  547. //
  548. // Scan line offsets
  549. //
  550. bltInfo.lDeltaMsk = pdioMsk->lDelta();
  551. if (bltInfo.yDir == 1)
  552. {
  553. bltInfo.lDeltaMskDir = bltInfo.lDeltaMsk;
  554. } else {
  555. bltInfo.lDeltaMskDir = -bltInfo.lDeltaMsk;
  556. }
  557. #if DBG_BLTLNK
  558. if (DbgBltLnk >= 2)
  559. {
  560. DbgPrint(" pjMask = %p\n",bltInfo.pjMsk);
  561. DbgPrint(" cxMask = %li\n",bltInfo.cxMsk);
  562. DbgPrint(" cyMask = %li\n",bltInfo.cyMsk);
  563. DbgPrint(" xMskOrg = %li\n",bltInfo.xMskOrg);
  564. DbgPrint(" yMskOrg = %li\n",bltInfo.yMskOrg);
  565. DbgPrint(" yMskDelta = %li\n",bltInfo.lDeltaMsk);
  566. }
  567. #endif
  568. }
  569. //
  570. // Set up the pat and possibly the mask if a mask is included in pat
  571. //
  572. if (!bNeedPat)
  573. {
  574. //
  575. // no Pat in this Blt
  576. //
  577. bltInfo.pjPat = (PBYTE) NULL;
  578. } else {
  579. //
  580. // check for valid brush pointer
  581. //
  582. if (pdbrush == (BRUSHOBJ *) NULL) {
  583. RIP("ERROR BltLnk brush Null");
  584. return(FALSE);
  585. }
  586. ircl = pdbrush->iSolidColor;
  587. //
  588. // check for solid color of 0xffffffff... this indicates
  589. // a real brush, not a solid color
  590. //
  591. if (ircl == 0xFFFFFFFF)
  592. {
  593. if (pBrush != (PENGBRUSH) NULL)
  594. {
  595. bltInfo.iSolidColor = ircl;
  596. //
  597. // Could have a brush that just has mask information.
  598. //
  599. if (pBrush->pjPat != (PBYTE) NULL)
  600. {
  601. //
  602. // fill in Pat info for BltLnkrect
  603. //
  604. bltInfo.lDeltaPat = pBrush->lDeltaPat;
  605. bltInfo.pjPat = pBrush->pjPat;
  606. bltInfo.cxPat = pBrush->cxPat;
  607. bltInfo.cyPat = pBrush->cyPat;
  608. bltInfo.xPatOrg = pptlBrush->x;
  609. bltInfo.yPatOrg = pptlBrush->y;
  610. if (bltInfo.yDir == 1)
  611. {
  612. bltInfo.lDeltaPatDir = bltInfo.lDeltaPat;
  613. } else {
  614. bltInfo.lDeltaPatDir = -bltInfo.lDeltaPat;
  615. }
  616. }
  617. } else {
  618. //
  619. // routine failed due to brush, return
  620. //
  621. return(FALSE);
  622. }
  623. } else {
  624. //
  625. // Set pjPat to Null.
  626. //
  627. bltInfo.pjPat = (PBYTE) NULL;
  628. //
  629. // Build iSolidColor into a 32 bit quantity
  630. //
  631. // Note cascaded fall through on switch to build up iColor.
  632. //
  633. switch(pdioDst->iFormat())
  634. {
  635. case BMF_1BPP:
  636. if (ircl) {
  637. ircl = 0xFFFFFFFF;
  638. }
  639. break;
  640. case BMF_4BPP:
  641. ircl = ircl | (ircl << 4);
  642. case BMF_8BPP:
  643. ircl = ircl | (ircl << 8);
  644. case BMF_16BPP:
  645. ircl = ircl | (ircl << 16);
  646. }
  647. bltInfo.iSolidColor = ircl;
  648. }
  649. }
  650. //
  651. // Check if there is a mask with this brush. The Mask passed
  652. // in with the call takes precedence over the brush mask.
  653. //
  654. if ((bNeedMsk) &&
  655. (bltInfo.pjMsk == (PBYTE) NULL) &&
  656. (pBrush != (PENGBRUSH) NULL) &&
  657. (pBrush->pjMsk != (PBYTE) NULL))
  658. {
  659. bltInfo.pjMsk = pBrush->pjMsk;
  660. bltInfo.cxMsk = pBrush->cxMsk;
  661. bltInfo.cyMsk = pBrush->cyMsk;
  662. bltInfo.lDeltaMsk = pBrush->lDeltaMsk;
  663. bltInfo.xMskOrg = prclDst->left - pptlBrush->x;
  664. bltInfo.yMskOrg = prclDst->top - pptlBrush->y;
  665. //
  666. // Normalize Mask x
  667. //
  668. if (bltInfo.xMskOrg >= (LONG)bltInfo.cxMsk)
  669. {
  670. bltInfo.xMskOrg %= bltInfo.cxMsk;
  671. } else {
  672. if (bltInfo.xMskOrg < 0)
  673. {
  674. bltInfo.xMskOrg = (bltInfo.cxMsk-1) -
  675. ((-bltInfo.xMskOrg-1) % bltInfo.cxMsk);
  676. }
  677. }
  678. //
  679. // Normalize Mask y
  680. //
  681. if (bltInfo.yMskOrg >= (LONG)bltInfo.cyMsk)
  682. {
  683. bltInfo.yMskOrg %= bltInfo.cyMsk;
  684. } else {
  685. if (bltInfo.yMskOrg < 0)
  686. {
  687. bltInfo.yMskOrg = (bltInfo.cyMsk-1) -
  688. ((-bltInfo.yMskOrg-1) % bltInfo.cyMsk);
  689. }
  690. }
  691. //
  692. // set sign on lDeltaMask based on a bottom to top or
  693. // top to bottom blt
  694. //
  695. if (bltInfo.yDir == 1)
  696. {
  697. bltInfo.lDeltaMskDir = bltInfo.lDeltaMsk;
  698. } else {
  699. bltInfo.lDeltaMskDir = -bltInfo.lDeltaMsk;
  700. }
  701. }
  702. //
  703. // make sure that if a mask is specified by the rop ,then a mask is available
  704. //
  705. if (bNeedMsk && (bltInfo.pjMsk == (PBYTE)NULL)) {
  706. RIP("ERROR: Bltlnk: ROP specifies mask but mask is null");
  707. return(FALSE);
  708. }
  709. //
  710. // set up clipping boundaries and call blt routine for each rect
  711. //
  712. if (pco != (CLIPOBJ *) NULL)
  713. {
  714. switch(pco->iDComplexity)
  715. {
  716. case DC_TRIVIAL:
  717. //
  718. // use the target for clipping
  719. //
  720. bMore = FALSE;
  721. clenr.c = 1;
  722. clenr.arcl[0] = *prclDst;
  723. break;
  724. case DC_RECT:
  725. //
  726. // use the bounding rect for clipping
  727. //
  728. bMore = FALSE;
  729. clenr.c = 1;
  730. clenr.arcl[0] = pco->rclBounds;
  731. break;
  732. case DC_COMPLEX:
  733. //
  734. // set up clipping enumeration
  735. //
  736. bMore = TRUE;
  737. ((ECLIPOBJ *) pco)->cEnumStart(FALSE,CT_RECTANGLES,bltInfo.iDir,CLIPOBJ_ENUM_LIMIT);
  738. break;
  739. default:
  740. RIP("ERROR: BltLnk - bad clipping type");
  741. return (FALSE);
  742. }
  743. } else {
  744. //
  745. // use target for clipping
  746. //
  747. bMore = FALSE;
  748. clenr.c = 1;
  749. clenr.arcl[0] = *prclDst;
  750. }
  751. //
  752. // blt each rect
  753. //
  754. do
  755. {
  756. if (bMore)
  757. {
  758. bMore = ((ECLIPOBJ *) pco)->bEnum(sizeof(clenr), (PVOID) &clenr);
  759. }
  760. for (ircl = 0; ircl < clenr.c; ircl++)
  761. {
  762. PRECTL prcl = &clenr.arcl[ircl];
  763. if (prcl->left < prclDst->left) {
  764. prcl->left = prclDst->left;
  765. }
  766. if (prcl->right > prclDst->right){
  767. prcl->right = prclDst->right;
  768. }
  769. if (prcl->top < prclDst->top) {
  770. prcl->top = prclDst->top;
  771. }
  772. if (prcl->bottom > prclDst->bottom){
  773. prcl->bottom = prclDst->bottom;
  774. }
  775. //
  776. // We check for NULL or inverted rectanges because we may get them.
  777. //
  778. if (prcl->top < prcl->bottom)
  779. {
  780. ASSERTGDI(prcl->top >= 0, "ERROR prcl->top >= 0");
  781. ASSERTGDI(prcl->left >= 0, "ERROR prcl->left >= 0");
  782. //
  783. // call BltLnkRect once for each vertical stripe that has width <=
  784. // to the size of the temporary scan line storage
  785. //
  786. // ulong count = (prcl->right - prcl->left)/(pixels per ulong) + 1;
  787. //
  788. while ((prcl->right - prcl->left) > 0)
  789. {
  790. RECTL TempRect;
  791. TempRect.left = prcl->right;
  792. TempRect.right = prcl->right;
  793. if (!bLocalAlloc) {
  794. if ((prcl->right - prcl->left) > MaxWidth)
  795. {
  796. prcl->right = prcl->left + MaxWidth;
  797. TempRect.left = prcl->right;
  798. }
  799. }
  800. //
  801. // if there is a mask, 2 passes will be required, one with negative
  802. // mask using the Rop3Low and then once with a positive mask flag
  803. // using Rop3High
  804. //
  805. if (Rop3Low != 0xAA)
  806. {
  807. bltInfo.rop3 = Rop3Low;
  808. bltInfo.RopSrc = RopSrcLow;
  809. bltInfo.RopDst = RopDstLow;
  810. bltInfo.bNeedSrc = bNeedSrcLow;
  811. bltInfo.bNeedDst = bNeedDstLow;
  812. bltInfo.bNeedPat = bNeedPatLow;
  813. bltInfo.bNeedMsk = bNeedMsk;
  814. bltInfo.NegateMsk = 0x00;
  815. BltLnkRect(&bltInfo,prcl);
  816. }
  817. if (bNeedMsk &&(Rop3High != 0xAA) )
  818. {
  819. //
  820. // perform second call to write the high mask ROP pixels
  821. //
  822. bltInfo.rop3 = Rop3High;
  823. bltInfo.RopSrc = RopSrcHigh;
  824. bltInfo.RopDst = RopDstHigh;
  825. bltInfo.bNeedSrc = bNeedSrcHigh;
  826. bltInfo.bNeedDst = bNeedDstHigh;
  827. bltInfo.bNeedPat = bNeedPatHigh;
  828. bltInfo.bNeedMsk = bNeedMsk;
  829. bltInfo.NegateMsk = 0xFF;
  830. BltLnkRect(&bltInfo,prcl);
  831. }
  832. prcl->left = TempRect.left;
  833. prcl->right = TempRect.right;
  834. }
  835. }
  836. }
  837. } while (bMore);
  838. return(TRUE);
  839. }
  840. /******************************Public*Routine******************************\
  841. *
  842. * Routine Name:
  843. *
  844. * BltLnkRect
  845. *
  846. * Routine Description:
  847. *
  848. * Perform rectangular BitBlt using rop3 passed from BltLnk. The rops are
  849. * performed using temporary scan line buffers so that the logical
  850. * operations are done 1 DWORD at a time. The Src data is copied to the
  851. * temporary buffer using SrcBlt so the the bitmap format and color
  852. * translation is done to match Src to Dst. Also Src alignment in matched
  853. * to Dst alignment in SrcBlt. The result of the logical combination is
  854. * copied to the destination using the appropriate SrcBlt routine.
  855. *
  856. * Arguments:
  857. *
  858. * pBlt - BLT specific information
  859. * prcl - clipping rectangle
  860. *
  861. * Return Value:
  862. *
  863. * None
  864. *
  865. \**************************************************************************/
  866. VOID
  867. BltLnkRect(
  868. PBLTLNKINFO pBlt,
  869. PRECTL prcl
  870. )
  871. {
  872. LONG cy;
  873. LONG DwordCount;
  874. ULONG ByteOffset;
  875. ULONG PixelOffset;
  876. ULONG PixelCount;
  877. ULONG rop2;
  878. BLTINFO SrcCopyBltInfo;
  879. BLTINFO DstCopyBltInfo;
  880. PFN_SRCCPY pfnSrcCopy;
  881. PFN_SRCCPY pfnDstCopy;
  882. PFN_BLTLNKROP pfnRop1,pfnRop2;
  883. PFN_READPAT pfnReadPat;
  884. PFN_SRCCOPYMASK pfnCopyMask;
  885. ULONG SrcBuffer[SCAN_LINE_BUFFER_LENGTH];
  886. ULONG DstBuffer[SCAN_LINE_BUFFER_LENGTH];
  887. ULONG RopBuffer0[SCAN_LINE_BUFFER_LENGTH];
  888. ULONG RopBuffer1[SCAN_LINE_BUFFER_LENGTH];
  889. PBYTE pjSrc = (PBYTE)NULL;
  890. PBYTE pjDst = (PBYTE)NULL;
  891. PBYTE pjPat = (PBYTE)NULL;
  892. ULONG cxPat;
  893. ULONG ixPat;
  894. LONG cyPat;
  895. LONG iyPat;
  896. ULONG ixMsk;
  897. LONG iyMsk;
  898. ULONG iSolidColor;
  899. ULONG ulDstStart;
  900. ULONG Index;
  901. ULONG ulIndex;
  902. ULONG BytesPerPixel = 0;
  903. ULONG ByteOffset24Bpp = 0;
  904. BLTLNK_MASKINFO bmskMaskInfo;
  905. #if DBG_BLTLNK
  906. if (DbgBltLnk >= 1)
  907. {
  908. DbgPrint("BltLnkRect:\n");
  909. DbgPrint(" prcl = %li,%li to %li,%li\n",
  910. prcl->left,prcl->top,prcl->right,prcl->bottom);
  911. DbgPrint(" yDir = %li, xDir = %li\n",
  912. pBlt->yDir,pBlt->xDir);
  913. DbgPrint(" pjSrc = 0x%lx, pjDst = 0x%lx\n",pBlt->pjSrc,pBlt->pjDst);
  914. }
  915. if (DbgBltLnk >= 2)
  916. {
  917. DbgPrint(" Address of SrcBuffer = 0x%p\n",&SrcBuffer[0]);
  918. DbgPrint(" Address of DstBuffer = 0x%p\n",&DstBuffer[0]);
  919. DbgPrint(" Address of RopBuffer0 = 0x%p\n",&RopBuffer0[0]);
  920. DbgPrint(" Address of RopBuffer1 = 0x%p\n",&RopBuffer1[0]);
  921. }
  922. #endif
  923. //
  924. // Calculate all temporary parameters needed to perform the BitBlt
  925. // based on source and destination bitmap formats (which may be different)
  926. //
  927. // cy = number of scan lines to Blt
  928. //
  929. cy = prcl->bottom - prcl->top;
  930. PixelCount = prcl->right - prcl->left;
  931. #if DBG_BLTLNK
  932. if (DbgBltLnk >= 2)
  933. {
  934. DbgPrint(" cy = %li\n",cy);
  935. }
  936. #endif
  937. //
  938. // calculate parameters for:
  939. //
  940. // 1) SrcBlt routine to load source into DWORD buffer
  941. // transformed to Dst alignment, format and color
  942. // 2) ROP2 routine to operate on DWORDS
  943. // 3) SrcBlt routine to store DWORD buffer to pjDst
  944. //
  945. switch(pBlt->pdioDst->iFormat())
  946. {
  947. case BMF_1BPP:
  948. ulDstStart = prcl->left >> 5;
  949. ByteOffset = (prcl->left >> 3) & 0x03;
  950. PixelOffset = prcl->left & 0x1f;
  951. DwordCount = (PixelOffset + PixelCount + 31) >> 5;
  952. break;
  953. case BMF_4BPP:
  954. ulDstStart = prcl->left >> 3;
  955. ByteOffset = (prcl->left >> 1) & 0x03;
  956. PixelOffset = prcl->left & 0x07;
  957. DwordCount = (PixelOffset + PixelCount + 7) >> 3;
  958. break;
  959. case BMF_8BPP:
  960. ulDstStart = prcl->left >> 2;
  961. ByteOffset = prcl->left & 0x03;
  962. PixelOffset = prcl->left & 0x03;
  963. DwordCount = (PixelOffset + PixelCount + 3) >> 2;
  964. BytesPerPixel = 1;
  965. break;
  966. case BMF_16BPP:
  967. ulDstStart = prcl->left >> 1;
  968. ByteOffset = (prcl->left & 0x01) << 1;
  969. PixelOffset = prcl->left & 0x01;
  970. DwordCount = (PixelOffset + PixelCount + 1) >> 1;
  971. BytesPerPixel = 2;
  972. break;
  973. case BMF_24BPP:
  974. ulDstStart = (prcl->left * 3) >> 2;
  975. ByteOffset = (prcl->left * 3) & 0x03;
  976. PixelOffset = 0;
  977. ByteOffset24Bpp = ByteOffset;
  978. BytesPerPixel = 3;
  979. DwordCount = (ByteOffset + 3 * PixelCount + 3) >> 2;
  980. break;
  981. case BMF_32BPP:
  982. ulDstStart = prcl->left;
  983. DwordCount = PixelCount;
  984. ByteOffset = 0;
  985. PixelOffset = 0;
  986. BytesPerPixel = 4;
  987. break;
  988. }
  989. #if DBG_BLTLNK
  990. if (DbgBltLnk >= 2)
  991. {
  992. DbgPrint(" ulDstStart = %li\n",ulDstStart);
  993. DbgPrint(" DwordCount = %li\n",DwordCount);
  994. DbgPrint(" ByteOffset = 0x%lx\n",ByteOffset);
  995. DbgPrint(" PixelOffset = 0x%lx\n",PixelOffset);
  996. }
  997. #endif
  998. //
  999. // if there is a pat that isn't a solid color then
  1000. // set up params based on prcl
  1001. //
  1002. if (pBlt->pjPat != (PBYTE) NULL)
  1003. {
  1004. //
  1005. // Set up format-specific pattern parameters for the call to
  1006. // ReadPat. Note: there is only one call for reading
  1007. // 8,16,24 and 32 Bpp patterns so cxPat, the pixel count is
  1008. // adjusted to become a byte count for these cases. ixPat is
  1009. // also adjusted to be a byte offset in these cases.
  1010. //
  1011. switch(pBlt->pdioDst->iFormat())
  1012. {
  1013. case BMF_1BPP:
  1014. cxPat = pBlt->cxPat;
  1015. ixPat = prcl->left - pBlt->xPatOrg;
  1016. pfnReadPat = BltLnkReadPat1;
  1017. break;
  1018. case BMF_4BPP:
  1019. cxPat = pBlt->cxPat;
  1020. ixPat = prcl->left - pBlt->xPatOrg;
  1021. pfnReadPat = BltLnkReadPat4;
  1022. break;
  1023. case BMF_8BPP:
  1024. cxPat = pBlt->cxPat;
  1025. ixPat = prcl->left - pBlt->xPatOrg;
  1026. pfnReadPat = BltLnkReadPat;
  1027. break;
  1028. case BMF_16BPP:
  1029. cxPat = pBlt->cxPat << 1;
  1030. ixPat = ((prcl->left - pBlt->xPatOrg) << 1);
  1031. pfnReadPat = BltLnkReadPat;
  1032. break;
  1033. case BMF_24BPP:
  1034. cxPat = pBlt->cxPat * 3;
  1035. ixPat = ((prcl->left - pBlt->xPatOrg) * 3);
  1036. pfnReadPat = BltLnkReadPat;
  1037. break;
  1038. case BMF_32BPP:
  1039. cxPat = pBlt->cxPat << 2;
  1040. ixPat = ((prcl->left - pBlt->xPatOrg) << 2);
  1041. pfnReadPat = BltLnkReadPat;
  1042. break;
  1043. }
  1044. //
  1045. // Normalize Pattern:
  1046. //
  1047. // make sure starting ixPat is within pattern limits
  1048. // and set up iyPat and cyPat
  1049. //
  1050. if (ixPat >= cxPat)
  1051. {
  1052. ixPat %= cxPat;
  1053. }// else if (ixPat < 0) {
  1054. // ixPat = (cxPat - 1) - ((-(LONG)ixPat - 1) % cxPat);
  1055. // }
  1056. cyPat = pBlt->cyPat;
  1057. iyPat = prcl->top - pBlt->yPatOrg;
  1058. if (pBlt->yDir < 0)
  1059. {
  1060. iyPat = iyPat + (cy - 1);
  1061. }
  1062. if (iyPat >= cyPat)
  1063. {
  1064. iyPat %= cyPat;
  1065. } else if (iyPat < 0) {
  1066. iyPat = (cyPat - 1) - ((-(LONG)iyPat - 1) % cyPat);
  1067. }
  1068. pjPat = pBlt->pjPat + (iyPat * pBlt->lDeltaPat);
  1069. #if DBG_BLTLNK
  1070. if (DbgBltLnk >= 2)
  1071. {
  1072. DbgPrint(" cxPat = 0x%lx cyPat = 0x%lx\n",cxPat,cyPat);
  1073. DbgPrint(" ixPat = 0x%lx iyPat = 0x%lx\n",ixPat,iyPat);
  1074. DbgPrint(" pjPat = 0x%p\n",pjPat);
  1075. DbgPrint(" lDeltaPat = 0x%lx\n",pBlt->lDeltaPat);
  1076. }
  1077. #endif
  1078. } else {
  1079. //
  1080. // solid color for pat
  1081. //
  1082. iSolidColor = pBlt->iSolidColor;
  1083. #if DBG_BLTLNK
  1084. if (DbgBltLnk >= 2)
  1085. {
  1086. DbgPrint(" iSolidColor = 0x%lx\n",iSolidColor);
  1087. }
  1088. #endif
  1089. }
  1090. //
  1091. // pjDst pointer to the beginning of the Dst scan line
  1092. //
  1093. // ulDstStart is added to (PULONG)pjDst to get the
  1094. // address of the first ULONG containing pixels needed in
  1095. // the blt
  1096. //
  1097. if (pBlt->yDir > 0)
  1098. {
  1099. pjDst = pBlt->pjDst + prcl->top * pBlt->lDeltaDst;
  1100. } else {
  1101. pjDst = pBlt->pjDst + (prcl->bottom - 1) * pBlt->lDeltaDst;
  1102. }
  1103. #if DBG_BLTLNK
  1104. if (DbgBltLnk >= 2)
  1105. {
  1106. DbgPrint(" ulDstStart = 0x%lx\n",ulDstStart);
  1107. DbgPrint(" starting pjDst = 0x%p\n",pjDst);
  1108. DbgPrint(" Byte Offset = 0x%lx\n",ByteOffset);
  1109. }
  1110. #endif
  1111. //
  1112. // calculate Src parameters if the Src is needed. Src paramters are
  1113. // used to load the entire Src into the temp buffer, aligned to
  1114. // Dst and converted to Dst format, one scan line at a time
  1115. //
  1116. if (pBlt->pjSrc != (PBYTE) NULL)
  1117. {
  1118. //
  1119. // set up color translate routines
  1120. //
  1121. SrcCopyBltInfo.pxlo = pBlt->pxlo;
  1122. //
  1123. // ySrc is the offset in scan lines from the start of the src bitmap
  1124. //
  1125. // xSrctart is the pixel offset from the strart of the scan line
  1126. // to the first pixel neded
  1127. //
  1128. // xSrcEnd is 1 pixel beyond the last one needed for the scan line
  1129. //
  1130. pBlt->ySrc = pBlt->ySrcOrg + prcl->top - pBlt->rclDst.top;
  1131. pBlt->xSrcStart = pBlt->xSrcOrg + prcl->left - pBlt->rclDst.left;
  1132. pBlt->xSrcEnd = pBlt->xSrcStart + (PixelCount);
  1133. //
  1134. // initialize pjSrc to point to the start of each scan line to be
  1135. // copied
  1136. //
  1137. pjSrc = pBlt->pjSrc;
  1138. if (pBlt->yDir > 0)
  1139. {
  1140. pjSrc = pjSrc + (pBlt->ySrc * pBlt->lDeltaSrc);
  1141. } else {
  1142. pjSrc = pjSrc + (pBlt->ySrc + cy - 1) * pBlt->lDeltaSrc;
  1143. }
  1144. #if DBG_BLTLNK
  1145. if (DbgBltLnk >= 2)
  1146. {
  1147. DbgPrint(" starting pjSrc = %p\n",pjSrc);
  1148. DbgPrint(" ySrc = %li\n",pBlt->ySrc);
  1149. DbgPrint(" xSrcStart = %li\n",pBlt->xSrcStart);
  1150. DbgPrint(" ySrcEnd = %li\n",pBlt->xSrcEnd);
  1151. }
  1152. #endif
  1153. }
  1154. //
  1155. // set up mask params
  1156. //
  1157. if (pBlt->bNeedMsk)
  1158. {
  1159. bmskMaskInfo.cxMsk = pBlt->cxMsk;
  1160. ixMsk = pBlt->xMskOrg + prcl->left - pBlt->rclDst.left;
  1161. iyMsk = pBlt->yMskOrg + prcl->top - pBlt->rclDst.top;
  1162. //
  1163. // # of pixels offsets to first pixel for src from start of scan
  1164. //
  1165. if (pBlt->yDir < 0)
  1166. {
  1167. iyMsk += (cy - 1);
  1168. }
  1169. //
  1170. // Normalize Msk again since prcl->left-pBlt->rclDst.left has
  1171. // been added.
  1172. //
  1173. // ixMsk should not be < 0 because MskOrg has already
  1174. // been normalized.
  1175. //
  1176. ASSERTGDI(iyMsk >= 0, " ERROR, negative iyMsk that has already been normalized");
  1177. if (ixMsk >= pBlt->cxMsk)
  1178. {
  1179. ixMsk = ixMsk % pBlt->cxMsk;
  1180. }
  1181. if (iyMsk >= pBlt->cyMsk)
  1182. {
  1183. iyMsk = iyMsk % pBlt->cyMsk;
  1184. }
  1185. //
  1186. // info for SrcCopyMsk routines
  1187. //
  1188. bmskMaskInfo.pjMskBase = pBlt->pjMsk;
  1189. bmskMaskInfo.pjMsk = pBlt->pjMsk + (iyMsk * pBlt->lDeltaMsk);
  1190. bmskMaskInfo.ixMsk = ixMsk;
  1191. bmskMaskInfo.cxMsk = pBlt->cxMsk;
  1192. bmskMaskInfo.iyMsk = iyMsk;
  1193. bmskMaskInfo.cyMsk = pBlt->cyMsk;
  1194. bmskMaskInfo.NegateMsk = pBlt->NegateMsk;
  1195. bmskMaskInfo.lDeltaMskDir = pBlt->lDeltaMskDir;
  1196. //
  1197. // select mask store routine
  1198. //
  1199. switch(pBlt->pdioDst->iFormat())
  1200. {
  1201. case BMF_1BPP:
  1202. pfnCopyMask = BltLnkSrcCopyMsk1;
  1203. break;
  1204. case BMF_4BPP:
  1205. pfnCopyMask = BltLnkSrcCopyMsk4;
  1206. break;
  1207. case BMF_8BPP:
  1208. pfnCopyMask = BltLnkSrcCopyMsk8;
  1209. break;
  1210. case BMF_16BPP:
  1211. pfnCopyMask = BltLnkSrcCopyMsk16;
  1212. break;
  1213. case BMF_24BPP:
  1214. pfnCopyMask = BltLnkSrcCopyMsk24;
  1215. break;
  1216. case BMF_32BPP:
  1217. pfnCopyMask = BltLnkSrcCopyMsk32;
  1218. break;
  1219. }
  1220. }
  1221. ////////////////////////////////////////////////////////////////
  1222. // //
  1223. // Place Accelerators Here for special cases that can not //
  1224. // go through the normal load/combine/store procedure. Only //
  1225. // positive x and y blts are accelerated (left to right), //
  1226. // top to bottom. //
  1227. // //
  1228. ////////////////////////////////////////////////////////////////
  1229. if ((pBlt->xDir > 0) && (pBlt->yDir > 0)) {
  1230. //
  1231. // Mask Blt
  1232. //
  1233. if ((pBlt->rop3 == 0xCC) &&
  1234. pBlt->bNeedMsk &&
  1235. (pBlt->pdioSrc->iFormat() == pBlt->pdioDst->iFormat()) &&
  1236. (pBlt->pxlo->bIsIdentity()))
  1237. {
  1238. //
  1239. // customize DstCopyBltInfo for MaskBlt 0xAACC or 0xCCAA will
  1240. // reach this point with a rop3 of CC. Color translations use the
  1241. // normal path.
  1242. //
  1243. DstCopyBltInfo.pjDst = pjDst;
  1244. DstCopyBltInfo.pjSrc = pjSrc;
  1245. DstCopyBltInfo.xDir = 1;
  1246. DstCopyBltInfo.yDir = pBlt->yDir;
  1247. DstCopyBltInfo.cx = PixelCount;
  1248. DstCopyBltInfo.cy = cy;
  1249. DstCopyBltInfo.lDeltaSrc = pBlt->lDeltaSrcDir;
  1250. DstCopyBltInfo.lDeltaDst = pBlt->lDeltaDstDir;
  1251. DstCopyBltInfo.xSrcStart = pBlt->xSrcStart;
  1252. DstCopyBltInfo.xSrcEnd = pBlt->xSrcStart + PixelCount;
  1253. DstCopyBltInfo.xDstStart = prcl->left;
  1254. DstCopyBltInfo.yDstStart = 0;
  1255. DstCopyBltInfo.pxlo = &xloIdent;
  1256. (*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],&DstBuffer[0]);
  1257. return;
  1258. }
  1259. //
  1260. // ROP B8B8, src = 1bpp, translate to 00,ff. this is a src of 1bpp used as a mask
  1261. // to blt a solid color to dst as Dst = (Src & Dst) | (~Src & Pat)
  1262. //
  1263. // Also accelerate ROP E2E2 which is the opposite of B8B8 ie:
  1264. //
  1265. // Dst = (~Src & Dst) | (Src & Pat)
  1266. //
  1267. if ( ((pBlt->rop3 == 0xB8) || (pBlt->rop3 == 0xE2)) &&
  1268. (!pBlt->bNeedMsk) &&
  1269. (pBlt->iSolidColor != 0xffffffff) &&
  1270. (pBlt->pdioSrc->iFormat() == BMF_1BPP) &&
  1271. ((pBlt->pdioDst->iFormat() >= BMF_8BPP) &&
  1272. (pBlt->pdioDst->iFormat() <= BMF_32BPP)) )
  1273. {
  1274. PFN_PATMASKCOPY pfnCopy;
  1275. ULONG colormask;
  1276. switch (pBlt->pdioDst->iFormat())
  1277. {
  1278. //
  1279. // BltLnkPatMaskCopy4 (and probably BltLnkPatMaskCopy1) are
  1280. // broken, so don't use them for now.
  1281. //
  1282. case BMF_8BPP:
  1283. pfnCopy = BltLnkPatMaskCopy8;
  1284. colormask = 0x0000ff;
  1285. break;
  1286. case BMF_16BPP:
  1287. pfnCopy = BltLnkPatMaskCopy16;
  1288. colormask = 0x00ffff;
  1289. break;
  1290. case BMF_24BPP:
  1291. pfnCopy = BltLnkPatMaskCopy24;
  1292. colormask = 0xffffff;
  1293. break;
  1294. case BMF_32BPP:
  1295. pfnCopy = BltLnkPatMaskCopy32;
  1296. colormask = 0xffffff;
  1297. break;
  1298. default:
  1299. RIP("Unexpected case.");
  1300. }
  1301. PULONG pulTranslate = pBlt->pxlo->pulXlate;
  1302. if ( ((pulTranslate[1] & colormask) == colormask) &&
  1303. ((pulTranslate[0] & colormask) == 0))
  1304. {
  1305. BYTE Invert = 0x00;
  1306. if (pBlt->rop3 == 0xE2) {
  1307. Invert = 0xFF;
  1308. }
  1309. //
  1310. // set up blt info
  1311. //
  1312. DstCopyBltInfo.pjDst = pjDst;
  1313. DstCopyBltInfo.pjSrc = pjSrc;
  1314. DstCopyBltInfo.xDir = 1;
  1315. DstCopyBltInfo.yDir = pBlt->yDir;
  1316. DstCopyBltInfo.cx = PixelCount;
  1317. DstCopyBltInfo.cy = cy;
  1318. DstCopyBltInfo.lDeltaSrc = pBlt->lDeltaSrcDir;
  1319. DstCopyBltInfo.lDeltaDst = pBlt->lDeltaDstDir;
  1320. DstCopyBltInfo.xSrcStart = pBlt->xSrcStart;
  1321. DstCopyBltInfo.xSrcEnd = pBlt->xSrcStart + PixelCount;
  1322. DstCopyBltInfo.xDstStart = prcl->left;
  1323. DstCopyBltInfo.yDstStart = 0;
  1324. DstCopyBltInfo.pxlo = pBlt->pxlo;
  1325. (*pfnCopy)(&DstCopyBltInfo,pBlt->iSolidColor,&SrcBuffer[0],Invert);
  1326. return;
  1327. }
  1328. }
  1329. //
  1330. // accelerators for VGA 256 special cases
  1331. //
  1332. if ((!pBlt->bNeedMsk) &&
  1333. (pBlt->bNeedSrc) &&
  1334. (pBlt->bNeedDst) &&
  1335. (pBlt->pdioDst->iFormat() == BMF_8BPP) &&
  1336. (pBlt->pdioSrc->iFormat() == BMF_8BPP) &&
  1337. (pBlt->pxlo->bIsIdentity())
  1338. )
  1339. {
  1340. //
  1341. // ROP 6666 DSx
  1342. //
  1343. if (pBlt->rop3 == 0x66)
  1344. {
  1345. BltLnkAccel6666(
  1346. pjSrc + pBlt->xSrcStart,
  1347. pjDst + prcl->left,
  1348. pBlt->lDeltaSrcDir,
  1349. pBlt->lDeltaDstDir,
  1350. PixelCount,
  1351. cy
  1352. );
  1353. return;
  1354. }
  1355. //
  1356. // ROP 8888 DSa
  1357. //
  1358. if (pBlt->rop3 == 0x88)
  1359. {
  1360. BltLnkAccel8888(
  1361. pjSrc + pBlt->xSrcStart,
  1362. pjDst + prcl->left,
  1363. pBlt->lDeltaSrcDir,
  1364. pBlt->lDeltaDstDir,
  1365. PixelCount,
  1366. cy
  1367. );
  1368. return;
  1369. }
  1370. //
  1371. // ROP EEEE DSo
  1372. //
  1373. if (pBlt->rop3 == 0xEE)
  1374. {
  1375. BltLnkAccelEEEE(
  1376. pjSrc + pBlt->xSrcStart,
  1377. pjDst + prcl->left,
  1378. pBlt->lDeltaSrcDir,
  1379. pBlt->lDeltaDstDir,
  1380. PixelCount,
  1381. cy
  1382. );
  1383. return;
  1384. }
  1385. }
  1386. //
  1387. // END OF ACCELERATORS
  1388. //
  1389. }
  1390. ////////////////////////////////////////////////////////////////
  1391. // //
  1392. // Non-accelerated cases //
  1393. // //
  1394. ////////////////////////////////////////////////////////////////
  1395. if (pBlt->bNeedSrc)
  1396. {
  1397. //
  1398. // fill out the SrcCopyBltInfo structure to be used by SrcBltxxx routine
  1399. // to read the src bitmap and copy it to dst format and alignment
  1400. //
  1401. SrcCopyBltInfo.pjDst = (PBYTE)(&SrcBuffer[0]) + ByteOffset24Bpp;
  1402. SrcCopyBltInfo.pjSrc = pjSrc;
  1403. SrcCopyBltInfo.xDir = 1;
  1404. SrcCopyBltInfo.yDir = pBlt->yDir;
  1405. SrcCopyBltInfo.cx = PixelCount;
  1406. SrcCopyBltInfo.cy = 1;
  1407. SrcCopyBltInfo.lDeltaSrc = 1;
  1408. SrcCopyBltInfo.lDeltaDst = 1;
  1409. SrcCopyBltInfo.xSrcStart = pBlt->xSrcStart;
  1410. SrcCopyBltInfo.xSrcEnd = pBlt->xSrcStart + SrcCopyBltInfo.cx;
  1411. SrcCopyBltInfo.xDstStart = PixelOffset;
  1412. SrcCopyBltInfo.yDstStart = 1;
  1413. SrcCopyBltInfo.pxlo = pBlt->pxlo;
  1414. //
  1415. // select SrcCopy routine based on bitmap formats and color translation
  1416. //
  1417. Index = (pBlt->pdioDst->iFormat() << 5) | (pBlt->pdioSrc->iFormat() << 2);
  1418. if (pBlt->pxlo->bIsIdentity())
  1419. {
  1420. Index += 1;
  1421. }
  1422. pfnSrcCopy = SrcCopyFunctionTable[Index];
  1423. }
  1424. //
  1425. // fill out the DstCopyBltInfo structure to be used by SrcBltxxx routine
  1426. // to copy the dst scan line to the actual destination
  1427. //
  1428. DstCopyBltInfo.pjDst = pjDst;
  1429. DstCopyBltInfo.pjSrc = (PBYTE)&DstBuffer[0] + ByteOffset24Bpp;
  1430. DstCopyBltInfo.xDir = 1;
  1431. DstCopyBltInfo.yDir = pBlt->yDir;
  1432. DstCopyBltInfo.cx = PixelCount;
  1433. DstCopyBltInfo.cy = 1;
  1434. DstCopyBltInfo.lDeltaSrc = 1;
  1435. DstCopyBltInfo.lDeltaDst = 1;
  1436. DstCopyBltInfo.xSrcStart = PixelOffset;
  1437. DstCopyBltInfo.xSrcEnd = PixelOffset + DstCopyBltInfo.cx;
  1438. DstCopyBltInfo.xDstStart = prcl->left;
  1439. DstCopyBltInfo.yDstStart = 0;
  1440. DstCopyBltInfo.pxlo = &xloIdent;
  1441. //
  1442. // select DstCopy routine based on bitmap formats and color translation,
  1443. // only need SrcCopy routine selection if not using mask
  1444. //
  1445. if (!pBlt->bNeedMsk)
  1446. {
  1447. Index = (pBlt->pdioDst->iFormat() << 5) | (pBlt->pdioDst->iFormat() << 2);
  1448. //
  1449. // color translation already done
  1450. //
  1451. Index += 1;
  1452. pfnDstCopy = SrcCopyFunctionTable[Index];
  1453. }
  1454. //
  1455. // define the ROP function, there are 4 possible ROP functions:
  1456. //
  1457. // if Pat is not need then it is a ROP 2 without Pat
  1458. //
  1459. // if Dst is not need then it is a ROP 2 without Dst
  1460. //
  1461. // if Src is not need then it is a ROP 2 without Src
  1462. //
  1463. // If src,dst and pat are needed to calculate the new dest then it is a
  1464. // full ROP3
  1465. //
  1466. //
  1467. if (!pBlt->bNeedPat)
  1468. {
  1469. rop2 = pBlt->rop3 & 0x0F;
  1470. #if DBG_BLTLNK
  1471. if (DbgBltLnk >= 2)
  1472. {
  1473. DbgPrint(" Select no pat rop, rop2 function = %li\n",rop2);
  1474. }
  1475. #endif
  1476. //
  1477. // ROP without Pat
  1478. //
  1479. pfnRop1 = RopFunctionTable[rop2];
  1480. //
  1481. // blt each scan line
  1482. //
  1483. Index = cy;
  1484. while (Index--)
  1485. {
  1486. if (pBlt->bNeedSrc)
  1487. {
  1488. //
  1489. // get src scan line if offset or
  1490. // color translation are needed
  1491. //
  1492. (*pfnSrcCopy)(&SrcCopyBltInfo);
  1493. //
  1494. // update pointer for next src line
  1495. //
  1496. SrcCopyBltInfo.pjSrc += pBlt->lDeltaSrcDir;
  1497. }
  1498. //
  1499. // ROP the buffers together
  1500. //
  1501. (*pfnRop1)(&DstBuffer[0],(PULONG)pjDst + ulDstStart,&SrcBuffer[0],DwordCount);
  1502. //
  1503. // copy the buffer to the dest
  1504. //
  1505. if (!pBlt->bNeedMsk)
  1506. {
  1507. (*pfnDstCopy)(&DstCopyBltInfo);
  1508. } else {
  1509. //
  1510. // call store routine with mask
  1511. //
  1512. (*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&RopBuffer0[0],NULL);
  1513. //
  1514. // increment to the next mask scan line,
  1515. // check for going off the edge. This must
  1516. // be done for pos and neg blts
  1517. //
  1518. // should be an inline function!
  1519. //
  1520. if (pBlt->yDir > 0) {
  1521. iyMsk++;
  1522. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  1523. if (iyMsk >= pBlt->cyMsk)
  1524. {
  1525. iyMsk = 0;
  1526. bmskMaskInfo.pjMsk = pBlt->pjMsk;
  1527. }
  1528. } else {
  1529. if (iyMsk == 0)
  1530. {
  1531. iyMsk = pBlt->cyMsk - 1;
  1532. bmskMaskInfo.pjMsk = pBlt->pjMsk +
  1533. (pBlt->lDeltaMsk * (pBlt->cyMsk - 1));
  1534. }
  1535. else
  1536. {
  1537. iyMsk--;
  1538. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  1539. }
  1540. }
  1541. }
  1542. //
  1543. // increment to the next scan line
  1544. //
  1545. pjDst += pBlt->lDeltaDstDir;
  1546. DstCopyBltInfo.pjDst = pjDst;
  1547. }
  1548. //
  1549. // ROP that doesn't require Dst
  1550. //
  1551. } else if (!pBlt->bNeedDst) {
  1552. rop2 = pBlt->RopDst & 0x0f;
  1553. pfnRop1 = RopFunctionTable[rop2];
  1554. #if DBG_BLTLNK
  1555. if (DbgBltLnk >= 2)
  1556. {
  1557. DbgPrint(" Select no dst rop, rop2 function = %lx\n",rop2);
  1558. }
  1559. #endif
  1560. //
  1561. // fill in solid color if there is no pjPat;
  1562. //
  1563. if (pjPat == (PBYTE) NULL)
  1564. {
  1565. if (pBlt->pdioDst->iFormat() != BMF_24BPP)
  1566. {
  1567. //
  1568. // fill in RopBuffer1 with the 32 bit solid color.
  1569. // Number of DWORDS = Number of BYTES/4
  1570. //
  1571. ulIndex = DwordCount;
  1572. while (ulIndex > 0)
  1573. {
  1574. RopBuffer1[--ulIndex] = iSolidColor;
  1575. }
  1576. } else {
  1577. PBYTE pjSolidPat = (PBYTE)(&RopBuffer1[0]) + ByteOffset24Bpp;
  1578. //
  1579. // read in 24bpp solid color
  1580. //
  1581. ulIndex = PixelCount;
  1582. while (ulIndex > 0)
  1583. {
  1584. *pjSolidPat = (BYTE)(iSolidColor & 0x0000FF);
  1585. *(pjSolidPat+1) = (BYTE)((iSolidColor >> 8) & 0x0000FF);
  1586. *(pjSolidPat+2) = (BYTE)((iSolidColor >> 16) & 0x0000FF);
  1587. pjSolidPat+=3;
  1588. ulIndex--;
  1589. }
  1590. }
  1591. }
  1592. //
  1593. // ROP without Dst
  1594. //
  1595. while (cy--)
  1596. {
  1597. if (pBlt->bNeedSrc)
  1598. {
  1599. //
  1600. // get src scan line
  1601. //
  1602. (*pfnSrcCopy)(&SrcCopyBltInfo);
  1603. //
  1604. // update pointer for next src line
  1605. //
  1606. SrcCopyBltInfo.pjSrc += pBlt->lDeltaSrcDir;
  1607. }
  1608. if (pjPat != (PBYTE) NULL)
  1609. {
  1610. if (pjPat != (PBYTE) NULL)
  1611. {
  1612. (*pfnReadPat)((PBYTE)&RopBuffer1[0]+ByteOffset,PixelOffset,pjPat,cxPat,ixPat,PixelCount,BytesPerPixel);
  1613. if (pBlt->yDir == 1) {
  1614. iyPat++;
  1615. pjPat += pBlt->lDeltaPatDir;
  1616. if (iyPat >= cyPat)
  1617. {
  1618. iyPat = 0;
  1619. pjPat = pBlt->pjPat;
  1620. }
  1621. } else {
  1622. if (iyPat == 0)
  1623. {
  1624. iyPat = cyPat - 1;
  1625. pjPat = pBlt->pjPat +
  1626. (pBlt->lDeltaPat * (cyPat - 1));
  1627. }
  1628. else
  1629. {
  1630. iyPat--;
  1631. pjPat -= pBlt->lDeltaPat;
  1632. }
  1633. }
  1634. }
  1635. }
  1636. //
  1637. // ROP the buffers together
  1638. //
  1639. (*pfnRop1)(&DstBuffer[0],&RopBuffer1[0],&SrcBuffer[0],DwordCount);
  1640. //
  1641. // copy the result to the screen
  1642. //
  1643. if (!pBlt->bNeedMsk)
  1644. {
  1645. (*pfnDstCopy)(&DstCopyBltInfo);
  1646. } else {
  1647. //
  1648. // call store routine with mask
  1649. //
  1650. (*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],NULL);
  1651. //
  1652. // increment to the next mask scan line,
  1653. // check for going off the edge. This must
  1654. // be done for pos and neg blts
  1655. //
  1656. // should be an inline function!
  1657. //
  1658. if (pBlt->yDir > 0) {
  1659. iyMsk++;
  1660. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  1661. if (iyMsk >= pBlt->cyMsk)
  1662. {
  1663. iyMsk = 0;
  1664. bmskMaskInfo.pjMsk = pBlt->pjMsk;
  1665. }
  1666. } else {
  1667. if (iyMsk == 0)
  1668. {
  1669. iyMsk = pBlt->cyMsk - 1;
  1670. bmskMaskInfo.pjMsk = pBlt->pjMsk +
  1671. (pBlt->lDeltaMsk * (pBlt->cyMsk - 1));
  1672. }
  1673. else
  1674. {
  1675. iyMsk--;
  1676. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  1677. }
  1678. }
  1679. }
  1680. //
  1681. // increment to the next scan line
  1682. //
  1683. pjDst += pBlt->lDeltaDstDir;
  1684. DstCopyBltInfo.pjDst = pjDst;
  1685. }
  1686. //
  1687. // ROP that doesn't require Src
  1688. //
  1689. } else if (!pBlt->bNeedSrc) {
  1690. //
  1691. // fill in solid color if there is no pjPat;
  1692. //
  1693. if (pjPat == (PBYTE) NULL)
  1694. {
  1695. if (pBlt->pdioDst->iFormat() != BMF_24BPP)
  1696. {
  1697. //
  1698. // Replicate solid pattern to buffer
  1699. // Number of DWORDS = Number of BYTES/4
  1700. //
  1701. ulIndex = DwordCount;
  1702. while (ulIndex > 0)
  1703. {
  1704. RopBuffer1[--ulIndex] = iSolidColor;
  1705. }
  1706. } else {
  1707. PBYTE pjSolidPat = (PBYTE)(&RopBuffer1[0]) + ByteOffset24Bpp;
  1708. ulIndex = PixelCount;
  1709. //
  1710. // read in 24bpp solid color
  1711. //
  1712. while (ulIndex > 0)
  1713. {
  1714. *pjSolidPat = (BYTE)(iSolidColor & 0x0000FF);
  1715. *(pjSolidPat+1) = (BYTE)((iSolidColor >> 8) & 0x0000FF);
  1716. *(pjSolidPat+2) = (BYTE)((iSolidColor >> 16) & 0x0000FF);
  1717. pjSolidPat+=3;
  1718. ulIndex--;
  1719. }
  1720. }
  1721. }
  1722. //
  1723. // Rop without SRC
  1724. //
  1725. rop2 = pBlt->RopSrc & 0x0f;
  1726. #if DBG_BLTLNK
  1727. if (DbgBltLnk >= 2)
  1728. {
  1729. DbgPrint(" Select no src rop, rop2 function = %lx\n",rop2);
  1730. }
  1731. #endif
  1732. pfnRop1 = RopFunctionTable[rop2];
  1733. //
  1734. // blt each scan line
  1735. //
  1736. Index = cy;
  1737. while (Index--)
  1738. {
  1739. //
  1740. // will need pat for sure
  1741. //
  1742. if (pBlt->bNeedPat)
  1743. {
  1744. if (pjPat != (PBYTE) NULL)
  1745. {
  1746. (*pfnReadPat)((PBYTE)&RopBuffer1[0]+ByteOffset,PixelOffset,pjPat,cxPat,ixPat,PixelCount,BytesPerPixel);
  1747. if (pBlt->yDir == 1) {
  1748. iyPat++;
  1749. pjPat += pBlt->lDeltaPatDir;
  1750. if (iyPat >= cyPat)
  1751. {
  1752. iyPat = 0;
  1753. pjPat = pBlt->pjPat;
  1754. }
  1755. } else {
  1756. if (iyPat == 0)
  1757. {
  1758. iyPat = cyPat - 1;
  1759. pjPat = pBlt->pjPat +
  1760. (pBlt->lDeltaPat * (cyPat - 1));
  1761. }
  1762. else
  1763. {
  1764. iyPat--;
  1765. pjPat -= pBlt->lDeltaPat;
  1766. }
  1767. }
  1768. }
  1769. }
  1770. //
  1771. // ROP the memory buffers together
  1772. //
  1773. (*pfnRop1)(&DstBuffer[0],(PULONG)pjDst + ulDstStart,&RopBuffer1[0],DwordCount);
  1774. //
  1775. // copy the result to the dest
  1776. //
  1777. if (!pBlt->bNeedMsk)
  1778. {
  1779. (*pfnDstCopy)(&DstCopyBltInfo);
  1780. } else {
  1781. //
  1782. // call store routine with mask
  1783. //
  1784. (*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],NULL);
  1785. //
  1786. // increment to the next mask scan line,
  1787. // check for going off the edge. This must
  1788. // be done for pos and neg blts
  1789. //
  1790. // should be an inline function!
  1791. //
  1792. if (pBlt->yDir > 0) {
  1793. iyMsk++;
  1794. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  1795. if (iyMsk >= pBlt->cyMsk)
  1796. {
  1797. iyMsk = 0;
  1798. bmskMaskInfo.pjMsk = pBlt->pjMsk;
  1799. }
  1800. } else {
  1801. if (iyMsk == 0)
  1802. {
  1803. iyMsk = pBlt->cyMsk - 1;
  1804. bmskMaskInfo.pjMsk = pBlt->pjMsk +
  1805. (pBlt->lDeltaMsk * (pBlt->cyMsk - 1));
  1806. }
  1807. else
  1808. {
  1809. iyMsk--;
  1810. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  1811. }
  1812. }
  1813. }
  1814. //
  1815. // increment to next dest
  1816. //
  1817. pjDst += pBlt->lDeltaDstDir;
  1818. DstCopyBltInfo.pjDst = pjDst;
  1819. }
  1820. //
  1821. // FULL rop3
  1822. //
  1823. } else {
  1824. PULONG pTmpDstBuffer;
  1825. PULONG pTmpRopBuffer0;
  1826. PULONG pTmpRopBuffer1;
  1827. PULONG pTmpSrcBuffer;
  1828. ULONG SrcColor;
  1829. //
  1830. // full ROP 3, perform in 2 passes through ROP 2, 1 for
  1831. // not Pat and one for Pat. This rop will need src,dst and pat
  1832. //
  1833. rop2 = pBlt->rop3;
  1834. #if DBG_BLTLNK
  1835. if (DbgBltLnk >= 2)
  1836. {
  1837. DbgPrint(" Select full rop, rop2 function = %lx\n",rop2 & 0x0f);
  1838. DbgPrint(" rop2 function = %lx\n",(rop2 & 0xf0) >> 4);
  1839. }
  1840. #endif
  1841. pfnRop1 = RopFunctionTable[ rop2 & 0x0f ];
  1842. pfnRop2 = RopFunctionTable[ ( rop2 & 0xf0 ) >> 4 ];
  1843. Index = cy;
  1844. while (Index--)
  1845. {
  1846. //
  1847. // get src scan line
  1848. //
  1849. (*pfnSrcCopy)(&SrcCopyBltInfo);
  1850. //
  1851. // update pointer for next src line
  1852. //
  1853. SrcCopyBltInfo.pjSrc += pBlt->lDeltaSrcDir;
  1854. //
  1855. // set dst buffer pointer to dst
  1856. //
  1857. pTmpDstBuffer = (PULONG)pjDst + ulDstStart;
  1858. //
  1859. // perform both rop passes
  1860. //
  1861. (*pfnRop1)(&RopBuffer0[0],pTmpDstBuffer,&SrcBuffer[0],DwordCount);
  1862. (*pfnRop2)(&RopBuffer1[0],pTmpDstBuffer,&SrcBuffer[0],DwordCount);
  1863. if (pjPat != (PBYTE) NULL)
  1864. {
  1865. //
  1866. // fill up a buffer with the pattern
  1867. //
  1868. (*pfnReadPat)((PBYTE)&SrcBuffer[0] + ByteOffset,PixelOffset,pjPat,cxPat,ixPat,PixelCount,BytesPerPixel);
  1869. if (pBlt->yDir == 1) {
  1870. iyPat++;
  1871. pjPat += pBlt->lDeltaPatDir;
  1872. if (iyPat >= cyPat)
  1873. {
  1874. iyPat = 0;
  1875. pjPat = pBlt->pjPat;
  1876. }
  1877. } else {
  1878. if (iyPat == 0)
  1879. {
  1880. iyPat = cyPat - 1;
  1881. pjPat = pBlt->pjPat +
  1882. (pBlt->lDeltaPat * (cyPat - 1));
  1883. }
  1884. else
  1885. {
  1886. iyPat--;
  1887. pjPat -= pBlt->lDeltaPat;
  1888. }
  1889. }
  1890. //
  1891. // combine ROPs based on pat
  1892. //
  1893. pTmpDstBuffer = &DstBuffer[0];
  1894. pTmpRopBuffer0 = &RopBuffer0[0];
  1895. pTmpRopBuffer1 = &RopBuffer1[0];
  1896. pTmpSrcBuffer = &SrcBuffer[0];
  1897. ulIndex = DwordCount;
  1898. while (ulIndex > 0)
  1899. {
  1900. SrcColor = *pTmpSrcBuffer;
  1901. *pTmpDstBuffer = (*pTmpRopBuffer1 & SrcColor |
  1902. *pTmpRopBuffer0 & ~SrcColor);
  1903. pTmpSrcBuffer++;
  1904. pTmpDstBuffer++;
  1905. pTmpRopBuffer0++;
  1906. pTmpRopBuffer1++;
  1907. ulIndex--;
  1908. }
  1909. } else {
  1910. //
  1911. // solid pattern
  1912. //
  1913. if (pBlt->pdioDst->iFormat() != BMF_24BPP)
  1914. {
  1915. pTmpDstBuffer = &DstBuffer[0];
  1916. pTmpRopBuffer0 = &RopBuffer0[0];
  1917. pTmpRopBuffer1 = &RopBuffer1[0];
  1918. ulIndex = DwordCount;
  1919. while (ulIndex > 0)
  1920. {
  1921. *pTmpDstBuffer = (*pTmpRopBuffer1 & iSolidColor |
  1922. *pTmpRopBuffer0 & ~iSolidColor);
  1923. pTmpDstBuffer++;
  1924. pTmpRopBuffer0++;
  1925. pTmpRopBuffer1++;
  1926. ulIndex--;
  1927. }
  1928. } else {
  1929. //
  1930. // fill up a buffer with 24bpp solid pat
  1931. //
  1932. PBYTE pjSolidPat = (PBYTE)(&SrcBuffer[0]) + ByteOffset24Bpp;
  1933. //
  1934. // read in 24bpp solid color
  1935. //
  1936. ulIndex = PixelCount;
  1937. while (ulIndex>0)
  1938. {
  1939. *pjSolidPat = (BYTE)(iSolidColor & 0x0000FF);
  1940. *(pjSolidPat+1) = (BYTE)((iSolidColor >> 8) & 0x0000FF);
  1941. *(pjSolidPat+2) = (BYTE)((iSolidColor >> 16) & 0x0000FF);
  1942. pjSolidPat+=3;
  1943. ulIndex--;
  1944. }
  1945. //
  1946. // combine ROPs based on pat
  1947. //
  1948. pTmpDstBuffer = &DstBuffer[0];
  1949. pTmpRopBuffer0 = &RopBuffer0[0];
  1950. pTmpRopBuffer1 = &RopBuffer1[0];
  1951. pTmpSrcBuffer = &SrcBuffer[0];
  1952. ulIndex = DwordCount;
  1953. while (ulIndex > 0)
  1954. {
  1955. SrcColor = *pTmpSrcBuffer;
  1956. *pTmpDstBuffer = (*pTmpRopBuffer1 & SrcColor |
  1957. *pTmpRopBuffer0 & ~SrcColor);
  1958. pTmpSrcBuffer++;
  1959. pTmpDstBuffer++;
  1960. pTmpRopBuffer0++;
  1961. pTmpRopBuffer1++;
  1962. ulIndex--;
  1963. }
  1964. }
  1965. }
  1966. //
  1967. // write out temp buffer to destination
  1968. //
  1969. if (!pBlt->bNeedMsk)
  1970. {
  1971. (*pfnDstCopy)(&DstCopyBltInfo);
  1972. } else {
  1973. //
  1974. // call store routine with mask
  1975. //
  1976. (*pfnCopyMask)(&DstCopyBltInfo,&bmskMaskInfo,&SrcBuffer[0],NULL);
  1977. //
  1978. // increment to the next mask scan line,
  1979. // check for going off the edge. This must
  1980. // be done for pos and neg blts
  1981. //
  1982. // should be an inline function!
  1983. //
  1984. if (pBlt->yDir > 0) {
  1985. iyMsk++;
  1986. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  1987. if (iyMsk >= pBlt->cyMsk)
  1988. {
  1989. iyMsk = 0;
  1990. bmskMaskInfo.pjMsk = pBlt->pjMsk;
  1991. }
  1992. } else {
  1993. if (iyMsk == 0)
  1994. {
  1995. iyMsk = pBlt->cyMsk - 1;
  1996. bmskMaskInfo.pjMsk = pBlt->pjMsk +
  1997. (pBlt->lDeltaMsk * (pBlt->cyMsk - 1));
  1998. }
  1999. else
  2000. {
  2001. iyMsk--;
  2002. bmskMaskInfo.pjMsk += pBlt->lDeltaMskDir;
  2003. }
  2004. }
  2005. }
  2006. //
  2007. // increment Dst to next scan line
  2008. //
  2009. pjDst += pBlt->lDeltaDstDir;
  2010. DstCopyBltInfo.pjDst = pjDst;
  2011. }
  2012. }
  2013. }