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.

3446 lines
87 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name:
  3. *
  4. * bltlnkfnc.cxx
  5. *
  6. * Abstract
  7. *
  8. * This module implements 2 operand ROP functions used by bltlnk
  9. * as well as the routines needed to:
  10. *
  11. * 1: Perform masked bitblt operations
  12. * 2: Perform color expansion
  13. * 3: Read and expand patterns
  14. *
  15. * Author:
  16. *
  17. * Mark Enstrom (marke) 9-27-93
  18. *
  19. * Copyright (c) 1993-1999 Microsoft Corporation
  20. *
  21. \**************************************************************************/
  22. #include "precomp.hxx"
  23. extern ULONG DbgBltLnk;
  24. ULONG DbgMask = 0;
  25. ULONG DbgPat = 0;
  26. BYTE StartMask[] = {0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00};
  27. BYTE EndMask[] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
  28. //
  29. //
  30. // the following routins are the 16 ROP 2 functions generated
  31. // by a combination of two variables:
  32. //
  33. // ROP Function
  34. // -----------------------------
  35. // 0 0
  36. // 1 ~(S | D)
  37. // 2 ~S & D
  38. // 3 ~S
  39. // 4 S & ~D
  40. // 5 ~D
  41. // 6 S ^ D
  42. // 7 ~S | ~D
  43. // 8 S & D
  44. // 9 ~(S ^ D)
  45. // A D
  46. // B ~S | D
  47. // C S
  48. // D S | ~D
  49. // E S | D
  50. // F 1
  51. //
  52. //
  53. // Each of these functions expects as input an array for S and and
  54. // Array for D and output is written to another array, Y
  55. //
  56. /******************************Public*Routine******************************\
  57. * Routine Name:
  58. *
  59. * vRop2Function 0 - F
  60. *
  61. * Routine Description:
  62. *
  63. * Perform Rop2 logical combination of cx DWORDS from pulSBuffer and
  64. * pulDBuffer into pulDstBuffer
  65. *
  66. * Arguments:
  67. *
  68. * pulDstBuffer - pointer to destination buffer
  69. * pulDBuffer - pointer to source for destination data
  70. * pulSBuffer - pointer to source for source data
  71. * cx - number of DWORDS to combine
  72. *
  73. * Return Value:
  74. *
  75. * none
  76. *
  77. \**************************************************************************/
  78. VOID
  79. vRop2Function0(
  80. PULONG pulDstBuffer,
  81. PULONG pulDBuffer,
  82. PULONG pulSBuffer,
  83. ULONG cx
  84. )
  85. {
  86. DONTUSE(pulDBuffer);
  87. DONTUSE(pulSBuffer);
  88. memset((void *)pulDstBuffer,0,(int)(cx<<2));
  89. }
  90. VOID
  91. vRop2Function1(
  92. PULONG pulDstBuffer,
  93. PULONG pulDBuffer,
  94. PULONG pulSBuffer,
  95. ULONG cx
  96. )
  97. {
  98. while (cx--) {
  99. *pulDstBuffer++ = ~(*pulSBuffer++ | *pulDBuffer++);
  100. }
  101. return;
  102. }
  103. VOID
  104. vRop2Function2(
  105. PULONG pulDstBuffer,
  106. PULONG pulDBuffer,
  107. PULONG pulSBuffer,
  108. ULONG cx
  109. )
  110. {
  111. while (cx--) {
  112. *pulDstBuffer++ = (~*pulSBuffer++ & *pulDBuffer++);
  113. }
  114. return;
  115. }
  116. VOID
  117. vRop2Function3(
  118. PULONG pulDstBuffer,
  119. PULONG pulDBuffer,
  120. PULONG pulSBuffer,
  121. ULONG cx
  122. )
  123. {
  124. DONTUSE(pulDBuffer);
  125. while (cx--) {
  126. *pulDstBuffer++ = ~*pulSBuffer++;
  127. }
  128. return;
  129. }
  130. VOID
  131. vRop2Function4(
  132. PULONG pulDstBuffer,
  133. PULONG pulDBuffer,
  134. PULONG pulSBuffer,
  135. ULONG cx
  136. )
  137. {
  138. while (cx--) {
  139. *pulDstBuffer++ = *pulSBuffer++ & ~*pulDBuffer++;
  140. }
  141. return;
  142. }
  143. VOID
  144. vRop2Function5(
  145. PULONG pulDstBuffer,
  146. PULONG pulDBuffer,
  147. PULONG pulSBuffer,
  148. ULONG cx
  149. )
  150. {
  151. DONTUSE(pulSBuffer);
  152. while (cx--) {
  153. *pulDstBuffer++ = ~*pulDBuffer++;
  154. }
  155. return;
  156. }
  157. VOID
  158. vRop2Function6(
  159. PULONG pulDstBuffer,
  160. PULONG pulDBuffer,
  161. PULONG pulSBuffer,
  162. ULONG cx
  163. )
  164. {
  165. while (cx--) {
  166. *pulDstBuffer++ = *pulSBuffer++ ^ *pulDBuffer++;
  167. }
  168. return;
  169. }
  170. VOID
  171. vRop2Function7(
  172. PULONG pulDstBuffer,
  173. PULONG pulDBuffer,
  174. PULONG pulSBuffer,
  175. ULONG cx
  176. )
  177. {
  178. while (cx--) {
  179. *pulDstBuffer++ = ~(*pulSBuffer++ & *pulDBuffer++);
  180. }
  181. return;
  182. }
  183. VOID
  184. vRop2Function8(
  185. PULONG pulDstBuffer,
  186. PULONG pulDBuffer,
  187. PULONG pulSBuffer,
  188. ULONG cx
  189. )
  190. {
  191. while (cx--) {
  192. *pulDstBuffer++ = *pulSBuffer++ & *pulDBuffer++;
  193. }
  194. return;
  195. }
  196. VOID
  197. vRop2Function9(
  198. PULONG pulDstBuffer,
  199. PULONG pulDBuffer,
  200. PULONG pulSBuffer,
  201. ULONG cx
  202. )
  203. {
  204. while (cx--) {
  205. *pulDstBuffer++ = ~(*pulSBuffer++ ^ *pulDBuffer++);
  206. }
  207. return;
  208. }
  209. VOID
  210. vRop2FunctionA(
  211. PULONG pulDstBuffer,
  212. PULONG pulDBuffer,
  213. PULONG pulSBuffer,
  214. ULONG cx
  215. )
  216. {
  217. DONTUSE(pulSBuffer);
  218. memcpy((void *)pulDstBuffer,(void *)pulDBuffer,(int)(cx<<2));
  219. return;
  220. }
  221. VOID
  222. vRop2FunctionB(
  223. PULONG pulDstBuffer,
  224. PULONG pulDBuffer,
  225. PULONG pulSBuffer,
  226. ULONG cx
  227. )
  228. {
  229. while (cx--) {
  230. *pulDstBuffer++ = (~*pulSBuffer++) | *pulDBuffer++;
  231. }
  232. return;
  233. }
  234. VOID
  235. vRop2FunctionC(
  236. PULONG pulDstBuffer,
  237. PULONG pulDBuffer,
  238. PULONG pulSBuffer,
  239. ULONG cx
  240. )
  241. {
  242. DONTUSE(pulDBuffer);
  243. memcpy((void *)pulDstBuffer,(void *)pulSBuffer,(int)(cx<<2));
  244. return;
  245. }
  246. VOID
  247. vRop2FunctionD(
  248. PULONG pulDstBuffer,
  249. PULONG pulDBuffer,
  250. PULONG pulSBuffer,
  251. ULONG cx
  252. )
  253. {
  254. while (cx--) {
  255. *pulDstBuffer++ = *pulSBuffer++ | (~*pulDBuffer++);
  256. }
  257. return;
  258. }
  259. VOID
  260. vRop2FunctionE(
  261. PULONG pulDstBuffer,
  262. PULONG pulDBuffer,
  263. PULONG pulSBuffer,
  264. ULONG cx
  265. )
  266. {
  267. while (cx--) {
  268. *pulDstBuffer++ = *pulSBuffer++ | *pulDBuffer++;
  269. }
  270. return;
  271. }
  272. VOID
  273. vRop2FunctionF(
  274. PULONG pulDstBuffer,
  275. PULONG pulDBuffer,
  276. PULONG pulSBuffer,
  277. ULONG cx
  278. )
  279. {
  280. DONTUSE(pulSBuffer);
  281. DONTUSE(pulDBuffer);
  282. memset((void *)pulDstBuffer,0xFF,(int)cx<<2);
  283. }
  284. /******************************Public*Routine******************************\
  285. * Routine Name:
  286. *
  287. * BltLnkSrcCopyMsk1
  288. *
  289. * Routine Description:
  290. *
  291. * Routines to store src to dst based on 1 bit per pixel mask.
  292. *
  293. * Arguments:
  294. *
  295. * pBltInfo - pointer to BLTINFO structure (src and dst info)
  296. * pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
  297. * Bytes - Number of Bytes per pixel
  298. * Buffer0 - Pointer to a temporary scan line buffer used to read mask
  299. * Buffer1 - Pointer to a temporary scan line buffer used align src
  300. * if necessary. Only used for Mask Blt, not ROPs which
  301. * are already aligned
  302. *
  303. * Return Value:
  304. *
  305. * none
  306. *
  307. \**************************************************************************/
  308. VOID
  309. BltLnkSrcCopyMsk1 (
  310. PBLTINFO pBltInfo,
  311. PBLTLNK_MASKINFO pMaskInfo,
  312. PULONG Buffer0,
  313. PULONG Buffer1
  314. )
  315. {
  316. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  317. PBYTE pjDstTmp = pBltInfo->pjDst;
  318. PBYTE pjSrc;
  319. PBYTE pjDst;
  320. ULONG ixDst;
  321. ULONG ixMsk;
  322. ULONG iyMsk = pMaskInfo->iyMsk;
  323. PBYTE pjMsk = pMaskInfo->pjMsk;
  324. LONG cx;
  325. ULONG cy = pBltInfo->cy;
  326. PBYTE pjBuffer = (PBYTE)&Buffer0[0];
  327. BYTE Mask;
  328. //
  329. // if src and dst are not aligned then use SrcBlt1 to
  330. // copy each scan line to temp buffer Buffer1 first
  331. // to align it to dst
  332. //
  333. while (cy--)
  334. {
  335. cx = (LONG)pBltInfo->cx;
  336. pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 3);
  337. pjDst = pjDstTmp + (pBltInfo->xDstStart >> 3);
  338. ixMsk = pMaskInfo->ixMsk;
  339. ixDst = pBltInfo->xDstStart;
  340. //
  341. // check Src and Dst alignment, if Src and Dst are not aligned,
  342. // copy Src to a temp buffer at Dst alignment
  343. //
  344. if ((pBltInfo->xSrcStart & 0x07) != (pBltInfo->xDstStart & 0x07))
  345. {
  346. //
  347. // copy and align src to dst
  348. //
  349. BltLnkReadPat1((PBYTE)Buffer1,
  350. ixDst & 0x07,
  351. pjSrc,
  352. cx,
  353. pBltInfo->xSrcStart & 0x07,
  354. cx,0);
  355. pjSrc = (PBYTE)Buffer1;
  356. }
  357. //
  358. // align mask using BltLnkReadPat1
  359. //
  360. BltLnkReadPat1((PBYTE)Buffer0,ixDst,pjMsk,pMaskInfo->cxMsk,ixMsk,cx,0);
  361. pjBuffer = (PBYTE)Buffer0;
  362. //
  363. // If pMaskInfo->NegateMsk is FALSE, then when a mask bit is set
  364. // the Src is written to Dst, Dst is unchanged when the mask is clear.
  365. //
  366. // If pMaskInfo->NegateMsk is TRUE, then when a mask bit is clear
  367. // the Src is written to Dst, Dst is unchanged when the mask is set.
  368. //
  369. // ReadPat1 will zero partial bits at the beginning and end of a
  370. // scan line, this work fine for !Negate because zero mask bits are
  371. // not copied. However, for Negate masks, partial bits at the
  372. // beginning and end of scan lines must be masked so that these
  373. // bits are "1"s so that Src will not be copied to Dst. This is
  374. // done by ORing start and end masks onto the mask line.
  375. //
  376. if (!pMaskInfo->NegateMsk)
  377. {
  378. while (cx>0)
  379. {
  380. Mask = *pjBuffer;
  381. if (Mask == 0xFF)
  382. {
  383. *pjDst = *pjSrc;
  384. } else if (Mask != 0) {
  385. *pjDst = (*pjSrc & Mask) | (*pjDst & ~Mask);
  386. }
  387. pjSrc++;
  388. pjDst++;
  389. pjBuffer++;
  390. cx -= 8;
  391. //
  392. // check if this was a partial byte,
  393. // in that case restore partial byte
  394. // to cx (cx -= 8 -(ixDst & 0x07))
  395. // but since already did cx -= 8,add
  396. // ixDst & 0x07 back in
  397. //
  398. if (ixDst & 0x07)
  399. {
  400. cx += ixDst & 0x07;
  401. //
  402. // zero ixDst, will not be needed again
  403. //
  404. ixDst = 0;
  405. }
  406. }
  407. } else {
  408. //
  409. // In this case write src to dst bits when mask == 0.
  410. // This means the beggining and end cases must have
  411. // mask set to 1 for the bits of partial bytes that are
  412. // not to be touched.
  413. //
  414. // ie : starting ixDst = 2
  415. // ���������������Ŀ
  416. // Mask = �0�1�2�3�4�5�6�7�
  417. // �����������������
  418. // ���������������Ŀ
  419. // or with �1�1�0�0�0�0�0�0�
  420. // �����������������
  421. //
  422. // to make sure pixels 0 and 1 are not written.
  423. // this is 0xFF << 6 = 0xFF << (8 - (ixDst & 7))
  424. //
  425. pjBuffer[0] |= (BYTE) (0xff << (8 - (ixDst & 0x07)));
  426. //
  427. // for the ending case, want to set all bits after the
  428. // last.
  429. //
  430. // ie: ixDst = 2, cx = 8. This means store byte 0
  431. // bits 2,3,4,5,6,7 and byte 1 bits 0 and 1
  432. // ���������������Ŀ
  433. // In this case the mask must be �0�0�1�1�1�1�1�1�
  434. // �����������������
  435. // which is 0xFF >> 2 = (ixDst + cx) & 0x07
  436. //
  437. pjBuffer[((ixDst&0x07) + cx) >> 3] |=
  438. (BYTE) (0xff >> ((ixDst + cx) & 0x07));
  439. while (cx>0)
  440. {
  441. Mask = *pjBuffer;
  442. if (Mask == 0x00)
  443. {
  444. *pjDst = *pjSrc;
  445. } else if (Mask != 0xFF) {
  446. *pjDst = (*pjDst & Mask) | (*pjSrc & ~Mask);
  447. }
  448. pjSrc++;
  449. pjDst++;
  450. pjBuffer++;
  451. cx -= 8;
  452. //
  453. // check if this was a partial byte,
  454. // in that case restore partial byte
  455. // to cx (cx -= 8 -(ixDst & 0x07))
  456. // but since already did cx -= 8,add
  457. // ixDst & 0x07 back in
  458. //
  459. if (ixDst & 0x07) {
  460. cx += ixDst & 0x07;
  461. //
  462. // zero ixDst, will not be needed again
  463. //
  464. ixDst = 0;
  465. }
  466. }
  467. }
  468. //
  469. // increment for next scan line
  470. //
  471. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  472. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  473. if (pBltInfo->yDir > 0) {
  474. iyMsk++;
  475. pjMsk += pMaskInfo->lDeltaMskDir;
  476. if ((LONG)iyMsk >= pMaskInfo->cyMsk)
  477. {
  478. iyMsk = 0;
  479. pjMsk = pMaskInfo->pjMskBase;
  480. }
  481. } else {
  482. if (iyMsk == 0)
  483. {
  484. iyMsk = pMaskInfo->cyMsk - 1;
  485. pjMsk = pMaskInfo->pjMskBase +
  486. (pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
  487. }
  488. else
  489. {
  490. iyMsk--;
  491. pjMsk += pMaskInfo->lDeltaMskDir;
  492. }
  493. }
  494. }
  495. }
  496. /******************************Public*Routine******************************\
  497. * Routine Name:
  498. *
  499. * BltLnkSrcCopyMsk4
  500. *
  501. * Routine Description:
  502. *
  503. * Routines to store src to dst based on 1 bit per pixel mask.
  504. *
  505. * Arguments:
  506. *
  507. * pBltInfo - pointer to BLTINFO structure (src and dst info)
  508. * pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
  509. * Bytes - Number of Bytes per pixel
  510. * Buffer - Pointer to a temporary buffer that may be used
  511. *
  512. * Return Value:
  513. *
  514. * none
  515. *
  516. \**************************************************************************/
  517. VOID
  518. BltLnkSrcCopyMsk4 (
  519. PBLTINFO pBltInfo,
  520. PBLTLNK_MASKINFO pMaskInfo,
  521. PULONG Buffer0,
  522. PULONG Buffer1
  523. )
  524. {
  525. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  526. PBYTE pjDstTmp = pBltInfo->pjDst;
  527. PBYTE pjSrc;
  528. PBYTE pjDst;
  529. BYTE jMsk;
  530. BYTE jSrc;
  531. BYTE jDst;
  532. BYTE jDstNew;
  533. ULONG ixSrc;
  534. ULONG ixDst;
  535. ULONG ixMsk;
  536. ULONG iyMsk = pMaskInfo->iyMsk;
  537. PBYTE pjMsk = pMaskInfo->pjMsk;
  538. ULONG cx;
  539. ULONG cy = pBltInfo->cy;
  540. DONTUSE(Buffer0);
  541. DONTUSE(Buffer1);
  542. while (cy--) {
  543. cx = pBltInfo->cx;
  544. pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 1);
  545. pjDst = pjDstTmp + (pBltInfo->xDstStart >> 1);
  546. ixMsk = pMaskInfo->ixMsk;
  547. ixSrc = pBltInfo->xSrcStart;
  548. ixDst = pBltInfo->xDstStart;
  549. //
  550. // load first mask byte and align it
  551. //
  552. jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
  553. jMsk <<= ixMsk & 0x7;
  554. //
  555. // if destination is on odd nibble we'll handle it now so the main
  556. // loop can process two nibbles per pass
  557. //
  558. if (ixDst & 1)
  559. {
  560. if (jMsk & 0x80)
  561. {
  562. if (ixSrc & 1)
  563. *pjDst = (*pjDst & 0xf0) | (*pjSrc & 0x0f);
  564. else
  565. *pjDst = (*pjDst & 0xf0) | ((*pjSrc & 0xf0) >> 4);
  566. }
  567. pjDst++;
  568. ixSrc++;
  569. if (!(ixSrc & 1))
  570. pjSrc++;
  571. jMsk <<= 1;
  572. ixMsk++;
  573. cx--;
  574. }
  575. ixSrc &= 1;
  576. //
  577. // main loop, pack two pixels into each output byte per pass
  578. //
  579. while (cx >= 2)
  580. {
  581. BYTE jMskTmp;
  582. //
  583. // calculate the mask bits for both pixels
  584. //
  585. if ((LONG)ixMsk == pMaskInfo->cxMsk)
  586. ixMsk = 0;
  587. if (!(ixMsk & 0x07))
  588. jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
  589. jMskTmp = jMsk;
  590. jMsk <<= 1;
  591. if ((LONG)++ixMsk == pMaskInfo->cxMsk)
  592. ixMsk = 0;
  593. if (!(ixMsk & 0x07))
  594. jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
  595. //
  596. // determine whether first nibble uses source
  597. //
  598. if (jMskTmp & 0x80)
  599. {
  600. if (jMsk & 0x80)
  601. {
  602. if (ixSrc)
  603. *pjDst = (*pjSrc << 4) | ((pjSrc[1] & 0xf0) >> 4);
  604. else
  605. *pjDst = *pjSrc;
  606. }
  607. else
  608. {
  609. if (ixSrc)
  610. *pjDst = (*pjDst & 0x0f) | (*pjSrc << 4);
  611. else
  612. *pjDst = (*pjDst & 0x0f) | (*pjSrc & 0xf0);
  613. }
  614. }
  615. else
  616. {
  617. if (jMsk & 0x80)
  618. {
  619. if (ixSrc)
  620. *pjDst = (*pjDst & 0xf0) | ((*pjSrc & 0xf0) >> 4);
  621. else
  622. *pjDst = (*pjDst & 0xf0) | (*pjSrc & 0x0f);
  623. }
  624. }
  625. jMsk <<= 1;
  626. ixMsk++;
  627. pjDst++;
  628. pjSrc++;
  629. cx -= 2;
  630. }
  631. //
  632. // handle remaining nibble if there is one
  633. //
  634. if (cx)
  635. {
  636. if ((LONG)ixMsk == pMaskInfo->cxMsk)
  637. ixMsk = 0;
  638. if (!(ixMsk & 0x07))
  639. jMsk = pjMsk[ixMsk >> 3] ^ pMaskInfo->NegateMsk;
  640. if (jMsk & 0x80)
  641. {
  642. if (ixSrc)
  643. *pjDst = (*pjDst & 0x0f) | (*pjSrc << 4);
  644. else
  645. *pjDst = (*pjDst & 0x0f) | (*pjSrc & 0xf0);
  646. }
  647. }
  648. //
  649. // increment for next scan line
  650. //
  651. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  652. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  653. if (pBltInfo->yDir > 0) {
  654. iyMsk++;
  655. pjMsk += pMaskInfo->lDeltaMskDir;
  656. if ((LONG)iyMsk >= pMaskInfo->cyMsk)
  657. {
  658. iyMsk = 0;
  659. pjMsk = pMaskInfo->pjMskBase;
  660. }
  661. } else {
  662. if (iyMsk == 0)
  663. {
  664. iyMsk = pMaskInfo->cyMsk - 1;
  665. pjMsk = pMaskInfo->pjMskBase +
  666. (pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
  667. }
  668. else
  669. {
  670. iyMsk--;
  671. pjMsk += pMaskInfo->lDeltaMskDir;
  672. }
  673. }
  674. }
  675. }
  676. /******************************Public*Routine******************************\
  677. * Routine Name:
  678. *
  679. * BltLnkSrcCopyMsk8
  680. *
  681. * Routine Description:
  682. *
  683. * Routines to store src to dst based on 1 bit per pixel mask.
  684. *
  685. * Arguments:
  686. *
  687. * pBltInfo - pointer to BLTLNKCOPYINFO structure (src and dst info)
  688. * pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
  689. * Bytes - Number of Bytes per pixel
  690. * Buffer - Pointer to a temporary buffer that may be used
  691. *
  692. * Return Value:
  693. *
  694. * none
  695. *
  696. \**************************************************************************/
  697. VOID
  698. BltLnkSrcCopyMsk8 (
  699. PBLTINFO pBltInfo,
  700. PBLTLNK_MASKINFO pMaskInfo,
  701. PULONG Buffer0,
  702. PULONG Buffer1
  703. )
  704. {
  705. ULONG jMsk = 0;
  706. LONG ixMsk;
  707. LONG cxMsk = pMaskInfo->cxMsk;
  708. LONG iyMsk = pMaskInfo->iyMsk;
  709. LONG icx;
  710. LONG cx;
  711. ULONG cy = pBltInfo->cy;
  712. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  713. PBYTE pjDstTmp = pBltInfo->pjDst;
  714. PBYTE pjSrc;
  715. PBYTE pjDst;
  716. PBYTE pjMsk = pMaskInfo->pjMsk;
  717. BYTE Negate = pMaskInfo->NegateMsk;
  718. ULONG icxDst;
  719. LONG DeltaMsk;
  720. DONTUSE(Buffer0);
  721. DONTUSE(Buffer1);
  722. while (cy--)
  723. {
  724. //
  725. // init loop params
  726. //
  727. cx = (LONG)pBltInfo->cx;
  728. ixMsk = pMaskInfo->ixMsk;
  729. pjSrc = pjSrcTmp + pBltInfo->xSrcStart;
  730. pjDst = pjDstTmp + pBltInfo->xDstStart;
  731. //
  732. // finish the scan line 8 mask bits at a time
  733. //
  734. while (cx > 0)
  735. {
  736. jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
  737. //
  738. // icx is the number of pixels left in the mask byte
  739. //
  740. icx = 8 - (ixMsk & 0x07);
  741. //
  742. // icx is the number of pixels to operate on with this mask byte.
  743. // Must make sure that icx is less than cx, the number of pixels
  744. // remaining in the blt and cx is less than DeltaMsk, the number
  745. // of bits in the mask still valid. If icx is reduced because of
  746. // cx of DeltaMsk, then jMsk must be shifted right to compensate.
  747. //
  748. DeltaMsk = cxMsk - ixMsk;
  749. icxDst = 0;
  750. if (icx > cx) {
  751. icxDst = icx - cx;
  752. icx = cx;
  753. }
  754. if (icx > DeltaMsk) {
  755. icxDst = icxDst + (icx - DeltaMsk);
  756. icx = DeltaMsk;
  757. }
  758. //
  759. // icxDst is now the number of pixels that can't be stored off
  760. // the right side of the mask
  761. //
  762. // Bit 7 6 5 4 3 2 1 0
  763. // ���������������Ŀ
  764. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  765. // ����������������� mask gets shifted right 2 to
  766. //
  767. //
  768. // Bit 7 6 5 4 3 2 1 0
  769. // ���������������Ŀ
  770. // ixMsk� � �0�1�2�3�4�5�
  771. // �����������������
  772. //
  773. //
  774. //
  775. // the number of mask bits valid = 8 minus the offset (ixMsk & 0x07)
  776. // minus the number of pixels that can't be stored because cx
  777. // runs out or because cxMsk runs out (icxDst)
  778. //
  779. cx -= icx;
  780. ixMsk += icx;
  781. if (jMsk != 0) {
  782. jMsk = jMsk >> icxDst;
  783. switch (icx)
  784. {
  785. case 8:
  786. if (jMsk & 0x01)
  787. {
  788. *(pjDst+7) = *(pjSrc+7);
  789. }
  790. jMsk >>= 1;
  791. case 7:
  792. if (jMsk & 0x01)
  793. {
  794. *(pjDst+6) = *(pjSrc+6);
  795. }
  796. jMsk >>= 1;
  797. case 6:
  798. if (jMsk & 0x01)
  799. {
  800. *(pjDst+5) = *(pjSrc+5);
  801. }
  802. jMsk >>= 1;
  803. case 5:
  804. if (jMsk & 0x01)
  805. {
  806. *(pjDst+4) = *(pjSrc+4);
  807. }
  808. jMsk >>= 1;
  809. case 4:
  810. if (jMsk & 0x01)
  811. {
  812. *(pjDst+3) = *(pjSrc+3);
  813. }
  814. jMsk >>= 1;
  815. case 3:
  816. if (jMsk & 0x01)
  817. {
  818. *(pjDst+2) = *(pjSrc+2);
  819. }
  820. jMsk >>= 1;
  821. case 2:
  822. if (jMsk & 0x01)
  823. {
  824. *(pjDst+1) = *(pjSrc+1);
  825. }
  826. jMsk >>= 1;
  827. case 1:
  828. if (jMsk & 0x01)
  829. {
  830. *pjDst = *pjSrc;
  831. }
  832. }
  833. }
  834. pjSrc += icx;
  835. pjDst += icx;
  836. if (ixMsk == cxMsk)
  837. {
  838. ixMsk = 0;
  839. }
  840. }
  841. //
  842. // Increment address to the next scan line.
  843. //
  844. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  845. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  846. //
  847. // Increment Mask address to the next scan line or
  848. // back to ther start if iy exceeds cy
  849. //
  850. if (pBltInfo->yDir > 0) {
  851. iyMsk++;
  852. pjMsk += pMaskInfo->lDeltaMskDir;
  853. if ((LONG)iyMsk >= pMaskInfo->cyMsk)
  854. {
  855. iyMsk = 0;
  856. pjMsk = pMaskInfo->pjMskBase;
  857. }
  858. } else {
  859. if (iyMsk == 0)
  860. {
  861. iyMsk = pMaskInfo->cyMsk - 1;
  862. pjMsk = pMaskInfo->pjMskBase +
  863. (pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
  864. }
  865. else
  866. {
  867. iyMsk--;
  868. pjMsk += pMaskInfo->lDeltaMskDir;
  869. }
  870. }
  871. }
  872. }
  873. /******************************Public*Routine******************************\
  874. * Routine Name:
  875. *
  876. * BltLnkSrcCopyMsk16
  877. *
  878. * Routine Description:
  879. *
  880. * Routines to store src to dst based on 1 bit per pixel mask.
  881. *
  882. * Arguments:
  883. *
  884. * pBltInfo - pointer to BLTINFO structure (src and dst info)
  885. * pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
  886. * Bytes - Number of Bytes per pixel
  887. * Buffer - Pointer to a temporary buffer that may be used
  888. *
  889. * Return Value:
  890. *
  891. * none
  892. *
  893. \**************************************************************************/
  894. VOID
  895. BltLnkSrcCopyMsk16 (
  896. PBLTINFO pBltInfo,
  897. PBLTLNK_MASKINFO pMaskInfo,
  898. PULONG Buffer0,
  899. PULONG Buffer1
  900. )
  901. {
  902. ULONG jMsk = 0;
  903. LONG ixMsk;
  904. LONG cxMsk = pMaskInfo->cxMsk;
  905. LONG iyMsk = pMaskInfo->iyMsk;
  906. LONG icx;
  907. LONG cx;
  908. ULONG cy = pBltInfo->cy;
  909. PUSHORT pusSrcTmp = (PUSHORT)pBltInfo->pjSrc;
  910. PUSHORT pusDstTmp = (PUSHORT)pBltInfo->pjDst;
  911. PUSHORT pusSrc;
  912. PUSHORT pusDst;
  913. PBYTE pjMsk = pMaskInfo->pjMsk;
  914. BYTE Negate = pMaskInfo->NegateMsk;
  915. ULONG icxDst;
  916. LONG DeltaMsk;
  917. DONTUSE(Buffer0);
  918. DONTUSE(Buffer1);
  919. while (cy--)
  920. {
  921. //
  922. // for each scan line, first do the writes necessary to
  923. // align the mask (ixMsk) to zero, then operate on the
  924. // mask 1 byte at a time (8 pixels) or cxMsk, whichever
  925. // is less
  926. //
  927. //
  928. // init loop params
  929. //
  930. cx = (LONG)pBltInfo->cx;
  931. ixMsk = pMaskInfo->ixMsk;
  932. pusSrc = pusSrcTmp + pBltInfo->xSrcStart;
  933. pusDst = pusDstTmp + pBltInfo->xDstStart;
  934. //
  935. // finish the aligned scan line 8 mask bits at a time
  936. //
  937. while (cx > 0)
  938. {
  939. jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
  940. //
  941. // icx is the number of pixels left in the mask byte
  942. //
  943. icx = 8 - (ixMsk & 0x07);
  944. //
  945. // icx is the number of pixels to operate on with this mask byte.
  946. // Must make sure that icx is less than cx, the number of pixels
  947. // remaining in the blt and cx is less than DeltaMsk, the number
  948. // of bits in the mask still valid. If icx is reduced because of
  949. // cx of DeltaMsk, then jMsk must be shifted right to compensate.
  950. //
  951. DeltaMsk = cxMsk - ixMsk;
  952. icxDst = 0;
  953. if (icx > cx) {
  954. icxDst = icx - cx;
  955. icx = cx;
  956. }
  957. if (icx > DeltaMsk) {
  958. icxDst = icxDst + (icx - DeltaMsk);
  959. icx = DeltaMsk;
  960. }
  961. //
  962. // icxDst is now the number of pixels that can't be stored off
  963. // the right side of the mask
  964. //
  965. // Bit 7 6 5 4 3 2 1 0
  966. // ���������������Ŀ
  967. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  968. // ����������������� mask gets shifted right 2 to
  969. //
  970. //
  971. // Bit 7 6 5 4 3 2 1 0
  972. // ���������������Ŀ
  973. // ixMsk� � �0�1�2�3�4�5�
  974. // �����������������
  975. //
  976. //
  977. //
  978. // the number of mask bits valid = 8 minus the offset (MskAln)
  979. // minus the number of pixels that can't be stored because cx
  980. // runs out or because cxMsk runs out (icxDst)
  981. //
  982. cx -= icx;
  983. ixMsk += icx;
  984. if (jMsk != 0) {
  985. jMsk = jMsk >> icxDst;
  986. switch (icx)
  987. {
  988. case 8:
  989. if (jMsk & 0x01)
  990. {
  991. *(pusDst+7) = *(pusSrc+7);
  992. }
  993. jMsk >>= 1;
  994. case 7:
  995. if (jMsk & 0x01)
  996. {
  997. *(pusDst+6) = *(pusSrc+6);
  998. }
  999. jMsk >>= 1;
  1000. case 6:
  1001. if (jMsk & 0x01)
  1002. {
  1003. *(pusDst+5) = *(pusSrc+5);
  1004. }
  1005. jMsk >>= 1;
  1006. case 5:
  1007. if (jMsk & 0x01)
  1008. {
  1009. *(pusDst+4) = *(pusSrc+4);
  1010. }
  1011. jMsk >>= 1;
  1012. case 4:
  1013. if (jMsk & 0x01)
  1014. {
  1015. *(pusDst+3) = *(pusSrc+3);
  1016. }
  1017. jMsk >>= 1;
  1018. case 3:
  1019. if (jMsk & 0x01)
  1020. {
  1021. *(pusDst+2) = *(pusSrc+2);
  1022. }
  1023. jMsk >>= 1;
  1024. case 2:
  1025. if (jMsk & 0x01)
  1026. {
  1027. *(pusDst+1) = *(pusSrc+1);
  1028. }
  1029. jMsk >>= 1;
  1030. case 1:
  1031. if (jMsk & 0x01)
  1032. {
  1033. *pusDst = *pusSrc;
  1034. }
  1035. }
  1036. }
  1037. pusSrc += icx;
  1038. pusDst += icx;
  1039. if (ixMsk == cxMsk)
  1040. {
  1041. ixMsk = 0;
  1042. }
  1043. }
  1044. //
  1045. // Increment address to the next scan line. Note: lDelta
  1046. // is in bytes
  1047. //
  1048. pusDstTmp = (PUSHORT)((PBYTE)pusDstTmp + pBltInfo->lDeltaDst);
  1049. pusSrcTmp = (PUSHORT)((PBYTE)pusSrcTmp + pBltInfo->lDeltaSrc);
  1050. //
  1051. // Increment Mask address to the next scan line or
  1052. // back to ther start if iy exceeds cy
  1053. //
  1054. if (pBltInfo->yDir > 0) {
  1055. iyMsk++;
  1056. pjMsk += pMaskInfo->lDeltaMskDir;
  1057. if ((LONG)iyMsk >= pMaskInfo->cyMsk)
  1058. {
  1059. iyMsk = 0;
  1060. pjMsk = pMaskInfo->pjMskBase;
  1061. }
  1062. } else {
  1063. if (iyMsk == 0)
  1064. {
  1065. iyMsk = pMaskInfo->cyMsk - 1;
  1066. pjMsk = pMaskInfo->pjMskBase +
  1067. (pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
  1068. }
  1069. else
  1070. {
  1071. iyMsk--;
  1072. pjMsk += pMaskInfo->lDeltaMskDir;
  1073. }
  1074. }
  1075. }
  1076. }
  1077. /******************************Public*Routine******************************\
  1078. * Routine Name:
  1079. *
  1080. * BltLnkSrcCopyMsk24
  1081. *
  1082. * Routine Description:
  1083. *
  1084. * Routines to store src to dst based on 1 bit per pixel mask.
  1085. *
  1086. * Arguments:
  1087. *
  1088. * pBltInfo - pointer to BLTINFO structure (src and dst info)
  1089. * pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
  1090. * Bytes - Number of Bytes per pixel
  1091. * Buffer - Pointer to a temporary buffer that may be used
  1092. *
  1093. * Return Value:
  1094. *
  1095. * none
  1096. *
  1097. \**************************************************************************/
  1098. VOID
  1099. BltLnkSrcCopyMsk24 (
  1100. PBLTINFO pBltInfo,
  1101. PBLTLNK_MASKINFO pMaskInfo,
  1102. PULONG Buffer0,
  1103. PULONG Buffer1
  1104. )
  1105. {
  1106. ULONG jMsk = 0;
  1107. LONG ixMsk;
  1108. LONG cxMsk = pMaskInfo->cxMsk;
  1109. LONG iyMsk = pMaskInfo->iyMsk;
  1110. LONG icx;
  1111. LONG cx;
  1112. ULONG cy = pBltInfo->cy;
  1113. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  1114. PBYTE pjDstTmp = pBltInfo->pjDst;
  1115. PBYTE pjSrc;
  1116. PBYTE pjDst;
  1117. PBYTE pjMsk = pMaskInfo->pjMsk;
  1118. BYTE Negate = pMaskInfo->NegateMsk;
  1119. ULONG icxDst;
  1120. LONG DeltaMsk;
  1121. DONTUSE(Buffer0);
  1122. DONTUSE(Buffer1);
  1123. while (cy--)
  1124. {
  1125. //
  1126. // for each scan line, first do the writes necessary to
  1127. // align the mask (ixMsk) to zero, then operate on the
  1128. // mask 1 byte at a time (8 pixels) or cxMsk, whichever
  1129. // is less
  1130. //
  1131. //
  1132. // init loop params
  1133. //
  1134. cx = (LONG)pBltInfo->cx;
  1135. ixMsk = pMaskInfo->ixMsk;
  1136. pjSrc = pjSrcTmp + 3 * pBltInfo->xSrcStart;
  1137. pjDst = pjDstTmp + 3 * pBltInfo->xDstStart;
  1138. //
  1139. // finish the aligned scan line 8 mask bits at a time
  1140. //
  1141. while (cx > 0)
  1142. {
  1143. jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
  1144. //
  1145. // icx is the number of pixels left in the mask byte
  1146. //
  1147. icx = 8 - (ixMsk & 0x07);
  1148. //
  1149. // icx is the number of pixels to operate on with this mask byte.
  1150. // Must make sure that icx is less than cx, the number of pixels
  1151. // remaining in the blt and cx is less than DeltaMsk, the number
  1152. // of bits in the mask still valid. If icx is reduced because of
  1153. // cx of DeltaMsk, then jMsk must be shifted right to compensate.
  1154. //
  1155. DeltaMsk = cxMsk - ixMsk;
  1156. icxDst = 0;
  1157. if (icx > cx) {
  1158. icxDst = icx - cx;
  1159. icx = cx;
  1160. }
  1161. if (icx > DeltaMsk) {
  1162. icxDst = icxDst + (icx - DeltaMsk);
  1163. icx = DeltaMsk;
  1164. }
  1165. //
  1166. // icxDst is now the number of pixels that can't be stored off
  1167. // the right side of the mask
  1168. //
  1169. // Bit 7 6 5 4 3 2 1 0
  1170. // ���������������Ŀ
  1171. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  1172. // ����������������� mask gets shifted right 2 to
  1173. //
  1174. //
  1175. // Bit 7 6 5 4 3 2 1 0
  1176. // ���������������Ŀ
  1177. // ixMsk� � �0�1�2�3�4�5�
  1178. // �����������������
  1179. //
  1180. //
  1181. //
  1182. // the number of mask bits valid = 8 minus the offset (MskAln)
  1183. // minus the number of pixels that can't be stored because cx
  1184. // runs out or because cxMsk runs out (icxDst)
  1185. //
  1186. cx -= icx;
  1187. ixMsk += icx;
  1188. if (jMsk != 0) {
  1189. jMsk = jMsk >> icxDst;
  1190. switch (icx)
  1191. {
  1192. case 8:
  1193. if (jMsk & 0x01)
  1194. {
  1195. *(pjDst+23) = *(pjSrc+23);
  1196. *(pjDst+22) = *(pjSrc+22);
  1197. *(pjDst+21) = *(pjSrc+21);
  1198. }
  1199. jMsk >>= 1;
  1200. case 7:
  1201. if (jMsk & 0x01)
  1202. {
  1203. *(pjDst+20) = *(pjSrc+20);
  1204. *(pjDst+19) = *(pjSrc+19);
  1205. *(pjDst+18) = *(pjSrc+18);
  1206. }
  1207. jMsk >>= 1;
  1208. case 6:
  1209. if (jMsk & 0x01)
  1210. {
  1211. *(pjDst+17) = *(pjSrc+17);
  1212. *(pjDst+16) = *(pjSrc+16);
  1213. *(pjDst+15) = *(pjSrc+15);
  1214. }
  1215. jMsk >>= 1;
  1216. case 5:
  1217. if (jMsk & 0x01)
  1218. {
  1219. *(pjDst+14) = *(pjSrc+14);
  1220. *(pjDst+13) = *(pjSrc+13);
  1221. *(pjDst+12) = *(pjSrc+12);
  1222. }
  1223. jMsk >>= 1;
  1224. case 4:
  1225. if (jMsk & 0x01)
  1226. {
  1227. *(pjDst+11) = *(pjSrc+11);
  1228. *(pjDst+10) = *(pjSrc+10);
  1229. *(pjDst+9) = *(pjSrc+9);
  1230. }
  1231. jMsk >>= 1;
  1232. case 3:
  1233. if (jMsk & 0x01)
  1234. {
  1235. *(pjDst+8) = *(pjSrc+8);
  1236. *(pjDst+7) = *(pjSrc+7);
  1237. *(pjDst+6) = *(pjSrc+6);
  1238. }
  1239. jMsk >>= 1;
  1240. case 2:
  1241. if (jMsk & 0x01)
  1242. {
  1243. *(pjDst+5) = *(pjSrc+5);
  1244. *(pjDst+4) = *(pjSrc+4);
  1245. *(pjDst+3) = *(pjSrc+3);
  1246. }
  1247. jMsk >>= 1;
  1248. case 1:
  1249. if (jMsk & 0x01)
  1250. {
  1251. *(pjDst+2) = *(pjSrc+2);
  1252. *(pjDst+1) = *(pjSrc+1);
  1253. *pjDst = *pjSrc;
  1254. }
  1255. }
  1256. }
  1257. pjSrc += 3*icx;
  1258. pjDst += 3*icx;
  1259. if (ixMsk == cxMsk)
  1260. {
  1261. ixMsk = 0;
  1262. }
  1263. }
  1264. //
  1265. // increment to next scan line
  1266. //
  1267. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  1268. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  1269. //
  1270. // Increment Mask address to the next scan line or
  1271. // back to ther start if iy exceeds cy
  1272. //
  1273. if (pBltInfo->yDir > 0) {
  1274. iyMsk++;
  1275. pjMsk += pMaskInfo->lDeltaMskDir;
  1276. if ((LONG)iyMsk >= pMaskInfo->cyMsk)
  1277. {
  1278. iyMsk = 0;
  1279. pjMsk = pMaskInfo->pjMskBase;
  1280. }
  1281. } else {
  1282. if (iyMsk == 0)
  1283. {
  1284. iyMsk = pMaskInfo->cyMsk - 1;
  1285. pjMsk = pMaskInfo->pjMskBase +
  1286. (pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
  1287. }
  1288. else
  1289. {
  1290. iyMsk--;
  1291. pjMsk += pMaskInfo->lDeltaMskDir;
  1292. }
  1293. }
  1294. }
  1295. }
  1296. /******************************Public*Routine******************************\
  1297. * Routine Name:
  1298. *
  1299. * BltLnkSrcCopyMsk32
  1300. *
  1301. * Routine Description:
  1302. *
  1303. * Routines to store src to dst based on 1 bit per pixel mask.
  1304. *
  1305. * Arguments:
  1306. *
  1307. * pBltInfo - pointer to BLTINFO structure (src and dst info)
  1308. * pMaskInfo - pointer to MASKINFO structure (pjMsk,ixMsk etc)
  1309. * Bytes - Number of Bytes per pixel
  1310. * Buffer - Pointer to a temporary buffer that may be used
  1311. *
  1312. * Return Value:
  1313. *
  1314. * none
  1315. *
  1316. \**************************************************************************/
  1317. VOID
  1318. BltLnkSrcCopyMsk32 (
  1319. PBLTINFO pBltInfo,
  1320. PBLTLNK_MASKINFO pMaskInfo,
  1321. PULONG Buffer0,
  1322. PULONG Buffer1
  1323. )
  1324. {
  1325. ULONG jMsk = 0;
  1326. LONG ixMsk;
  1327. LONG cxMsk = pMaskInfo->cxMsk;
  1328. LONG iyMsk = pMaskInfo->iyMsk;
  1329. LONG icx;
  1330. LONG cx;
  1331. ULONG cy = pBltInfo->cy;
  1332. PULONG pulSrcTmp = (PULONG)pBltInfo->pjSrc;
  1333. PULONG pulDstTmp = (PULONG)pBltInfo->pjDst;
  1334. PULONG pulSrc;
  1335. PULONG pulDst;
  1336. PBYTE pjMsk = pMaskInfo->pjMsk;
  1337. BYTE Negate = pMaskInfo->NegateMsk;
  1338. ULONG icxDst;
  1339. LONG DeltaMsk;
  1340. DONTUSE(Buffer0);
  1341. DONTUSE(Buffer1);
  1342. while (cy--)
  1343. {
  1344. //
  1345. // for each scan line, first do the writes necessary to
  1346. // align the mask (ixMsk) to zero, then operate on the
  1347. // mask 1 byte at a time (8 pixels) or cxMsk, whichever
  1348. // is less
  1349. //
  1350. //
  1351. // init loop params
  1352. //
  1353. cx = (LONG)pBltInfo->cx;
  1354. ixMsk = pMaskInfo->ixMsk;
  1355. pulSrc = pulSrcTmp + pBltInfo->xSrcStart;
  1356. pulDst = pulDstTmp + pBltInfo->xDstStart;
  1357. //
  1358. // finish the aligned scan line 8 mask bits at a time
  1359. //
  1360. while (cx > 0)
  1361. {
  1362. jMsk = (ULONG)(pjMsk[ixMsk>>3] ^ Negate);
  1363. //
  1364. // icx is the number of pixels left in the mask byte
  1365. //
  1366. icx = 8 - (ixMsk & 0x07);
  1367. //
  1368. // icx is the number of pixels to operate on with this mask byte.
  1369. // Must make sure that icx is less than cx, the number of pixels
  1370. // remaining in the blt and cx is less than DeltaMsk, the number
  1371. // of bits in the mask still valid. If icx is reduced because of
  1372. // cx of DeltaMsk, then jMsk must be shifted right to compensate.
  1373. //
  1374. DeltaMsk = cxMsk - ixMsk;
  1375. icxDst = 0;
  1376. if (icx > cx) {
  1377. icxDst = icx - cx;
  1378. icx = cx;
  1379. }
  1380. if (icx > DeltaMsk) {
  1381. icxDst = icxDst + (icx - DeltaMsk);
  1382. icx = DeltaMsk;
  1383. }
  1384. //
  1385. // icxDst is now the number of pixels that can't be stored off
  1386. // the right side of the mask
  1387. //
  1388. // Bit 7 6 5 4 3 2 1 0
  1389. // ���������������Ŀ
  1390. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  1391. // ����������������� mask gets shifted right 2 to
  1392. //
  1393. //
  1394. // Bit 7 6 5 4 3 2 1 0
  1395. // ���������������Ŀ
  1396. // ixMsk� � �0�1�2�3�4�5�
  1397. // �����������������
  1398. //
  1399. // the number of mask bits valid = 8 minus the offset (MskAln)
  1400. // minus the number of pixels that can't be stored because cx
  1401. // runs out or because cxMsk runs out (icxDst)
  1402. //
  1403. cx -= icx;
  1404. ixMsk += icx;
  1405. if (jMsk != 0) {
  1406. jMsk = jMsk >> icxDst;
  1407. switch (icx)
  1408. {
  1409. case 8:
  1410. if (jMsk & 0x01)
  1411. {
  1412. *(pulDst+7) = *(pulSrc+7);
  1413. }
  1414. jMsk >>= 1;
  1415. case 7:
  1416. if (jMsk & 0x01)
  1417. {
  1418. *(pulDst+6) = *(pulSrc+6);
  1419. }
  1420. jMsk >>= 1;
  1421. case 6:
  1422. if (jMsk & 0x01)
  1423. {
  1424. *(pulDst+5) = *(pulSrc+5);
  1425. }
  1426. jMsk >>= 1;
  1427. case 5:
  1428. if (jMsk & 0x01)
  1429. {
  1430. *(pulDst+4) = *(pulSrc+4);
  1431. }
  1432. jMsk >>= 1;
  1433. case 4:
  1434. if (jMsk & 0x01)
  1435. {
  1436. *(pulDst+3) = *(pulSrc+3);
  1437. }
  1438. jMsk >>= 1;
  1439. case 3:
  1440. if (jMsk & 0x01)
  1441. {
  1442. *(pulDst+2) = *(pulSrc+2);
  1443. }
  1444. jMsk >>= 1;
  1445. case 2:
  1446. if (jMsk & 0x01)
  1447. {
  1448. *(pulDst+1) = *(pulSrc+1);
  1449. }
  1450. jMsk >>= 1;
  1451. case 1:
  1452. if (jMsk & 0x01)
  1453. {
  1454. *pulDst = *pulSrc;
  1455. }
  1456. }
  1457. }
  1458. pulSrc += icx;
  1459. pulDst += icx;
  1460. if (ixMsk == cxMsk)
  1461. {
  1462. ixMsk = 0;
  1463. }
  1464. }
  1465. //
  1466. // Increment to next scan line, note: lDelta is
  1467. // in bytes.
  1468. //
  1469. pulDstTmp = (PULONG)((PBYTE)pulDstTmp + pBltInfo->lDeltaDst);
  1470. pulSrcTmp = (PULONG)((PBYTE)pulSrcTmp + pBltInfo->lDeltaSrc);
  1471. //
  1472. // Increment Mask address to the next scan line or
  1473. // back to ther start if iy exceeds cy
  1474. //
  1475. if (pBltInfo->yDir > 0) {
  1476. iyMsk++;
  1477. pjMsk += pMaskInfo->lDeltaMskDir;
  1478. if ((LONG)iyMsk >= pMaskInfo->cyMsk)
  1479. {
  1480. iyMsk = 0;
  1481. pjMsk = pMaskInfo->pjMskBase;
  1482. }
  1483. } else {
  1484. if (iyMsk == 0)
  1485. {
  1486. iyMsk = pMaskInfo->cyMsk - 1;
  1487. pjMsk = pMaskInfo->pjMskBase +
  1488. (pMaskInfo->lDeltaMskDir * (pMaskInfo->cyMsk - 1));
  1489. }
  1490. else
  1491. {
  1492. iyMsk--;
  1493. pjMsk += pMaskInfo->lDeltaMskDir;
  1494. }
  1495. }
  1496. }
  1497. }
  1498. /******************************Public*Routine******************************\
  1499. * BltLnkReadPat
  1500. *
  1501. * Routine Description:
  1502. *
  1503. * Read pattern into a scan line buffer for 8,16,24,32 Bpp
  1504. *
  1505. * Arguments:
  1506. *
  1507. * pjDst - destination buffer
  1508. * pjPat - pattern starting address
  1509. * cxPat - Width of pattern
  1510. * ixPat - initial pattern offset
  1511. * ByteCount - Number of Bytes to transfer
  1512. * BytesPerPixel - Number of Bytes per pixel(1,2,3,4)
  1513. *
  1514. * Return Value:
  1515. *
  1516. *
  1517. \**************************************************************************/
  1518. VOID
  1519. BltLnkReadPat(
  1520. PBYTE pjDst,
  1521. ULONG ixDst,
  1522. PBYTE pjPat,
  1523. ULONG cxPat,
  1524. ULONG ixPat,
  1525. ULONG PixelCount,
  1526. ULONG BytesPerPixel
  1527. )
  1528. {
  1529. ULONG ixPatTemp = ixPat;
  1530. ULONG ByteCount = PixelCount;
  1531. DONTUSE(ixDst);
  1532. //
  1533. // expand byte count by number of bytes per
  1534. // pixel
  1535. //
  1536. if (BytesPerPixel == 2) {
  1537. ByteCount = ByteCount << 1;
  1538. } else if (BytesPerPixel == 3) {
  1539. ByteCount = ByteCount *3;
  1540. } else if (BytesPerPixel == 4) {
  1541. ByteCount = ByteCount << 2;
  1542. }
  1543. while (ByteCount--) {
  1544. //
  1545. // make sure ixPat stays within the pattern
  1546. //
  1547. if (ixPatTemp == cxPat) {
  1548. ixPatTemp = 0;
  1549. }
  1550. *pjDst++ = pjPat[ixPatTemp++];
  1551. }
  1552. }
  1553. /******************************Public*Routine******************************\
  1554. * Routine Name:
  1555. *
  1556. * BltLnkReadPat4
  1557. *
  1558. * Routine Description:
  1559. *
  1560. * Build a byte array of specified length from a 4 bit per pixel mask
  1561. *
  1562. * Arguments:
  1563. *
  1564. * pjDst - byte pointer to store pattern
  1565. * pjPat - Starting Pat address
  1566. * cxPat - Pattern width in nibbles
  1567. * ixPat - Starting nibble offset in pattern
  1568. * PixelCount - Number of pixels (nibbles) to transfer
  1569. * BytesPerPixel - Only used in ReadPat(8,16,24,32)
  1570. *
  1571. * Return Value:
  1572. *
  1573. * none
  1574. *
  1575. \**************************************************************************/
  1576. VOID
  1577. BltLnkReadPat4 (
  1578. PBYTE pjDst,
  1579. ULONG ixDst,
  1580. PBYTE pjPat,
  1581. ULONG cxPat,
  1582. ULONG ixPat,
  1583. ULONG PixelCount,
  1584. ULONG BytesPerPixel
  1585. )
  1586. {
  1587. BYTE jDst;
  1588. LONG iOffset;
  1589. LONG Cnt;
  1590. DONTUSE(BytesPerPixel);
  1591. //
  1592. // handle case where destination starts on odd nibble
  1593. //
  1594. if ((ixDst & 1) && PixelCount)
  1595. {
  1596. jDst = pjPat[ixPat >> 1];
  1597. if (!(ixPat & 1))
  1598. jDst >>= 4;
  1599. *pjDst++ = jDst & 0x0f;
  1600. ixPat++;
  1601. PixelCount--;
  1602. }
  1603. //
  1604. // test whether it is worthwhile to implement fast version
  1605. // the offset needs to be a multiple of cxPat and even
  1606. //
  1607. iOffset = cxPat;
  1608. if (iOffset & 1)
  1609. iOffset *= 2;
  1610. if ((LONG)PixelCount > iOffset)
  1611. {
  1612. PixelCount -= iOffset;
  1613. iOffset >>= 1;
  1614. Cnt = iOffset;
  1615. }
  1616. else
  1617. {
  1618. Cnt = PixelCount >> 1;
  1619. PixelCount &= 1;
  1620. }
  1621. //
  1622. // handle packing two nibbles per loop to one destination byte
  1623. //
  1624. while (Cnt--)
  1625. {
  1626. if (ixPat == cxPat)
  1627. ixPat = 0;
  1628. jDst = pjPat[ixPat >> 1];
  1629. if (!(ixPat & 1))
  1630. {
  1631. if (++ixPat == cxPat)
  1632. {
  1633. ixPat = 0;
  1634. jDst = (jDst & 0xf0) | ((pjPat[0] & 0xf0) >> 4);
  1635. }
  1636. }
  1637. else
  1638. {
  1639. if (++ixPat == cxPat)
  1640. ixPat = 0;
  1641. jDst = (jDst << 4) | ((pjPat[ixPat >> 1] & 0xf0) >> 4);
  1642. }
  1643. *pjDst++ = jDst;
  1644. ixPat++;
  1645. }
  1646. //
  1647. // test for fast mode
  1648. //
  1649. if (PixelCount > 1)
  1650. {
  1651. // loop while copying from the beginning of the pattern to the end
  1652. // we loop multiple times so that the Src and Dst don't overlap.
  1653. // each pass allows us to copy twice as many bytes the next time
  1654. // (a single RtlMoveMemory doesn't work)
  1655. Cnt = PixelCount >> 1;
  1656. while (1)
  1657. {
  1658. LONG i = iOffset;
  1659. if (i > Cnt)
  1660. i = Cnt;
  1661. RtlCopyMemory(pjDst,&pjDst[-iOffset],i);
  1662. pjDst += i;
  1663. if (!(Cnt -= i))
  1664. break;
  1665. iOffset *= 2;
  1666. }
  1667. if (PixelCount & 1)
  1668. *pjDst = pjDst[-iOffset] & 0xf0;
  1669. }
  1670. //
  1671. // handle case where destination ends on odd nibble
  1672. //
  1673. else if (PixelCount & 1)
  1674. {
  1675. if (ixPat == cxPat)
  1676. ixPat = 0;
  1677. if (ixPat & 1)
  1678. *pjDst = pjPat[ixPat >> 1] << 4;
  1679. else
  1680. *pjDst = pjPat[ixPat >> 1] & 0xf0;
  1681. }
  1682. }
  1683. /******************************Public*Routine******************************\
  1684. * Routine Name:
  1685. *
  1686. * BltLnkReadPat1
  1687. *
  1688. * Routine Description:
  1689. *
  1690. * Build a byte array of specified length from a 1 bit per pixel mask
  1691. *
  1692. * Arguments:
  1693. *
  1694. * pjDst - byte pointer to store pattern
  1695. * ixDst - starting bit offset in Dst
  1696. * pjPat - Starting Pat address
  1697. * cxPat - Pattern width in bits
  1698. * ixPat - Starting bit offset in pattern
  1699. * PixelCount - Number of pixels (bits) to transfer
  1700. * BytesPerPixel - Only used in ReadPat(8,16,24,32)
  1701. *
  1702. * Return Value:
  1703. *
  1704. * none
  1705. *
  1706. \**************************************************************************/
  1707. VOID
  1708. BltLnkReadPat1 (
  1709. PBYTE pjDst,
  1710. ULONG ixDst,
  1711. PBYTE pjPat,
  1712. ULONG cxPat,
  1713. ULONG ixPat,
  1714. ULONG PixelCount,
  1715. ULONG BytesPerPixel
  1716. )
  1717. {
  1718. ULONG jDst;
  1719. ULONG jPat;
  1720. ULONG DstAln;
  1721. ULONG PatAln;
  1722. ULONG icx;
  1723. DONTUSE(BytesPerPixel);
  1724. jDst = 0;
  1725. DstAln = ixDst & 0x07;
  1726. PatAln = ixPat & 0x07;
  1727. while (PixelCount>0) {
  1728. jPat = pjPat[ixPat>>3] & StartMask[PatAln];
  1729. if (DstAln > PatAln)
  1730. {
  1731. icx = 8 - DstAln;
  1732. if (icx > PixelCount)
  1733. {
  1734. icx = PixelCount;
  1735. }
  1736. if (icx > (cxPat - ixPat)) {
  1737. icx = cxPat - ixPat;
  1738. }
  1739. jPat &= EndMask[PatAln + icx];
  1740. jPat = jPat >> (DstAln - PatAln);
  1741. } else {
  1742. icx = 8 - PatAln;
  1743. if (icx > PixelCount)
  1744. {
  1745. icx = PixelCount;
  1746. }
  1747. if (icx > (cxPat - ixPat)) {
  1748. icx = cxPat - ixPat;
  1749. }
  1750. jPat &= EndMask[PatAln + icx];
  1751. jPat = jPat << (PatAln - DstAln);
  1752. }
  1753. jDst |= jPat;
  1754. ixDst += icx;
  1755. DstAln = ixDst & 0x07;
  1756. ixPat += icx;
  1757. PatAln = ixPat & 0x07;
  1758. PixelCount -= icx;
  1759. if (ixPat == cxPat) {
  1760. ixPat = 0;
  1761. PatAln = 0;
  1762. }
  1763. if (!(ixDst & 0x07) || (PixelCount == 0)) {
  1764. *pjDst = (BYTE)jDst;
  1765. pjDst++;
  1766. jDst = 0;
  1767. }
  1768. }
  1769. }
  1770. /******************************Public*Routine******************************\
  1771. * Routine Name:
  1772. *
  1773. * BltLnkPatMaskCopy1
  1774. *
  1775. * Routine Description:
  1776. *
  1777. * Transparent Color Expansion to 1bpp
  1778. *
  1779. * Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
  1780. * to Dst. Where src is 1, leave Dst unchanged.
  1781. *
  1782. *
  1783. *
  1784. * Arguments:
  1785. *
  1786. * pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
  1787. * ulPat - Solid color pattern
  1788. * pBuffer - Scan line buffer if needed
  1789. * Invert - XOR mask used on Src to determine whether to write
  1790. * through "1" pixels or "0" pixels
  1791. *
  1792. * Return Value:
  1793. *
  1794. * none
  1795. *
  1796. \**************************************************************************/
  1797. VOID
  1798. BltLnkPatMaskCopy1(
  1799. PBLTINFO pBltInfo,
  1800. ULONG ulPat,
  1801. PULONG pBuffer,
  1802. BYTE Invert
  1803. )
  1804. {
  1805. ULONG cx;
  1806. ULONG cy = pBltInfo->cy;
  1807. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  1808. PBYTE pjDstTmp = pBltInfo->pjDst;
  1809. PBYTE pjSrc;
  1810. PBYTE pjDst;
  1811. ULONG ixDst;
  1812. ULONG SrcAln;
  1813. ULONG DstAln;
  1814. LONG ByteCount;
  1815. BYTE Pat;
  1816. //
  1817. // For each scan line, first make sure Src and Dst are aligned.
  1818. // If they are not aligned then copy Src to a temp buffer at
  1819. // Dst alignment.
  1820. //
  1821. // Next, the start and end of the scan line must be masked so that
  1822. // partial byte writes only store the correct bits. This is done by
  1823. // ORing "1"s to the start and end of the scan line where appropriate.
  1824. //
  1825. // Finally, the logic operation is performed:
  1826. //
  1827. // Dst = (Mask & Dst) | (~Mask & Pat);
  1828. //
  1829. // Pat is ulPat[0] replicated to 8 bits
  1830. //
  1831. Pat = (BYTE) (ulPat & 0x01);
  1832. Pat |= Pat << 1;
  1833. Pat |= Pat << 2;
  1834. Pat |= Pat << 4;
  1835. SrcAln = pBltInfo->xSrcStart & 0x07;
  1836. DstAln = pBltInfo->xDstStart & 0x07;
  1837. ixDst = pBltInfo->xDstStart;
  1838. cx = pBltInfo->cx;
  1839. while(cy--) {
  1840. pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 3);
  1841. pjDst = pjDstTmp + (pBltInfo->xSrcStart >> 3);
  1842. BltLnkReadPat1((PBYTE)pBuffer,DstAln,pjSrc,cx,SrcAln,cx,0);
  1843. pjSrc = (PBYTE)pBuffer;
  1844. if (Invert == 0)
  1845. {
  1846. //
  1847. // mask start and end byte, if invert = 0x00 then start and end cases
  1848. // are masked by ORing with "1"s
  1849. //
  1850. pjSrc[0] |= (BYTE) (0xff >> (8 - DstAln));
  1851. pjSrc[(ixDst + cx) >> 3] |= (BYTE) (0xff << ((ixDst + cx) & 0x07));
  1852. //
  1853. // Number of whole bytes to transfer
  1854. //
  1855. ByteCount = (DstAln + cx + 7) >> 3;
  1856. while (ByteCount--)
  1857. {
  1858. BYTE Mask = *pjSrc;
  1859. *pjDst = (Mask & *pjDst) | (~Mask & Pat);
  1860. pjDst++;
  1861. pjSrc++;
  1862. }
  1863. } else {
  1864. //
  1865. // mask start and end byte, if invert = 0xFF then start and end cases
  1866. // are already masked to '0's by ReadPat1
  1867. //
  1868. //
  1869. // Number of whole bytes to transfer
  1870. //
  1871. ByteCount = (DstAln + cx + 7) >> 3;
  1872. while (ByteCount--)
  1873. {
  1874. BYTE Mask = *pjSrc;
  1875. *pjDst = (~Mask & *pjDst) | (Mask & Pat);
  1876. pjDst++;
  1877. pjSrc++;
  1878. }
  1879. }
  1880. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  1881. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  1882. }
  1883. return;
  1884. }
  1885. /******************************Public*Routine******************************\
  1886. * Routine Name:
  1887. *
  1888. * BltLnkPatMaskCopy4
  1889. *
  1890. * Routine Description:
  1891. *
  1892. * Transparent Color Expansion to 4bpp
  1893. *
  1894. * Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
  1895. * to Dst. Where src is 1, leave Dst unchanged.
  1896. *
  1897. *
  1898. *
  1899. * Arguments:
  1900. *
  1901. * pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
  1902. * ulPat - Solid color pattern
  1903. * pBuffer - Scan line buffer if needed
  1904. * Invert - XOR mask used on Src to determine whether to write
  1905. * through "1" pixels or "0" pixels
  1906. *
  1907. * Return Value:
  1908. *
  1909. * none
  1910. *
  1911. \**************************************************************************/
  1912. VOID
  1913. BltLnkPatMaskCopy4(
  1914. PBLTINFO pBltInfo,
  1915. ULONG ulPat,
  1916. PULONG pBuffer,
  1917. BYTE Invert
  1918. )
  1919. {
  1920. ULONG ulSrc;
  1921. ULONG cy = pBltInfo->cy;
  1922. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  1923. PBYTE pjDstTmp = pBltInfo->pjDst;
  1924. PBYTE pjSrc;
  1925. PBYTE pjDst;
  1926. ULONG ixSrc;
  1927. ULONG ixDst;
  1928. ULONG jDst = 0;
  1929. ULONG jDstNew = 0;
  1930. UCHAR ucPat0 = (UCHAR)ulPat & 0xF0;
  1931. UCHAR ucPat1 = (UCHAR)ulPat & 0x0F;
  1932. DONTUSE(pBuffer);
  1933. //
  1934. // for each scan line perform the transparency mask function
  1935. //
  1936. while(cy--)
  1937. {
  1938. PUCHAR pjDstEnd;
  1939. LONG xMask = 8 - (pBltInfo->xSrcStart & 0x0007);
  1940. UCHAR ucMask;
  1941. ixDst = pBltInfo->xDstStart;
  1942. pjSrc = pjSrcTmp + (pBltInfo->xSrcStart >> 3);
  1943. ucMask = (*pjSrc++ ^ Invert);
  1944. ulSrc = (ULONG)ucMask << (16 - xMask);
  1945. pjDst = pjDstTmp + (pBltInfo->xSrcStart >> 1);
  1946. pjDstEnd = pjDst + pBltInfo->cx;
  1947. //
  1948. // write partial nibble if needed
  1949. //
  1950. if ((ULONG_PTR)pjDst & 0x01)
  1951. {
  1952. if (!(ulSrc & 0x8000))
  1953. {
  1954. *pjDst = (*pjDst & 0xf0) | ucPat1;
  1955. }
  1956. pjDst++;
  1957. ulSrc <<=1;
  1958. xMask--;
  1959. }
  1960. //
  1961. // aligned 2-byte stores
  1962. //
  1963. while (pjDst < (pjDstEnd - 1))
  1964. {
  1965. //
  1966. // Need a new mask byte?
  1967. //
  1968. if (xMask < 2)
  1969. {
  1970. ucMask = (*pjSrc++ ^ Invert);
  1971. ulSrc |= ucMask << (8 - xMask);
  1972. xMask += 8;
  1973. }
  1974. //
  1975. // 2-nibble aligned store
  1976. //
  1977. switch (ulSrc & 0xc000)
  1978. {
  1979. case 0x0:
  1980. //
  1981. // write both
  1982. //
  1983. *pjDst = (UCHAR)ulPat;
  1984. break;
  1985. case 0x8000:
  1986. //
  1987. // don't write 0, write 1
  1988. //
  1989. *pjDst = (*pjDst & 0xf0) | ucPat1;
  1990. break;
  1991. case 0x4000:
  1992. //
  1993. // write 0, don't write 1
  1994. //
  1995. *pjDst = (*pjDst & 0x0f) | ucPat0;
  1996. break;
  1997. //
  1998. // case c000 does not draw anything
  1999. //
  2000. }
  2001. pjDst++;
  2002. ulSrc <<=2;
  2003. xMask -= 2;
  2004. }
  2005. //
  2006. // check if a partial jDst needs to be stored
  2007. //
  2008. if ((pjDst != pjDstEnd) && (!(ulSrc & 0x8000)))
  2009. {
  2010. *pjDst = (*pjDst & 0x0f) | ucPat0;
  2011. }
  2012. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  2013. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  2014. }
  2015. return;
  2016. }
  2017. /******************************Public*Routine******************************\
  2018. * Routine Name:
  2019. *
  2020. * BltLnkPatMaskCopy8
  2021. *
  2022. * Routine Description:
  2023. *
  2024. * Transparent Color Expansion to 8bpp
  2025. *
  2026. * Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
  2027. * to Dst. Where src is 1, leave Dst unchanged.
  2028. *
  2029. * Arguments:
  2030. *
  2031. * pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
  2032. * ulPat - Solid color pattern
  2033. * pBuffer - Scan line buffer if needed
  2034. * Invert - XOR mask used on Src to determine whether to write
  2035. * through "1" pixels or "0" pixels
  2036. *
  2037. * Return Value:
  2038. *
  2039. * none
  2040. *
  2041. \**************************************************************************/
  2042. VOID
  2043. BltLnkPatMaskCopy8 (
  2044. PBLTINFO pBltInfo,
  2045. ULONG ulPat,
  2046. PULONG pBuffer,
  2047. BYTE Invert
  2048. )
  2049. {
  2050. ULONG jMsk = 0;
  2051. LONG ixSrc;
  2052. LONG icx;
  2053. LONG cx;
  2054. ULONG cy = pBltInfo->cy;
  2055. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  2056. PBYTE pjDstTmp = pBltInfo->pjDst;
  2057. PBYTE pjSrc;
  2058. PBYTE pjDst;
  2059. ULONG icxDst;
  2060. DONTUSE(pBuffer);
  2061. while (cy--)
  2062. {
  2063. //
  2064. // for each scan line, first do the writes necessary to
  2065. // align ixSrc to zero, then operate on the
  2066. // Src 1 byte at a time (8 pixels) or cxSrc, whichever
  2067. // is less
  2068. //
  2069. //
  2070. // init loop params
  2071. //
  2072. cx = (LONG)pBltInfo->cx;
  2073. ixSrc = pBltInfo->xSrcStart;
  2074. pjSrc = pjSrcTmp;
  2075. pjDst = pjDstTmp + pBltInfo->xDstStart;
  2076. //
  2077. // finish the aligned scan line 8 mask bits at a time
  2078. //
  2079. while (cx > 0)
  2080. {
  2081. jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
  2082. //
  2083. // icx is the number of pixels left in the mask byte
  2084. //
  2085. icx = 8 - (ixSrc & 0x07);
  2086. //
  2087. // icx is the number of pixels to operate on with this mask byte.
  2088. // Must make sure that icx is less than cx, the number of pixels
  2089. // remaining in the blt. If icx is reduced because of
  2090. // cx, then jMsk must be shifted right to compensate.
  2091. //
  2092. icxDst = 0;
  2093. if (icx > cx) {
  2094. icxDst = icx - cx;
  2095. icx = cx;
  2096. }
  2097. //
  2098. // icxDst is now the number of pixels that can't be stored off
  2099. // the right side of the mask
  2100. //
  2101. // Bit 7 6 5 4 3 2 1 0
  2102. // ���������������Ŀ
  2103. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  2104. // ����������������� mask gets shifted right 2 to
  2105. //
  2106. //
  2107. // Bit 7 6 5 4 3 2 1 0
  2108. // ���������������Ŀ
  2109. // ixMsk� � �0�1�2�3�4�5�
  2110. // �����������������
  2111. //
  2112. // the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
  2113. // minus the number of pixels that can't be stored because cx
  2114. // runs out or because cxMsk runs out (icxDst)
  2115. //
  2116. cx -= icx;
  2117. ixSrc += icx;
  2118. if (jMsk != 0xFF) {
  2119. jMsk = jMsk >> icxDst;
  2120. switch (icx)
  2121. {
  2122. case 8:
  2123. if (!(jMsk & 0x01))
  2124. {
  2125. *(pjDst+7) = (BYTE)ulPat;
  2126. }
  2127. jMsk >>= 1;
  2128. case 7:
  2129. if (!(jMsk & 0x01))
  2130. {
  2131. *(pjDst+6) = (BYTE)ulPat;
  2132. }
  2133. jMsk >>= 1;
  2134. case 6:
  2135. if (!(jMsk & 0x01))
  2136. {
  2137. *(pjDst+5) = (BYTE)ulPat;
  2138. }
  2139. jMsk >>= 1;
  2140. case 5:
  2141. if (!(jMsk & 0x01))
  2142. {
  2143. *(pjDst+4) = (BYTE)ulPat;
  2144. }
  2145. jMsk >>= 1;
  2146. case 4:
  2147. if (!(jMsk & 0x01))
  2148. {
  2149. *(pjDst+3) = (BYTE)ulPat;
  2150. }
  2151. jMsk >>= 1;
  2152. case 3:
  2153. if (!(jMsk & 0x01))
  2154. {
  2155. *(pjDst+2) = (BYTE)ulPat;
  2156. }
  2157. jMsk >>= 1;
  2158. case 2:
  2159. if (!(jMsk & 0x01))
  2160. {
  2161. *(pjDst+1) = (BYTE)ulPat;
  2162. }
  2163. jMsk >>= 1;
  2164. case 1:
  2165. if (!(jMsk & 0x01))
  2166. {
  2167. *pjDst = (BYTE)ulPat;
  2168. }
  2169. }
  2170. }
  2171. pjDst += icx;
  2172. }
  2173. //
  2174. // increment 8 bpp Dst and 1 bpp Src to next scan line
  2175. //
  2176. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  2177. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  2178. }
  2179. }
  2180. /******************************Public*Routine******************************\
  2181. * Routine Name:
  2182. *
  2183. * BltLnkPatMaskCopy16
  2184. *
  2185. * Routine Description:
  2186. *
  2187. * Transparent Color Expansion to 16bpp
  2188. *
  2189. * Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
  2190. * to Dst. Where src is 1, leave Dst unchanged.
  2191. *
  2192. * Arguments:
  2193. *
  2194. * pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
  2195. * ulPat - Solid color pattern
  2196. * pBuffer - Scan line buffer if needed
  2197. * Invert - XOR mask used on Src to determine whether to write
  2198. * through "1" pixels or "0" pixels
  2199. *
  2200. * Return Value:
  2201. *
  2202. * none
  2203. *
  2204. \**************************************************************************/
  2205. VOID
  2206. BltLnkPatMaskCopy16 (
  2207. PBLTINFO pBltInfo,
  2208. ULONG ulPat,
  2209. PULONG pBuffer,
  2210. BYTE Invert
  2211. )
  2212. {
  2213. ULONG jMsk = 0;
  2214. LONG ixSrc;
  2215. LONG icx;
  2216. LONG cx;
  2217. ULONG cy = pBltInfo->cy;
  2218. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  2219. PUSHORT pusDstTmp = (PUSHORT)pBltInfo->pjDst;
  2220. PBYTE pjSrc;
  2221. PUSHORT pusDst;
  2222. ULONG icxDst;
  2223. DONTUSE(pBuffer);
  2224. while (cy--)
  2225. {
  2226. //
  2227. // for each scan line, first do the writes necessary to
  2228. // align ixSrc to zero, then operate on the
  2229. // Src 1 byte at a time (8 pixels) or cxSrc, whichever
  2230. // is less
  2231. //
  2232. //
  2233. // init loop params
  2234. //
  2235. cx = (LONG)pBltInfo->cx;
  2236. ixSrc = pBltInfo->xSrcStart;
  2237. pjSrc = pjSrcTmp;
  2238. pusDst = pusDstTmp + pBltInfo->xDstStart;
  2239. //
  2240. // load first mask byte if the mask is not aligned to 0
  2241. //
  2242. //
  2243. // finish the aligned scan line 8 mask bits at a time
  2244. //
  2245. while (cx > 0)
  2246. {
  2247. jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
  2248. //
  2249. // icx is the number of pixels left in the mask byte
  2250. //
  2251. icx = 8 - (ixSrc & 0x07);
  2252. //
  2253. // icx is the number of pixels to operate on with this mask byte.
  2254. // Must make sure that icx is less than cx, the number of pixels
  2255. // remaining in the blt. If icx is reduced because of
  2256. // cx, then jMsk must be shifted right to compensate.
  2257. //
  2258. icxDst = 0;
  2259. if (icx > cx) {
  2260. icxDst = icx - cx;
  2261. icx = cx;
  2262. }
  2263. //
  2264. // icxDst is now the number of pixels that can't be stored off
  2265. // the right side of the mask
  2266. //
  2267. // Bit 7 6 5 4 3 2 1 0
  2268. // ���������������Ŀ
  2269. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  2270. // ����������������� mask gets shifted right 2 to
  2271. //
  2272. //
  2273. // Bit 7 6 5 4 3 2 1 0
  2274. // ���������������Ŀ
  2275. // ixMsk� � �0�1�2�3�4�5�
  2276. // �����������������
  2277. //
  2278. //
  2279. //
  2280. // the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
  2281. // minus the number of pixels that can't be stored because cx
  2282. // runs out or because cxMsk runs out (icxDst)
  2283. //
  2284. cx -= icx;
  2285. ixSrc += icx;
  2286. if (jMsk != 0xFF) {
  2287. jMsk = jMsk >> icxDst;
  2288. switch (icx)
  2289. {
  2290. case 8:
  2291. if (!(jMsk & 0x01))
  2292. {
  2293. *(pusDst+7) = (USHORT)ulPat;
  2294. }
  2295. jMsk >>= 1;
  2296. case 7:
  2297. if (!(jMsk & 0x01))
  2298. {
  2299. *(pusDst+6) = (USHORT)ulPat;
  2300. }
  2301. jMsk >>= 1;
  2302. case 6:
  2303. if (!(jMsk & 0x01))
  2304. {
  2305. *(pusDst+5) = (USHORT)ulPat;
  2306. }
  2307. jMsk >>= 1;
  2308. case 5:
  2309. if (!(jMsk & 0x01))
  2310. {
  2311. *(pusDst+4) = (USHORT)ulPat;
  2312. }
  2313. jMsk >>= 1;
  2314. case 4:
  2315. if (!(jMsk & 0x01))
  2316. {
  2317. *(pusDst+3) = (USHORT)ulPat;
  2318. }
  2319. jMsk >>= 1;
  2320. case 3:
  2321. if (!(jMsk & 0x01))
  2322. {
  2323. *(pusDst+2) = (USHORT)ulPat;
  2324. }
  2325. jMsk >>= 1;
  2326. case 2:
  2327. if (!(jMsk & 0x01))
  2328. {
  2329. *(pusDst+1) = (USHORT)ulPat;
  2330. }
  2331. jMsk >>= 1;
  2332. case 1:
  2333. if (!(jMsk & 0x01))
  2334. {
  2335. *pusDst = (USHORT)ulPat;
  2336. }
  2337. }
  2338. }
  2339. pusDst += icx;
  2340. }
  2341. //
  2342. // increment 16 bpp Dst and 1 bpp Src to next scan line
  2343. //
  2344. pusDstTmp = (PUSHORT)((PBYTE)pusDstTmp + pBltInfo->lDeltaDst);
  2345. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  2346. }
  2347. }
  2348. /******************************Public*Routine******************************\
  2349. * Routine Name:
  2350. *
  2351. * BltLnkPatMaskCopy24
  2352. *
  2353. * Routine Description:
  2354. *
  2355. * Transparent Color Expansion to 24bpp
  2356. *
  2357. * Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
  2358. * to Dst. Where src is 1, leave Dst unchanged.
  2359. *
  2360. * Arguments:
  2361. *
  2362. * pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
  2363. * ulPat - Solid color pattern
  2364. * pBuffer - Scan line buffer if needed
  2365. * Invert - XOR mask used on Src to determine whether to write
  2366. * through "1" pixels or "0" pixels
  2367. *
  2368. * Return Value:
  2369. *
  2370. * none
  2371. *
  2372. \**************************************************************************/
  2373. VOID
  2374. BltLnkPatMaskCopy24 (
  2375. PBLTINFO pBltInfo,
  2376. ULONG ulPat,
  2377. PULONG pBuffer,
  2378. BYTE Invert
  2379. )
  2380. {
  2381. ULONG jMsk = 0;
  2382. LONG ixSrc;
  2383. LONG icx;
  2384. LONG cx;
  2385. ULONG cy = pBltInfo->cy;
  2386. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  2387. PBYTE pjDstTmp = pBltInfo->pjDst;
  2388. PBYTE pjSrc;
  2389. PBYTE pjDst;
  2390. ULONG icxDst;
  2391. BYTE jPat0 = (BYTE)ulPat;
  2392. BYTE jPat1 = (BYTE)(ulPat >> 8);
  2393. BYTE jPat2 = (BYTE)(ulPat >> 16);
  2394. DONTUSE(pBuffer);
  2395. while (cy--)
  2396. {
  2397. //
  2398. // for each scan line, first do the writes necessary to
  2399. // align ixSrc to zero, then operate on the
  2400. // Src 1 byte at a time (8 pixels) or cxSrc, whichever
  2401. // is less
  2402. //
  2403. //
  2404. // init loop params
  2405. //
  2406. cx = (LONG)pBltInfo->cx;
  2407. ixSrc = pBltInfo->xSrcStart;
  2408. pjSrc = pjSrcTmp;
  2409. pjDst = pjDstTmp + 3 * pBltInfo->xDstStart;
  2410. //
  2411. // finish the aligned scan line 8 mask bits at a time
  2412. //
  2413. while (cx > 0)
  2414. {
  2415. jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
  2416. //
  2417. // icx is the number of pixels left in the mask byte
  2418. //
  2419. icx = 8 - (ixSrc & 0x07);
  2420. //
  2421. // icx is the number of pixels to operate on with this mask byte.
  2422. // Must make sure that icx is less than cx, the number of pixels
  2423. // remaining in the blt. If icx is reduced because of
  2424. // cx, then jMsk must be shifted right to compensate.
  2425. //
  2426. icxDst = 0;
  2427. if (icx > cx) {
  2428. icxDst = icx - cx;
  2429. icx = cx;
  2430. }
  2431. //
  2432. // icxDst is now the number of pixels that can't be stored off
  2433. // the right side of the mask
  2434. //
  2435. // Bit 7 6 5 4 3 2 1 0
  2436. // ���������������Ŀ
  2437. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  2438. // ����������������� mask gets shifted right 2 to
  2439. //
  2440. //
  2441. // Bit 7 6 5 4 3 2 1 0
  2442. // ���������������Ŀ
  2443. // ixMsk� � �0�1�2�3�4�5�
  2444. // �����������������
  2445. //
  2446. //
  2447. // the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
  2448. // minus the number of pixels that can't be stored because cx
  2449. // runs out or because cxMsk runs out (icxDst)
  2450. //
  2451. cx -= icx;
  2452. ixSrc += icx;
  2453. if (jMsk != 0xFF) {
  2454. jMsk = jMsk >> icxDst;
  2455. switch (icx)
  2456. {
  2457. case 8:
  2458. if (!(jMsk & 0x01))
  2459. {
  2460. *(pjDst+23) = (BYTE)jPat2;
  2461. *(pjDst+22) = (BYTE)jPat1;
  2462. *(pjDst+21) = (BYTE)jPat0;
  2463. }
  2464. jMsk >>= 1;
  2465. case 7:
  2466. if (!(jMsk & 0x01))
  2467. {
  2468. *(pjDst+20) = (BYTE)jPat2;
  2469. *(pjDst+19) = (BYTE)jPat1;
  2470. *(pjDst+18) = (BYTE)jPat0;
  2471. }
  2472. jMsk >>= 1;
  2473. case 6:
  2474. if (!(jMsk & 0x01))
  2475. {
  2476. *(pjDst+17) = (BYTE)jPat2;
  2477. *(pjDst+16) = (BYTE)jPat1;
  2478. *(pjDst+15) = (BYTE)jPat0;
  2479. }
  2480. jMsk >>= 1;
  2481. case 5:
  2482. if (!(jMsk & 0x01))
  2483. {
  2484. *(pjDst+14) = (BYTE)jPat2;
  2485. *(pjDst+13) = (BYTE)jPat1;
  2486. *(pjDst+12) = (BYTE)jPat0;
  2487. }
  2488. jMsk >>= 1;
  2489. case 4:
  2490. if (!(jMsk & 0x01))
  2491. {
  2492. *(pjDst+11) = (BYTE)jPat2;
  2493. *(pjDst+10) = (BYTE)jPat1;
  2494. *(pjDst+9) = (BYTE)jPat0;
  2495. }
  2496. jMsk >>= 1;
  2497. case 3:
  2498. if (!(jMsk & 0x01))
  2499. {
  2500. *(pjDst+8) = (BYTE)jPat2;
  2501. *(pjDst+7) = (BYTE)jPat1;
  2502. *(pjDst+6) = (BYTE)jPat0;
  2503. }
  2504. jMsk >>= 1;
  2505. case 2:
  2506. if (!(jMsk & 0x01))
  2507. {
  2508. *(pjDst+5) = (BYTE)jPat2;
  2509. *(pjDst+4) = (BYTE)jPat1;
  2510. *(pjDst+3) = (BYTE)jPat0;
  2511. }
  2512. jMsk >>= 1;
  2513. case 1:
  2514. if (!(jMsk & 0x01))
  2515. {
  2516. *(pjDst+2) = (BYTE)jPat2;
  2517. *(pjDst+1) = (BYTE)jPat1;
  2518. *pjDst = (BYTE)jPat0;
  2519. }
  2520. }
  2521. }
  2522. pjDst += icx * 3;
  2523. }
  2524. //
  2525. // increment 24 bpp Dst and 1 bpp Src to next scan line
  2526. //
  2527. pjDstTmp = pjDstTmp + pBltInfo->lDeltaDst;
  2528. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  2529. }
  2530. }
  2531. /******************************Public*Routine******************************\
  2532. * Routine Name:
  2533. *
  2534. * BltLnkPatMaskCopy32
  2535. *
  2536. * Routine Description:
  2537. *
  2538. * Transparent Color Expansion to 32bpp
  2539. *
  2540. * Src is a 1 Bpp mask, where src is 0, copy 1 pixel solid color
  2541. * to Dst. Where src is 1, leave Dst unchanged.
  2542. *
  2543. * Arguments:
  2544. *
  2545. * pBltInfo - Pointer to BLTINFO structure containing Dst and Src information
  2546. * ulPat - Solid color pattern
  2547. * pBuffer - Scan line buffer if needed
  2548. * Invert - XOR mask used on Src to determine whether to write
  2549. * through "1" pixels or "0" pixels
  2550. *
  2551. * Return Value:
  2552. *
  2553. * none
  2554. *
  2555. \**************************************************************************/
  2556. VOID
  2557. BltLnkPatMaskCopy32 (
  2558. PBLTINFO pBltInfo,
  2559. ULONG ulPat,
  2560. PULONG pBuffer,
  2561. BYTE Invert
  2562. )
  2563. {
  2564. ULONG jMsk = 0;
  2565. LONG ixSrc;
  2566. LONG icx;
  2567. LONG cx;
  2568. ULONG cy = pBltInfo->cy;
  2569. PBYTE pjSrcTmp = pBltInfo->pjSrc;
  2570. PULONG pulDstTmp = (PULONG)pBltInfo->pjDst;
  2571. PBYTE pjSrc;
  2572. PULONG pulDst;
  2573. ULONG icxDst;
  2574. DONTUSE(pBuffer);
  2575. while (cy--)
  2576. {
  2577. //
  2578. // for each scan line, first do the writes necessary to
  2579. // align ixSrc to zero, then operate on the
  2580. // Src 1 byte at a time (8 pixels) or cxSrc, whichever
  2581. // is less
  2582. //
  2583. //
  2584. // init loop params
  2585. //
  2586. cx = (LONG)pBltInfo->cx;
  2587. ixSrc = pBltInfo->xSrcStart;
  2588. pjSrc = pjSrcTmp;
  2589. pulDst = pulDstTmp + pBltInfo->xDstStart;
  2590. //
  2591. // finish the aligned scan line 8 mask bits at a time
  2592. //
  2593. while (cx > 0)
  2594. {
  2595. jMsk = (ULONG)pjSrc[ixSrc>>3] ^ Invert;
  2596. //
  2597. // icx is the number of pixels left in the mask byte
  2598. //
  2599. icx = 8 - (ixSrc & 0x07);
  2600. //
  2601. // icx is the number of pixels to operate on with this mask byte.
  2602. // Must make sure that icx is less than cx, the number of pixels
  2603. // remaining in the blt. If icx is reduced because of
  2604. // cx, then jMsk must be shifted right to compensate.
  2605. //
  2606. icxDst = 0;
  2607. if (icx > cx) {
  2608. icxDst = icx - cx;
  2609. icx = cx;
  2610. }
  2611. //
  2612. // icxDst is now the number of pixels that can't be stored off
  2613. // the right side of the mask
  2614. //
  2615. // Bit 7 6 5 4 3 2 1 0
  2616. // ���������������Ŀ
  2617. // ixMsk�0�1�2�3�4�5�6�7� if mask 7 and 6 can't be written, this
  2618. // ����������������� mask gets shifted right 2 to
  2619. //
  2620. //
  2621. // Bit 7 6 5 4 3 2 1 0
  2622. // ���������������Ŀ
  2623. // ixMsk� � �0�1�2�3�4�5�
  2624. // �����������������
  2625. //
  2626. //
  2627. //
  2628. // the number of mask bits valid = 8 minus the offset (ixSrc & 0x07)
  2629. // minus the number of pixels that can't be stored because cx
  2630. // runs out or because cxMsk runs out (icxDst)
  2631. //
  2632. cx -= icx;
  2633. ixSrc += icx;
  2634. if (jMsk != 0xFF) {
  2635. jMsk = jMsk >> icxDst;
  2636. switch (icx)
  2637. {
  2638. case 8:
  2639. if (!(jMsk & 0x01))
  2640. {
  2641. *(pulDst+7) = ulPat;
  2642. }
  2643. jMsk >>= 1;
  2644. case 7:
  2645. if (!(jMsk & 0x01))
  2646. {
  2647. *(pulDst+6) = ulPat;
  2648. }
  2649. jMsk >>= 1;
  2650. case 6:
  2651. if (!(jMsk & 0x01))
  2652. {
  2653. *(pulDst+5) = ulPat;
  2654. }
  2655. jMsk >>= 1;
  2656. case 5:
  2657. if (!(jMsk & 0x01))
  2658. {
  2659. *(pulDst+4) = ulPat;
  2660. }
  2661. jMsk >>= 1;
  2662. case 4:
  2663. if (!(jMsk & 0x01))
  2664. {
  2665. *(pulDst+3) = ulPat;
  2666. }
  2667. jMsk >>= 1;
  2668. case 3:
  2669. if (!(jMsk & 0x01))
  2670. {
  2671. *(pulDst+2) = ulPat;
  2672. }
  2673. jMsk >>= 1;
  2674. case 2:
  2675. if (!(jMsk & 0x01))
  2676. {
  2677. *(pulDst+1) = ulPat;
  2678. }
  2679. jMsk >>= 1;
  2680. case 1:
  2681. if (!(jMsk & 0x01))
  2682. {
  2683. *pulDst = ulPat;
  2684. }
  2685. }
  2686. }
  2687. pulDst += icx;
  2688. }
  2689. //
  2690. // increment 32 bpp Dst and 1 bpp Src to next scan line
  2691. //
  2692. pulDstTmp = (PULONG)((PBYTE)pulDstTmp + pBltInfo->lDeltaDst);
  2693. pjSrcTmp = pjSrcTmp + pBltInfo->lDeltaSrc;
  2694. }
  2695. }
  2696. /******************************Public*Routine******************************\
  2697. * Routine Name:
  2698. *
  2699. * BltLnkAccel6666
  2700. *
  2701. * Routine Description:
  2702. *
  2703. * Special case accelerator for 8bpp to 8bpp no translation ROP 6666
  2704. * D = S xor D
  2705. *
  2706. * Arguments:
  2707. *
  2708. * pjSrcStart - address of first src byte
  2709. * pjDstStart - address of first dst byte
  2710. * lDeltaSrcDir - delta address for src scan lines
  2711. * lDeltaDstDir - delta address for dst scan lines
  2712. * cx - pixels per scan line
  2713. * cy - number of scan lines
  2714. *
  2715. * Return Value:
  2716. *
  2717. * none
  2718. *
  2719. \**************************************************************************/
  2720. VOID
  2721. BltLnkAccel6666 (
  2722. PBYTE pjSrcStart,
  2723. PBYTE pjDstStart,
  2724. LONG lDeltaSrcDir,
  2725. LONG lDeltaDstDir,
  2726. LONG cx,
  2727. LONG cy
  2728. )
  2729. {
  2730. //
  2731. // ROP 6666 8Bpp
  2732. //
  2733. ULONG ulCx4 = cx >> 2;
  2734. ULONG ulCxOdd = cx & 0x03;
  2735. ULONG ulCxTemp;
  2736. ULONG ulSrc;
  2737. PBYTE pjSrc;
  2738. PBYTE pjDst;
  2739. while(cy--)
  2740. {
  2741. pjSrc = pjSrcStart;
  2742. pjDst = pjDstStart;
  2743. //
  2744. // NOTE PERF: We can have the loop handle dword aligned pels and
  2745. // take care of the non-aligned head/tail separately.
  2746. //
  2747. for (ulCxTemp = ulCx4; ulCxTemp > 0; ulCxTemp--)
  2748. {
  2749. ulSrc = *UNALIGNED_DWORD_POINTER(pjSrc);
  2750. if (ulSrc != 0) {
  2751. *UNALIGNED_DWORD_POINTER(pjDst) ^= ulSrc;
  2752. }
  2753. pjSrc += 4;
  2754. pjDst += 4;
  2755. }
  2756. for (ulCxTemp = ulCxOdd; ulCxTemp > 0; ulCxTemp--)
  2757. {
  2758. *pjDst++ ^= *pjSrc++;
  2759. }
  2760. pjDstStart = pjDstStart + lDeltaDstDir;
  2761. pjSrcStart = pjSrcStart + lDeltaSrcDir;
  2762. }
  2763. }
  2764. /******************************Public*Routine******************************\
  2765. * Routine Name:
  2766. *
  2767. * BltLnkAccel8888
  2768. *
  2769. * Routine Description:
  2770. *
  2771. * Special case accelerator for 8bpp to 8bpp no translation ROP 8888
  2772. * D = S and D
  2773. *
  2774. * Arguments:
  2775. *
  2776. * pjSrcStart - address of first src byte
  2777. * pjDstStart - address of first dst byte
  2778. * lDeltaSrcDir - delta address for src scan lines
  2779. * lDeltaDstDir - delta address for dst scan lines
  2780. * cx - pixels per scan line
  2781. * cy - number of scan lines
  2782. *
  2783. * Return Value:
  2784. *
  2785. * none
  2786. *
  2787. \**************************************************************************/
  2788. VOID
  2789. BltLnkAccel8888(
  2790. PBYTE pjSrcStart,
  2791. PBYTE pjDstStart,
  2792. LONG lDeltaSrcDir,
  2793. LONG lDeltaDstDir,
  2794. LONG cx,
  2795. LONG cy
  2796. )
  2797. {
  2798. //
  2799. // With no translation, we can go a dword at a time and really
  2800. // fly
  2801. //
  2802. ULONG ulCx4 = cx >> 2;
  2803. ULONG ulCxOdd = cx & 0x03;
  2804. ULONG ulCxTemp;
  2805. ULONG ulSrc;
  2806. PBYTE pjSrc;
  2807. PBYTE pjDst;
  2808. while(cy--)
  2809. {
  2810. pjSrc = pjSrcStart;
  2811. pjDst = pjDstStart;
  2812. //
  2813. // NOTE PERF: We can have the loop handle dword aligned pels and
  2814. // take care of the non-aligned head/tail separately.
  2815. // We could also special-case source 0 and 0xFF to avoid
  2816. // unnecessary reads and writes
  2817. //
  2818. for (ulCxTemp = ulCx4; ulCxTemp > 0; ulCxTemp--)
  2819. {
  2820. ulSrc = *UNALIGNED_DWORD_POINTER(pjSrc);
  2821. if (ulSrc != ~0) {
  2822. if (ulSrc == 0) {
  2823. *UNALIGNED_DWORD_POINTER(pjDst) = 0;
  2824. } else {
  2825. *UNALIGNED_DWORD_POINTER(pjDst) &= ulSrc;
  2826. }
  2827. }
  2828. pjSrc += 4;
  2829. pjDst += 4;
  2830. }
  2831. for (ulCxTemp = ulCxOdd; ulCxTemp > 0; ulCxTemp--)
  2832. {
  2833. *pjDst++ &= *pjSrc++;
  2834. }
  2835. pjDstStart = pjDstStart + lDeltaDstDir;
  2836. pjSrcStart = pjSrcStart + lDeltaSrcDir;
  2837. }
  2838. return;
  2839. }
  2840. /******************************Public*Routine******************************\
  2841. * Routine Name:
  2842. *
  2843. * BltLnkAccelEEEE
  2844. *
  2845. * Routine Description:
  2846. *
  2847. * Special case accelerator for 8bpp to 8bpp no translation ROP EEEE7
  2848. * D = S or D
  2849. *
  2850. * Arguments:
  2851. *
  2852. * pjSrcStart - address of first src byte
  2853. * pjDstStart - address of first dst byte
  2854. * lDeltaSrcDir - delta address for src scan lines
  2855. * lDeltaDstDir - delta address for dst scan lines
  2856. * cx - pixels per scan line
  2857. * cy - number of scan lines
  2858. *
  2859. * Return Value:
  2860. *
  2861. * none
  2862. *
  2863. \**************************************************************************/
  2864. VOID
  2865. BltLnkAccelEEEE (
  2866. PBYTE pjSrcStart,
  2867. PBYTE pjDstStart,
  2868. LONG lDeltaSrcDir,
  2869. LONG lDeltaDstDir,
  2870. LONG cx,
  2871. LONG cy
  2872. )
  2873. {
  2874. //
  2875. // With no translation, we can go a dword at a time and really
  2876. // fly
  2877. //
  2878. ULONG ulCx4 = cx >> 2;
  2879. ULONG ulCxOdd = cx & 0x03;
  2880. ULONG ulCxTemp;
  2881. ULONG ulSrc;
  2882. PBYTE pjSrc;
  2883. PBYTE pjDst;
  2884. while(cy--)
  2885. {
  2886. pjSrc = pjSrcStart;
  2887. pjDst = pjDstStart;
  2888. //
  2889. // NOTE PERF: We can have the loop handle dword aligned pels and
  2890. // take care of the non-dword-aligned pels separately.
  2891. // We could also special-case source 0 and 0xFF to avoid
  2892. // unnecessary reads and writes
  2893. //
  2894. for (ulCxTemp = ulCx4; ulCxTemp > 0; ulCxTemp--)
  2895. {
  2896. ulSrc = *UNALIGNED_DWORD_POINTER(pjSrc);
  2897. if (ulSrc != 0) {
  2898. if (ulSrc == ~0) {
  2899. *UNALIGNED_DWORD_POINTER(pjDst) = 0xffffffff;
  2900. } else {
  2901. *UNALIGNED_DWORD_POINTER(pjDst) |= ulSrc;
  2902. }
  2903. }
  2904. pjSrc += 4;
  2905. pjDst += 4;
  2906. }
  2907. for (ulCxTemp = ulCxOdd; ulCxTemp > 0; ulCxTemp--)
  2908. {
  2909. *pjDst++ |= *pjSrc++;
  2910. }
  2911. pjDstStart = pjDstStart + lDeltaDstDir;
  2912. pjSrcStart = pjSrcStart + lDeltaSrcDir;
  2913. }
  2914. }