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.

1688 lines
52 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: curseng.cxx
  3. *
  4. * Engine cursor support. These routines are only called by USER to
  5. * set the cursor shape and move it about the screen. This is not the
  6. * engine simulation of the pointer.
  7. *
  8. * Created: 18-Mar-1991 11:39:40
  9. * Author: Tue 12-May-1992 01:49:04 -by- Charles Whitmer [chuckwh]
  10. *
  11. * Copyright (c) 1991-1999 Microsoft Corporation
  12. \**************************************************************************/
  13. #include "precomp.hxx"
  14. // We always create the alpha bitmap from the master shape with two
  15. // rows of pixels on every side to give room for two pixels of blur and
  16. // for an edge of work space.
  17. #define ALPHA_EDGE 3
  18. // Some constants defining the shadow cursor:
  19. #define SHADOW_X_OFFSET 3
  20. #define SHADOW_Y_OFFSET 1
  21. #define SHADOW_ALPHA 0x40000000
  22. /******************************Public*Routine******************************\
  23. * vDetermineSurfaceBounds
  24. *
  25. * Calculate a tight bounds for the surface, given a byte-value that is
  26. * evaluated as the 'space' on the edges.
  27. *
  28. * History:
  29. * 20-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  30. * Wrote it.
  31. \**************************************************************************/
  32. LONG galBitsPerPixel[] = { 0, 1, 4, 8, 16, 24, 32 };
  33. VOID vDetermineSurfaceBounds(
  34. SURFOBJ* pso,
  35. BYTE jBlank,
  36. LONG yTop, // Start scan
  37. LONG yBottom, // End scan
  38. RECTL* prclBounds) // Output
  39. {
  40. LONG lDelta;
  41. BYTE* pjScan0;
  42. BYTE* pj;
  43. ULONG cj;
  44. ULONG cy;
  45. ULONG i;
  46. BYTE* pjTop;
  47. BYTE* pjBottom;
  48. BYTE* pjLeft;
  49. BYTE* pjRight;
  50. BYTE jStamp;
  51. LONG iLeft;
  52. LONG iRight;
  53. LONG xRight;
  54. LONG cBitsPerPixel;
  55. ASSERTGDI(pso->iType == STYPE_BITMAP,
  56. "Can directly access only STYPE_BITMAP surfaces");
  57. lDelta = pso->lDelta;
  58. cBitsPerPixel = galBitsPerPixel[pso->iBitmapFormat];
  59. xRight = pso->sizlBitmap.cx;
  60. cj = (xRight * cBitsPerPixel + 7) >> 3;
  61. pjScan0 = (BYTE*) pso->pvScan0;
  62. iLeft = 0;
  63. iRight = cj;
  64. // Blank the right bits up to the byte multiple:
  65. if ((pso->iBitmapFormat == BMF_1BPP) && (xRight & 7))
  66. {
  67. jStamp = (0x100 >> (xRight & 7)) - 1; // 1 -> 0x7f, 2 -> 0x3f ...7 -> 0x01
  68. pjRight = pjScan0 + lDelta * yTop + cj - 1;
  69. if (jBlank)
  70. {
  71. for (pj = pjRight, i = (yBottom - yTop); i != 0; pj += lDelta, i--)
  72. {
  73. *pj |= jStamp;
  74. }
  75. }
  76. else
  77. {
  78. jStamp = ~jStamp;
  79. for (pj = pjRight, i = (yBottom - yTop); i != 0; pj += lDelta, i--)
  80. {
  81. *pj &= jStamp;
  82. }
  83. }
  84. }
  85. // Trim the top:
  86. pjTop = pjScan0 + lDelta * yTop;
  87. while (TRUE)
  88. {
  89. for (pj = pjTop, i = cj; i != 0; pj++, i--)
  90. {
  91. if (*pj != jBlank)
  92. goto Done_Top_Trim;
  93. }
  94. pjTop += lDelta;
  95. yTop++;
  96. // Catch the case where the surface is completely empty:
  97. if (yTop >= yBottom)
  98. {
  99. prclBounds->left = LONG_MAX;
  100. prclBounds->top = LONG_MAX;
  101. prclBounds->right = LONG_MIN;
  102. prclBounds->bottom = LONG_MIN;
  103. return;
  104. }
  105. }
  106. Done_Top_Trim:
  107. // Trim the bottom:
  108. pjBottom = pjScan0 + lDelta * (yBottom - 1);
  109. while (TRUE)
  110. {
  111. for (pj = pjBottom, i = cj; i != 0; pj++, i--)
  112. {
  113. if (*pj != jBlank)
  114. goto Done_Bottom_Trim;
  115. }
  116. pjBottom -= lDelta;
  117. yBottom--;
  118. ASSERTGDI(yTop < yBottom, "Empty cursor should have been caught above");
  119. }
  120. Done_Bottom_Trim:
  121. // Trim the left side:
  122. cy = yBottom - yTop;
  123. pjLeft = pjTop;
  124. while (TRUE)
  125. {
  126. for (pj = pjLeft, i = cy; i != 0; pj += lDelta, i--)
  127. {
  128. if (*pj != jBlank)
  129. goto Done_Left_Trim;
  130. }
  131. pjLeft++;
  132. iLeft++;
  133. ASSERTGDI(iLeft < iRight, "Empty cursor should have been caught above");
  134. }
  135. Done_Left_Trim:
  136. // Trim the right side:
  137. pjRight = pjTop + cj - 1;
  138. while (TRUE)
  139. {
  140. for (pj = pjRight, i = cy; i != 0; pj += lDelta, i--)
  141. {
  142. if (*pj != jBlank)
  143. goto Done_Right_Trim;
  144. }
  145. pjRight--;
  146. iRight--;
  147. ASSERTGDI(iLeft < iRight, "Empty cursor should have been caught above");
  148. }
  149. Done_Right_Trim:
  150. prclBounds->top = yTop;
  151. prclBounds->bottom = yBottom;
  152. prclBounds->left = (8 * iLeft) / cBitsPerPixel; // Floor
  153. prclBounds->right = (8 * iRight + cBitsPerPixel - 1) / cBitsPerPixel; // Ceiling
  154. // Account for the fact that we are checking on bytes worth at a time, and
  155. // so might actually end up somewhat past the right edge of the bitmap:
  156. prclBounds->right = min(prclBounds->right, pso->sizlBitmap.cx);
  157. }
  158. /******************************Public*Routine******************************\
  159. * vCalculateCursorBounds
  160. *
  161. * Calculate a tight bounds for the specified cursor shape.
  162. *
  163. * History:
  164. * 20-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  165. * Wrote it.
  166. \**************************************************************************/
  167. VOID vCalculateCursorBounds(
  168. SURFOBJ* psoMask,
  169. SURFOBJ* psoColor,
  170. RECTL* prclBounds)
  171. {
  172. LONG cyMask;
  173. ERECTL erclBounds;
  174. ERECTL erclMask;
  175. cyMask = psoMask->sizlBitmap.cy >> 1;
  176. vDetermineSurfaceBounds(psoMask, 0xff, 0, cyMask, &erclMask);
  177. if (psoColor == NULL)
  178. {
  179. vDetermineSurfaceBounds(psoMask, 0x00, cyMask, 2 * cyMask, &erclBounds);
  180. if (!erclBounds.bWrapped())
  181. {
  182. erclBounds.top -= cyMask;
  183. erclBounds.bottom -= cyMask;
  184. }
  185. }
  186. else
  187. {
  188. vDetermineSurfaceBounds(psoColor, 0x00, 0, cyMask, &erclBounds);
  189. }
  190. // The bounds are the union of the AND mask bounds and the OR mask bounds:
  191. erclBounds |= erclMask;
  192. if (erclBounds.bWrapped())
  193. {
  194. erclBounds.left = 0;
  195. erclBounds.top = 0;
  196. erclBounds.right = 1;
  197. erclBounds.bottom = 1;
  198. }
  199. // KdPrint((">> Cursor bounds: (%li, %li, %li, %li)\n",
  200. // erclBounds.left, erclBounds.top, erclBounds.right, erclBounds.bottom));
  201. //
  202. // Stash the bounds away for next time:
  203. *prclBounds = erclBounds;
  204. }
  205. /******************************Public*Routine******************************\
  206. * bBlurCursorShadow
  207. *
  208. * Do an in-place blur of the cursor shadow (i.e., the blurred image will
  209. * replace the image passed in).
  210. *
  211. * This is done by applying an approximation of a 3x3 boxcar convolution.
  212. *
  213. * The cursor shadow is assumed to be in the MSB of the surface. The surface
  214. * is assumed to be a 32bpp BGRA surface.
  215. *
  216. * History:
  217. * 03-Mar-1998 -by- Gilman Wong [gilmanw]
  218. * Wrote it.
  219. \**************************************************************************/
  220. BOOL bBlurCursorShadow(
  221. SURFOBJ* pso)
  222. {
  223. USHORT aus0[64];
  224. USHORT aus1[64];
  225. USHORT aus2[64];
  226. PUSHORT apus[3];
  227. // Function assumes caller will pass a 32bpp surface.
  228. ASSERTGDI(pso->iBitmapFormat == BMF_32BPP,
  229. "bBlurCursorShadow: bad iBitmapFormat\n");
  230. // Must at least be 3x3. Don't bother if it's too small.
  231. if ((pso->sizlBitmap.cx < 3) || (pso->sizlBitmap.cy < 3))
  232. {
  233. WARNING("bBlurCursorShadow: bitmap too small\n");
  234. return(FALSE);
  235. }
  236. // Setup temporary scanline memory. If it will fit, use the stack
  237. // buffer. Otherwise allocate pool memory.
  238. if (pso->sizlBitmap.cx > 64)
  239. {
  240. apus[0] = (PUSHORT) PALLOCMEM(pso->sizlBitmap.cx * sizeof(USHORT) * 3, 'pmtG');
  241. if (apus[0])
  242. {
  243. apus[1] = apus[0] + pso->sizlBitmap.cx;
  244. apus[2] = apus[1] + pso->sizlBitmap.cx;
  245. }
  246. }
  247. else
  248. {
  249. apus[0] = aus0;
  250. apus[1] = aus1;
  251. apus[2] = aus2;
  252. }
  253. if (apus[0] == NULL)
  254. {
  255. WARNING("bBlurCursorShadow: mem alloc failure\n");
  256. return(FALSE);
  257. }
  258. // Fill up the scanline memory with 3x1 boxcar sums for the
  259. // first three scanlines.
  260. PULONG pulIn = (PULONG) pso->pvScan0;
  261. PULONG pulTmp;
  262. USHORT usLast;
  263. USHORT *pus, *pusEnd;
  264. ULONG j;
  265. for (j = 0; j < 3; j++)
  266. {
  267. // Compute the scanline sum. Note that output is two pixels
  268. // smaller than the input.
  269. pus = apus[j];
  270. pusEnd = pus + (pso->sizlBitmap.cx - 2);
  271. pulTmp = pulIn;
  272. while (pus < pusEnd)
  273. {
  274. *pus = (USHORT) ((pulTmp[0] >> 24) + (pulTmp[1] >> 24) + (pulTmp[2] >> 24));
  275. pus += 1;
  276. pulTmp += 1;
  277. }
  278. // Next scanline.
  279. pulIn = (PULONG) (((PBYTE) pulIn) + pso->lDelta);
  280. }
  281. // Compute the average (3x3 boxcar convolution) for each output
  282. // scanline.
  283. PULONG pulOut = ((PULONG) (((PBYTE) pso->pvScan0) + pso->lDelta)) + 1;
  284. ULONG ulNumScans = pso->sizlBitmap.cy - 2;
  285. ULONG ulNext = 0;
  286. while (ulNumScans--)
  287. {
  288. // Setup output pointers.
  289. PULONG pulAvg = pulOut;
  290. PULONG pulAvgEnd = pulAvg + (pso->sizlBitmap.cx - 2);
  291. // Setup pointers to run the scanline 3x1 sums.
  292. PUSHORT pusTmp[3];
  293. pusTmp[0] = apus[0];
  294. pusTmp[1] = apus[1];
  295. pusTmp[2] = apus[2];
  296. // Compute the average scanline.
  297. while (pulAvg < pulAvgEnd)
  298. {
  299. USHORT usSum;
  300. // Strictly speaking we should divide the sum by 9, but since
  301. // this is just for looks, we can approximate as a divide by 8
  302. // minus a divide by 64 (will produce in a slightly too small
  303. // result).
  304. //
  305. // 1/9 = 0.111111111... in decimal
  306. // = 0.000111000111... in binary
  307. //
  308. // Approximations:
  309. //
  310. // 1/8 - 1/64 = 0.109375
  311. // 1/8 - 1/64 + 1/512 = 0.111328125
  312. // 1/8 - 1/64 + 1/512 - 1/4096 = 0.111083984
  313. usSum = *pusTmp[0] + *pusTmp[1] + *pusTmp[2];
  314. //*pulAvg = (usSum / 9) << 24;
  315. //*pulAvg = ((usSum >> 3) - (usSum >> 6)) << 24;
  316. *pulAvg = (usSum >> 3) << 24;
  317. pulAvg += 1;
  318. pusTmp[0] += 1;
  319. pusTmp[1] += 1;
  320. pusTmp[2] += 1;
  321. }
  322. // Next output scanline.
  323. pulOut = (PULONG) (((PBYTE) pulOut) + pso->lDelta);
  324. // Need to compute 3x1 boxcar sum for the next scanline.
  325. if (ulNumScans)
  326. {
  327. // Compute the scanline sum. Note that output is two pixels
  328. // smaller than the input.
  329. pus = apus[ulNext];
  330. pusEnd = pus + (pso->sizlBitmap.cx - 2);
  331. pulTmp = pulIn;
  332. while (pus < pusEnd)
  333. {
  334. *pus = (USHORT) ((pulTmp[0] >> 24) + (pulTmp[1] >> 24) + (pulTmp[2] >> 24));
  335. pus += 1;
  336. pulTmp += 1;
  337. }
  338. // Next scanline.
  339. pulIn = (PULONG) (((PBYTE) pulIn) + pso->lDelta);
  340. // Next scanline summation buffer.
  341. ulNext++;
  342. if (ulNext >= 3)
  343. ulNext = 0;
  344. }
  345. }
  346. // Cleanup temporary memory.
  347. if (apus[0] != aus0)
  348. {
  349. VFREEMEM(apus[0]);
  350. }
  351. return(TRUE);
  352. }
  353. /******************************Public*Routine******************************\
  354. * bApplicationAlphaCursor
  355. *
  356. * This routine will create a pre-muliplied alpha version of the specified
  357. * cursor if the cursor has non-pre-mulitplied alpha values in it.
  358. *
  359. * History:
  360. * 20-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  361. * Wrote it.
  362. \**************************************************************************/
  363. BOOL bApplicationAlphaCursor(
  364. SURFOBJ* psoAlpha,
  365. SURFOBJ* psoColor,
  366. RECTL* prclBounds)
  367. {
  368. ULONG ulAlpha;
  369. ULONG ul;
  370. ULONG* pulScan0;
  371. ULONG* pul;
  372. ULONG cPixels;
  373. BOOL bPerPixelAlpha;
  374. ULONG i;
  375. RECTL rclDst;
  376. ASSERTGDI(psoColor->iBitmapFormat == BMF_32BPP,
  377. "Expected only BGRA 32-bpp bitmaps");
  378. // Copy the cursor to our alpha surface, accounting for the same
  379. // offset that is needed for shadowed cursors:
  380. rclDst.left = ALPHA_EDGE;
  381. rclDst.top = ALPHA_EDGE;
  382. rclDst.right = ALPHA_EDGE + prclBounds->right;
  383. rclDst.bottom = ALPHA_EDGE + prclBounds->bottom;
  384. EngCopyBits(psoAlpha, psoColor, NULL, NULL, &rclDst, &gptlZero);
  385. // Check for any pixels with non-zero alpha:
  386. cPixels = psoAlpha->sizlBitmap.cx * psoAlpha->sizlBitmap.cy;
  387. pulScan0 = (ULONG*) psoAlpha->pvBits;
  388. bPerPixelAlpha = FALSE;
  389. for (pul = pulScan0, i = cPixels; i != 0; pul++, i--)
  390. {
  391. if ((*pul & 0xff000000) != 0)
  392. {
  393. bPerPixelAlpha = TRUE;
  394. break;
  395. }
  396. }
  397. if (bPerPixelAlpha)
  398. {
  399. // Okay, we can now assume that the application gave us a per-pixel
  400. // alpha cursor shape. Now go through and convert it to pre-multiplied
  401. // alpha.
  402. for (pul = pulScan0, i = cPixels; i != 0; pul++, i--)
  403. {
  404. ul = *pul;
  405. ulAlpha = (ul & 0xff000000) >> 24;
  406. *pul = (((ul & 0xff000000)))
  407. | ((((ul & 0xff0000) * ulAlpha) >> 8) & 0xff0000)
  408. | ((((ul & 0xff00) * ulAlpha) >> 8) & 0xff00)
  409. | ((((ul & 0xff) * ulAlpha) >> 8) & 0xff);
  410. }
  411. }
  412. return(bPerPixelAlpha);
  413. }
  414. /******************************Public*Routine******************************\
  415. * bShadowAlphaCursor
  416. *
  417. * This routine will create a pre-multiplied alpha version of the specified
  418. * cursor along with a shadow mask, assuming that the specified cursor does
  419. * not try to do 'XOR'.
  420. *
  421. * History:
  422. * 20-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  423. * Wrote it.
  424. \**************************************************************************/
  425. BOOL bShadowAlphaCursor(
  426. SURFOBJ* psoAlpha,
  427. SURFOBJ* psoMask,
  428. SURFOBJ* psoColor,
  429. XLATEOBJ* pxloMask,
  430. XLATEOBJ* pxloColor,
  431. RECTL* prclBounds)
  432. {
  433. BOOL bRet = FALSE; // Assume failure
  434. ULONG cxMask;
  435. ULONG cyMask;
  436. RECTL rclDst;
  437. XLATEOBJ xlo;
  438. ULONG aulXlate[2];
  439. ULONG* pul;
  440. ULONG i;
  441. POINTL ptlSrc;
  442. cyMask = psoMask->sizlBitmap.cy >> 1;
  443. cxMask = psoMask->sizlBitmap.cx;
  444. xlo.pulXlate = aulXlate;
  445. // We can only generate a shadow cursor if there are no XOR pixels
  446. // in the definition of the cursor (because we use an AlphaBlend
  447. // function which has no concept of XOR). So check if there are
  448. // any XOR pixels. We do this by ANDing the XOR mask with the AND
  449. // mask; if any part of the result is non-zero, then there is an
  450. // XOR component to the cursor.
  451. //
  452. // First, make a copy of the AND bits, converting it to 32bpp for
  453. // convenience:
  454. rclDst.left = 0;
  455. rclDst.top = 0;
  456. rclDst.right = cxMask;
  457. rclDst.bottom = cyMask;
  458. if (psoColor != NULL)
  459. {
  460. EngBitBlt(psoAlpha, psoColor, NULL, NULL, pxloColor, &rclDst,
  461. &gptlZero, NULL, NULL, NULL, 0xeeee); // SRCPAINT
  462. }
  463. else
  464. {
  465. ptlSrc.x = 0;
  466. ptlSrc.y = cyMask;
  467. EngBitBlt(psoAlpha, psoMask, NULL, NULL, pxloMask, &rclDst,
  468. &ptlSrc, NULL, NULL, NULL, 0xeeee); // SRCPAINT
  469. }
  470. // Now, AND in the XOR mask. Use a fake XLATEOBJ to do the color
  471. // expansion:
  472. aulXlate[0] = 0x00000000;
  473. aulXlate[1] = 0xffffffff;
  474. EngBitBlt(psoAlpha, psoMask, NULL, NULL, &xlo, &rclDst, &gptlZero,
  475. NULL, NULL, NULL, 0x8888); // SRCAND
  476. // Now check for any non-zero resulting pixels:
  477. pul = (ULONG*) psoAlpha->pvBits;
  478. i = psoAlpha->sizlBitmap.cy * abs(psoAlpha->lDelta) / 4;
  479. for (; i != 0; pul++, i--)
  480. {
  481. if (*pul != 0)
  482. {
  483. return(FALSE);
  484. }
  485. }
  486. // Okay, we're golden for adding the shadow. First, construct a
  487. // rectangle that represents the shadow's position:
  488. rclDst.left = ALPHA_EDGE + SHADOW_X_OFFSET;
  489. rclDst.top = ALPHA_EDGE + SHADOW_Y_OFFSET;
  490. rclDst.right = ALPHA_EDGE + SHADOW_X_OFFSET + prclBounds->right;
  491. rclDst.bottom = ALPHA_EDGE + SHADOW_Y_OFFSET + prclBounds->bottom;
  492. // Create a copy of the mask, giving the mask a particular alpha
  493. // value:
  494. aulXlate[0] = SHADOW_ALPHA;
  495. aulXlate[1] = 0x0;
  496. EngCopyBits(psoAlpha, psoMask, NULL, &xlo, &rclDst, &gptlZero);
  497. // Create the blur from the copy. We invoke the 3x3 blur twice
  498. // to get a better blur (note that we changed ALPHA_EDGE to
  499. // accomodate this).
  500. if (bBlurCursorShadow(psoAlpha) && bBlurCursorShadow(psoAlpha))
  501. {
  502. rclDst.left = ALPHA_EDGE;
  503. rclDst.top = ALPHA_EDGE;
  504. rclDst.right = ALPHA_EDGE + prclBounds->right;
  505. rclDst.bottom = ALPHA_EDGE + prclBounds->bottom;
  506. // Now, zero the opaque pixels:
  507. aulXlate[0] = 0x00000000;
  508. aulXlate[1] = 0xffffffff;
  509. EngBitBlt(psoAlpha, psoMask, NULL, NULL, &xlo, &rclDst, &gptlZero,
  510. NULL, NULL, NULL, 0x8888); // SRCAND
  511. // Now, give all the opaque pixels an alpha value of 0xff:
  512. aulXlate[0] = 0xff000000;
  513. aulXlate[1] = 0x00000000;
  514. EngBitBlt(psoAlpha, psoMask, NULL, NULL, &xlo, &rclDst, &gptlZero,
  515. NULL, NULL, NULL, 0xeeee); // SRCPAINT
  516. // Finally, OR in the opaque bits on top of the shadow:
  517. if (psoColor != NULL)
  518. {
  519. EngBitBlt(psoAlpha, psoColor, NULL, NULL, pxloColor, &rclDst,
  520. &gptlZero, NULL, NULL, NULL, 0xeeee); // SRCPAINT
  521. }
  522. else
  523. {
  524. ptlSrc.x = 0;
  525. ptlSrc.y = cyMask;
  526. EngBitBlt(psoAlpha, psoMask, NULL, NULL, pxloMask, &rclDst,
  527. &ptlSrc, NULL, NULL, NULL, 0xeeee); // SRCPAINT
  528. }
  529. bRet = TRUE;
  530. }
  531. return(bRet);
  532. }
  533. /******************************Public*Routine******************************\
  534. * vProcessCursorShape
  535. *
  536. * This routine will:
  537. *
  538. * 1. Calculate the bounds on the cursor shape;
  539. * 2. Create a pre-multiplied alpha surface if the cursor shape has per-
  540. * pixel alpha;
  541. * 3. Create a pre-multiplied alpha shadow surface for the cursor if
  542. * we've been asked to create a 'shadow'.
  543. *
  544. * History:
  545. * 20-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  546. * Wrote it.
  547. \**************************************************************************/
  548. VOID vProcessCursorShape(
  549. HDEV hdev,
  550. BOOL bShadow,
  551. SURFOBJ* psoMask,
  552. SURFOBJ* psoColor,
  553. PALETTE* ppalColor,
  554. RECTL* prclBounds,
  555. HBITMAP* phbmAlpha)
  556. {
  557. SPRITESTATE* pSpriteState;
  558. SURFACE* psurfColor;
  559. SURFMEM SurfDimo;
  560. BOOL bAlpha;
  561. DEVBITMAPINFO dbmi;
  562. SURFOBJ* psoAlpha;
  563. RECTL rclAlpha;
  564. RECTL rclColor;
  565. // Delete the existing hbmAlpha, so that it can be regenerated.
  566. if (*phbmAlpha != NULL)
  567. {
  568. GreDeleteObject(*phbmAlpha);
  569. *phbmAlpha = NULL;
  570. }
  571. // Do a first-pass bounds calculation taking into account only
  572. // the monochrome mask:
  573. vCalculateCursorBounds(psoMask, NULL, prclBounds);
  574. // Create a 32bpp DIB to hold the alpha bits. We add in 4 to
  575. // the dimensions to account for the one pixel extra on every
  576. // side that the blurring result needs, plus the one extra
  577. // pixel on every side that the blurring process needs as work-
  578. // space.
  579. rclAlpha.left = 0;
  580. rclAlpha.top = 0;
  581. rclAlpha.right = SHADOW_X_OFFSET + (2 * ALPHA_EDGE)
  582. + (psoMask->sizlBitmap.cx);
  583. rclAlpha.bottom = SHADOW_Y_OFFSET + (2 * ALPHA_EDGE)
  584. + (psoMask->sizlBitmap.cy >> 1);
  585. dbmi.cxBitmap = rclAlpha.right;
  586. dbmi.cyBitmap = rclAlpha.bottom;
  587. dbmi.iFormat = BMF_32BPP;
  588. dbmi.fl = BMF_TOPDOWN;
  589. dbmi.hpal = NULL;
  590. if (SurfDimo.bCreateDIB(&dbmi, NULL))
  591. {
  592. psoAlpha = SurfDimo.pSurfobj();
  593. psurfColor = SURFOBJ_TO_SURFACE_NOT_NULL(psoColor);
  594. EXLATEOBJ xloMono;
  595. EXLATEOBJ xloColor;
  596. XEPALOBJ palColor(ppalColor);
  597. XEPALOBJ palDefault(ppalDefault);
  598. XEPALOBJ palRGB(gppalRGB);
  599. XEPALOBJ palMono(ppalMono);
  600. if (xloMono.bInitXlateObj(NULL, DC_ICM_OFF, palMono, palRGB,
  601. palDefault, palDefault, 0, 0xffffff, 0))
  602. {
  603. if ((psoColor == NULL) ||
  604. (xloColor.bInitXlateObj(NULL, DC_ICM_OFF, palColor, palRGB,
  605. palDefault, palDefault, 0, 0, 0)))
  606. {
  607. bAlpha = FALSE;
  608. if (psoColor != NULL)
  609. {
  610. // Do a second-pass bounds accumulation, taking into
  611. // account both the monochrome and color masks. We
  612. // use the Alpha surface to create a directly-readable
  613. // copy of 'psoColor' (it might be STYPE_DEVBITMAP):
  614. rclColor.left = 0;
  615. rclColor.top = 0;
  616. rclColor.right = psoMask->sizlBitmap.cx;
  617. rclColor.bottom = psoMask->sizlBitmap.cy >> 1;
  618. EngCopyBits(psoAlpha,
  619. psoColor,
  620. NULL,
  621. xloColor.pxlo(),
  622. &rclColor,
  623. &gptlZero);
  624. vCalculateCursorBounds(psoMask, psoAlpha, prclBounds);
  625. }
  626. if ((psoColor != NULL) &&
  627. (xloColor.pxlo()->flXlate & XO_TRIVIAL) &&
  628. (psoColor->iBitmapFormat == BMF_32BPP))
  629. {
  630. EngEraseSurface(psoAlpha, &rclAlpha, 0);
  631. bAlpha = bApplicationAlphaCursor(psoAlpha,
  632. psoColor,
  633. prclBounds);
  634. }
  635. if ((!bAlpha) && (bShadow))
  636. {
  637. EngEraseSurface(psoAlpha, &rclAlpha, 0);
  638. bAlpha = bShadowAlphaCursor(psoAlpha,
  639. psoMask,
  640. psoColor,
  641. xloMono.pxlo(),
  642. xloColor.pxlo(),
  643. prclBounds);
  644. }
  645. if (bAlpha)
  646. {
  647. SurfDimo.vKeepIt();
  648. SurfDimo.vSetPID(OBJECT_OWNER_PUBLIC);
  649. *phbmAlpha = (HBITMAP) SurfDimo.ps->hsurf();
  650. }
  651. }
  652. }
  653. }
  654. }
  655. /******************************Public*Routine******************************\
  656. * vSetPointer
  657. *
  658. * Set the cursor shape, position and hot spot.
  659. *
  660. * History:
  661. * Sat 25-Apr-1998 -by- J. Andrew Goossen [andrewgo]
  662. * Re-wrote it to handle sprites, shadows, and alpha cursors.
  663. *
  664. * Sun 09-Aug-1992 -by- Patrick Haluptzok [patrickh]
  665. * add engine pointer simulations, validate data from USER.
  666. *
  667. * Tue 12-May-1992 01:49:04 -by- Charles Whitmer [chuckwh]
  668. * Wrote it.
  669. \**************************************************************************/
  670. VOID vSetPointer(HDEV hdev, PCURSINFO pci, ULONG fl, ULONG ulTrailLength, ULONG ulFreq)
  671. {
  672. BOOL bShadow = (fl & SPS_ALPHA);
  673. PDEVOBJ po(hdev);
  674. ASSERTGDI(po.bValid() && !po.bMetaDriver(), "Invalid HDEV");
  675. if (po.bDisabled())
  676. return;
  677. // Perhaps we're being told to tear the pointer down.
  678. if (pci == (PCURSINFO) NULL)
  679. {
  680. if (po.bSoftwarePointer())
  681. {
  682. EngSetPointerShape(po.pSurface()->pSurfobj(), NULL, NULL,
  683. NULL, 0, 0, 0, 0, NULL, 0);
  684. }
  685. if (po.bHardwarePointer())
  686. {
  687. PPFNDRV(po, MovePointer)(po.pSurface()->pSurfobj(), -1, -1, NULL);
  688. }
  689. po.bHardwarePointer(FALSE);
  690. po.bSoftwarePointer(FALSE);
  691. po.bMouseTrails(FALSE);
  692. return;
  693. }
  694. // OK, now we have some serious work to be done. We have to have a mask.
  695. // Lock down and validate the cursor.
  696. SURFREF soMask((HSURF) pci->hbmMask);
  697. if (!soMask.bValid() ||
  698. (soMask.ps->iFormat() != BMF_1BPP) ||
  699. (soMask.ps->sizl().cy & 0x0001))
  700. {
  701. WARNING("GreSetPointer failed because of weird cursor\n");
  702. return;
  703. }
  704. XEPALOBJ palSrc;
  705. XEPALOBJ palDisp;
  706. XEPALOBJ palDispDC(ppalDefault);
  707. SURFACE *psurfColor = NULL;
  708. SURFACE *psurfAlpha = NULL;
  709. XLATEOBJ *pxlo = NULL;
  710. EXLATEOBJ xlo;
  711. SURFREF soColor;
  712. SURFREF soAlpha;
  713. PPALETTE ppalSrc;
  714. FLONG flDriver;
  715. RECTL* prclOpaqueBounds;
  716. RECTL rclAlphaBounds;
  717. // We can reference pSurface() only once the Devlock is acquired,
  718. // for dynamic mode changing.
  719. SURFOBJ* psoDisplay = po.pSurface()->pSurfobj();
  720. if (pci->hbmColor)
  721. {
  722. soColor.vAltCheckLock((HSURF) pci->hbmColor);
  723. if (soColor.bValid())
  724. {
  725. if (soColor.ps->sizl().cy != (soMask.ps->sizl().cy >> 1))
  726. {
  727. WARNING("GreSetPointer failed color not half height mask\n");
  728. return;
  729. }
  730. // Handle the weird case where we get a compatible bitmap created
  731. // for the parent:
  732. ppalSrc = soColor.ps->ppal();
  733. if ((ppalSrc == NULL) && (po.hdevParent() != po.hdev()))
  734. {
  735. PDEVOBJ poParent(po.hdevParent());
  736. ppalSrc = poParent.ppalSurf();
  737. }
  738. if (!bIsCompatible(&ppalSrc, ppalSrc, soColor.ps, po.hdev()))
  739. {
  740. WARNING("GreSetPointer failed - bitmap not compatible with surface\n");
  741. return;
  742. }
  743. palSrc.ppalSet(ppalSrc);
  744. palDisp.ppalSet(po.ppalSurf());
  745. if (xlo.bInitXlateObj(NULL, DC_ICM_OFF, palSrc, palDisp, palDispDC,
  746. palDispDC, 0x000000L, 0xFFFFFFL, 0))
  747. {
  748. pxlo = xlo.pxlo();
  749. psurfColor = soColor.ps;
  750. }
  751. }
  752. }
  753. // If we've never seen this cursor before, compute the bounds and
  754. // create the alpha shadow if necessary.
  755. prclOpaqueBounds = (RECTL*) &pci->rcBounds;
  756. if ((prclOpaqueBounds->bottom == 0) ||
  757. ((pci->CURSORF_flags & CURSORF_SHADOW) && !bShadow) ||
  758. (!(pci->CURSORF_flags & CURSORF_SHADOW) && bShadow))
  759. {
  760. vProcessCursorShape(hdev,
  761. bShadow,
  762. soMask.pSurfobj(),
  763. psurfColor->pSurfobj(),
  764. ppalSrc,
  765. (RECTL*) &pci->rcBounds,
  766. (HBITMAP*) &pci->hbmAlpha);
  767. if (bShadow)
  768. {
  769. pci->CURSORF_flags |= CURSORF_SHADOW;
  770. }
  771. else
  772. {
  773. pci->CURSORF_flags &= ~CURSORF_SHADOW;
  774. }
  775. }
  776. // Ignore the alpha flag now and use the existence of 'hbmAlpha' to
  777. // determine whether the cursor should use the pre-generated alpha
  778. // surface.
  779. fl &= ~SPS_ALPHA;
  780. if ((pci->hbmAlpha != NULL) && (po.iDitherFormat() > BMF_8BPP))
  781. {
  782. soAlpha.vAltCheckLock((HSURF) pci->hbmAlpha);
  783. psurfAlpha = soAlpha.ps;
  784. rclAlphaBounds.left = pci->rcBounds.left;
  785. rclAlphaBounds.top = pci->rcBounds.top;
  786. rclAlphaBounds.right = pci->rcBounds.right
  787. + SHADOW_X_OFFSET + (2 * ALPHA_EDGE);
  788. rclAlphaBounds.bottom = pci->rcBounds.bottom
  789. + SHADOW_Y_OFFSET + (2 * ALPHA_EDGE);
  790. // Trim off the outside edge on all sides, which was used only
  791. // temporarily by the bBlurCursorShadow routine.
  792. rclAlphaBounds.left++;
  793. rclAlphaBounds.top++;
  794. rclAlphaBounds.right--;
  795. rclAlphaBounds.bottom--;
  796. }
  797. ULONG iMode;
  798. LONG xPointer;
  799. LONG yPointer;
  800. RECTL rclBoundsCopy;
  801. BOOL bHardwarePointer;
  802. BOOL bSoftwarePointer;
  803. BOOL bSynchronousPointer;
  804. BOOL bMouseTrails;
  805. if (!po.bDisabled())
  806. {
  807. po.ptlHotSpot(pci->xHotspot, pci->yHotspot);
  808. xPointer = po.ptlPointer().x;
  809. yPointer = po.ptlPointer().y;
  810. flDriver = SPS_CHANGE | (fl & (SPS_ANIMATESTART | SPS_ANIMATEUPDATE));
  811. bHardwarePointer = FALSE;
  812. bSoftwarePointer = TRUE;
  813. bMouseTrails = FALSE;
  814. bSynchronousPointer = FALSE;
  815. if(ulTrailLength != 0 && ulFreq != 0)
  816. {
  817. ulTrailLength = MIN(ulTrailLength, 16);
  818. ulFreq = MIN(ulFreq, 255);
  819. flDriver |= ((ulTrailLength << 8) & SPS_LENGTHMASK);
  820. flDriver |= ((ulFreq <<12) & SPS_FREQMASK);
  821. bMouseTrails = TRUE;
  822. }
  823. if (PPFNVALID(po, SetPointerShape) &&
  824. (!bMouseTrails || (po.flGraphicsCaps2() & GCAPS2_MOUSETRAILS)) )
  825. {
  826. // Give the hardware the first crack at the alpha surface (if
  827. // there is one).
  828. if (psurfAlpha != NULL)
  829. {
  830. if (po.flGraphicsCaps2() & GCAPS2_ALPHACURSOR)
  831. {
  832. rclBoundsCopy = rclAlphaBounds;
  833. iMode = PPFNDRV(po, SetPointerShape)
  834. (psoDisplay,
  835. NULL,
  836. psurfAlpha->pSurfobj(),
  837. NULL,
  838. pci->xHotspot + ALPHA_EDGE,
  839. pci->yHotspot + ALPHA_EDGE,
  840. xPointer,
  841. yPointer,
  842. &rclBoundsCopy,
  843. flDriver | SPS_ALPHA);
  844. // SPS_ACCEPT_EXCLUDE is obsolete ... force software
  845. // iMode is now treated as a set of flags
  846. if(iMode == SPS_ACCEPT_EXCLUDE)
  847. bHardwarePointer = FALSE;
  848. else
  849. bHardwarePointer = (iMode & SPS_ACCEPT_NOEXCLUDE ? TRUE : FALSE);
  850. bSoftwarePointer = !bHardwarePointer;
  851. bSynchronousPointer = (iMode & SPS_ACCEPT_SYNCHRONOUS ? TRUE : FALSE);
  852. }
  853. }
  854. else
  855. {
  856. // Handle the normal, no-alpha, cursor case:
  857. rclBoundsCopy = *prclOpaqueBounds;
  858. iMode = PPFNDRV(po, SetPointerShape)
  859. (psoDisplay,
  860. soMask.pSurfobj(),
  861. psurfColor->pSurfobj(),
  862. pxlo,
  863. pci->xHotspot,
  864. pci->yHotspot,
  865. xPointer,
  866. yPointer,
  867. &rclBoundsCopy,
  868. flDriver);
  869. // Since the introduction of 'sprites', we no longer
  870. // support SPS_ACCEPT_EXCLUDE.
  871. if (iMode == SPS_ACCEPT_EXCLUDE)
  872. {
  873. PPFNDRV(po, MovePointer)(psoDisplay, -1, -1, NULL);
  874. iMode = SPS_DECLINE;
  875. }
  876. bHardwarePointer = (iMode & SPS_ACCEPT_NOEXCLUDE ? TRUE : FALSE);
  877. bSoftwarePointer = !bHardwarePointer;
  878. bSynchronousPointer = (iMode & SPS_ACCEPT_SYNCHRONOUS ? TRUE : FALSE);
  879. }
  880. }
  881. if (bSoftwarePointer)
  882. {
  883. if (psurfAlpha != NULL)
  884. {
  885. EngSetPointerShape(psoDisplay,
  886. NULL,
  887. psurfAlpha->pSurfobj(),
  888. NULL,
  889. pci->xHotspot + ALPHA_EDGE,
  890. pci->yHotspot + ALPHA_EDGE,
  891. xPointer,
  892. yPointer,
  893. &rclAlphaBounds,
  894. flDriver | SPS_ALPHA);
  895. }
  896. else
  897. {
  898. EngSetPointerShape(psoDisplay,
  899. soMask.pSurfobj(),
  900. psurfColor->pSurfobj(),
  901. pxlo,
  902. pci->xHotspot,
  903. pci->yHotspot,
  904. xPointer,
  905. yPointer,
  906. prclOpaqueBounds,
  907. flDriver);
  908. }
  909. }
  910. if ((!bSoftwarePointer) && (po.bSoftwarePointer()))
  911. {
  912. // Turn off software cursor:
  913. EngMovePointer(psoDisplay, -1, -1, NULL);
  914. }
  915. if ((!bHardwarePointer) && (po.bHardwarePointer()))
  916. {
  917. // Turn off hardware cursor:
  918. PPFNDRV(po, MovePointer)(psoDisplay, -1, -1, NULL);
  919. }
  920. po.bSoftwarePointer(bSoftwarePointer);
  921. po.bHardwarePointer(bHardwarePointer);
  922. po.bMouseTrails(bMouseTrails);
  923. // Synchronous pointer flag forces synchronization of pointer even if
  924. // GCAPS_ASYNCMOVE was specified allowing drivers to accept some pointers
  925. // but have them drawn synchronously.
  926. po.bSynchronousPointer(bSynchronousPointer);
  927. }
  928. }
  929. /******************************Public*Routine******************************\
  930. * vMovePointer
  931. *
  932. * Move the Pointer to the specified location. This is called only by
  933. * USER.
  934. *
  935. * History:
  936. * Thu 14-Apr-1994 -by- Patrick Haluptzok [patrickh]
  937. * Optimize / make Async pointers work
  938. *
  939. * See GreMovePointer for info on ulFlags
  940. *
  941. * Tue 12-May-1992 02:11:51 -by- Charles Whitmer [chuckwh]
  942. * Wrote it.
  943. \**************************************************************************/
  944. VOID vMovePointer(HDEV hdev, int x, int y, LONG ulFlags)
  945. {
  946. RECTL *prcl;
  947. SURFOBJ *pso;
  948. PDEVOBJ po(hdev);
  949. ASSERTGDI(po.bValid() && !po.bMetaDriver(), "Invalid HDEV");
  950. // bDisabled can't change with hsemDevLock and hsemPointer both held.
  951. // bPtrHidden can't change unless hsemPointer is held if the
  952. // pointer is currently Async and the device supports Async movement.
  953. if ((po.ptlPointer().x != x) || (po.ptlPointer().y != y) || po.bMouseTrails())
  954. {
  955. po.ptlPointer(x, y);
  956. if (!po.bDisabled())
  957. {
  958. pso = po.pSurface()->pSurfobj();
  959. if (po.bHardwarePointer())
  960. {
  961. if (!PPFNVALID(po, MovePointerEx))
  962. {
  963. PPFNDRV(po, MovePointer)(pso, x, y, NULL);
  964. }
  965. else
  966. {
  967. // Use the Ex entry point to pass additional info
  968. // to the driver. E.g. TS uses this to pass source
  969. // information about mouse moves so that programmatic
  970. // mouse moves that originate at the server are always
  971. // sent down to the client.
  972. PPFNDRV(po, MovePointerEx)(pso, x, y, ulFlags);
  973. }
  974. }
  975. if (po.bSoftwarePointer())
  976. {
  977. EngMovePointer(pso, x, y, NULL);
  978. }
  979. // Panning drivers want to see the pointer update even
  980. // if the pointer isn't enabled, because the position
  981. // is used to update the visible rectangle within the
  982. // virtual desktop space.
  983. //
  984. // Note: There are cases where ntuser will turn off the
  985. // cursor expecting us to ignore pointer moves.
  986. // Unfortunately, this can happen during mode changes where
  987. // ntuser may have a temporarily bigger desktop than
  988. // physically exists in ntgdi. Therefore, we must check
  989. // the pointer position against the virtual desktop bounds.
  990. if ((po.flGraphicsCaps() & GCAPS_PANNING) && (y != -1) &&
  991. (x < pso->sizlBitmap.cx) && (y < pso->sizlBitmap.cy))
  992. {
  993. // The driver wants to be notified of the pointer
  994. // position even if a pointer isn't actually visible
  995. // (invisible panning!). Let it know the pointer is
  996. // still turned off by giving it a negative 'y':
  997. PPFNDRV(po, MovePointer)(pso, x, y - pso->sizlBitmap.cy, NULL);
  998. }
  999. }
  1000. }
  1001. }
  1002. /******************************Public*Routine******************************\
  1003. * GreSetPointer
  1004. *
  1005. * Set the cursor shape and hot spot.
  1006. *
  1007. \**************************************************************************/
  1008. VOID GreSetPointer(HDEV hdev, PCURSINFO pci, ULONG fl, ULONG ulTrailLength, ULONG ulFreq)
  1009. {
  1010. PVDEV pvdev;
  1011. PDISPSURF pds;
  1012. LONG csurf;
  1013. PDEVOBJ po(hdev);
  1014. DEVLOCKOBJ dlo(po);
  1015. SEMOBJ so(po.hsemPointer());
  1016. // Just pass directly to 'bSetPointer' when not running multi-mon:
  1017. if (!po.bMetaDriver())
  1018. {
  1019. vSetPointer(hdev, pci, fl, ulTrailLength, ulFreq);
  1020. }
  1021. else
  1022. {
  1023. // Okay, we've got work to do.
  1024. pvdev = (VDEV*) po.dhpdev();
  1025. pds = pvdev->pds;
  1026. csurf = pvdev->cSurfaces;
  1027. do {
  1028. vSetPointer(pds->hdev, pci, fl, ulTrailLength, ulFreq);
  1029. pds = pds->pdsNext;
  1030. } while (--csurf);
  1031. }
  1032. }
  1033. /******************************Public*Routine******************************\
  1034. * GreMovePointer
  1035. *
  1036. * Set the cursor position.
  1037. *
  1038. *
  1039. * ulFlags specified additional information about the move.
  1040. * E.g. Termsrv uses this to determine when to send updates to the client.
  1041. *
  1042. * If you make a programmatic mouse move that originates at the server
  1043. * use MP_PROCEDURAL
  1044. *
  1045. *
  1046. \**************************************************************************/
  1047. VOID GreMovePointer(HDEV hdev, int x, int y, ULONG ulFlags)
  1048. {
  1049. GDIFunctionID(GreMovePointer);
  1050. PVDEV pvdev;
  1051. PDISPSURF pds;
  1052. LONG csurf;
  1053. BOOL bUnlockBoth = FALSE;
  1054. PDEVOBJ po(hdev);
  1055. // If the driver has indicated it has bAsyncPointerMove capabilities
  1056. // and it currently is managing the pointer, and the pointer is
  1057. // supported in hardware so it doesn't need to be excluded
  1058. // (indicated by bPtrNeedsExcluding) then we only need to grab the pointer
  1059. // mutex which is only grabbed by people trying to make the pointer
  1060. // shape change and a few other odd ball places.
  1061. //
  1062. // Otherwise we grab the DEVLOCK and the pointer mutex which
  1063. // ensures nobody else is drawing, changing the pointer shape,
  1064. // etc.
  1065. if (po.bAsyncPointerMove() && !po.bSoftwarePointer())
  1066. {
  1067. //
  1068. // Note: We pass in NULL for parent semaphore here because we have
  1069. // no yet acquired the dev lock and thus under global ordering
  1070. // restrictions.
  1071. //
  1072. GreAcquireSemaphoreEx(po.hsemPointer(), SEMORDER_POINTER, NULL);
  1073. // Make sure we really got it, bAsyncPointerMove may change if you
  1074. // don't hold the DEVLOCK or the POINTER mutex.
  1075. if (!po.bAsyncPointerMove() || po.bSoftwarePointer())
  1076. {
  1077. // Release and regrab everything, for sure we are safe with
  1078. // both of them.
  1079. GreReleaseSemaphoreEx(po.hsemPointer());
  1080. GreAcquireSemaphoreEx(po.hsemDevLock(), SEMORDER_DEVLOCK, NULL);
  1081. GreAcquireSemaphoreEx(po.hsemPointer(), SEMORDER_POINTER, po.hsemDevLock());
  1082. bUnlockBoth = TRUE;
  1083. }
  1084. }
  1085. else
  1086. {
  1087. GreAcquireSemaphoreEx(po.hsemDevLock(), SEMORDER_DEVLOCK, NULL);
  1088. GreAcquireSemaphoreEx(po.hsemPointer(), SEMORDER_POINTER, po.hsemDevLock());
  1089. bUnlockBoth = TRUE;
  1090. }
  1091. GreEnterMonitoredSection(po.ppdev, WD_POINTER);
  1092. // Just pass directly to 'vMovePointer' when not running multi-mon:
  1093. if (!po.bMetaDriver())
  1094. {
  1095. vMovePointer(hdev, x, y, ulFlags);
  1096. }
  1097. else
  1098. {
  1099. // Okay, we've got work to do.
  1100. pvdev = (VDEV*) po.dhpdev();
  1101. pds = pvdev->pds;
  1102. csurf = pvdev->cSurfaces;
  1103. do {
  1104. if ((x >= pds->rcl.left) &&
  1105. (x < pds->rcl.right) &&
  1106. (y >= pds->rcl.top) &&
  1107. (y < pds->rcl.bottom))
  1108. {
  1109. vMovePointer(pds->hdev, x - pds->rcl.left, y - pds->rcl.top,
  1110. ulFlags);
  1111. }
  1112. else
  1113. {
  1114. vMovePointer(pds->hdev, -1, -1,
  1115. ulFlags);
  1116. }
  1117. pds = pds->pdsNext;
  1118. } while (--csurf);
  1119. }
  1120. po.ptlPointer(x, y);
  1121. GreExitMonitoredSection(po.ppdev, WD_POINTER);
  1122. GreReleaseSemaphoreEx(po.hsemPointer());
  1123. if (bUnlockBoth)
  1124. {
  1125. GreReleaseSemaphoreEx(po.hsemDevLock());
  1126. }
  1127. }
  1128. /******************************Public*Routine******************************\
  1129. * EngSetPointerTag
  1130. *
  1131. * This is the engine entry point that allows device drivers to create a
  1132. * 'tag' that will be combined with the pointer shape whenever it's sent
  1133. * to other drivers in the DDML chain via the DrvSetPointerShape call.
  1134. *
  1135. * This functionality is primarily intended to allow remoting DDML drivers
  1136. * to allow a name be added to the pointer to signify who owns 'control' of
  1137. * the machine's input. But they don't want to transmit the shape with the
  1138. * name over the wire, which is why we adopt the convention that this applies
  1139. * to every *other* device in the DDML chain.
  1140. *
  1141. * History:
  1142. * 20-Oct-1996 -by- J. Andrew Goossen [andrewgo]
  1143. * Wrote it.
  1144. \**************************************************************************/
  1145. BOOL EngSetPointerTag(
  1146. HDEV hdev, // Identifies device's PDEV. This is not the MDEV!
  1147. SURFOBJ* psoInputMask, // May be NULL when resetting the tag
  1148. SURFOBJ* psoInputColor, // Will be NULL if monochrome
  1149. XLATEOBJ* pxlo, // Reserved, must be NULL for now
  1150. FLONG fl) // Reserved, must be zero for now
  1151. {
  1152. // We shipped NT4 SP3 with this functionality, but it's obsolete as
  1153. // of NT5.
  1154. return(FALSE);
  1155. }
  1156. /******************************Public*Routine******************************\
  1157. * DEVLOCKOBJ::bLock
  1158. *
  1159. * Device locking object. Optionally computes the Rao region.
  1160. *
  1161. * History:
  1162. * Sun 30-Aug-1992 -by- Patrick Haluptzok [patrickh]
  1163. * change to boolean return
  1164. *
  1165. * Mon 27-Apr-1992 22:46:41 -by- Charles Whitmer [chuckwh]
  1166. * Clean up again.
  1167. *
  1168. * Tue 16-Jul-1991 -by- Patrick Haluptzok [patrickh]
  1169. * Clean up.
  1170. *
  1171. * 15-Sep-1990 -by- Donald Sidoroff [donalds]
  1172. * Wrote it.
  1173. \**************************************************************************/
  1174. BOOL DEVLOCKOBJ::bLock(XDCOBJ& dco)
  1175. {
  1176. GDIFunctionID(DEVLOCKOBJ::bLock);
  1177. hsemTrg = NULL; // Remember the semaphore we're waiting on.
  1178. ppdevTrg = NULL; // Remember pdev we're monitoring.
  1179. fl = DLO_VALID; // Remember if it is valid.
  1180. // We lock the semphore on direct display DCs and DFB's if
  1181. // the device has set GCAPS_SYNCHRONIZEACCESS set.
  1182. if (dco.bSynchronizeAccess())
  1183. {
  1184. // make sure we don't have any wrong sequence of acquiring locks
  1185. // should always acquire a DEVLOCK before we have the palette semaphore
  1186. ASSERTGDI ( (!GreIsSemaphoreOwnedByCurrentThread(ghsemPalette))
  1187. || (GreIsSemaphoreOwnedByCurrentThread(dco.hsemDcDevLock())),
  1188. "potential deadlock!\n");
  1189. // Grab the display semaphore
  1190. if(dco.bShareAccess())
  1191. {
  1192. GreAcquireSemaphoreShared(ghsemShareDevLock);
  1193. fl |= DLO_SHAREDACCESS;
  1194. }
  1195. else
  1196. {
  1197. hsemTrg = dco.hsemDcDevLock();
  1198. ppdevTrg = dco.pdc->ppdev();
  1199. GreAcquireSemaphoreEx(hsemTrg, SEMORDER_DEVLOCK, NULL);
  1200. GreEnterMonitoredSection(ppdevTrg, WD_DEVLOCK);
  1201. }
  1202. if (dco.pdc->bInFullScreen())
  1203. {
  1204. fl &= ~(DLO_VALID);
  1205. return(FALSE);
  1206. }
  1207. }
  1208. // Compute the new Rao region if it's dirty.
  1209. if (dco.pdc->bDirtyRao())
  1210. {
  1211. if (!dco.pdc->bCompute())
  1212. {
  1213. fl &= ~(DLO_VALID);
  1214. return(FALSE);
  1215. }
  1216. }
  1217. return(TRUE);
  1218. }
  1219. /******************************Public*Routine******************************\
  1220. * DEVLOCKOBJ::vLockNoDrawing
  1221. *
  1222. * Device locking object for when no drawing will take place.
  1223. *
  1224. * Used primarily to protect against dynamic mode changing when looking at
  1225. * surface fields. Because no drawing will take place, the rao region
  1226. * computations and full-screen checks need not be made.
  1227. *
  1228. * History:
  1229. * Thu 8-Feb-1996 -by- J. Andrew Goossen [andrewgo]
  1230. * Wrote it.
  1231. \**************************************************************************/
  1232. VOID DEVLOCKOBJ::vLockNoDrawing(XDCOBJ& dco)
  1233. {
  1234. GDIFunctionID(DEVLOCKOBJ::vLockNoDrawing);
  1235. hsemTrg = NULL; // Remember the semaphore we're waiting on.
  1236. ppdevTrg = NULL; // Remember pdev we're monitoring.
  1237. fl = DLO_VALID; // Remember if it is valid.
  1238. // We lock display DC's even if bSynchronizeAccess() isn't set so that
  1239. // the surface palette will still be locked down even for device-
  1240. // dependent-bitmaps.
  1241. PDEVOBJ po(dco.hdev());
  1242. if (po.bDisplayPDEV())
  1243. {
  1244. // Grab the display semaphore
  1245. hsemTrg = dco.hsemDcDevLock();
  1246. ppdevTrg = dco.pdc->ppdev();
  1247. GreAcquireSemaphoreEx(hsemTrg, SEMORDER_DEVLOCK, NULL);
  1248. GreEnterMonitoredSection(ppdevTrg, WD_DEVLOCK);
  1249. }
  1250. }
  1251. /******************************Public*Routine******************************\
  1252. * DEVLOCKBLTOBJ::bLock
  1253. *
  1254. * Device locking object. Optionally computes the Rao region.
  1255. *
  1256. * History:
  1257. * Sun 30-Aug-1992 -by- Patrick Haluptzok [patrickh]
  1258. * change to boolean return
  1259. *
  1260. * Mon 27-Apr-1992 22:46:41 -by- Charles Whitmer [chuckwh]
  1261. * Clean up again.
  1262. *
  1263. * Tue 16-Jul-1991 -by- Patrick Haluptzok [patrickh]
  1264. * Clean up.
  1265. *
  1266. * 15-Sep-1990 -by- Donald Sidoroff [donalds]
  1267. * Wrote it.
  1268. \**************************************************************************/
  1269. BOOL DEVLOCKBLTOBJ::bLock(XDCOBJ& dco)
  1270. {
  1271. GDIFunctionID(DEVLOCKBLTOBJ::bLock);
  1272. hsemTrg = NULL; // Remember the semaphore we're waiting on.
  1273. hsemSrc = NULL; // Remember the semaphore we're waiting on.
  1274. ppdevTrg = NULL; // Remember pdev we're monitoring.
  1275. ppdevSrc = NULL; // Remember pdev we're monitoring.
  1276. fl = DLO_VALID; // Remember if it is valid.
  1277. // We lock the semphore on direct display DCs and DFB's if
  1278. // the device has set GCAPS_SYNCHRONIZEACCESS set.
  1279. if (dco.bSynchronizeAccess())
  1280. {
  1281. // Grab the display semaphore
  1282. if(dco.bShareAccess())
  1283. {
  1284. GreAcquireSemaphoreShared(ghsemShareDevLock);
  1285. fl |= DLO_SHAREDACCESS;
  1286. }
  1287. else
  1288. {
  1289. hsemTrg = dco.hsemDcDevLock();
  1290. ppdevTrg = dco.pdc->ppdev();
  1291. GreAcquireSemaphoreEx(hsemTrg, SEMORDER_DEVLOCK, NULL);
  1292. GreEnterMonitoredSection(ppdevTrg, WD_DEVLOCK);
  1293. }
  1294. // Check if we are in full screen and drawing
  1295. // to the Display, this may just be a DFB.
  1296. if (dco.bInFullScreen())
  1297. {
  1298. fl &= ~(DLO_VALID);
  1299. return(FALSE);
  1300. }
  1301. }
  1302. // Compute the new Rao region if it's dirty.
  1303. if (dco.pdc->bDirtyRao())
  1304. {
  1305. if (!dco.pdc->bCompute())
  1306. {
  1307. fl &= ~(DLO_VALID);
  1308. return(FALSE);
  1309. }
  1310. }
  1311. return(TRUE);
  1312. }
  1313. /******************************Public*Routine******************************\
  1314. * DEVLOCKBLTOBJ::bLock
  1315. *
  1316. * Lock both a source and target DC. Used by StretchBlt, PlgBlt and such.
  1317. *
  1318. * We must check to see if we are in full screen and fail if we are.
  1319. *
  1320. * History:
  1321. * Mon 18-Apr-1994 -by- Patrick Haluptzok [patrickh]
  1322. * bSynchronize Checks
  1323. *
  1324. * 16-Feb-1993 -by- Eric Kutter [erick]
  1325. * Added full screen checks
  1326. *
  1327. * 11-Nov-1992 -by- Donald Sidoroff [donalds]
  1328. * Wrote it.
  1329. \**************************************************************************/
  1330. BOOL DEVLOCKBLTOBJ::bLock(XDCOBJ& dcoTrg, XDCOBJ& dcoSrc)
  1331. {
  1332. GDIFunctionID(DEVLOCKBLTOBJ::bLock);
  1333. hsemTrg = NULL;
  1334. hsemSrc = NULL;
  1335. ppdevTrg = NULL; // Remember pdev we're monitoring.
  1336. ppdevSrc = NULL; // Remember pdev we're monitoring.
  1337. fl = DLO_VALID;
  1338. if(dcoSrc.bShareAccess() || dcoTrg.bShareAccess())
  1339. {
  1340. GreAcquireSemaphoreShared(ghsemShareDevLock);
  1341. fl |= DLO_SHAREDACCESS;
  1342. }
  1343. if (dcoSrc.bSynchronizeAccess())
  1344. {
  1345. // Grab the display semaphore
  1346. if(!dcoSrc.bShareAccess())
  1347. {
  1348. hsemSrc = dcoSrc.hsemDcDevLock();
  1349. ppdevSrc = dcoSrc.pdc->ppdev();
  1350. GreAcquireSemaphoreEx(hsemSrc, SEMORDER_DEVLOCK, NULL);
  1351. GreEnterMonitoredSection(ppdevSrc, WD_DEVLOCK);
  1352. }
  1353. // Check if we are in full screen and drawing
  1354. // to the Display, this may just be a DFB.
  1355. if (dcoSrc.bInFullScreen())
  1356. {
  1357. fl &= ~(DLO_VALID);
  1358. return(FALSE);
  1359. }
  1360. }
  1361. if (dcoTrg.bSynchronizeAccess())
  1362. {
  1363. // Grab the display semaphore
  1364. if(!dcoTrg.bShareAccess())
  1365. {
  1366. hsemTrg = dcoTrg.hsemDcDevLock();
  1367. ppdevTrg = dcoTrg.pdc->ppdev();
  1368. GreAcquireSemaphoreEx(hsemTrg, SEMORDER_DEVLOCK, NULL);
  1369. GreEnterMonitoredSection(ppdevTrg, WD_DEVLOCK);
  1370. }
  1371. // Check if we are in full screen and drawing
  1372. // to the Display, this may just be a DFB.
  1373. if (dcoTrg.bInFullScreen())
  1374. {
  1375. fl = 0;
  1376. return(FALSE);
  1377. }
  1378. }
  1379. // Compute the new Rao regions.
  1380. if (dcoTrg.pdc->bDirtyRao())
  1381. {
  1382. if (!dcoTrg.pdc->bCompute())
  1383. {
  1384. fl &= ~(DLO_VALID);
  1385. return(FALSE);
  1386. }
  1387. }
  1388. if (dcoSrc.pdc->bDirtyRao())
  1389. {
  1390. if (!dcoSrc.pdc->bCompute())
  1391. {
  1392. fl &= ~(DLO_VALID);
  1393. return(FALSE);
  1394. }
  1395. }
  1396. return(TRUE);
  1397. }