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.

5715 lines
188 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: multi.cxx
  3. *
  4. * Supports splitting of request over multiple PDEVs
  5. *
  6. * Copyright (c) 1995-1999 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.hxx"
  9. extern PPALETTE DrvRealizeHalftonePalette(HDEV hdevPalette, BOOL bForce);
  10. BOOL gbMultiMonMismatchColor = FALSE;
  11. RECTL grclEmpty; // Implicitly initialized to (0,0,0,0)
  12. BYTE gaMixNeedsPattern[] = { 0, 0, 1, 1, 1, 1, 0, 1,
  13. 1, 1, 1, 0, 1, 1, 1, 1 };
  14. #define ROP4_NEEDS_PATTERN(rop4) ((((rop4) >> 4) ^ (rop4)) & 0x0f0f)
  15. // Work around for bug #362287
  16. // #define MIX_NEEDS_PATTERN(mix) (gaMixNeedsPattern[mix & 0xf])
  17. #define MIX_NEEDS_PATTERN(mix) (TRUE)
  18. #define REALIZE_HALFTONE_PALETTE(hdev) (DrvRealizeHalftonePalette((hdev),FALSE))
  19. typedef struct _MULTIFONTINFO
  20. {
  21. PVDEV pvdev;
  22. PVOID pv[1];
  23. } MULTIFONTINFO, *PMULTIFONTINFO;
  24. class MULTIFONT {
  25. private:
  26. FONTOBJ* pfoOrg;
  27. PMULTIFONTINFO pMultiFontInfo;
  28. public:
  29. MULTIFONT(FONTOBJ *pfo, LONG csurf, PVDEV pvdev)
  30. {
  31. /********************************************************************
  32. *********************************************************************
  33. MulDestroyFont calls this constructor with csurf of -1 and a
  34. pvdev of NULL if and only if pfo->pvConsumer != NULL. It needs to
  35. call the pvdev() method. csurf and pvdev are ONLY referenced if
  36. pfo->pvConsumer == NULL.
  37. *** KEEP IT THAT WAY***
  38. *********************************************************************
  39. ********************************************************************/
  40. pfoOrg = pfo;
  41. if (pfoOrg)
  42. {
  43. if (pfoOrg->pvConsumer == NULL)
  44. {
  45. pfoOrg->pvConsumer = (PVOID)EngAllocMem(FL_ZERO_MEMORY,
  46. (sizeof(MULTIFONTINFO) + ((csurf-1) *
  47. sizeof(PVOID))), 'lumG');
  48. pMultiFontInfo = (PMULTIFONTINFO)pfoOrg->pvConsumer;
  49. if (pMultiFontInfo)
  50. {
  51. pMultiFontInfo->pvdev = pvdev;
  52. }
  53. else
  54. {
  55. KdPrint(("MULTIFONT::MULTIFONT failed table allocation\n"));
  56. }
  57. }
  58. else
  59. {
  60. pMultiFontInfo = (PMULTIFONTINFO)pfoOrg->pvConsumer;
  61. }
  62. }
  63. }
  64. ~MULTIFONT()
  65. {
  66. if (pfoOrg)
  67. {
  68. pfoOrg->pvConsumer = pMultiFontInfo;
  69. }
  70. }
  71. BOOL Valid()
  72. {
  73. return (pMultiFontInfo ? TRUE : FALSE);
  74. }
  75. VOID DestroyTable()
  76. {
  77. if (pfoOrg && (pMultiFontInfo != NULL))
  78. {
  79. EngFreeMem(pMultiFontInfo);
  80. pMultiFontInfo = NULL;
  81. }
  82. }
  83. VOID LoadElement(LONG i)
  84. {
  85. if (pfoOrg)
  86. {
  87. pfoOrg->pvConsumer = pMultiFontInfo->pv[i];
  88. }
  89. }
  90. VOID StoreElement(LONG i)
  91. {
  92. if (pfoOrg)
  93. {
  94. pMultiFontInfo->pv[i] = pfoOrg->pvConsumer;
  95. }
  96. }
  97. PVDEV pvdev()
  98. {
  99. return pMultiFontInfo->pvdev;
  100. }
  101. };
  102. typedef struct _MULTIREALIZEDBRUSH
  103. {
  104. PVOID pvD;
  105. PVOID pvE;
  106. } MULTIREALIZEDBRUSH;
  107. typedef struct _MULTIBRUSHINFO
  108. {
  109. ULONG cSurfaces;
  110. MULTIREALIZEDBRUSH aBrush[1];
  111. } MULTIBRUSHINFO, *PMULTIBRUSHINFO;
  112. class MULTIBRUSH {
  113. private:
  114. BOOL bValid;
  115. EBRUSHOBJ* pboOrg;
  116. SURFACE* psurfOrg;
  117. XEPALOBJ palSurfOrg;
  118. PMULTIBRUSHINFO pMultiBrushInfo;
  119. ULONG iSolidColorOrg;
  120. PENGBRUSH pengbrushOrg;
  121. public:
  122. MULTIBRUSH(BRUSHOBJ *pbo,
  123. LONG csurf,
  124. PVDEV pvdev,
  125. SURFOBJ *pso,
  126. BOOL bPatternNeeded)
  127. {
  128. bValid = TRUE;
  129. // This function is monstrous and should probably be moved out of
  130. // line. But beware that 'bPatternNeeded' is often passed in as
  131. // a constant 'FALSE', meaning that for those case this currently
  132. // expands to nothing.
  133. pboOrg = (EBRUSHOBJ*) pbo;
  134. // pso might be NULL, so we make sure to check psurfOrg
  135. // whenever we use it.
  136. psurfOrg = SURFOBJ_TO_SURFACE(pso);
  137. // Invalidate other fields.
  138. pMultiBrushInfo = NULL;
  139. iSolidColorOrg = 0xffffffff;
  140. pengbrushOrg = (PENGBRUSH)-1;
  141. if (pboOrg)
  142. {
  143. // Early out for solid brush.
  144. if ((!bPatternNeeded) || (pboOrg->iSolidColor != 0xffffffff))
  145. {
  146. // Keep original color index for iSolidColor.
  147. iSolidColorOrg = pboOrg->iSolidColor;
  148. return;
  149. }
  150. // Save the original palette for the surface (since we will switch the surface)
  151. palSurfOrg = pboOrg->palSurf();
  152. if (pboOrg->pvRbrush == NULL)
  153. {
  154. LONG cj = (sizeof(MULTIBRUSHINFO) + ((csurf-1) * sizeof(MULTIREALIZEDBRUSH)));
  155. pboOrg->pvRbrush = BRUSHOBJ_pvGetRbrush(pboOrg);
  156. // It is possible that BRUSHOBJ_pvGetRbrush will fail because
  157. // the hatch type of the brush is NULL. In this case we have
  158. // pMultiBrushInfo == NULL even though there is a brush. This will
  159. // be ok because the pvRbrush will not be accessed for such a
  160. // brush.
  161. pMultiBrushInfo = (PMULTIBRUSHINFO)pboOrg->pvRbrush;
  162. if (pMultiBrushInfo)
  163. {
  164. memset (pMultiBrushInfo, 0, cj);
  165. pMultiBrushInfo->cSurfaces = pvdev->cSurfaces;
  166. PRBRUSH prbrush = (PDBRUSH)DBRUSHSTART(pboOrg->pvRbrush);
  167. prbrush->bMultiBrush(TRUE);
  168. }
  169. else
  170. {
  171. bValid = FALSE;
  172. }
  173. }
  174. else
  175. {
  176. pMultiBrushInfo = (PMULTIBRUSHINFO)pboOrg->pvRbrush;
  177. }
  178. }
  179. }
  180. ~MULTIBRUSH()
  181. {
  182. }
  183. BOOL Valid()
  184. {
  185. return (bValid);
  186. }
  187. VOID DestroyTable()
  188. {
  189. // NOTE: This routine MUST NOT access any data in from 'pvdev',
  190. // as the DDML may already be disabled, and 'pvdev' freed, when
  191. // this brush is deleted.
  192. if (pboOrg && (pMultiBrushInfo != NULL))
  193. {
  194. ULONG csurf = pMultiBrushInfo->cSurfaces;
  195. ASSERTGDI((csurf > 0), "Expected at least one surface in the list.");
  196. while (csurf)
  197. {
  198. csurf--;
  199. // Free the driver's DBRUSH if there is one
  200. PVOID pvRbrush;
  201. if (pvRbrush = pMultiBrushInfo->aBrush[csurf].pvD)
  202. {
  203. PRBRUSH prbrush = (PDBRUSH) DBRUSHSTART(pvRbrush);
  204. // point to DBRUSH (pvRbrush points to
  205. // realization, which is at the end of DBRUSH)
  206. prbrush->vRemoveRef(RB_DRIVER);
  207. // decrement the reference count on the
  208. // realization and free the brush if
  209. // this is the last reference
  210. pMultiBrushInfo->aBrush[csurf].pvD = NULL;
  211. }
  212. if (pvRbrush = pMultiBrushInfo->aBrush[csurf].pvE)
  213. {
  214. PRBRUSH prbrush = (PENGBRUSH) pvRbrush;
  215. // point to engine brush realization
  216. prbrush->vRemoveRef(RB_ENGINE);
  217. // decrement the reference count on the
  218. // realization and free the brush if
  219. // this is the last reference
  220. pMultiBrushInfo->aBrush[csurf].pvE = NULL;
  221. }
  222. }
  223. }
  224. }
  225. VOID LoadElement(DISPSURF *pds, SURFACE *psurf)
  226. {
  227. if (pboOrg)
  228. {
  229. // If psurf == NULL, we were called from MulDestroyBrush.
  230. // We just leave the brush associated with the multi layer.
  231. // Otherwise, associate it with the driver we're about to call.
  232. if (psurf != NULL)
  233. {
  234. if (pds->iCompatibleColorFormat != 0)
  235. {
  236. PDEVOBJ pdo(pds->hdev);
  237. PPALETTE ppalDC = ppalDefault;
  238. //
  239. // If this is palette managed device, use halftone palette.
  240. //
  241. if (pdo.bIsPalManaged())
  242. {
  243. ppalDC = REALIZE_HALFTONE_PALETTE(pdo.hdev());
  244. }
  245. //
  246. // If current device has higher color depth than primary
  247. // and this dithered brush. we don't use dithered brush
  248. // on this, just use solid color here... since this device
  249. // should be able to produce much colors...
  250. //
  251. if ((pds->iCompatibleColorFormat > 0) &&
  252. (pboOrg->iSolidColor == 0xffffffff) &&
  253. (pboOrg->crDCPalColor() != 0xffffffff))
  254. {
  255. // Try to map the solid color from surface palette.
  256. pboOrg->iSolidColor = ulGetNearestIndexFromColorref(
  257. psurf->ppal(),
  258. ppalDC,
  259. pboOrg->crDCPalColor());
  260. // Behave as solid color brush.
  261. pboOrg->pvRbrush = NULL;
  262. }
  263. //
  264. // If this is solid color, map color index in destination
  265. // device palette. we can not use the color index from
  266. // meta device when this is different color depth than
  267. // primary.
  268. //
  269. else if (pboOrg->iSolidColor != 0xffffffff)
  270. {
  271. // Try to map the solid color from surface palette.
  272. pboOrg->iSolidColor = ulGetNearestIndexFromColorref(
  273. psurf->ppal(),
  274. ppalDC,
  275. pboOrg->crDCPalColor());
  276. // ASSERTGDI(pboOrg->pvRbrush == NULL,
  277. // "MBRUSH:LoadElement(): solid brush, but Rbrush != NULL\n");
  278. }
  279. else if (pMultiBrushInfo)
  280. {
  281. // Save the original engine brush, then replace with device specific one.
  282. pengbrushOrg = pboOrg->pengbrush();
  283. pboOrg->pengbrush((ENGBRUSH *)(pMultiBrushInfo->aBrush[pds->iDispSurf].pvE));
  284. // Get device specifc Dbrush.
  285. pboOrg->pvRbrush = pMultiBrushInfo->aBrush[pds->iDispSurf].pvD;
  286. }
  287. }
  288. else if (pMultiBrushInfo)
  289. {
  290. // Get device specifc Dbrush.
  291. pboOrg->pvRbrush = pMultiBrushInfo->aBrush[pds->iDispSurf].pvD;
  292. }
  293. if (pMultiBrushInfo)
  294. {
  295. pboOrg->psoTarg(psurf);
  296. if (psurf->ppal())
  297. {
  298. pboOrg->palSurf(psurf->ppal());
  299. }
  300. }
  301. }
  302. }
  303. }
  304. VOID StoreElement(LONG i)
  305. {
  306. if (pboOrg)
  307. {
  308. if (pMultiBrushInfo)
  309. {
  310. // Restore engine brush (if saved)
  311. if (pengbrushOrg != (PENGBRUSH)-1)
  312. {
  313. #if DBG
  314. if (pengbrushOrg)
  315. {
  316. // Make sure the engbrush is not freed.
  317. // If freed, this might causes bugcheck.
  318. pengbrushOrg->vAddRef();
  319. pengbrushOrg->vRemoveRef(RB_ENGINE);
  320. }
  321. #endif
  322. pMultiBrushInfo->aBrush[i].pvE = pboOrg->pengbrush();
  323. pboOrg->pengbrush(pengbrushOrg);
  324. pengbrushOrg = (PENGBRUSH)-1;
  325. }
  326. // Restore device brush.
  327. pMultiBrushInfo->aBrush[i].pvD = pboOrg->pvRbrush;
  328. if (psurfOrg)
  329. {
  330. pboOrg->psoTarg(psurfOrg);
  331. }
  332. if (palSurfOrg.bValid())
  333. {
  334. pboOrg->palSurf(palSurfOrg);
  335. }
  336. }
  337. pboOrg->iSolidColor = iSolidColorOrg;
  338. pboOrg->pvRbrush = pMultiBrushInfo;
  339. }
  340. }
  341. };
  342. /******************************Public*Routine******************************\
  343. * BOOL GreIsPaletteDisplay
  344. *
  345. * Return TRUE if the display is palettized
  346. *
  347. * History:
  348. * 1-Jan-1997 -by- Vadim Gorokhovsky [vadimg]
  349. \**************************************************************************/
  350. BOOL GreIsPaletteDisplay(HDEV hdev)
  351. {
  352. PDEVOBJ po(hdev);
  353. ASSERTGDI(po.bValid(), "Invalid PDEV");
  354. return (po.GdiInfoNotDynamic()->flRaster & RC_PALETTE);
  355. }
  356. /******************************Public*Routine******************************\
  357. * BOOL bIntersect
  358. *
  359. * If 'prcl1' and 'prcl2' intersect, has a return value of TRUE and returns
  360. * the intersection in 'prclResult'. If they don't intersect, has a return
  361. * value of FALSE, and 'prclResult' is undefined.
  362. *
  363. \**************************************************************************/
  364. BOOL FASTCALL bIntersect(
  365. CONST RECTL* prcl1,
  366. CONST RECTL* prcl2,
  367. RECTL* prclResult)
  368. {
  369. prclResult->left = max(prcl1->left, prcl2->left);
  370. prclResult->right = min(prcl1->right, prcl2->right);
  371. if (prclResult->left < prclResult->right)
  372. {
  373. prclResult->top = max(prcl1->top, prcl2->top);
  374. prclResult->bottom = min(prcl1->bottom, prcl2->bottom);
  375. if (prclResult->top < prclResult->bottom)
  376. {
  377. return(TRUE);
  378. }
  379. }
  380. return(FALSE);
  381. }
  382. /******************************Public*Routine******************************\
  383. * BOOL bIntersect
  384. *
  385. * Returns TRUE if 'prcl1' and 'prcl2' intersect.
  386. *
  387. \**************************************************************************/
  388. BOOL FASTCALL bIntersect(
  389. CONST RECTL* prcl1,
  390. CONST RECTL* prcl2)
  391. {
  392. return((prcl1->left < prcl2->right) &&
  393. (prcl1->top < prcl2->bottom) &&
  394. (prcl1->right > prcl2->left) &&
  395. (prcl1->bottom > prcl2->top));
  396. }
  397. /******************************Public*Routine******************************\
  398. * BOOL bContains
  399. *
  400. * Returns TRUE if 'prcl1' contains 'prcl2'.
  401. *
  402. \**************************************************************************/
  403. BOOL FASTCALL bContains(
  404. CONST RECTL* prcl1,
  405. CONST RECTL* prcl2)
  406. {
  407. return((prcl1->left <= prcl2->left) &&
  408. (prcl1->right >= prcl2->right) &&
  409. (prcl1->top <= prcl2->top) &&
  410. (prcl1->bottom >= prcl2->bottom));
  411. }
  412. /******************************Public*Routine******************************\
  413. * BOOL MSURF::bFindSurface
  414. *
  415. * Given the drawing bounds and clip object, this routine finds a surface
  416. * that will be affected by the drawing. The child surface's driver should
  417. * then be called using MSURF's public 'pso' surface and 'pco' clip object
  418. * members.
  419. *
  420. * If no surface can be found (the drawing is occuring off-screen from all
  421. * video cards), FALSE is returned.
  422. *
  423. \**************************************************************************/
  424. BOOL MSURF::bFindSurface(
  425. SURFOBJ* psoOriginal,
  426. CLIPOBJ* pcoOriginal,
  427. RECTL* prclDraw)
  428. {
  429. GDIFunctionID(MSURF::bFindSurface);
  430. pvdev = (VDEV*) psoOriginal->dhpdev;
  431. ASSERTGDI((prclDraw->left < prclDraw->right) &&
  432. (prclDraw->top < prclDraw->bottom),
  433. "Poorly ordered draw rectangle");
  434. pmdsurf = NULL;
  435. if (psoOriginal->iType == STYPE_DEVBITMAP)
  436. {
  437. PDEVOBJ pdo(psoOriginal->hdev);
  438. ASSERTGDI(pdo.bValid() && pdo.bMetaDriver(), "Surface is not a valid Meta surface");
  439. // Some drivers want to hook drawing calls to device bitmaps and
  440. // DIBs. We handle those cases here.
  441. pmdsurf = (MDSURF*) psoOriginal->dhsurf;
  442. ASSERTGDI(pmdsurf != NULL, "Unexpected NULL dhsurf");
  443. pco = pcoOriginal;
  444. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  445. {
  446. if (pmdsurf->apso[pds->iDispSurf] != NULL)
  447. {
  448. pso = pmdsurf->apso[pds->iDispSurf];
  449. pOffset = &gptlZero;
  450. return(TRUE);
  451. }
  452. }
  453. }
  454. else
  455. {
  456. // Okay, the drawing is to the screen:
  457. if ((pcoOriginal == NULL) || (pcoOriginal->iDComplexity == DC_TRIVIAL))
  458. {
  459. pco = pvdev->pco;
  460. iOriginalDComplexity = DC_TRIVIAL;
  461. rclOriginalBounds = pco->rclBounds;
  462. rclDraw = *prclDraw;
  463. }
  464. else
  465. {
  466. pco = pcoOriginal;
  467. iOriginalDComplexity = pco->iDComplexity;
  468. rclOriginalBounds = pco->rclBounds;
  469. // Intersect the drawing bounds with the clipping bounds, because
  470. // we touch pixels that intersect both:
  471. if (!bIntersect(prclDraw, &rclOriginalBounds, &rclDraw))
  472. {
  473. return(FALSE);
  474. }
  475. }
  476. // Find the first surface that is affected:
  477. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  478. {
  479. // WINBUG #340569 3-29-2001 jasonha
  480. // Prevent access to screen during mode change / full screen mode
  481. if (!pds->po.bDisabled())
  482. {
  483. // First, test for the trivial case where the drawing is
  484. // contained entirely within this surface:
  485. if ((iOriginalDComplexity == DC_TRIVIAL) &&
  486. (rclDraw.left >= pds->rcl.left) &&
  487. (rclDraw.top >= pds->rcl.top) &&
  488. (rclDraw.right <= pds->rcl.right) &&
  489. (rclDraw.bottom <= pds->rcl.bottom))
  490. {
  491. pco->iDComplexity = DC_TRIVIAL;
  492. pco->rclBounds = rclDraw;
  493. pso = pds->pso;
  494. pOffset = &pds->Off;
  495. return(TRUE);
  496. }
  497. else if (bIntersect(&rclDraw, &pds->rcl, &pco->rclBounds))
  498. {
  499. // Since the drawing is not contained entirely within this
  500. // surface, then we don't have DC_TRIVIAL clipping:
  501. pco->iDComplexity = (iOriginalDComplexity != DC_TRIVIAL)
  502. ? iOriginalDComplexity
  503. : DC_RECT;
  504. pso = pds->pso;
  505. pOffset = &pds->Off;
  506. return(TRUE);
  507. }
  508. }
  509. }
  510. // Restore everything originally passed in that we modified:
  511. pco->rclBounds = rclOriginalBounds;
  512. pco->iDComplexity = iOriginalDComplexity;
  513. }
  514. return(FALSE);
  515. }
  516. /******************************Public*Routine******************************\
  517. * BOOL MSURF::bNextSurface
  518. *
  519. * Finds the next driver surface that is affected by the drawing call.
  520. *
  521. * Returns FALSE if no surface can be found.
  522. *
  523. \**************************************************************************/
  524. BOOL MSURF::bNextSurface()
  525. {
  526. if (pmdsurf != NULL)
  527. {
  528. // Find the next driver that wants to hook drawing to device
  529. // bitmaps and DIBs.
  530. for (pds = pds->pdsNext; pds != NULL; pds = pds->pdsNext)
  531. {
  532. if (pmdsurf->apso[pds->iDispSurf] != NULL)
  533. {
  534. pso = pmdsurf->apso[pds->iDispSurf];
  535. pOffset = &gptlZero;
  536. return(TRUE);
  537. }
  538. }
  539. }
  540. else
  541. {
  542. // Find the next driver that is affected by this drawing to the
  543. // screen.
  544. for (pds = pds->pdsNext; pds != NULL; pds = pds->pdsNext)
  545. {
  546. // WINBUG #340569 3-29-2001 jasonha
  547. // Prevent access to screen during mode change / full screen mode
  548. if (!pds->po.bDisabled())
  549. {
  550. // First, test for the trivial case where the drawing is
  551. // contained entirely within this surface:
  552. if ((iOriginalDComplexity == DC_TRIVIAL) &&
  553. (rclDraw.left >= pds->rcl.left) &&
  554. (rclDraw.top >= pds->rcl.top) &&
  555. (rclDraw.right <= pds->rcl.right) &&
  556. (rclDraw.bottom <= pds->rcl.bottom))
  557. {
  558. pco->iDComplexity = DC_TRIVIAL;
  559. pso = pds->pso;
  560. pOffset = &pds->Off;
  561. return(TRUE);
  562. }
  563. else if (bIntersect(&rclDraw, &pds->rcl, &pco->rclBounds))
  564. {
  565. // Since the drawing is not contained entirely within this
  566. // surface, then we don't have DC_TRIVIAL clipping:
  567. pco->iDComplexity = (iOriginalDComplexity != DC_TRIVIAL)
  568. ? iOriginalDComplexity
  569. : DC_RECT;
  570. pso = pds->pso;
  571. pOffset = &pds->Off;
  572. return(TRUE);
  573. }
  574. }
  575. }
  576. // Restore everything originally passed in that we modified:
  577. pco->rclBounds = rclOriginalBounds;
  578. pco->iDComplexity = iOriginalDComplexity;
  579. }
  580. return(FALSE);
  581. }
  582. /******************************Member*Routine******************************\
  583. * MSURF::vRestore
  584. *
  585. * Restores state that may have been changed by bFindSurface/bNextSurface.
  586. *
  587. * Note: This must always be used when bFindSurface/bNextSurface return
  588. * TRUE, but won't be called again. (Early loop termination.)
  589. *
  590. \**************************************************************************/
  591. void MSURF::vRestore()
  592. {
  593. // WINBUG: 451121 pravins 08/07/2001 Should be checking for non DEVBITMAP case here. For time being just check the PCO.
  594. if (pmdsurf != NULL && pco != NULL)
  595. {
  596. // Restore everything originally passed in that we modified:
  597. pco->rclBounds = rclOriginalBounds;
  598. pco->iDComplexity = iOriginalDComplexity;
  599. }
  600. }
  601. /*****************************Private*Routine******************************\
  602. * MULTISURF::vInit
  603. *
  604. * Initializes members and prepares default source surface values
  605. *
  606. \**************************************************************************/
  607. void
  608. MULTISURF::vInit(
  609. SURFOBJ *psoOriginal,
  610. RECTL *prclOriginal
  611. )
  612. {
  613. GDIFunctionID(MULTISURF::vInit);
  614. pso = psoOriginal;
  615. prcl = &rclOrg;
  616. fl = 0;
  617. pmdsurf = NULL;
  618. if (psoOriginal != NULL)
  619. {
  620. rclOrg = *prclOriginal;
  621. dhpdevOrg = psoOriginal->dhpdev;
  622. // Is this a device associated bitmap?
  623. if (dhpdevOrg != NULL)
  624. {
  625. // Save original source settings
  626. psurfOrg = SURFOBJ_TO_SURFACE_NOT_NULL(psoOriginal);
  627. dhsurfOrg = psurfOrg->dhsurf();
  628. flagsOrg = psurfOrg->flags();
  629. PDEVOBJ pdo(psurfOrg->hdev());
  630. ASSERTGDI(pdo.bValid(), "Source doesn't have a valid HDEV");
  631. // Setup up source
  632. if (psurfOrg->iType() == STYPE_DEVBITMAP && pdo.bMetaDriver())
  633. {
  634. pmdsurf = (MDSURF*) dhsurfOrg;
  635. ASSERTGDI(psurfOrg->pvBits() != NULL, "Meta DEVBITMAP doesn't have pvBits");
  636. // Unmark source to make it look like a DIB
  637. fl = MULTISURF_SET_AS_DIB;
  638. psurfOrg->iType(STYPE_BITMAP);
  639. psurfOrg->dhsurf(NULL);
  640. psurfOrg->dhpdev(NULL);
  641. psurfOrg->flags(0);
  642. }
  643. else
  644. {
  645. // Is the surface opaque or does it live in video memory?
  646. if (psurfOrg->iType() != STYPE_BITMAP ||
  647. pso->fjBitmap & BMF_NOTSYSMEM)
  648. {
  649. fl = MULTISURF_USE_COPY;
  650. }
  651. }
  652. }
  653. }
  654. else
  655. {
  656. dhpdevOrg = NULL;
  657. }
  658. }
  659. /*****************************Private*Routine******************************\
  660. * MULTISURF::bCreateDIB
  661. *
  662. * Creates a DIB copy of the original surface and computes an adjusted
  663. * rectangle/origin for the surface.
  664. *
  665. \**************************************************************************/
  666. BOOL
  667. MULTISURF::bCreateDIB()
  668. {
  669. GDIFunctionID(MULTISURF::bCreateDIB);
  670. ASSERTGDI(!SurfDIB.bValid(), "SurfDIB already created");
  671. PDEVOBJ pdo(psurfOrg->hdev());
  672. ERECTL erclTrim(0L,
  673. 0L,
  674. psurfOrg->sizl().cx,
  675. psurfOrg->sizl().cy);
  676. // Find intersection of surface and area needed
  677. erclTrim *= rclOrg;
  678. ERECTL erclTmp(0L,
  679. 0L,
  680. erclTrim.right - erclTrim.left,
  681. erclTrim.bottom - erclTrim.top);
  682. DEVBITMAPINFO dbmi;
  683. dbmi.iFormat = psurfOrg->iFormat();
  684. dbmi.cxBitmap = erclTmp.right;
  685. dbmi.cyBitmap = erclTmp.bottom;
  686. dbmi.hpal = psurfOrg->ppal() ? (HPALETTE)psurfOrg->ppal()->hGet() : 0;
  687. ASSERTGDI(!psurfOrg->bUMPD(), "UMPD surface");
  688. dbmi.fl = BMF_TOPDOWN;
  689. if (!SurfDIB.bCreateDIB(&dbmi, NULL))
  690. {
  691. WARNING("Failed SurfDIB memory allocation\n");
  692. return FALSE;
  693. }
  694. (*PPFNDRV(pdo,CopyBits)) (SurfDIB.pSurfobj(),
  695. &psurfOrg->so,
  696. (CLIPOBJ *) NULL,
  697. NULL,
  698. (PRECTL) &erclTmp,
  699. (POINTL *) &erclTrim);
  700. rclDIB.left = prcl->left - erclTrim.left;
  701. rclDIB.top = prcl->top - erclTrim.top;
  702. rclDIB.right = prcl->right - erclTrim.left;
  703. rclDIB.bottom = prcl->bottom - erclTrim.top;
  704. return TRUE;
  705. }
  706. /*****************************Public*Members*******************************\
  707. * BOOL MULTISURF::bLoadSource (2 versions)
  708. *
  709. * Prepares the next source surface for the given destination as follows:
  710. *
  711. * For a non-device BITMAP (dhpdev = NULL), the orignal surface is used.
  712. *
  713. * For a Meta DEVBITMAP, a matching device surface is used or if there
  714. * isn't a match the backing DIB is used (unmarked during vInit).
  715. *
  716. * For other surfaces, if the destination device is different the original
  717. * surface is unmarked to look like a DIB when the bits are present in
  718. * system memory or a DIB copy is created.
  719. *
  720. * Returns FALSE if no surface can be prepared.
  721. *
  722. \**************************************************************************/
  723. BOOL MULTISURF::bLoadSource(
  724. DISPSURF* pdsDst
  725. )
  726. {
  727. GDIFunctionID(MULTISURF::bLoadSource);
  728. BOOL bRet = TRUE;
  729. // If this is a device bitmap, there is work to do.
  730. if (dhpdevOrg != NULL)
  731. {
  732. if (pmdsurf != NULL)
  733. {
  734. // Meta DEVBITMAP:
  735. // Use device managed bitmap for source, else go for the DIB
  736. pso = pmdsurf->apso[pdsDst->iDispSurf];
  737. if (pso == NULL)
  738. {
  739. pso = &psurfOrg->so;
  740. }
  741. }
  742. else
  743. {
  744. bRet = bLoadSourceNotMetaDEVBITMAP(pdsDst->hdev);
  745. }
  746. }
  747. return bRet;
  748. }
  749. BOOL MULTISURF::bLoadSource(
  750. HDEV hdevDst
  751. )
  752. {
  753. GDIFunctionID(MULTISURF::bLoadSource);
  754. BOOL bRet = TRUE;
  755. // If this is a device bitmap, there is work to do.
  756. if (dhpdevOrg != NULL)
  757. {
  758. if (pmdsurf != NULL)
  759. {
  760. // Meta DEVBITMAP:
  761. // Use device managed bitmap for source, else go for the DIB
  762. VDEV *pvdev = pmdsurf->pvdev;
  763. DISPSURF *pds;
  764. ASSERTGDI(pvdev != NULL, "pvdev is NULL.\n");
  765. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  766. {
  767. if (pds->hdev == hdevDst)
  768. {
  769. pso = pmdsurf->apso[pds->iDispSurf];
  770. break;
  771. }
  772. }
  773. if (pso == NULL)
  774. {
  775. pso = &psurfOrg->so;
  776. }
  777. }
  778. else
  779. {
  780. bRet = bLoadSourceNotMetaDEVBITMAP(hdevDst);
  781. }
  782. }
  783. return bRet;
  784. }
  785. /*****************************Private*Member*******************************\
  786. * BOOL MULTISURF::bLoadSourceNotMetaDEVBITMAP
  787. *
  788. * If the destination device is different the original surface is unmarked
  789. * to look like a DIB when the bits are present in system memory or a DIB
  790. * copy is created.
  791. *
  792. * Returns FALSE if no surface can be prepared.
  793. *
  794. * NOTE: This routine assumes BITMAPs and Meta DEVBITMAPs have already been
  795. * handled and won't come here. See bLoadSource members.
  796. *
  797. \**************************************************************************/
  798. BOOL MULTISURF::bLoadSourceNotMetaDEVBITMAP(
  799. HDEV hdevDst
  800. )
  801. {
  802. GDIFunctionID(MULTISURF::bLoadSourceNotMetaDEVBITMAP);
  803. if (fl & MULTISURF_USE_COPY)
  804. {
  805. // Opaque or video memory surface:
  806. // Use a DIB copy if destination doesn't match the source
  807. if (psurfOrg->hdev() != hdevDst)
  808. {
  809. // Do we already have a DIB copy?
  810. if (!SurfDIB.bValid())
  811. {
  812. // Allocate an intermediate DIB for a source
  813. if (!bCreateDIB())
  814. {
  815. return FALSE;
  816. }
  817. }
  818. // Make pso and prcl point to the copy
  819. pso = SurfDIB.pSurfobj();
  820. prcl = &rclDIB;
  821. }
  822. else
  823. {
  824. // Just use original surface
  825. pso = &psurfOrg->so;
  826. prcl = &rclOrg;
  827. }
  828. }
  829. else
  830. {
  831. // BITMAP in system memory:
  832. // Unmark to appear as DIB if destination doesn't match the source
  833. if (psurfOrg->hdev() != hdevDst)
  834. {
  835. if (!(fl & MULTISURF_SET_AS_DIB))
  836. {
  837. if (!(fl & MULTISURF_SYNCHRONIZED))
  838. {
  839. PDEVOBJ pdo(psurfOrg->hdev());
  840. pdo.vSync(pso, prcl, 0);
  841. fl |= MULTISURF_SYNCHRONIZED;
  842. }
  843. // Unset fields to look like a DIB
  844. fl |= MULTISURF_SET_AS_DIB;
  845. psurfOrg->dhpdev(NULL);
  846. psurfOrg->dhsurf(NULL);
  847. psurfOrg->flags(0);
  848. }
  849. }
  850. else
  851. {
  852. if (fl & MULTISURF_SET_AS_DIB)
  853. {
  854. // Restore original settings
  855. fl &= ~MULTISURF_SET_AS_DIB;
  856. psurfOrg->dhpdev(dhpdevOrg);
  857. psurfOrg->dhsurf(dhsurfOrg);
  858. psurfOrg->flags(flagsOrg);
  859. }
  860. }
  861. }
  862. return TRUE;
  863. }
  864. /******************************Public*Routine******************************\
  865. * BOOL MulEnableDriver
  866. *
  867. * Standard driver DrvEnableDriver function
  868. *
  869. \**************************************************************************/
  870. BOOL MulEnableDriver(
  871. ULONG iEngineVersion,
  872. ULONG cj,
  873. DRVENABLEDATA* pded)
  874. {
  875. pded->pdrvfn = gadrvfnMulti;
  876. pded->c = gcdrvfnMulti;
  877. pded->iDriverVersion = DDI_DRIVER_VERSION_NT5;
  878. return(TRUE);
  879. }
  880. /******************************Public*Routine******************************\
  881. * DHPDEV MulEnablePDEV
  882. *
  883. * Creates a single large VDEV that will represent the combination of other
  884. * smaller PDEVs
  885. *
  886. * This function creates an internal structure that keeps the location of
  887. * the various cards, and also keeps the appropriate data structures to
  888. * be passed down to each driver.
  889. *
  890. \**************************************************************************/
  891. DHPDEV MulEnablePDEV(
  892. DEVMODEW *pdm,
  893. LPWSTR pwszLogAddress,
  894. ULONG cPat,
  895. HSURF *phsurfPatterns,
  896. ULONG cjCaps,
  897. GDIINFO *pdevcaps,
  898. ULONG cjDevInfo,
  899. DEVINFO *pdi,
  900. HDEV hdev,
  901. LPWSTR pwszDeviceName,
  902. HANDLE hDriver)
  903. {
  904. PMDEV pmdev = (PMDEV) pdm;
  905. PVDEV pvdev;
  906. DISPSURF dsAnchor;
  907. DISPSURF* pds;
  908. DISPSURF* pdsPrev;
  909. DISPSURF* pdsTmp;
  910. HDEV* paHdev;
  911. ULONG i,j;
  912. ULONG flGraphicsCaps = 0xffffffff;
  913. ULONG flGraphicsCaps2 = 0xffffffff;
  914. HDEV hdevPrimary = NULL;
  915. BOOL bPrimaryPalManaged = FALSE;
  916. pdsPrev = &dsAnchor;
  917. // Create the main multi dispsurf structure.
  918. LONG cjAlloc = ((sizeof(VDEV)) + (sizeof(DISPSURF) * pmdev->chdev));
  919. pvdev = (VDEV*) EngAllocMem(FL_ZERO_MEMORY, cjAlloc, 'vdVG');
  920. if (pvdev == NULL)
  921. return(NULL);
  922. paHdev = (HDEV*) EngAllocMem(FL_ZERO_MEMORY, sizeof(HDEV) * pmdev->chdev, 'sdvG');
  923. if (paHdev == NULL)
  924. {
  925. EngFreeMem(pvdev);
  926. return(NULL);
  927. }
  928. pds = (DISPSURF*) ((BYTE*)pvdev + sizeof(VDEV));
  929. pvdev->cSurfaces = pmdev->chdev;
  930. pvdev->hdev = hdev;
  931. // Loop through the list of MDEVs passed in.
  932. pvdev->rclBounds.left = 0x7fffffff;
  933. pvdev->rclBounds.top = 0x7fffffff;
  934. pvdev->rclBounds.right = 0x80000000;
  935. pvdev->rclBounds.bottom = 0x80000000;
  936. ASSERTGDI((pmdev->chdev > 0), "Expected at least one surface in the list.");
  937. for (i = 0; i < pmdev->chdev; i++)
  938. {
  939. // Set this PDEV as parent to each of the PDEVs that we'll manage.
  940. PDEVOBJ pdo(pmdev->Dev[i].hdev);
  941. #if TEXTURE_DEMO
  942. if ((pmdev->Dev[i].rect.left == 0) && (pmdev->Dev[i].rect.top == 0))
  943. #else
  944. if (pdo.ppdev->pGraphicsDevice->stateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
  945. #endif
  946. {
  947. ASSERTGDI(!hdevPrimary, "2 or more primary devices in MulEnablePDEV");
  948. ASSERTGDI(pmdev->Dev[i].rect.left == 0, "mispositioned primary");
  949. ASSERTGDI(pmdev->Dev[i].rect.top == 0, "mispositioned primary");
  950. hdevPrimary = pdo.hdev();
  951. bPrimaryPalManaged = pdo.bIsPalManaged();
  952. *pdevcaps = *pdo.GdiInfo();
  953. *pdi = *pdo.pdevinfo();
  954. }
  955. // Take the intersection of flags that are capabilities.
  956. flGraphicsCaps &= pdo.pdevinfo()->flGraphicsCaps;
  957. flGraphicsCaps2 &= pdo.pdevinfo()->flGraphicsCaps2;
  958. pdsPrev->pdsNext = pds;
  959. pdsPrev->pdsBltNext = pds;
  960. pds->iDispSurf = i;
  961. pds->rcl = *((PRECTL) &(pmdev->Dev[i].rect));
  962. pds->hdev = pmdev->Dev[i].hdev;
  963. pds->po.vInit(pds->hdev);
  964. pds->po.vReferencePdev();
  965. pds->Off.x = -pdo.pptlOrigin()->x;
  966. pds->Off.y = -pdo.pptlOrigin()->y;
  967. pds->pso = pdo.pSurface()->pSurfobj();
  968. // Primary (readable) surfaces are always first in the MDEV structure;
  969. // Secondary (non-readable) surfaces are always second. So if this
  970. // surfaces overlaps a previous one, this surface must be non-readable:
  971. pds->bIsReadable = TRUE;
  972. for (pdsTmp = dsAnchor.pdsNext; pdsTmp != pds; pdsTmp = pdsTmp->pdsNext)
  973. {
  974. if (bIntersect(&pdsTmp->rcl, &pds->rcl))
  975. pds->bIsReadable = FALSE;
  976. }
  977. // Adjust bounding rectangle:
  978. pvdev->rclBounds.left = min(pvdev->rclBounds.left, pds->rcl.left);
  979. pvdev->rclBounds.top = min(pvdev->rclBounds.top, pds->rcl.top);
  980. pvdev->rclBounds.right = max(pvdev->rclBounds.right, pds->rcl.right);
  981. pvdev->rclBounds.bottom = max(pvdev->rclBounds.bottom, pds->rcl.bottom);
  982. pdsPrev = pds;
  983. pds++;
  984. }
  985. ASSERTGDI(hdevPrimary, "No primary devices found in MulEnablePDEV");
  986. // Make these numbers negative since we don't want them scaled again
  987. // by GDI.
  988. pdevcaps->ulHorzSize = (ULONG) -((LONG)pdevcaps->ulHorzSize);
  989. pdevcaps->ulVertSize = (ULONG) -((LONG)pdevcaps->ulVertSize);
  990. // Plug in the intersection of the GCAPS:
  991. flGraphicsCaps &= ~(GCAPS_ASYNCMOVE | GCAPS_ASYNCCHANGE | GCAPS_PANNING);
  992. // If primary is palette managed device, make it Meta device palette managed, too.
  993. if (bPrimaryPalManaged)
  994. pdi->flGraphicsCaps = (flGraphicsCaps | GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
  995. else
  996. pdi->flGraphicsCaps = flGraphicsCaps;
  997. pdi->flGraphicsCaps2 = flGraphicsCaps2;
  998. pvdev->iBitmapFormat = pdi->iDitherFormat;
  999. // Set the root of the list of dispsurfs
  1000. pvdev->pds = dsAnchor.pdsNext;
  1001. pvdev->pdsBlt = dsAnchor.pdsNext;
  1002. // Set hdev primary
  1003. pvdev->hdevPrimary = hdevPrimary;
  1004. PDEVOBJ poMeta(hdev);
  1005. // Walk through pds list to check each device's colour depth and format
  1006. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1007. {
  1008. PDEVOBJ poThis(pds->hdev);
  1009. if (poThis.hdev() == hdevPrimary)
  1010. {
  1011. // This is primary PDEV. 0 means compatible.
  1012. pds->iCompatibleColorFormat = 0;
  1013. KdPrint(("GDI DDML: %ws - iDitherFormat is %d, and this is primary.\n",
  1014. ((PDEV *)(poThis.hdev()))->pGraphicsDevice->szWinDeviceName,
  1015. poThis.iDitherFormat()));
  1016. }
  1017. else
  1018. {
  1019. // Compare colour depth primary and this device.
  1020. //
  1021. // iCompatibleColorFormat will be ...
  1022. // 0 - same as the primary
  1023. // Plus value - higher colour depth than primary
  1024. // Minus value - lower colour depth than primary
  1025. pds->iCompatibleColorFormat = (poThis.iDitherFormat() - pvdev->iBitmapFormat);
  1026. KdPrint(("GDI DDML: %ws - iDitherFormat is %d.\n",
  1027. ((PDEV *)(poThis.hdev()))->pGraphicsDevice->szWinDeviceName,
  1028. poThis.iDitherFormat()));
  1029. KdPrint(("GDI DDML: %ws - PalManaged - %s\n",
  1030. ((PDEV *)(poThis.hdev()))->pGraphicsDevice->szWinDeviceName,
  1031. (poThis.bIsPalManaged() ? "Yes" : "No")));
  1032. // If colour depth is same check palette format.
  1033. if (pds->iCompatibleColorFormat == 0)
  1034. {
  1035. EPALOBJ palMeta(pdi->hpalDefault);
  1036. EPALOBJ palThis(poThis.pdevinfo()->hpalDefault);
  1037. // Compare the palette type.
  1038. //
  1039. // If not equal, treat it as 1 (this is higher colour depth than primary)
  1040. pds->iCompatibleColorFormat =
  1041. ((palMeta.iPalMode() == palThis.iPalMode()) ? 0 : 1);
  1042. KdPrint(("GDI DDML: %ws - iPalMode is %d.\n",
  1043. ((PDEV *)(poThis.hdev()))->pGraphicsDevice->szWinDeviceName,
  1044. palThis.iPalMode()));
  1045. if ((pds->iCompatibleColorFormat == 0) &&
  1046. (palMeta.iPalMode() == PAL_BITFIELDS))
  1047. {
  1048. // If the palette is bitfields, should check R, G, B assignment.
  1049. //
  1050. // If not equal, treat it as 1 (this is higher colour depth than primary)
  1051. pds->iCompatibleColorFormat =
  1052. (((palMeta.flRed() == palThis.flRed()) &&
  1053. (palMeta.flGre() == palThis.flGre()) &&
  1054. (palMeta.flBlu() == palThis.flBlu())) ? 0 : 1);
  1055. }
  1056. }
  1057. // Mark in global variable if one of device is not same as Meta.
  1058. if (pds->iCompatibleColorFormat != 0)
  1059. {
  1060. // mark hdev in this mdev does not have same color depth.
  1061. pmdev->ulFlags |= MDEV_MISMATCH_COLORDEPTH;
  1062. gbMultiMonMismatchColor = TRUE;
  1063. KdPrint(("GDI DDML: %ws is NOT compatible as primary.\n",
  1064. ((PDEV *)(poThis.hdev()))->pGraphicsDevice->szWinDeviceName));
  1065. }
  1066. else
  1067. {
  1068. // This flag should not be back to FALSE, if system once became mismatch
  1069. // color depth mode. This flag only can be FALSE, when system NEVER experience
  1070. // mismatch color depth mode since system booted.
  1071. //
  1072. // gbMultiMonMismatchColor = FALSE;
  1073. KdPrint(("GDI DDML: %ws is compatible as primary.\n",
  1074. ((PDEV *)(poThis.hdev()))->pGraphicsDevice->szWinDeviceName));
  1075. }
  1076. }
  1077. }
  1078. // Set the origin in the meta-PDEV. Note that we do NOT set 'ptlOffset'
  1079. // in the surface, as that would cause all our drawing to the meta-surface
  1080. // to be offset by that amount, which is NOT what we want.
  1081. poMeta.ppdev->ptlOrigin.x = pvdev->rclBounds.left;
  1082. poMeta.ppdev->ptlOrigin.y = pvdev->rclBounds.top;
  1083. poMeta.ppdev->sizlMeta.cx = pvdev->rclBounds.right - pvdev->rclBounds.left;
  1084. poMeta.ppdev->sizlMeta.cy = pvdev->rclBounds.bottom - pvdev->rclBounds.top;
  1085. // Mark this as Meta-PDEV.
  1086. poMeta.bMetaDriver(TRUE);
  1087. KdPrint(("GDI DDML: %li devices at (%li, %li, %li, %li).\n",
  1088. pmdev->chdev, pvdev->rclBounds.left, pvdev->rclBounds.top,
  1089. pvdev->rclBounds.right, pvdev->rclBounds.bottom));
  1090. #if TEXTURE_DEMO
  1091. if (ghdevTextureParent)
  1092. {
  1093. paHdev[0] = ghdevTextureParent;
  1094. vSpEnableMultiMon(hdev, 1, paHdev); // References 'paHdev'
  1095. return((DHPDEV) pvdev);
  1096. }
  1097. #endif
  1098. // Initialize Sprite stuff.
  1099. // (Put Mirroring device first, then other drivers).
  1100. j = 0;
  1101. for (i = 0; i < pmdev->chdev; i++)
  1102. {
  1103. PDEVOBJ pdoTmp(pmdev->Dev[i].hdev);
  1104. if (pdoTmp.flGraphicsCaps() & GCAPS_LAYERED)
  1105. {
  1106. paHdev[j++] = pmdev->Dev[i].hdev;
  1107. }
  1108. }
  1109. for (i = 0; i < pmdev->chdev; i++)
  1110. {
  1111. PDEVOBJ pdoTmp(pmdev->Dev[i].hdev);
  1112. if (!(pdoTmp.flGraphicsCaps() & GCAPS_LAYERED))
  1113. {
  1114. paHdev[j++] = pmdev->Dev[i].hdev;
  1115. }
  1116. }
  1117. vSpEnableMultiMon(hdev, pmdev->chdev, paHdev); // References 'paHdev'
  1118. return((DHPDEV) pvdev);
  1119. }
  1120. /******************************Public*Routine******************************\
  1121. * VOID MulDisablePDEV
  1122. *
  1123. * History:
  1124. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  1125. * Wrote it.
  1126. *
  1127. \**************************************************************************/
  1128. VOID MulDisablePDEV(DHPDEV dhpdev)
  1129. {
  1130. PVDEV pvdev;
  1131. DISPSURF* pds;
  1132. pvdev = (PVDEV) dhpdev;
  1133. vSpDisableMultiMon(pvdev->hdev); // Frees 'paHdev'
  1134. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1135. {
  1136. pds->po.vUnreferencePdev();
  1137. }
  1138. EngFreeMem(pvdev);
  1139. }
  1140. /******************************Public*Routine******************************\
  1141. * VOID MulCompletePDEV
  1142. *
  1143. * This function informs us of the 'hdev' that GDI has assigned us.
  1144. * We already got that initially information from MulEnablePDEV, but
  1145. * GDI reassigns 'hdev's during some mode changes.
  1146. *
  1147. * WINBUG #289937 01-23-2001 jasonha
  1148. * PDEV still has a reference after removing a monitor
  1149. *
  1150. * If we are being assigned an 'hdev' that was previously assigned to
  1151. * one of the children, then that child is taking over our previously
  1152. * assigned 'hdev'. We update our 'hdev's accordingly.
  1153. * NOTE: We must be able to grab ghsemDriverMgmt to successfully
  1154. * reference and unreference PDEV's.
  1155. *
  1156. * All of the layered drivers that have hdev changes have their
  1157. * DrvCompletePDEV functions called directly by GDI.
  1158. *
  1159. \**************************************************************************/
  1160. VOID MulCompletePDEV(
  1161. DHPDEV dhpdev,
  1162. HDEV hdev)
  1163. {
  1164. GDIFunctionID(MulCompletePDEV);
  1165. PVDEV pvdev = (PVDEV) dhpdev;
  1166. HDEV hdevPrev = pvdev->hdev;
  1167. DISPSURF* pds;
  1168. if (hdevPrev != hdev)
  1169. {
  1170. // Update hdevPrimary
  1171. if (pvdev->hdevPrimary == hdev)
  1172. {
  1173. pvdev->hdevPrimary = hdevPrev;
  1174. }
  1175. // Update child 'hdev's
  1176. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1177. {
  1178. if (pds->po.hdev() == hdev)
  1179. {
  1180. ASSERTGDI(pds->po.cPdevRefs() > 1, "Incorrect PDEV reference count.\n");
  1181. pds->po.vUnreferencePdev();
  1182. pds->hdev = hdevPrev;
  1183. pds->po.vInit(hdevPrev);
  1184. pds->po.vReferencePdev();
  1185. }
  1186. }
  1187. pvdev->hdev = hdev;
  1188. }
  1189. }
  1190. /******************************Public*Routine******************************\
  1191. * HSURF MulEnableSurface
  1192. *
  1193. * History:
  1194. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  1195. * Wrote it.
  1196. *
  1197. \**************************************************************************/
  1198. HSURF MulEnableSurface(DHPDEV dhpdev)
  1199. {
  1200. PVDEV pvdev;
  1201. PDISPSURF pds;
  1202. LONG csurf;
  1203. SIZEL sizlVirtual;
  1204. HSURF hsurfVirtual;
  1205. HSURF hsurf;
  1206. CLIPOBJ* pco;
  1207. SURFACE *psurf;
  1208. pvdev = (VDEV*) dhpdev;
  1209. // Note that we don't hook SYNCHRONIZE because we always return a
  1210. // device managed surface to GDI.
  1211. pvdev->flHooks = (HOOK_BITBLT
  1212. | HOOK_TEXTOUT
  1213. | HOOK_STROKEPATH
  1214. | HOOK_FILLPATH
  1215. | HOOK_STROKEANDFILLPATH
  1216. | HOOK_LINETO
  1217. | HOOK_COPYBITS
  1218. | HOOK_STRETCHBLT
  1219. | HOOK_GRADIENTFILL
  1220. | HOOK_TRANSPARENTBLT
  1221. | HOOK_ALPHABLEND);
  1222. // Now create the surface which the engine will use to refer to our
  1223. // entire multi-board virtual screen:
  1224. sizlVirtual.cx = pvdev->rclBounds.right - pvdev->rclBounds.left;
  1225. sizlVirtual.cy = pvdev->rclBounds.bottom - pvdev->rclBounds.top;
  1226. hsurfVirtual = EngCreateDeviceSurface((DHSURF) pvdev,
  1227. sizlVirtual,
  1228. pvdev->iBitmapFormat);
  1229. if (hsurfVirtual == 0)
  1230. goto ReturnFailure;
  1231. pvdev->hsurf = hsurfVirtual;
  1232. if (!EngAssociateSurface(hsurfVirtual, pvdev->hdev, pvdev->flHooks))
  1233. goto ReturnFailure;
  1234. // Get and save a pointer to the SURFOBJ for the DDML
  1235. pvdev->pso = EngLockSurface(hsurfVirtual);
  1236. if (!pvdev->pso)
  1237. goto ReturnFailure;
  1238. // Create a temporary clip object that we can use when a drawing
  1239. // operation spans multiple boards:
  1240. pco = EngCreateClip();
  1241. if (pco == NULL)
  1242. goto ReturnFailure;
  1243. pco->rclBounds = pvdev->rclBounds;
  1244. ((ECLIPOBJ*) pco)->vSet(&pco->rclBounds);
  1245. pvdev->pco = pco;
  1246. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1247. {
  1248. PDEVOBJ poThis(pds->hdev);
  1249. if (poThis.flGraphicsCaps() & GCAPS_LAYERED)
  1250. {
  1251. poThis.pSurface()->hMirrorParent = hsurfVirtual;
  1252. }
  1253. }
  1254. // We're done!
  1255. return(hsurfVirtual);
  1256. ReturnFailure:
  1257. KdPrint(("Failed MulEnableSurface\n"));
  1258. MulDisableSurface((DHPDEV) pvdev);
  1259. return(0);
  1260. }
  1261. /******************************Public*Routine******************************\
  1262. * VOID MulDisableSurface
  1263. *
  1264. * History:
  1265. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  1266. * Wrote it.
  1267. *
  1268. \**************************************************************************/
  1269. VOID MulDisableSurface(DHPDEV dhpdev)
  1270. {
  1271. PVDEV pvdev;
  1272. HSURF hsurf;
  1273. HOBJ hobj;
  1274. SURFACE* pSurface;
  1275. pvdev = (VDEV*) dhpdev;
  1276. PDEVOBJ po(pvdev->hdev);
  1277. ASSERTGDI(po.bValid(), "Invalid PDEV");
  1278. EngDeleteClip(pvdev->pco);
  1279. EngUnlockSurface(pvdev->pso);
  1280. EngDeleteSurface(pvdev->hsurf);
  1281. }
  1282. /******************************Public*Routine******************************\
  1283. * BOOL MulSetPalette
  1284. *
  1285. * History:
  1286. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  1287. * Wrote it.
  1288. *
  1289. \**************************************************************************/
  1290. BOOL MulSetPalette(
  1291. DHPDEV dhpdev,
  1292. PALOBJ *ppalo,
  1293. FLONG fl,
  1294. ULONG iStart,
  1295. ULONG cColors)
  1296. {
  1297. PVDEV pvdev;
  1298. PDISPSURF pds;
  1299. BOOL bRet = TRUE;
  1300. pvdev = (VDEV*) dhpdev;
  1301. pds = pvdev->pds;
  1302. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1303. {
  1304. PDEVOBJ pdo(pds->hdev);
  1305. if (pdo.bIsPalManaged() && PPFNVALID(pdo,SetPalette))
  1306. {
  1307. bRet &= (*PPFNDRV(pdo,SetPalette)) (pdo.dhpdev(),
  1308. ppalo,
  1309. fl,
  1310. iStart,
  1311. cColors);
  1312. }
  1313. }
  1314. return (bRet);
  1315. }
  1316. /******************************Public*Routine******************************\
  1317. * BOOL MulIcmSetDeviceGammaRamp
  1318. *
  1319. * History:
  1320. * 19-Feb-1998 -by- Hideyuki Nagase [hideyukn]
  1321. * Wrote it.
  1322. *
  1323. \**************************************************************************/
  1324. ULONG MulIcmSetDeviceGammaRamp(
  1325. DHPDEV dhpdev,
  1326. ULONG iFormat,
  1327. LPVOID lpRamp)
  1328. {
  1329. PVDEV pvdev;
  1330. PDISPSURF pds;
  1331. BOOL bRet = FALSE;
  1332. pvdev = (VDEV*) dhpdev;
  1333. pds = pvdev->pds;
  1334. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1335. {
  1336. PDEVOBJ pdo(pds->hdev);
  1337. if ((PPFNVALID(pdo, IcmSetDeviceGammaRamp)) &&
  1338. (pdo.flGraphicsCaps2() & GCAPS2_CHANGEGAMMARAMP))
  1339. {
  1340. bRet &= (*PPFNDRV(pdo,IcmSetDeviceGammaRamp))
  1341. (pdo.dhpdev(),
  1342. iFormat,
  1343. lpRamp);
  1344. }
  1345. }
  1346. return (bRet);
  1347. }
  1348. /******************************Public*Routine******************************\
  1349. * BOOL MulRealizeBrush
  1350. *
  1351. * This function's only job is to handle the call caused by the pvGetRbrush
  1352. * in the MULTIBRUSH object. It should just allocate enough memory for the
  1353. * object, and return.
  1354. *
  1355. * History:
  1356. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  1357. * Wrote it.
  1358. *
  1359. \**************************************************************************/
  1360. BOOL MulRealizeBrush(
  1361. BRUSHOBJ *pbo,
  1362. SURFOBJ *psoDst,
  1363. SURFOBJ *psoPat,
  1364. SURFOBJ *psoMask,
  1365. XLATEOBJ *pxlo,
  1366. ULONG iHatch)
  1367. {
  1368. PVDEV pvdev;
  1369. LONG cj;
  1370. pvdev = (VDEV*) psoDst->dhpdev;
  1371. ASSERTGDI(pbo->pvRbrush == NULL, "MulRealizeBrush has a memory leak.\n"
  1372. "Called with pbo->pvRbrush != NULL");
  1373. cj = sizeof(MULTIBRUSHINFO) +
  1374. (pvdev->cSurfaces - 1) * sizeof(MULTIREALIZEDBRUSH);
  1375. return(BRUSHOBJ_pvAllocRbrush(pbo, cj) != NULL);
  1376. }
  1377. /******************************Public*Routine******************************\
  1378. * ULONG MulEscape
  1379. *
  1380. * History:
  1381. * 12-Jul-1996 -by- Tom Zakrajsek [tomzak]
  1382. * Wrote it.
  1383. *
  1384. \**************************************************************************/
  1385. ULONG MulEscape(
  1386. SURFOBJ *pso,
  1387. ULONG iEsc,
  1388. ULONG cjIn,
  1389. PVOID pvIn,
  1390. ULONG cjOut,
  1391. PVOID pvOut)
  1392. {
  1393. PVDEV pvdev;
  1394. PDISPSURF pds;
  1395. LONG csurf;
  1396. ULONG ulRet = 0;
  1397. ASSERTGDI((pso->dhsurf != NULL), "Expected device dest.");
  1398. // OpenGL ExtEscapes from the ICD (and MCD) can still
  1399. // end up here at DeletContext time when the original
  1400. // DC has been lost and they try to communicate to the
  1401. // driver with a DC they got by GetDC(NULL).
  1402. //
  1403. // This routine really shouldn't do anything but return 0.
  1404. if ((iEsc == OPENGL_CMD) || (iEsc == OPENGL_GETINFO) ||
  1405. (iEsc == MCDFUNCS) || (iEsc == WNDOBJ_SETUP))
  1406. {
  1407. return (0);
  1408. }
  1409. pvdev = (VDEV*) pso->dhpdev;
  1410. pds = pvdev->pds;
  1411. csurf = pvdev->cSurfaces;
  1412. ASSERTGDI((csurf > 0), "Expected at least one surface in the list.");
  1413. while (csurf--)
  1414. {
  1415. PDEVOBJ pdo(pds->hdev);
  1416. if (PPFNVALID(pdo,Escape))
  1417. {
  1418. ULONG ulTmp;
  1419. ulTmp = pdo.Escape(pds->pso, iEsc, cjIn, pvIn, cjOut, pvOut);
  1420. // set ulRet to last non-zero value returned
  1421. if (ulTmp != 0)
  1422. {
  1423. ulRet = ulTmp;
  1424. }
  1425. }
  1426. pds = pds->pdsNext;
  1427. }
  1428. return(ulRet);
  1429. }
  1430. /******************************Public*Routine******************************\
  1431. * VOID MulDestroyFont
  1432. *
  1433. * History:
  1434. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  1435. * Wrote it.
  1436. *
  1437. \**************************************************************************/
  1438. VOID MulDestroyFont(
  1439. FONTOBJ* pfo)
  1440. {
  1441. PVDEV pvdev;
  1442. PDISPSURF pds;
  1443. LONG csurf;
  1444. BOOL bRet = TRUE;
  1445. if (pfo->pvConsumer != NULL)
  1446. {
  1447. MULTIFONT MFONT(pfo, -1, NULL);
  1448. pvdev = MFONT.pvdev();
  1449. pds = pvdev->pds;
  1450. csurf = pvdev->cSurfaces;
  1451. ASSERTGDI((csurf > 0), "Expected at least one surface in the list.");
  1452. while (csurf--)
  1453. {
  1454. PDEVOBJ pdo(pds->hdev);
  1455. if (PPFNVALID(pdo,DestroyFont))
  1456. {
  1457. MFONT.LoadElement(pds->iDispSurf);
  1458. pdo.DestroyFont(pfo);
  1459. MFONT.StoreElement(pds->iDispSurf);
  1460. }
  1461. pds = pds->pdsNext;
  1462. }
  1463. MFONT.DestroyTable();
  1464. }
  1465. }
  1466. /******************************Public*Routine******************************\
  1467. * VOID MulDestroyBrushInternal
  1468. *
  1469. * Internal brush destruction routine. This is called to delete our
  1470. * private information associated with multi brushes.
  1471. *
  1472. * History:
  1473. * 9-July-1996 -by- Tom Zakrajsek [tomzak]
  1474. * Wrote it.
  1475. *
  1476. \**************************************************************************/
  1477. VOID MulDestroyBrushInternal(
  1478. PVOID pvRbrush)
  1479. {
  1480. PVDEV pvdev;
  1481. PDISPSURF pds;
  1482. LONG csurf;
  1483. BOOL bRet = TRUE;
  1484. if (pvRbrush != NULL)
  1485. {
  1486. BRUSHOBJ boTmp;
  1487. boTmp.iSolidColor = 0xffffffff;
  1488. boTmp.pvRbrush = pvRbrush;
  1489. boTmp.flColorType = 0;
  1490. MULTIBRUSH MBRUSH(&boTmp, -1, NULL, NULL, TRUE);
  1491. MBRUSH.DestroyTable();
  1492. }
  1493. }
  1494. /******************************Public*Routine******************************\
  1495. * ULONG ulSimulateSaveScreenBits
  1496. *
  1497. * This function simulates SaveScreenBits for those drivers that do not
  1498. * hook it, by using a temporary bitmap and copying in and out of that.
  1499. *
  1500. \**************************************************************************/
  1501. ULONG_PTR ulSimulateSaveScreenBits(
  1502. SURFOBJ* psoScreen,
  1503. ULONG iMode,
  1504. ULONG_PTR ulIdent,
  1505. RECTL* prcl) // Already in device's coordinates
  1506. {
  1507. SIZEL sizl;
  1508. HSURF hsurf;
  1509. SURFOBJ* psoSave;
  1510. SURFACE* psurfSave;
  1511. SURFACE* psurfScreen;
  1512. ULONG_PTR ulRet;
  1513. RECTL rclDst;
  1514. POINTL ptlSrc;
  1515. PDEVOBJ pdo(psoScreen->hdev);
  1516. if (iMode == SS_SAVE)
  1517. {
  1518. sizl.cx = prcl->right - prcl->left;
  1519. sizl.cy = prcl->bottom - prcl->top;
  1520. ASSERTGDI((sizl.cx > 0) && (sizl.cy > 0), "Empty rectangle on save");
  1521. // First, try to create the temporary save bitmap as a Device-Format-
  1522. // Bitmap, and if that fails try it as a normal DIB. (Many display
  1523. // drivers support off-screen bitmaps via CreateDeviceBitmap, so this
  1524. // is often the fastest way to do it.)
  1525. hsurf = 0;
  1526. if (PPFNVALID(pdo, CreateDeviceBitmap))
  1527. {
  1528. hsurf = (HSURF) (*PPFNDRV(pdo, CreateDeviceBitmap))
  1529. (psoScreen->dhpdev,
  1530. sizl,
  1531. psoScreen->iBitmapFormat);
  1532. }
  1533. if (hsurf == 0)
  1534. {
  1535. hsurf = (HSURF) EngCreateBitmap(sizl,
  1536. 0,
  1537. psoScreen->iBitmapFormat,
  1538. BMF_TOPDOWN,
  1539. NULL);
  1540. }
  1541. psoSave = EngLockSurface(hsurf);
  1542. if (psoSave)
  1543. {
  1544. rclDst.left = 0;
  1545. rclDst.top = 0;
  1546. rclDst.right = sizl.cx;
  1547. rclDst.bottom = sizl.cy;
  1548. psurfSave = SURFOBJ_TO_SURFACE(psoSave);
  1549. // Copy the screen to the temporary bitmap. Note that
  1550. // we do not use OffCopyBits as the coordinates have
  1551. // already been offset to take into account the monitor's
  1552. // origin:
  1553. (*PPFNGET(pdo, CopyBits, psurfSave->flags()))(psoSave,
  1554. psoScreen,
  1555. NULL,
  1556. NULL,
  1557. &rclDst,
  1558. (POINTL*) prcl);
  1559. }
  1560. ulRet = (ULONG_PTR) psoSave;
  1561. }
  1562. else
  1563. {
  1564. psoSave = (SURFOBJ*) ulIdent;
  1565. if (iMode == SS_RESTORE)
  1566. {
  1567. ptlSrc.x = 0;
  1568. ptlSrc.y = 0;
  1569. psurfScreen = SURFOBJ_TO_SURFACE(psoScreen);
  1570. // Copy the temporary bitmap back to the screen:
  1571. (*PPFNGET(pdo, CopyBits, psurfScreen->flags()))(psoScreen,
  1572. psoSave,
  1573. NULL,
  1574. NULL,
  1575. prcl,
  1576. &ptlSrc);
  1577. }
  1578. // Free the bitmap, remembering to retrieve any data from the
  1579. // SURFOBJ before we unlock it. Note that EngDeleteSurface
  1580. // handles calling DrvDeleteDeviceBitmap if it's a device
  1581. // format bitmap:
  1582. hsurf = psoSave->hsurf;
  1583. EngUnlockSurface(psoSave);
  1584. EngDeleteSurface(hsurf);
  1585. ulRet = TRUE;
  1586. }
  1587. return(ulRet);
  1588. }
  1589. /******************************Public*Routine******************************\
  1590. * ULONG MulSaveScreenBits
  1591. *
  1592. * It's important for the DDML to hook SaveScreenBits even if some of the
  1593. * underlying drivers do not, for scenarios such as NetMeeting. This is
  1594. * because if SaveScreenBits is not hooked, USER goes and simulates by
  1595. * creating a temporary bitmap and saving and restoring the bits into that
  1596. * bitmap via CopyBits -- meaning that for NetMeeting the temporary bitmap
  1597. * is sent in full both ways over the wire. NetMeeting much prefers to be
  1598. * able to hook SaveScreenBits so that it can send a small token over the wire
  1599. * representing the save or restore. The problem is that most drivers do
  1600. * not support SaveScreenBits, and so for those drivers we simply emulate
  1601. * ourselves (thus allowing us to hook SaveScreenBits even if all the
  1602. * drivers do not hook SaveScreenBits).
  1603. *
  1604. * Note also that NetMeeting likes to be able to fail its SS_RESTORE call so
  1605. * that it can force a repaint if it wants to.
  1606. *
  1607. \**************************************************************************/
  1608. #define SS_GDI_ENGINE 1
  1609. #define SS_GDI_DRIVER 2
  1610. typedef struct _MULTISAVEBITS {
  1611. FLONG flType;
  1612. ULONG_PTR ulBits;
  1613. } MULTISAVEBITS, *PMULTISAVEBITS;
  1614. ULONG_PTR MulSaveScreenBits(
  1615. SURFOBJ* pso,
  1616. ULONG iMode,
  1617. ULONG_PTR ulIdent,
  1618. RECTL* prcl)
  1619. {
  1620. PVDEV pvdev;
  1621. PDISPSURF pds;
  1622. LONG csurf;
  1623. ULONG_PTR ulRet;
  1624. ULONG_PTR ulThisBits;
  1625. FLONG flThisType;
  1626. MULTISAVEBITS* pulIdent;
  1627. RECTL rclThis;
  1628. PFN_DrvSaveScreenBits pfnSaveScreenBits;
  1629. pvdev = (VDEV*) pso->dhpdev;
  1630. pds = pvdev->pds;
  1631. csurf = pvdev->cSurfaces;
  1632. if (iMode == SS_SAVE)
  1633. {
  1634. pulIdent = (MULTISAVEBITS*)
  1635. EngAllocMem(FL_ZERO_MEMORY, csurf * sizeof(MULTISAVEBITS), 'vdVG');
  1636. ulRet = (ULONG_PTR)pulIdent;
  1637. if (pulIdent)
  1638. {
  1639. do {
  1640. ulThisBits = 0;
  1641. if (bIntersect(prcl, &pds->rcl, &rclThis))
  1642. {
  1643. rclThis.left -= pds->rcl.left;
  1644. rclThis.right -= pds->rcl.left;
  1645. rclThis.top -= pds->rcl.top;
  1646. rclThis.bottom -= pds->rcl.top;
  1647. PDEVOBJ pdoThis(pds->hdev);
  1648. pfnSaveScreenBits = PPFNVALID(pdoThis, SaveScreenBits)
  1649. ? PPFNDRV(pdoThis, SaveScreenBits)
  1650. : ulSimulateSaveScreenBits;
  1651. ulThisBits = pfnSaveScreenBits(pds->pso,
  1652. SS_SAVE,
  1653. 0,
  1654. &rclThis);
  1655. if (ulThisBits == 0)
  1656. {
  1657. // Ack, this driver failed to save its screenbits.
  1658. //
  1659. // Try the software simulation (if we haven't tried)
  1660. if (pfnSaveScreenBits != ulSimulateSaveScreenBits)
  1661. {
  1662. pfnSaveScreenBits = ulSimulateSaveScreenBits;
  1663. ulThisBits = pfnSaveScreenBits(pds->pso,
  1664. SS_SAVE,
  1665. 0,
  1666. &rclThis);
  1667. }
  1668. if (ulThisBits == 0)
  1669. {
  1670. // We have to free any screenbits that any earlier
  1671. // driver saved:
  1672. MulSaveScreenBits(pso,
  1673. SS_FREE,
  1674. ulRet,
  1675. &grclEmpty);
  1676. return(0);
  1677. }
  1678. }
  1679. }
  1680. if ((pulIdent[pds->iDispSurf].ulBits = ulThisBits) != 0)
  1681. {
  1682. pulIdent[pds->iDispSurf].flType =
  1683. (pfnSaveScreenBits == ulSimulateSaveScreenBits)
  1684. ? SS_GDI_ENGINE : SS_GDI_DRIVER;
  1685. }
  1686. pds = pds->pdsNext;
  1687. } while (--csurf);
  1688. }
  1689. }
  1690. else
  1691. {
  1692. pulIdent = (MULTISAVEBITS*)ulIdent;
  1693. ulRet = TRUE; // Assume success
  1694. do {
  1695. ulThisBits = pulIdent[pds->iDispSurf].ulBits;
  1696. flThisType = pulIdent[pds->iDispSurf].flType;
  1697. if (ulThisBits)
  1698. {
  1699. PDEVOBJ pdoThis(pds->hdev);
  1700. if (bIntersect(prcl, &pds->rcl, &rclThis))
  1701. {
  1702. rclThis.left -= pds->rcl.left;
  1703. rclThis.right -= pds->rcl.left;
  1704. rclThis.top -= pds->rcl.top;
  1705. rclThis.bottom -= pds->rcl.top;
  1706. }
  1707. else
  1708. {
  1709. rclThis = grclEmpty;
  1710. }
  1711. if ((flThisType == SS_GDI_DRIVER) &&
  1712. (PPFNVALID(pdoThis, SaveScreenBits)))
  1713. {
  1714. pfnSaveScreenBits = PPFNDRV(pdoThis, SaveScreenBits);
  1715. }
  1716. else
  1717. {
  1718. pfnSaveScreenBits = ulSimulateSaveScreenBits;
  1719. }
  1720. ulThisBits = pfnSaveScreenBits(pds->pso,
  1721. iMode,
  1722. ulThisBits,
  1723. &rclThis);
  1724. if ((ulThisBits == 0) && (iMode == SS_RESTORE))
  1725. {
  1726. // Ack, this driver failed to restore its screenbits.
  1727. // We'll have to tell USER that we failed, too. But
  1728. // first, we have to continue to free the screenbits of
  1729. // any drivers following in the DDML list:
  1730. ulRet = FALSE;
  1731. iMode = SS_FREE;
  1732. prcl = &grclEmpty;
  1733. }
  1734. }
  1735. pds = pds->pdsNext;
  1736. } while (--csurf);
  1737. EngFreeMem((VOID*) ulIdent);
  1738. }
  1739. return(ulRet);
  1740. }
  1741. /******************************Public*Routine******************************\
  1742. * VOID MulDeleteDeviceBitmap
  1743. *
  1744. * If the surface has been hooked by the DDML, do any clean-up required
  1745. * so that the surface can be deleted.
  1746. *
  1747. \**************************************************************************/
  1748. VOID MulDeleteDeviceBitmap(
  1749. DHSURF dhsurf)
  1750. {
  1751. MDSURF* pmdsurf;
  1752. VDEV* pvdev;
  1753. DISPSURF* pds;
  1754. SURFOBJ* psoMirror;
  1755. HSURF hsurfMirror;
  1756. pmdsurf = (MDSURF*) dhsurf;
  1757. pvdev = pmdsurf->pvdev;
  1758. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1759. {
  1760. psoMirror = pmdsurf->apso[pds->iDispSurf];
  1761. if (psoMirror != NULL)
  1762. {
  1763. // Note that EngDeleteSurface takes care of calling
  1764. // DrvDeleteDeviceBitmap:
  1765. hsurfMirror = psoMirror->hsurf;
  1766. EngUnlockSurface(psoMirror);
  1767. EngDeleteSurface(hsurfMirror);
  1768. }
  1769. }
  1770. // Note that GDI handles the freeing of the hsurfDevice bitmap.
  1771. EngFreeMem(pmdsurf);
  1772. }
  1773. /******************************Public*Routine******************************\
  1774. * HBITMAP MulCreateDeviceBitmap
  1775. *
  1776. * Screen readers and other clients of the DDML have to be able to watch
  1777. * all drawing calls to compatible bitmaps.
  1778. *
  1779. \**************************************************************************/
  1780. HBITMAP MulCreateDeviceBitmap(
  1781. DHPDEV dhpdev,
  1782. SIZEL sizl,
  1783. ULONG iFormat)
  1784. {
  1785. GDIFunctionID(MulCreateDeviceBitmap);
  1786. HSURF hsurfDevice;
  1787. HSURF hsurfMirror;
  1788. MDSURF* pmdsurf;
  1789. VDEV* pvdev;
  1790. DISPSURF* pds;
  1791. SURFOBJ* psoMirror;
  1792. SURFACE* psurfMirror;
  1793. FLONG flHooks;
  1794. pvdev = (VDEV*) dhpdev;
  1795. flHooks = 0;
  1796. pmdsurf = NULL;
  1797. hsurfDevice = NULL;
  1798. // First, pass the call to every mirrored driver and see if they
  1799. // want to create a Mirrored version:
  1800. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  1801. {
  1802. PDEVOBJ poThis(pds->hdev);
  1803. if ((poThis.flGraphicsCaps() & GCAPS_LAYERED) &&
  1804. PPFNDRV(poThis, CreateDeviceBitmap))
  1805. {
  1806. // We compare to TRUE to allow for the possibility that
  1807. // in the future we'll change the return value to be
  1808. // something other than BOOL.
  1809. hsurfMirror = (HSURF) PPFNDRV(poThis, CreateDeviceBitmap)
  1810. (poThis.dhpdev(),
  1811. sizl,
  1812. iFormat);
  1813. if (hsurfMirror)
  1814. psoMirror = EngLockSurface(hsurfMirror);
  1815. else
  1816. psoMirror = NULL;
  1817. if (psoMirror)
  1818. {
  1819. if (pmdsurf == NULL)
  1820. {
  1821. hsurfDevice = (HSURF) EngCreateBitmap(sizl, 0, iFormat, BMF_TOPDOWN, NULL);
  1822. pmdsurf = (MDSURF*) EngAllocMem(
  1823. FL_ZERO_MEMORY,
  1824. sizeof(MDSURF) + pvdev->cSurfaces * sizeof(SURFOBJ*),
  1825. 'fsVG');
  1826. if ((pmdsurf == NULL) || (hsurfDevice == NULL))
  1827. {
  1828. if (pmdsurf != NULL)
  1829. {
  1830. EngFreeMem(pmdsurf);
  1831. }
  1832. // Failure, so we're outta here...
  1833. EngUnlockSurface(psoMirror);
  1834. EngDeleteSurface(hsurfDevice);
  1835. return((HBITMAP) NULL);
  1836. }
  1837. pmdsurf->apso = (SURFOBJ**)
  1838. ((BYTE*)pmdsurf + sizeof(MDSURF));
  1839. }
  1840. pmdsurf->pvdev = pvdev;
  1841. pmdsurf->apso[pds->iDispSurf] = psoMirror;
  1842. psurfMirror = SURFOBJ_TO_SURFACE_NOT_NULL(psoMirror);
  1843. psurfMirror->vSetMirror();
  1844. psurfMirror->hMirrorParent = hsurfDevice;
  1845. if (!poThis.bIsPalManaged())
  1846. {
  1847. // Dev bitmap will have device palette.
  1848. HPALETTE hpalDevice = (HPALETTE) poThis.ppalSurf()->hGet();
  1849. EPALOBJ palDeviceSurf(hpalDevice);
  1850. ASSERTGDI(palDeviceSurf.bValid(), "ERROR invalid palette\n");
  1851. psurfMirror->ppal(palDeviceSurf.ppalGet());
  1852. // Reference count it by making it not unlocked.
  1853. palDeviceSurf.ppalSet((PPALETTE)NULL);
  1854. }
  1855. }
  1856. }
  1857. }
  1858. // If any layering driver hooked the call, make our surface opaque
  1859. // so that we can catch all drawing calls.
  1860. if (pmdsurf != NULL)
  1861. {
  1862. SURFREF sr(hsurfDevice);
  1863. if (sr.bValid())
  1864. {
  1865. sr.ps->vSetEngCreateDeviceBitmap();
  1866. sr.ps->iType(STYPE_DEVBITMAP);
  1867. sr.ps->so.dhsurf = (DHSURF)pmdsurf;
  1868. flHooks = pvdev->flHooks;
  1869. // DrvCreateDeviceBitmap calls must always 'EngAssociateSurface'
  1870. // the returned bitmap:
  1871. EngAssociateSurface(hsurfDevice, pvdev->hdev, flHooks);
  1872. }
  1873. }
  1874. return((HBITMAP) hsurfDevice);
  1875. }
  1876. #ifdef OPENGL_MM
  1877. // ICD calls directly dispatch to real driver in API level, so it bypass DDML.
  1878. #else
  1879. /******************************Public*Routine******************************\
  1880. * BOOL MulSetPixelFormat
  1881. *
  1882. *
  1883. \**************************************************************************/
  1884. BOOL MulSetPixelFormat(
  1885. SURFOBJ* pso,
  1886. LONG iPixelFormat,
  1887. HWND hwnd)
  1888. {
  1889. PVDEV pvdev;
  1890. PDISPSURF pds;
  1891. LONG csurf;
  1892. BOOL bRet = FALSE;
  1893. pvdev = (VDEV*) pso->dhpdev;
  1894. pds = pvdev->pds;
  1895. csurf = pvdev->cSurfaces;
  1896. do {
  1897. PDEVOBJ pdo(pds->hdev);
  1898. if (PPFNVALID(pdo, SetPixelFormat))
  1899. {
  1900. bRet = (*PPFNDRV(pdo, SetPixelFormat))(pds->pso,
  1901. iPixelFormat,
  1902. hwnd);
  1903. }
  1904. pds = pds->pdsNext;
  1905. } while (--csurf != 0);
  1906. return(bRet);
  1907. }
  1908. /******************************Public*Routine******************************\
  1909. * LONG MulDescribePixelFormat
  1910. *
  1911. *
  1912. \**************************************************************************/
  1913. LONG MulDescribePixelFormat(
  1914. DHPDEV dhpdev,
  1915. LONG iPixelFormat,
  1916. ULONG cjpfd,
  1917. PIXELFORMATDESCRIPTOR* ppfd)
  1918. {
  1919. PVDEV pvdev;
  1920. PDISPSURF pds;
  1921. LONG csurf;
  1922. DHPDEV dhpdevDriver;
  1923. LONG lRet = 0;
  1924. pvdev = (VDEV*) dhpdev;
  1925. pds = pvdev->pds;
  1926. csurf = pvdev->cSurfaces;
  1927. do {
  1928. PDEVOBJ pdo(pds->hdev);
  1929. if (PPFNVALID(pdo, DescribePixelFormat))
  1930. {
  1931. dhpdevDriver = pds->pso->dhpdev;
  1932. lRet = (*PPFNDRV(pdo, DescribePixelFormat))(dhpdevDriver,
  1933. iPixelFormat,
  1934. cjpfd,
  1935. ppfd);
  1936. }
  1937. pds = pds->pdsNext;
  1938. } while (--csurf != 0);
  1939. return(lRet);
  1940. }
  1941. /******************************Public*Routine******************************\
  1942. * BOOL MulSwapBuffers
  1943. *
  1944. *
  1945. \**************************************************************************/
  1946. BOOL MulSwapBuffers(
  1947. SURFOBJ* pso,
  1948. WNDOBJ* pwo)
  1949. {
  1950. PVDEV pvdev;
  1951. PDISPSURF pds;
  1952. LONG csurf;
  1953. BOOL bRet = FALSE;
  1954. pvdev = (VDEV*) pso->dhpdev;
  1955. pds = pvdev->pds;
  1956. csurf = pvdev->cSurfaces;
  1957. do {
  1958. PDEVOBJ pdo(pds->hdev);
  1959. if (PPFNVALID(pdo, SwapBuffers))
  1960. {
  1961. bRet = (*PPFNDRV(pdo, SwapBuffers))(pds->pso,
  1962. pwo);
  1963. }
  1964. pds = pds->pdsNext;
  1965. } while (--csurf != 0);
  1966. return(bRet);
  1967. }
  1968. #endif // #ifdef OPENGL_MM
  1969. /******************************Public*Routine******************************\
  1970. * BOOL MulTextOut
  1971. *
  1972. * WARNING - WHEN OPTIMIZING
  1973. *
  1974. * When optimizing for one driver, remember that you'll still
  1975. * have to set the psurf on brushes to the driver's surface.
  1976. * Otherwise, you'll get a callback for DrvRealizeBrush.
  1977. *
  1978. * History:
  1979. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  1980. * Wrote it.
  1981. *
  1982. \**************************************************************************/
  1983. BOOL MulTextOut(
  1984. SURFOBJ *pso,
  1985. STROBJ *pstro,
  1986. FONTOBJ *pfo,
  1987. CLIPOBJ *pco,
  1988. RECTL *prclExtra,
  1989. RECTL *prclOpaque,
  1990. BRUSHOBJ *pboFore,
  1991. BRUSHOBJ *pboOpaque,
  1992. POINTL *pptlOrg,
  1993. MIX mix)
  1994. {
  1995. PVDEV pvdev = (VDEV*) pso->dhpdev;
  1996. BOOL bRet = TRUE;
  1997. MSURF msurf;
  1998. ULONG cgposCopied;
  1999. RECTL rclOpaque;
  2000. ASSERTGDI((pboFore->iSolidColor != (ULONG) -1) &&
  2001. (pboOpaque->iSolidColor != (ULONG) -1),
  2002. "Didn't expect patterned brush");
  2003. if (pso->iType == STYPE_DEVBITMAP)
  2004. {
  2005. // Handle drawing to 'master' device bitmap:
  2006. MULTISURF mDst(pso);
  2007. bRet = EngTextOut(mDst.pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore,
  2008. pboOpaque, pptlOrg, mix);
  2009. }
  2010. MULTIBRUSH MBRUSH_Fore(pboFore, pvdev->cSurfaces, pvdev, pvdev->pso, MIX_NEEDS_PATTERN(mix));
  2011. if (!MBRUSH_Fore.Valid())
  2012. {
  2013. return (FALSE);
  2014. }
  2015. MULTIBRUSH MBRUSH_Opaque(pboOpaque, pvdev->cSurfaces, pvdev, pvdev->pso, MIX_NEEDS_PATTERN(mix));
  2016. if (!MBRUSH_Opaque.Valid())
  2017. {
  2018. return (FALSE);
  2019. }
  2020. MULTIFONT MFONT(pfo, pvdev->cSurfaces, pvdev);
  2021. if (!MFONT.Valid())
  2022. {
  2023. return (FALSE);
  2024. }
  2025. RECTL* prclBounds = (prclOpaque != NULL)
  2026. ? prclOpaque
  2027. : &pstro->rclBkGround;
  2028. cgposCopied = ((ESTROBJ*)pstro)->cgposCopied;
  2029. rclOpaque = *prclBounds;
  2030. if (msurf.bFindSurface(pso, pco, prclBounds))
  2031. {
  2032. do {
  2033. STROBJ_vEnumStart(pstro);
  2034. MFONT.LoadElement(msurf.pds->iDispSurf);
  2035. MBRUSH_Fore.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  2036. MBRUSH_Opaque.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  2037. ((ESTROBJ*)pstro)->cgposCopied = cgposCopied;
  2038. // Some drivers modify 'prclOpaque', so always pass them a copy:
  2039. *prclBounds = rclOpaque;
  2040. bRet &= OffTextOut(PPFNMGET(msurf, TextOut),
  2041. msurf.pOffset,
  2042. msurf.pso,
  2043. pstro,
  2044. pfo,
  2045. msurf.pco,
  2046. prclExtra,
  2047. prclOpaque,
  2048. pboFore,
  2049. pboOpaque,
  2050. pptlOrg,
  2051. mix);
  2052. MBRUSH_Fore.StoreElement(msurf.pds->iDispSurf);
  2053. MBRUSH_Opaque.StoreElement(msurf.pds->iDispSurf);
  2054. MFONT.StoreElement(msurf.pds->iDispSurf);
  2055. } while (msurf.bNextSurface());
  2056. }
  2057. return(bRet);
  2058. }
  2059. /******************************Public*Routine******************************\
  2060. * BOOL MulStrokePath
  2061. *
  2062. * History:
  2063. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  2064. * Wrote it.
  2065. *
  2066. \**************************************************************************/
  2067. BOOL MulStrokePath(
  2068. SURFOBJ *pso,
  2069. PATHOBJ *ppo,
  2070. CLIPOBJ *pco,
  2071. XFORMOBJ *pxo,
  2072. BRUSHOBJ *pbo,
  2073. POINTL *pptlBrushOrg,
  2074. LINEATTRS *pla,
  2075. MIX mix)
  2076. {
  2077. PVDEV pvdev = (VDEV*) pso->dhpdev;
  2078. BOOL bRet = TRUE;
  2079. FLOAT_LONG elStyleState = pla->elStyleState;
  2080. MSURF msurf;
  2081. if (pso->iType == STYPE_DEVBITMAP)
  2082. {
  2083. // Handle drawing to 'master' device bitmap:
  2084. MULTISURF mDst(pso);
  2085. bRet = EngStrokePath(mDst.pso, ppo, pco, pxo, pbo, pptlBrushOrg, pla, mix);
  2086. }
  2087. MULTIBRUSH MBRUSH(pbo, pvdev->cSurfaces, pvdev, pvdev->pso, MIX_NEEDS_PATTERN(mix));
  2088. if (!MBRUSH.Valid())
  2089. {
  2090. return FALSE;
  2091. }
  2092. // Get the path bounds and make it lower-right exclusive:
  2093. RECTL rclDst;
  2094. RECTFX rcfxBounds;
  2095. PATHOBJ_vGetBounds(ppo, &rcfxBounds);
  2096. rclDst.left = (rcfxBounds.xLeft >> 4);
  2097. rclDst.top = (rcfxBounds.yTop >> 4);
  2098. rclDst.right = (rcfxBounds.xRight >> 4) + 2;
  2099. rclDst.bottom = (rcfxBounds.yBottom >> 4) + 2;
  2100. if (msurf.bFindSurface(pso, pco, &rclDst))
  2101. {
  2102. do {
  2103. PATHOBJ_vEnumStart(ppo);
  2104. pla->elStyleState = elStyleState;
  2105. MBRUSH.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  2106. bRet &= OffStrokePath(PPFNMGET(msurf, StrokePath),
  2107. msurf.pOffset,
  2108. msurf.pso,
  2109. ppo,
  2110. msurf.pco,
  2111. pxo,
  2112. pbo,
  2113. pptlBrushOrg,
  2114. pla,
  2115. mix);
  2116. MBRUSH.StoreElement(msurf.pds->iDispSurf);
  2117. } while (msurf.bNextSurface());
  2118. }
  2119. return(bRet);
  2120. }
  2121. /******************************Public*Routine******************************\
  2122. * BOOL MulFillPath
  2123. *
  2124. * History:
  2125. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  2126. * Wrote it.
  2127. *
  2128. \**************************************************************************/
  2129. BOOL MulFillPath(
  2130. SURFOBJ *pso,
  2131. PATHOBJ *ppo,
  2132. CLIPOBJ *pco,
  2133. BRUSHOBJ *pbo,
  2134. POINTL *pptlBrushOrg,
  2135. MIX mix,
  2136. FLONG flOptions)
  2137. {
  2138. PVDEV pvdev = (VDEV*) pso->dhpdev;
  2139. BOOL bRet = TRUE;
  2140. MSURF msurf;
  2141. if (pso->iType == STYPE_DEVBITMAP)
  2142. {
  2143. // Handle drawing to 'master' device bitmap:
  2144. MULTISURF mDst(pso);
  2145. bRet = EngFillPath(mDst.pso, ppo, pco, pbo, pptlBrushOrg, mix, flOptions);
  2146. }
  2147. MULTIBRUSH MBRUSH(pbo, pvdev->cSurfaces, pvdev, pvdev->pso, MIX_NEEDS_PATTERN(mix));
  2148. if (!MBRUSH.Valid())
  2149. {
  2150. return FALSE;
  2151. }
  2152. // Get the path bounds and make it lower-right exclusive:
  2153. RECTL rclDst;
  2154. RECTFX rcfxBounds;
  2155. PATHOBJ_vGetBounds(ppo, &rcfxBounds);
  2156. rclDst.left = (rcfxBounds.xLeft >> 4);
  2157. rclDst.top = (rcfxBounds.yTop >> 4);
  2158. rclDst.right = (rcfxBounds.xRight >> 4) + 2;
  2159. rclDst.bottom = (rcfxBounds.yBottom >> 4) + 2;
  2160. if (msurf.bFindSurface(pso, pco, &rclDst))
  2161. {
  2162. do {
  2163. PATHOBJ_vEnumStart(ppo);
  2164. MBRUSH.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  2165. bRet &= OffFillPath(PPFNMGET(msurf, FillPath),
  2166. msurf.pOffset,
  2167. msurf.pso,
  2168. ppo,
  2169. msurf.pco,
  2170. pbo,
  2171. pptlBrushOrg,
  2172. mix,
  2173. flOptions);
  2174. MBRUSH.StoreElement(msurf.pds->iDispSurf);
  2175. } while (msurf.bNextSurface());
  2176. }
  2177. return(bRet);
  2178. }
  2179. /******************************Public*Routine******************************\
  2180. * BOOL MulStrokeAndFillPath
  2181. *
  2182. * History:
  2183. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  2184. * Wrote it.
  2185. *
  2186. \**************************************************************************/
  2187. BOOL MulStrokeAndFillPath(
  2188. SURFOBJ *pso,
  2189. PATHOBJ *ppo,
  2190. CLIPOBJ *pco,
  2191. XFORMOBJ *pxo,
  2192. BRUSHOBJ *pboStroke,
  2193. LINEATTRS *pla,
  2194. BRUSHOBJ *pboFill,
  2195. POINTL *pptlBrushOrg,
  2196. MIX mixFill,
  2197. FLONG flOptions)
  2198. {
  2199. PVDEV pvdev = (VDEV*) pso->dhpdev;
  2200. BOOL bRet = TRUE;
  2201. FLOAT_LONG elSavedStyleState = pla->elStyleState;
  2202. MSURF msurf;
  2203. if (pso->iType == STYPE_DEVBITMAP)
  2204. {
  2205. // Handle drawing to 'master' device bitmap:
  2206. MULTISURF mDst(pso);
  2207. bRet = EngStrokeAndFillPath(mDst.pso, ppo, pco, pxo, pboStroke, pla, pboFill,
  2208. pptlBrushOrg, mixFill, flOptions);
  2209. }
  2210. MULTIBRUSH MBRUSH_Stroke(pboStroke, pvdev->cSurfaces, pvdev, pvdev->pso, FALSE);
  2211. if (!MBRUSH_Stroke.Valid())
  2212. {
  2213. return FALSE;
  2214. }
  2215. MULTIBRUSH MBRUSH_Fill(pboFill, pvdev->cSurfaces, pvdev, pvdev->pso, MIX_NEEDS_PATTERN(mixFill));
  2216. if (!MBRUSH_Fill.Valid())
  2217. {
  2218. return FALSE;
  2219. }
  2220. // Get the path bounds and make it lower-right exclusive:
  2221. RECTL rclDst;
  2222. RECTFX rcfxBounds;
  2223. PATHOBJ_vGetBounds(ppo, &rcfxBounds);
  2224. rclDst.left = (rcfxBounds.xLeft >> 4);
  2225. rclDst.top = (rcfxBounds.yTop >> 4);
  2226. rclDst.right = (rcfxBounds.xRight >> 4) + 2;
  2227. rclDst.bottom = (rcfxBounds.yBottom >> 4) + 2;
  2228. if (msurf.bFindSurface(pso, pco, &rclDst))
  2229. {
  2230. do {
  2231. pla->elStyleState = elSavedStyleState;
  2232. PATHOBJ_vEnumStart(ppo);
  2233. MBRUSH_Stroke.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  2234. MBRUSH_Fill.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  2235. bRet &= OffStrokeAndFillPath(PPFNMGET(msurf, StrokeAndFillPath),
  2236. msurf.pOffset,
  2237. msurf.pso,
  2238. ppo,
  2239. msurf.pco,
  2240. pxo,
  2241. pboStroke,
  2242. pla,
  2243. pboFill,
  2244. pptlBrushOrg,
  2245. mixFill,
  2246. flOptions);
  2247. MBRUSH_Stroke.StoreElement(msurf.pds->iDispSurf);
  2248. MBRUSH_Fill.StoreElement(msurf.pds->iDispSurf);
  2249. } while (msurf.bNextSurface());
  2250. }
  2251. return(bRet);
  2252. }
  2253. /******************************Public*Routine******************************\
  2254. * BOOL MulLineTo
  2255. *
  2256. * History:
  2257. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  2258. * Wrote it.
  2259. *
  2260. \**************************************************************************/
  2261. BOOL MulLineTo(
  2262. SURFOBJ *pso,
  2263. CLIPOBJ *pco,
  2264. BRUSHOBJ *pbo,
  2265. LONG x1,
  2266. LONG y1,
  2267. LONG x2,
  2268. LONG y2,
  2269. RECTL *prclBounds,
  2270. MIX mix)
  2271. {
  2272. PVDEV pvdev = (VDEV*) pso->dhpdev;
  2273. BOOL bRet = TRUE;
  2274. MSURF msurf;
  2275. if (pso->iType == STYPE_DEVBITMAP)
  2276. {
  2277. // Handle drawing to 'master' device bitmap:
  2278. MULTISURF mDst(pso,prclBounds);
  2279. bRet = EngLineTo(mDst.pso, pco, pbo, x1, y1, x2, y2, mDst.prcl, mix);
  2280. }
  2281. MULTIBRUSH MBRUSH(pbo, pvdev->cSurfaces, pvdev, pvdev->pso, FALSE);
  2282. if (!MBRUSH.Valid())
  2283. {
  2284. return FALSE;
  2285. }
  2286. if (msurf.bFindSurface(pso, pco, prclBounds))
  2287. {
  2288. do {
  2289. MBRUSH.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  2290. bRet &= OffLineTo(PPFNMGET(msurf, LineTo),
  2291. msurf.pOffset,
  2292. msurf.pso,
  2293. msurf.pco,
  2294. pbo,
  2295. x1,
  2296. y1,
  2297. x2,
  2298. y2,
  2299. prclBounds,
  2300. mix);
  2301. MBRUSH.StoreElement(msurf.pds->iDispSurf);
  2302. } while (msurf.bNextSurface());
  2303. }
  2304. return(bRet);
  2305. }
  2306. /******************************Public*Routine******************************\
  2307. * BOOL MulGradientFill
  2308. *
  2309. * History:
  2310. * 23-Apr-1998 -by- Hideyuki Nagase [hideyukn]
  2311. * Wrote it.
  2312. *
  2313. \**************************************************************************/
  2314. BOOL MulGradientFill(
  2315. SURFOBJ *pso,
  2316. CLIPOBJ *pco,
  2317. XLATEOBJ *pxlo,
  2318. TRIVERTEX *pVertex,
  2319. ULONG nVertex,
  2320. PVOID pMesh,
  2321. ULONG nMesh,
  2322. RECTL *prclExtents,
  2323. POINTL *pptlDitherOrg,
  2324. ULONG ulMode)
  2325. {
  2326. PVDEV pvdev = (VDEV*) pso->dhpdev;
  2327. XLATEOBJ *pxloSave = pxlo;
  2328. BOOL bRet = TRUE;
  2329. MSURF msurf;
  2330. if (pso->iType == STYPE_DEVBITMAP)
  2331. {
  2332. // Handle drawing to 'master' device bitmap:
  2333. MULTISURF mDst(pso,prclExtents);
  2334. bRet = EngGradientFill(mDst.pso, pco, pxlo, pVertex, nVertex, pMesh, nMesh,
  2335. mDst.prcl, pptlDitherOrg, ulMode);
  2336. }
  2337. if (msurf.bFindSurface(pso, pco, prclExtents))
  2338. {
  2339. do {
  2340. PSURFACE pSurfDest = SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso);
  2341. EXLATEOBJ xloDevice;
  2342. // if the target surface is not compatible to primary surface,
  2343. // create XLATEOBJ for source surface to target. otherwise
  2344. // we can just use given XLATEOBJ.
  2345. if (pSurfDest->iFormat() > BMF_8BPP)
  2346. {
  2347. // 16bpp or above do not require a translation object.
  2348. pxlo = NULL;
  2349. }
  2350. else if (msurf.pds->iCompatibleColorFormat != 0)
  2351. {
  2352. XLATE *pxloM = (XLATE *) pxlo;
  2353. PPALETTE ppalDestDC = ppalDefault;
  2354. PPALETTE ppalSurfSrc = gppalRGB;
  2355. PDEVOBJ pdo(msurf.pds->hdev);
  2356. if (pdo.bIsPalManaged())
  2357. {
  2358. // Use halftone palette for pal-managed device.
  2359. ppalDestDC = REALIZE_HALFTONE_PALETTE(pdo.hdev());
  2360. }
  2361. if (xloDevice.bInitXlateObj(
  2362. (pxloM ? pxloM->hcmXform : NULL),
  2363. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  2364. ppalSurfSrc, // Source palette
  2365. pSurfDest->ppal(), // Destination palette
  2366. ppalDestDC, // Source DC palette
  2367. ppalDestDC, // Destination DC palette
  2368. (pxloM ? pxloM->iForeDst : 0x0L),
  2369. (pxloM ? pxloM->iBackDst : 0x0L),
  2370. (pxloM ? pxloM->iBackSrc : 0x0L),
  2371. 0))
  2372. {
  2373. pxlo = xloDevice.pxlo();
  2374. }
  2375. }
  2376. bRet &= OffGradientFill(PPFNMGET(msurf, GradientFill),
  2377. msurf.pOffset,
  2378. msurf.pso,
  2379. msurf.pco,
  2380. pxlo,
  2381. pVertex,
  2382. nVertex,
  2383. pMesh,
  2384. nMesh,
  2385. prclExtents,
  2386. pptlDitherOrg,
  2387. ulMode);
  2388. // Restore XLATEOBJ
  2389. pxlo = pxloSave;
  2390. } while (msurf.bNextSurface());
  2391. }
  2392. return(bRet);
  2393. }
  2394. /******************************Public*Routine******************************\
  2395. * BOOL MulStretchBlt
  2396. *
  2397. * History:
  2398. * 1-May-1996 -by- Tom Zakrajsek [tomzak]
  2399. * Wrote it.
  2400. *
  2401. \**************************************************************************/
  2402. BOOL MulStretchBlt(
  2403. SURFOBJ* psoDst,
  2404. SURFOBJ* psoSrc,
  2405. SURFOBJ* psoMask,
  2406. CLIPOBJ* pco,
  2407. XLATEOBJ* pxlo,
  2408. COLORADJUSTMENT* pca,
  2409. POINTL* pptlHTOrg,
  2410. RECTL* prclDst,
  2411. RECTL* prclSrc,
  2412. POINTL* pptlMask,
  2413. ULONG iMode)
  2414. {
  2415. GDIFunctionID(MulStretchBlt);
  2416. XLATEOBJ *pxloSave = pxlo;
  2417. //
  2418. // We cannot handle cases where the source is a meta,
  2419. // so make a copy in this case.
  2420. //
  2421. SURFMEM srcCopy;
  2422. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc);
  2423. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  2424. RECTL rclSrcCopy = *prclSrc;
  2425. if( psoSrc->iType == STYPE_DEVICE && pdoSrc.bValid() &&
  2426. pdoSrc.bMetaDriver())
  2427. {
  2428. if(!MulCopyDeviceToDIB( psoSrc, &srcCopy, &rclSrcCopy ))
  2429. return FALSE;
  2430. if(srcCopy.ps == NULL)
  2431. {
  2432. // We didn't get to the point of creating the surface
  2433. // becasue the rect was out of bounds.
  2434. return TRUE;
  2435. }
  2436. prclSrc = &rclSrcCopy;
  2437. psoSrc = srcCopy.pSurfobj();
  2438. pSurfSrc= SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc);
  2439. pdoSrc.vInit(pSurfSrc->hdev());
  2440. }
  2441. //
  2442. // Inverting stretches are a pain because 'bFindSurface' doesn't
  2443. // understand poorly ordered rectangles. So we'll make yet
  2444. // another copy of the source in this case.
  2445. //
  2446. SURFMEM srcInv;
  2447. RECTL rclDstCopy;
  2448. PPALETTE ppalSrc = pSurfSrc->ppal();
  2449. if ((prclDst->left >= prclDst->right) ||
  2450. (prclDst->top >= prclDst->bottom))
  2451. {
  2452. DEVBITMAPINFO dbmi;
  2453. RECTL rclSrcClip = *prclSrc;
  2454. if( rclSrcClip.left < 0 )
  2455. {
  2456. rclSrcClip.left = 0;
  2457. }
  2458. if( rclSrcClip.right > pSurfSrc->sizl().cx )
  2459. {
  2460. rclSrcClip.right = pSurfSrc->sizl().cx;
  2461. }
  2462. if( rclSrcClip.top < 0 )
  2463. {
  2464. rclSrcClip.top = 0;
  2465. }
  2466. if( rclSrcClip.bottom > pSurfSrc->sizl().cy )
  2467. {
  2468. rclSrcClip.bottom = pSurfSrc->sizl().cy;
  2469. }
  2470. if( (rclSrcClip.right <= rclSrcClip.left) ||
  2471. (rclSrcClip.bottom <= rclSrcClip.top ) )
  2472. {
  2473. return TRUE;
  2474. }
  2475. dbmi.cxBitmap = rclSrcClip.right - rclSrcClip.left;
  2476. dbmi.cyBitmap = rclSrcClip.bottom - rclSrcClip.top;
  2477. dbmi.hpal = ppalSrc ? ((HPALETTE) ppalSrc->hGet()) : 0;
  2478. dbmi.iFormat = pSurfSrc->iFormat();
  2479. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  2480. srcInv.bCreateDIB(&dbmi, (VOID *) NULL);
  2481. if (!srcInv.bValid())
  2482. return(FALSE);
  2483. rclSrcCopy.left -= rclSrcClip.left;
  2484. rclSrcCopy.right -= rclSrcClip.left;
  2485. rclSrcCopy.top -= rclSrcClip.top;
  2486. rclSrcCopy.bottom -= rclSrcClip.top;
  2487. RECTL rclInv;
  2488. // Setup for x-inversion
  2489. if( prclDst->left >= prclDst->right )
  2490. {
  2491. rclDstCopy.left = prclDst->right;
  2492. rclDstCopy.right= prclDst->left;
  2493. rclInv.left = rclSrcCopy.right;
  2494. rclInv.right = rclSrcCopy.left;
  2495. }
  2496. else
  2497. {
  2498. rclDstCopy.left = prclDst->left;
  2499. rclDstCopy.right= prclDst->right;
  2500. rclInv.left = rclSrcCopy.left;
  2501. rclInv.right = rclSrcCopy.right;
  2502. }
  2503. // Setup for y-inversion
  2504. if( prclDst->top >= prclDst->bottom )
  2505. {
  2506. rclDstCopy.top = prclDst->bottom;
  2507. rclDstCopy.bottom = prclDst->top;
  2508. rclInv.top = rclSrcCopy.bottom;
  2509. rclInv.bottom = rclSrcCopy.top;
  2510. }
  2511. else
  2512. {
  2513. rclDstCopy.top = prclDst->top;
  2514. rclDstCopy.bottom = prclDst->bottom;
  2515. rclInv.top = rclSrcCopy.top;
  2516. rclInv.bottom = rclSrcCopy.bottom;
  2517. }
  2518. // Do the actual inversion
  2519. if(!EngStretchBlt(srcInv.pSurfobj(), psoSrc, NULL, (CLIPOBJ *)NULL, &xloIdent, NULL,
  2520. NULL, &rclInv, prclSrc, NULL, COLORONCOLOR))
  2521. return FALSE;
  2522. prclSrc = &rclSrcCopy;
  2523. prclDst = &rclDstCopy;
  2524. psoSrc = srcInv.pSurfobj();
  2525. pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc);
  2526. pdoSrc.vInit(pSurfSrc->hdev());
  2527. }
  2528. PVDEV pvdev = (VDEV*) psoDst->dhpdev;
  2529. USHORT iDstType = psoDst->iType;
  2530. BOOL bMultiDst;
  2531. BOOL bRet = TRUE;
  2532. MSURF msurf;
  2533. RECTL rclDst;
  2534. RECTL rclSrc;
  2535. ASSERTGDI(iDstType != STYPE_BITMAP, "BITMAP destination\n");
  2536. bMultiDst = msurf.bFindSurface(psoDst, pco, prclDst);
  2537. // WINBUG #298689 4-4-2001 jasonha Handle multi-device stretches
  2538. MULTISURF mSrc(psoSrc, prclSrc);
  2539. //
  2540. // If the destination is a Device Bitmap, we must draw to
  2541. // the master DIB also.
  2542. //
  2543. if (iDstType == STYPE_DEVBITMAP)
  2544. {
  2545. MULTISURF mDst(psoDst,prclDst);
  2546. bRet = EngStretchBlt(mDst.pso, mSrc.pso, psoMask, pco, pxlo, pca,
  2547. pptlHTOrg, mDst.prcl, mSrc.prcl, pptlMask, iMode);
  2548. }
  2549. if (bMultiDst)
  2550. {
  2551. do {
  2552. BOOL bError;
  2553. EXLATEOBJ xloDevice;
  2554. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso);
  2555. bError = !mSrc.bLoadSource(msurf.pds);
  2556. if (bError == FALSE)
  2557. {
  2558. pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(mSrc.pso);
  2559. ppalSrc = pSurfSrc->ppal();
  2560. // if the target surface is not compatible to primary surface,
  2561. // create XLATEOBJ for source surface to target. otherwise
  2562. // we can just use given XLATEOBJ.
  2563. if (msurf.pds->iCompatibleColorFormat != 0)
  2564. {
  2565. XLATE *pxloM = (XLATE *) pxlo;
  2566. PPALETTE ppalDestDC = ppalDefault;
  2567. PDEVOBJ pdoDst(msurf.pds->hdev);
  2568. if (pdoDst.bIsPalManaged())
  2569. {
  2570. // Use halftone palette for pal-managed device.
  2571. ppalDestDC = REALIZE_HALFTONE_PALETTE(pdoDst.hdev());
  2572. }
  2573. if (!ppalSrc)
  2574. {
  2575. // Source surface does not have associated palette.
  2576. // (Source surface is compatible bitmap)
  2577. if (pxloM && pxloM->ppalSrc)
  2578. {
  2579. // if XLATEOBJ has source palette, use it.
  2580. ppalSrc = pxloM->ppalSrc;
  2581. }
  2582. else
  2583. {
  2584. PSURFACE pSurfTmp = SURFOBJ_TO_SURFACE_NOT_NULL(psoDst);
  2585. if ((pxloM == NULL) || pxloM->bIsIdentity())
  2586. {
  2587. // if translation is identity, we can use the palette for
  2588. // meta-destination surface as source. since it's trivial.
  2589. // WINBUG #396667 10-03-2001 jasonha A/V due to improper XLATE setup
  2590. if (mSrc.pso == psoSrc)
  2591. {
  2592. ppalSrc = pSurfTmp->ppal();
  2593. }
  2594. }
  2595. else if (pxloM->ppalDstDC)
  2596. {
  2597. // We are bitblting from compatible bitmap to a surface in
  2598. // meta-surface. but we are not in foreground.
  2599. ppalDestDC = pxloM->ppalDstDC;
  2600. // WINBUG #274637 02-12-2001 jasonha A/V due to improper XLATE setup
  2601. if (pSurfSrc->iFormat() == pSurfTmp->iFormat())
  2602. {
  2603. // We are bitblting from a compatible bitmap that is
  2604. // not palettized but is a the same format as the
  2605. // meta-surface, so we use the destination palette.
  2606. ppalSrc = pSurfTmp->ppal();
  2607. }
  2608. }
  2609. else
  2610. {
  2611. #if HIDEYUKN_DBG
  2612. DbgPrint("GDI DDML: MulStretchBlt(): ppalSrc is NULL\n");
  2613. DbgBreakPoint();
  2614. #endif
  2615. bError = TRUE;
  2616. }
  2617. }
  2618. }
  2619. if (bError == FALSE)
  2620. {
  2621. XEPALOBJ palSurfSrc(ppalSrc);
  2622. ULONG flFlags = 0;
  2623. if (palSurfSrc.bValid() && palSurfSrc.bIsPalManaged())
  2624. {
  2625. // Source is palette managed surface.
  2626. if (ppalDestDC == ppalDefault)
  2627. {
  2628. // We don't know DC palette here, but we know we are in foregroud,
  2629. // (since translation is trivial)
  2630. // so, we just map from source surface palette to destination
  2631. // surface palette directly (destination is at least higher color
  2632. // depth than source).
  2633. flFlags = XLATE_USE_SURFACE_PAL;
  2634. }
  2635. else
  2636. {
  2637. // We may not be in foreground. but map from foreground translation
  2638. // in source, so that we will not loose original color on secondary
  2639. // devices which can produce higher color depth then source.
  2640. flFlags = XLATE_USE_FOREGROUND;
  2641. }
  2642. }
  2643. if (xloDevice.bInitXlateObj(
  2644. (pxloM ? pxloM->hcmXform : NULL),
  2645. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  2646. palSurfSrc, // Source palette
  2647. pSurfDst->ppal(), // Destination palette
  2648. ppalDefault, // Source DC palette
  2649. ppalDestDC, // Destination DC palette
  2650. (pxloM ? pxloM->iForeDst : 0x0L),
  2651. (pxloM ? pxloM->iBackDst : 0x0L),
  2652. (pxloM ? pxloM->iBackSrc : 0x0L),
  2653. flFlags))
  2654. {
  2655. pxlo = xloDevice.pxlo();
  2656. }
  2657. else
  2658. {
  2659. bError = TRUE;
  2660. }
  2661. }
  2662. }
  2663. }
  2664. if (bError == FALSE)
  2665. {
  2666. PFN_DrvStretchBlt pfn = PPFNMGET(msurf, StretchBlt);
  2667. //
  2668. // If the source is also a device surface, it must correspond
  2669. // to one of the drivers. In this case, call Eng if the
  2670. // same driver does not manage the source and the destination
  2671. //
  2672. if( mSrc.pso->iType == STYPE_DEVICE &&
  2673. (pSurfSrc->hdev() != pSurfDst->hdev()))
  2674. {
  2675. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  2676. }
  2677. //
  2678. // If the driver does not support halftoning we call Eng
  2679. //
  2680. if( iMode == HALFTONE )
  2681. {
  2682. PDEVOBJ pdoTrg(pSurfDst->hdev());
  2683. if (!(pdoTrg.flGraphicsCapsNotDynamic() & GCAPS_HALFTONE))
  2684. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  2685. }
  2686. // Don't call the driver if the source rectangle exceeds the source
  2687. // surface. Some drivers punt using a duplicate of the source
  2688. // SURFOBJ, but without preserving its sizlBitmap member.
  2689. // This causes a source clipping bug (77102).
  2690. if((mSrc.prcl->left < 0) ||
  2691. (mSrc.prcl->top < 0) ||
  2692. (mSrc.prcl->right > mSrc.pso->sizlBitmap.cx) ||
  2693. (mSrc.prcl->bottom > mSrc.pso->sizlBitmap.cy))
  2694. {
  2695. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  2696. }
  2697. bRet &= OffStretchBlt(pfn,
  2698. msurf.pOffset,
  2699. msurf.pso,
  2700. &gptlZero,
  2701. mSrc.pso,
  2702. psoMask,
  2703. msurf.pco,
  2704. pxlo,
  2705. pca,
  2706. pptlHTOrg,
  2707. prclDst,
  2708. mSrc.prcl,
  2709. pptlMask,
  2710. iMode);
  2711. }
  2712. else
  2713. {
  2714. bRet = FALSE;
  2715. }
  2716. // Restore XLATEOBJ
  2717. pxlo = pxloSave;
  2718. } while (msurf.bNextSurface());
  2719. }
  2720. return(bRet);
  2721. }
  2722. /******************************Public*Routine******************************\
  2723. * BOOL MulAlphaBlend
  2724. *
  2725. * History:
  2726. * 17-dec-1998 -by- Andre Matos [amatos]
  2727. * Wrote it.
  2728. *
  2729. \**************************************************************************/
  2730. BOOL MulAlphaBlend(
  2731. SURFOBJ *psoDst,
  2732. SURFOBJ *psoSrc,
  2733. CLIPOBJ *pco,
  2734. XLATEOBJ *pxlo,
  2735. RECTL *prclDst,
  2736. RECTL *prclSrc,
  2737. BLENDOBJ *pBlendObj)
  2738. {
  2739. GDIFunctionID(MulAlphaBlend);
  2740. XLATEOBJ *pxloSave = pxlo;
  2741. XLATEOBJ *pxloSaveDCto32 = ((EBLENDOBJ*)pBlendObj)->pxloDstTo32;
  2742. XLATEOBJ *pxloSave32toDC = ((EBLENDOBJ*)pBlendObj)->pxlo32ToDst;
  2743. XLATEOBJ *pxloSaveSrcTo32 = ((EBLENDOBJ*)pBlendObj)->pxloSrcTo32;
  2744. //
  2745. // We cannot handle cases where the source is a meta,
  2746. // so make a copy in this case.
  2747. //
  2748. SURFMEM srcCopy;
  2749. PDEVOBJ pdoSrc(SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc)->hdev());
  2750. RECTL rclCopy = *prclSrc;
  2751. if( psoSrc->iType == STYPE_DEVICE && pdoSrc.bValid() &&
  2752. pdoSrc.bMetaDriver())
  2753. {
  2754. if(!MulCopyDeviceToDIB( psoSrc, &srcCopy, &rclCopy ))
  2755. return FALSE;
  2756. if(srcCopy.ps == NULL )
  2757. {
  2758. // We didn't get to the point of creating the surface
  2759. // becasue the rect was out of bounds.
  2760. return TRUE;
  2761. }
  2762. prclSrc = &rclCopy;
  2763. psoSrc = srcCopy.pSurfobj();
  2764. pdoSrc.vInit(SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc)->hdev());
  2765. }
  2766. PVDEV pvdev = (VDEV*) psoDst->dhpdev;
  2767. USHORT iDstType = psoDst->iType;
  2768. BOOL bMultiDst;
  2769. BOOL bRet = TRUE;
  2770. MSURF msurf;
  2771. RECTL rclDst;
  2772. RECTL rclSrc;
  2773. ASSERTGDI(iDstType != STYPE_BITMAP, "BITMAP destination\n");
  2774. bMultiDst = msurf.bFindSurface(psoDst, pco, prclDst);
  2775. MULTISURF mSrc(psoSrc,prclSrc);
  2776. //
  2777. // If the destination is a Device Bitmap, we must draw to
  2778. // the master DIB also.
  2779. //
  2780. if (iDstType == STYPE_DEVBITMAP)
  2781. {
  2782. MULTISURF mDst(psoDst,prclDst);
  2783. bRet = EngAlphaBlend(mDst.pso, mSrc.pso, pco, pxlo, mDst.prcl,
  2784. mSrc.prcl, pBlendObj);
  2785. }
  2786. if (bMultiDst)
  2787. {
  2788. do {
  2789. BOOL bError = FALSE;
  2790. EXLATEOBJ xloDevice;
  2791. EXLATEOBJ xloDstDCto32;
  2792. EXLATEOBJ xlo32toDstDC;
  2793. EXLATEOBJ xloSrcTo32;
  2794. XEPALOBJ palRGB(gppalRGB);
  2795. bError = !mSrc.bLoadSource(msurf.pds);
  2796. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso);
  2797. PSURFACE pSurfSrc;
  2798. if (bError == FALSE)
  2799. {
  2800. pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(mSrc.pso);
  2801. // if the target surface is not compatible to primary surface,
  2802. // create XLATEOBJ for source surface to target. otherwise
  2803. // we can just use given XLATEOBJ.
  2804. if (msurf.pds->iCompatibleColorFormat != 0)
  2805. {
  2806. XLATE *pxloM = (XLATE *) pxlo;
  2807. PPALETTE ppalSrc = pSurfSrc->ppal();
  2808. PPALETTE ppalDestDC = ppalDefault;
  2809. PDEVOBJ pdoDst(msurf.pds->hdev);
  2810. if (pdoDst.bIsPalManaged())
  2811. {
  2812. // Use halftone palette for pal-managed device.
  2813. ppalDestDC = REALIZE_HALFTONE_PALETTE(pdoDst.hdev());
  2814. }
  2815. if (!ppalSrc)
  2816. {
  2817. // Source surface does not have associated palette.
  2818. // (Source surface is compatible bitmap)
  2819. if (pxloM && pxloM->ppalSrc)
  2820. {
  2821. // if XLATEOBJ has source palette, use it.
  2822. ppalSrc = pxloM->ppalSrc;
  2823. }
  2824. else
  2825. {
  2826. PSURFACE pSurfTmp = SURFOBJ_TO_SURFACE_NOT_NULL(psoDst);
  2827. if ((pxloM == NULL) || pxloM->bIsIdentity())
  2828. {
  2829. // if translation is identity, we can use the palette for
  2830. // meta-destination surface as source. since it's trivial.
  2831. // WINBUG #396667 10-03-2001 jasonha A/V due to improper XLATE setup
  2832. if (mSrc.pso == psoSrc)
  2833. {
  2834. ppalSrc = pSurfTmp->ppal();
  2835. }
  2836. }
  2837. else if (pxloM->ppalDstDC)
  2838. {
  2839. // We are bitblting from compatible bitmap to a surface in
  2840. // meta-surface. but we are not in foreground.
  2841. ppalDestDC = pxloM->ppalDstDC;
  2842. // WINBUG #274637 02-12-2001 jasonha A/V due to improper XLATE setup
  2843. if (pSurfSrc->iFormat() == pSurfTmp->iFormat())
  2844. {
  2845. // We are bitblting from a compatible bitmap that is
  2846. // not palettized but is a the same format as the
  2847. // meta-surface, so we use the destination palette.
  2848. ppalSrc = pSurfTmp->ppal();
  2849. }
  2850. }
  2851. else
  2852. {
  2853. #if HIDEYUKN_DBG
  2854. DbgPrint("GDI DDML: MulAlphaBlend(): ppalSrc is NULL\n");
  2855. DbgBreakPoint();
  2856. #endif
  2857. bError = TRUE;
  2858. }
  2859. }
  2860. }
  2861. if (bError == FALSE)
  2862. {
  2863. XEPALOBJ palSurfSrc(ppalSrc);
  2864. ULONG flFlags = 0;
  2865. if (palSurfSrc.bValid() && palSurfSrc.bIsPalManaged())
  2866. {
  2867. // Source is palette managed surface.
  2868. if (ppalDestDC == ppalDefault)
  2869. {
  2870. // We don't know DC palette here, but we know we are in foregroud,
  2871. // (since translation is trivial)
  2872. // so, we just map from source surface palette to destination
  2873. // surface palette directly (destination is at least higher color
  2874. // depth than source).
  2875. flFlags = XLATE_USE_SURFACE_PAL;
  2876. }
  2877. else
  2878. {
  2879. // We may not be in foreground. but map from foreground translation
  2880. // in source, so that we will not loose original color on secondary
  2881. // devices which can produce higher color depth then source.
  2882. flFlags = XLATE_USE_FOREGROUND;
  2883. }
  2884. }
  2885. ULONG iForeDst;
  2886. if( pxloM )
  2887. {
  2888. iForeDst = pxloM->iForeDst;
  2889. }
  2890. else
  2891. {
  2892. iForeDst = 0x0L;
  2893. }
  2894. ULONG iBackDst;
  2895. if( pxloM )
  2896. {
  2897. iBackDst = pxloM->iBackDst;
  2898. }
  2899. else
  2900. {
  2901. iBackDst = 0x0L;
  2902. }
  2903. ULONG iBackSrc;
  2904. if( pxloM )
  2905. {
  2906. iBackSrc = pxloM->iBackSrc;
  2907. }
  2908. else
  2909. {
  2910. iBackSrc = 0x0L;
  2911. }
  2912. //
  2913. // Src to Dst
  2914. //
  2915. if (xloDevice.bInitXlateObj(
  2916. (pxloM ? pxloM->hcmXform : NULL),
  2917. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  2918. palSurfSrc, // Source palette
  2919. pSurfDst->ppal(), // Destination palette
  2920. ppalDefault, // Source DC palette
  2921. ppalDestDC, // Destination DC palette
  2922. iForeDst,
  2923. iBackDst,
  2924. iBackSrc,
  2925. flFlags))
  2926. {
  2927. pxlo = xloDevice.pxlo();
  2928. }
  2929. else
  2930. {
  2931. bError = TRUE;
  2932. }
  2933. //
  2934. // Dst to 32
  2935. //
  2936. if ((bError == FALSE) &&
  2937. xloDstDCto32.bInitXlateObj(
  2938. NULL,
  2939. DC_ICM_OFF,
  2940. pSurfDst->ppal(),
  2941. palRGB,
  2942. ppalDestDC,
  2943. ppalDestDC,
  2944. iForeDst,
  2945. iBackDst,
  2946. iBackSrc))
  2947. {
  2948. ((EBLENDOBJ*)pBlendObj)->pxloDstTo32 = xloDstDCto32.pxlo();
  2949. }
  2950. else
  2951. {
  2952. bError = TRUE;
  2953. }
  2954. //
  2955. // 32 to Dst
  2956. //
  2957. if ((bError == FALSE) &&
  2958. xlo32toDstDC.bInitXlateObj(
  2959. NULL,
  2960. DC_ICM_OFF,
  2961. palRGB,
  2962. pSurfDst->ppal(),
  2963. ppalDestDC,
  2964. ppalDestDC,
  2965. iForeDst,
  2966. iBackDst,
  2967. iBackSrc))
  2968. {
  2969. ((EBLENDOBJ*)pBlendObj)->pxlo32ToDst = xlo32toDstDC.pxlo();
  2970. }
  2971. else
  2972. {
  2973. bError = TRUE;
  2974. }
  2975. //
  2976. // Src to 32
  2977. //
  2978. if ((bError == FALSE) &&
  2979. (mSrc.pso != psoSrc))
  2980. {
  2981. if (xloSrcTo32.bInitXlateObj(
  2982. NULL,
  2983. DC_ICM_OFF,
  2984. pSurfSrc->ppal(),
  2985. palRGB,
  2986. ppalDefault,
  2987. ppalDestDC,
  2988. iForeDst,
  2989. iBackDst,
  2990. iBackSrc))
  2991. {
  2992. ((EBLENDOBJ*)pBlendObj)->pxloSrcTo32 = xloSrcTo32.pxlo();
  2993. }
  2994. else
  2995. {
  2996. bError = TRUE;
  2997. }
  2998. }
  2999. }
  3000. }
  3001. }
  3002. if (bError == FALSE)
  3003. {
  3004. PFN_DrvAlphaBlend pfn = PPFNMGET(msurf, AlphaBlend);
  3005. //
  3006. // If the source is also a device surface, it must correspond
  3007. // to one of the drivers. In this case, call Eng if the
  3008. // same driver does not manage the source and the destination
  3009. //
  3010. if( mSrc.pso->iType == STYPE_DEVICE &&
  3011. (pSurfSrc->hdev() != pSurfDst->hdev()))
  3012. {
  3013. pfn = (PFN_DrvAlphaBlend)EngAlphaBlend;
  3014. }
  3015. bRet &= OffAlphaBlend(pfn,
  3016. msurf.pOffset,
  3017. msurf.pso,
  3018. &gptlZero,
  3019. mSrc.pso,
  3020. msurf.pco,
  3021. pxlo,
  3022. prclDst,
  3023. mSrc.prcl,
  3024. pBlendObj);
  3025. }
  3026. else
  3027. {
  3028. bRet = FALSE;
  3029. }
  3030. // Restore XLATEOBJ
  3031. pxlo = pxloSave;
  3032. ((EBLENDOBJ*)pBlendObj)->pxloDstTo32 = pxloSaveDCto32;
  3033. ((EBLENDOBJ*)pBlendObj)->pxlo32ToDst = pxloSave32toDC;
  3034. ((EBLENDOBJ*)pBlendObj)->pxloSrcTo32 = pxloSaveSrcTo32;
  3035. } while (msurf.bNextSurface());
  3036. }
  3037. return(bRet);
  3038. }
  3039. /******************************Public*Routine******************************\
  3040. * BOOL MulTransparentBlt
  3041. *
  3042. * History:
  3043. * 22-Dec-1998 -by- Andre Matos [amatos]
  3044. * Wrote it.
  3045. *
  3046. \**************************************************************************/
  3047. BOOL MulTransparentBlt(
  3048. SURFOBJ* psoDst,
  3049. SURFOBJ* psoSrc,
  3050. CLIPOBJ* pco,
  3051. XLATEOBJ* pxlo,
  3052. RECTL* prclDst,
  3053. RECTL* prclSrc,
  3054. ULONG TransColor,
  3055. ULONG ulReserved)
  3056. {
  3057. GDIFunctionID(MulTransparentBlt);
  3058. XLATEOBJ *pxloSave = pxlo;
  3059. ULONG TransColorSave = TransColor;
  3060. //
  3061. // We cannot handle cases where the source is a meta,
  3062. // so make a copy in this case.
  3063. //
  3064. SURFMEM srcCopy;
  3065. PDEVOBJ pdoSrc(SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc)->hdev());
  3066. RECTL rclCopy = *prclSrc;
  3067. if( psoSrc->iType == STYPE_DEVICE && pdoSrc.bValid() &&
  3068. pdoSrc.bMetaDriver())
  3069. {
  3070. if(!MulCopyDeviceToDIB( psoSrc, &srcCopy, &rclCopy ))
  3071. return FALSE;
  3072. if(srcCopy.ps == NULL )
  3073. {
  3074. // We didn't get to the point of creating the surface
  3075. // becasue the rect was out of bounds.
  3076. return TRUE;
  3077. }
  3078. prclSrc = &rclCopy;
  3079. psoSrc = srcCopy.pSurfobj();
  3080. pdoSrc.vInit(SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc)->hdev());
  3081. }
  3082. PVDEV pvdev = (VDEV*) psoDst->dhpdev;
  3083. USHORT iDstType = psoDst->iType;
  3084. BOOL bMultiDst;
  3085. BOOL bRet = TRUE;
  3086. MSURF msurf;
  3087. RECTL rclDst;
  3088. RECTL rclSrc;
  3089. ASSERTGDI(iDstType != STYPE_BITMAP, "BITMAP destination\n");
  3090. bMultiDst = msurf.bFindSurface(psoDst, pco, prclDst);
  3091. MULTISURF mSrc(psoSrc,prclSrc);
  3092. //
  3093. // If the destination is a Device Bitmap, we must draw to
  3094. // the master DIB also.
  3095. //
  3096. if (iDstType == STYPE_DEVBITMAP)
  3097. {
  3098. MULTISURF mDst(psoDst,prclDst);
  3099. bRet = EngTransparentBlt(mDst.pso, mSrc.pso, pco, pxlo,
  3100. mDst.prcl, mSrc.prcl, TransColor, ulReserved);
  3101. }
  3102. if (bMultiDst)
  3103. {
  3104. do {
  3105. BOOL bError = FALSE;
  3106. EXLATEOBJ xloDevice;
  3107. bError = !mSrc.bLoadSource(msurf.pds);
  3108. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso);
  3109. PSURFACE pSurfSrc;
  3110. if (bError == FALSE)
  3111. {
  3112. pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(mSrc.pso);
  3113. // if the target surface is not compatible to primary surface,
  3114. // create XLATEOBJ for source surface to target. otherwise
  3115. // we can just use given XLATEOBJ.
  3116. if (msurf.pds->iCompatibleColorFormat != 0)
  3117. {
  3118. XLATE *pxloM = (XLATE *) pxlo;
  3119. PPALETTE ppalSrc = pSurfSrc->ppal();
  3120. PPALETTE ppalDestDC = ppalDefault;
  3121. PDEVOBJ pdoDst(msurf.pds->hdev);
  3122. if (pdoDst.bIsPalManaged())
  3123. {
  3124. // Use halftone palette for pal-managed device.
  3125. ppalDestDC = REALIZE_HALFTONE_PALETTE(pdoDst.hdev());
  3126. }
  3127. if (!ppalSrc)
  3128. {
  3129. // Source surface does not have associated palette.
  3130. // (Source surface is compatible bitmap)
  3131. if (pxloM && pxloM->ppalSrc)
  3132. {
  3133. // if XLATEOBJ has source palette, use it.
  3134. ppalSrc = pxloM->ppalSrc;
  3135. }
  3136. else
  3137. {
  3138. PSURFACE pSurfTmp = SURFOBJ_TO_SURFACE_NOT_NULL(psoDst);
  3139. if ((pxloM == NULL) || pxloM->bIsIdentity())
  3140. {
  3141. // if translation is identity, we can use the palette for
  3142. // meta-destination surface as source. since it's trivial.
  3143. // WINBUG #396667 10-03-2001 jasonha A/V due to improper XLATE setup
  3144. if (mSrc.pso == psoSrc)
  3145. {
  3146. ppalSrc = pSurfTmp->ppal();
  3147. }
  3148. }
  3149. else if (pxloM->ppalDstDC)
  3150. {
  3151. // We are bitblting from compatible bitmap to a surface in
  3152. // meta-surface. but we are not in foreground.
  3153. ppalDestDC = pxloM->ppalDstDC;
  3154. // WINBUG #274637 02-12-2001 jasonha A/V due to improper XLATE setup
  3155. if (pSurfSrc->iFormat() == pSurfTmp->iFormat())
  3156. {
  3157. // We are bitblting from a compatible bitmap that is
  3158. // not palettized but is a the same format as the
  3159. // meta-surface, so we use the destination palette.
  3160. ppalSrc = pSurfTmp->ppal();
  3161. }
  3162. }
  3163. else
  3164. {
  3165. #if HIDEYUKN_DBG
  3166. DbgPrint("GDI DDML: MulTransparent(): ppalSrc is NULL\n");
  3167. DbgBreakPoint();
  3168. #endif
  3169. bError = TRUE;
  3170. }
  3171. }
  3172. }
  3173. if (bError == FALSE)
  3174. {
  3175. XEPALOBJ palSurfSrc(ppalSrc);
  3176. ULONG flFlags = 0;
  3177. if (palSurfSrc.bValid() && palSurfSrc.bIsPalManaged())
  3178. {
  3179. // Source is palette managed surface.
  3180. if (ppalDestDC == ppalDefault)
  3181. {
  3182. // We don't know DC palette here, but we know we are in foregroud,
  3183. // (since translation is trivial)
  3184. // so, we just map from source surface palette to destination
  3185. // surface palette directly (destination is at least higher color
  3186. // depth than source).
  3187. flFlags = XLATE_USE_SURFACE_PAL;
  3188. }
  3189. else
  3190. {
  3191. // We may not be in foreground. but map from foreground translation
  3192. // in source, so that we will not loose original color on secondary
  3193. // devices which can produce higher color depth then source.
  3194. flFlags = XLATE_USE_FOREGROUND;
  3195. }
  3196. }
  3197. if (xloDevice.bInitXlateObj(
  3198. (pxloM ? pxloM->hcmXform : NULL),
  3199. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  3200. palSurfSrc, // Source palette
  3201. pSurfDst->ppal(), // Destination palette
  3202. ppalDefault, // Source DC palette
  3203. ppalDestDC, // Destination DC palette
  3204. (pxloM ? pxloM->iForeDst : 0x0L),
  3205. (pxloM ? pxloM->iBackDst : 0x0L),
  3206. (pxloM ? pxloM->iBackSrc : 0x0L),
  3207. flFlags))
  3208. {
  3209. pxlo = xloDevice.pxlo();
  3210. }
  3211. else
  3212. {
  3213. bError = TRUE;
  3214. }
  3215. }
  3216. }
  3217. if (mSrc.pso != psoSrc)
  3218. {
  3219. PSURFACE pSurfSrcOrg = SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc);
  3220. TransColor =
  3221. ulGetNearestIndexFromColorref(
  3222. pSurfSrc->ppal(),
  3223. ppalDefault,
  3224. ulIndexToRGB(
  3225. pSurfSrcOrg->ppal(),
  3226. ppalDefault,
  3227. TransColor),
  3228. SE_DO_SEARCH_EXACT_FIRST);
  3229. }
  3230. }
  3231. if (bError == FALSE)
  3232. {
  3233. PFN_DrvTransparentBlt pfn = PPFNMGET(msurf, TransparentBlt);
  3234. //
  3235. // If the source is also a device surface, it must correspond
  3236. // to one of the drivers. In this case, call Eng if the
  3237. // same driver does not manage the source and the destination
  3238. //
  3239. if( mSrc.pso->iType == STYPE_DEVICE &&
  3240. (pSurfSrc->hdev() != pSurfDst->hdev()))
  3241. {
  3242. pfn = (PFN_DrvTransparentBlt)EngTransparentBlt;
  3243. }
  3244. bRet &= OffTransparentBlt(pfn,
  3245. msurf.pOffset,
  3246. msurf.pso,
  3247. &gptlZero,
  3248. mSrc.pso,
  3249. msurf.pco,
  3250. pxlo,
  3251. prclDst,
  3252. mSrc.prcl,
  3253. TransColor,
  3254. ulReserved);
  3255. }
  3256. else
  3257. {
  3258. bRet = FALSE;
  3259. }
  3260. // Restore XLATEOBJ
  3261. pxlo = pxloSave;
  3262. TransColor = TransColorSave;
  3263. } while (msurf.bNextSurface());
  3264. }
  3265. return(bRet);
  3266. }
  3267. /******************************Public*Routine******************************\
  3268. * BOOL MulDrawStream
  3269. *
  3270. * 1-27-2001 bhouse
  3271. * Wrote it.
  3272. *
  3273. \**************************************************************************/
  3274. BOOL MulDrawStream(
  3275. SURFOBJ* psoDst,
  3276. SURFOBJ* psoSrc,
  3277. CLIPOBJ* pco,
  3278. XLATEOBJ* pxlo,
  3279. RECTL* prclDstBounds,
  3280. POINTL* pptlDstOffset,
  3281. ULONG ulIn,
  3282. PVOID pvIn,
  3283. DSSTATE* pdss)
  3284. {
  3285. GDIFunctionID(MulDrawStream);
  3286. XLATEOBJ * pxloSave = pxlo;
  3287. PDRAWSTREAMINFO pdsi = (PDRAWSTREAMINFO) pdss;
  3288. XLATEOBJ * pxloSaveDstToBGRA = pdsi->pxloDstToBGRA;
  3289. XLATEOBJ * pxloSaveBGRAToDst = pdsi->pxloBGRAToDst;
  3290. XLATEOBJ * pxloSaveSrcToBGRA = pdsi->pxloSrcToBGRA;
  3291. COLORREF crSaveColorKey = pdsi->dss.crColorKey;
  3292. //
  3293. // We cannot handle cases where the source is a meta,
  3294. // so make a copy in this case.
  3295. //
  3296. PDEVOBJ pdoSrc(SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc)->hdev());
  3297. if( psoSrc->iType == STYPE_DEVICE && pdoSrc.bValid() &&
  3298. pdoSrc.bMetaDriver())
  3299. {
  3300. DbgPrint("MulDrawStream: this should never happen\n");
  3301. return TRUE;
  3302. }
  3303. PVDEV pvdev = (VDEV*) psoDst->dhpdev;
  3304. USHORT iDstType = psoDst->iType;
  3305. BOOL bMultiDst;
  3306. BOOL bRet = TRUE;
  3307. MSURF msurf;
  3308. RECTL rclDst;
  3309. RECTL rclSrc;
  3310. ASSERTGDI(iDstType != STYPE_BITMAP, "BITMAP destination\n");
  3311. bMultiDst = msurf.bFindSurface(psoDst, pco, prclDstBounds);
  3312. MULTISURF mSrc(psoSrc);
  3313. //
  3314. // If the destination is a Device Bitmap, we must draw to
  3315. // the master DIB also.
  3316. //
  3317. if (iDstType == STYPE_DEVBITMAP)
  3318. {
  3319. MULTISURF mDst(psoDst);
  3320. bRet = EngDrawStream(mDst.pso, mSrc.pso, pco, pxlo,
  3321. prclDstBounds, pptlDstOffset, ulIn, pvIn, pdss);
  3322. }
  3323. // TODO bhouse
  3324. // Need to fix translates in pdsi
  3325. if (bMultiDst)
  3326. {
  3327. do {
  3328. BOOL bError = FALSE;
  3329. EXLATEOBJ xloDevice;
  3330. EXLATEOBJ xloDstToBGRA;
  3331. EXLATEOBJ xloBGRAToDst;
  3332. EXLATEOBJ xloSrcToBGRA;
  3333. XEPALOBJ palRGB(gppalRGB);
  3334. bError = !mSrc.bLoadSource(msurf.pds);
  3335. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso);
  3336. PSURFACE pSurfSrc;
  3337. if (bError == FALSE)
  3338. {
  3339. pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(mSrc.pso);
  3340. // if the target surface is not compatible to primary surface,
  3341. // create XLATEOBJ for source surface to target. otherwise
  3342. // we can just use given XLATEOBJ.
  3343. if (msurf.pds->iCompatibleColorFormat != 0)
  3344. {
  3345. XLATE *pxloM = (XLATE *) pxlo;
  3346. PPALETTE ppalSrc = pSurfSrc->ppal();
  3347. PPALETTE ppalDestDC = ppalDefault;
  3348. PDEVOBJ pdoDst(msurf.pds->hdev);
  3349. if (pdoDst.bIsPalManaged())
  3350. {
  3351. // Use halftone palette for pal-managed device.
  3352. ppalDestDC = REALIZE_HALFTONE_PALETTE(pdoDst.hdev());
  3353. }
  3354. if (!ppalSrc)
  3355. {
  3356. // Source surface does not have associated palette.
  3357. // (Source surface is compatible bitmap)
  3358. if (pxloM && pxloM->ppalSrc)
  3359. {
  3360. // if XLATEOBJ has source palette, use it.
  3361. ppalSrc = pxloM->ppalSrc;
  3362. }
  3363. else
  3364. {
  3365. PSURFACE pSurfTmp = SURFOBJ_TO_SURFACE_NOT_NULL(psoDst);
  3366. if ((pxloM == NULL) || pxloM->bIsIdentity())
  3367. {
  3368. // if translation is identity, we can use the palette for
  3369. // meta-destination surface as source. since it's trivial.
  3370. // WINBUG #396667 10-03-2001 jasonha A/V due to improper XLATE setup
  3371. if (mSrc.pso == psoSrc)
  3372. {
  3373. ppalSrc = pSurfTmp->ppal();
  3374. }
  3375. }
  3376. else if (pxloM->ppalDstDC)
  3377. {
  3378. // We are bitblting from compatible bitmap to a surface in
  3379. // meta-surface. but we are not in foreground.
  3380. ppalDestDC = pxloM->ppalDstDC;
  3381. // WINBUG #274637 02-12-2001 jasonha A/V due to improper XLATE setup
  3382. if (pSurfSrc->iFormat() == pSurfTmp->iFormat())
  3383. {
  3384. // We are bitblting from a compatible bitmap that is
  3385. // not palettized but is a the same format as the
  3386. // meta-surface, so we use the destination palette.
  3387. ppalSrc = pSurfTmp->ppal();
  3388. }
  3389. }
  3390. else
  3391. {
  3392. #if HIDEYUKN_DBG
  3393. DbgPrint("GDI DDML: MulDrawStream(): ppalSrc is NULL\n");
  3394. DbgBreakPoint();
  3395. #endif
  3396. bError = TRUE;
  3397. }
  3398. }
  3399. }
  3400. if (bError == FALSE)
  3401. {
  3402. XEPALOBJ palSurfSrc(ppalSrc);
  3403. ULONG flFlags = 0;
  3404. if (palSurfSrc.bValid() && palSurfSrc.bIsPalManaged())
  3405. {
  3406. // Source is palette managed surface.
  3407. if (ppalDestDC == ppalDefault)
  3408. {
  3409. // We don't know DC palette here, but we know we are in foregroud,
  3410. // (since translation is trivial)
  3411. // so, we just map from source surface palette to destination
  3412. // surface palette directly (destination is at least higher color
  3413. // depth than source).
  3414. flFlags = XLATE_USE_SURFACE_PAL;
  3415. }
  3416. else
  3417. {
  3418. // We may not be in foreground. but map from foreground translation
  3419. // in source, so that we will not loose original color on secondary
  3420. // devices which can produce higher color depth then source.
  3421. flFlags = XLATE_USE_FOREGROUND;
  3422. }
  3423. }
  3424. if (xloDevice.bInitXlateObj(
  3425. (pxloM ? pxloM->hcmXform : NULL),
  3426. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  3427. palSurfSrc, // Source palette
  3428. pSurfDst->ppal(), // Destination palette
  3429. ppalDefault, // Source DC palette
  3430. ppalDestDC, // Destination DC palette
  3431. (pxloM ? pxloM->iForeDst : 0x0L),
  3432. (pxloM ? pxloM->iBackDst : 0x0L),
  3433. (pxloM ? pxloM->iBackSrc : 0x0L),
  3434. flFlags))
  3435. {
  3436. pxlo = xloDevice.pxlo();
  3437. }
  3438. else
  3439. {
  3440. bError = TRUE;
  3441. }
  3442. if ((bError == FALSE) &&
  3443. xloDstToBGRA.bInitXlateObj(
  3444. NULL,
  3445. DC_ICM_OFF,
  3446. pSurfDst->ppal(),
  3447. palRGB,
  3448. ppalDestDC,
  3449. ppalDestDC,
  3450. (pxloM ? pxloM->iForeDst : 0x0L),
  3451. (pxloM ? pxloM->iBackDst : 0x0L),
  3452. (pxloM ? pxloM->iBackSrc : 0x0L)))
  3453. {
  3454. pdsi->pxloDstToBGRA = xloDstToBGRA.pxlo();
  3455. }
  3456. else
  3457. {
  3458. bError = TRUE;
  3459. }
  3460. //
  3461. // 32 to Dst
  3462. //
  3463. if ((bError == FALSE) &&
  3464. xloBGRAToDst.bInitXlateObj(
  3465. NULL,
  3466. DC_ICM_OFF,
  3467. palRGB,
  3468. pSurfDst->ppal(),
  3469. ppalDestDC,
  3470. ppalDestDC,
  3471. (pxloM ? pxloM->iForeDst : 0x0L),
  3472. (pxloM ? pxloM->iBackDst : 0x0L),
  3473. (pxloM ? pxloM->iBackSrc : 0x0L)))
  3474. {
  3475. pdsi->pxloBGRAToDst = xloBGRAToDst.pxlo();
  3476. }
  3477. else
  3478. {
  3479. bError = TRUE;
  3480. }
  3481. if ((bError == FALSE) &&
  3482. (mSrc.pso != psoSrc))
  3483. {
  3484. //
  3485. // Src to 32
  3486. //
  3487. if (xloSrcToBGRA.bInitXlateObj(
  3488. NULL,
  3489. DC_ICM_OFF,
  3490. pSurfSrc->ppal(),
  3491. palRGB,
  3492. ppalDefault,
  3493. ppalDestDC,
  3494. (pxloM ? pxloM->iForeDst : 0x0L),
  3495. (pxloM ? pxloM->iBackDst : 0x0L),
  3496. (pxloM ? pxloM->iBackSrc : 0x0L)))
  3497. {
  3498. pdsi->pxloSrcToBGRA = xloSrcToBGRA.pxlo();
  3499. }
  3500. else
  3501. {
  3502. bError = TRUE;
  3503. }
  3504. if (bError == FALSE)
  3505. {
  3506. PSURFACE pSurfSrcOrg = SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc);
  3507. pdsi->dss.crColorKey =
  3508. ulGetNearestIndexFromColorref(
  3509. pSurfSrc->ppal(),
  3510. ppalDefault,
  3511. ulIndexToRGB(
  3512. pSurfSrcOrg->ppal(),
  3513. ppalDefault,
  3514. pdsi->dss.crColorKey),
  3515. SE_DO_SEARCH_EXACT_FIRST);
  3516. }
  3517. }
  3518. }
  3519. }
  3520. }
  3521. if (bError == FALSE)
  3522. {
  3523. PFN_DrvDrawStream pfn = PPFNDRVENG(msurf.pds->po, DrawStream);
  3524. //
  3525. // If the source is also a device surface, it must correspond
  3526. // to one of the drivers. In this case, call Eng if the
  3527. // same driver does not manage the source and the destination
  3528. //
  3529. if( mSrc.pso->iType == STYPE_DEVICE &&
  3530. (pSurfSrc->hdev() != pSurfDst->hdev()))
  3531. {
  3532. pfn = (PFN_DrvDrawStream) EngDrawStream;
  3533. }
  3534. bRet &= OffDrawStream(pfn,
  3535. msurf.pOffset,
  3536. msurf.pso,
  3537. mSrc.pso,
  3538. msurf.pco,
  3539. pxlo,
  3540. prclDstBounds,
  3541. pptlDstOffset,
  3542. ulIn,
  3543. pvIn,
  3544. pdss);
  3545. }
  3546. else
  3547. {
  3548. bRet = FALSE;
  3549. }
  3550. // Restore XLATEOBJ
  3551. pxlo = pxloSave;
  3552. pdsi->pxloBGRAToDst = pxloSaveBGRAToDst;
  3553. pdsi->pxloDstToBGRA = pxloSaveDstToBGRA;
  3554. pdsi->pxloSrcToBGRA = pxloSaveSrcToBGRA;
  3555. pdsi->dss.crColorKey = crSaveColorKey;
  3556. } while (msurf.bNextSurface());
  3557. }
  3558. return(bRet);
  3559. }
  3560. /******************************Public*Routine******************************\
  3561. * BOOL bSrcBeforeDst
  3562. *
  3563. * This function determines if the source rectangle, offset by dx and dy,
  3564. * will intersect the destination rectangle. In other words, the source
  3565. * will be required to do the blt to the destination. This means that the
  3566. * blt must be done to the destination before the blt to the source so that
  3567. * the source bits are not overwritten before they're used.
  3568. *
  3569. * History:
  3570. * 25-Apr-1996 -by- Tom Zakrajsek [tomzak]
  3571. * Wrote it.
  3572. *
  3573. \**************************************************************************/
  3574. inline BOOL bSrcBeforeDst(
  3575. RECTL* prclDst,
  3576. RECTL* prclSrc,
  3577. LONG dx,
  3578. LONG dy)
  3579. {
  3580. return((prclDst->left < dx + prclSrc->right) &&
  3581. (prclDst->right > dx + prclSrc->left) &&
  3582. (prclDst->top < dy + prclSrc->bottom) &&
  3583. (prclDst->bottom > dy + prclSrc->top));
  3584. }
  3585. /******************************Public*Routine******************************\
  3586. * VOID vSortBltOrder
  3587. *
  3588. * This function sorts the list of surfaces for the correct ordering on
  3589. * screen-to-screen blts that span boards.
  3590. *
  3591. * When this routine is done, 'pvdev->pdsBlt' will point to the first
  3592. * surface that should be processed, and each surface's 'pdsBltNext'
  3593. * field will point to the next one in order.
  3594. *
  3595. * History:
  3596. * 25-Apr-1996 -by- Tom Zakrajsek [tomzak]
  3597. * Wrote it.
  3598. *
  3599. \**************************************************************************/
  3600. VOID vSortBltOrder(
  3601. VDEV* pvdev,
  3602. LONG dx,
  3603. LONG dy)
  3604. {
  3605. DISPSURF* pdsBltHeadOld = pvdev->pdsBlt;
  3606. DISPSURF* pdsBltHeadNew = pdsBltHeadOld;
  3607. pdsBltHeadOld = pdsBltHeadOld->pdsBltNext;
  3608. pdsBltHeadNew->pdsBltNext = NULL;
  3609. while (pdsBltHeadOld)
  3610. {
  3611. DISPSURF * pdsBltInsert = pdsBltHeadOld;
  3612. DISPSURF * pdsBltPrev = pdsBltHeadNew;
  3613. DISPSURF * pdsBltCur = pdsBltHeadNew;
  3614. pdsBltInsert = pdsBltHeadOld;
  3615. pdsBltHeadOld = pdsBltHeadOld->pdsBltNext;
  3616. while((pdsBltCur) &&
  3617. (!bSrcBeforeDst(&pdsBltInsert->rcl, // Dst
  3618. &pdsBltCur->rcl, // Src
  3619. dx,
  3620. dy)))
  3621. {
  3622. pdsBltPrev = pdsBltCur;
  3623. pdsBltCur = pdsBltCur->pdsBltNext;
  3624. }
  3625. if (pdsBltCur == pdsBltHeadNew)
  3626. {
  3627. pdsBltHeadNew = pdsBltInsert;
  3628. pdsBltInsert->pdsBltNext = pdsBltCur;
  3629. }
  3630. else
  3631. {
  3632. pdsBltPrev->pdsBltNext = pdsBltInsert;
  3633. pdsBltInsert->pdsBltNext = pdsBltCur;
  3634. }
  3635. }
  3636. pvdev->pdsBlt = pdsBltHeadNew;
  3637. }
  3638. /******************************Public*Routine******************************\
  3639. * BOOL bBitBltScreenToScreen
  3640. *
  3641. * Handles screen-to-screen blts that may possibly span multiple displays.
  3642. *
  3643. \**************************************************************************/
  3644. BOOL bBitBltScreenToScreen(
  3645. SURFOBJ *pso,
  3646. SURFOBJ *psoMask,
  3647. CLIPOBJ *pco,
  3648. XLATEOBJ *pxlo,
  3649. RECTL *prclDst,
  3650. POINTL *pptlSrc,
  3651. POINTL *pptlMask,
  3652. BRUSHOBJ *pbo,
  3653. POINTL *pptlBrush,
  3654. ROP4 rop4)
  3655. {
  3656. VDEV* pvdev;
  3657. LONG dx;
  3658. LONG dy;
  3659. DISPSURF* pdsDst;
  3660. DISPSURF* pdsSrc;
  3661. SURFOBJ* psoDst;
  3662. SURFOBJ* psoSrc;
  3663. POINTL* pOffDst;
  3664. POINTL* pOffSrc;
  3665. RECTL rclDst;
  3666. POINTL ptlSrc;
  3667. #if _MSC_VER < 1300
  3668. DHSURF dhsurfSave;
  3669. DHPDEV dhpdevSave;
  3670. #endif
  3671. SIZEL sizl;
  3672. HSURF hsurfTmp;
  3673. SURFOBJ* psoTmp;
  3674. RECTL rclDstTmp;
  3675. BOOL bRet;
  3676. RECTL rclSaveBounds;
  3677. bRet = TRUE;
  3678. pvdev = (VDEV*) pso->dhpdev;
  3679. dx = prclDst->left - pptlSrc->x;
  3680. dy = prclDst->top - pptlSrc->y;
  3681. vSortBltOrder(pvdev, dx, dy);
  3682. XLATEOBJ *pxloSave = pxlo;
  3683. MULTIBRUSH MBRUSH(pbo, pvdev->cSurfaces, pvdev, pvdev->pso, ROP4_NEEDS_PATTERN(rop4));
  3684. if (!MBRUSH.Valid())
  3685. {
  3686. return FALSE;
  3687. }
  3688. if (pco != NULL)
  3689. {
  3690. rclSaveBounds = pco->rclBounds;
  3691. }
  3692. BOOL bWndBltNotify = (pso != NULL) && (pso->fjBitmap & BMF_WINDOW_BLT);
  3693. for (pdsDst = pvdev->pdsBlt; pdsDst != NULL; pdsDst = pdsDst->pdsBltNext)
  3694. {
  3695. for (pdsSrc = pdsDst; pdsSrc != NULL; pdsSrc = pdsSrc->pdsBltNext)
  3696. {
  3697. rclDst.left = dx + pdsSrc->rcl.left;
  3698. rclDst.right = dx + pdsSrc->rcl.right;
  3699. rclDst.top = dy + pdsSrc->rcl.top;
  3700. rclDst.bottom = dy + pdsSrc->rcl.bottom;
  3701. if (bIntersect(prclDst, &rclDst, &rclDst) &&
  3702. bIntersect(&rclDst, &pdsDst->rcl, &rclDst))
  3703. {
  3704. ptlSrc.x = rclDst.left - dx;
  3705. ptlSrc.y = rclDst.top - dy;
  3706. psoSrc = pdsSrc->pso;
  3707. psoDst = pdsDst->pso;
  3708. pOffSrc = &pdsSrc->Off;
  3709. pOffDst = &pdsDst->Off;
  3710. #if _MSC_VER < 1300
  3711. dhpdevSave = NULL;
  3712. #endif
  3713. hsurfTmp = NULL;
  3714. if (psoSrc == psoDst)
  3715. {
  3716. // This simply amounts to a screen-to-screen blt on
  3717. // the same surface.
  3718. }
  3719. else if ((!pdsSrc->bIsReadable) ||
  3720. (bIntersect(&pdsSrc->rcl, &pdsDst->rcl)))
  3721. {
  3722. // If the source surface isn't readable, or if the two
  3723. // surfaces overlap (such as can happen when two display
  3724. // cards are echoing the same output), don't use the
  3725. // source as a destination for updating the display. We
  3726. // need to do this otherwise when we do a screen-to-
  3727. // screen blt with a mirroring driver in the background,
  3728. // we'll think that the mirrored surface has to be blt
  3729. // to the screen -- but the read of the surface will
  3730. // fail and we'll end up blting blackness.
  3731. psoSrc = NULL;
  3732. }
  3733. else
  3734. {
  3735. // This blt has to happen across boards, and the source
  3736. // bits aren't directly readable. We'll have to create
  3737. // a temporary buffer and make a copy:
  3738. sizl.cx = rclDst.right - rclDst.left;
  3739. sizl.cy = rclDst.bottom - rclDst.top;
  3740. PDEVOBJ pdoSrc(pdsSrc->hdev);
  3741. hsurfTmp = (HSURF) EngCreateBitmap(sizl,
  3742. 0,
  3743. pdoSrc.iDitherFormat(),
  3744. 0,
  3745. NULL);
  3746. psoTmp = EngLockSurface(hsurfTmp);
  3747. if (psoTmp)
  3748. {
  3749. rclDstTmp.left = 0;
  3750. rclDstTmp.top = 0;
  3751. rclDstTmp.right = sizl.cx;
  3752. rclDstTmp.bottom = sizl.cy;
  3753. bRet &= OffCopyBits(*PPFNGET(pdoSrc,
  3754. CopyBits,
  3755. pdoSrc.pSurface()->flags()),
  3756. &gptlZero,
  3757. psoTmp,
  3758. &pdsSrc->Off,
  3759. psoSrc,
  3760. NULL,
  3761. NULL,
  3762. &rclDstTmp,
  3763. &ptlSrc);
  3764. }
  3765. psoSrc = psoTmp;
  3766. pOffSrc = &gptlZero;
  3767. ptlSrc.x = 0;
  3768. ptlSrc.y = 0;
  3769. }
  3770. // Do the blt:
  3771. if (psoSrc)
  3772. {
  3773. BOOL bError = FALSE;
  3774. PDEVOBJ pdoSrc(pdsSrc->hdev);
  3775. PDEVOBJ pdoDst(pdsDst->hdev);
  3776. EXLATEOBJ xloDevice;
  3777. if ((psoDst != psoSrc) &&
  3778. ((pdsDst->iCompatibleColorFormat != 0) ||
  3779. (pdsSrc->iCompatibleColorFormat != 0)))
  3780. {
  3781. XLATE *pxloM = (XLATE *) pxlo;
  3782. PSURFACE pSurfSrc = pdsSrc->po.pSurface();
  3783. PSURFACE pSurfDst = pdsDst->po.pSurface();
  3784. PPALETTE ppalSrcDC = ppalDefault;
  3785. PPALETTE ppalDstDC = ppalDefault;
  3786. // If destination surface is not compatible as primary
  3787. // and pal-managed device, then use halftone palette
  3788. // (source is higher then destination).
  3789. if ((pdsDst->iCompatibleColorFormat != 0) &&
  3790. pdoDst.bIsPalManaged())
  3791. {
  3792. ppalDstDC = REALIZE_HALFTONE_PALETTE(pdoDst.hdev());
  3793. }
  3794. if (xloDevice.bInitXlateObj(
  3795. (pxloM ? pxloM->hcmXform : NULL),
  3796. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  3797. pSurfSrc->ppal(), // Source palette
  3798. pSurfDst->ppal(), // Destination palette
  3799. ppalSrcDC, // Source DC palette
  3800. ppalDstDC, // Destination DC palette
  3801. (pxloM ? pxloM->iForeDst : 0x0L),
  3802. (pxloM ? pxloM->iBackDst : 0x0L),
  3803. (pxloM ? pxloM->iBackSrc : 0x0L),
  3804. (pdsSrc->po.bIsPalManaged() ? XLATE_USE_SURFACE_PAL : 0)))
  3805. {
  3806. pxlo = xloDevice.pxlo();
  3807. }
  3808. else
  3809. {
  3810. bError = TRUE;
  3811. }
  3812. }
  3813. if (bError == FALSE)
  3814. {
  3815. // If we have a clipobj,
  3816. // We must ensure that pco->rclBounds is never bigger than
  3817. // prclDst on the CopyBits call.
  3818. if ((pco == NULL) ||
  3819. bIntersect(&rclSaveBounds, &rclDst, &pco->rclBounds))
  3820. {
  3821. if (rop4 == 0xcccc)
  3822. {
  3823. // If window blt notification is needed (i.e.,
  3824. // destination meta-surface has BMF_WINDOW_BLT bit
  3825. // set), setthe notification bit in the destination
  3826. // surfobj.
  3827. USHORT fjBitmapSave = psoDst->fjBitmap;
  3828. if (bWndBltNotify)
  3829. psoDst->fjBitmap |= BMF_WINDOW_BLT;
  3830. bRet &= OffCopyBits(PPFNGET(pdoDst,
  3831. CopyBits,
  3832. pdoDst.pSurface()->flags()),
  3833. pOffDst,
  3834. psoDst,
  3835. pOffSrc,
  3836. psoSrc,
  3837. pco,
  3838. pxlo,
  3839. &rclDst,
  3840. &ptlSrc);
  3841. // Restore the surfobj flagss.
  3842. psoDst->fjBitmap = fjBitmapSave;
  3843. }
  3844. else
  3845. {
  3846. MBRUSH.LoadElement(pdsDst, SURFOBJ_TO_SURFACE_NOT_NULL(psoDst));
  3847. bRet &= OffBitBlt(PPFNGET(pdoDst,
  3848. BitBlt,
  3849. pdoDst.pSurface()->flags()),
  3850. pOffDst,
  3851. psoDst,
  3852. pOffSrc,
  3853. psoSrc,
  3854. psoMask,
  3855. pco,
  3856. pxlo,
  3857. &rclDst,
  3858. &ptlSrc,
  3859. pptlMask,
  3860. pbo,
  3861. pptlBrush,
  3862. rop4);
  3863. MBRUSH.StoreElement(pdsDst->iDispSurf);
  3864. }
  3865. }
  3866. }
  3867. else
  3868. {
  3869. bRet = FALSE;
  3870. }
  3871. // Restore XLATEOBJ.
  3872. pxlo = pxloSave;
  3873. }
  3874. // Now undo everything:
  3875. #if _MSC_VER < 1300
  3876. if (dhpdevSave)
  3877. {
  3878. psoSrc->dhsurf = dhsurfSave;
  3879. psoSrc->dhpdev = dhpdevSave;
  3880. }
  3881. else
  3882. #endif
  3883. if (hsurfTmp)
  3884. {
  3885. EngUnlockSurface(psoTmp);
  3886. EngDeleteSurface(hsurfTmp);
  3887. }
  3888. }
  3889. }
  3890. }
  3891. if (pco != NULL)
  3892. {
  3893. pco->rclBounds = rclSaveBounds;
  3894. }
  3895. return(bRet);
  3896. }
  3897. /******************************Public*Routine******************************\
  3898. * BOOL bBitBltFromScreen
  3899. *
  3900. * Handles screen-to-bitmap blts that may possibly span multiple displays.
  3901. *
  3902. \**************************************************************************/
  3903. BOOL bBitBltFromScreen(
  3904. SURFOBJ *psoDst,
  3905. SURFOBJ *psoSrc,
  3906. SURFOBJ *psoMask,
  3907. CLIPOBJ *pco,
  3908. XLATEOBJ *pxlo,
  3909. RECTL *prclDst,
  3910. POINTL *pptlSrc,
  3911. POINTL *pptlMask,
  3912. BRUSHOBJ *pbo,
  3913. POINTL *pptlBrush,
  3914. ROP4 rop4)
  3915. {
  3916. GDIFunctionID(bBitBltFromScreen);
  3917. VDEV* pvdev;
  3918. DHPDEV dhpdevDst;
  3919. RECTL rclDraw;
  3920. MSURF msurf;
  3921. POINTL ptlSrc;
  3922. RECTL rclDst;
  3923. SURFOBJ* psoDstTmp;
  3924. LONG dx;
  3925. LONG dy;
  3926. XLATEOBJ *pxloSave = pxlo;
  3927. BOOL bRet = TRUE;
  3928. pvdev = (VDEV*) psoSrc->dhpdev;
  3929. MULTISURF mDst(psoDst,prclDst);
  3930. dx = prclDst->left - pptlSrc->x;
  3931. dy = prclDst->top - pptlSrc->y;
  3932. // Trim the destination rectangle to what's specified in the CLIPOBJ's
  3933. // 'rclBounds':
  3934. rclDraw = *prclDst;
  3935. if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
  3936. {
  3937. if (!bIntersect(&pco->rclBounds, &rclDraw, &rclDraw))
  3938. return(TRUE);
  3939. }
  3940. // Convert 'rclDraw' from destination coordinates to source coordinates:
  3941. rclDraw.left -= dx;
  3942. rclDraw.right -= dx;
  3943. rclDraw.top -= dy;
  3944. rclDraw.bottom -= dy;
  3945. MULTIBRUSH MBRUSH(pbo, pvdev->cSurfaces, pvdev, pvdev->pso, ROP4_NEEDS_PATTERN(rop4));
  3946. if (!MBRUSH.Valid())
  3947. {
  3948. return FALSE;
  3949. }
  3950. // Source is screen.
  3951. if (msurf.bFindSurface(psoSrc, NULL, &rclDraw))
  3952. {
  3953. do {
  3954. PDEVOBJ poSrc(msurf.pso->hdev);
  3955. // for DIB we blit once from each screen. For device managed bitmaps, we blit
  3956. // once to the master compatible bitmap and once to the device managed bitmap
  3957. // for each screen.
  3958. if (poSrc.flGraphicsCaps() & GCAPS_LAYERED)
  3959. {
  3960. if (mDst.pmdsurf == NULL || mDst.pmdsurf->apso[msurf.pds->iDispSurf] == NULL)
  3961. continue;
  3962. psoDstTmp = mDst.pmdsurf->apso[msurf.pds->iDispSurf];
  3963. }
  3964. else
  3965. psoDstTmp = mDst.pso;
  3966. do {
  3967. BOOL bError = FALSE;
  3968. EXLATEOBJ xloDevice;
  3969. // if the source surface is not compatible to primary surface,
  3970. // create XLATEOBJ for source surface to target. otherwise
  3971. // we can just use given XLATEOBJ.
  3972. if (msurf.pds->iCompatibleColorFormat != 0)
  3973. {
  3974. XLATE *pxloM = (XLATE *) pxlo;
  3975. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso);
  3976. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE_NOT_NULL(psoDstTmp);
  3977. PPALETTE ppalDst = pSurfDst->ppal();
  3978. if (!ppalDst)
  3979. {
  3980. // Destination surface does not have associated palette.
  3981. // (Destination surface is compatible bitmap)
  3982. if (pxloM && pxloM->ppalDst)
  3983. {
  3984. // if XLATEOBJ has destination palette, use it.
  3985. ppalDst = pxloM->ppalDst;
  3986. }
  3987. else
  3988. {
  3989. if ((pxloM == NULL) || pxloM->bIsIdentity())
  3990. {
  3991. PSURFACE pSurfTmp = SURFOBJ_TO_SURFACE_NOT_NULL(psoSrc);
  3992. // if translation is identity, we can use the palette for
  3993. // meta-source surface as destination. since it's trivial.
  3994. // WINBUG #396667 10-03-2001 jasonha A/V due to improper XLATE setup
  3995. if (psoDstTmp == psoDst)
  3996. {
  3997. ppalDst = pSurfTmp->ppal();
  3998. }
  3999. }
  4000. else
  4001. {
  4002. #if HIDEYUKN_DBG
  4003. DbgPrint("GDI DDML: bBitBltFromScreen(): ppalDst is NULL\n");
  4004. DbgBreakPoint();
  4005. #endif
  4006. bError = TRUE;
  4007. }
  4008. }
  4009. }
  4010. if (bError == FALSE)
  4011. {
  4012. // WINBUG #365408 4-10-2001 jasonha Need to investigate old comment in bBitBltFromScreen
  4013. //
  4014. // We need to investigate the following old comment:
  4015. // make sure that when the target surface is paletee managed we should
  4016. // foreground realization to copy bits from non-primary surface.
  4017. if (xloDevice.bInitXlateObj(
  4018. (pxloM ? pxloM->hcmXform : NULL),
  4019. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  4020. pSurfSrc->ppal(), // Source (device surface) palette
  4021. ppalDst, // Destination palette
  4022. ppalDefault, // Source DC palette
  4023. ppalDefault, // Destination DC palette
  4024. (pxloM ? pxloM->iForeDst : 0x0L),
  4025. (pxloM ? pxloM->iBackDst : 0x0L),
  4026. (pxloM ? pxloM->iBackSrc : 0x0L),
  4027. XLATE_USE_SURFACE_PAL))
  4028. {
  4029. pxlo = xloDevice.pxlo();
  4030. }
  4031. else
  4032. {
  4033. bError = TRUE;
  4034. }
  4035. }
  4036. }
  4037. if (bError == FALSE)
  4038. {
  4039. if (msurf.pco->iDComplexity == DC_TRIVIAL)
  4040. {
  4041. // Since bFindSurface/bNextSurface specified no clipping,
  4042. // the entire source surface is readable in one shot:
  4043. ptlSrc = *pptlSrc;
  4044. rclDst = *prclDst;
  4045. }
  4046. else
  4047. {
  4048. // Since the screen is the source, but the clip bounds
  4049. // apply to the destination, we have to convert our surface
  4050. // clipping information to destination coordinates:
  4051. ptlSrc.x = msurf.pco->rclBounds.left;
  4052. ptlSrc.y = msurf.pco->rclBounds.top;
  4053. rclDst.left = msurf.pco->rclBounds.left + dx;
  4054. rclDst.right = msurf.pco->rclBounds.right + dx;
  4055. rclDst.top = msurf.pco->rclBounds.top + dy;
  4056. rclDst.bottom = msurf.pco->rclBounds.bottom + dy;
  4057. }
  4058. if (rop4 == 0xcccc)
  4059. {
  4060. bRet &= OffCopyBits(
  4061. PPFNMGET(msurf, CopyBits),
  4062. &gptlZero,
  4063. psoDstTmp,
  4064. msurf.pOffset,
  4065. msurf.pso,
  4066. pco, // Note that this is the original 'pco'
  4067. pxlo,
  4068. &rclDst,
  4069. &ptlSrc);
  4070. }
  4071. else
  4072. {
  4073. MBRUSH.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  4074. bRet &= OffBitBlt(
  4075. PPFNMGET(msurf, BitBlt),
  4076. &gptlZero,
  4077. psoDstTmp,
  4078. msurf.pOffset,
  4079. msurf.pso,
  4080. psoMask,
  4081. pco, // Note that this is the original 'pco'
  4082. pxlo,
  4083. &rclDst,
  4084. &ptlSrc,
  4085. pptlMask,
  4086. pbo,
  4087. pptlBrush,
  4088. rop4);
  4089. MBRUSH.StoreElement(msurf.pds->iDispSurf);
  4090. }
  4091. }
  4092. else
  4093. {
  4094. bRet = FALSE;
  4095. }
  4096. // Restore XLATEOBJ.
  4097. pxlo = pxloSave;
  4098. #if 1
  4099. ASSERTGDI(!((mDst.pmdsurf != NULL) &&
  4100. (psoDstTmp == mDst.pso) &&
  4101. (mDst.pmdsurf->apso[msurf.pds->iDispSurf] != NULL)),
  4102. "Non-Layered device is part of Meta DEVBITMAP.\n");
  4103. psoDstTmp = NULL;
  4104. #else
  4105. if ((mDst.pmdsurf != NULL) && (psoDstTmp == mDst.pso))
  4106. psoDstTmp = mDst.pmdsurf->apso[msurf.pds->iDispSurf];
  4107. else
  4108. psoDstTmp = NULL;
  4109. #endif
  4110. } while (psoDstTmp != NULL);
  4111. } while (msurf.bNextSurface());
  4112. }
  4113. return(bRet);
  4114. }
  4115. /******************************Public*Routine******************************\
  4116. * BOOL MulBitBlt
  4117. *
  4118. \**************************************************************************/
  4119. BOOL MulBitBlt(
  4120. SURFOBJ *psoDst,
  4121. SURFOBJ *psoSrc,
  4122. SURFOBJ *psoMask,
  4123. CLIPOBJ *pco,
  4124. XLATEOBJ *pxlo,
  4125. RECTL *prclDst,
  4126. POINTL *pptlSrc,
  4127. POINTL *pptlMask,
  4128. BRUSHOBJ *pbo,
  4129. POINTL *pptlBrush,
  4130. ROP4 rop4)
  4131. {
  4132. GDIFunctionID(MulBitBlt);
  4133. BOOL bFromScreen;
  4134. BOOL bToScreen;
  4135. VDEV* pvdev;
  4136. USHORT iDstType;
  4137. BOOL bMultiDst;
  4138. MDSURF* pmdsurfSrc;
  4139. DHPDEV dhpdevSrc;
  4140. RECTL rclDst;
  4141. MSURF msurf;
  4142. BOOL bRet;
  4143. BOOL bError;
  4144. XLATEOBJ *pxloSave = pxlo;
  4145. bFromScreen = ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE));
  4146. bToScreen = (psoDst->iType == STYPE_DEVICE);
  4147. // We copy the prclDst rectangle here because sometimes GDI will
  4148. // simply point prclDst to the same rectangle in pco->rclBounds,
  4149. // and we'll be mucking with pco->rclBounds...
  4150. rclDst = *prclDst;
  4151. if (bToScreen && bFromScreen)
  4152. {
  4153. return(bBitBltScreenToScreen(psoDst, psoMask, pco, pxlo,
  4154. &rclDst, pptlSrc, pptlMask, pbo,
  4155. pptlBrush, rop4));
  4156. }
  4157. else if (bFromScreen)
  4158. {
  4159. return(bBitBltFromScreen(psoDst, psoSrc, psoMask, pco, pxlo,
  4160. &rclDst, pptlSrc, pptlMask, pbo,
  4161. pptlBrush, rop4));
  4162. }
  4163. else // if (bToScreen)
  4164. {
  4165. bRet = TRUE;
  4166. pvdev = (VDEV*) psoDst->dhpdev;
  4167. // WINBUG #380128 05-04-2001 jasonha Initialize MSURF before MULTISURF
  4168. // WINBUG #402896 05-24-2001 jasonha Initialize MULTIBURSH before MULTISURF
  4169. // MULTIBRUSH and MSURF must be intialized before the destination
  4170. // SURFACE might be modified. The destination SURFACE may be changed
  4171. // when the source and destination are the same.
  4172. iDstType = psoDst->iType;
  4173. bMultiDst = (iDstType != STYPE_BITMAP) && msurf.bFindSurface(psoDst, pco, prclDst);
  4174. // MBRUSH is only needed for the bMultiDst case, therefore pass
  4175. // a NULL pbo, to reduce unnecessary setup.
  4176. MULTIBRUSH MBRUSH(((bMultiDst) ? pbo : NULL),
  4177. ((bMultiDst) ? pvdev->cSurfaces : 0),
  4178. ((bMultiDst) ? pvdev: NULL),
  4179. ((bMultiDst) ? pvdev->pso : NULL),
  4180. ((bMultiDst) ? ROP4_NEEDS_PATTERN(rop4) : FALSE));
  4181. MULTISURF mSrc(psoSrc, pptlSrc, rclDst.right - rclDst.left, rclDst.bottom - rclDst.top);
  4182. if (iDstType != STYPE_DEVICE)
  4183. {
  4184. // For STYPE_BITMAP, we only blit to the DIB.
  4185. // For STYPE_DEVBITMAP, we then blit to each device bitmap.
  4186. MULTISURF mDst(psoDst,prclDst);
  4187. bRet = EngBitBlt(mDst.pso, mSrc.pso, psoMask, pco, pxlo, mDst.prcl,
  4188. mSrc.pptl(), pptlMask, pbo, pptlBrush, rop4);
  4189. }
  4190. if (bMultiDst)
  4191. {
  4192. if (!MBRUSH.Valid())
  4193. {
  4194. msurf.vRestore();
  4195. return FALSE;
  4196. }
  4197. do {
  4198. bError = !mSrc.bLoadSource(msurf.pds);
  4199. EXLATEOBJ xloDevice;
  4200. // if the target surface is not compatible to primary surface,
  4201. // create XLATEOBJ for source surface to target. otherwise
  4202. // we can just use given XLATEOBJ.
  4203. if ((bError == FALSE) &&
  4204. (mSrc.pso != NULL) &&
  4205. (msurf.pds->iCompatibleColorFormat != 0))
  4206. {
  4207. XLATE *pxloM = (XLATE *) pxlo;
  4208. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE_NOT_NULL(mSrc.pso);
  4209. PSURFACE pSurfDst = SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso);
  4210. PPALETTE ppalSrc = pSurfSrc->ppal();
  4211. PPALETTE ppalDestDC = ppalDefault;
  4212. PDEVOBJ pdoDst(msurf.pds->hdev);
  4213. if (pdoDst.bIsPalManaged())
  4214. {
  4215. // Use halftone palette for pal-managed device.
  4216. ppalDestDC = REALIZE_HALFTONE_PALETTE(pdoDst.hdev());
  4217. }
  4218. if (!ppalSrc)
  4219. {
  4220. // Source surface does not have associated palette.
  4221. // (Source surface is compatible bitmap)
  4222. if (pxloM && pxloM->ppalSrc)
  4223. {
  4224. // if XLATEOBJ has source palette, use it.
  4225. ppalSrc = pxloM->ppalSrc;
  4226. }
  4227. else
  4228. {
  4229. PSURFACE pSurfTmp = SURFOBJ_TO_SURFACE_NOT_NULL(psoDst);
  4230. if ((pxloM == NULL) || pxloM->bIsIdentity())
  4231. {
  4232. // if translation is identity, we can use the palette for
  4233. // meta-destination surface as source. since it's trivial.
  4234. // WINBUG #396667 10-03-2001 jasonha A/V due to improper XLATE setup
  4235. if (mSrc.pso == psoSrc)
  4236. {
  4237. ppalSrc = pSurfTmp->ppal();
  4238. }
  4239. }
  4240. else if (pxloM->ppalDstDC)
  4241. {
  4242. // We are bitblting from compatible bitmap to a surface in
  4243. // meta-surface. but we are not in foreground.
  4244. ppalDestDC = pxloM->ppalDstDC;
  4245. // WINBUG #274637 02-12-2001 jasonha A/V due to improper XLATE setup
  4246. if (pSurfSrc->iFormat() == pSurfTmp->iFormat())
  4247. {
  4248. // We are bitblting from a compatible bitmap that is
  4249. // not palettized but is a the same format as the
  4250. // meta-surface, so we use the destination palette.
  4251. ppalSrc = pSurfTmp->ppal();
  4252. }
  4253. }
  4254. else
  4255. {
  4256. #if HIDEYUKN_DBG
  4257. DbgPrint("GDI DDML: MulBitBlt(): ppalDst is NULL\n");
  4258. DbgBreakPoint();
  4259. #endif
  4260. bError = TRUE;
  4261. }
  4262. }
  4263. }
  4264. if (bError == FALSE)
  4265. {
  4266. XEPALOBJ palSurfSrc(ppalSrc);
  4267. ULONG flFlags = 0;
  4268. if (palSurfSrc.bValid() && palSurfSrc.bIsPalManaged())
  4269. {
  4270. // Source is palette managed surface.
  4271. if (ppalDestDC == ppalDefault)
  4272. {
  4273. // We don't know DC palette here, but we know we are in foregroud,
  4274. // (since translation is trivial)
  4275. // so, we just map from source surface palette to destination
  4276. // surface palette directly (destination is at least higher color
  4277. // depth than source).
  4278. flFlags = XLATE_USE_SURFACE_PAL;
  4279. }
  4280. else
  4281. {
  4282. // We may not be in foreground. but map from foreground translation
  4283. // in source, so that we will not loose original color on secondary
  4284. // devices which can produce higher color depth then source.
  4285. flFlags = XLATE_USE_FOREGROUND;
  4286. }
  4287. }
  4288. if (xloDevice.bInitXlateObj(
  4289. (pxloM ? pxloM->hcmXform : NULL),
  4290. (pxloM ? pxloM->lIcmMode : DC_ICM_OFF),
  4291. palSurfSrc, // Source palette
  4292. pSurfDst->ppal(), // Destination palette
  4293. ppalDefault, // Source DC palette
  4294. ppalDestDC, // Destination DC palette
  4295. (pxloM ? pxloM->iForeDst : 0x0L),
  4296. (pxloM ? pxloM->iBackDst : 0x0L),
  4297. (pxloM ? pxloM->iBackSrc : 0x0L),
  4298. flFlags))
  4299. {
  4300. pxlo = xloDevice.pxlo();
  4301. }
  4302. else
  4303. {
  4304. bError = TRUE;
  4305. }
  4306. }
  4307. }
  4308. if (bError == FALSE)
  4309. {
  4310. if (0) // (bHalftone)
  4311. {
  4312. MBRUSH.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  4313. bRet &= OffStretchBltROP(EngStretchBltROP,
  4314. msurf.pOffset,
  4315. msurf.pso,
  4316. &gptlZero,
  4317. mSrc.pso,
  4318. psoMask,
  4319. msurf.pco,
  4320. pxlo,
  4321. NULL,
  4322. &gptlZero,
  4323. &rclDst,
  4324. mSrc.prcl,
  4325. pptlMask,
  4326. HALFTONE,
  4327. pbo,
  4328. rop4);
  4329. MBRUSH.StoreElement(msurf.pds->iDispSurf);
  4330. }
  4331. else if (rop4 == 0xcccc)
  4332. {
  4333. bRet &= OffCopyBits(PPFNMGET(msurf, CopyBits),
  4334. msurf.pOffset,
  4335. msurf.pso,
  4336. &gptlZero,
  4337. mSrc.pso,
  4338. msurf.pco,
  4339. pxlo,
  4340. &rclDst,
  4341. mSrc.pptl());
  4342. }
  4343. else
  4344. {
  4345. MBRUSH.LoadElement(msurf.pds, SURFOBJ_TO_SURFACE_NOT_NULL(msurf.pso));
  4346. bRet &= OffBitBlt(PPFNMGET(msurf, BitBlt),
  4347. msurf.pOffset,
  4348. msurf.pso,
  4349. &gptlZero,
  4350. mSrc.pso,
  4351. psoMask,
  4352. msurf.pco,
  4353. pxlo,
  4354. &rclDst,
  4355. mSrc.pptl(),
  4356. pptlMask,
  4357. pbo,
  4358. pptlBrush,
  4359. rop4);
  4360. MBRUSH.StoreElement(msurf.pds->iDispSurf);
  4361. }
  4362. }
  4363. else
  4364. {
  4365. bRet = FALSE;
  4366. }
  4367. // Restore XLATEOBJ.
  4368. pxlo = pxloSave;
  4369. } while (msurf.bNextSurface());
  4370. }
  4371. }
  4372. return(bRet);
  4373. }
  4374. /******************************Public*Routine******************************\
  4375. * BOOL MulCopyBits
  4376. *
  4377. \**************************************************************************/
  4378. BOOL MulCopyBits(
  4379. SURFOBJ *psoDst,
  4380. SURFOBJ *psoSrc,
  4381. CLIPOBJ *pco,
  4382. XLATEOBJ *pxlo,
  4383. RECTL *prclDst,
  4384. POINTL *pptlSrc)
  4385. {
  4386. return(MulBitBlt(psoDst, psoSrc, NULL, pco, pxlo, prclDst,
  4387. pptlSrc, NULL, NULL, NULL, 0xcccc));
  4388. }
  4389. /******************************Public*Routine******************************\
  4390. * BOOL MulUpdateColors
  4391. *
  4392. * History:
  4393. * 18-Aug-1998 -by- Hideyuki Nagase [hideyukn]
  4394. * Wrote it.
  4395. *
  4396. \**************************************************************************/
  4397. BOOL MulUpdateColors(
  4398. SURFOBJ *pso,
  4399. CLIPOBJ *pco,
  4400. XLATEOBJ *pxlo)
  4401. {
  4402. VDEV* pvdev;
  4403. DISPSURF* pdsDst;
  4404. SURFOBJ* psoDst;
  4405. POINTL* pOffDst;
  4406. RECTL rclDst;
  4407. POINTL ptlSrc;
  4408. RECTL rclBounds;
  4409. BOOL bRet;
  4410. bRet = TRUE;
  4411. pvdev = (VDEV*) pso->dhpdev;
  4412. ASSERTGDI(pco,"MulUpdateColors(): pco is null\n");
  4413. //
  4414. // Save bounds rectangle to updates.
  4415. //
  4416. rclBounds = pco->rclBounds;
  4417. //
  4418. // Walk through all devices.
  4419. //
  4420. for (pdsDst = pvdev->pds; pdsDst != NULL; pdsDst = pdsDst->pdsNext)
  4421. {
  4422. PDEVOBJ pdo(pdsDst->hdev);
  4423. //
  4424. // Check the device is palette managed or not.
  4425. //
  4426. // + If this is not palette managed device, we don't need to
  4427. // do anything.
  4428. //
  4429. // + Palette is shared with all palette devices, so we can
  4430. // use exactly same XLATEOBJ for all palette devices.
  4431. //
  4432. if (pdo.bIsPalManaged())
  4433. {
  4434. //
  4435. // Clip the rectangle to monitor.
  4436. //
  4437. if (bIntersect(&rclBounds, &pdsDst->rcl, &rclDst))
  4438. {
  4439. //
  4440. // We must ensure that pco->rclBounds is never bigger than
  4441. // prclDst on the CopyBits call.
  4442. //
  4443. pco->rclBounds = rclDst;
  4444. //
  4445. // Source points is same as destination upper-left.
  4446. //
  4447. ptlSrc.x = rclDst.left;
  4448. ptlSrc.y = rclDst.top;
  4449. psoDst = pdsDst->pso;
  4450. pOffDst = &pdsDst->Off;
  4451. //
  4452. // Update each pixel with correct color (by XLATEOBJ).
  4453. //
  4454. bRet &= OffCopyBits(PPFNGET(pdo,
  4455. CopyBits,
  4456. pdo.pSurface()->flags()),
  4457. pOffDst, psoDst,
  4458. pOffDst, psoDst,
  4459. pco, pxlo,
  4460. &rclDst, &ptlSrc);
  4461. }
  4462. }
  4463. }
  4464. //
  4465. // Restore original.
  4466. //
  4467. pco->rclBounds = rclBounds;
  4468. return(bRet);
  4469. }
  4470. /******************************Public*Routine******************************\
  4471. * BOOL MulCopyDeviceToDIB
  4472. *
  4473. * Copies the specified rectangle of a multimon device surface to a DIB
  4474. * updating the rectangle to be relativeto the DIB's origin (0,0)
  4475. *
  4476. * The surface is not actually created if the rectangle is
  4477. * out of bounds, so the caller has to check if the value
  4478. * of pDibSurface.ps was modified at all.
  4479. *
  4480. * History:
  4481. * 16-Dec-1998 -by- Andre Matos [amatos]
  4482. * Wrote it.
  4483. *
  4484. \**************************************************************************/
  4485. BOOL MulCopyDeviceToDIB(
  4486. SURFOBJ *pso,
  4487. SURFMEM *pDibSurf,
  4488. RECTL *prclSrc)
  4489. {
  4490. DEVBITMAPINFO dbmi;
  4491. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(pso);
  4492. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  4493. RECTL rclSrcClip = *prclSrc;
  4494. if(rclSrcClip.left < pdoSrc.pptlOrigin()->x)
  4495. {
  4496. rclSrcClip.left = pdoSrc.pptlOrigin()->x;
  4497. }
  4498. if(rclSrcClip.right >
  4499. (pdoSrc.pptlOrigin()->x + pSurfSrc->sizl().cx))
  4500. {
  4501. rclSrcClip.right =
  4502. pdoSrc.pptlOrigin()->x + pSurfSrc->sizl().cx;
  4503. }
  4504. if(rclSrcClip.top < pdoSrc.pptlOrigin()->y)
  4505. {
  4506. rclSrcClip.top = pdoSrc.pptlOrigin()->y;
  4507. }
  4508. if(rclSrcClip.bottom >
  4509. (pdoSrc.pptlOrigin()->y + pSurfSrc->sizl().cy))
  4510. {
  4511. rclSrcClip.bottom =
  4512. pdoSrc.pptlOrigin()->y + pSurfSrc->sizl().cy;
  4513. }
  4514. // If the source rectangle was outside of the source
  4515. // surface, we can return.
  4516. if((rclSrcClip.top >= rclSrcClip.bottom) ||
  4517. (rclSrcClip.left >= rclSrcClip.right ))
  4518. {
  4519. return TRUE;
  4520. }
  4521. RECTL rclDst = {0, 0, rclSrcClip.right - rclSrcClip.left,
  4522. rclSrcClip.bottom - rclSrcClip.top};
  4523. POINTL srcOrigin = { rclSrcClip.left, rclSrcClip.top };
  4524. PPALETTE ppalSrc = pSurfSrc->ppal();
  4525. dbmi.cxBitmap = rclDst.right;
  4526. dbmi.cyBitmap = rclDst.bottom;
  4527. dbmi.hpal = ppalSrc ? ((HPALETTE) ppalSrc->hGet()) : 0;
  4528. dbmi.iFormat = pSurfSrc->iFormat();
  4529. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  4530. pDibSurf->bCreateDIB(&dbmi, (VOID *) NULL);
  4531. if (!pDibSurf->bValid())
  4532. return(FALSE);
  4533. if (!MulBitBlt(pDibSurf->pSurfobj(), pso, NULL, (CLIPOBJ *) NULL,
  4534. &xloIdent, &rclDst, &srcOrigin, NULL, NULL, NULL, 0xcccc))
  4535. return FALSE;
  4536. prclSrc->left -= rclSrcClip.left;
  4537. prclSrc->right -= rclSrcClip.left;
  4538. prclSrc->top -= rclSrcClip.top;
  4539. prclSrc->bottom -= rclSrcClip.top;
  4540. return TRUE;
  4541. }
  4542. /******************************Public*Structure****************************\
  4543. * DRVFN gadrvfnMulti[]
  4544. *
  4545. * Build the driver function table gadrvfnMulti with function index/address
  4546. * pairs. This table tells GDI which DDI calls we support, and their
  4547. * location (GDI does an indirect call through this table to call us).
  4548. *
  4549. \**************************************************************************/
  4550. DRVFN gadrvfnMulti[] = {
  4551. // Effectively required by all drivers:
  4552. { INDEX_DrvEnablePDEV , (PFN) MulEnablePDEV },
  4553. { INDEX_DrvCompletePDEV , (PFN) MulCompletePDEV },
  4554. { INDEX_DrvDisablePDEV , (PFN) MulDisablePDEV },
  4555. { INDEX_DrvEnableSurface , (PFN) MulEnableSurface },
  4556. { INDEX_DrvDisableSurface , (PFN) MulDisableSurface },
  4557. { INDEX_DrvSetPalette , (PFN) MulSetPalette },
  4558. { INDEX_DrvRealizeBrush , (PFN) MulRealizeBrush },
  4559. //
  4560. // The DDML is special in that it does not manage any physical device.
  4561. // GDI and USER should handle all calls involing modes, and those calls
  4562. // should never get to the DDML.
  4563. //
  4564. // { INDEX_DrvAssertMode , (PFN) MulAssertMode },
  4565. // { INDEX_DrvGetModes , (PFN) MulGetModes },
  4566. // Required for device-managed surfaces:
  4567. { INDEX_DrvTextOut , (PFN) MulTextOut },
  4568. { INDEX_DrvStrokePath , (PFN) MulStrokePath },
  4569. { INDEX_DrvCopyBits , (PFN) MulCopyBits },
  4570. // Optional, must be supported by "Eng" backup calls:
  4571. { INDEX_DrvBitBlt , (PFN) MulBitBlt },
  4572. { INDEX_DrvLineTo , (PFN) MulLineTo },
  4573. { INDEX_DrvFillPath , (PFN) MulFillPath },
  4574. { INDEX_DrvStrokeAndFillPath , (PFN) MulStrokeAndFillPath },
  4575. { INDEX_DrvStretchBlt , (PFN) MulStretchBlt },
  4576. { INDEX_DrvAlphaBlend , (PFN) MulAlphaBlend },
  4577. { INDEX_DrvTransparentBlt , (PFN) MulTransparentBlt },
  4578. { INDEX_DrvGradientFill , (PFN) MulGradientFill },
  4579. { INDEX_DrvDrawStream , (PFN) MulDrawStream },
  4580. // For handling device bitmaps with layered drivers:
  4581. { INDEX_DrvCreateDeviceBitmap , (PFN) MulCreateDeviceBitmap },
  4582. { INDEX_DrvDeleteDeviceBitmap , (PFN) MulDeleteDeviceBitmap },
  4583. // These calls only go to drivers that specifically need to get them.
  4584. // DrvDestroyFont is only called for the specific drivers that hooked
  4585. // it. I checked it out, and the engine calls DrvDestroyFont regardless
  4586. // of whether or not pvConsumer is NULL. Therefore, I do the same for
  4587. // each of the drivers.
  4588. { INDEX_DrvDestroyFont , (PFN) MulDestroyFont },
  4589. { INDEX_DrvEscape , (PFN) MulEscape },
  4590. { INDEX_DrvSaveScreenBits , (PFN) MulSaveScreenBits },
  4591. #ifdef OPENGL_MM
  4592. // ICD calls directly dispatch to real driver in API level, so it bypass DDML.
  4593. #else
  4594. { INDEX_DrvSetPixelFormat , (PFN) MulSetPixelFormat },
  4595. { INDEX_DrvDescribePixelFormat , (PFN) MulDescribePixelFormat },
  4596. { INDEX_DrvSwapBuffers , (PFN) MulSwapBuffers },
  4597. #endif // OPENGL_MM
  4598. // Image Color Management - DeviceGammaRamp control:
  4599. { INDEX_DrvIcmSetDeviceGammaRamp , (PFN) MulIcmSetDeviceGammaRamp},
  4600. };
  4601. ULONG gcdrvfnMulti = sizeof(gadrvfnMulti) / sizeof(DRVFN);
  4602. #ifdef OPENGL_MM
  4603. /******************************Public*Routine******************************\
  4604. * HDEV hdevFindDeviceHDEV
  4605. *
  4606. * OpenGL calls should only go to one driver and not the meta device.
  4607. * Try to find the appropriate hdev and return it.
  4608. *
  4609. * History:
  4610. * 28-Jan-1998 -by- Robert Tray [v-rotray]
  4611. * First pass.
  4612. *
  4613. \**************************************************************************/
  4614. HDEV hdevFindDeviceHdev(
  4615. HDEV hdevMeta,
  4616. RECTL rect,
  4617. PEWNDOBJ pwo) // OPTIONAL
  4618. {
  4619. //
  4620. // *PixelFormat, SwapBuffers, & OGL Escape calls should
  4621. // only go to one device. Which one?
  4622. // If there is a valid WNDOBJ then it will tell us
  4623. // which surface is the right one.
  4624. // If the extents of the window are completely contained
  4625. // on one monitor then return the hdev of that device.
  4626. // If the window straddles monitors then .... how about
  4627. // we return 0 and hopefully in that case the app will
  4628. // fall back to software rendering. By the time the app
  4629. // is serious about rendering he has a WNDOBJ. So hopefully
  4630. // we will only hit these ambiguous situations while the
  4631. // app is doing a DescribePixelFormat.
  4632. //
  4633. PDEVOBJ pdo(hdevMeta);
  4634. ASSERTGDI(pdo.bMetaDriver(),"hdevFindDeviceHDEV(): hdevMeta is not meta-PDEV\n");
  4635. PVDEV pvdev = (VDEV*) pdo.dhpdev();
  4636. PDISPSURF pds;
  4637. HDEV hdevMatch = NULL;
  4638. //
  4639. // If WNDOBJ is given and the HDEV for the WNDOBJ
  4640. // is one of child of this meta-PDEV. use it.
  4641. //
  4642. if (pwo && pwo->bValid())
  4643. {
  4644. hdevMatch = pwo->pto->pSurface->hdev();
  4645. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  4646. {
  4647. if (hdevMatch == pds->hdev)
  4648. {
  4649. // found the match
  4650. return (hdevMatch);
  4651. }
  4652. }
  4653. }
  4654. ULONG intersectMon = 0;
  4655. for (pds = pvdev->pds; pds != NULL; pds = pds->pdsNext)
  4656. {
  4657. if (bContains(&pds->rcl,&rect))
  4658. {
  4659. // The window is contained on this device
  4660. return (pds->hdev);
  4661. }
  4662. if (bIntersect(&pds->rcl,&rect))
  4663. {
  4664. // The window is intersected with this device.
  4665. PDEVOBJ pdoDevice(pds->hdev);
  4666. // If this device has GCAPS2_ICD_MULTIMON flag, they
  4667. // wants us to call them with any OpenGL window intersect
  4668. // with thier device.
  4669. if (pdoDevice.flGraphicsCaps2() & GCAPS2_ICD_MULTIMON)
  4670. {
  4671. return (pds->hdev);
  4672. }
  4673. intersectMon++;
  4674. hdevMatch = pds->hdev;
  4675. }
  4676. }
  4677. //
  4678. // If the window is not contained on one monitor but
  4679. // it only intersects one then that might mean that it's
  4680. // hanging off the outside edge of a monitor.
  4681. //
  4682. if (intersectMon == 1)
  4683. {
  4684. return hdevMatch;
  4685. }
  4686. //
  4687. // I suppose you could possibly return the hdev for the
  4688. // primary monitor in some of these ambiguous cases but
  4689. // until I think of them I'll just return NULL
  4690. //
  4691. return NULL;
  4692. }
  4693. #endif // OPENGL_MM