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.

3498 lines
111 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: maskblt.cxx
  3. *
  4. * This contains the blting API functions.
  5. *
  6. * Created: 25-Apr-1991 11:35:16
  7. * Author: Patrick Haluptzok patrickh
  8. *
  9. * Copyright (c) 1991-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. /******************************Public*Data*********************************\
  13. * MIX translation table
  14. *
  15. * Translates a mix 1-16, into an old style Rop 0-255.
  16. *
  17. * History:
  18. * 07-Sep-1991 -by- Patrick Haluptzok patrickh
  19. * Added it as a global table for the Engine.
  20. \**************************************************************************/
  21. BYTE gaMix[] =
  22. {
  23. 0xFF, // R2_WHITE - This is so you can do: Rop = gaMix[mix & 0x0F]
  24. 0x00, // R2_BLACK
  25. 0x05, // R2_NOTMERGEPEN
  26. 0x0A, // R2_MASKNOTPEN
  27. 0x0F, // R2_NOTCOPYPEN
  28. 0x50, // R2_MASKPENNOT
  29. 0x55, // R2_NOT
  30. 0x5A, // R2_XORPEN
  31. 0x5F, // R2_NOTMASKPEN
  32. 0xA0, // R2_MASKPEN
  33. 0xA5, // R2_NOTXORPEN
  34. 0xAA, // R2_NOP
  35. 0xAF, // R2_MERGENOTPEN
  36. 0xF0, // R2_COPYPEN
  37. 0xF5, // R2_MERGEPENNOT
  38. 0xFA, // R2_MERGEPEN
  39. 0xFF // R2_WHITE
  40. };
  41. /******************************Public*Data*********************************\
  42. * ROP3 translation table
  43. *
  44. * Translates the usual ternary rop into A-vector notation. Each bit in
  45. * this new notation corresponds to a term in a polynomial translation of
  46. * the rop.
  47. *
  48. * Rop(D,S,P) = a + a D + a S + a P + a DS + a DP + a SP + a DSP
  49. * 0 d s p ds dp sp dsp
  50. *
  51. * History:
  52. * Wed 22-Aug-1990 16:51:16 -by- Charles Whitmer [chuckwh]
  53. * Added it as a global table for the Engine.
  54. \**************************************************************************/
  55. BYTE gajRop3[] =
  56. {
  57. 0x00, 0xff, 0xb2, 0x4d, 0xd4, 0x2b, 0x66, 0x99,
  58. 0x90, 0x6f, 0x22, 0xdd, 0x44, 0xbb, 0xf6, 0x09,
  59. 0xe8, 0x17, 0x5a, 0xa5, 0x3c, 0xc3, 0x8e, 0x71,
  60. 0x78, 0x87, 0xca, 0x35, 0xac, 0x53, 0x1e, 0xe1,
  61. 0xa0, 0x5f, 0x12, 0xed, 0x74, 0x8b, 0xc6, 0x39,
  62. 0x30, 0xcf, 0x82, 0x7d, 0xe4, 0x1b, 0x56, 0xa9,
  63. 0x48, 0xb7, 0xfa, 0x05, 0x9c, 0x63, 0x2e, 0xd1,
  64. 0xd8, 0x27, 0x6a, 0x95, 0x0c, 0xf3, 0xbe, 0x41,
  65. 0xc0, 0x3f, 0x72, 0x8d, 0x14, 0xeb, 0xa6, 0x59,
  66. 0x50, 0xaf, 0xe2, 0x1d, 0x84, 0x7b, 0x36, 0xc9,
  67. 0x28, 0xd7, 0x9a, 0x65, 0xfc, 0x03, 0x4e, 0xb1,
  68. 0xb8, 0x47, 0x0a, 0xf5, 0x6c, 0x93, 0xde, 0x21,
  69. 0x60, 0x9f, 0xd2, 0x2d, 0xb4, 0x4b, 0x06, 0xf9,
  70. 0xf0, 0x0f, 0x42, 0xbd, 0x24, 0xdb, 0x96, 0x69,
  71. 0x88, 0x77, 0x3a, 0xc5, 0x5c, 0xa3, 0xee, 0x11,
  72. 0x18, 0xe7, 0xaa, 0x55, 0xcc, 0x33, 0x7e, 0x81,
  73. 0x80, 0x7f, 0x32, 0xcd, 0x54, 0xab, 0xe6, 0x19,
  74. 0x10, 0xef, 0xa2, 0x5d, 0xc4, 0x3b, 0x76, 0x89,
  75. 0x68, 0x97, 0xda, 0x25, 0xbc, 0x43, 0x0e, 0xf1,
  76. 0xf8, 0x07, 0x4a, 0xb5, 0x2c, 0xd3, 0x9e, 0x61,
  77. 0x20, 0xdf, 0x92, 0x6d, 0xf4, 0x0b, 0x46, 0xb9,
  78. 0xb0, 0x4f, 0x02, 0xfd, 0x64, 0x9b, 0xd6, 0x29,
  79. 0xc8, 0x37, 0x7a, 0x85, 0x1c, 0xe3, 0xae, 0x51,
  80. 0x58, 0xa7, 0xea, 0x15, 0x8c, 0x73, 0x3e, 0xc1,
  81. 0x40, 0xbf, 0xf2, 0x0d, 0x94, 0x6b, 0x26, 0xd9,
  82. 0xd0, 0x2f, 0x62, 0x9d, 0x04, 0xfb, 0xb6, 0x49,
  83. 0xa8, 0x57, 0x1a, 0xe5, 0x7c, 0x83, 0xce, 0x31,
  84. 0x38, 0xc7, 0x8a, 0x75, 0xec, 0x13, 0x5e, 0xa1,
  85. 0xe0, 0x1f, 0x52, 0xad, 0x34, 0xcb, 0x86, 0x79,
  86. 0x70, 0x8f, 0xc2, 0x3d, 0xa4, 0x5b, 0x16, 0xe9,
  87. 0x08, 0xf7, 0xba, 0x45, 0xdc, 0x23, 0x6e, 0x91,
  88. 0x98, 0x67, 0x2a, 0xd5, 0x4c, 0xb3, 0xfe, 0x01
  89. };
  90. /******************************Public*Routine******************************\
  91. * GrePatBltLockedDC
  92. *
  93. * This routine is called by PatBlt,PolyPatBlt, and queued PatBlt once the
  94. * dc is locked, the devlock is owned and all parameters are captured.
  95. *
  96. * Arguments:
  97. *
  98. * dcoDst - reference to locked DC object
  99. * prclDst - destination rect in screen coords
  100. * xoDst - reference to xlate object
  101. * rop4 - raster op
  102. * pSurfDst - pointer to dst surface
  103. *
  104. * Return Value:
  105. *
  106. * bool status
  107. *
  108. * History:
  109. *
  110. * 21-Aug-1995 -by- Mark Enstrom [marke]
  111. *
  112. \**************************************************************************/
  113. BOOL
  114. GrePatBltLockedDC(
  115. XDCOBJ &dcoDst,
  116. EXFORMOBJ &xoDst,
  117. ERECTL *prclDst,
  118. DWORD rop4,
  119. SURFACE *pSurfDst,
  120. COLORREF crTextColor,
  121. COLORREF crBackColor,
  122. ULONG ulTextColor,
  123. ULONG ulBackColor
  124. )
  125. {
  126. BOOL bReturn = TRUE; // return true if it is just clipped
  127. ECLIPOBJ *pco = NULL;
  128. if (dcoDst.bDisplay() && !dcoDst.bRedirection() && !UserScreenAccessCheck())
  129. {
  130. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  131. return (FALSE);
  132. }
  133. //
  134. // Same as GreMaskblt, bail out
  135. // if the dest DC has a stock bitmap
  136. //
  137. ASSERTGDI(!dcoDst.bStockBitmap(), "GrePatBltLockedDC dst stock bitmap\n");
  138. if (dcoDst.bStockBitmap())
  139. {
  140. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  141. return FALSE;
  142. }
  143. //
  144. // This is a expression to save a return in here.
  145. // Basically pco can be NULL if the rect is completely in the
  146. // cached rect in the DC or if we set up a clip object that isn't empty.
  147. //
  148. // it is possible for the coordinates to wrap after adding in the origin
  149. // so we need to check that the rectangle is still well ordered. If not,
  150. // we just fail since the result would be a blt going the opposite direction
  151. // as intended.
  152. //
  153. *prclDst += dcoDst.eptlOrigin();
  154. if (
  155. (
  156. (prclDst->left < prclDst->right) &&
  157. (prclDst->top < prclDst->bottom)
  158. ) &&
  159. (
  160. (
  161. (prclDst->left >= dcoDst.prclClip()->left) &&
  162. (prclDst->right <= dcoDst.prclClip()->right) &&
  163. (prclDst->top >= dcoDst.prclClip()->top) &&
  164. (prclDst->bottom <= dcoDst.prclClip()->bottom)
  165. ) ||
  166. (
  167. pco = dcoDst.pco(),
  168. pco->vSetup(dcoDst.prgnEffRao(), *prclDst,CLIP_NOFORCETRIV),
  169. *prclDst = pco->erclExclude(),
  170. (!prclDst->bEmpty())
  171. )
  172. )
  173. )
  174. {
  175. EBRUSHOBJ *pboFill;
  176. if ((((rop4 << 4) ^ rop4) & 0x00F0) != 0)
  177. {
  178. pboFill = dcoDst.peboFill();
  179. if (
  180. (dcoDst.ulDirty() & DIRTY_FILL) ||
  181. (dcoDst.pdc->flbrush() & DIRTY_FILL) ||
  182. (pboFill->bCareAboutFg() && (pboFill->crCurrentText() != crTextColor)) ||
  183. (pboFill->bCareAboutBg() && (pboFill->crCurrentBack() != crBackColor))
  184. )
  185. {
  186. COLORREF crTextColorOld = dcoDst.pdc->crTextClr();
  187. COLORREF crBackColorOld = dcoDst.pdc->crBackClr();
  188. ULONG ulTextColorOld = dcoDst.pdc->ulTextClr();
  189. ULONG ulBackColorOld = dcoDst.pdc->ulBackClr();
  190. dcoDst.ulDirtySub(DIRTY_FILL);
  191. dcoDst.pdc->flbrushSub(DIRTY_FILL);
  192. XEPALOBJ palDst(pSurfDst->ppal());
  193. XEPALOBJ palDstDC(dcoDst.ppal());
  194. // batched Textcolor and Bkcolor, need to be restored
  195. dcoDst.pdc->crTextClr(crTextColor);
  196. dcoDst.pdc->crBackClr(crBackColor);
  197. dcoDst.pdc->ulTextClr(ulTextColor);
  198. dcoDst.pdc->ulBackClr(ulBackColor);
  199. pboFill->vInitBrush(dcoDst.pdc,
  200. dcoDst.pdc->pbrushFill(),
  201. palDstDC,
  202. palDst,
  203. pSurfDst);
  204. dcoDst.pdc->crTextClr(crTextColorOld);
  205. dcoDst.pdc->crBackClr(crBackColorOld);
  206. dcoDst.pdc->ulTextClr(ulTextColorOld);
  207. dcoDst.pdc->ulBackClr(ulBackColorOld);
  208. }
  209. }
  210. else
  211. {
  212. pboFill = NULL;
  213. }
  214. DEVEXCLUDEOBJ dxo(dcoDst,prclDst,pco);
  215. //
  216. // Inc the target surface uniqueness
  217. //
  218. INC_SURF_UNIQ(pSurfDst);
  219. //
  220. // Dispatch the call.
  221. //
  222. bReturn = (*(pSurfDst->pfnBitBlt()))
  223. (
  224. pSurfDst->pSurfobj(),
  225. (SURFOBJ *) NULL,
  226. (SURFOBJ *) NULL,
  227. pco,
  228. NULL,
  229. prclDst,
  230. (POINTL *) NULL,
  231. (POINTL *) NULL,
  232. pboFill,
  233. &dcoDst.pdc->ptlFillOrigin(),
  234. rop4
  235. );
  236. }
  237. return(bReturn);
  238. }
  239. /******************************Public*Routine******************************\
  240. * NtGdiPatBlt
  241. *
  242. * Pattern Blting Output API.
  243. *
  244. * Arguments:
  245. *
  246. * hdcDst - Destination DC
  247. * x - Destination x position
  248. * y - Destination y position
  249. * cx - Destination width
  250. * cy - Destination height
  251. * rop4 - Destination raster operation
  252. *
  253. * Return Value:
  254. *
  255. * BOOL Status
  256. *
  257. \**************************************************************************/
  258. BOOL
  259. NtGdiPatBlt(
  260. HDC hdcDst,
  261. int x,
  262. int y,
  263. int cx,
  264. int cy,
  265. DWORD rop4
  266. )
  267. {
  268. GDITraceHandle(NtGdiPatBlt, "(%X, %d, %d, %d, %d, %X)\n", (va_list)&hdcDst,
  269. hdcDst);
  270. BOOL bReturn = FALSE;
  271. BOOL bLock = FALSE;
  272. PDC pdc;
  273. XDCOBJ dcoDst(hdcDst);
  274. //
  275. // Validate the destination DC.
  276. //
  277. if (dcoDst.bValid())
  278. {
  279. //
  280. // Process the rop for DDI, check for no source required.
  281. //
  282. rop4 = (rop4 >> 16) & 0x000000FF;
  283. rop4 = (rop4 << 8) | rop4;
  284. if ((((rop4 << 2) ^ rop4) & 0x00CC) == 0)
  285. {
  286. EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
  287. if (!xoDst.bRotation())
  288. {
  289. ERECTL erclDst(x,y,x+cx,y+cy);
  290. xoDst.bXform(erclDst);
  291. erclDst.vOrder();
  292. if (!erclDst.bEmpty())
  293. {
  294. //
  295. // Accumulate bounds. We can do this before knowing if the operation is
  296. // successful because bounds can be loose.
  297. //
  298. if (dcoDst.fjAccum())
  299. {
  300. dcoDst.vAccumulate(erclDst);
  301. }
  302. //
  303. // Lock the device and surface.
  304. //
  305. DEVLOCKOBJ dloTrg;
  306. if (dloTrg.bLock(dcoDst))
  307. {
  308. //
  309. // Check surface is included in DC.
  310. //
  311. SURFACE *pSurfDst = dcoDst.pSurface();
  312. if (pSurfDst != NULL)
  313. {
  314. ULONG ulDirty = dcoDst.pdc->ulDirty();
  315. if (ulDirty & DC_BRUSH_DIRTY)
  316. {
  317. GreDCSelectBrush (dcoDst.pdc, dcoDst.pdc->hbrush());
  318. }
  319. bReturn = GrePatBltLockedDC(dcoDst,
  320. xoDst,
  321. &erclDst,
  322. rop4,
  323. pSurfDst,
  324. dcoDst.pdc->crTextClr(),
  325. dcoDst.pdc->crBackClr(),
  326. dcoDst.pdc->ulTextClr(),
  327. dcoDst.pdc->ulBackClr()
  328. );
  329. }
  330. else
  331. {
  332. bReturn = TRUE;
  333. }
  334. }
  335. else
  336. {
  337. bReturn = dcoDst.bFullScreen();
  338. }
  339. }
  340. else
  341. {
  342. bReturn = TRUE;
  343. }
  344. }
  345. else
  346. {
  347. //
  348. // There is rotation involved - send it off to MaskBlt to handle it.
  349. //
  350. bReturn = GreMaskBlt(hdcDst, x, y, cx, cy, 0, 0, 0, 0, 0, 0, rop4 << 16, 0);
  351. }
  352. }
  353. else
  354. {
  355. WARNING1("ERROR PatBlt called with Rop requires Source or on invalid Dst\n");
  356. }
  357. //
  358. // Unlock DC
  359. //
  360. dcoDst.vUnlock();
  361. }
  362. else
  363. {
  364. WARNING1("ERORR PatBlt called on invalid DC\n");
  365. }
  366. return(bReturn);
  367. }
  368. /******************************Public*Routine******************************\
  369. * GrePolyPatBltInternal
  370. *
  371. * Arguments:
  372. *
  373. * dcoDst - Destination DC (locked)
  374. * rop4 - Destination raster op
  375. * pPolyPat - POLYPATBLT structure
  376. * Count - number of POLYPATBLTs
  377. * crTextClr - rext color
  378. * crBackClr - background color
  379. *
  380. * Return Value:
  381. *
  382. * status
  383. *
  384. * History:
  385. *
  386. * 18-May-1995 -by- Mark Enstrom [marke]
  387. *
  388. \**************************************************************************/
  389. BOOL
  390. GrePolyPatBltInternal(
  391. XDCOBJ &dcoDst,
  392. DWORD rop4,
  393. PPOLYPATBLT pPolyPat,
  394. DWORD Count,
  395. DWORD Mode,
  396. COLORREF crTextClr,
  397. COLORREF crBackClr,
  398. ULONG ulTextClr,
  399. ULONG ulBackClr
  400. )
  401. {
  402. GDITraceHandle(GrePolyPatBltInternal, "(dcoDst, %X, %p, %u, %X, %X, %X)\n",
  403. (va_list)&rop4, dcoDst.bValid() ? dcoDst.hdc() : NULL);
  404. BOOL bReturn = TRUE;
  405. //
  406. // validate input params
  407. //
  408. if ((Count != 0) && (pPolyPat != NULL) && (Mode == PPB_BRUSH))
  409. {
  410. //
  411. // Process the rop for DDI, check for no source required.
  412. //
  413. rop4 = (rop4 >> 16) & 0x000000FF;
  414. rop4 = (rop4 << 8) | rop4;
  415. if ((((rop4 << 2) ^ rop4) & 0x00CC) == 0)
  416. {
  417. //
  418. // Validate the destination DC
  419. //
  420. if (dcoDst.bValid())
  421. {
  422. HBRUSH hbrSave = dcoDst.pdc->hbrush();
  423. //
  424. // make sure brush is in sync in DC
  425. //
  426. if (dcoDst.pdc->ulDirty() & DC_BRUSH_DIRTY)
  427. {
  428. GreDCSelectBrush(dcoDst.pdc,hbrSave);
  429. }
  430. //
  431. // lock the device 1 time for all calls
  432. //
  433. DEVLOCKOBJ dloTrg;
  434. if (dloTrg.bLock(dcoDst))
  435. {
  436. EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
  437. SURFACE *pSurfDst = dcoDst.pSurface();
  438. while (Count--)
  439. {
  440. int x;
  441. int y;
  442. int cx;
  443. int cy;
  444. HBRUSH hbr;
  445. __try
  446. {
  447. x = pPolyPat->x;
  448. y = pPolyPat->y;
  449. cx = pPolyPat->cx;
  450. cy = pPolyPat->cy;
  451. hbr = pPolyPat->BrClr.hbr;
  452. }
  453. __except(EXCEPTION_EXECUTE_HANDLER)
  454. {
  455. bReturn = FALSE;
  456. //
  457. // must break out of while loop but restore brush
  458. //
  459. break;
  460. }
  461. GDITraceHandle(GrePolyPatBltInternal,
  462. " pPolyPat = { (%d, %d) - (%d, %d) }\n",
  463. (va_list)pPolyPat, dcoDst.hdc());
  464. //
  465. // select in brush for this patblt, remember old
  466. // brush for restore if needed
  467. //
  468. if (hbr != (HBRUSH)NULL)
  469. {
  470. GreDCSelectBrush(dcoDst.pdc, hbr);
  471. }
  472. if (!xoDst.bRotation())
  473. {
  474. ERECTL erclDst(x,y,x+cx,y+cy);
  475. xoDst.bXform(erclDst);
  476. erclDst.vOrder();
  477. if (!erclDst.bEmpty())
  478. {
  479. //
  480. // Accumulate bounds. We can do this before knowing if the operation is
  481. // successful because bounds can be loose.
  482. //
  483. if (dcoDst.fjAccum())
  484. {
  485. dcoDst.vAccumulate(erclDst);
  486. }
  487. //
  488. // Check surface is included in DC.
  489. //
  490. if (pSurfDst != NULL)
  491. {
  492. bReturn = GrePatBltLockedDC(dcoDst,
  493. xoDst,
  494. &erclDst,
  495. rop4,
  496. pSurfDst,
  497. crTextClr,
  498. crBackClr,
  499. ulTextClr,
  500. ulBackClr
  501. );
  502. }
  503. }
  504. }
  505. else
  506. {
  507. //
  508. // There is rotation involved - send it off to MaskBlt to handle it.
  509. //
  510. bReturn = GreMaskBlt((HDC)dcoDst.pdc->hHmgr, x, y, cx, cy, 0, 0, 0, 0, 0, 0, rop4 << 16, 0);
  511. }
  512. pPolyPat++;
  513. }
  514. }
  515. else
  516. {
  517. bReturn = dcoDst.bFullScreen();
  518. }
  519. //
  520. // make sure dc brush is restored
  521. //
  522. if (dcoDst.pdc->hbrush() != hbrSave)
  523. {
  524. dcoDst.pdc->hbrush(hbrSave);
  525. dcoDst.pdc->ulDirtyAdd(DC_BRUSH_DIRTY);
  526. }
  527. }
  528. else
  529. {
  530. WARNING1("ERORR PatBlt called on invalid DC\n");
  531. bReturn = FALSE;
  532. }
  533. }
  534. else
  535. {
  536. WARNING1("ERROR PatBlt called with Rop requires Source or on invalid Dst\n");
  537. bReturn = FALSE;
  538. }
  539. }
  540. else
  541. {
  542. if (Count != 0)
  543. {
  544. WARNING1("ERORR PolyPatBlt called with NULL pPolyPat\n");
  545. bReturn = FALSE;
  546. }
  547. }
  548. return(bReturn);
  549. }
  550. /******************************Public*Routine******************************\
  551. * NtGdiPolyPatBlt
  552. *
  553. * Arguments:
  554. *
  555. * hdcDst - Destination DC
  556. * rop4 - Destination raster op
  557. * pPolyPat - POLYPATBLT structure
  558. * Count - number of POLYPATBLTs
  559. *
  560. * Return Value:
  561. *
  562. * status
  563. *
  564. * History:
  565. *
  566. * 18-May-1995 -by- Mark Enstrom [marke]
  567. *
  568. \**************************************************************************/
  569. BOOL
  570. APIENTRY
  571. NtGdiPolyPatBlt(
  572. HDC hdc,
  573. DWORD rop4,
  574. PPOLYPATBLT pPoly,
  575. DWORD Count,
  576. DWORD Mode
  577. )
  578. {
  579. GDITraceHandle(NtGdiPolyPatBlt, "(%X, %X, %p, %u, %X)\n", (va_list)&hdc,
  580. hdc);
  581. BOOL bRet = TRUE;
  582. if (Count != 0)
  583. {
  584. if (pPoly != NULL)
  585. {
  586. XDCOBJ dcoDst(hdc);
  587. if (dcoDst.bValid())
  588. {
  589. //
  590. // Make sure length do not overflow.
  591. //
  592. // Note: using MAXULONG instead of MAXIMUM_POOL_ALLOC (or the
  593. // BALLOC_ macros) because we are not allocating memory.
  594. //
  595. if (Count <= (MAXULONG / sizeof(POLYPATBLT)))
  596. {
  597. __try
  598. {
  599. ProbeForRead(pPoly,sizeof(POLYPATBLT)*Count,sizeof(DWORD));
  600. }
  601. __except(EXCEPTION_EXECUTE_HANDLER)
  602. {
  603. WARNINGX(46);
  604. bRet = FALSE;
  605. }
  606. }
  607. else
  608. {
  609. bRet = FALSE;
  610. }
  611. if (bRet)
  612. {
  613. bRet = GrePolyPatBltInternal(dcoDst,
  614. rop4,
  615. pPoly,
  616. Count,
  617. Mode,
  618. dcoDst.pdc->crTextClr(),
  619. dcoDst.pdc->crBackClr(),
  620. dcoDst.pdc->ulTextClr(),
  621. dcoDst.pdc->ulBackClr());
  622. }
  623. dcoDst.vUnlockFast();
  624. }
  625. else
  626. {
  627. bRet = FALSE;
  628. EngSetLastError(ERROR_INVALID_HANDLE);
  629. }
  630. }
  631. else
  632. {
  633. bRet = FALSE;
  634. }
  635. }
  636. return(bRet);
  637. }
  638. /******************************Public*Routine******************************\
  639. * GrePolyPatBlt
  640. *
  641. * Arguments:
  642. *
  643. * hdcDst - Destination DC
  644. * rop4 - Destination raster op
  645. * pPolyPat - POLYPATBLT structure
  646. * Count - number of POLYPATBLTs
  647. * Mode - color mode
  648. *
  649. * Return Value:
  650. *
  651. * status
  652. *
  653. * History:
  654. *
  655. * 18-May-1995 -by- Mark Enstrom [marke]
  656. *
  657. \**************************************************************************/
  658. BOOL
  659. APIENTRY
  660. GrePolyPatBlt(
  661. HDC hdc,
  662. DWORD rop4,
  663. PPOLYPATBLT pPoly,
  664. DWORD Count,
  665. DWORD Mode
  666. )
  667. {
  668. GDITraceHandle(GrePolyPatBlt, "(%X, %X, %p, %u, %X)\n", (va_list)&hdc, hdc);
  669. XDCOBJ dcoDst(hdc);
  670. BOOL bRet = FALSE;
  671. if (dcoDst.bValid())
  672. {
  673. bRet = GrePolyPatBltInternal(dcoDst,
  674. rop4,
  675. pPoly,
  676. Count,
  677. Mode,
  678. dcoDst.pdc->crTextClr(),
  679. dcoDst.pdc->crBackClr(),
  680. dcoDst.pdc->ulTextClr(),
  681. dcoDst.pdc->ulBackClr());
  682. dcoDst.vUnlockFast();
  683. }
  684. else
  685. {
  686. EngSetLastError(ERROR_INVALID_HANDLE);
  687. }
  688. return(bRet);
  689. }
  690. /******************************Public*Routine******************************\
  691. * NtGdiFlushUserBatch
  692. *
  693. * Unbatch drawing calls (all to same DC so DC lock and
  694. * DEVLOCK and XFORMOBJ are same.
  695. *
  696. * Arguments:
  697. *
  698. * None
  699. *
  700. * Return Value:
  701. *
  702. * None
  703. *
  704. * History:
  705. *
  706. * 18-May-1995 -by- Mark Enstrom [marke]
  707. *
  708. \**************************************************************************/
  709. #if DBG_GDI_BATCH
  710. ULONG GdiBatchCounts[32];
  711. ULONG GdiBatchTypeCounts[8];
  712. ULONG SystemTable[4096];
  713. ULONG gClearTable = 1;
  714. #endif
  715. VOID
  716. NtGdiFlushUserBatch()
  717. {
  718. //
  719. // DBG_GDI_BATCH is never tuyrned on in a debug or free build, it
  720. // is a private measuring tool.
  721. //
  722. #if DBG_GDI_BATCH
  723. _asm
  724. {
  725. ;eax is the system service
  726. lea ebx, SystemTable
  727. and eax, 4096-1
  728. inc DWORD PTR[ebx + 4*eax]
  729. }
  730. #endif
  731. GDITrace(NtGdiFlushUserBatch, "", NULL);
  732. PTEB pteb = NtCurrentTeb();
  733. ULONG GdiBatchCount;
  734. PBYTE pGdiBatch;
  735. //
  736. // Non dc commands must be executed from batch
  737. // whether dc/dev locks succeed or not
  738. //
  739. BOOL bExecNonDCOnly = TRUE;
  740. #if DBG_GDI_BATCH
  741. if (gClearTable)
  742. {
  743. RtlZeroMemory(&SystemTable[0],4*4096);
  744. RtlZeroMemory(&GdiBatchCounts[0],4*32);
  745. RtlZeroMemory(&GdiBatchTypeCounts[0],4*8);
  746. gClearTable = 0;
  747. }
  748. #endif
  749. //
  750. // clear batch control
  751. //
  752. __try
  753. {
  754. GdiBatchCount = pteb->GdiBatchCount;
  755. pGdiBatch = (PBYTE)&pteb->GdiTebBatch.Buffer[0];
  756. pteb->GdiBatchCount = 0;
  757. pteb->GdiTebBatch.Offset = 0;
  758. }
  759. __except(EXCEPTION_EXECUTE_HANDLER)
  760. {
  761. return;
  762. }
  763. PBYTE pGdiBatchEnd = pGdiBatch + GDI_BATCH_SIZE;
  764. //
  765. // read batch once at start
  766. //
  767. if (
  768. (GdiBatchCount > 0) &&
  769. (GdiBatchCount < (GDI_BATCH_SIZE/4))
  770. )
  771. {
  772. HDC hdcDst = 0;
  773. __try
  774. {
  775. hdcDst = (HDC)pteb->GdiTebBatch.HDC;
  776. }
  777. __except(EXCEPTION_EXECUTE_HANDLER)
  778. {
  779. }
  780. if (hdcDst != NULL)
  781. {
  782. XDCOBJ dcoDst(hdcDst);
  783. //
  784. // Validate the destination DC.
  785. //
  786. if (dcoDst.bValid())
  787. {
  788. //
  789. // Stats
  790. //
  791. #if DBG_GDI_BATCH
  792. if (GdiBatchCount < 32)
  793. {
  794. GdiBatchCounts[GdiBatchCount]++;
  795. }
  796. #endif
  797. //
  798. // Lock the device.
  799. //
  800. DEVLOCKOBJ dloTrg;
  801. if (dloTrg.bLock(dcoDst))
  802. {
  803. //
  804. // execute all batch commands from DC loop
  805. //
  806. bExecNonDCOnly = FALSE;
  807. //
  808. // remember DC_ATTR hbr
  809. //
  810. HBRUSH hbrDCA = dcoDst.pdc->hbrush();
  811. do
  812. {
  813. //
  814. // Pull patblt off teb and execute. TEB is not safe
  815. // so all offsets must be checked to make sure no
  816. // corruption has occured.
  817. //
  818. ULONG GdiBatchType;
  819. ULONG GdiBatchLength;
  820. ULONG GdiBatchIncrement;
  821. BOOL bRead = TRUE;
  822. __try
  823. {
  824. GdiBatchType = ((PBATCHCOMMAND)pGdiBatch)->Type;
  825. GdiBatchLength = ((PBATCHCOMMAND)pGdiBatch)->Length;
  826. }
  827. __except(EXCEPTION_EXECUTE_HANDLER)
  828. {
  829. break;
  830. }
  831. if ((pGdiBatch + GdiBatchLength) > pGdiBatchEnd)
  832. {
  833. //
  834. // exit while loop
  835. //
  836. WARNING("Error in GDI TEB batch address");
  837. break;
  838. }
  839. //
  840. // performance measure
  841. //
  842. #if DBG_GDI_BATCH
  843. if (GdiBatchType <8)
  844. {
  845. GdiBatchTypeCounts[GdiBatchType]++;
  846. }
  847. #endif
  848. //
  849. // Check command type
  850. //
  851. switch (GdiBatchType)
  852. {
  853. //
  854. // execute ExtTextOut and ExtTextOutRect
  855. //
  856. case BatchTypeTextOut:
  857. case BatchTypeTextOutRect:
  858. {
  859. GreBatchTextOut(
  860. dcoDst,
  861. (PBATCHTEXTOUT)pGdiBatch,
  862. GdiBatchLength
  863. );
  864. }
  865. break;
  866. //
  867. // execute SelectClip
  868. //
  869. case BatchTypeSelectClip:
  870. {
  871. RECTL rclClip;
  872. int iMode;
  873. __try
  874. {
  875. rclClip = ((PBATCHSELECTCLIP)pGdiBatch)->rclClip;
  876. iMode = ((PBATCHSELECTCLIP)pGdiBatch)->iMode;
  877. }
  878. __except(EXCEPTION_EXECUTE_HANDLER)
  879. {
  880. bRead = FALSE;
  881. }
  882. if (bRead)
  883. {
  884. GreExtSelectClipRgnLocked(
  885. dcoDst,
  886. &rclClip,
  887. iMode);
  888. }
  889. }
  890. break;
  891. //
  892. // delete brush
  893. //
  894. case BatchTypeDeleteBrush:
  895. {
  896. HOBJ hObj;
  897. __try
  898. {
  899. hObj = (HOBJ)((PBATCHDELETEBRUSH)pGdiBatch)->hbrush;
  900. }
  901. __except(EXCEPTION_EXECUTE_HANDLER)
  902. {
  903. bRead = FALSE;
  904. }
  905. if (bRead)
  906. NtGdiDeleteObjectApp(hObj);
  907. }
  908. break;
  909. //
  910. // delete region
  911. //
  912. case BatchTypeDeleteRegion:
  913. {
  914. HOBJ hObj;
  915. __try
  916. {
  917. hObj = (HOBJ)((PBATCHDELETEREGION)pGdiBatch)->hregion;
  918. }
  919. __except(EXCEPTION_EXECUTE_HANDLER)
  920. {
  921. bRead = FALSE;
  922. }
  923. if (bRead)
  924. NtGdiDeleteObjectApp(hObj);
  925. }
  926. break;
  927. //
  928. // set brush origin
  929. //
  930. case BatchTypeSetBrushOrg:
  931. {
  932. int x, y;
  933. __try
  934. {
  935. x = ((PBATCHSETBRUSHORG)pGdiBatch)->x;
  936. y = ((PBATCHSETBRUSHORG)pGdiBatch)->y;
  937. }
  938. __except(EXCEPTION_EXECUTE_HANDLER)
  939. {
  940. bRead = FALSE;
  941. }
  942. if (bRead)
  943. dcoDst.pdc->ptlBrushOrigin(
  944. x,
  945. y
  946. );
  947. }
  948. break;
  949. case BatchTypeSelectFont:
  950. {
  951. HFONT hFont;
  952. __try
  953. {
  954. hFont = (HFONT)((PBATCHSELECTFONT)pGdiBatch)->hFont;
  955. }
  956. __except(EXCEPTION_EXECUTE_HANDLER)
  957. {
  958. bRead = FALSE;
  959. }
  960. if (bRead)
  961. GreSelectFont(hdcDst,
  962. hFont
  963. );
  964. }
  965. break;
  966. //
  967. // batched PolyPatBlt
  968. //
  969. case BatchTypePolyPatBlt:
  970. {
  971. PBATCHPOLYPATBLT pBatch;
  972. COLORREF crSaveDCBrushColor;
  973. COLORREF crBatchDCBrushColor;
  974. POINTL ptlViewportOrgSave;
  975. POINTL ptlBatchViewportOrg;
  976. ULONG ulSaveDCBrushColor;
  977. ULONG ulBatchDCBrushColor;
  978. ULONG Mode;
  979. ULONG TextColor, BackColor;
  980. ULONG ulTextColor, ulBackColor;
  981. pBatch = (PBATCHPOLYPATBLT)pGdiBatch;
  982. //
  983. // Pull count off the TEB, the data could be
  984. // overwritten so do all checking against the copy.
  985. //
  986. COUNT Count;
  987. COUNT cjBuffer = GdiBatchLength - offsetof(BATCHPOLYPATBLT, ulBuffer);
  988. __try
  989. {
  990. Count = pBatch->Count;
  991. }
  992. __except(EXCEPTION_EXECUTE_HANDLER)
  993. {
  994. break;
  995. }
  996. //
  997. // Validate pBatch->Count and size of
  998. // ulBuffer
  999. //
  1000. if ((Count < (MAXULONG / sizeof(POLYPATBLT))) &&
  1001. ((Count * sizeof(POLYPATBLT)) <= cjBuffer))
  1002. {
  1003. //
  1004. // Set the DCBrush Color
  1005. //
  1006. crSaveDCBrushColor = dcoDst.pdc->crDCBrushClr();
  1007. ulSaveDCBrushColor = dcoDst.pdc->ulDCBrushClr();
  1008. __try
  1009. {
  1010. Mode = pBatch->Mode;
  1011. TextColor = pBatch->TextColor;
  1012. BackColor = pBatch->BackColor;
  1013. ulTextColor = pBatch->ulTextColor;
  1014. ulBackColor = pBatch->ulBackColor;
  1015. crBatchDCBrushColor = pBatch->DCBrushColor;
  1016. ulBatchDCBrushColor = pBatch->ulDCBrushColor;
  1017. }
  1018. __except(EXCEPTION_EXECUTE_HANDLER)
  1019. {
  1020. break;
  1021. }
  1022. if (crSaveDCBrushColor != crBatchDCBrushColor)
  1023. {
  1024. dcoDst.pdc->crDCBrushClr(crBatchDCBrushColor);
  1025. dcoDst.pdc->ulDCBrushClr(ulBatchDCBrushColor);
  1026. dcoDst.pdc->ulDirtyAdd(DIRTY_FILL);
  1027. }
  1028. ptlViewportOrgSave = dcoDst.pdc->ptlViewportOrg();
  1029. __try
  1030. {
  1031. ptlBatchViewportOrg.x = pBatch->ptlViewportOrg.x;
  1032. ptlBatchViewportOrg.y = pBatch->ptlViewportOrg.y;
  1033. }
  1034. __except(EXCEPTION_EXECUTE_HANDLER)
  1035. {
  1036. break;
  1037. }
  1038. if ((ptlViewportOrgSave.x != ptlBatchViewportOrg.x) ||
  1039. (ptlViewportOrgSave.y != ptlBatchViewportOrg.y))
  1040. {
  1041. dcoDst.pdc->lViewportOrgX(ptlBatchViewportOrg.x);
  1042. dcoDst.pdc->lViewportOrgY(ptlBatchViewportOrg.y);
  1043. dcoDst.pdc->flSet_flXform(
  1044. PAGE_XLATE_CHANGED |
  1045. DEVICE_TO_WORLD_INVALID);
  1046. }
  1047. GrePolyPatBltInternal(
  1048. dcoDst,
  1049. pBatch->rop4,
  1050. (PPOLYPATBLT)&pBatch->ulBuffer[0],
  1051. Count,
  1052. Mode,
  1053. TextColor,
  1054. BackColor,
  1055. ulTextColor,
  1056. ulBackColor
  1057. );
  1058. //
  1059. // Restore the original DCBrush color
  1060. //
  1061. if (crSaveDCBrushColor != dcoDst.pdc->crDCBrushClr())
  1062. {
  1063. dcoDst.pdc->crDCBrushClr(crSaveDCBrushColor);
  1064. dcoDst.pdc->ulDCBrushClr(ulSaveDCBrushColor);
  1065. dcoDst.pdc->ulDirtyAdd(DIRTY_FILL);
  1066. }
  1067. if ((ptlViewportOrgSave.x != dcoDst.pdc->lViewportOrgX()) ||
  1068. (ptlViewportOrgSave.y != dcoDst.pdc->lViewportOrgY()))
  1069. {
  1070. dcoDst.pdc->lViewportOrgX(ptlViewportOrgSave.x);
  1071. dcoDst.pdc->lViewportOrgY(ptlViewportOrgSave.y);
  1072. dcoDst.pdc->flSet_flXform(
  1073. PAGE_XLATE_CHANGED |
  1074. DEVICE_TO_WORLD_INVALID);
  1075. }
  1076. }
  1077. else
  1078. {
  1079. WARNING1("ERROR PolyPatBlt batch overflow\n");
  1080. }
  1081. }
  1082. break;
  1083. //
  1084. // common path for PatBlt and BitBlt
  1085. //
  1086. case BatchTypePatBlt:
  1087. {
  1088. PBATCHPATBLT pBatchPpb = (PBATCHPATBLT)pGdiBatch;
  1089. GDITraceHandle2(NtGdiPatBlt, "-BATCH %8lX: (%ld, %ld), %ldx%ld, HBR %lX, rop %lX...\n", (va_list)pBatchPpb, hdcDst, pBatchPpb->hbr);
  1090. int x;
  1091. int y;
  1092. int cx;
  1093. int cy;
  1094. DWORD rop4;
  1095. ULONG TextColor, ulTextColor;
  1096. ULONG BackColor, ulBackColor;
  1097. __try
  1098. {
  1099. x = pBatchPpb->x;
  1100. y = pBatchPpb->y;
  1101. cx = pBatchPpb->cx;
  1102. cy = pBatchPpb->cy;
  1103. rop4 = pBatchPpb->rop4;
  1104. TextColor = pBatchPpb->TextColor;
  1105. BackColor = pBatchPpb->BackColor;
  1106. ulTextColor = pBatchPpb->ulTextColor;
  1107. ulBackColor = pBatchPpb->ulBackColor;
  1108. }
  1109. __except(EXCEPTION_EXECUTE_HANDLER)
  1110. {
  1111. break;
  1112. }
  1113. //
  1114. // Process the rop for DDI, check for no source required.
  1115. //
  1116. rop4 = (rop4 >> 16) & 0x000000FF;
  1117. rop4 = (rop4 << 8) | rop4;
  1118. //
  1119. // make sure command is a BitBlt or PatBlt with rop
  1120. // specifying no source required.
  1121. //
  1122. if ((((rop4 << 2) ^ rop4) & 0x00CC) == 0)
  1123. {
  1124. //
  1125. // get color information
  1126. //
  1127. HBRUSH hbrBatch,
  1128. hbrSave = dcoDst.pdc->hbrush();
  1129. COLORREF crSaveDCBrushColor,
  1130. crSaveIcmBrushColor,
  1131. crBatchDCBrushColor,
  1132. crBatchIcmBrushColor;
  1133. BOOL bIcmBrush = FALSE;
  1134. POINTL ptlViewportOrgSave;
  1135. POINTL ptlBatchViewportOrg;
  1136. ULONG ulSaveDCBrushColor;
  1137. ULONG ulBatchDCBrushColor;
  1138. __try
  1139. {
  1140. hbrBatch = pBatchPpb->hbr;
  1141. }
  1142. __except(EXCEPTION_EXECUTE_HANDLER)
  1143. {
  1144. break;
  1145. }
  1146. //
  1147. // Select the brush from batch record
  1148. //
  1149. GreDCSelectBrush(dcoDst.pdc,hbrBatch);
  1150. //
  1151. // Set the DCBrush Color from batch record
  1152. //
  1153. crSaveDCBrushColor = dcoDst.pdc->crDCBrushClr();
  1154. ulSaveDCBrushColor = dcoDst.pdc->ulDCBrushClr();
  1155. __try
  1156. {
  1157. crBatchDCBrushColor = pBatchPpb->DCBrushColor;
  1158. ulBatchDCBrushColor = pBatchPpb->ulDCBrushColor;
  1159. }
  1160. __except(EXCEPTION_EXECUTE_HANDLER)
  1161. {
  1162. break;
  1163. }
  1164. if (crSaveDCBrushColor != crBatchDCBrushColor)
  1165. {
  1166. dcoDst.pdc->crDCBrushClr(crBatchDCBrushColor);
  1167. dcoDst.pdc->ulDCBrushClr(ulBatchDCBrushColor);
  1168. dcoDst.pdc->ulDirtyAdd(DIRTY_FILL);
  1169. }
  1170. //
  1171. // Set the ICM-ed color from batch record
  1172. // (only effective when ICM is turned-on)
  1173. //
  1174. if (dcoDst.pdc->bIsHostICM() &&
  1175. dcoDst.pdc->hcmXform())
  1176. {
  1177. //
  1178. // Save the current ICM brush state.
  1179. //
  1180. bIcmBrush = dcoDst.pdc->bValidIcmBrushColor();
  1181. //
  1182. // if the ICM is enabled, we believe batch
  1183. // record contains valid ICMed color.
  1184. //
  1185. dcoDst.pdc->ulDirtyAdd(ICM_BRUSH_TRANSLATED);
  1186. crSaveIcmBrushColor = dcoDst.pdc->crIcmBrushColor();
  1187. __try
  1188. {
  1189. crBatchIcmBrushColor = pBatchPpb->IcmBrushColor;
  1190. }
  1191. __except(EXCEPTION_EXECUTE_HANDLER)
  1192. {
  1193. break;
  1194. }
  1195. if (crSaveIcmBrushColor != crBatchIcmBrushColor)
  1196. {
  1197. dcoDst.pdc->crIcmBrushColor(crBatchIcmBrushColor);
  1198. dcoDst.pdc->ulDirtyAdd(DIRTY_FILL);
  1199. }
  1200. }
  1201. ptlViewportOrgSave = dcoDst.pdc->ptlViewportOrg();
  1202. __try
  1203. {
  1204. ptlBatchViewportOrg.x = pBatchPpb->ptlViewportOrg.x;
  1205. ptlBatchViewportOrg.y = pBatchPpb->ptlViewportOrg.y;
  1206. }
  1207. __except(EXCEPTION_EXECUTE_HANDLER)
  1208. {
  1209. break;
  1210. }
  1211. if ((ptlViewportOrgSave.x != ptlBatchViewportOrg.x) ||
  1212. (ptlViewportOrgSave.y != ptlBatchViewportOrg.y))
  1213. {
  1214. dcoDst.pdc->lViewportOrgX(ptlBatchViewportOrg.x);
  1215. dcoDst.pdc->lViewportOrgY(ptlBatchViewportOrg.y);
  1216. dcoDst.pdc->flSet_flXform(
  1217. PAGE_XLATE_CHANGED |
  1218. DEVICE_TO_WORLD_INVALID);
  1219. }
  1220. //
  1221. // Execute PatBlt
  1222. //
  1223. EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
  1224. if (!xoDst.bRotation())
  1225. {
  1226. ERECTL erclDst(x,y,x+cx,y+cy);
  1227. xoDst.bXform(erclDst);
  1228. erclDst.vOrder();
  1229. if (!erclDst.bEmpty())
  1230. {
  1231. //
  1232. // Accumulate bounds. We can do this before knowing if the operation is
  1233. // successful because bounds can be loose.
  1234. //
  1235. if (dcoDst.fjAccum())
  1236. {
  1237. dcoDst.vAccumulate(erclDst);
  1238. }
  1239. //
  1240. // metafile patblt will have NULL surface but must still
  1241. // accumulate bounds
  1242. //
  1243. SURFACE *pSurfDst = dcoDst.pSurface();
  1244. if (pSurfDst != NULL)
  1245. {
  1246. GrePatBltLockedDC(
  1247. dcoDst,
  1248. xoDst,
  1249. &erclDst,
  1250. rop4,
  1251. pSurfDst,
  1252. TextColor,
  1253. BackColor,
  1254. ulTextColor,
  1255. ulBackColor
  1256. );
  1257. }
  1258. }
  1259. }
  1260. else
  1261. {
  1262. //
  1263. // There is rotation involved - send it off to MaskBlt to handle it.
  1264. //
  1265. COLORREF crTextColorOld = dcoDst.pdc->crTextClr();
  1266. COLORREF crBackColorOld = dcoDst.pdc->crBackClr();
  1267. COLORREF ulTextColorOld = dcoDst.pdc->ulTextClr();
  1268. COLORREF ulBackColorOld = dcoDst.pdc->ulBackClr();
  1269. dcoDst.pdc->crTextClr(TextColor);
  1270. dcoDst.pdc->crBackClr(BackColor);
  1271. dcoDst.pdc->ulTextClr(ulTextColor);
  1272. dcoDst.pdc->ulBackClr(ulBackColor);
  1273. GreMaskBlt(hdcDst, x, y, cx, cy, 0, 0, 0, 0, 0, 0, rop4 << 16, 0);
  1274. dcoDst.pdc->crTextClr(crTextColorOld);
  1275. dcoDst.pdc->crBackClr(crBackColorOld);
  1276. dcoDst.pdc->ulTextClr(ulTextColorOld);
  1277. dcoDst.pdc->ulBackClr(ulBackColorOld);
  1278. }
  1279. //
  1280. // make sure dc brush is restored
  1281. //
  1282. if (dcoDst.pdc->hbrush() != hbrSave)
  1283. {
  1284. dcoDst.pdc->hbrush(hbrSave);
  1285. dcoDst.pdc->ulDirtyAdd(DC_BRUSH_DIRTY);
  1286. }
  1287. //
  1288. // Restore the original.
  1289. //
  1290. if (crSaveDCBrushColor != dcoDst.pdc->crDCBrushClr())
  1291. {
  1292. dcoDst.pdc->crDCBrushClr(crSaveDCBrushColor);
  1293. dcoDst.pdc->ulDCBrushClr(ulSaveDCBrushColor);
  1294. dcoDst.pdc->ulDirtyAdd(DIRTY_FILL);
  1295. }
  1296. if (dcoDst.pdc->bIsHostICM() &&
  1297. dcoDst.pdc->hcmXform())
  1298. {
  1299. if (crSaveIcmBrushColor != dcoDst.pdc->crIcmBrushColor())
  1300. {
  1301. dcoDst.pdc->crIcmBrushColor(crSaveIcmBrushColor);
  1302. dcoDst.pdc->ulDirtyAdd(DIRTY_FILL);
  1303. }
  1304. if (!bIcmBrush)
  1305. dcoDst.pdc->ulDirtySub(ICM_BRUSH_TRANSLATED);
  1306. }
  1307. if ((ptlViewportOrgSave.x != dcoDst.pdc->lViewportOrgX()) ||
  1308. (ptlViewportOrgSave.y != dcoDst.pdc->lViewportOrgY()))
  1309. {
  1310. dcoDst.pdc->lViewportOrgX(ptlViewportOrgSave.x);
  1311. dcoDst.pdc->lViewportOrgY(ptlViewportOrgSave.y);
  1312. dcoDst.pdc->flSet_flXform(
  1313. PAGE_XLATE_CHANGED |
  1314. DEVICE_TO_WORLD_INVALID);
  1315. }
  1316. }
  1317. else
  1318. {
  1319. WARNING1("ERROR PatBlt called with Rop requires Source or on invalid Dst\n");
  1320. }
  1321. }
  1322. break;
  1323. default:
  1324. //
  1325. // unknown command on TEB
  1326. //
  1327. WARNING("ERROR in GDI batch command code");
  1328. }
  1329. //
  1330. // Decrement the batch command count and increment the batch
  1331. // pointer to the next batch command
  1332. //
  1333. GdiBatchCount--;
  1334. GdiBatchIncrement = (GdiBatchLength + sizeof(PVOID) - 1)
  1335. & ~(sizeof(PVOID)-1);
  1336. pGdiBatch += GdiBatchIncrement;
  1337. } while (
  1338. (GdiBatchCount > 0) &&
  1339. ((pGdiBatch + sizeof(BATCHCOMMAND)) < pGdiBatchEnd)
  1340. );
  1341. //
  1342. // clear batch control
  1343. //
  1344. __try
  1345. {
  1346. pteb->GdiBatchCount = 0;
  1347. pteb->GdiTebBatch.Offset = 0;
  1348. }
  1349. __except(EXCEPTION_EXECUTE_HANDLER)
  1350. {
  1351. }
  1352. //
  1353. // restore DC_ATTR brush and set dirty flag
  1354. //
  1355. dcoDst.pdc->hbrush(hbrDCA);
  1356. dcoDst.pdc->ulDirtyAdd(DC_BRUSH_DIRTY);
  1357. }
  1358. //
  1359. // Unlock DC
  1360. //
  1361. dcoDst.vUnlock();
  1362. }
  1363. else
  1364. {
  1365. WARNING("GDI Batch routine: invalid hdc");
  1366. }
  1367. }
  1368. //
  1369. // non dc based commands must be executed whether there
  1370. // was a dc or devlock failure or not. If the batch was
  1371. // not flushed above, it must be flushed here.
  1372. //
  1373. if (bExecNonDCOnly)
  1374. {
  1375. //
  1376. // can only be non-dc based batched commands
  1377. //
  1378. do
  1379. {
  1380. //
  1381. // Pull patblt off teb and execute. TEB is not safe
  1382. // so all offsets must be checked to make sure no
  1383. // corruption has occured.
  1384. //
  1385. ULONG GdiBatchType;
  1386. ULONG GdiBatchLength;
  1387. ULONG GdiBatchIncrement;
  1388. BOOL bRead = TRUE;
  1389. __try
  1390. {
  1391. GdiBatchType = ((PBATCHCOMMAND)pGdiBatch)->Type;
  1392. GdiBatchLength = ((PBATCHCOMMAND)pGdiBatch)->Length;
  1393. }
  1394. __except(EXCEPTION_EXECUTE_HANDLER)
  1395. {
  1396. break;
  1397. }
  1398. if ((pGdiBatch + GdiBatchLength) > pGdiBatchEnd)
  1399. {
  1400. //
  1401. // exit while loop
  1402. //
  1403. WARNING("Error in GDI TEB batch address");
  1404. break;
  1405. }
  1406. //
  1407. // performance measure
  1408. //
  1409. #if DBG_GDI_BATCH
  1410. if (GdiBatchType <8)
  1411. {
  1412. GdiBatchTypeCounts[GdiBatchType]++;
  1413. }
  1414. #endif
  1415. //
  1416. // Check command type
  1417. //
  1418. switch (GdiBatchType)
  1419. {
  1420. //
  1421. // execute ExtTextOut and ExtTextOutRect
  1422. //
  1423. case BatchTypeTextOut:
  1424. case BatchTypeTextOutRect:
  1425. case BatchTypeSelectClip:
  1426. case BatchTypeSelectFont:
  1427. case BatchTypePolyPatBlt:
  1428. case BatchTypePatBlt:
  1429. case BatchTypeSetBrushOrg:
  1430. break;
  1431. //
  1432. // delete brush
  1433. //
  1434. case BatchTypeDeleteBrush:
  1435. {
  1436. HOBJ hObj;
  1437. __try
  1438. {
  1439. hObj = (HOBJ)((PBATCHDELETEBRUSH)pGdiBatch)->hbrush;
  1440. }
  1441. __except(EXCEPTION_EXECUTE_HANDLER)
  1442. {
  1443. bRead = FALSE;
  1444. }
  1445. if (bRead)
  1446. NtGdiDeleteObjectApp(hObj);
  1447. }
  1448. break;
  1449. //
  1450. // delete region
  1451. //
  1452. case BatchTypeDeleteRegion:
  1453. {
  1454. HOBJ hObj;
  1455. __try
  1456. {
  1457. hObj = (HOBJ)((PBATCHDELETEREGION)pGdiBatch)->hregion;
  1458. }
  1459. __except(EXCEPTION_EXECUTE_HANDLER)
  1460. {
  1461. bRead = FALSE;
  1462. }
  1463. if (bRead)
  1464. NtGdiDeleteObjectApp(hObj);
  1465. }
  1466. break;
  1467. default:
  1468. //
  1469. // unknown command on TEB
  1470. //
  1471. WARNING("ERROR in GDI batch command code");
  1472. }
  1473. //
  1474. // Decrement the batch command count and increment the batch
  1475. // pointer to the next batch command
  1476. //
  1477. GdiBatchCount--;
  1478. GdiBatchIncrement = (GdiBatchLength + sizeof(PVOID) - 1)
  1479. & ~(sizeof(PVOID)-1);
  1480. pGdiBatch += GdiBatchIncrement;
  1481. } while (
  1482. (GdiBatchCount > 0) &&
  1483. ((pGdiBatch + sizeof(BATCHCOMMAND)) < pGdiBatchEnd)
  1484. );
  1485. __try
  1486. {
  1487. pteb->GdiBatchCount = 0;
  1488. pteb->GdiTebBatch.Offset = 0;
  1489. }
  1490. _except(EXCEPTION_EXECUTE_HANDLER)
  1491. {
  1492. }
  1493. }
  1494. }
  1495. //
  1496. // reset hDC
  1497. //
  1498. __try
  1499. {
  1500. pteb->GdiTebBatch.HDC = 0;
  1501. }
  1502. __except(EXCEPTION_EXECUTE_HANDLER)
  1503. {
  1504. }
  1505. }
  1506. /******************************Public*Routine******************************\
  1507. * GdiThreadCalloutFlushUserBatch
  1508. *
  1509. * Processes all delete region calls that are part of the batch queue,
  1510. * called only when a thread terminates and we want to recover the resources
  1511. * allocated to a region.
  1512. * WINBUG We need a better solution to process the whole batch list when
  1513. * thread terminates.
  1514. *
  1515. * Arguments:
  1516. *
  1517. * None
  1518. *
  1519. * Return Value:
  1520. *
  1521. * None
  1522. *
  1523. * History:
  1524. *
  1525. \**************************************************************************/
  1526. VOID
  1527. GdiThreadCalloutFlushUserBatch()
  1528. {
  1529. PTEB pteb = NtCurrentTeb();
  1530. ULONG GdiBatchCount;
  1531. PBYTE pGdiBatch;
  1532. //
  1533. // clear batch control
  1534. //
  1535. __try
  1536. {
  1537. GdiBatchCount = pteb->GdiBatchCount;
  1538. pGdiBatch = (PBYTE)&pteb->GdiTebBatch.Buffer[0];
  1539. pteb->GdiBatchCount = 0;
  1540. pteb->GdiTebBatch.Offset = 0;
  1541. }
  1542. __except(EXCEPTION_EXECUTE_HANDLER)
  1543. {
  1544. return;
  1545. }
  1546. PBYTE pGdiBatchEnd = pGdiBatch + GDI_BATCH_SIZE;
  1547. //
  1548. // read batch once at start
  1549. //
  1550. if (
  1551. (GdiBatchCount > 0) &&
  1552. (GdiBatchCount < (GDI_BATCH_SIZE/4))
  1553. )
  1554. {
  1555. do
  1556. {
  1557. ULONG GdiBatchType;
  1558. ULONG GdiBatchLength;
  1559. ULONG GdiBatchIncrement;
  1560. BOOL bRead = TRUE;
  1561. __try
  1562. {
  1563. GdiBatchType = ((PBATCHCOMMAND)pGdiBatch)->Type;
  1564. GdiBatchLength = ((PBATCHCOMMAND)pGdiBatch)->Length;
  1565. }
  1566. __except(EXCEPTION_EXECUTE_HANDLER)
  1567. {
  1568. //
  1569. // Exit while loop.
  1570. //
  1571. break;
  1572. }
  1573. if ((pGdiBatch + GdiBatchLength) > pGdiBatchEnd)
  1574. {
  1575. //
  1576. // exit while loop
  1577. //
  1578. WARNING("Error in GDI TEB batch address");
  1579. break;
  1580. }
  1581. //
  1582. // Check command type
  1583. //
  1584. switch (GdiBatchType)
  1585. {
  1586. //
  1587. // execute ExtTextOut and ExtTextOutRect
  1588. //
  1589. case BatchTypeTextOut:
  1590. case BatchTypeTextOutRect:
  1591. case BatchTypeSelectClip:
  1592. case BatchTypeSelectFont:
  1593. case BatchTypePolyPatBlt:
  1594. case BatchTypePatBlt:
  1595. case BatchTypeSetBrushOrg:
  1596. case BatchTypeDeleteBrush:
  1597. break;
  1598. //
  1599. // delete region
  1600. //
  1601. case BatchTypeDeleteRegion:
  1602. {
  1603. HOBJ hObj;
  1604. __try
  1605. {
  1606. hObj = (HOBJ)((PBATCHDELETEREGION)pGdiBatch)->hregion;
  1607. }
  1608. __except(EXCEPTION_EXECUTE_HANDLER)
  1609. {
  1610. bRead = FALSE;
  1611. }
  1612. if (bRead)
  1613. NtGdiDeleteObjectApp(hObj);
  1614. }
  1615. break;
  1616. default:
  1617. //
  1618. // unknown command on TEB
  1619. //
  1620. WARNING("ERROR in GDI batch command code");
  1621. }
  1622. //
  1623. // Decrement the batch command count and increment the batch
  1624. // pointer to the next batch command
  1625. //
  1626. GdiBatchCount--;
  1627. GdiBatchIncrement = (GdiBatchLength + sizeof(PVOID) - 1)
  1628. & ~(sizeof(PVOID)-1);
  1629. pGdiBatch += GdiBatchIncrement;
  1630. } while (
  1631. (GdiBatchCount > 0) &&
  1632. ((pGdiBatch + sizeof(BATCHCOMMAND)) < pGdiBatchEnd)
  1633. );
  1634. }
  1635. }
  1636. /******************************Public*Routine******************************\
  1637. * NtGdiBitBlt
  1638. *
  1639. * API entry point for doing a BitBlt.
  1640. *
  1641. * returns: TRUE for success, FALSE for failure.
  1642. *
  1643. * History:
  1644. * Wed 03-Nov-1993 -by- Patrick Haluptzok [patrickh]
  1645. * optimize for size, we make sure at dispatch level not to send functions
  1646. * that don't need a SRC to PatBlt.
  1647. *
  1648. * Sun 30-Aug-1992 -by- Patrick Haluptzok [patrickh]
  1649. * optimize for performance
  1650. *
  1651. * 18-Mar-1992 -by- Donald Sidoroff [donalds]
  1652. * Accumulate bounds, region pointer change.
  1653. *
  1654. * Sun 20-Oct-1991 -by- Patrick Haluptzok [patrickh]
  1655. * Make ATTRCACHE the default.
  1656. *
  1657. * 23-Apr-1991 -by- Patrick Haluptzok patrickh
  1658. * Expanded on ChuckWh's BitBlt code.
  1659. *
  1660. * Wed 22-Aug-1990 15:22:39 -by- Charles Whitmer [chuckwh]
  1661. * BitBlt: Wrote it. This is a first pass.
  1662. \**************************************************************************/
  1663. BOOL
  1664. NtGdiBitBlt(
  1665. HDC hdcDst,
  1666. int x,
  1667. int y,
  1668. int cx,
  1669. int cy,
  1670. HDC hdcSrc,
  1671. int xSrc,
  1672. int ySrc,
  1673. DWORD rop4,
  1674. #ifdef _WINDOWBLT_NOTIFICATION_
  1675. DWORD crBackColor,
  1676. FLONG fl
  1677. #else
  1678. DWORD crBackColor
  1679. #endif
  1680. )
  1681. {
  1682. #ifdef _WINDOWBLT_NOTIFICATION_
  1683. GDITraceHandle2(NtGdiBitBlt, "(%X, %d, %d, %d, %d, %X, %d, %d, %X, %X, %X)\n",
  1684. (va_list)&hdcDst, hdcDst, hdcSrc);
  1685. #else
  1686. GDITraceHandle2(NtGdiBitBlt, "(%X, %d, %d, %d, %d, %X, %d, %d, %X, %X)\n",
  1687. (va_list)&hdcDst, hdcDst, hdcSrc);
  1688. #endif
  1689. BOOL bReturn = FALSE;
  1690. //
  1691. // Check for CAPTUREBLT rop flag; if it's set, let StretchBlt handle
  1692. // it. [Bug #278291]
  1693. //
  1694. if (rop4 & CAPTUREBLT)
  1695. {
  1696. return GreStretchBlt(hdcDst,x,y,cx,cy,hdcSrc,xSrc,ySrc,cx,cy,rop4,crBackColor);
  1697. }
  1698. POINTL ptOrgDst;
  1699. DWORD OrgRop4 = rop4, dwOldLayout;
  1700. rop4 = rop4 & ~NOMIRRORBITMAP;
  1701. #if DBG
  1702. if ((((rop4 << 2) ^ rop4) & 0x00CC0000) == 0)
  1703. {
  1704. WARNING("NtGdiBitBlt() called with no source required\n");
  1705. }
  1706. #endif
  1707. // Lock down the DC
  1708. XDCOBJ dcoDst(hdcDst);
  1709. if (dcoDst.bValid() && !dcoDst.bStockBitmap())
  1710. {
  1711. XDCOBJ dcoSrc(hdcSrc);
  1712. if (dcoSrc.bValid())
  1713. {
  1714. if ( ((dcoDst.pdc->dwLayout() & LAYOUT_ORIENTATIONMASK) != (dcoSrc.pdc->dwLayout() & LAYOUT_ORIENTATIONMASK)) &&
  1715. (((OrgRop4 & NOMIRRORBITMAP) && MIRRORED_DC(dcoDst.pdc)) || MIRRORED_DC_NO_BITMAP_FLIP(dcoDst.pdc))
  1716. ) {
  1717. dcoDst.pdc->vGet_ptlWindowOrg( &ptOrgDst );
  1718. dwOldLayout = dcoDst.pdc->dwSetLayout(-1, 0);
  1719. x = ptOrgDst.x - x - cx;
  1720. // Restore the DC if the flag is in the DC and not part
  1721. // of the Rops. [samera]
  1722. //
  1723. OrgRop4 = NOMIRRORBITMAP;
  1724. } else {
  1725. OrgRop4 = 0;
  1726. }
  1727. EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
  1728. EXFORMOBJ xoSrc(dcoSrc, WORLD_TO_DEVICE);
  1729. if ((!xoDst.bRotation()) && (xoDst.bEqualExceptTranslations(xoSrc)))
  1730. {
  1731. //
  1732. // Return null operations. Don't need to check source for
  1733. // empty because the xforms are the same except translation.
  1734. //
  1735. ERECTL erclSrc(xSrc,ySrc,xSrc+cx,ySrc+cy);
  1736. xoSrc.bXform(erclSrc);
  1737. erclSrc.vOrder();
  1738. ERECTL erclDst(x,y,x+cx,y+cy);
  1739. xoDst.bXform(erclDst);
  1740. erclDst.vOrder();
  1741. if (!erclDst.bEmpty())
  1742. {
  1743. //
  1744. // Accumulate bounds. We can do this outside the DEVLOCK
  1745. //
  1746. if (dcoDst.fjAccum())
  1747. dcoDst.vAccumulate(erclDst);
  1748. //
  1749. // Lock the Rao region and the surface if we are drawing on a
  1750. // display surface. Bail out if we are in full screen mode.
  1751. //
  1752. DEVLOCKBLTOBJ dlo;
  1753. BOOL bLocked;
  1754. bLocked = dlo.bLock(dcoDst, dcoSrc);
  1755. if (bLocked)
  1756. {
  1757. //
  1758. // Check pSurfDst, this may be an info DC or a memory DC with default bitmap.
  1759. //
  1760. SURFACE *pSurfDst;
  1761. if ((pSurfDst = dcoDst.pSurface()) != NULL)
  1762. {
  1763. //
  1764. // Set up the brush if necessary.
  1765. //
  1766. XEPALOBJ palDst(pSurfDst->ppal());
  1767. XEPALOBJ palDstDC(dcoDst.ppal());
  1768. EBRUSHOBJ *pbo;
  1769. //
  1770. // Finish rop to pass over ddi to driver.
  1771. //
  1772. rop4 = (rop4 >> 16) & 0x000000FF;
  1773. rop4 = (rop4 << 8) | rop4;
  1774. //
  1775. // Check if we need a brush.
  1776. //
  1777. if ((((rop4 << 4) ^ rop4) & 0x00F0) != 0)
  1778. {
  1779. pbo = dcoDst.peboFill();
  1780. ULONG ulDirty = dcoDst.pdc->ulDirty();
  1781. if ( ulDirty & DC_BRUSH_DIRTY)
  1782. {
  1783. GreDCSelectBrush(dcoDst.pdc,dcoDst.pdc->hbrush());
  1784. }
  1785. if ((dcoDst.ulDirty() & DIRTY_FILL) || (dcoDst.pdc->flbrush() & DIRTY_FILL))
  1786. {
  1787. dcoDst.ulDirtySub(DIRTY_FILL);
  1788. dcoDst.pdc->flbrushSub(DIRTY_FILL);
  1789. pbo->vInitBrush(
  1790. dcoDst.pdc,
  1791. dcoDst.pdc->pbrushFill(),
  1792. palDstDC,
  1793. palDst,
  1794. pSurfDst);
  1795. }
  1796. }
  1797. else
  1798. {
  1799. pbo = NULL;
  1800. }
  1801. //
  1802. // With a fixed DC origin we can change the destination to SCREEN coordinates.
  1803. //
  1804. erclDst += dcoDst.eptlOrigin();
  1805. EPOINTL eptlOffset;
  1806. SURFACE *pSurfSrc = dcoSrc.pSurface();
  1807. //
  1808. // Basically we check that pSurfSrc is not NULL which
  1809. // happens for memory bitmaps with the default bitmap
  1810. // and for info DC's. Otherwise we continue if
  1811. // the source is readable or if it isn't we continue
  1812. // if we are blting display to display or if User says
  1813. // we have ScreenAccess on this display DC. Note
  1814. // that if pSurfSrc is not readable the only way we
  1815. // can continue the blt is if the src is a display.
  1816. //
  1817. if (pSurfSrc != NULL)
  1818. {
  1819. if ((pSurfSrc->bReadable() && ((dcoDst.bDisplay() && !dcoDst.bRedirection()) ? UserScreenAccessCheck() : TRUE)) ||
  1820. ( (dcoSrc.bDisplay()) &&
  1821. ((dcoDst.bDisplay()) || UserScreenAccessCheck() )))
  1822. {
  1823. //
  1824. // Lock the source surface.
  1825. //
  1826. XEPALOBJ palSrc(pSurfSrc->ppal());
  1827. //
  1828. // Compute the offset between source and dest, in screen coordinates.
  1829. //
  1830. eptlOffset.x = erclDst.left - erclSrc.left - dcoSrc.eptlOrigin().x;
  1831. eptlOffset.y = erclDst.top - erclSrc.top - dcoSrc.eptlOrigin().y;
  1832. //
  1833. // Compute the source surface origin, taking into account multi-mon
  1834. // and negative offsets:
  1835. //
  1836. LONG xOrigin = 0;
  1837. LONG yOrigin = 0;
  1838. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  1839. if ((pdoSrc.bValid()) && (pdoSrc.bPrimary(pSurfSrc)) && (pdoSrc.bMetaDriver()))
  1840. {
  1841. xOrigin = pdoSrc.pptlOrigin()->x;
  1842. yOrigin = pdoSrc.pptlOrigin()->y;
  1843. }
  1844. //
  1845. // Take care of the source rectangle. We may have to reduce it. We do this
  1846. // so a driver can always assume that neither the source nor the destination
  1847. // rectangles hang over the edge of a surface.
  1848. //
  1849. // Intersect the dest with the source surface extents.
  1850. //
  1851. erclDst.left = MAX(xOrigin + eptlOffset.x, erclDst.left);
  1852. erclDst.top = MAX(yOrigin + eptlOffset.y, erclDst.top);
  1853. erclDst.right = MIN((xOrigin + pSurfSrc->sizl().cx + eptlOffset.x), erclDst.right);
  1854. erclDst.bottom = MIN((yOrigin + pSurfSrc->sizl().cy + eptlOffset.y), erclDst.bottom);
  1855. if ((erclDst.left < erclDst.right) && (erclDst.top < erclDst.bottom))
  1856. {
  1857. //
  1858. // This is a pretty gnarly expression to save a return in here.
  1859. // Basically pco can be NULL if the rect is completely in the
  1860. // cached rect in the DC or if we set up a clip object that isn't empty.
  1861. //
  1862. ECLIPOBJ *pco = NULL;
  1863. if (((erclDst.left >= dcoDst.prclClip()->left) &&
  1864. (erclDst.right <= dcoDst.prclClip()->right) &&
  1865. (erclDst.top >= dcoDst.prclClip()->top) &&
  1866. (erclDst.bottom <= dcoDst.prclClip()->bottom)) ||
  1867. (pco = dcoDst.pco(),
  1868. pco->vSetup(dcoDst.prgnEffRao(), erclDst, CLIP_NOFORCETRIV),
  1869. erclDst = pco->erclExclude(),
  1870. (!erclDst.bEmpty())))
  1871. {
  1872. //
  1873. // Compute the (reduced) origin.
  1874. //
  1875. erclSrc.left = erclDst.left - eptlOffset.x;
  1876. erclSrc.top = erclDst.top - eptlOffset.y;
  1877. DEVEXCLUDEOBJ dxo;
  1878. EXLATEOBJ xlo;
  1879. XLATEOBJ *pxlo;
  1880. //
  1881. // C++ would generate alot of code to exit here to have
  1882. // a return so we set bReturn to TRUE if we succeed to
  1883. // init a valid xlate. We avoid a return this way.
  1884. //
  1885. if (dcoSrc.pSurface() == dcoDst.pSurface())
  1886. {
  1887. pxlo = NULL;
  1888. bReturn = TRUE;
  1889. //
  1890. // To Call vExclude directly you must check it's a Display PDEV
  1891. // and that cursor exclusion needs to be done.
  1892. //
  1893. if (dcoDst.bDisplay() && dcoDst.bNeedsSomeExcluding())
  1894. {
  1895. //
  1896. // Compute the exclusion rectangle. (It's expanded to include the source.)
  1897. //
  1898. ERECTL erclReduced = erclDst;
  1899. if (erclSrc.left < erclReduced.left)
  1900. erclReduced.left = erclSrc.left;
  1901. else
  1902. erclReduced.right += (erclSrc.left - erclReduced.left);
  1903. if (erclSrc.top < erclReduced.top)
  1904. erclReduced.top = erclSrc.top;
  1905. else
  1906. erclReduced.bottom += (erclSrc.top - erclReduced.top);
  1907. dxo.vExclude2(dcoDst.hdev(), &erclReduced, pco, &eptlOffset);
  1908. }
  1909. }
  1910. else
  1911. {
  1912. //
  1913. // Get a translate object.
  1914. //
  1915. XEPALOBJ palSrcDC(dcoSrc.ppal());
  1916. if (crBackColor == (COLORREF)-1)
  1917. crBackColor = dcoSrc.pdc->ulBackClr();
  1918. //
  1919. // No ICM with BitBlt(), so pass NULL color transform to XLATEOBJ
  1920. //
  1921. bReturn = xlo.bInitXlateObj(NULL, // hColorTransform
  1922. dcoDst.pdc->lIcmMode(), // ICM mode
  1923. palSrc,
  1924. palDst,
  1925. palSrcDC,
  1926. palDstDC,
  1927. dcoDst.pdc->crTextClr(),
  1928. dcoDst.pdc->crBackClr(),
  1929. crBackColor);
  1930. pxlo = xlo.pxlo();
  1931. //
  1932. // WARNING: When we support multiple displays that support cursors
  1933. // the following exclude logic will need to be redone. Right now
  1934. // we assume that there can only be 1 display surface around that
  1935. // needs cursor exclusion.
  1936. //
  1937. if (dcoDst.bDisplay())
  1938. {
  1939. if (dcoDst.bNeedsSomeExcluding())
  1940. {
  1941. //
  1942. // To Call vExclude directly you must check it's a Display PDEV
  1943. // and that cursor exclusion needs to be done.
  1944. //
  1945. dxo.vExclude(dcoDst.hdev(),&erclDst,pco);
  1946. }
  1947. }
  1948. else
  1949. {
  1950. //
  1951. // The left top of erclSrc is correctly computed
  1952. // we just need the bottom,right updated now.
  1953. //
  1954. erclSrc.right = erclDst.right - eptlOffset.x,
  1955. erclSrc.bottom = erclDst.bottom - eptlOffset.y,
  1956. dxo.vExcludeDC(dcoSrc,&erclSrc);
  1957. }
  1958. }
  1959. if (bReturn)
  1960. {
  1961. //
  1962. // Inc the target surface uniqueness
  1963. //
  1964. INC_SURF_UNIQ(pSurfDst);
  1965. //
  1966. // Check if we're on the same PDEV, we can't blt between
  1967. // different PDEV's. Well, actually we can so long as the
  1968. // source is an engine-exclusive surface, which we check
  1969. // by looking at iType() and dhsurf().
  1970. //
  1971. if ((dcoDst.hdev() == dcoSrc.hdev()) ||
  1972. ((pSurfSrc->iType() == STYPE_BITMAP) &&
  1973. (pSurfSrc->dhsurf() == NULL) && !dcoDst.bPrinter()))
  1974. {
  1975. if (rop4 == 0xCCCC)
  1976. {
  1977. PDEVOBJ pdo(pSurfDst->hdev());
  1978. //
  1979. // Define _WINDOWBLT_NOTIFICATION_ to turn on Window BLT notification.
  1980. // This notification will set a special flag in the SURFOBJ passed to
  1981. // drivers when the DrvCopyBits operation is called to move a window.
  1982. //
  1983. // To enable, need to add these to winddi.h:
  1984. //
  1985. // #define GCAPS2_WINDOW_BLT 0x00000004
  1986. // #define BMF_WINDOW_BLT 0x0040
  1987. //
  1988. // In addition, w32\kmode\services.tab needs to be modified to add a
  1989. // parameter to BitBlt.
  1990. //
  1991. // See also:
  1992. // w32\w32inc\gre.h
  1993. // ntgdi\inc\ntgdi.h
  1994. // ntgdi\client\output.c
  1995. // ntgdi\gre\maskblt.cxx
  1996. // ntuser\kernel\swp.c zzzBltValidBits is where BitBlt
  1997. // is called to move the window
  1998. //
  1999. #ifdef _WINDOWBLT_NOTIFICATION_
  2000. //
  2001. // If window blt notification needed, add
  2002. // the bit to dst surface flags.
  2003. //
  2004. if (fl & GBB_WINDOWBLT)
  2005. pSurfDst->fjBitmap(pSurfDst->fjBitmap() | BMF_WINDOW_BLT);
  2006. #endif
  2007. bReturn = (*PPFNGET(pdo, CopyBits, pSurfDst->flags())) (
  2008. pSurfDst->pSurfobj(),
  2009. pSurfSrc->pSurfobj(),
  2010. pco,
  2011. pxlo,
  2012. &erclDst,
  2013. (POINTL *) &erclSrc);
  2014. #ifdef _WINDOWBLT_NOTIFICATION_
  2015. //
  2016. // Clear the window blt notification flag. Not
  2017. // valid anywhere else, so don't bother checking
  2018. // if we actually set it.
  2019. //
  2020. pSurfDst->fjBitmap(pSurfDst->fjBitmap() & ~BMF_WINDOW_BLT);
  2021. #endif
  2022. }
  2023. else
  2024. {
  2025. bReturn = (*(pSurfDst->pfnBitBlt())) (
  2026. pSurfDst->pSurfobj(),
  2027. pSurfSrc->pSurfobj(),
  2028. (SURFOBJ *) NULL,
  2029. pco,
  2030. pxlo,
  2031. &erclDst,
  2032. (POINTL *) &erclSrc,
  2033. (POINTL *) NULL,
  2034. pbo,
  2035. &dcoDst.pdc->ptlFillOrigin(),
  2036. rop4);
  2037. }
  2038. }
  2039. else
  2040. {
  2041. //
  2042. // we need to carry dlo down since we may need
  2043. // to free the DEVLOCK of the source surf if
  2044. // we are going out to user mode printer drivers
  2045. //
  2046. PDEVOBJ pdoDst(pSurfDst->hdev());
  2047. bReturn = SimBitBlt(
  2048. pSurfDst->pSurfobj(),
  2049. pSurfSrc->pSurfobj(),
  2050. (SURFOBJ *) NULL,
  2051. pco,
  2052. pxlo,
  2053. &erclDst,
  2054. (POINTL *) &erclSrc,
  2055. (POINTL *) NULL,
  2056. pbo,
  2057. &dcoDst.pdc->ptlFillOrigin(),
  2058. rop4,
  2059. pdoDst.bPrinter() ? &dlo : NULL);
  2060. }
  2061. }
  2062. else
  2063. {
  2064. WARNING1("bInitXlateObj failed in GreBitBlt\n");
  2065. }
  2066. }
  2067. else
  2068. {
  2069. bReturn = TRUE;
  2070. }
  2071. }
  2072. else
  2073. {
  2074. bReturn = TRUE;
  2075. }
  2076. }
  2077. else
  2078. {
  2079. WARNING1("GreBitBlt failed - trying to read from unreadable surface\n");
  2080. EngSetLastError(ERROR_INVALID_HANDLE);
  2081. }
  2082. }
  2083. else
  2084. {
  2085. bReturn = TRUE;
  2086. }
  2087. }
  2088. else
  2089. {
  2090. bReturn = TRUE;
  2091. }
  2092. }
  2093. else
  2094. {
  2095. // Return True if we are in full screen mode.
  2096. bReturn = dcoDst.bFullScreen() | dcoSrc.bFullScreen();
  2097. }
  2098. }
  2099. else
  2100. {
  2101. bReturn = TRUE;
  2102. }
  2103. }
  2104. else
  2105. {
  2106. bReturn = GreStretchBlt(hdcDst,x,y,cx,cy,hdcSrc,xSrc,ySrc,cx,cy,rop4,crBackColor);
  2107. }
  2108. if (OrgRop4 & NOMIRRORBITMAP) {
  2109. dcoDst.pdc->dwSetLayout(-1, dwOldLayout);
  2110. }
  2111. dcoSrc.vUnlockFast();
  2112. }
  2113. else
  2114. {
  2115. WARNING1("GreBitBlt failed invalid SrcDC\n");
  2116. }
  2117. dcoDst.vUnlockFast();
  2118. }
  2119. else
  2120. {
  2121. WARNING1("GreBitBlt failed invalid DstDC\n");
  2122. }
  2123. return(bReturn);
  2124. }
  2125. /******************************Public*Routine******************************\
  2126. * GreRectBlt
  2127. *
  2128. * Internal entry point for faster Rectangle drawing. The rectangle is
  2129. * specified in device pixel coordinates.
  2130. *
  2131. * NOTE: The caller must have already taken care of the brush dirty bits!
  2132. *
  2133. * History:
  2134. * 6-May-1992 -by- J. Andrew Goossen [andrewgo]
  2135. * Cloned some code.
  2136. \**************************************************************************/
  2137. BOOL GreRectBlt(
  2138. DCOBJ& dcoTrg,
  2139. ERECTL* percl // Device pixel coordinates
  2140. )
  2141. {
  2142. ASSERTGDI(dcoTrg.bValid(), "Invalid DC");
  2143. BLTRECORD blt;
  2144. // Initialize the blt record
  2145. ROP4 rop4 = gaMix[dcoTrg.pdc->jROP2() & 0x0F];
  2146. ULONG ulAvec = (ULONG) gajRop3[rop4];
  2147. ASSERTGDI(!(ulAvec & AVEC_NEED_SOURCE), "Invalid rop");
  2148. // Accumulate bounds. We can do this outside the DEVLOCK
  2149. if (dcoTrg.fjAccum())
  2150. dcoTrg.vAccumulate(*percl);
  2151. // Lock the target surface
  2152. DEVLOCKBLTOBJ dlo(dcoTrg);
  2153. // This check also verifies that there's a surface
  2154. if (dcoTrg.bFullScreen())
  2155. {
  2156. return(TRUE);
  2157. }
  2158. if (!dlo.bValid())
  2159. {
  2160. return(FALSE);
  2161. }
  2162. blt.pSurfTrg(dcoTrg.pSurface());
  2163. ASSERTGDI(blt.pSurfTrg() != NULL, "ERROR no good");
  2164. blt.ppoTrg()->ppalSet(blt.pSurfTrg()->ppal());
  2165. blt.ppoTrgDC()->ppalSet(dcoTrg.ppal());
  2166. // Set up the brush if necessary.
  2167. if (ulAvec & AVEC_NEED_PATTERN)
  2168. {
  2169. blt.pbo(dcoTrg.peboFill());
  2170. ULONG ulDirty = dcoTrg.pdc->ulDirty();
  2171. if ( ulDirty & DC_BRUSH_DIRTY)
  2172. {
  2173. GreDCSelectBrush(dcoTrg.pdc,dcoTrg.pdc->hbrush());
  2174. }
  2175. if ((dcoTrg.ulDirty() & DIRTY_FILL) || (dcoTrg.pdc->flbrush() & DIRTY_FILL))
  2176. {
  2177. dcoTrg.ulDirtySub(DIRTY_FILL);
  2178. dcoTrg.pdc->flbrushSub(DIRTY_FILL);
  2179. blt.pbo()->vInitBrush(
  2180. dcoTrg.pdc,
  2181. dcoTrg.pdc->pbrushFill(),
  2182. *((XEPALOBJ *) blt.ppoTrgDC()),
  2183. *((XEPALOBJ *) blt.ppoTrg()),
  2184. blt.pSurfTrg()
  2185. );
  2186. }
  2187. // We have to check for a NULL brush because the dirty bits might be
  2188. // wrong, and the 'realized' brush is a NULL one:
  2189. if (blt.pbo()->bIsNull())
  2190. return(FALSE);
  2191. blt.Brush(dcoTrg.pdc->ptlFillOrigin());
  2192. if ((blt.pbo()->bIsMasking()) &&
  2193. (dcoTrg.pdc->jBkMode() == TRANSPARENT))
  2194. {
  2195. rop4 = rop4 | (0xAA00);
  2196. }
  2197. else
  2198. {
  2199. rop4 = (rop4 << 8) | rop4;
  2200. }
  2201. }
  2202. else
  2203. {
  2204. // No masking being done, simple rop.
  2205. blt.pbo(NULL);
  2206. rop4 = (rop4 << 8) | rop4;
  2207. }
  2208. blt.rop(rop4);
  2209. // Initialize some stuff for DDI.
  2210. blt.pSurfMsk((SURFACE *) NULL);
  2211. // Set the target rectangle and blt the bits.
  2212. *blt.perclTrg() = *percl;
  2213. return(blt.bBitBlt(dcoTrg, dcoTrg, ulAvec));
  2214. }
  2215. /******************************Public*Routine******************************\
  2216. * GreMaskBlt
  2217. *
  2218. * API entry point for doing a BitBlt with a Mask.
  2219. *
  2220. * History:
  2221. * 18-Mar-1992 -by- Donald Sidoroff [donalds]
  2222. * Complete rewrite.
  2223. *
  2224. * 20-Oct-1991 -by- Patrick Haluptzok [patrickh]
  2225. * Make ATTRCACHE the default.
  2226. *
  2227. * 23-Apr-1991 -by- Patrick Haluptzok patrickh
  2228. * Expanded on ChuckWh's BitBlt code.
  2229. *
  2230. * Wed 22-Aug-1990 15:22:39 -by- Charles Whitmer [chuckwh]
  2231. * BitBlt: Wrote it. This is a first pass.
  2232. \**************************************************************************/
  2233. BOOL
  2234. GreMaskBlt(
  2235. HDC hdcTrg,
  2236. int x,
  2237. int y,
  2238. int cx,
  2239. int cy,
  2240. HDC hdcSrc,
  2241. int xSrc,
  2242. int ySrc,
  2243. HBITMAP hbmMask,
  2244. int xMask,
  2245. int yMask,
  2246. DWORD rop4,
  2247. DWORD crBackColor
  2248. )
  2249. {
  2250. GDITraceHandle3(GreMaskBlt,
  2251. "(%X, %d, %d, %d, %d, %X, %d, %d, %X, %d, %d, %X, %X)\n",
  2252. (va_list)&hdcTrg, hdcTrg, hdcSrc, hbmMask);
  2253. ULONG ulAvec;
  2254. BLTRECORD blt;
  2255. //
  2256. // Lock the target DC and surface
  2257. //
  2258. DCOBJ dcoTrg(hdcTrg);
  2259. BOOL bReturn = FALSE;
  2260. if (!dcoTrg.bValidSurf())
  2261. {
  2262. if (dcoTrg.bValid() && !dcoTrg.bStockBitmap())
  2263. {
  2264. if (dcoTrg.fjAccum())
  2265. {
  2266. EXFORMOBJ exo(dcoTrg, WORLD_TO_DEVICE);
  2267. ERECTL ercl(x, y, x + cx, y + cy);
  2268. if (exo.bXform(ercl))
  2269. {
  2270. //
  2271. // Make the rectangle well ordered.
  2272. //
  2273. ercl.vOrder();
  2274. dcoTrg.vAccumulate(ercl);
  2275. bReturn = TRUE;
  2276. }
  2277. }
  2278. else
  2279. bReturn = TRUE;
  2280. }
  2281. else
  2282. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2283. return(bReturn);
  2284. }
  2285. if (dcoTrg.bStockBitmap())
  2286. {
  2287. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2288. return bReturn;
  2289. }
  2290. // Initialize the blt record
  2291. // Deal with the mask if needed
  2292. rop4 >>= 16;
  2293. if ((hbmMask == 0) || ((rop4 & 0x00FF) == ((rop4 >> 8) & 0x00FF)))
  2294. {
  2295. rop4 &= 0x00FF;
  2296. ulAvec = gajRop3[rop4];
  2297. rop4 = rop4 | (rop4 << 8);
  2298. blt.rop(rop4);
  2299. blt.pSurfMsk((SURFACE *) NULL);
  2300. }
  2301. else
  2302. {
  2303. SURFREF soMsk((HSURF)hbmMask);
  2304. if (!soMsk.bValid())
  2305. {
  2306. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2307. return(FALSE);
  2308. }
  2309. blt.pSurfMsk((SURFACE *) soMsk.ps);
  2310. if ((blt.pSurfMsk()->iType() != STYPE_BITMAP) ||
  2311. (blt.pSurfMsk()->iFormat() != BMF_1BPP))
  2312. {
  2313. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2314. return(FALSE);
  2315. }
  2316. soMsk.vKeepIt();
  2317. blt.flSet(BLTREC_MASK_NEEDED | BLTREC_MASK_LOCKED);
  2318. blt.rop(rop4);
  2319. ulAvec = ((ULONG) gajRop3[blt.ropFore()]) |
  2320. ((ULONG) gajRop3[blt.ropBack()]);
  2321. ulAvec |= AVEC_NEED_MASK;
  2322. }
  2323. // Lock the source DC if necessary
  2324. DCOBJ dcoSrc;
  2325. // Lock the relevant surfaces
  2326. DEVLOCKBLTOBJ dlo;
  2327. if (ulAvec & AVEC_NEED_SOURCE)
  2328. {
  2329. dcoSrc.vLock(hdcSrc);
  2330. }
  2331. if ((ulAvec & AVEC_NEED_SOURCE) && (dcoSrc.bValid()))
  2332. {
  2333. dlo.bLock(dcoTrg, dcoSrc);
  2334. }
  2335. else
  2336. {
  2337. dlo.bLock(dcoTrg);
  2338. }
  2339. if (!dlo.bValid())
  2340. {
  2341. return(dcoTrg.bFullScreen());
  2342. }
  2343. blt.pSurfTrg(dcoTrg.pSurface());
  2344. blt.pxoTrg()->vInit(dcoTrg,WORLD_TO_DEVICE);
  2345. blt.ppoTrg()->ppalSet(blt.pSurfTrg()->ppal());
  2346. blt.ppoTrgDC()->ppalSet(dcoTrg.ppal());
  2347. if (ulAvec & AVEC_NEED_SOURCE)
  2348. {
  2349. if (!dcoSrc.bValidSurf() || !dcoSrc.pSurface()->bReadable())
  2350. {
  2351. if (!dcoSrc.bValid())
  2352. {
  2353. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2354. return(FALSE);
  2355. }
  2356. if (!dcoSrc.pSurfaceEff()->bReadable())
  2357. {
  2358. if (dcoTrg.dctp() == DCTYPE_INFO)
  2359. {
  2360. if (dcoTrg.fjAccum())
  2361. {
  2362. EXFORMOBJ exo(dcoTrg, WORLD_TO_DEVICE);
  2363. ERECTL ercl(x, y, x + cx, y + cy);
  2364. if (exo.bXform(ercl))
  2365. {
  2366. // Make the rectangle well ordered.
  2367. ercl.vOrder();
  2368. dcoTrg.vAccumulate(ercl);
  2369. }
  2370. return(TRUE);
  2371. }
  2372. }
  2373. // Do the security test on SCREEN to MEMORY blits.
  2374. if (dcoSrc.bDisplay() && !dcoTrg.bDisplay())
  2375. {
  2376. if (!UserScreenAccessCheck())
  2377. {
  2378. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  2379. return(FALSE);
  2380. }
  2381. }
  2382. }
  2383. // If the source isn't a DISPLAY we should exit
  2384. if (!dcoSrc.bDisplay())
  2385. return(FALSE);
  2386. }
  2387. blt.pSurfSrc(dcoSrc.pSurfaceEff());
  2388. blt.ppoSrc()->ppalSet(blt.pSurfSrc()->ppal());
  2389. blt.ppoSrcDC()->ppalSet(dcoSrc.ppal());
  2390. blt.pxoSrc()->vInit(dcoSrc,WORLD_TO_DEVICE);
  2391. // Now set the source rectangle
  2392. if (blt.pxoSrc()->bRotation() || !blt.Src(xSrc, ySrc, cx, cy))
  2393. {
  2394. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2395. return(FALSE);
  2396. }
  2397. // If there is a mask, set the mask rectangle
  2398. if (ulAvec & AVEC_NEED_MASK)
  2399. blt.Msk(xMask, yMask);
  2400. // Create the color translation object
  2401. //
  2402. // No ICM with MaskBlt(), so pass NULL color transform to XLATEOBJ
  2403. if (!blt.pexlo()->bInitXlateObj(NULL, // hColorTransform
  2404. dcoTrg.pdc->lIcmMode(), // ICM mode
  2405. *blt.ppoSrc(),
  2406. *blt.ppoTrg(),
  2407. *blt.ppoSrcDC(),
  2408. *blt.ppoTrgDC(),
  2409. dcoTrg.pdc->crTextClr(),
  2410. dcoTrg.pdc->crBackClr(),
  2411. crBackColor))
  2412. {
  2413. WARNING("bInitXlateObj failed in MaskBlt\n");
  2414. return(FALSE);
  2415. }
  2416. blt.flSet(BLTREC_PXLO);
  2417. }
  2418. else
  2419. {
  2420. blt.pSurfSrc((SURFACE *) NULL);
  2421. // We need to lock the source DC if a mask is required. We need
  2422. // this to get the transform for the mask rectangle.
  2423. if (ulAvec & AVEC_NEED_MASK)
  2424. {
  2425. //
  2426. // if hdcSrc is NULL, assign to hdcTrg
  2427. //
  2428. if (hdcSrc == (HDC)NULL) {
  2429. hdcSrc = hdcTrg;
  2430. }
  2431. dcoSrc.vLock(hdcSrc);
  2432. if (!dcoSrc.bValid())
  2433. {
  2434. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2435. return(FALSE);
  2436. }
  2437. blt.pxoSrc()->vInit(dcoSrc,WORLD_TO_DEVICE);
  2438. // Use the target extents (we need something) to specify the
  2439. // size of the mask. The extent is actually saved in the SOURCE
  2440. // rectangle, since this is the only meaningful place for it.
  2441. if (blt.pxoSrc()->bRotation() || !blt.Msk(xMask, yMask, cx, cy))
  2442. {
  2443. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2444. return(FALSE);
  2445. }
  2446. }
  2447. }
  2448. // Set up the brush if necesary.
  2449. if (ulAvec & AVEC_NEED_PATTERN)
  2450. {
  2451. ULONG ulDirty = dcoTrg.pdc->ulDirty();
  2452. blt.pbo(dcoTrg.peboFill());
  2453. if ( ulDirty & DC_BRUSH_DIRTY)
  2454. {
  2455. GreDCSelectBrush(dcoTrg.pdc,dcoTrg.pdc->hbrush());
  2456. }
  2457. if ((dcoTrg.ulDirty() & DIRTY_FILL) || (dcoTrg.pdc->flbrush() & DIRTY_FILL))
  2458. {
  2459. dcoTrg.ulDirtySub(DIRTY_FILL);
  2460. dcoTrg.pdc->flbrushSub(DIRTY_FILL);
  2461. blt.pbo()->vInitBrush(
  2462. dcoTrg.pdc,
  2463. dcoTrg.pdc->pbrushFill(),
  2464. *((XEPALOBJ *) blt.ppoTrgDC()),
  2465. *((XEPALOBJ *) blt.ppoTrg()),
  2466. blt.pSurfTrg());
  2467. }
  2468. blt.Brush(dcoTrg.pdc->ptlFillOrigin());
  2469. } else {
  2470. //
  2471. // NULL the pebo
  2472. //
  2473. blt.pbo((EBRUSHOBJ *)NULL);
  2474. }
  2475. // Now all the essential information has been collected. We now
  2476. // need to check for promotion and call the appropriate method to
  2477. // finish the blt. If we rotate we must send the call away.
  2478. if (dcoTrg.bDisplay() && !dcoTrg.bRedirection() && dcoSrc.bValidSurf() && !dcoSrc.bDisplay())
  2479. {
  2480. if (!UserScreenAccessCheck())
  2481. {
  2482. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  2483. return (FALSE);
  2484. }
  2485. }
  2486. if (blt.pxoTrg()->bRotation())
  2487. {
  2488. if (!blt.TrgPlg(x, y, cx, cy))
  2489. {
  2490. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2491. return(FALSE);
  2492. }
  2493. return(blt.bRotate(dcoTrg, dcoSrc, ulAvec, dcoTrg.pdc->jStretchBltMode()));
  2494. }
  2495. // We can now set the target rectangle
  2496. if (!blt.Trg(x, y, cx, cy))
  2497. {
  2498. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2499. return(FALSE);
  2500. }
  2501. // If there is a source and we scale, send the call away. Note that
  2502. // since the mask extent is cleverly placed in aptlSrc if there is no
  2503. // source, maskblts that scale will get sent to bStretch().
  2504. if ((ulAvec & AVEC_NEED_SOURCE) && !blt.bEqualExtents())
  2505. return(blt.bStretch(dcoTrg, dcoSrc, ulAvec, dcoTrg.pdc->jStretchBltMode()));
  2506. return(blt.bBitBlt(dcoTrg, dcoSrc, ulAvec));
  2507. }
  2508. /******************************Public*Routine******************************\
  2509. * BLTRECORD::bBitBlt(dcoTrg, dcoSrc, ulAvec)
  2510. *
  2511. * Do a bitblt from the blt record
  2512. *
  2513. * History:
  2514. * 18-Mar-1992 -by- Donald Sidoroff [donalds]
  2515. * Wrote it.
  2516. \**************************************************************************/
  2517. BOOL BLTRECORD::bBitBlt(
  2518. DCOBJ& dcoTrg,
  2519. DCOBJ& dcoSrc,
  2520. ULONG ulAvec)
  2521. {
  2522. //
  2523. // Make the target rectangle well ordered.
  2524. //
  2525. perclTrg()->vOrder();
  2526. //
  2527. // Compute the new Rao region if it's dirty. This can happen if
  2528. // we need clipping due to a rotation (the DEVLOCKBLTOBJ is obtained
  2529. // before we compute the clipping in the prgnAPI)
  2530. //
  2531. if (dcoTrg.pdc->bDirtyRao())
  2532. {
  2533. if (!dcoTrg.pdc->bCompute())
  2534. {
  2535. return(FALSE);
  2536. }
  2537. }
  2538. //
  2539. // Accumulate bounds. We can do this before knowing if the operation is
  2540. // successful because bounds can be loose.
  2541. //
  2542. if (dcoTrg.fjAccum())
  2543. dcoTrg.vAccumulate(*perclTrg());
  2544. //
  2545. // With a fixed DC origin we can change the target to SCREEN coordinates.
  2546. //
  2547. *perclTrg() += dcoTrg.eptlOrigin();
  2548. //
  2549. // Handle BitBlts without source
  2550. //
  2551. //
  2552. // Get an PDEV for dispatching
  2553. //
  2554. PDEVOBJ pdoTrg(pSurfTrg()->hdev());
  2555. if (!(ulAvec & AVEC_NEED_SOURCE))
  2556. {
  2557. ECLIPOBJ eco(dcoTrg.prgnEffRao(), *perclTrg());
  2558. //
  2559. // Check the target which is reduced by clipping.
  2560. //
  2561. if (eco.erclExclude().bEmpty())
  2562. {
  2563. return(TRUE);
  2564. }
  2565. //
  2566. // Before we call to the driver, validate that the mask will actually
  2567. // cover the entire target. Rememeber, the source extent equals the
  2568. // required size for the mask in cases with no source needed!
  2569. //
  2570. // The mask offsets must not be negative.
  2571. //
  2572. // cx and cy, which are stored in perclSrc, may be negative
  2573. //
  2574. // if cx is negative then the mask x points must be swapped
  2575. // if cy is negative then the mask y points must be swapped
  2576. //
  2577. if (perclSrc()->right < 0) {
  2578. LONG lTmp;
  2579. lTmp = aptlMask[0].x;
  2580. aptlMask[0].x = aptlMask[1].x;
  2581. aptlMask[1].x = lTmp;
  2582. }
  2583. if (perclSrc()->bottom < 0) {
  2584. LONG lTmp;
  2585. lTmp = aptlMask[0].y;
  2586. aptlMask[0].y = aptlMask[1].y;
  2587. aptlMask[1].y = lTmp;
  2588. }
  2589. if (pSurfMskOut() != (SURFACE *) NULL)
  2590. {
  2591. if ((aptlMask[0].x < 0) ||
  2592. (aptlMask[0].y < 0) ||
  2593. (pSurfMsk()->sizl().cx - aptlMask[0].x < ABS(perclSrc()->right)) ||
  2594. (pSurfMsk()->sizl().cy - aptlMask[0].y < ABS(perclSrc()->bottom)))
  2595. {
  2596. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2597. return(FALSE);
  2598. }
  2599. //
  2600. // Adjust the mask origin for clipping
  2601. //
  2602. aptlMask[0].x += eco.erclExclude().left - perclTrg()->left;
  2603. aptlMask[0].y += eco.erclExclude().top - perclTrg()->top;
  2604. }
  2605. //
  2606. // Exclude the pointer.
  2607. //
  2608. DEVEXCLUDEOBJ dxo(dcoTrg,&eco.erclExclude(),&eco);
  2609. //
  2610. // Inc the target surface uniqueness
  2611. //
  2612. INC_SURF_UNIQ(pSurfTrg());
  2613. //
  2614. // Dispatch the call.
  2615. //
  2616. return((*(pSurfTrg()->pfnBitBlt()))
  2617. (pSurfTrg()->pSurfobj(),
  2618. (SURFOBJ *) NULL,
  2619. pSurfMskOut()->pSurfobj(),
  2620. &eco,
  2621. NULL,
  2622. perclTrg(),
  2623. (POINTL *) NULL,
  2624. aptlMask,
  2625. pbo(),
  2626. aptlBrush,
  2627. rop4));
  2628. }
  2629. //
  2630. // Now compute the source rectangle
  2631. //
  2632. EPOINTL *peptlOff = (EPOINTL *) &aptlSrc[0];
  2633. EPOINTL *peptlSrc = (EPOINTL *) &aptlSrc[1];
  2634. peptlSrc->x = MIN(peptlSrc->x, peptlOff->x);
  2635. peptlSrc->y = MIN(peptlSrc->y, peptlOff->y);
  2636. ERECTL erclReduced;
  2637. //
  2638. // if cx or cy was negative then hte corosponding mask extents
  2639. // must be swapped
  2640. //
  2641. if (aptlSrc[0].x > aptlSrc[1].x) {
  2642. LONG lTmp;
  2643. lTmp = aptlMask[0].x;
  2644. aptlMask[0].x = aptlMask[1].x;
  2645. aptlMask[1].x = lTmp;
  2646. }
  2647. if (aptlSrc[0].y > aptlSrc[1].y) {
  2648. LONG lTmp;
  2649. lTmp = aptlMask[0].y;
  2650. aptlMask[0].y = aptlMask[1].y;
  2651. aptlMask[1].y = lTmp;
  2652. }
  2653. //
  2654. // If the source and target are the same surface, we won't have
  2655. // to DEVLOCK the source and other fun stuff.
  2656. //
  2657. if (dcoSrc.pSurface() == dcoTrg.pSurface())
  2658. {
  2659. //
  2660. // Compute the source surface origin, taking into account multi-mon
  2661. // and negative offsets:
  2662. //
  2663. LONG xOrigin = 0;
  2664. LONG yOrigin = 0;
  2665. PDEVOBJ pdoSrc(pSurfSrc()->hdev());
  2666. if ((pdoSrc.bValid()) && (pdoSrc.bPrimary(pSurfSrc())) && (pdoSrc.bMetaDriver()))
  2667. {
  2668. xOrigin = pdoSrc.pptlOrigin()->x;
  2669. yOrigin = pdoSrc.pptlOrigin()->y;
  2670. }
  2671. //
  2672. // Compute the offset between source and target, in screen coordinates.
  2673. //
  2674. peptlOff->x = perclTrg()->left - peptlSrc->x - dcoSrc.eptlOrigin().x;
  2675. peptlOff->y = perclTrg()->top - peptlSrc->y - dcoSrc.eptlOrigin().y;
  2676. //
  2677. // Take care of the source rectangle. We may have to reduce it. This is
  2678. // not good enough for a secure system, we are doing it so that the device
  2679. // driver can always assume that neither the source nor the target
  2680. // rectangles hang over the edge of a surface.
  2681. //
  2682. // Intersect the target with the source clipping window.
  2683. //
  2684. erclReduced.left = peptlOff->x + xOrigin;
  2685. erclReduced.top = peptlOff->y + yOrigin;
  2686. erclReduced.right = peptlOff->x + xOrigin + pSurfTrg()->sizl().cx;
  2687. erclReduced.bottom = peptlOff->y + yOrigin + pSurfTrg()->sizl().cy;
  2688. erclReduced *= *perclTrg();
  2689. ECLIPOBJ eco(dcoTrg.prgnEffRao(), erclReduced);
  2690. erclReduced = eco.erclExclude();
  2691. //
  2692. // Check the target which is reduced by clipping.
  2693. //
  2694. if (erclReduced.bEmpty())
  2695. {
  2696. return(TRUE);
  2697. }
  2698. //
  2699. // Before we call to the driver, validate that the mask will actually
  2700. // cover the entire target.
  2701. //
  2702. // aptlMask must not be negative.
  2703. //
  2704. // Blt Trg extents have already been ordered
  2705. //
  2706. if (pSurfMskOut() != (SURFACE *) NULL)
  2707. {
  2708. if ((aptlMask[0].x < 0) ||
  2709. (aptlMask[0].y < 0) ||
  2710. ((pSurfMsk()->sizl().cx - aptlMask[0].x) < (perclTrg()->right - perclTrg()->left)) ||
  2711. ((pSurfMsk()->sizl().cy - aptlMask[0].y) < (perclTrg()->bottom - perclTrg()->top)))
  2712. {
  2713. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2714. return(FALSE);
  2715. }
  2716. //
  2717. // Adjust the mask origin for clipping
  2718. //
  2719. aptlMask[0].x += eco.erclExclude().left - perclTrg()->left;
  2720. aptlMask[0].y += eco.erclExclude().top - perclTrg()->top;
  2721. }
  2722. //
  2723. // Compute the (reduced) origin.
  2724. //
  2725. peptlSrc->x = erclReduced.left - peptlOff->x;
  2726. peptlSrc->y = erclReduced.top - peptlOff->y;
  2727. //
  2728. // Compute the exclusion rectangle. (It's expanded to include the source.)
  2729. //
  2730. if (peptlSrc->x < erclReduced.left)
  2731. erclReduced.left = peptlSrc->x;
  2732. else
  2733. erclReduced.right += peptlSrc->x - erclReduced.left;
  2734. if (peptlSrc->y < erclReduced.top)
  2735. erclReduced.top = peptlSrc->y;
  2736. else
  2737. erclReduced.bottom += peptlSrc->y - erclReduced.top;
  2738. //
  2739. // Exclude the pointer from the output region and offset region.
  2740. //
  2741. DEVEXCLUDEOBJ dxo(dcoTrg,&erclReduced,&eco,peptlOff);
  2742. //
  2743. // Inc the target surface uniqueness
  2744. //
  2745. INC_SURF_UNIQ(pSurfTrg());
  2746. //
  2747. // Dispatch the call.
  2748. //
  2749. if (rop4 == 0xCCCC) {
  2750. //
  2751. // call copy bits if rop specifies srccopy
  2752. //
  2753. return((*PPFNGET(pdoTrg,CopyBits,pSurfTrg()->flags())) (
  2754. pSurfTrg()->pSurfobj(),
  2755. pSurfSrc()->pSurfobj(),
  2756. &eco,
  2757. NULL,
  2758. &eco.erclExclude(),
  2759. peptlSrc));
  2760. } else {
  2761. return((*(pSurfTrg()->pfnBitBlt())) (
  2762. pSurfTrg()->pSurfobj(),
  2763. pSurfSrc()->pSurfobj(),
  2764. pSurfMskOut()->pSurfobj(),
  2765. &eco,
  2766. NULL,
  2767. &eco.erclExclude(),
  2768. peptlSrc,
  2769. aptlMask,
  2770. pbo(),
  2771. aptlBrush,
  2772. rop4));
  2773. }
  2774. }
  2775. //
  2776. // If the devices are on different PDEV's and we are not targeting a meta driver
  2777. // then we can only succeed if the Engine
  2778. // manages one or both of the surfaces. Check for this.
  2779. //
  2780. // WINBUG #298689 4-4-2001 jasonha Handle any device stretch to Meta
  2781. BOOL bTrgMetaDriver = (dcoTrg.bSynchronizeAccess() && pdoTrg.bValid() && pdoTrg.bMetaDriver());
  2782. if (dcoTrg.hdev() != dcoSrc.hdev())
  2783. {
  2784. if (!bTrgMetaDriver)
  2785. {
  2786. if(((dcoTrg.pSurfaceEff()->iType() != STYPE_BITMAP)
  2787. || (dcoTrg.pSurfaceEff()->dhsurf() != NULL)) &&
  2788. ((dcoSrc.pSurfaceEff()->iType() != STYPE_BITMAP)
  2789. || (dcoSrc.pSurfaceEff()->dhsurf() != NULL)))
  2790. {
  2791. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2792. return(FALSE);
  2793. }
  2794. }
  2795. }
  2796. //
  2797. // Compute the source surface origin, taking into account multi-mon
  2798. // and negative offsets:
  2799. //
  2800. LONG xOrigin = 0;
  2801. LONG yOrigin = 0;
  2802. PDEVOBJ pdoSrc(pSurfSrc()->hdev());
  2803. if ((pdoSrc.bValid()) && (pdoSrc.bPrimary(pSurfSrc())) && (pdoSrc.bMetaDriver()))
  2804. {
  2805. xOrigin = pdoSrc.pptlOrigin()->x;
  2806. yOrigin = pdoSrc.pptlOrigin()->y;
  2807. }
  2808. //
  2809. // Compute the offset between source and dest, in screen coordinates.
  2810. //
  2811. peptlOff->x = perclTrg()->left - peptlSrc->x - dcoSrc.eptlOrigin().x;
  2812. peptlOff->y = perclTrg()->top - peptlSrc->y - dcoSrc.eptlOrigin().y;
  2813. //
  2814. // Take care of the source rectangle. We may have to reduce it. This is
  2815. // not good enough for a secure system, we are doing it so that the device
  2816. // driver can always assume that neither the source nor the destination
  2817. // rectangles hang over the edge of a surface.
  2818. // Intersect the dest with the source surface extents.
  2819. //
  2820. erclReduced.left = peptlOff->x + xOrigin;
  2821. erclReduced.top = peptlOff->y + yOrigin;
  2822. erclReduced.right = peptlOff->x + xOrigin + pSurfSrc()->sizl().cx;
  2823. erclReduced.bottom = peptlOff->y + yOrigin + pSurfSrc()->sizl().cy;
  2824. erclReduced *= *perclTrg();
  2825. ECLIPOBJ eco(dcoTrg.prgnEffRao(), erclReduced);
  2826. erclReduced = eco.erclExclude();
  2827. //
  2828. // Check the destination which is reduced by clipping.
  2829. //
  2830. if (erclReduced.bEmpty())
  2831. {
  2832. return(TRUE);
  2833. }
  2834. //
  2835. // Before we call to the driver, validate that the mask will actually
  2836. // cover the entire source/target.
  2837. //
  2838. if (pSurfMskOut() != (SURFACE *) NULL)
  2839. {
  2840. if ((aptlMask[0].x < 0) ||
  2841. (aptlMask[0].y < 0) ||
  2842. ((pSurfMsk()->sizl().cx - aptlMask[0].x) < (perclTrg()->right - perclTrg()->left)) ||
  2843. ((pSurfMsk()->sizl().cy - aptlMask[0].y) < (perclTrg()->bottom - perclTrg()->top)))
  2844. {
  2845. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2846. return(FALSE);
  2847. }
  2848. // Adjust the mask origin for clipping
  2849. aptlMask[0].x += eco.erclExclude().left - perclTrg()->left;
  2850. aptlMask[0].y += eco.erclExclude().top - perclTrg()->top;
  2851. }
  2852. //
  2853. // Compute the (reduced) origin.
  2854. //
  2855. peptlSrc->x = erclReduced.left - peptlOff->x;
  2856. peptlSrc->y = erclReduced.top - peptlOff->y;
  2857. //
  2858. // Get ready to exclude the cursor
  2859. //
  2860. DEVEXCLUDEOBJ dxo;
  2861. //
  2862. // They can't both be display so if the source is do the special stuff.
  2863. // The following code assumes there is only 1 display in the system.
  2864. //
  2865. if (dcoSrc.bDisplay())
  2866. {
  2867. erclReduced -= *peptlOff;
  2868. dxo.vExclude(dcoSrc.hdev(),&erclReduced,NULL);
  2869. }
  2870. else if (dcoTrg.bDisplay())
  2871. {
  2872. dxo.vExclude(dcoTrg.hdev(),&erclReduced,&eco);
  2873. }
  2874. //
  2875. // Inc the target surface uniqueness
  2876. //
  2877. INC_SURF_UNIQ(pSurfTrg());
  2878. //
  2879. // Dispatch the call.
  2880. //
  2881. if (rop4 == 0xCCCC) {
  2882. //
  2883. // call copy bits if rop specifies srccopy
  2884. //
  2885. return((*PPFNGET(pdoTrg,CopyBits,pSurfTrg()->flags())) (
  2886. pSurfTrg()->pSurfobj(),
  2887. pSurfSrc()->pSurfobj(),
  2888. &eco,
  2889. pexlo()->pxlo(),
  2890. &eco.erclExclude(),
  2891. peptlSrc));
  2892. } else {
  2893. return((*(pSurfTrg()->pfnBitBlt()))
  2894. (pSurfTrg()->pSurfobj(),
  2895. pSurfSrc()->pSurfobj(),
  2896. pSurfMskOut()->pSurfobj(),
  2897. &eco,
  2898. pexlo()->pxlo(),
  2899. &eco.erclExclude(),
  2900. peptlSrc,
  2901. aptlMask,
  2902. pbo(),
  2903. aptlBrush,
  2904. rop4));
  2905. }
  2906. }