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.

2123 lines
68 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 driver.
  10. * We also have support for color space double buffering using the RAMDAC pixel
  11. * read mask.
  12. *
  13. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  14. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  15. \*****************************************************************************/
  16. #include "precomp.h"
  17. #include "pointer.h"
  18. #include "tvp4020.h"
  19. #include "p2rd.h"
  20. #include "gdi.h"
  21. #include "heap.h"
  22. //
  23. // Look-up table for masking the right edge of the given pointer bitmap:
  24. //
  25. BYTE gajMask[] =
  26. {
  27. 0x00, 0x80, 0xC0, 0xE0,
  28. 0xF0, 0xF8, 0xFC, 0xFE,
  29. };
  30. UCHAR nibbleToByteP2RD[] =
  31. {
  32. 0x00, // 0000 --> 00000000
  33. 0x80, // 0001 --> 10000000
  34. 0x20, // 0010 --> 00100000
  35. 0xA0, // 0011 --> 10100000
  36. 0x08, // 0100 --> 00001000
  37. 0x88, // 0101 --> 10001000
  38. 0x28, // 0110 --> 00101000
  39. 0xA8, // 0111 --> 10101000
  40. 0x02, // 1000 --> 00000010
  41. 0x82, // 1001 --> 10000010
  42. 0x22, // 1010 --> 00100010
  43. 0xA2, // 1011 --> 10100010
  44. 0x0A, // 1100 --> 00001010
  45. 0x8A, // 1101 --> 10001010
  46. 0x2A, // 1110 --> 00101010
  47. 0xAA, // 1111 --> 10101010
  48. };
  49. //-----------------------------------------------------------------------------
  50. //
  51. // LONG HWPointerCacheInit()
  52. //
  53. // Initialise the hardware pointer cache.
  54. //
  55. //-----------------------------------------------------------------------------
  56. VOID
  57. HWPointerCacheInit(HWPointerCache* ptrCache)
  58. {
  59. ptrCache->cPtrCacheInUseCount = 0;
  60. ptrCache->ptrCacheCurTimeStamp = 0;
  61. }// HWPointerCacheInit()
  62. //-----------------------------------------------------------------------------
  63. //
  64. // 64 x 64 Hardware Pointer Caching
  65. // --------------------------------
  66. // The code below implements hardware independent caching of pointers. It
  67. // maintains a cache big enough to store ONE 64x64 cursor or FOUR 32x32
  68. // cursors. The code will work with all RAMDACs that support this form of
  69. // caching.
  70. //
  71. //-----------------------------------------------------------------------------
  72. //-----------------------------------------------------------------------------
  73. //
  74. // LONG HWPointerCacheCheckAndAdd()
  75. //
  76. // This function does a byte-by-byte comparison of the supplied pointer data
  77. // with each pointer that is in cache, if it finds a matching one then it
  78. // returns the index of the item in the cache (0 to 3) otherwise it adds it to
  79. // the cache and returns the index.
  80. //
  81. //-----------------------------------------------------------------------------
  82. LONG
  83. HWPointerCacheCheckAndAdd(HWPointerCache* ptrCache,
  84. HSURF hsurf,
  85. ULONG ulKey,
  86. BOOL* isCached)
  87. {
  88. BOOL pointerIsCached = FALSE;
  89. LONG i, j, z;
  90. LONG cacheItem;
  91. DBG_GDI((6, "HWPointerCacheCheckAndAdd called"));
  92. //
  93. // If there are entries in the cache and they are the same format as the
  94. // one that we are looking for then search the cache.
  95. //
  96. if ( ptrCache->cPtrCacheInUseCount )
  97. {
  98. DBG_GDI((6, "Found entry in cache with the same format"));
  99. //
  100. // Search the cache
  101. //
  102. LONG lTotalcached = ptrCache->cPtrCacheInUseCount;
  103. //
  104. // Examine all valid entries in the cache to see if they are the same
  105. // as the pointer that we've been handed based on its unique key number
  106. // and the surface handle.
  107. // Note: the reason we check "hsurf" here is that it is possible that
  108. // two surfaces has the same iUniq number since Every time the surface
  109. // changes this value is incremented
  110. //
  111. for ( z = 0; !pointerIsCached && z < lTotalcached; z++ )
  112. {
  113. if ( (ulKey == ptrCache->ptrCacheItemList[z].ulKey)
  114. &&(hsurf == ptrCache->ptrCacheItemList[z].hsurf) )
  115. {
  116. cacheItem = z;
  117. pointerIsCached = TRUE;
  118. }
  119. }// loop through all the cached items
  120. }// Found entry in cache with the same format
  121. DBG_GDI((6, "Found an entry in cache (%s)", pointerIsCached?"YES":"NO"));
  122. //
  123. // If we couldn't find an entry in the pointer cache then add one to the
  124. // cache.
  125. //
  126. if ( !pointerIsCached )
  127. {
  128. //
  129. // Add the pointer to the cache
  130. //
  131. LONG z2;
  132. //
  133. // If there are some spare entries then allocate a free entry, otherwise
  134. // find the least recently used entry and use that.
  135. //
  136. if ( ptrCache->cPtrCacheInUseCount < SMALL_POINTER_MAX )
  137. {
  138. cacheItem = ptrCache->cPtrCacheInUseCount++;
  139. }
  140. else
  141. {
  142. ULONG oldestValue = 0xFFFFFFFF;
  143. //
  144. // Look for the LRU entry
  145. //
  146. for ( z2 = 0, cacheItem = 0; z2 < SMALL_POINTER_MAX; z2++ )
  147. {
  148. if ( ptrCache->ptrCacheItemList[z2].ptrCacheTimeStamp
  149. < oldestValue )
  150. {
  151. cacheItem = z2;
  152. oldestValue =
  153. ptrCache->ptrCacheItemList[z2].ptrCacheTimeStamp;
  154. }
  155. }
  156. }// Determine cacheItem
  157. ptrCache->ptrCacheItemList[cacheItem].ulKey = ulKey;
  158. ptrCache->ptrCacheItemList[cacheItem].hsurf = hsurf;
  159. }// If not found entry, add one
  160. //
  161. // Set the timestamp
  162. //
  163. ptrCache->ptrCacheItemList[cacheItem].ptrCacheTimeStamp
  164. = ptrCache->ptrCacheCurTimeStamp++;
  165. //
  166. // Set up the return value to say whether the pointer was cached and return
  167. // the number of the current cached position
  168. //
  169. *isCached = pointerIsCached;
  170. DBG_GDI((6, "HWPointerCacheCheckAndAdd finished and return item %d",
  171. cacheItem));
  172. return(cacheItem);
  173. }// HWPointerCacheCheckAndAdd()
  174. //-----------------------------------------------------------------------------
  175. //
  176. // VOID vShowPointerP2RD()
  177. //
  178. // Show or hide the 3Dlabs P2RD hardware pointer.
  179. //
  180. //-----------------------------------------------------------------------------
  181. VOID
  182. vShowPointerP2RD(PDev* ppdev,
  183. BOOL bShow)
  184. {
  185. ULONG cmr;
  186. PERMEDIA_DECL_VARS;
  187. P2RD_DECL_VARS;
  188. PERMEDIA_DECL_INIT;
  189. P2RD_DECL_INIT;
  190. DBG_GDI((6, "vShowPointerP2RD (%s)", bShow ? "on" : "off"));
  191. if ( bShow )
  192. {
  193. //
  194. // No need to sync since this case is called only if we've just
  195. // moved the cursor and that will already have done a sync.
  196. //
  197. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_MODE, (pP2RDinfo->cursorModeCurrent | P2RD_CURSOR_MODE_ENABLED));
  198. P2RD_MOVE_CURSOR (pP2RDinfo->x, pP2RDinfo->y);
  199. }
  200. else
  201. {
  202. //
  203. // move the cursor off screen
  204. //
  205. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_Y_HIGH, 0xff);
  206. }
  207. }// vShowPointerP2RD()
  208. //-----------------------------------------------------------------------------
  209. //
  210. // VOID vMovePointerP2RD()
  211. //
  212. // Move the 3Dlabs P2RD hardware pointer.
  213. //
  214. //-----------------------------------------------------------------------------
  215. VOID
  216. vMovePointerP2RD(PDev* ppdev,
  217. LONG x,
  218. LONG y)
  219. {
  220. PERMEDIA_DECL_VARS;
  221. P2RD_DECL_VARS;
  222. PERMEDIA_DECL_INIT;
  223. P2RD_DECL_INIT;
  224. DBG_GDI((6, "vMovePointerP2RD to (%d, %d)", x, y));
  225. pP2RDinfo->x = x;
  226. pP2RDinfo->y = y;
  227. P2RD_SYNC_WITH_PERMEDIA;
  228. P2RD_MOVE_CURSOR(x, y);
  229. }// vMovePointerP2RD()
  230. //-----------------------------------------------------------------------------
  231. //
  232. // BOOL bSet3ColorPointerShapeP2RD()
  233. //
  234. // Stores the 3-color cursor in the RAMDAC: currently only 32bpp and 15/16bpp
  235. // cursors are supported
  236. //
  237. //-----------------------------------------------------------------------------
  238. BOOL
  239. bSet3ColorPointerShapeP2RD(PDev* ppdev,
  240. SURFOBJ* psoMask, // defines AND and MASK bits
  241. // for cursor
  242. SURFOBJ* psoColor, // we may handle some color
  243. // cursors at some point
  244. LONG x, // If -1, pointer should be
  245. // created hidden
  246. LONG y,
  247. LONG xHot,
  248. LONG yHot)
  249. {
  250. LONG cx, cy;
  251. LONG cxcyCache;
  252. LONG cjCacheRow, cjCacheRemx, cjCacheRemy, cj;
  253. BYTE *pjAndMask, *pj;
  254. ULONG *pulColor, *pul;
  255. LONG cjAndDelta, cjColorDelta;
  256. LONG iRow, iCol;
  257. BYTE AndBit, AndByte;
  258. ULONG CI2ColorIndex, CI2ColorData;
  259. ULONG ulColor;
  260. ULONG aulColorsIndexed[3];
  261. LONG Index, HighestIndex = 0;
  262. ULONG r, g, b;
  263. PERMEDIA_DECL_VARS;
  264. P2RD_DECL_VARS;
  265. PERMEDIA_DECL_INIT;
  266. P2RD_DECL_INIT;
  267. DBG_GDI((6, "bSet3ColorPointerShapeP2RD started"));
  268. cx = psoColor->sizlBitmap.cx;
  269. cy = psoColor->sizlBitmap.cy;
  270. if ( cx <= 32 && cy <= 32 )
  271. {
  272. //
  273. // 32x32 cursor : we'll cache it in cursor partition 0 and scrub the
  274. // old cache
  275. //
  276. cxcyCache = 32;
  277. pP2RDinfo->cursorSize = P2RD_CURSOR_SIZE_32_3COLOR;
  278. pP2RDinfo->cursorModeCurrent = pP2RDinfo->cursorModeOff
  279. | P2RD_CURSOR_SEL(pP2RDinfo->cursorSize, 0)
  280. | P2RD_CURSOR_MODE_3COLOR;
  281. //
  282. // We don't cache color cursors
  283. //
  284. HWPointerCacheInvalidate (&(ppdev->HWPtrCache));
  285. }
  286. else if ( cx <= 64 && cy <= 64 )
  287. {
  288. //
  289. // 64x64 cursor : we'll cache it in cursor partition 0 and scrub the
  290. // old cache
  291. //
  292. cxcyCache = 64;
  293. pP2RDinfo->cursorSize = P2RD_CURSOR_SIZE_64_3COLOR;
  294. pP2RDinfo->cursorModeCurrent = pP2RDinfo->cursorModeOff
  295. | P2RD_CURSOR_SEL(pP2RDinfo->cursorSize, 0)
  296. | P2RD_CURSOR_MODE_3COLOR;
  297. //
  298. // We don't cache color cursors
  299. //
  300. HWPointerCacheInvalidate (&(ppdev->HWPtrCache));
  301. }
  302. else
  303. {
  304. DBG_GDI((6, "declining cursor: %d x %d is too big", cx, cy));
  305. return(FALSE); // cursor is too big to fit in the hardware
  306. }
  307. //
  308. // work out the remaining bytes in the cache (in x and y) that will need
  309. // clearing
  310. //
  311. cjCacheRow = 2 * cxcyCache / 8;
  312. cjCacheRemx = cjCacheRow - 2 * ((cx+7) / 8);
  313. cjCacheRemy = (cxcyCache - cy) * cjCacheRow;
  314. //
  315. // Set-up a pointer to the 1bpp AND mask bitmap
  316. //
  317. pjAndMask = (UCHAR*)psoMask->pvScan0;
  318. cjAndDelta = psoMask->lDelta;
  319. //
  320. // Set-up a pointer to the 32bpp color bitmap
  321. //
  322. pulColor = (ULONG*)psoColor->pvScan0;
  323. cjColorDelta = psoColor->lDelta;
  324. //
  325. // Hide the pointer
  326. //
  327. vShowPointerP2RD(ppdev, FALSE);
  328. //
  329. // Load the cursor array (we have auto-increment turned on so initialize
  330. // to entry 0 here)
  331. //
  332. P2RD_CURSOR_ARRAY_START(0);
  333. for ( iRow = 0;
  334. iRow < cy;
  335. ++iRow, pjAndMask += cjAndDelta,
  336. pulColor = (ULONG*)((BYTE*)pulColor+cjColorDelta) )
  337. {
  338. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: Row %d (of %d): pjAndMask(%p) pulColor(%p)",
  339. iRow, cy, pjAndMask, pulColor));
  340. pj = pjAndMask;
  341. pul = pulColor;
  342. CI2ColorIndex = CI2ColorData = 0;
  343. for ( iCol = 0; iCol < cx; ++iCol, CI2ColorIndex += 2 )
  344. {
  345. AndBit = (BYTE)(7 - (iCol & 7));
  346. if ( AndBit == 7 )
  347. {
  348. //
  349. // We're onto the next byte of the and mask
  350. //
  351. AndByte = *pj++;
  352. }
  353. if ( CI2ColorIndex == 8 )
  354. {
  355. //
  356. // We've filled a byte with 4 CI2 colors
  357. //
  358. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: writing cursor data %xh",
  359. CI2ColorData));
  360. P2RD_LOAD_CURSOR_ARRAY(CI2ColorData);
  361. CI2ColorData = 0;
  362. CI2ColorIndex = 0;
  363. }
  364. //
  365. // Get the source pixel
  366. //
  367. if ( ppdev->cPelSize == P2DEPTH32 )
  368. {
  369. ulColor = *pul++;
  370. }
  371. else
  372. {
  373. ulColor = *(USHORT*)pul;
  374. pul = (ULONG*)((USHORT*)pul + 1);
  375. }
  376. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: Column %d (of %d) AndByte(%08xh) AndBit(%d) ulColor(%08xh)",
  377. iCol, cx, AndByte, AndBit, ulColor));
  378. //
  379. // Figure out what to do with it:-
  380. // AND Color Result
  381. // 0 X color
  382. // 1 0 transparent
  383. // 1 1 inverse
  384. //
  385. if ( AndByte & (1 << AndBit) )
  386. {
  387. //
  388. // Transparent or inverse
  389. //
  390. if ( ulColor == 0 )
  391. {
  392. //
  393. // color == black:
  394. // transparent and seeing as the CI2ColorData is
  395. // initialized to 0 we don't have to explicitly clear these
  396. // bits - go on to the next pixel
  397. //
  398. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: transparent - ignore"));
  399. continue;
  400. }
  401. if ( ulColor == ppdev->ulWhite )
  402. {
  403. //
  404. // color == white:
  405. // inverse, but we don't support this. We've destroyed the
  406. // cache for nothing
  407. //
  408. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: failed - inverted colors aren't supported"));
  409. return(FALSE);
  410. }
  411. }
  412. //
  413. // Get the index for this color: first see if we've already indexed
  414. // it
  415. //
  416. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: looking up color %08xh",
  417. ulColor));
  418. for ( Index = 0;
  419. Index < HighestIndex && aulColorsIndexed[Index] != ulColor;
  420. ++Index );
  421. if ( Index == 3 )
  422. {
  423. //
  424. // Too many colors in this cursor
  425. //
  426. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: failed - cursor has more than 3 colors"));
  427. return(FALSE);
  428. }
  429. else if ( Index == HighestIndex )
  430. {
  431. //
  432. // We've found another color: add it to the color index
  433. //
  434. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: adding %08xh to cursor palette",
  435. ulColor));
  436. aulColorsIndexed[HighestIndex++] = ulColor;
  437. }
  438. //
  439. // Add this pixel's index to the CI2 cursor data. NB. Need Index+1
  440. // as 0 == transparent
  441. //
  442. CI2ColorData |= (Index + 1) << CI2ColorIndex;
  443. }
  444. //
  445. // End of the cursor row: save the remaining indexed pixels then blank
  446. // any unused columns
  447. //
  448. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: writing remaining data for this row (%08xh) and %d trailing bytes",
  449. CI2ColorData, cjCacheRemx));
  450. P2RD_LOAD_CURSOR_ARRAY(CI2ColorData);
  451. if ( cjCacheRemx )
  452. {
  453. for ( cj = cjCacheRemx; --cj >=0; )
  454. {
  455. P2RD_LOAD_CURSOR_ARRAY(P2RD_CURSOR_3_COLOR_TRANSPARENT);
  456. }
  457. }
  458. }
  459. //
  460. // End of cursor: blank any unused rows Nb. cjCacheRemy == cy blank
  461. // rows * cj bytes per row
  462. //
  463. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: writing %d trailing bytes for this cursor",
  464. cjCacheRemy));
  465. for ( cj = cjCacheRemy; --cj >= 0; )
  466. {
  467. //
  468. // 0 == transparent
  469. //
  470. P2RD_LOAD_CURSOR_ARRAY(P2RD_CURSOR_3_COLOR_TRANSPARENT);
  471. }
  472. DBG_GDI((7, "bSet3ColorPointerShapeP2RD: setting up the cursor palette"));
  473. //
  474. // Now set-up the cursor palette
  475. //
  476. for ( iCol = 0; iCol < HighestIndex; ++iCol )
  477. {
  478. //
  479. // The cursor colors are at native depth, convert them to 24bpp
  480. //
  481. if ( ppdev->cPelSize == P2DEPTH32 )
  482. {
  483. //
  484. // 32bpp
  485. //
  486. b = 0xff & aulColorsIndexed[iCol];
  487. g = 0xff & (aulColorsIndexed[iCol] >> 8);
  488. r = 0xff & (aulColorsIndexed[iCol] >> 16);
  489. }
  490. else
  491. {
  492. //
  493. // (ppdev->cPelSize == P2DEPTH16)
  494. //
  495. if ( ppdev->ulWhite == 0xffff )
  496. {
  497. //
  498. // 16bpp
  499. //
  500. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  501. g = (0x3f & (aulColorsIndexed[iCol] >> 5)) << 2;
  502. r = (0x1f & (aulColorsIndexed[iCol] >> 11)) << 3;
  503. }
  504. else
  505. {
  506. //
  507. // 15bpp
  508. //
  509. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  510. g = (0x1f & (aulColorsIndexed[iCol] >> 5)) << 3;
  511. r = (0x1f & (aulColorsIndexed[iCol] >> 10)) << 3;
  512. }
  513. }
  514. P2RD_CURSOR_PALETTE_CURSOR_RGB(iCol, r, g, b);
  515. }
  516. //
  517. // Enable the cursor
  518. //
  519. P2RD_CURSOR_HOTSPOT(xHot, yHot);
  520. if ( x != -1 )
  521. {
  522. vMovePointerP2RD (ppdev, x, y);
  523. //
  524. // Need to explicitly show the pointer if not using interrupts
  525. //
  526. vShowPointerP2RD(ppdev, TRUE);
  527. }
  528. DBG_GDI((6, "b3ColorSetPointerShapeP2RD done"));
  529. return(TRUE);
  530. }// bSet3ColorPointerShapeP2RD()
  531. //-----------------------------------------------------------------------------
  532. //
  533. // BOOL bSet15ColorPointerShapeP2RD
  534. //
  535. // Stores the 15-color cursor in the RAMDAC: currently only 32bpp and 15/16bpp
  536. // cursors are supported
  537. //
  538. //-----------------------------------------------------------------------------
  539. BOOL
  540. bSet15ColorPointerShapeP2RD(PDev* ppdev,
  541. SURFOBJ* psoMask, // defines AND and MASK
  542. // bits for cursor
  543. SURFOBJ* psoColor, // we may handle some color
  544. // cursors at some point
  545. LONG x, // If -1, pointer should be
  546. // created hidden
  547. LONG y,
  548. LONG xHot,
  549. LONG yHot)
  550. {
  551. LONG cx, cy;
  552. LONG cxcyCache;
  553. LONG cjCacheRow, cjCacheRemx, cjCacheRemy, cj;
  554. BYTE* pjAndMask;
  555. BYTE* pj;
  556. ULONG* pulColor;
  557. ULONG* pul;
  558. LONG cjAndDelta;
  559. LONG cjColorDelta;
  560. LONG iRow;
  561. LONG iCol;
  562. BYTE AndBit;
  563. BYTE AndByte;
  564. ULONG CI4ColorIndex;
  565. ULONG CI4ColorData;
  566. ULONG ulColor;
  567. ULONG aulColorsIndexed[15];
  568. LONG Index;
  569. LONG HighestIndex = 0;
  570. ULONG r;
  571. ULONG g;
  572. ULONG b;
  573. PERMEDIA_DECL_VARS;
  574. P2RD_DECL_VARS;
  575. PERMEDIA_DECL_INIT;
  576. P2RD_DECL_INIT;
  577. DBG_GDI((6, "bSet15ColorPointerShapeP2RD started"));
  578. cx = psoColor->sizlBitmap.cx;
  579. cy = psoColor->sizlBitmap.cy;
  580. if ( cx <= 32 && cy <= 32 )
  581. {
  582. //
  583. // 32x32 cursor : we'll cache it in cursor partition 0 and scrub the
  584. // old cache
  585. //
  586. cxcyCache = 32;
  587. pP2RDinfo->cursorSize = P2RD_CURSOR_SIZE_32_15COLOR;
  588. pP2RDinfo->cursorModeCurrent = pP2RDinfo->cursorModeOff
  589. | P2RD_CURSOR_SEL(pP2RDinfo->cursorSize, 0)
  590. | P2RD_CURSOR_MODE_15COLOR;
  591. //
  592. // We don't cache color cursors
  593. //
  594. HWPointerCacheInvalidate (&(ppdev->HWPtrCache));
  595. }
  596. else if ( cx <= 64 && cy <= 64 )
  597. {
  598. //
  599. // It's too big to cache as a fifteen color cursor, but we might just
  600. // be able to cache it if it has 3 or fewer colors
  601. //
  602. BOOL bRet;
  603. bRet = bSet3ColorPointerShapeP2RD(ppdev, psoMask, psoColor, x, y, xHot,
  604. yHot);
  605. return(bRet);
  606. }
  607. else
  608. {
  609. DBG_GDI((6, "declining cursor: %d x %d is too big", cx, cy));
  610. return(FALSE); // cursor is too big to fit in the hardware
  611. }
  612. //
  613. // Work out the remaining bytes in the cache (in x and y) that will need
  614. // clearing
  615. //
  616. cjCacheRow = 2 * cxcyCache / 8;
  617. cjCacheRemx = cjCacheRow - 2 * ((cx+7) / 8);
  618. cjCacheRemy = (cxcyCache - cy) * cjCacheRow;
  619. //
  620. // Set-up a pointer to the 1bpp AND mask bitmap
  621. //
  622. pjAndMask = (UCHAR*)psoMask->pvScan0;
  623. cjAndDelta = psoMask->lDelta;
  624. //
  625. // Set-up a pointer to the 32bpp color bitmap
  626. //
  627. pulColor = (ULONG*)psoColor->pvScan0;
  628. cjColorDelta = psoColor->lDelta;
  629. //
  630. // Hide the pointer
  631. //
  632. vShowPointerP2RD(ppdev, FALSE);
  633. //
  634. // Load the cursor array (we have auto-increment turned on so initialize to
  635. // entry 0 here)
  636. //
  637. P2RD_CURSOR_ARRAY_START(0);
  638. for ( iRow = 0; iRow < cy;
  639. ++iRow, pjAndMask += cjAndDelta,
  640. pulColor = (ULONG*)((BYTE*)pulColor + cjColorDelta) )
  641. {
  642. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: Row %d (of %d): pjAndMask(%p) pulColor(%p)",
  643. iRow, cy, pjAndMask, pulColor));
  644. pj = pjAndMask;
  645. pul = pulColor;
  646. CI4ColorIndex = CI4ColorData = 0;
  647. for ( iCol = 0; iCol < cx; ++iCol, CI4ColorIndex += 4 )
  648. {
  649. AndBit = (BYTE)(7 - (iCol & 7));
  650. if ( AndBit == 7 )
  651. {
  652. //
  653. // We're onto the next byte of the and mask
  654. //
  655. AndByte = *pj++;
  656. }
  657. if ( CI4ColorIndex == 8 )
  658. {
  659. //
  660. // We've filled a byte with 2 CI4 colors
  661. //
  662. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: writing cursor data %xh",
  663. CI4ColorData));
  664. P2RD_LOAD_CURSOR_ARRAY(CI4ColorData);
  665. CI4ColorData = 0;
  666. CI4ColorIndex = 0;
  667. }
  668. //
  669. // Get the source pixel
  670. //
  671. if ( ppdev->cPelSize == P2DEPTH32 )
  672. {
  673. ulColor = *pul++;
  674. }
  675. else
  676. {
  677. ulColor = *(USHORT *)pul;
  678. pul = (ULONG *)((USHORT *)pul + 1);
  679. }
  680. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: Column %d (of %d) AndByte(%08xh) AndBit(%d) ulColor(%08xh)",
  681. iCol, cx, AndByte, AndBit, ulColor));
  682. //
  683. // figure out what to do with it:-
  684. // AND Color Result
  685. // 0 X color
  686. // 1 0 transparent
  687. // 1 1 inverse
  688. if ( AndByte & (1 << AndBit) )
  689. {
  690. //
  691. // Transparent or inverse
  692. //
  693. if ( ulColor == 0 )
  694. {
  695. //
  696. // color == black:
  697. // Transparent and seeing as the CI2ColorData is initialized
  698. // to 0 we don't have to explicitly clear these bits - go on
  699. // to the next pixel
  700. //
  701. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: transparent - ignore"));
  702. continue;
  703. }
  704. if ( ulColor == ppdev->ulWhite )
  705. {
  706. //
  707. // color == white:
  708. // Inverse, but we don't support this. We've destroyed the
  709. // cache for nothing
  710. //
  711. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: failed - inverted colors aren't supported"));
  712. return(FALSE);
  713. }
  714. }
  715. //
  716. // Get the index for this color: first see if we've already indexed
  717. // it
  718. //
  719. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: looking up color %08xh",
  720. ulColor));
  721. for ( Index = 0;
  722. Index < HighestIndex && aulColorsIndexed[Index] != ulColor;
  723. ++Index );
  724. if ( Index == 15 )
  725. {
  726. //
  727. // Too many colors in this cursor
  728. //
  729. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: failed - cursor has more than 15 colors"));
  730. return(FALSE);
  731. }
  732. else if ( Index == HighestIndex )
  733. {
  734. //
  735. // We've found another color: add it to the color index
  736. //
  737. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: adding %08xh to cursor palette",
  738. ulColor));
  739. aulColorsIndexed[HighestIndex++] = ulColor;
  740. }
  741. //
  742. // Add this pixel's index to the CI4 cursor data.
  743. // Note: Need Index+1 as 0 == transparent
  744. //
  745. CI4ColorData |= (Index + 1) << CI4ColorIndex;
  746. }
  747. //
  748. // End of the cursor row: save the remaining indexed pixels then blank
  749. // any unused columns
  750. //
  751. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: writing remaining data for this row (%08xh) and %d trailing bytes", CI4ColorData, cjCacheRemx));
  752. P2RD_LOAD_CURSOR_ARRAY(CI4ColorData);
  753. if ( cjCacheRemx )
  754. {
  755. for ( cj = cjCacheRemx; --cj >=0; )
  756. {
  757. P2RD_LOAD_CURSOR_ARRAY(P2RD_CURSOR_15_COLOR_TRANSPARENT);
  758. }
  759. }
  760. }
  761. //
  762. // End of cursor: blank any unused rows Nb. cjCacheRemy == cy blank
  763. // rows * cj bytes per row
  764. //
  765. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: writing %d trailing bytes for this cursor", cjCacheRemy));
  766. for ( cj = cjCacheRemy; --cj >= 0; )
  767. {
  768. //
  769. // 0 == transparent
  770. //
  771. P2RD_LOAD_CURSOR_ARRAY(P2RD_CURSOR_15_COLOR_TRANSPARENT);
  772. }
  773. DBG_GDI((7, "bSet15ColorPointerShapeP2RD: setting up the cursor palette"));
  774. // now set-up the cursor palette
  775. for ( iCol = 0; iCol < HighestIndex; ++iCol )
  776. {
  777. //
  778. // The cursor colors are at native depth, convert them to 24bpp
  779. //
  780. if ( ppdev->cPelSize == P2DEPTH32 )
  781. {
  782. //
  783. // 32bpp
  784. //
  785. b = 0xff & aulColorsIndexed[iCol];
  786. g = 0xff & (aulColorsIndexed[iCol] >> 8);
  787. r = 0xff & (aulColorsIndexed[iCol] >> 16);
  788. }
  789. else
  790. {
  791. //
  792. // (ppdev->cPelSize == P2DEPTH16)
  793. //
  794. if ( ppdev->ulWhite == 0xffff )
  795. {
  796. //
  797. // 16bpp
  798. //
  799. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  800. g = (0x3f & (aulColorsIndexed[iCol] >> 5)) << 2;
  801. r = (0x1f & (aulColorsIndexed[iCol] >> 11)) << 3;
  802. }
  803. else
  804. {
  805. //
  806. // 15bpp
  807. //
  808. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  809. g = (0x1f & (aulColorsIndexed[iCol] >> 5)) << 3;
  810. r = (0x1f & (aulColorsIndexed[iCol] >> 10)) << 3;
  811. }
  812. }
  813. P2RD_CURSOR_PALETTE_CURSOR_RGB(iCol, r, g, b);
  814. }
  815. //
  816. // Enable the cursor
  817. //
  818. P2RD_CURSOR_HOTSPOT(xHot, yHot);
  819. if ( x != -1 )
  820. {
  821. vMovePointerP2RD (ppdev, x, y);
  822. //
  823. // need to explicitly show the pointer if not using interrupts
  824. //
  825. vShowPointerP2RD(ppdev, TRUE);
  826. }
  827. DBG_GDI((6, "b3ColorSetPointerShapeP2RD done"));
  828. return(TRUE);
  829. }// bSet15ColorPointerShapeP2RD()
  830. //-----------------------------------------------------------------------------
  831. //
  832. // VOID vShowPointerTVP4020
  833. //
  834. // Show or hide the TI TVP4020 hardware pointer.
  835. //
  836. //-----------------------------------------------------------------------------
  837. VOID
  838. vShowPointerTVP4020(PDev* ppdev,
  839. BOOL bShow)
  840. {
  841. ULONG ccr;
  842. PERMEDIA_DECL_VARS;
  843. TVP4020_DECL_VARS;
  844. PERMEDIA_DECL_INIT;
  845. TVP4020_DECL_INIT;
  846. DBG_GDI((6, "vShowPointerTVP4020 (%s)", bShow ? "on" : "off"));
  847. if ( bShow )
  848. {
  849. //
  850. // No need to sync since this case is called only if we've just moved
  851. // the cursor and that will already have done a sync.
  852. //
  853. ccr = (pTVP4020info->cursorControlCurrent | TVP4020_CURSOR_XGA);
  854. }
  855. else
  856. {
  857. ccr = pTVP4020info->cursorControlOff & ~TVP4020_CURSOR_XGA;
  858. }
  859. TVP4020_WRITE_INDEX_REG(__TVP4020_CURSOR_CONTROL, ccr);
  860. }// vShowPointerTVP4020()
  861. //-----------------------------------------------------------------------------
  862. //
  863. // VOID vMovePointerTVP4020
  864. //
  865. // Move the TI TVP4020 hardware pointer.
  866. //
  867. //-----------------------------------------------------------------------------
  868. VOID
  869. vMovePointerTVP4020(PDev* ppdev,
  870. LONG x,
  871. LONG y)
  872. {
  873. PERMEDIA_DECL_VARS;
  874. TVP4020_DECL_VARS;
  875. PERMEDIA_DECL_INIT;
  876. TVP4020_DECL_INIT;
  877. DBG_GDI((6, "vMovePointerTVP4020 to (%d, %d)", x, y));
  878. TVP4020_MOVE_CURSOR(x + ppdev->xPointerHot , y + ppdev->yPointerHot);
  879. }// vMovePointerTVP4020()
  880. //-----------------------------------------------------------------------------
  881. //
  882. // BOOL bSetPointerShapeTVP4020
  883. //
  884. // Set the TI TVP4020 hardware pointer shape.
  885. //
  886. // Parameters:
  887. // psoMask-----defines AND and MASK bits for cursor
  888. // psoColor----we may handle some color cursors at some point
  889. // x-----------If -1, pointer should be created hidden
  890. //
  891. //-----------------------------------------------------------------------------
  892. BOOL
  893. bSetPointerShapeTVP4020(PDev* ppdev,
  894. SURFOBJ* psoMask,
  895. SURFOBJ* psoColor,
  896. LONG x,
  897. LONG y,
  898. LONG xHot,
  899. LONG yHot)
  900. {
  901. ULONG cx;
  902. ULONG cy;
  903. ULONG i, iMax;
  904. ULONG j, jMax;
  905. BYTE bValue;
  906. BYTE* pjScan;
  907. LONG lDelta;
  908. ULONG cValid;
  909. ULONG ulMask;
  910. ULONG cursorRAMxOff;
  911. ULONG cursorRAMyOff;
  912. BOOL pointerIsCached;
  913. LONG cacheItem;
  914. PERMEDIA_DECL_VARS;
  915. TVP4020_DECL_VARS;
  916. PERMEDIA_DECL_INIT;
  917. TVP4020_DECL_INIT;
  918. DBG_GDI((6, "bSetPointerShapeTVP4020 started"));
  919. cx = psoMask->sizlBitmap.cx; // Note that 'sizlBitmap.cy' accounts
  920. cy = psoMask->sizlBitmap.cy >> 1; // for the double height due to the
  921. // inclusion of both the AND masks
  922. // and the XOR masks. We're
  923. // only interested in the true
  924. // pointer dimensions, so we divide
  925. // by 2.
  926. //
  927. // We currently don't handle colored cursors. Later, we could handle
  928. // cursors up to 64x64 with <= 3 colors. Checking this and setting it up
  929. // may be more trouble than it's worth.
  930. //
  931. if ( psoColor != NULL )
  932. {
  933. DBG_GDI((6, "bSetPointerShapeTVP4020: declining colored cursor"));
  934. return FALSE;
  935. }
  936. //
  937. // We only handle 32x32.
  938. //
  939. if ( (cx > 32) || (cy > 32) )
  940. {
  941. DBG_GDI((6, "declining cursor: %d x %d is too big", cx, cy));
  942. return(FALSE); // cursor is too big to fit in the hardware
  943. }
  944. //
  945. // Check to see if the pointer is cached, add it to the cache if it isn't
  946. //
  947. DBG_GDI((6, "iUniq =%ld hsurf=0x%x", psoMask->iUniq, psoMask->hsurf));
  948. cacheItem = HWPointerCacheCheckAndAdd(&(ppdev->HWPtrCache),
  949. psoMask->hsurf,
  950. psoMask->iUniq,
  951. &pointerIsCached);
  952. DBG_GDI((7, "bSetPointerShapeTVP4020: Add Cache iscac %d item %d",
  953. (int)pointerIsCached, cacheItem));
  954. vMovePointerTVP4020(ppdev, 0, ppdev->cyScreen + 64);
  955. pTVP4020info->cursorControlCurrent = pTVP4020info->cursorControlOff
  956. | TVP4020_CURSOR_SIZE_32
  957. | TVP4020_CURSOR_32_SEL(cacheItem);
  958. //
  959. // Cursor slots 1 & 3 have an x offset of 8 bytes, cursor slots 2 & 3 have
  960. // a y offset of 256 bytes
  961. //
  962. cursorRAMxOff = (cacheItem & 1) << 2;
  963. cursorRAMyOff = (cacheItem & 2) << 7;
  964. //
  965. // If the pointer is not cached, then download the pointer data to the DAC
  966. //
  967. if ( !pointerIsCached )
  968. {
  969. //
  970. // Disable the pointer
  971. //
  972. TVP4020_WRITE_INDEX_REG(__TVP4020_CURSOR_CONTROL,
  973. pTVP4020info->cursorControlCurrent);
  974. cValid = (cx + 7) / 8;
  975. ulMask = gajMask[cx & 0x07];
  976. if ( ulMask == 0 )
  977. {
  978. ulMask = 0xFF;
  979. }
  980. pjScan = (UCHAR*)psoMask->pvScan0;
  981. lDelta = psoMask->lDelta;
  982. iMax = 32; // max rows for 32 x 32 cursor
  983. jMax = 4; // max column bytes
  984. //
  985. // Send cursor plane 0 - in our case XOR
  986. //
  987. for ( i = 0; i < iMax; ++i )
  988. {
  989. TVP4020_CURSOR_ARRAY_START(CURSOR_PLANE0_OFFSET + cursorRAMyOff
  990. + (i * 8) + cursorRAMxOff);
  991. for ( j = 0; j < jMax; ++j )
  992. {
  993. if ( (j < cValid) && ( i < cy ) )
  994. {
  995. bValue = *(pjScan + j + (i + cy) * lDelta);
  996. }
  997. else
  998. {
  999. bValue = 0;
  1000. }
  1001. TVP4020_LOAD_CURSOR_ARRAY((ULONG)bValue);
  1002. }
  1003. }
  1004. //
  1005. // Send cursor plane 1 - in our case AND
  1006. //
  1007. for ( i = 0; i < iMax; ++i )
  1008. {
  1009. TVP4020_CURSOR_ARRAY_START(CURSOR_PLANE1_OFFSET + cursorRAMyOff
  1010. + (i * 8) + cursorRAMxOff);
  1011. for ( j = 0; j < jMax; ++j )
  1012. {
  1013. if ( (j < cValid) && ( i < cy ) )
  1014. {
  1015. bValue = *(pjScan + j + i * lDelta);
  1016. }
  1017. else
  1018. {
  1019. bValue = 0xFF;
  1020. }
  1021. TVP4020_LOAD_CURSOR_ARRAY((ULONG)bValue);
  1022. }
  1023. }
  1024. }// If pointer is not cached
  1025. //
  1026. // If the new cursor is different to the last cursor then set up the hot
  1027. // spot and other bits'n'pieces.
  1028. //
  1029. if ( ppdev->HWPtrLastCursor != cacheItem || !pointerIsCached )
  1030. {
  1031. //
  1032. // Make this item the last item
  1033. //
  1034. ppdev->HWPtrLastCursor = cacheItem;
  1035. ppdev->xPointerHot = 32 - xHot;
  1036. ppdev->yPointerHot = 32 - yHot;
  1037. }
  1038. if ( x != -1 )
  1039. {
  1040. vShowPointerTVP4020(ppdev, TRUE);
  1041. vMovePointerTVP4020(ppdev, x, y);
  1042. // Enable the cursor:
  1043. }
  1044. DBG_GDI((6, "bSetPointerShapeTVP4020 done"));
  1045. return(TRUE);
  1046. }// bSetPointerShapeTVP4020()
  1047. //-----------------------------------------------------------------------------
  1048. //
  1049. // VOID vEnablePointerTVP4020
  1050. //
  1051. // Get the hardware ready to use the TI TVP4020 hardware pointer.
  1052. //
  1053. //-----------------------------------------------------------------------------
  1054. VOID
  1055. vEnablePointerTVP4020(PDev* ppdev)
  1056. {
  1057. pTVP4020RAMDAC pRamdac;
  1058. ULONG ulMask;
  1059. PERMEDIA_DECL_VARS;
  1060. TVP4020_DECL_VARS;
  1061. PERMEDIA_DECL_INIT;
  1062. DBG_GDI((6, "vEnablePointerTVP4020 called"));
  1063. ppdev->pvPointerData = &ppdev->ajPointerData[0];
  1064. TVP4020_DECL_INIT;
  1065. //
  1066. // Get a pointer to the RAMDAC registers from the memory mapped
  1067. // control register space.
  1068. //
  1069. pRamdac = (pTVP4020RAMDAC)(ppdev->pulRamdacBase);
  1070. //
  1071. // set up memory mapping for the control registers and save in the pointer
  1072. // specific area provided in ppdev.
  1073. //
  1074. __TVP4020_PAL_WR_ADDR = (UINT_PTR)
  1075. TRANSLATE_ADDR_ULONG(&(pRamdac->pciAddrWr));
  1076. __TVP4020_PAL_RD_ADDR = (UINT_PTR)
  1077. TRANSLATE_ADDR_ULONG(&(pRamdac->pciAddrRd));
  1078. __TVP4020_PAL_DATA = (UINT_PTR)
  1079. TRANSLATE_ADDR_ULONG(&(pRamdac->palData));
  1080. __TVP4020_PIXEL_MASK = (UINT_PTR)
  1081. TRANSLATE_ADDR_ULONG(&(pRamdac->pixelMask));
  1082. __TVP4020_INDEX_DATA = (UINT_PTR)
  1083. TRANSLATE_ADDR_ULONG(&(pRamdac->indexData));
  1084. __TVP4020_CUR_RAM_DATA = (UINT_PTR)
  1085. TRANSLATE_ADDR_ULONG(&(pRamdac->curRAMData));
  1086. __TVP4020_CUR_RAM_WR_ADDR = (UINT_PTR)
  1087. TRANSLATE_ADDR_ULONG(&(pRamdac->pciAddrWr));
  1088. __TVP4020_CUR_RAM_RD_ADDR = (UINT_PTR)
  1089. TRANSLATE_ADDR_ULONG(&(pRamdac->pciAddrRd));
  1090. __TVP4020_CUR_COL_ADDR = (UINT_PTR)
  1091. TRANSLATE_ADDR_ULONG(&(pRamdac->curColAddr));
  1092. __TVP4020_CUR_COL_DATA = (UINT_PTR)
  1093. TRANSLATE_ADDR_ULONG(&(pRamdac->curColData));
  1094. __TVP4020_CUR_X_LSB = (UINT_PTR)
  1095. TRANSLATE_ADDR_ULONG(&(pRamdac->cursorXLow));
  1096. __TVP4020_CUR_X_MSB = (UINT_PTR)
  1097. TRANSLATE_ADDR_ULONG(&(pRamdac->cursorXHigh));
  1098. __TVP4020_CUR_Y_LSB = (UINT_PTR)
  1099. TRANSLATE_ADDR_ULONG(&(pRamdac->cursorYLow));
  1100. __TVP4020_CUR_Y_MSB = (UINT_PTR)
  1101. TRANSLATE_ADDR_ULONG(&(pRamdac->cursorYHigh));
  1102. //
  1103. // Initialize Cursor Control register. disables cursor. save a copy for
  1104. // enabling/disabling and setting the size. Then reset the cursor position,
  1105. // hot spot and colors.
  1106. //
  1107. // ulMask is used to prepare initial cursor control register
  1108. //
  1109. ulMask = TVP4020_CURSOR_RAM_MASK
  1110. | TVP4020_CURSOR_MASK
  1111. | TVP4020_CURSOR_SIZE_MASK;
  1112. //
  1113. // Set the cursor control to default values.
  1114. //
  1115. TVP4020_READ_INDEX_REG(__TVP4020_CURSOR_CONTROL,
  1116. pTVP4020info->cursorControlOff);
  1117. pTVP4020info->cursorControlOff &= ~ulMask;
  1118. pTVP4020info->cursorControlOff |= TVP4020_CURSOR_OFF;
  1119. TVP4020_WRITE_INDEX_REG(__TVP4020_CURSOR_CONTROL,
  1120. pTVP4020info->cursorControlOff);
  1121. pTVP4020info->cursorControlCurrent = pTVP4020info->cursorControlOff;
  1122. ppdev->xPointerHot = 0;
  1123. ppdev->yPointerHot = 0;
  1124. //
  1125. // Zero the RGB colors for foreground and background. The mono cursor is
  1126. // always black and white so we don't have to reload these values again.
  1127. //
  1128. TVP4020_SET_CURSOR_COLOR0(0, 0, 0);
  1129. TVP4020_SET_CURSOR_COLOR1(0xFF, 0xFF, 0xFF);
  1130. }// vEnablePointerTVP4020()
  1131. //-----------------------------------------------------------------------------
  1132. //
  1133. // BOOL bTVP4020CheckCSBuffering
  1134. //
  1135. // Determine whether we can do color space double buffering in the current
  1136. // mode.
  1137. //
  1138. // Returns
  1139. // TRUE if we can do the color space double buffering, FALSE otherwise.
  1140. //
  1141. //-----------------------------------------------------------------------------
  1142. BOOL
  1143. bTVP4020CheckCSBuffering(PDev* ppdev)
  1144. {
  1145. return FALSE;
  1146. }
  1147. //-----------------------------------------------------------------------------
  1148. //
  1149. // BOOL bSetPointerShapeP2RD
  1150. //
  1151. // Set the P2RD hardware pointer shape.
  1152. //
  1153. //-----------------------------------------------------------------------------
  1154. BOOL
  1155. bSetPointerShapeP2RD(PDev* ppdev,
  1156. SURFOBJ* pso, // defines AND and MASK bits for cursor
  1157. SURFOBJ* psoColor, // we may handle some color cursors at some point
  1158. XLATEOBJ* pxlo,
  1159. LONG x, // If -1, pointer should be created hidden
  1160. LONG y,
  1161. LONG xHot,
  1162. LONG yHot)
  1163. {
  1164. ULONG cx;
  1165. ULONG cy;
  1166. LONG i;
  1167. LONG j;
  1168. ULONG ulValue;
  1169. BYTE* pjAndScan;
  1170. BYTE* pjXorScan;
  1171. BYTE* pjAnd;
  1172. BYTE* pjXor;
  1173. BYTE andByte;
  1174. BYTE xorByte;
  1175. BYTE jMask;
  1176. LONG lDelta;
  1177. LONG cpelFraction;
  1178. LONG cjWhole;
  1179. LONG cClear;
  1180. LONG cRemPels;
  1181. BOOL pointerIsCached;
  1182. LONG cacheItem;
  1183. LONG cursorBytes;
  1184. LONG cursorRAMOff;
  1185. PERMEDIA_DECL_VARS;
  1186. P2RD_DECL_VARS;
  1187. PERMEDIA_DECL_INIT;
  1188. P2RD_DECL_INIT;
  1189. DBG_GDI((6, "bSetPointerShapeP2RD called"));
  1190. if ( psoColor != NULL )
  1191. {
  1192. Surf* psurfSrc = (Surf*)psoColor->dhsurf;
  1193. //
  1194. // It's a colored cursor
  1195. //
  1196. if ( (psoColor->dhsurf != NULL)
  1197. ||(!(psoColor->iBitmapFormat == BMF_16BPP))
  1198. ||(psoColor->iBitmapFormat == BMF_32BPP) )
  1199. {
  1200. //
  1201. // Currently we only handle DIB cursors at 32bpp
  1202. //
  1203. DBG_GDI((2, "declining colored cursor - iType(%d) iBMPFormat(%d)",
  1204. psoColor->iType, psoColor->iBitmapFormat));
  1205. return FALSE;
  1206. }
  1207. if ( pxlo != NULL )
  1208. {
  1209. if ( pxlo->flXlate != XO_TRIVIAL )
  1210. {
  1211. DBG_GDI((2, "declining colored cursor - flXlate(%xh)",
  1212. pxlo->flXlate));
  1213. return FALSE;
  1214. }
  1215. }
  1216. if ( !bSet15ColorPointerShapeP2RD(ppdev, pso, psoColor, x, y, xHot,
  1217. yHot) )
  1218. {
  1219. DBG_GDI((2, "declining colored cursor"));
  1220. return FALSE;
  1221. }
  1222. DBG_GDI((6, "bSetPointerShapeP2RD done"));
  1223. return(TRUE);
  1224. }// if ( psoColor != NULL )
  1225. //
  1226. // Note that 'sizlBitmap.cy' accounts for the double height due to the
  1227. // inclusion of both the AND masks and the XOR masks. We're only
  1228. // interested in the true pointer dimensions, so we divide by 2.
  1229. //
  1230. cx = pso->sizlBitmap.cx;
  1231. cy = pso->sizlBitmap.cy >> 1;
  1232. //
  1233. // We can handle up to 64x64. cValid indicates the number of bytes
  1234. // occupied by cursor on one line
  1235. //
  1236. if ( cx <= 32 && cy <= 32 )
  1237. {
  1238. //
  1239. // 32 horiz pixels: 2 bits per pixel, 1 horiz line per 8 bytes
  1240. //
  1241. pP2RDinfo->cursorSize = P2RD_CURSOR_SIZE_32_MONO;
  1242. cursorBytes = 32 * 32 * 2 / 8;
  1243. cClear = 8 - 2 * ((cx+7) / 8);
  1244. cRemPels = (32 - cy) << 3;
  1245. }
  1246. else
  1247. {
  1248. DBG_GDI((6, "declining cursor: %d x %d is too big", cx, cy));
  1249. return(FALSE); // cursor is too big to fit in the hardware
  1250. }
  1251. //
  1252. // Check to see if the pointer is cached, add it to the cache if it isn't
  1253. //
  1254. cacheItem = HWPointerCacheCheckAndAdd(&(ppdev->HWPtrCache),
  1255. pso->hsurf,
  1256. pso->iUniq,
  1257. &pointerIsCached);
  1258. DBG_GDI((7, "bSetPointerShapeP2RD: Add Cache iscac %d item %d",
  1259. (int)pointerIsCached, cacheItem));
  1260. pP2RDinfo->cursorModeCurrent = pP2RDinfo->cursorModeOff
  1261. | P2RD_CURSOR_SEL(pP2RDinfo->cursorSize,
  1262. cacheItem);
  1263. //
  1264. // Hide the pointer
  1265. //
  1266. vShowPointerP2RD(ppdev, FALSE);
  1267. if ( !pointerIsCached )
  1268. {
  1269. //
  1270. // Now we're going to take the requested pointer AND masks and XOR
  1271. // masks and interleave them by taking a nibble at a time from each,
  1272. // expanding each out and or'ing together. Use the nibbleToByteP2RD
  1273. // array to help this.
  1274. //
  1275. // 'psoMsk' is actually cy * 2 scans high; the first 'cy' scans
  1276. // define the AND mask.
  1277. //
  1278. pjAndScan = (UCHAR*)pso->pvScan0;
  1279. lDelta = pso->lDelta;
  1280. pjXorScan = pjAndScan + (cy * lDelta);
  1281. cjWhole = cx >> 3; // Each byte accounts for 8 pels
  1282. cpelFraction = cx & 0x7; // Number of fractional pels
  1283. jMask = gajMask[cpelFraction];
  1284. //
  1285. // We've got auto-increment turned on so just point to the first entry
  1286. // to write to in the array then write repeatedly until the cursor
  1287. // pattern has been transferred
  1288. //
  1289. cursorRAMOff = cacheItem * cursorBytes;
  1290. P2RD_CURSOR_ARRAY_START(cursorRAMOff);
  1291. for ( i = cy; --i >= 0; pjXorScan += lDelta, pjAndScan += lDelta )
  1292. {
  1293. pjAnd = pjAndScan;
  1294. pjXor = pjXorScan;
  1295. //
  1296. // Interleave nibbles from whole words. We are using Windows cursor
  1297. // mode.
  1298. // Note, the AND bit occupies the higher bit position for each
  1299. // 2bpp cursor pel; the XOR bit is in the lower bit position.
  1300. // The nibbleToByteP2RD array expands each nibble to occupy the bit
  1301. // positions for the AND bytes. So when we use it to calculate the
  1302. // XOR bits we shift the result right by 1.
  1303. //
  1304. for ( j = cjWhole; --j >= 0; ++pjAnd, ++pjXor )
  1305. {
  1306. andByte = *pjAnd;
  1307. xorByte = *pjXor;
  1308. ulValue = nibbleToByteP2RD[andByte >> 4]
  1309. | (nibbleToByteP2RD[xorByte >> 4] >> 1);
  1310. P2RD_LOAD_CURSOR_ARRAY (ulValue);
  1311. andByte &= 0xf;
  1312. xorByte &= 0xf;
  1313. ulValue = nibbleToByteP2RD[andByte]
  1314. | (nibbleToByteP2RD[xorByte] >> 1);
  1315. P2RD_LOAD_CURSOR_ARRAY (ulValue);
  1316. }
  1317. if ( cpelFraction )
  1318. {
  1319. andByte = *pjAnd & jMask;
  1320. xorByte = *pjXor & jMask;
  1321. ulValue = nibbleToByteP2RD[andByte >> 4]
  1322. | (nibbleToByteP2RD[xorByte >> 4] >> 1);
  1323. P2RD_LOAD_CURSOR_ARRAY (ulValue);
  1324. andByte &= 0xf;
  1325. xorByte &= 0xf;
  1326. ulValue = nibbleToByteP2RD[andByte]
  1327. | (nibbleToByteP2RD[xorByte] >> 1);
  1328. P2RD_LOAD_CURSOR_ARRAY (ulValue);
  1329. }
  1330. //
  1331. // Finally clear out any remaining cursor pels on this line.
  1332. //
  1333. if ( cClear )
  1334. {
  1335. for ( j = 0; j < cClear; ++j )
  1336. {
  1337. P2RD_LOAD_CURSOR_ARRAY (P2RD_CURSOR_2_COLOR_TRANSPARENT);
  1338. }
  1339. }
  1340. }
  1341. //
  1342. // If we've loaded fewer than the full number of lines configured in
  1343. // the cursor RAM, clear out the remaining lines. cRemPels is
  1344. // precalculated to be the number of lines * number of pels per line.
  1345. //
  1346. if ( cRemPels > 0 )
  1347. {
  1348. do
  1349. {
  1350. P2RD_LOAD_CURSOR_ARRAY (P2RD_CURSOR_2_COLOR_TRANSPARENT);
  1351. }
  1352. while ( --cRemPels > 0 );
  1353. }
  1354. }// if ( !pointerIsCached )
  1355. //
  1356. // Now set-up the cursor colors
  1357. //
  1358. P2RD_CURSOR_PALETTE_CURSOR_RGB(0, 0x00, 0x00, 0x00);
  1359. P2RD_CURSOR_PALETTE_CURSOR_RGB(1, 0xFF, 0xFF, 0xFF);
  1360. //
  1361. // If the new cursor is different to the last cursor then set up
  1362. // the hot spot and other bits'n'pieces. As we currently only support
  1363. // mono cursors we don't need to reload the cursor palette
  1364. //
  1365. if ( ppdev->HWPtrLastCursor != cacheItem || !pointerIsCached )
  1366. {
  1367. //
  1368. // Make this item the last item
  1369. //
  1370. ppdev->HWPtrLastCursor = cacheItem;
  1371. P2RD_CURSOR_HOTSPOT(xHot, yHot);
  1372. }
  1373. if ( x != -1 )
  1374. {
  1375. vMovePointerP2RD (ppdev, x, y);
  1376. //
  1377. // Need to explicitly show the pointer if not using interrupts
  1378. //
  1379. vShowPointerP2RD(ppdev, TRUE);
  1380. }
  1381. DBG_GDI((6, "bSetPointerShapeP2RD done"));
  1382. return(TRUE);
  1383. }// bSetPointerShapeP2RD()
  1384. //-----------------------------------------------------------------------------
  1385. //
  1386. // VOID vEnablePointerP2RD
  1387. //
  1388. // Get the hardware ready to use the 3Dlabs P2RD hardware pointer.
  1389. //
  1390. //-----------------------------------------------------------------------------
  1391. VOID
  1392. vEnablePointerP2RD(PDev* ppdev)
  1393. {
  1394. pP2RDRAMDAC pRamdac;
  1395. ULONG ul;
  1396. PERMEDIA_DECL_VARS;
  1397. P2RD_DECL_VARS;
  1398. PERMEDIA_DECL_INIT;
  1399. DBG_GDI((6, "vEnablePointerP2RD called"));
  1400. ppdev->pvPointerData = &ppdev->ajPointerData[0];
  1401. P2RD_DECL_INIT;
  1402. //
  1403. // get a pointer to the RAMDAC registers from the memory mapped
  1404. // control register space.
  1405. //
  1406. pRamdac = (pP2RDRAMDAC)(ppdev->pulRamdacBase);
  1407. //
  1408. // set up memory mapping for the control registers and save in the pointer
  1409. // specific area provided in ppdev.
  1410. //
  1411. P2RD_PAL_WR_ADDR
  1412. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDPaletteWriteAddress));
  1413. P2RD_PAL_RD_ADDR
  1414. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDPaletteAddressRead));
  1415. P2RD_PAL_DATA
  1416. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDPaletteData));
  1417. P2RD_PIXEL_MASK
  1418. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDPixelMask));
  1419. P2RD_INDEX_ADDR_HI
  1420. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDIndexHigh));
  1421. P2RD_INDEX_ADDR_LO
  1422. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDIndexLow));
  1423. P2RD_INDEX_DATA
  1424. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDIndexedData));
  1425. P2RD_INDEX_CONTROL
  1426. = (ULONG_PTR)TRANSLATE_ADDR_ULONG(&(pRamdac->RDIndexControl));
  1427. //
  1428. // Not used, but set-up zero anyway
  1429. //
  1430. ppdev->xPointerHot = 0;
  1431. ppdev->yPointerHot = 0;
  1432. //
  1433. // Enable auto-increment
  1434. //
  1435. ul = READ_P2RDREG_ULONG(P2RD_INDEX_CONTROL);
  1436. ul |= P2RD_IDX_CTL_AUTOINCREMENT_ENABLED;
  1437. WRITE_P2RDREG_ULONG(P2RD_INDEX_CONTROL, ul);
  1438. P2RD_READ_INDEX_REG(P2RD_CURSOR_CONTROL, pP2RDinfo->cursorControl);
  1439. pP2RDinfo->cursorModeCurrent = pP2RDinfo->cursorModeOff = 0;
  1440. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_MODE, pP2RDinfo->cursorModeOff);
  1441. P2RD_INDEX_REG(P2RD_CURSOR_X_LOW);
  1442. P2RD_LOAD_DATA(0); // cursor x low
  1443. P2RD_LOAD_DATA(0); // cursor x high
  1444. P2RD_LOAD_DATA(0); // cursor y low
  1445. P2RD_LOAD_DATA(0xff); // cursor y high
  1446. P2RD_LOAD_DATA(0); // cursor x hotspot
  1447. P2RD_LOAD_DATA(0); // cursor y hotspot
  1448. }// vEnablePointerP2RD()
  1449. //-----------------------------------------------------------------------------
  1450. //
  1451. // BOOL bP2RDCheckCSBuffering
  1452. //
  1453. // Determine whether we can do color space double buffering in the current mode
  1454. //
  1455. // Returns
  1456. // TRUE if we can do the color space double buffering, FALSE otherwise.
  1457. //
  1458. //-----------------------------------------------------------------------------
  1459. BOOL
  1460. bP2RDCheckCSBuffering(PDev* ppdev)
  1461. {
  1462. return (FALSE);
  1463. }// bP2RDCheckCSBuffering()
  1464. //-----------------------------------------------------------------------------
  1465. //
  1466. // BOOL bP2RDSwapCSBuffers
  1467. //
  1468. // Use the pixel read mask to perform color space double buffering. This is
  1469. // only called when we have 12bpp with interleaved nibbles. We do a polled
  1470. // wait for VBLANK before the swap. In the future we may do all this in the
  1471. // miniport via interrupts.
  1472. //
  1473. // Returns
  1474. // We should never be called if this is inappropriate so return TRUE.
  1475. //
  1476. //-----------------------------------------------------------------------------
  1477. BOOL
  1478. bP2RDSwapCSBuffers(PDev* ppdev,
  1479. LONG bufNo)
  1480. {
  1481. ULONG index;
  1482. ULONG color;
  1483. PERMEDIA_DECL_VARS;
  1484. P2RD_DECL_VARS;
  1485. PERMEDIA_DECL_INIT;
  1486. P2RD_DECL_INIT;
  1487. //
  1488. // Work out the RAMDAC read pixel mask for the buffer
  1489. //
  1490. DBG_GDI((6, "loading the palette to swap to buffer %d", bufNo));
  1491. P2RD_PALETTE_START_WR (0);
  1492. if ( bufNo == 0 )
  1493. {
  1494. for ( index = 0; index < 16; ++index )
  1495. for ( color = 0; color <= 0xff; color += 0x11 )
  1496. P2RD_LOAD_PALETTE (color, color, color);
  1497. }
  1498. else
  1499. {
  1500. for ( color = 0; color <= 0xff; color += 0x11 )
  1501. for ( index = 0; index < 16; ++index )
  1502. P2RD_LOAD_PALETTE (color, color, color);
  1503. }
  1504. return(TRUE);
  1505. }// bP2RDSwapCSBuffers()
  1506. //-------------------------------Public*Routine-------------------------------
  1507. //
  1508. // VOID DrvMovePointer
  1509. //
  1510. // This function moves the pointer to a new position and ensures that GDI does
  1511. // not interfere with the display of the pointer.
  1512. //
  1513. // Parameters:
  1514. // pso-------Points to a SURFOBJ structure that describes the surface of a
  1515. // display device.
  1516. // x,y-------Specify the x and y coordinates on the display where the hot spot
  1517. // of the pointer should be positioned.
  1518. // A negative x value indicates that the pointer should be removed
  1519. // from the display because drawing is about to occur where it is
  1520. // presently located. If the pointer has been removed from the display
  1521. // and the x value is nonnegative, the pointer should be restored.
  1522. //
  1523. // A negative y value indicates that GDI is calling this function only
  1524. // to notify the driver of the cursor's current position. The current
  1525. // position can be computed as (x, y+pso->sizlBitmap.cy).
  1526. // prcl------Points to a RECTL structure defining an area that bounds all pixels
  1527. // affected by the pointer on the display. GDI will not draw in this
  1528. // rectangle without first removing the pointer from the screen. This
  1529. // parameter can be null.
  1530. //
  1531. // NOTE: Because we have set GCAPS_ASYNCMOVE, this call may occur at any
  1532. // time, even while we're executing another drawing call!
  1533. //
  1534. //-----------------------------------------------------------------------------
  1535. VOID
  1536. DrvMovePointer(SURFOBJ* pso,
  1537. LONG x,
  1538. LONG y,
  1539. RECTL* prcl)
  1540. {
  1541. PDev* ppdev = (PDev*)pso->dhpdev;
  1542. DBG_GDI((6, "DrvMovePointer called, dhpdev(%xh), to pos(%ld, %ld)",
  1543. ppdev, x, y));
  1544. //
  1545. // A negative y value indicates that GDI is calling this function only to
  1546. // notify the driver of the cursor's current position. So, at least, for
  1547. // HW cursor, we don't need to move this pointer. Just return
  1548. //
  1549. if ( ( y < 0 ) && ( x > 0 ) )
  1550. {
  1551. DBG_GDI((6, "DrvMovePointer return because x and y both < 0"));
  1552. return;
  1553. }
  1554. DBG_GDI((6, "DrvMovePointer really moves HW pointer"));
  1555. //
  1556. // Negative X indicates that the pointer should be removed from the display
  1557. // because drawing is about to occur where it is presently located.
  1558. //
  1559. if ( x > -1 )
  1560. {
  1561. //
  1562. // If we're doing any hardware zooming then the cusor position will
  1563. // have to be doubled.
  1564. //
  1565. if ( (ppdev->flCaps & CAPS_P2RD_POINTER) == 0 )
  1566. {
  1567. if ( ppdev->flCaps & CAPS_ZOOM_Y_BY2 )
  1568. {
  1569. DBG_GDI((6,"HW zooming Y_BY2"));
  1570. y *= 2;
  1571. }
  1572. if ( ppdev->flCaps & CAPS_ZOOM_X_BY2 )
  1573. {
  1574. DBG_GDI((6,"HW zooming X_BY2"));
  1575. x *= 2;
  1576. }
  1577. }
  1578. //
  1579. // If they have genuinely moved the cursor, then move it
  1580. //
  1581. if ( (x != ppdev->HWPtrPos_X) || (y != ppdev->HWPtrPos_Y) )
  1582. {
  1583. if ( ppdev->flCaps & CAPS_TVP4020_POINTER )
  1584. {
  1585. vMovePointerTVP4020(ppdev, x, y);
  1586. }
  1587. else if ( ppdev->flCaps & CAPS_P2RD_POINTER )
  1588. {
  1589. vMovePointerP2RD(ppdev, x, y);
  1590. }
  1591. ppdev->HWPtrPos_X = x;
  1592. ppdev->HWPtrPos_Y = y;
  1593. }
  1594. //
  1595. // We may have to make the pointer visible:
  1596. //
  1597. if ( !(ppdev->flPointer & PTR_HW_ACTIVE) )
  1598. {
  1599. DBG_GDI((6, "Showing hardware pointer"));
  1600. ppdev->flPointer |= PTR_HW_ACTIVE;
  1601. if ( ppdev->flCaps & CAPS_TVP4020_POINTER )
  1602. {
  1603. vShowPointerTVP4020(ppdev, TRUE);
  1604. }
  1605. else if ( ppdev->flCaps & CAPS_P2RD_POINTER )
  1606. {
  1607. vShowPointerP2RD(ppdev, TRUE);
  1608. }
  1609. }
  1610. }// if ( x > -1 )
  1611. else if ( ppdev->flPointer & PTR_HW_ACTIVE )
  1612. {
  1613. //
  1614. // The pointer is visible, and we've been asked to hide it
  1615. //
  1616. DBG_GDI((6, "Hiding hardware pointer"));
  1617. ppdev->flPointer &= ~PTR_HW_ACTIVE;
  1618. if ( ppdev->flCaps & CAPS_TVP4020_POINTER )
  1619. {
  1620. DBG_GDI((7, "Showing hardware pointer"));
  1621. vShowPointerTVP4020(ppdev, FALSE);
  1622. }
  1623. else if ( ppdev->flCaps & CAPS_P2RD_POINTER )
  1624. {
  1625. vShowPointerP2RD(ppdev, FALSE);
  1626. }
  1627. }
  1628. //
  1629. // Note that we don't have to modify 'prcl', since we have a
  1630. // NOEXCLUDE pointer...
  1631. //
  1632. DBG_GDI((6, "DrvMovePointer exited, dhpdev(%xh)", ppdev));
  1633. }// DrvMovePointer()
  1634. //---------------------------Public*Routine------------------------------------
  1635. //
  1636. // VOID DrvSetPointerShape
  1637. //
  1638. // This function is used to request the driver to:
  1639. //
  1640. // 1) Take the pointer off the display, if the driver has drawn it there.
  1641. // 2) Attempt to set a new pointer shape.
  1642. // 3) Put the new pointer on the display at a specified position.
  1643. //
  1644. // Parameters:
  1645. // psO-------Points to a SURFOBJ structure that describes the surface on which
  1646. // TO draw.
  1647. // psoMask---Points to a SURFOBJ structure that defines the AND-XOR mask. (The
  1648. // AND-XOR mask is described in Drawing Monochrome Pointers.) The
  1649. // dimensions of this bitmap determine the size of the pointer. There
  1650. // are no implicit constraints on pointer sizes, but optimal pointer
  1651. // sizes are 32 x 32, 48 x 48, and 64 x 64 pixels. If this parameter
  1652. // IS NULL, the pointer is transparent.
  1653. // psoColor--Points to a SURFOBJ structure that defines the colors for a color
  1654. // pointer. If this parameter is NULL, the pointer is monochrome. The
  1655. // pointer bitmap has the same width as psoMask and half the height.
  1656. // pxlo------Points to a XLATEOBJ structure that defines the colors in psoColor.
  1657. // xHot,yHot-Specify the x and y positions of the pointer's hot spot relative
  1658. // to its upper-left pixel. The pixel indicated by the hot spot should
  1659. // be positioned at the new pointer position.
  1660. // x, y------Specify the new pointer position.
  1661. // prcl------Is the location in which the driver should write a rectangle that
  1662. // specifies a tight bound for the visible portion of the pointer.
  1663. // fl--------Specifies an extensible set of flags. The driver should decline the
  1664. // call if any flags are set that it does not understand. This
  1665. // parameter can be one or more of the following predefined values,
  1666. // and one or more driver-defined values:
  1667. // Flag Meaning
  1668. // SPS_CHANGE----------The driver is requested to change the pointer shape.
  1669. // SPS_ASYNCCHANGE-----This flag is obsolete. For legacy drivers, the driver
  1670. // should accept the change only if it is capable of
  1671. // changing the pointer shape in the hardware while other
  1672. // drawing is underway on the device. GDI uses this option
  1673. // only if the now obsolete GCAPS_ASYNCCHANGE flag is set
  1674. // in the flGraphicsCaps member of the DEVINFO structure.
  1675. // SPS_ANIMATESTART----The driver should be prepared to receive a series of
  1676. // similarly-sized pointer shapes that will comprise an
  1677. // animated pointer effect.
  1678. // SPS_ANIMATEUPDATE---The driver should draw the next pointer shape in the
  1679. // animated series.
  1680. // SPS_ALPHA-----------The pointer has per-pixel alpha values.
  1681. //
  1682. // Return Value
  1683. // The return value can be one of the following values:
  1684. //
  1685. // Value Meaning
  1686. // SPS_ERROR-----------The driver normally supports this shape, but failed for
  1687. // unusual reasons.
  1688. // SPS_DECLINE---------The driver does not support the shape, so GDI must
  1689. // simulate it.
  1690. // SPS_ACCEPT_NOEXCLUDE-The driver accepts the shape. The shape is supported
  1691. // in hardware and GDI is not concerned about other
  1692. // drawings overwriting the pointer.
  1693. // SPS_ACCEPT_EXCLUDE--Is obsolete. GDI will disable the driver's pointer and
  1694. // revert to software simulation if the driver returns
  1695. // this value.
  1696. //
  1697. //-----------------------------------------------------------------------------
  1698. ULONG
  1699. DrvSetPointerShape(SURFOBJ* pso,
  1700. SURFOBJ* psoMsk,
  1701. SURFOBJ* psoColor,
  1702. XLATEOBJ* pxlo,
  1703. LONG xHot,
  1704. LONG yHot,
  1705. LONG x,
  1706. LONG y,
  1707. RECTL* prcl,
  1708. FLONG fl)
  1709. {
  1710. PDev* ppdev;
  1711. BOOL bAccept = FALSE;
  1712. ppdev = (PDev*)pso->dhpdev;
  1713. DBG_GDI((6, "DrvSetPointerShape called, dhpdev(%x)", ppdev));
  1714. DBG_GDI((6, "DrvSetPointerShape psocolor (0x%x)", psoColor));
  1715. //
  1716. // When CAPS_SW_POINTER is set, we have no hardware pointer available,
  1717. // so we always ask GDI to simulate the pointer for us, using
  1718. // DrvCopyBits calls:
  1719. //
  1720. if ( ppdev->flCaps & CAPS_SW_POINTER )
  1721. {
  1722. DBG_GDI((6, "SetPtrShape: CAPS_SW_POINTER not set, rtn SPS_DECLINE"));
  1723. return (SPS_DECLINE);
  1724. }
  1725. //
  1726. // We're not going to handle flags that we don't understand.
  1727. //
  1728. if ( !(fl & SPS_CHANGE) )
  1729. {
  1730. DBG_GDI((6, "DrvSetPointerShape decline: Unknown flag =%x", fl));
  1731. goto HideAndDecline;
  1732. }
  1733. //
  1734. // Remove any pointer first.
  1735. // We have a special x value for the software cursor to indicate that
  1736. // it should be removed immediatly, not delayed. DrvMovePointer needs to
  1737. // recognise it as remove for any pointers though.
  1738. // Note: CAPS_{P2RD, TVP4020, SW}_POINTER should be set in miniport after
  1739. // it detects the DAC type
  1740. //
  1741. if ( x != -1 )
  1742. {
  1743. if ( (ppdev->flCaps & CAPS_P2RD_POINTER) == 0 )
  1744. {
  1745. //
  1746. // If we're doing any hardware zooming then the cusor position will
  1747. // have to be doubled.
  1748. //
  1749. if ( ppdev->flCaps & CAPS_ZOOM_Y_BY2 )
  1750. {
  1751. y *= 2;
  1752. }
  1753. if ( ppdev->flCaps & CAPS_ZOOM_X_BY2 )
  1754. {
  1755. x *= 2;
  1756. }
  1757. }
  1758. }
  1759. DBG_GDI((6, "iUniq is %ld", psoMsk->iUniq));
  1760. if ( ppdev->flCaps & CAPS_TVP4020_POINTER )
  1761. {
  1762. DBG_GDI((6, "DrvSetPointerShape tring to set TVP4020 pointer"));
  1763. bAccept = bSetPointerShapeTVP4020(ppdev, psoMsk, psoColor,
  1764. x, y, xHot, yHot);
  1765. }
  1766. else if ( ppdev->flCaps & CAPS_P2RD_POINTER )
  1767. {
  1768. bAccept = bSetPointerShapeP2RD(ppdev, psoMsk, psoColor, pxlo,
  1769. x, y, xHot, yHot);
  1770. }
  1771. //
  1772. // If we failed setup the hardware pointer shape, then return SPS_DECLINE
  1773. // and let GDI handles it
  1774. //
  1775. if ( !bAccept )
  1776. {
  1777. DBG_GDI((6, "set hardware pointer shape failed"));
  1778. return (SPS_DECLINE);
  1779. }
  1780. //
  1781. // Set flag to indicate that we have initialized hardware pointer shape
  1782. // so that in vAssertModePointer, we can do some clean up
  1783. //
  1784. ppdev->bPointerInitialized = TRUE;
  1785. if ( x != -1 )
  1786. {
  1787. //
  1788. // Save the X and Y values
  1789. //
  1790. ppdev->HWPtrPos_X = x;
  1791. ppdev->HWPtrPos_Y = y;
  1792. ppdev->flPointer |= PTR_HW_ACTIVE;
  1793. }
  1794. else
  1795. {
  1796. ppdev->flPointer &= ~PTR_HW_ACTIVE;
  1797. }
  1798. //
  1799. // Since it's a hardware pointer, GDI doesn't have to worry about
  1800. // overwriting the pointer on drawing operations (meaning that it
  1801. // doesn't have to exclude the pointer), so we return 'NOEXCLUDE'.
  1802. // Since we're returning 'NOEXCLUDE', we also don't have to update
  1803. // the 'prcl' that GDI passed us.
  1804. //
  1805. DBG_GDI((6, "DrvSetPointerShape return SPS_ACCEPT_NOEXCLUDE"));
  1806. return (SPS_ACCEPT_NOEXCLUDE);
  1807. HideAndDecline:
  1808. //
  1809. // Remove whatever pointer is installed.
  1810. //
  1811. DrvMovePointer(pso, -2, -1, NULL);
  1812. ppdev->flPointer &= ~PTR_SW_ACTIVE;
  1813. DBG_GDI((6, "Cursor declined"));
  1814. DBG_GDI((6, "DrvSetPointerShape exited (cursor declined)"));
  1815. return (SPS_DECLINE);
  1816. }// DrvSetPointerShape()
  1817. //-----------------------------------------------------------------------------
  1818. //
  1819. // VOID vAssertModePointer
  1820. //
  1821. // Do whatever has to be done to enable everything but hide the pointer.
  1822. //
  1823. //-----------------------------------------------------------------------------
  1824. VOID
  1825. vAssertModePointer(PDev* ppdev,
  1826. BOOL bEnable)
  1827. {
  1828. DBG_GDI((6, "vAssertModePointer called"));
  1829. if ( (ppdev->bPointerInitialized == FALSE)
  1830. ||(ppdev->flCaps & CAPS_SW_POINTER) )
  1831. {
  1832. //
  1833. // With a software pointer, or the pointer hasn't been initialized,
  1834. // we don't have to do anything.
  1835. //
  1836. return;
  1837. }
  1838. //
  1839. // Invalidate the hardware pointer cache
  1840. //
  1841. HWPointerCacheInvalidate(&(ppdev->HWPtrCache));
  1842. if ( ppdev->flCaps & CAPS_TVP4020_POINTER )
  1843. {
  1844. vShowPointerTVP4020(ppdev, FALSE);
  1845. }
  1846. else if ( ppdev->flCaps & CAPS_P2RD_POINTER )
  1847. {
  1848. vShowPointerP2RD(ppdev, FALSE);
  1849. }
  1850. else if ( ppdev->flCaps & CAPS_P2RD_POINTER )
  1851. {
  1852. vEnablePointerP2RD(ppdev);
  1853. }
  1854. ppdev->flPointer &= ~(PTR_HW_ACTIVE | PTR_SW_ACTIVE);
  1855. }// vAssertModePointer()
  1856. //-----------------------------------------------------------------------------
  1857. //
  1858. // BOOL bEnablePointer(PDev* ppdev)
  1859. //
  1860. // This function initializes hardware pointer or software pointer depends on
  1861. // on the CAPS settinsg in ppdev->flCaps
  1862. //
  1863. // This function always returns TRUE
  1864. //
  1865. //-----------------------------------------------------------------------------
  1866. BOOL
  1867. bEnablePointer(PDev* ppdev)
  1868. {
  1869. DBG_GDI((6, "bEnablePointer called"));
  1870. //
  1871. // Initialise the pointer cache.
  1872. //
  1873. HWPointerCacheInit(&(ppdev->HWPtrCache));
  1874. //
  1875. // Set the last cursor to something invalid
  1876. //
  1877. ppdev->HWPtrLastCursor = HWPTRCACHE_INVALIDENTRY;
  1878. //
  1879. // Initialise the X and Y values to something silly
  1880. //
  1881. ppdev->HWPtrPos_X = 1000000000;
  1882. ppdev->HWPtrPos_Y = 1000000000;
  1883. if ( ppdev->flCaps & CAPS_SW_POINTER )
  1884. {
  1885. // With a software pointer, we don't have to do anything.
  1886. }
  1887. else if ( ppdev->flCaps & CAPS_TVP4020_POINTER )
  1888. {
  1889. vEnablePointerTVP4020(ppdev);
  1890. }
  1891. else if ( ppdev->flCaps & CAPS_P2RD_POINTER )
  1892. {
  1893. vEnablePointerP2RD(ppdev);
  1894. }
  1895. return (TRUE);
  1896. }// bEnablePointer()