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.

1691 lines
51 KiB

  1. /******************************Module*Header*******************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: pointer.c
  8. *
  9. * This module contains the hardware pointer support for the display
  10. * driver. This supports both the built-in S3 hardware pointer and
  11. * some common DAC hardware pointers.
  12. *
  13. * Copyright (c) 1992-1998 Microsoft Corporation
  14. \**************************************************************************/
  15. #include "precomp.h"
  16. typedef struct BT485_POINTER_DATA {
  17. LONG xHot;
  18. LONG yHot;
  19. ULONG ulExtendedDacControl;
  20. BYTE jCommandRegister0;
  21. BYTE jCommandRegister1;
  22. BYTE jCommandRegister2;
  23. BYTE jCommandRegister3;
  24. } BT485_POINTER_DATA;
  25. typedef struct TI025_POINTER_DATA {
  26. ULONG ulExtendedDacControl;
  27. } TI025_POINTER_DATA;
  28. ULONG NewMmIoSetPointerShape(
  29. PDEV* ppdev,
  30. SURFOBJ* psoMsk,
  31. SURFOBJ* psoColor,
  32. XLATEOBJ* pxlo,
  33. LONG xHot,
  34. LONG yHot,
  35. LONG x,
  36. LONG y,
  37. RECTL* prcl,
  38. FLONG fl,
  39. BYTE* pBuf
  40. );
  41. /******************************Public*Routine******************************\
  42. * VOID vShowPointerBt485
  43. *
  44. * Show or hide the Brooktree 485 hardware pointer.
  45. *
  46. \**************************************************************************/
  47. VOID vShowPointerBt485(
  48. PDEV* ppdev,
  49. BT485_POINTER_DATA* pbp,
  50. BOOL bShow)
  51. {
  52. BYTE* pjIoBase = ppdev->pjIoBase;
  53. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0200);
  54. OUTP(pjIoBase, BT485_ADDR_CMD_REG2, (bShow) ?
  55. (pbp->jCommandRegister2 | BT485_CURSOR_MODE2) :
  56. pbp->jCommandRegister2);
  57. if (!bShow)
  58. {
  59. // Move the hardware pointer off-screen so that it doesn't flash
  60. // in the old position when we finally turn it back on:
  61. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0300);
  62. OUTP(pjIoBase, BT485_CURSOR_X_LOW, 0);
  63. OUTP(pjIoBase, BT485_CURSOR_X_HIGH, 0);
  64. // A 'y' value of 1600 should be enough...
  65. OUTP(pjIoBase, BT485_CURSOR_Y_LOW, 1663);
  66. OUTP(pjIoBase, BT485_CURSOR_Y_HIGH, (1663 >> 8));
  67. }
  68. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl);
  69. }
  70. /******************************Public*Routine******************************\
  71. * VOID vMovePointerBt485
  72. *
  73. * Move the Brooktree 485 hardware pointer.
  74. *
  75. \**************************************************************************/
  76. VOID vMovePointerBt485(
  77. PDEV* ppdev,
  78. BT485_POINTER_DATA* pbp,
  79. LONG x,
  80. LONG y)
  81. {
  82. BYTE* pjIoBase = ppdev->pjIoBase;
  83. x -= pbp->xHot;
  84. y -= pbp->yHot;
  85. x += 64;
  86. y += 64;
  87. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0300);
  88. OUTP(pjIoBase, BT485_CURSOR_X_LOW, (x));
  89. OUTP(pjIoBase, BT485_CURSOR_X_HIGH, (x >> 8));
  90. OUTP(pjIoBase, BT485_CURSOR_Y_LOW, (y));
  91. OUTP(pjIoBase, BT485_CURSOR_Y_HIGH, (y >> 8));
  92. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl);
  93. }
  94. /******************************Public*Routine******************************\
  95. * BOOL bSetPointerShapeBt485
  96. *
  97. * Set the Brooktree 485 hardware pointer shape.
  98. *
  99. \**************************************************************************/
  100. BOOL bSetPointerShapeBt485(
  101. PDEV* ppdev,
  102. BT485_POINTER_DATA* pbp,
  103. LONG x, // If -1, pointer should be created hidden
  104. LONG y,
  105. LONG xHot,
  106. LONG yHot,
  107. LONG cx,
  108. LONG cy,
  109. BYTE* pjShape)
  110. {
  111. BYTE* pjIoBase = ppdev->pjIoBase;
  112. BYTE* pjSrc;
  113. LONG i;
  114. // Get access to command register 3:
  115. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0100);
  116. OUTP(pjIoBase, BT485_ADDR_CMD_REG0, pbp->jCommandRegister0 | BT485_CMD_REG_3_ACCESS);
  117. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl);
  118. OUTP(pjIoBase, BT485_ADDR_CMD_REG1, 0x01);
  119. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0200);
  120. OUTP(pjIoBase, BT485_ADDR_CMD_REG3, pbp->jCommandRegister3);
  121. // Disable the pointer:
  122. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0200);
  123. OUTP(pjIoBase, BT485_ADDR_CMD_REG2, pbp->jCommandRegister2);
  124. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl);
  125. OUTP(pjIoBase, BT485_ADDR_CUR_RAM_WRITE, 0x0);
  126. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0200);
  127. // Point to first XOR word:
  128. pjSrc = pjShape + 2;
  129. // Download the XOR mask:
  130. for (i = 256; i > 0; i--)
  131. {
  132. OUTP(pjIoBase, BT485_CUR_RAM_ARRAY_DATA, *(pjSrc));
  133. OUTP(pjIoBase, BT485_CUR_RAM_ARRAY_DATA, *(pjSrc + 1));
  134. // Skip over AND word:
  135. pjSrc += 4;
  136. }
  137. // Pointer to first AND word:
  138. pjSrc = pjShape;
  139. // Download the AND mask:
  140. for (i = 256; i > 0; i--)
  141. {
  142. OUTP(pjIoBase, BT485_CUR_RAM_ARRAY_DATA, *(pjSrc));
  143. OUTP(pjIoBase, BT485_CUR_RAM_ARRAY_DATA, *(pjSrc + 1));
  144. // Skip over XOR word:
  145. pjSrc += 4;
  146. }
  147. pbp->xHot = xHot;
  148. pbp->yHot = yHot;
  149. // Set the position of the pointer:
  150. if (x != -1)
  151. {
  152. x -= xHot;
  153. y -= yHot;
  154. x += 64;
  155. y += 64;
  156. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0300);
  157. OUTP(pjIoBase, BT485_CURSOR_X_LOW, (x));
  158. OUTP(pjIoBase, BT485_CURSOR_X_HIGH, (x >> 8));
  159. OUTP(pjIoBase, BT485_CURSOR_Y_LOW, (y));
  160. OUTP(pjIoBase, BT485_CURSOR_Y_HIGH, (y >> 8));
  161. // Enable the pointer:
  162. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0200);
  163. OUTP(pjIoBase, BT485_ADDR_CMD_REG2, pbp->jCommandRegister2 | BT485_CURSOR_MODE2);
  164. }
  165. else
  166. {
  167. // Move the hardware pointer off-screen so that it doesn't flash
  168. // in the old position when we finally turn it back on:
  169. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0300);
  170. OUTP(pjIoBase, BT485_CURSOR_X_LOW, 0);
  171. OUTP(pjIoBase, BT485_CURSOR_X_HIGH, 0);
  172. // A 'y' value of 1600 should be enough...
  173. OUTP(pjIoBase, BT485_CURSOR_Y_LOW, 1663);
  174. OUTP(pjIoBase, BT485_CURSOR_Y_HIGH, (1663 >> 8));
  175. }
  176. // Reset the DAC extended register:
  177. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl);
  178. return(TRUE);
  179. }
  180. /******************************Public*Routine******************************\
  181. * VOID vEnablePointerBt485
  182. *
  183. * Get the hardware ready to use the Brooktree 485 hardware pointer.
  184. *
  185. \**************************************************************************/
  186. VOID vEnablePointerBt485(
  187. PDEV* ppdev,
  188. BT485_POINTER_DATA* pbp,
  189. BOOL bFirst)
  190. {
  191. BYTE* pjIoBase = ppdev->pjIoBase;
  192. if (bFirst)
  193. {
  194. // Make a copy of the extended DAC control register:
  195. OUTP(pjIoBase, CRTC_INDEX, EX_DAC_CT);
  196. pbp->ulExtendedDacControl = ((INP(pjIoBase, CRTC_DATA) << 8) | EX_DAC_CT) & ~0x0300;
  197. // Make copies of command registers 1 and 2:
  198. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0100);
  199. pbp->jCommandRegister0 = INP(pjIoBase, BT485_ADDR_CMD_REG0);
  200. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0200);
  201. pbp->jCommandRegister1 = INP(pjIoBase, BT485_ADDR_CMD_REG1);
  202. // Make a copy of command register 2 and mask off the pointer control bits:
  203. pbp->jCommandRegister2 = INP(pjIoBase, BT485_ADDR_CMD_REG2) & BT485_CURSOR_DISABLE;
  204. // Disable the pointer:
  205. OUTP(pjIoBase, BT485_ADDR_CMD_REG2, pbp->jCommandRegister2);
  206. // To access command register 3, we do the following:
  207. // 1. Set the command register access bit in command register 0.
  208. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0100);
  209. OUTP(pjIoBase, BT485_ADDR_CMD_REG0, pbp->jCommandRegister0 | BT485_CMD_REG_3_ACCESS);
  210. // 2. Set the index to 1.
  211. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl);
  212. OUTP(pjIoBase, BT485_ADDR_CMD_REG1, 0x01);
  213. // 3. Now read command register 3.
  214. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0200);
  215. pbp->jCommandRegister3 = INP(pjIoBase, BT485_ADDR_CMD_REG3);
  216. // Set command register 3 for a 64 X 64 pointer:
  217. pbp->jCommandRegister3 |= BT485_64X64_CURSOR;
  218. OUTP(pjIoBase, BT485_ADDR_CMD_REG3, pbp->jCommandRegister3);
  219. // Disable access to command register 3:
  220. OUTPW(pjIoBase, CRTC_INDEX, (pbp->ulExtendedDacControl | 0x0100));
  221. OUTP(pjIoBase, BT485_ADDR_CMD_REG0, pbp->jCommandRegister0);
  222. // Set the colour 1 and colour 2 for the pointer. Select address
  223. // register; pointer/overscan color write on the Bt485.
  224. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl | 0x0100);
  225. OUTP(pjIoBase, BT485_ADDR_CUR_COLOR_WRITE, BT485_CURSOR_COLOR_1);
  226. // Output the RGB for pointer colour 1 (black):
  227. OUTP(pjIoBase, BT485_CUR_COLOR_DATA, 0x00);
  228. OUTP(pjIoBase, BT485_CUR_COLOR_DATA, 0x00);
  229. OUTP(pjIoBase, BT485_CUR_COLOR_DATA, 0x00);
  230. // Output the RGB for pointer colour 2 (white):
  231. OUTP(pjIoBase, BT485_CUR_COLOR_DATA, 0xff);
  232. OUTP(pjIoBase, BT485_CUR_COLOR_DATA, 0xff);
  233. OUTP(pjIoBase, BT485_CUR_COLOR_DATA, 0xff);
  234. // Reset the DAC control register:
  235. OUTPW(pjIoBase, CRTC_INDEX, pbp->ulExtendedDacControl);
  236. }
  237. }
  238. /******************************Public*Routine******************************\
  239. * VOID vShowPointerTi025
  240. *
  241. * Show or hide the TI 025 hardware pointer.
  242. *
  243. \**************************************************************************/
  244. VOID vShowPointerTi025(
  245. PDEV* ppdev,
  246. TI025_POINTER_DATA* ptp,
  247. BOOL bShow)
  248. {
  249. BYTE* pjIoBase = ppdev->pjIoBase;
  250. BYTE jDacControl;
  251. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl | 0x0100);
  252. OUTP(pjIoBase, 0x3c6, 6);
  253. jDacControl = INP(pjIoBase, 0x3c7);
  254. if (bShow)
  255. jDacControl |= 0x40;
  256. else
  257. {
  258. jDacControl &= ~0x40;
  259. // Move the hardware pointer off-screen so that it doesn't flash
  260. // in the old position when we finally turn it back on:
  261. OUTP(pjIoBase, 0x3c6, 0);
  262. OUTP(pjIoBase, 0x3c7, 0);
  263. OUTP(pjIoBase, 0x3c6, 1);
  264. OUTP(pjIoBase, 0x3c7, 0);
  265. OUTP(pjIoBase, 0x3c6, 2);
  266. OUTP(pjIoBase, 0x3c7, 1663); // A 'y' value of 1600 should be enough...
  267. OUTP(pjIoBase, 0x3c6, 3);
  268. OUTP(pjIoBase, 0x3c7, (1663 >> 8));
  269. }
  270. OUTP(pjIoBase, 0x3c6, 6);
  271. OUTP(pjIoBase, 0x3c7, jDacControl);
  272. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl);
  273. }
  274. /******************************Public*Routine******************************\
  275. * VOID vMovePointerTi025
  276. *
  277. * Move the TI 025 hardware pointer.
  278. *
  279. \**************************************************************************/
  280. VOID vMovePointerTi025(
  281. PDEV* ppdev,
  282. TI025_POINTER_DATA* ptp,
  283. LONG x,
  284. LONG y)
  285. {
  286. BYTE* pjIoBase = ppdev->pjIoBase;
  287. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl | 0x0100);
  288. OUTP(pjIoBase, 0x3c6, 0);
  289. OUTP(pjIoBase, 0x3c7, (x));
  290. OUTP(pjIoBase, 0x3c6, 1);
  291. OUTP(pjIoBase, 0x3c7, (x >> 8));
  292. OUTP(pjIoBase, 0x3c6, 2);
  293. OUTP(pjIoBase, 0x3c7, (y));
  294. OUTP(pjIoBase, 0x3c6, 3);
  295. OUTP(pjIoBase, 0x3c7, (y >> 8));
  296. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl);
  297. }
  298. /******************************Public*Routine******************************\
  299. * BOOL bSetPointerShapeTi025
  300. *
  301. * Set the TI 025 hardware pointer shape.
  302. *
  303. * Don't do word outs to the DAC because they may not be performed correctly
  304. * on some ISA machines.
  305. *
  306. \**************************************************************************/
  307. BOOL bSetPointerShapeTi025(
  308. PDEV* ppdev,
  309. TI025_POINTER_DATA* ptp,
  310. LONG x, // If -1, pointer should be created hidden
  311. LONG y,
  312. LONG xHot,
  313. LONG yHot,
  314. LONG cx,
  315. LONG cy,
  316. BYTE* pjShape)
  317. {
  318. BYTE* pjIoBase = ppdev->pjIoBase;
  319. LONG i;
  320. DWORD dwShape;
  321. LONG cShift;
  322. WORD wMask;
  323. WORD wAnd;
  324. WORD wXor;
  325. BYTE jDacControl;
  326. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl | 0x0100);
  327. // Hide the pointer, otherwise it will show random garbage when
  328. // animating cursors on the TI 020 DAC.
  329. OUTP(pjIoBase, 0x3c6, 6);
  330. jDacControl = INP(pjIoBase, 0x3c7);
  331. jDacControl &= ~0x40;
  332. OUTP(pjIoBase, 0x3c7, jDacControl);
  333. // Set the pointer hot-spot offset:
  334. OUTP(pjIoBase, 0x3c6, 4);
  335. OUTP(pjIoBase, 0x3c7, xHot);
  336. OUTP(pjIoBase, 0x3c6, 5);
  337. OUTP(pjIoBase, 0x3c7, yHot);
  338. // Download the pointer shape. Do the OUTs for downloading the
  339. // pointer data slowly -- don't use REP OUTSB.
  340. OUTP(pjIoBase, 0x3c6, 8);
  341. OUTP(pjIoBase, 0x3c7, 0);
  342. OUTP(pjIoBase, 0x3c6, 9);
  343. OUTP(pjIoBase, 0x3c7, 0); // Start with pixel 0 of the pointer
  344. OUTP(pjIoBase, 0x3c6, 10); // Get ready for downloading
  345. for (i = 256; i != 0; i--)
  346. {
  347. // Every time through this loop we'll handle one AND word and one
  348. // XOR word of the pointer data (which is good because the S3
  349. // display driver gives us the pointer shape in 'pjShape' such that
  350. // it starts with the first AND word, followed by the first XOR
  351. // word, followed by the second AND word, etc.)
  352. dwShape = 0;
  353. // The AND word is first. Don't forget about endianness...
  354. wAnd = (*(pjShape) << 8) | *(pjShape + 1);
  355. for (wMask = 0x8000, cShift = 16; wMask != 0; wMask >>= 1, cShift--)
  356. {
  357. dwShape |= ((wAnd & wMask) << cShift);
  358. }
  359. // The XOR word is next. Don't forget about endianness...
  360. wXor = (*(pjShape + 2) << 8) | *(pjShape + 3);
  361. for (wMask = 0x8000, cShift = 15; wMask != 0; wMask >>= 1, cShift--)
  362. {
  363. dwShape |= ((wXor & wMask) << cShift);
  364. }
  365. // We've now interleaved the AND and XOR words into a dword such
  366. // that if the AND word bits are ABC... and the XOR word bits are
  367. // 123..., the resulting dword will be A1B2C3...
  368. OUTP(pjIoBase, 0x3c7, (dwShape >> 24));
  369. OUTP(pjIoBase, 0x3c7, (dwShape >> 16));
  370. OUTP(pjIoBase, 0x3c7, (dwShape >> 8));
  371. OUTP(pjIoBase, 0x3c7, (dwShape));
  372. // Advance to next AND/XOR word pair:
  373. pjShape += 4;
  374. }
  375. if (x != -1)
  376. {
  377. // Set the position of the pointer:
  378. OUTP(pjIoBase, 0x3c6, 0);
  379. OUTP(pjIoBase, 0x3c7, (x));
  380. OUTP(pjIoBase, 0x3c6, 1);
  381. OUTP(pjIoBase, 0x3c7, (x >> 8));
  382. OUTP(pjIoBase, 0x3c6, 2);
  383. OUTP(pjIoBase, 0x3c7, (y));
  384. OUTP(pjIoBase, 0x3c6, 3);
  385. OUTP(pjIoBase, 0x3c7, (y >> 8));
  386. // Show the pointer:
  387. OUTP(pjIoBase, 0x3c6, 6);
  388. OUTP(pjIoBase, 0x3c7, jDacControl | 0x40);
  389. }
  390. else
  391. {
  392. // Move the hardware pointer off-screen so that it doesn't flash
  393. // in the old position when we finally turn it back on:
  394. OUTP(pjIoBase, 0x3c6, 0);
  395. OUTP(pjIoBase, 0x3c7, 0);
  396. OUTP(pjIoBase, 0x3c6, 1);
  397. OUTP(pjIoBase, 0x3c7, 0);
  398. OUTP(pjIoBase, 0x3c6, 2);
  399. OUTP(pjIoBase, 0x3c7, 1663); // A 'y' value of 1600 should be enough...
  400. OUTP(pjIoBase, 0x3c6, 3);
  401. OUTP(pjIoBase, 0x3c7, (1663 >> 8));
  402. }
  403. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl);
  404. // Reset DAC read mask to 0xff:
  405. OUTP(pjIoBase, 0x3c6, 0xff);
  406. return(TRUE);
  407. }
  408. /******************************Public*Routine******************************\
  409. * VOID vEnablePointerTi025
  410. *
  411. * Get the hardware ready to use the TI 025 hardware pointer.
  412. *
  413. * Don't do word outs to the DAC because they may not be performed correctly
  414. * on some ISA machines.
  415. *
  416. \**************************************************************************/
  417. VOID vEnablePointerTi025(
  418. PDEV* ppdev,
  419. TI025_POINTER_DATA* ptp,
  420. BOOL bFirst)
  421. {
  422. BYTE* pjIoBase = ppdev->pjIoBase;
  423. BYTE jMode;
  424. BYTE jDacControl;
  425. // Make a copy of the extended DAC control register:
  426. OUTP(pjIoBase, CRTC_INDEX, EX_DAC_CT);
  427. ptp->ulExtendedDacControl = ((INP(pjIoBase, CRTC_DATA) << 8) | EX_DAC_CT) & ~0x0300;
  428. // Disable the DAC's Bt485 emulation so that we can use the TI hardware
  429. // pointer.
  430. OUTP(pjIoBase, CRTC_INDEX, 0x5C);
  431. jMode = INP(pjIoBase, CRTC_DATA);
  432. OUTP(pjIoBase, CRTC_DATA, jMode & ~0x20); // Select TI mode in the DAC
  433. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl | 0x0100);
  434. OUTP(pjIoBase, 0x3c6, 6);
  435. jDacControl = INP(pjIoBase, 0x3c7);
  436. OUTP(pjIoBase, 0x3c7, jDacControl & 0x7f); // Set to TI mode (non planar)
  437. // Set the pointer colours to black and white.
  438. OUTP(pjIoBase, 0x3c6, 0x26);
  439. OUTP(pjIoBase, 0x3c7, 0xff); // Foreground red component
  440. OUTP(pjIoBase, 0x3c6, 0x27);
  441. OUTP(pjIoBase, 0x3c7, 0xff); // Foreground green component
  442. OUTP(pjIoBase, 0x3c6, 0x28);
  443. OUTP(pjIoBase, 0x3c7, 0xff); // Foreground blue component
  444. OUTP(pjIoBase, 0x3c6, 0x23);
  445. OUTP(pjIoBase, 0x3c7, 0x00); // Background red component
  446. OUTP(pjIoBase, 0x3c6, 0x24);
  447. OUTP(pjIoBase, 0x3c7, 0x00); // Background green component
  448. OUTP(pjIoBase, 0x3c6, 0x25);
  449. OUTP(pjIoBase, 0x3c7, 0x00); // Background blue component
  450. OUTPW(pjIoBase, CRTC_INDEX, ptp->ulExtendedDacControl);
  451. OUTP(pjIoBase, 0x3c6, 0xff); // Reset DAC read mask to 0xff
  452. // Note that we don't have to bother hiding the pointer, because
  453. // vShowPointer will be called immediately...
  454. }
  455. /******************************Public*Routine******************************\
  456. * VOID vShowPointerS3
  457. *
  458. * Show or hide the S3 hardware pointer.
  459. *
  460. * We hide the pointer by making it only one row high (we always reserve
  461. * the bottom scan of the pointer shape to be invisible). We do it this
  462. * way because we ran into problems doing it with any other method:
  463. *
  464. * 1. Disabling the hardware pointer via register CR45 will hang
  465. * 80x/928/864 chips if it is done at exactly the wrong time during
  466. * the horizontal retrace. It's is not safe to wait for vertical
  467. * blank and do it then, because we're a user mode process and
  468. * could get context switched after doing the wait but before setting
  469. * the bit.
  470. *
  471. * 2. Simply changing the pointer position to move it off-screen works,
  472. * but is not a good solution because the pointer position is latched
  473. * by the hardware, and it usually takes a couple of frames for the
  474. * new position to take effect (which causes the pointer to jump even
  475. * more than it currently does).
  476. *
  477. * 3. Using registers CR4C and CR4D to switch to a pre-defined 'invisible'
  478. * pointer also worked, but still caused machines to crash with the
  479. * same symptoms as from solution 1 (although it was somewhat more
  480. * rare).
  481. *
  482. \**************************************************************************/
  483. VOID vShowPointerS3(
  484. PDEV* ppdev,
  485. BOOL bShow) // If TRUE, show the pointer. If FALSE, hide the pointer.
  486. {
  487. BYTE* pjIoBase = ppdev->pjIoBase;
  488. LONG x;
  489. LONG y;
  490. LONG dx;
  491. LONG dy;
  492. // If we don't wait for vertical retrace here, the S3 sometimes ignores
  493. // the setting of the new pointer position:
  494. while (INP(pjIoBase, STATUS_1) & VBLANK_ACTIVE)
  495. ; // Wait for bit 3 to become 0
  496. while (!(INP(pjIoBase, STATUS_1) & VBLANK_ACTIVE))
  497. ; // Wait for bit 3 to become 1
  498. if (bShow)
  499. {
  500. // Make the hardware pointer visible:
  501. x = ppdev->xPointer;
  502. y = ppdev->yPointer;
  503. dx = ppdev->dxPointer;
  504. dy = ppdev->dyPointer;
  505. }
  506. else
  507. {
  508. // Move the hardware pointer off-screen so that it doesn't flash
  509. // in the old position when we finally turn it back on:
  510. x = ppdev->cxScreen + 64;
  511. y = ppdev->cyScreen + 64;
  512. dx = 0;
  513. dy = HW_POINTER_HIDE;
  514. }
  515. // Note that due to register shadowing, these OUTs should be done
  516. // in a specific order, otherwise you may get a flashing pointer:
  517. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGX_MSB | ((x >> 8) << 8));
  518. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGX_LSB | ((x & 0xff) << 8));
  519. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGY_LSB | ((y & 0xff) << 8));
  520. OUTPW(pjIoBase, CRTC_INDEX, HGC_DX | ((dx) << 8));
  521. OUTPW(pjIoBase, CRTC_INDEX, HGC_DY | ((dy) << 8));
  522. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGY_MSB | ((y >> 8) << 8));
  523. }
  524. /******************************Public*Routine******************************\
  525. * VOID vMovePointerS3
  526. *
  527. * Move the S3 hardware pointer.
  528. *
  529. \**************************************************************************/
  530. VOID vMovePointerS3(
  531. PDEV* ppdev,
  532. LONG x,
  533. LONG y)
  534. {
  535. BYTE* pjIoBase = ppdev->pjIoBase;
  536. LONG dx;
  537. LONG dy;
  538. // 'dx' and 'dy' are the offsets into the pointer bitmap at which
  539. // the hardware is supposed to start drawing, when the pointer is
  540. // along the left or top edge and needs to be clipped:
  541. x -= ppdev->xPointerHot;
  542. y -= ppdev->yPointerHot;
  543. dx = 0;
  544. dy = 0;
  545. if (x <= 0)
  546. {
  547. dx = -x;
  548. x = 0;
  549. }
  550. if (y <= 0)
  551. {
  552. dy = -y;
  553. y = 0;
  554. }
  555. // Account for pointer position scaling in high-colour modes:
  556. x <<= ppdev->cPointerShift;
  557. ppdev->dxPointer = dx;
  558. ppdev->dyPointer = dy;
  559. ppdev->xPointer = x;
  560. ppdev->yPointer = y;
  561. // Note that due to register shadowing, these OUTs should be done
  562. // in a specific order, otherwise you may get a flashing pointer:
  563. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGX_MSB | ((x >> 8) << 8));
  564. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGX_LSB | ((x & 0xff) << 8));
  565. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGY_LSB | ((y & 0xff) << 8));
  566. OUTPW(pjIoBase, CRTC_INDEX, HGC_DX | ((dx) << 8));
  567. OUTPW(pjIoBase, CRTC_INDEX, HGC_DY | ((dy) << 8));
  568. OUTPW(pjIoBase, CRTC_INDEX, HGC_ORGY_MSB | ((y >> 8) << 8));
  569. }
  570. /******************************Public*Routine******************************\
  571. * VOID vSetPointerShapeS3
  572. *
  573. \**************************************************************************/
  574. VOID vSetPointerShapeS3(
  575. SURFOBJ* pso,
  576. LONG x, // Relative coordinates
  577. LONG y, // Relative coordinates
  578. LONG xHot,
  579. LONG yHot,
  580. BYTE* pjShape,
  581. FLONG fl)
  582. {
  583. BYTE* pjIoBase;
  584. PDEV* ppdev;
  585. ULONG* pulSrc;
  586. ULONG* pulDst;
  587. LONG i;
  588. ppdev = (PDEV*) pso->dhpdev;
  589. pjIoBase = ppdev->pjIoBase;
  590. // 1. Hide the current pointer.
  591. if (!(fl & SPS_ANIMATEUPDATE))
  592. {
  593. // Hide the pointer to try and lessen the jumpiness when the
  594. // new shape has a different hot spot. We don't hide the
  595. // pointer while animating, because that definitely causes
  596. // flashing:
  597. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  598. OUTPW(pjIoBase, CRTC_INDEX, HGC_DY | (HW_POINTER_HIDE << 8));
  599. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  600. }
  601. // 2. Wait until the vertical retrace is done.
  602. // --
  603. //
  604. // If we don't wait for vertical retrace here, the S3 sometimes ignores
  605. // the setting of the new pointer position:
  606. while (INP(pjIoBase, STATUS_1) & VBLANK_ACTIVE)
  607. ; // Wait for bit 3 to become 0
  608. while (!(INP(pjIoBase, STATUS_1) & VBLANK_ACTIVE))
  609. ; // Wait for bit 3 to become 1
  610. // 3. Set the new pointer position.
  611. // --
  612. ppdev->xPointerHot = xHot;
  613. ppdev->yPointerHot = yHot;
  614. DrvMovePointer(pso, x, y, NULL); // Note: Must pass relative coordinates!
  615. // 4. Download the new pointer shape.
  616. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  617. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  618. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, ppdev->iPointerBank);
  619. pulSrc = (ULONG*) pjShape;
  620. pulDst = (ULONG*) ppdev->pvPointerShape;
  621. if (DIRECT_ACCESS(ppdev))
  622. {
  623. for (i = HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i != 0; i--)
  624. {
  625. *pulDst++ = *pulSrc++;
  626. }
  627. }
  628. else
  629. {
  630. for (i = HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i != 0; i--)
  631. {
  632. WRITE_REGISTER_ULONG(pulDst, *pulSrc);
  633. pulSrc++;
  634. pulDst++;
  635. }
  636. }
  637. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  638. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  639. }
  640. /******************************Public*Routine******************************\
  641. * VOID DrvMovePointer
  642. *
  643. * NOTE: Because we have set GCAPS_ASYNCMOVE, this call may occur at any
  644. * time, even while we're executing another drawing call!
  645. *
  646. * Consequently, we have to explicitly synchronize any shared
  647. * resources. In our case, since we touch the CRTC register here
  648. * and in the banking code, we synchronize access using a critical
  649. * section.
  650. *
  651. \**************************************************************************/
  652. VOID DrvMovePointer(
  653. SURFOBJ* pso,
  654. LONG x,
  655. LONG y,
  656. RECTL* prcl)
  657. {
  658. PDEV* ppdev;
  659. ppdev = (PDEV*) pso->dhpdev;
  660. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  661. if (x != -1)
  662. {
  663. if (ppdev->flCaps & CAPS_DAC_POINTER)
  664. {
  665. ppdev->pfnMovePointer(ppdev, ppdev->pvPointerData, x, y);
  666. }
  667. else
  668. {
  669. vMovePointerS3(ppdev, x, y);
  670. }
  671. if (!ppdev->bHwPointerActive)
  672. {
  673. // We have to make the pointer visible:
  674. ppdev->bHwPointerActive = TRUE;
  675. if (ppdev->flCaps & CAPS_DAC_POINTER)
  676. {
  677. ppdev->pfnShowPointer(ppdev, ppdev->pvPointerData, TRUE);
  678. }
  679. else
  680. {
  681. vShowPointerS3(ppdev, TRUE);
  682. }
  683. }
  684. }
  685. else
  686. {
  687. if (ppdev->bHwPointerActive)
  688. {
  689. // The pointer is visible, and we've been asked to hide it:
  690. ppdev->bHwPointerActive = FALSE;
  691. if (ppdev->flCaps & CAPS_DAC_POINTER)
  692. {
  693. ppdev->pfnShowPointer(ppdev, ppdev->pvPointerData, FALSE);
  694. }
  695. else
  696. {
  697. vShowPointerS3(ppdev, FALSE);
  698. }
  699. }
  700. }
  701. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  702. // Note that we don't have to modify 'prcl', since we have a
  703. // NOEXCLUDE pointer...
  704. }
  705. /******************************Public*Routine******************************\
  706. * VOID DrvSetPointerShape
  707. *
  708. * Sets the new pointer shape.
  709. *
  710. \**************************************************************************/
  711. ULONG DrvSetPointerShape(
  712. SURFOBJ* pso,
  713. SURFOBJ* psoMsk,
  714. SURFOBJ* psoColor,
  715. XLATEOBJ* pxlo,
  716. LONG xHot,
  717. LONG yHot,
  718. LONG x,
  719. LONG y,
  720. RECTL* prcl,
  721. FLONG fl)
  722. {
  723. PDEV* ppdev;
  724. DWORD* pul;
  725. ULONG cx;
  726. ULONG cy;
  727. LONG i;
  728. LONG j;
  729. BYTE* pjSrcScan;
  730. BYTE* pjDstScan;
  731. LONG lSrcDelta;
  732. LONG lDstDelta;
  733. WORD* pwSrc;
  734. WORD* pwDst;
  735. LONG cwWhole;
  736. BOOL bAccept;
  737. BYTE ajBuf[HW_POINTER_TOTAL_SIZE];
  738. ppdev = (PDEV*) pso->dhpdev;
  739. // When CAPS_SW_POINTER is set, we have no hardware pointer available,
  740. // so we always ask GDI to simulate the pointer for us, using
  741. // DrvCopyBits calls:
  742. if (ppdev->flCaps & CAPS_SW_POINTER)
  743. return(SPS_DECLINE);
  744. // We're not going to handle any colour pointers, pointers that
  745. // are larger than our hardware allows, or flags that we don't
  746. // understand.
  747. //
  748. // (Note that the spec says we should decline any flags we don't
  749. // understand, but we'll actually be declining if we don't see
  750. // the only flag we *do* understand...)
  751. //
  752. // Our old documentation says that 'psoMsk' may be NULL, which means
  753. // that the pointer is transparent. Well, trust me, that's wrong.
  754. // I've checked GDI's code, and it will never pass us a NULL psoMsk:
  755. cx = psoMsk->sizlBitmap.cx; // Note that 'sizlBitmap.cy' accounts
  756. cy = psoMsk->sizlBitmap.cy >> 1; // for the double height due to the
  757. // inclusion of both the AND masks
  758. // and the XOR masks. For now, we're
  759. // only interested in the true
  760. // pointer dimensions, so we divide
  761. // by 2.
  762. // We reserve the bottom scan of the pointer shape and keep it
  763. // empty so that we can hide the pointer by changing the S3's
  764. // display start y-pixel position register to show only the bottom
  765. // scan of the pointer shape:
  766. if ((cx > HW_POINTER_DIMENSION) ||
  767. (cy > (HW_POINTER_DIMENSION - 1)) ||
  768. (psoColor != NULL) ||
  769. !(fl & SPS_CHANGE) ||
  770. (cx & 0x7)) // make sure cx is a multiple of 8 (byte aligned).
  771. {
  772. goto HideAndDecline;
  773. }
  774. ASSERTDD(psoMsk != NULL, "GDI gave us a NULL psoMsk. It can't do that!");
  775. //ASSERTDD(pso->iType == STYPE_DEVICE, "GDI gave us a weird surface");
  776. if ((cx <= (HW_POINTER_DIMENSION / 2)) &&
  777. !(ppdev->flCaps & CAPS_DAC_POINTER) &&
  778. (ppdev->flCaps & CAPS_NEW_MMIO))
  779. {
  780. return( NewMmIoSetPointerShape(
  781. ppdev,
  782. psoMsk,
  783. psoColor,
  784. pxlo,
  785. xHot,
  786. yHot,
  787. x,
  788. y,
  789. prcl,
  790. fl,
  791. ajBuf
  792. ));
  793. }
  794. pul = (ULONG*) &ajBuf[0];
  795. for (i = HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i != 0; i--)
  796. {
  797. // Here we initialize the entire pointer work buffer to be
  798. // transparent (the S3 has no means of specifying a pointer size
  799. // other than 64 x 64 -- so if we're asked to draw a 32 x 32
  800. // pointer, we want the unused portion to be transparent).
  801. //
  802. // The S3's hardware pointer is defined by an interleaved pattern
  803. // of AND words and XOR words. So a totally transparent pointer
  804. // starts off with the word 0xffff, followed by the word 0x0000,
  805. // followed by 0xffff, etc.. Since we're a little endian system,
  806. // this is simply the repeating dword '0x0000ffff'.
  807. //
  808. // The compiler is nice enough to optimize this into a REP STOSD
  809. // for us:
  810. *pul++ = 0x0000ffff;
  811. }
  812. // Now we're going to take the requested pointer AND masks and XOR
  813. // masks and combine them into our work buffer, being careful of
  814. // the edges so that we don't disturb the transparency when the
  815. // requested pointer size is not a multiple of 16.
  816. //
  817. // 'psoMsk' is actually cy * 2 scans high; the first 'cy' scans
  818. // define the AND mask. So we start with that:
  819. pjSrcScan = psoMsk->pvScan0;
  820. lSrcDelta = psoMsk->lDelta;
  821. pjDstScan = &ajBuf[0]; // Start with first AND word
  822. lDstDelta = HW_POINTER_DIMENSION / 4;// Every 8 pels is one AND/XOR word
  823. cwWhole = cx / 16; // Each word accounts for 16 pels
  824. for (i = cy; i != 0; i--)
  825. {
  826. pwSrc = (WORD*) pjSrcScan;
  827. pwDst = (WORD*) pjDstScan;
  828. for (j = cwWhole; j != 0; j--)
  829. {
  830. *pwDst = *pwSrc;
  831. pwSrc += 1; // Go to next word in source mask
  832. pwDst += 2; // Skip over the XOR word in the dest mask
  833. }
  834. pjSrcScan += lSrcDelta;
  835. pjDstScan += lDstDelta;
  836. }
  837. // Now handle the XOR mask:
  838. pjDstScan = &ajBuf[2]; // Start with first XOR word
  839. for (i = cy; i != 0; i--)
  840. {
  841. pwSrc = (WORD*) pjSrcScan;
  842. pwDst = (WORD*) pjDstScan;
  843. for (j = cwWhole; j != 0; j--)
  844. {
  845. *pwDst = *pwSrc;
  846. pwSrc += 1; // Go to next word in source mask
  847. pwDst += 2; // Skip over the AND word in the dest mask
  848. }
  849. pjSrcScan += lSrcDelta;
  850. pjDstScan += lDstDelta;
  851. }
  852. // Okay, I admit it -- I'm wildly inconsistent here. I pass
  853. // absolute (x, y) coordinates to pfnSetPointerShape, but pass
  854. // relative (x, y) coordinates to vSetPointerShapeS3. I would
  855. // clean this all up, but we're too close to shipping. LATER!
  856. if (ppdev->flCaps & CAPS_DAC_POINTER)
  857. {
  858. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  859. bAccept = ppdev->pfnSetPointerShape(ppdev, ppdev->pvPointerData, x, y,
  860. xHot, yHot, cx, cy, &ajBuf[0]);
  861. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  862. ppdev->bHwPointerActive = (x != -1);
  863. if (!bAccept)
  864. goto HideAndDecline;
  865. }
  866. else
  867. {
  868. vSetPointerShapeS3(pso, x, y, xHot, yHot, &ajBuf[0], fl);
  869. }
  870. // Since it's a hardware pointer, GDI doesn't have to worry about
  871. // overwriting the pointer on drawing operations (meaning that it
  872. // doesn't have to exclude the pointer), so we return 'NOEXCLUDE'.
  873. // Since we're returning 'NOEXCLUDE', we also don't have to update
  874. // the 'prcl' that GDI passed us.
  875. return(SPS_ACCEPT_NOEXCLUDE);
  876. HideAndDecline:
  877. // Since we're declining the new pointer, GDI will simulate it via
  878. // DrvCopyBits calls. So we should really hide the old hardware
  879. // pointer if it's visible. We can get DrvMovePointer to do this
  880. // for us:
  881. DrvMovePointer(pso, -1, -1, NULL);
  882. return(SPS_DECLINE);
  883. }
  884. /******************************Public*Routine******************************\
  885. * VOID vDisablePointer
  886. *
  887. \**************************************************************************/
  888. VOID vDisablePointer(
  889. PDEV* ppdev)
  890. {
  891. // Nothing to do, really
  892. }
  893. /******************************Public*Routine******************************\
  894. * VOID vAssertModePointer
  895. *
  896. \**************************************************************************/
  897. VOID vAssertModePointer(
  898. PDEV* ppdev,
  899. BOOL bEnable)
  900. {
  901. ULONG* pulDst;
  902. LONG i;
  903. LONG lPointerShape;
  904. // We will turn any hardware pointer -- either in the S3 or in the
  905. // DAC -- off to begin with:
  906. ppdev->bHwPointerActive = FALSE;
  907. if (ppdev->flCaps & CAPS_SW_POINTER)
  908. {
  909. // With a software pointer, we don't have to do anything.
  910. }
  911. else if (ppdev->flCaps & CAPS_DAC_POINTER)
  912. {
  913. // Hide the DAC pointer:
  914. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  915. // hide the pointer by moving offscreen
  916. ppdev->pfnShowPointer(ppdev, ppdev->pvPointerData, FALSE);
  917. // but enable the pointer registers
  918. ppdev->pfnEnablePointer(ppdev, ppdev->pvPointerData, TRUE);
  919. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  920. }
  921. else
  922. {
  923. // We're using the built-in hardware pointer:
  924. if (bEnable)
  925. {
  926. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  927. ppdev->cPointerShift = 0;
  928. if (ppdev->iBitmapFormat > BMF_8BPP)
  929. {
  930. // Initializing the pointer colours is a bit different
  931. // for high-colour modes:
  932. if (ppdev->flCaps & CAPS_SCALE_POINTER)
  933. {
  934. ppdev->cPointerShift = 1;
  935. ppdev->ulHwGraphicsCursorModeRegister_45 |= (0x4 << 8);
  936. }
  937. }
  938. // We download an invisible pointer shape because we're about
  939. // to enable the hardware pointer, but we still want the
  940. // pointer hidden until we get the first DrvSetPointerShape
  941. // call:
  942. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_ON);
  943. ppdev->pfnBankMap(ppdev, ppdev->pvBankData, ppdev->iPointerBank);
  944. pulDst = (ULONG*) ppdev->pvPointerShape;
  945. if (DIRECT_ACCESS(ppdev))
  946. {
  947. for (i = HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i != 0; i--)
  948. {
  949. *pulDst++ = 0x0000ffff;
  950. }
  951. }
  952. else
  953. {
  954. for (i = HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i != 0; i--)
  955. {
  956. WRITE_REGISTER_ULONG(pulDst, 0x0000ffff);
  957. pulDst++;
  958. }
  959. }
  960. ppdev->pfnBankSelectMode(ppdev, ppdev->pvBankData, BANK_OFF);
  961. // Point the S3 to where we're storing the pointer shape.
  962. // The location is specified as a multiple of 1024:
  963. lPointerShape = ppdev->cjPointerOffset / 1024;
  964. OUTPW(ppdev->pjIoBase, CRTC_INDEX, CR4C | ((lPointerShape >> 8) << 8));
  965. OUTPW(ppdev->pjIoBase, CRTC_INDEX, CR4D | ((lPointerShape & 0xff) << 8));
  966. // Now hide it by moving it off-screen:
  967. vShowPointerS3(ppdev, FALSE);
  968. // Enable the hardware pointer. As per the 8/31/93 Design
  969. // Alert from S3 Incorporated, there's a goofy bug in all
  970. // S3 chips up to the 928 where writing to this register
  971. // at the same time as a horizontal sync may cause the
  972. // chip to crash. So we wait for the vertical sync to be safe.
  973. //
  974. // Note that since we're a preemptive multitasking
  975. // operating system, the following code is not guaranteed
  976. // to be safe. To do that, we would have to put this in
  977. // the miniport, where we could disable all interrupts while
  978. // we wait for the vertical sync.
  979. //
  980. // However, this is only ever executed once at initialization
  981. // and every time full-screen is executed, so I would expect
  982. // the chances of there still being a problem to be extremely
  983. // small:
  984. while (INP(ppdev->pjIoBase, STATUS_1) & VBLANK_ACTIVE)
  985. ; // Wait for bit 3 to become 0
  986. while (!(INP(ppdev->pjIoBase, STATUS_1) & VBLANK_ACTIVE))
  987. ; // Wait for bit 3 to become 1
  988. OUTPW(ppdev->pjIoBase, CRTC_INDEX,
  989. ppdev->ulHwGraphicsCursorModeRegister_45 | (HGC_ENABLE << 8));
  990. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  991. }
  992. }
  993. }
  994. /******************************Public*Routine******************************\
  995. * BOOL bEnablePointer
  996. *
  997. \**************************************************************************/
  998. BOOL bEnablePointer(
  999. PDEV* ppdev)
  1000. {
  1001. RECTL rclDraw;
  1002. RECTL rclBank;
  1003. LONG iBank;
  1004. LONG cjOffset;
  1005. LONG cjOffsetInBank;
  1006. if (ppdev->flCaps & CAPS_SW_POINTER)
  1007. {
  1008. // With a software pointer, we don't have to do anything.
  1009. }
  1010. else if (ppdev->flCaps & CAPS_DAC_POINTER)
  1011. {
  1012. // Initialize the DAC pointer:
  1013. if (ppdev->flCaps & CAPS_BT485_POINTER)
  1014. {
  1015. ppdev->pfnShowPointer = vShowPointerBt485;
  1016. ppdev->pfnMovePointer = vMovePointerBt485;
  1017. ppdev->pfnSetPointerShape = bSetPointerShapeBt485;
  1018. ppdev->pfnEnablePointer = vEnablePointerBt485;
  1019. }
  1020. else
  1021. {
  1022. ASSERTDD(ppdev->flCaps & CAPS_TI025_POINTER,
  1023. "A new DAC type was added?");
  1024. ppdev->pfnShowPointer = vShowPointerTi025;
  1025. ppdev->pfnMovePointer = vMovePointerTi025;
  1026. ppdev->pfnSetPointerShape = bSetPointerShapeTi025;
  1027. ppdev->pfnEnablePointer = vEnablePointerTi025;
  1028. }
  1029. ppdev->pvPointerData = &ppdev->ajPointerData[0];
  1030. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1031. ppdev->pfnEnablePointer(ppdev, ppdev->pvPointerData, TRUE);
  1032. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1033. }
  1034. else
  1035. {
  1036. // Enable the S3 hardware pointer.
  1037. // We're going to assume that the pointer shape doesn't span
  1038. // more than one bank. We have to figure out what bank that
  1039. // will be, and so we call 'pfnBankCompute' with the start
  1040. // point:
  1041. rclDraw.left = rclDraw.right = ppdev->xPointerShape;
  1042. rclDraw.top = rclDraw.bottom = ppdev->yPointerShape;
  1043. ppdev->pfnBankCompute(ppdev, &rclDraw, &rclBank, &cjOffset, &iBank);
  1044. cjOffsetInBank = ppdev->cjPointerOffset - cjOffset;
  1045. ASSERTDD(cjOffsetInBank + HW_POINTER_TOTAL_SIZE <= ppdev->cjBank,
  1046. "SetPointerShape assumes pointer shape doesn't span banks");
  1047. // When bank 'iPointerBank' is mapped in, 'pvPointerShape' is the
  1048. // actual pointer to be the beginning of the pointer shape bits
  1049. // in off-screen memory:
  1050. ppdev->pvPointerShape = ppdev->pjScreen + cjOffsetInBank;
  1051. ppdev->iPointerBank = iBank;
  1052. // Get a copy of the current register '45' state, so that whenever
  1053. // we enable or disable the S3 hardware pointer, we don't have to
  1054. // do a read-modify-write on this register:
  1055. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1056. OUTP(ppdev->pjIoBase, CRTC_INDEX, HGC_MODE);
  1057. ppdev->ulHwGraphicsCursorModeRegister_45
  1058. = ((INP(ppdev->pjIoBase, CRTC_DATA) << 8) | HGC_MODE) & ~(HGC_ENABLE << 8);
  1059. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1060. }
  1061. // Actually turn on the pointer:
  1062. vAssertModePointer(ppdev, TRUE);
  1063. DISPDBG((5, "Passed bEnablePointer"));
  1064. return(TRUE);
  1065. }
  1066. /******************************Public*Routine******************************\
  1067. *
  1068. * Sets the new pointer shape.
  1069. *
  1070. \**************************************************************************/
  1071. ULONG NewMmIoSetPointerShape(
  1072. PDEV* ppdev,
  1073. SURFOBJ* psoMsk,
  1074. SURFOBJ* psoColor,
  1075. XLATEOBJ* pxlo,
  1076. LONG xHot,
  1077. LONG yHot,
  1078. LONG x,
  1079. LONG y,
  1080. RECTL* prcl,
  1081. FLONG fl,
  1082. BYTE* pBuf)
  1083. {
  1084. ULONG cx;
  1085. ULONG cy;
  1086. LONG i;
  1087. LONG j;
  1088. BYTE* pjSrcScan;
  1089. BYTE* pjDstScan;
  1090. LONG lSrcDelta;
  1091. LONG lDstDelta;
  1092. WORD* pwSrc;
  1093. WORD* pwDst;
  1094. BYTE* pbSrc;
  1095. BYTE* pbDst;
  1096. ULONG* pulDst;
  1097. ULONG* pulSrc;
  1098. LONG cxWhole;
  1099. LONG xHotWordBnd;
  1100. ULONG ulTransp = 0xFFFF0000L;
  1101. ULONG ulData, ulPreviousData;
  1102. UCHAR ucTemp;
  1103. // We're not going to handle any colour pointers, pointers that
  1104. // are larger than our hardware allows, or flags that we don't
  1105. // understand.
  1106. //
  1107. // (Note that the spec says we should decline any flags we don't
  1108. // understand, but we'll actually be declining if we don't see
  1109. // the only flag we *do* understand...)
  1110. //
  1111. // Our old documentation says that 'psoMsk' may be NULL, which means
  1112. // that the pointer is transparent. Well, trust me, that's wrong.
  1113. // I've checked GDI's code, and it will never pass us a NULL psoMsk:
  1114. cx = psoMsk->sizlBitmap.cx; // Note that 'sizlBitmap.cy' accounts
  1115. cy = psoMsk->sizlBitmap.cy >> 1; // for the double height due to the
  1116. // inclusion of both the AND masks
  1117. // and the XOR masks. For now, we're
  1118. // only interested in the true
  1119. // pointer dimensions, so we divide
  1120. // by 2.
  1121. //
  1122. // 'psoMsk' is actually cy * 2 scans high; the first 'cy' scans
  1123. // define the AND mask. So we start with that:
  1124. pjSrcScan = psoMsk->pvScan0;
  1125. lSrcDelta = psoMsk->lDelta;
  1126. lDstDelta = HW_POINTER_DIMENSION / 4; // Every 8 pels is one AND/XOR word
  1127. cxWhole = cx / 16; // Each word accounts for 16 pels
  1128. // caculating pointer checksum whether update the pointer or not
  1129. pulSrc = (ULONG*) pjSrcScan;
  1130. ulData = 0L;
  1131. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1132. if (!(fl & SPS_ANIMATEUPDATE))
  1133. {
  1134. OUTPW(ppdev->pjIoBase, CRTC_INDEX, HGC_DY | (HW_POINTER_HIDE << 8));
  1135. }
  1136. if(x >= 0)
  1137. {
  1138. vMovePointerS3(ppdev, x, y);
  1139. }
  1140. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1141. // Now we're going to take the requested pointer AND masks and XOR
  1142. // masks and combine them into our work buffer, being careful of
  1143. // the edges so that we don't disturb the transparency when the
  1144. // requested pointer size is not a multiple of 16.
  1145. pulDst = (ULONG*) pBuf;
  1146. for (i = 0; i < HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i++)
  1147. {
  1148. // Here we initialize the entire pointer work buffer to be
  1149. // transparent (the S3 has no means of specifying a pointer size
  1150. // other than 64 x 64 -- so if we're asked to draw a 32 x 32
  1151. // pointer, we want the unused portion to be transparent).
  1152. //
  1153. // The S3's hardware pointer is defined by an interleaved pattern
  1154. // of AND words and XOR words. So a totally transparent pointer
  1155. // starts off with the word 0xffff, followed by the word 0x0000,
  1156. // followed by 0xffff, etc.. Since we're a little endian system,
  1157. // this is simply the repeating dword '0x0000ffff'.
  1158. //
  1159. // The compiler is nice enough to optimize this into a REP STOSD
  1160. // for us:
  1161. *pulDst++ = 0x0000ffff;
  1162. }
  1163. // ekl - take care word bnd.
  1164. // Start with first AND word
  1165. pjDstScan = (BYTE *) pBuf;
  1166. pjDstScan += ((HW_POINTER_DIMENSION / 2 - yHot) * lDstDelta +
  1167. (HW_POINTER_DIMENSION / 2 - ((xHot+15) & 0xFFFFFFF0L)) / 4);
  1168. cxWhole = cx / 16; // Each word accounts for 16 pels
  1169. xHotWordBnd = xHot % 16;
  1170. if(xHotWordBnd)
  1171. {
  1172. ulTransp >>= (16 - xHotWordBnd);
  1173. cxWhole *= 2;
  1174. for (i = cy; i != 0; i--)
  1175. {
  1176. pbSrc = pjSrcScan;
  1177. pbDst = pjDstScan;
  1178. ulPreviousData = ulTransp << 16;
  1179. for (j = 0; j < cxWhole; j++, pbSrc++)
  1180. {
  1181. ulData = (ULONG) (*pbSrc);
  1182. ulData <<= (8 + xHotWordBnd);
  1183. ulData |= ulPreviousData;
  1184. ucTemp = (UCHAR)(ulData >> 24);
  1185. *pbDst = ucTemp;
  1186. pbDst += (j % 2 ? 3 : 1);
  1187. // next byte
  1188. ulData <<= 8;
  1189. ulPreviousData = ulData;
  1190. }
  1191. // last word
  1192. ulData |= ulTransp;
  1193. ucTemp = (UCHAR)(ulData >> 24);
  1194. *pbDst = ucTemp;
  1195. pbDst += (2*j + 1);
  1196. ucTemp = (UCHAR)(ulData >> 16);
  1197. *pbDst = ucTemp;
  1198. pjSrcScan += lSrcDelta;
  1199. pjDstScan += lDstDelta;
  1200. }
  1201. }
  1202. else
  1203. {
  1204. for (i = cy; i != 0; i--)
  1205. {
  1206. pwSrc = (WORD*) pjSrcScan;
  1207. pwDst = (WORD*) pjDstScan;
  1208. for (j = cxWhole; j != 0; j--)
  1209. {
  1210. *pwDst = *pwSrc;
  1211. pwSrc += 1; // Go to next word in source mask
  1212. pwDst += 2; // Skip over the XOR word in the dest mask
  1213. }
  1214. pjSrcScan += lSrcDelta;
  1215. pjDstScan += lDstDelta;
  1216. }
  1217. }
  1218. // Now handle the XOR mask:
  1219. pjDstScan = (BYTE *) pBuf;
  1220. pjDstScan += (2 + (HW_POINTER_DIMENSION / 2 - yHot) * lDstDelta +
  1221. (HW_POINTER_DIMENSION / 2 - ((xHot+15) & 0xFFFFFFF0L)) / 4);
  1222. if(xHotWordBnd)
  1223. {
  1224. for (i = cy; i != 0; i--)
  1225. {
  1226. pbSrc = pjSrcScan;
  1227. pbDst = pjDstScan;
  1228. ulPreviousData = 0;
  1229. for (j = 0; j < cxWhole; j++, pbSrc++)
  1230. {
  1231. ulData = (ULONG) (*pbSrc);
  1232. ulData <<= (8 + xHotWordBnd);
  1233. ulData |= ulPreviousData;
  1234. ucTemp = (UCHAR)(ulData >> 24);
  1235. *pbDst = ucTemp;
  1236. pbDst += (j % 2 ? 3 : 1);
  1237. // Next byte
  1238. ulData <<= 8;
  1239. ulPreviousData = ulData;
  1240. }
  1241. ucTemp = (UCHAR)(ulData >> 24);
  1242. *pbDst = ucTemp;
  1243. pbDst += (2*j + 1);
  1244. ucTemp = (UCHAR)(ulData >> 16);
  1245. *pbDst = ucTemp;
  1246. pjSrcScan += lSrcDelta;
  1247. pjDstScan += lDstDelta;
  1248. }
  1249. }
  1250. else
  1251. {
  1252. for (i = cy; i != 0; i--)
  1253. {
  1254. pwSrc = (WORD*) pjSrcScan;
  1255. pwDst = (WORD*) pjDstScan;
  1256. for (j = cxWhole; j != 0; j--)
  1257. {
  1258. *pwDst = *pwSrc;
  1259. pwSrc += 1; // Go to next word in source mask
  1260. pwDst += 2; // Skip over the AND word in the dest mask
  1261. }
  1262. pjSrcScan += lSrcDelta;
  1263. pjDstScan += lDstDelta;
  1264. }
  1265. }
  1266. ACQUIRE_CRTC_CRITICAL_SECTION(ppdev);
  1267. pulSrc = (ULONG*) pBuf;
  1268. pulDst = (ULONG*) ppdev->pvPointerShape;
  1269. if (DIRECT_ACCESS(ppdev))
  1270. {
  1271. for (i = HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i != 0; i--)
  1272. {
  1273. *pulDst++ = *pulSrc++;
  1274. }
  1275. }
  1276. else
  1277. {
  1278. for (i = HW_POINTER_TOTAL_SIZE / sizeof(ULONG); i != 0; i--)
  1279. {
  1280. WRITE_REGISTER_ULONG(pulDst, *pulSrc);
  1281. pulSrc++;
  1282. pulDst++;
  1283. }
  1284. }
  1285. if(x >= 0)
  1286. {
  1287. if (!ppdev->bHwPointerActive) {
  1288. ppdev->bHwPointerActive = TRUE;
  1289. vShowPointerS3(ppdev, TRUE);
  1290. }
  1291. }
  1292. else
  1293. {
  1294. if (ppdev->bHwPointerActive) {
  1295. ppdev->bHwPointerActive = FALSE;
  1296. vShowPointerS3(ppdev, FALSE);
  1297. }
  1298. }
  1299. RELEASE_CRTC_CRITICAL_SECTION(ppdev);
  1300. // fix the hot spot at the center of the HW cursor
  1301. ppdev->xPointerHot = HW_POINTER_DIMENSION / 2;
  1302. ppdev->yPointerHot = HW_POINTER_DIMENSION / 2;
  1303. return(SPS_ACCEPT_NOEXCLUDE);
  1304. }