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.

1652 lines
58 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: pointer.c
  8. *
  9. * Content:
  10. *
  11. * This module contains the hardware pointer support for the display
  12. * driver. This supports the IBM RGB525 RAMDAC pointer. We also have
  13. * support for color space double buffering using the RAMDAC pixel
  14. * read mask.
  15. *
  16. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  17. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  18. \*****************************************************************************/
  19. #include "precomp.h"
  20. #include "glint.h"
  21. #include "p3rd.h"
  22. BOOL bSet3ColorPointerShapeP3RD(PPDEV ppdev, SURFOBJ *psoMask, SURFOBJ *psoColor,
  23. LONG x, LONG y, LONG xHot, LONG yHot);
  24. BOOL bSet15ColorPointerShapeP3RD(PPDEV ppdev, SURFOBJ *psoMask, SURFOBJ *psoColor,
  25. LONG x, LONG y, LONG xHot, LONG yHot);
  26. /******************************Public*Routine******************************\
  27. * VOID DrvMovePointer
  28. *
  29. * NOTE: Because we have set GCAPS_ASYNCMOVE, this call may occur at any
  30. * time, even while we're executing another drawing call!
  31. *
  32. \**************************************************************************/
  33. VOID DrvMovePointer(
  34. SURFOBJ* pso,
  35. LONG x,
  36. LONG y,
  37. RECTL* prcl)
  38. {
  39. OH* poh;
  40. PDEV* ppdev = (PDEV*) pso->dhpdev;
  41. DISPDBG((DBGLVL, "DrvMovePointer called"));
  42. if (x > -1)
  43. {
  44. // Convert the pointer's position from relative to absolute
  45. // coordinates (this is only significant for multiple board
  46. // support):
  47. poh = ((DSURF*) pso->dhsurf)->poh;
  48. x += poh->x;
  49. y += poh->y;
  50. // If we're doing any hardware zooming then the cusor position will
  51. // have to be doubled.
  52. //
  53. if (ppdev->flCaps & CAPS_ZOOM_Y_BY2)
  54. y *= 2;
  55. if (ppdev->flCaps & CAPS_ZOOM_X_BY2)
  56. x *= 2;
  57. // If they have genuinely moved the cursor, then
  58. // move it
  59. if (x != ppdev->HWPtrPos_X || y != ppdev->HWPtrPos_Y)
  60. {
  61. vMovePointerP3RD(ppdev, x, y);
  62. ppdev->HWPtrPos_X = x;
  63. ppdev->HWPtrPos_Y = y;
  64. }
  65. // We may have to make the pointer visible:
  66. if (!(ppdev->flPointer & PTR_HW_ACTIVE))
  67. {
  68. DISPDBG((DBGLVL, "Showing hardware pointer"));
  69. ppdev->flPointer |= PTR_HW_ACTIVE;
  70. vShowPointerP3RD(ppdev, TRUE);
  71. }
  72. }
  73. else if (ppdev->flPointer & PTR_HW_ACTIVE)
  74. {
  75. // The pointer is visible, and we've been asked to hide it:
  76. DISPDBG((DBGLVL, "Hiding hardware pointer"));
  77. ppdev->flPointer &= ~PTR_HW_ACTIVE;
  78. vShowPointerP3RD(ppdev, FALSE);
  79. }
  80. #if DBG
  81. else
  82. {
  83. DISPDBG((DBGLVL, "DrvMovePointer: x == -1 but not PTR_HW_ACTIVE"));
  84. }
  85. #endif
  86. // Note that we don't have to modify 'prcl', since we have a
  87. // NOEXCLUDE pointer...
  88. DISPDBG((DBGLVL, "DrvMovePointer exited"));
  89. }
  90. /******************************Public*Routine******************************\
  91. * VOID DrvSetPointerShape
  92. *
  93. * Sets the new pointer shape.
  94. *
  95. \**************************************************************************/
  96. ULONG DrvSetPointerShape(
  97. SURFOBJ* pso,
  98. SURFOBJ* psoMsk,
  99. SURFOBJ* psoColor,
  100. XLATEOBJ* pxlo,
  101. LONG xHot,
  102. LONG yHot,
  103. LONG x,
  104. LONG y,
  105. RECTL* prcl,
  106. FLONG fl)
  107. {
  108. PDEV* ppdev;
  109. OH *poh;
  110. BOOL bAccept;
  111. DISPDBG((DBGLVL, "DrvSetPointerShape called"));
  112. ppdev = (PDEV*) pso->dhpdev;
  113. if (!(fl & SPS_CHANGE))
  114. {
  115. goto HideAndDecline;
  116. }
  117. ASSERTDD(psoMsk != NULL, "GDI gave us a NULL psoMsk. It can't do that!");
  118. ASSERTDD(pso->iType == STYPE_DEVICE, "GDI gave us a weird surface");
  119. if (x != -1)
  120. {
  121. // Convert the pointer's position from relative to absolute
  122. // coordinates (this is only significant for multiple board
  123. // support):
  124. if (pso->dhsurf != NULL)
  125. {
  126. poh = ((DSURF*) pso->dhsurf)->poh;
  127. x += poh->x;
  128. y += poh->y;
  129. }
  130. // If we're doing any hardware zooming then the cusor position will
  131. // have to be doubled.
  132. //
  133. if (ppdev->flCaps & CAPS_ZOOM_Y_BY2)
  134. y *= 2;
  135. if (ppdev->flCaps & CAPS_ZOOM_X_BY2)
  136. x *= 2;
  137. }
  138. // See if our hardware cursor can handle this.
  139. bAccept = bSetPointerShapeP3RD(ppdev, psoMsk, psoColor, pxlo,
  140. x, y, xHot, yHot);
  141. if (bAccept)
  142. {
  143. if (x != -1)
  144. {
  145. // Save the X and Y values
  146. ppdev->HWPtrPos_X = x;
  147. ppdev->HWPtrPos_Y = y;
  148. ppdev->flPointer |= PTR_HW_ACTIVE;
  149. }
  150. else
  151. {
  152. ppdev->flPointer &= ~PTR_HW_ACTIVE;
  153. }
  154. // Since it's a hardware pointer, GDI doesn't have to worry about
  155. // overwriting the pointer on drawing operations (meaning that it
  156. // doesn't have to exclude the pointer), so we return 'NOEXCLUDE'.
  157. // Since we're returning 'NOEXCLUDE', we also don't have to update
  158. // the 'prcl' that GDI passed us.
  159. return(SPS_ACCEPT_NOEXCLUDE);
  160. }
  161. HideAndDecline:
  162. // Remove whatever pointer is installed.
  163. DrvMovePointer(pso, -2, -1, NULL);
  164. DISPDBG((DBGLVL, "Cursor declined"));
  165. return(SPS_DECLINE);
  166. }
  167. /******************************Public*Routine******************************\
  168. * VOID vDisablePointer
  169. *
  170. \**************************************************************************/
  171. VOID vDisablePointer(
  172. PDEV* ppdev)
  173. {
  174. if(ppdev->bPointerEnabled)
  175. {
  176. vDisablePointerP3RD(ppdev);
  177. }
  178. }
  179. /******************************Public*Routine******************************\
  180. * VOID vAssertModePointer
  181. *
  182. * Do whatever has to be done to enable everything but hide the pointer.
  183. *
  184. \**************************************************************************/
  185. VOID vAssertModePointer(
  186. PDEV* ppdev,
  187. BOOL bEnable)
  188. {
  189. // Invalidate the hardware pointer cache
  190. HWPointerCacheInvalidate (&(ppdev->HWPtrCache));
  191. // Remove the hardware pointer
  192. vShowPointerP3RD(ppdev, FALSE);
  193. ppdev->flPointer &= ~PTR_HW_ACTIVE;
  194. }
  195. /******************************Public*Routine******************************\
  196. * BOOL bEnablePointer
  197. *
  198. \**************************************************************************/
  199. BOOL bEnablePointer(
  200. PDEV* ppdev)
  201. {
  202. // Initialise the pointer cache.
  203. HWPointerCacheInit (&(ppdev->HWPtrCache));
  204. // Set the last cursor to something invalid
  205. ppdev->HWPtrLastCursor = HWPTRCACHE_INVALIDENTRY;
  206. // Initialise the X and Y values to something invalid.
  207. ppdev->HWPtrPos_X = 1000000000;
  208. ppdev->HWPtrPos_Y = 1000000000;
  209. // Call the enable function
  210. vEnablePointerP3RD(ppdev);
  211. // Mark the pointer as enabled for this PDEV
  212. ppdev->bPointerEnabled = TRUE;
  213. return(TRUE);
  214. }
  215. /****************************************************************************************
  216. * *
  217. * 64 x 64 Hardware Pointer Caching *
  218. * -------------------------------- *
  219. * The code below implements hardware independent caching of pointers, it maintains *
  220. * a cache big enough to store ONE 64x64 cursor or FOUR 32x32 cursors. The code will *
  221. * work with all RAMDACs that support this form of caching (i.e. the RGB525 and TVP3033)*
  222. * however the TVP3026 supports a 64x64 cursor but this can't be broken down into 4 *
  223. * smaller ones. *
  224. * *
  225. ****************************************************************************************/
  226. /******************************Public*Routine******************************\
  227. * LONG HWPointerCacheInit
  228. *
  229. * Initialise the hardware pointer cache.
  230. \**************************************************************************/
  231. VOID
  232. HWPointerCacheInit (HWPointerCache * ptrCache)
  233. {
  234. ptrCache->ptrCacheInUseCount = 0;
  235. ptrCache->ptrCacheCurTimeStamp = 0;
  236. }
  237. /******************************Public*Routine******************************\
  238. * LONG HWPointerCacheCheckAndAdd
  239. *
  240. * This function does a byte-by-byte comparison of the supplied pointer data
  241. * with each pointer that is in cache, if it finds a matching one then it
  242. * returns the index of the item in the cache (0 to 3) otherwise it adds it to
  243. * the cache and returns the index.
  244. \**************************************************************************/
  245. LONG
  246. HWPointerCacheCheckAndAdd (HWPointerCache * ptrCache, ULONG cx, ULONG cy,
  247. LONG lDelta, BYTE * scan0, BOOL * isCached)
  248. {
  249. BOOL pointerIsCached = FALSE;
  250. BOOL isLargePtr = (cx > 32) || (cy > 32);
  251. LONG i, j, z;
  252. LONG cacheItem;
  253. #if !defined(_WIN64)
  254. //@@BEGIN_DDKSPLIT
  255. // Quick Fix IA64 AV
  256. //@@END_DDKSPLIT
  257. // If there are entries in the cache and they are the same format as the one
  258. // that we are looking for then search the cache.
  259. if (ptrCache->ptrCacheInUseCount && ptrCache->ptrCacheIsLargePtr == isLargePtr)
  260. {
  261. // *** SEARCH THE CACHE ***
  262. LONG xInBytes = (cx >> 3);
  263. LONG yInLines = (cy << 1); // The AND plane and the XOR plane
  264. BYTE jMask = gajMask [cx & 0x7];
  265. LONG cacheCnt = ptrCache->ptrCacheInUseCount;
  266. // Examine all valid entries in the cache to see if they are the same as the
  267. // pointer that we've been handed.
  268. for (z = 0; !pointerIsCached && z < cacheCnt; z++)
  269. {
  270. BYTE * cacheLinePtr = ((BYTE *) ptrCache->ptrCacheData) + (z * SMALL_POINTER_MEM);
  271. BYTE * cachePtr;
  272. LONG cacheLDelta = ptrCache->ptrCacheItemList [z].ptrCacheLDelta;
  273. BYTE * scanLinePtr = (BYTE *) scan0;
  274. BYTE * scanPtr;
  275. // Compare the data
  276. for (i = 0, pointerIsCached = TRUE; pointerIsCached && i < yInLines; i++)
  277. {
  278. cachePtr = cacheLinePtr;
  279. scanPtr = scanLinePtr;
  280. // Compare each byte - could do a series of long comparisons here.
  281. for (j = 0; (j < xInBytes) && (*scanPtr == *cachePtr); j++, scanPtr++, cachePtr++)
  282. ;
  283. pointerIsCached = (j == xInBytes) &&
  284. ((*scanPtr & jMask) == (*cachePtr & jMask));
  285. cacheLinePtr += cacheLDelta;
  286. scanLinePtr += lDelta;
  287. }
  288. cacheItem = z;
  289. }
  290. }
  291. #endif // !defined(_WIN64)
  292. // If we couldn't find an entry in the pointer cache then add one to the cache.
  293. if (!pointerIsCached)
  294. {
  295. /* **** ADD POINTER TO THE CACHE ****** */
  296. LONG xInBytes = ((cx + 7) >> 3);
  297. LONG yInLines = (cy << 1); // The AND plane and the XOR plane
  298. BYTE * scanLinePtr = (BYTE *) scan0;
  299. BYTE * scanPtr;
  300. BYTE * cacheLinePtr;
  301. BYTE * cachePtr;
  302. LONG cacheLDelta = (cx <= 32) ? 4 : 8;
  303. BYTE jMask = gajMask [cx & 0x7];
  304. // If the new pointer is a big one then re-use item 0, else if
  305. // the pointer is small and there are some spare entries then allocate
  306. // a free entry, otherwise find the least recently used entry and use
  307. // that.
  308. if (isLargePtr)
  309. {
  310. cacheItem = 0;
  311. }
  312. else if (ptrCache->ptrCacheInUseCount < SMALL_POINTER_MAX)
  313. {
  314. cacheItem = ptrCache->ptrCacheInUseCount++;
  315. }
  316. else
  317. {
  318. ULONG oldestValue = 0xFFFFFFFF;
  319. // look for the LRU entry
  320. for (z = 0, cacheItem = 0; z < SMALL_POINTER_MAX; z++)
  321. {
  322. if (ptrCache->ptrCacheItemList [z].ptrCacheTimeStamp < oldestValue)
  323. {
  324. cacheItem = z;
  325. oldestValue = ptrCache->ptrCacheItemList [z].ptrCacheTimeStamp;
  326. }
  327. }
  328. }
  329. // Get a pointer to the first line in the cache
  330. cacheLinePtr = ((BYTE *) ptrCache->ptrCacheData) + (cacheItem * SMALL_POINTER_MEM);
  331. // Add the pointer to the cache
  332. for (i = 0; i < yInLines; i++)
  333. {
  334. cachePtr = cacheLinePtr;
  335. scanPtr = scanLinePtr;
  336. for (j = 0; (j < xInBytes); j++, scanPtr++, cachePtr++)
  337. *cachePtr = *scanPtr;
  338. cacheLinePtr += cacheLDelta;
  339. scanLinePtr += lDelta;
  340. }
  341. // If the pointer type is different then reset the whole
  342. // cache
  343. if (ptrCache->ptrCacheIsLargePtr != isLargePtr)
  344. {
  345. ptrCache->ptrCacheInUseCount = 1;
  346. ptrCache->ptrCacheIsLargePtr = (BYTE)isLargePtr;
  347. }
  348. // Set up the cache entry
  349. ptrCache->ptrCacheItemList [cacheItem].ptrCacheLDelta = cacheLDelta;
  350. ptrCache->ptrCacheItemList [cacheItem].ptrCacheCX = cx;
  351. ptrCache->ptrCacheItemList [cacheItem].ptrCacheCY = cy;
  352. }
  353. // Set the timestamp
  354. ptrCache->ptrCacheItemList [cacheItem].ptrCacheTimeStamp = ptrCache->ptrCacheCurTimeStamp++;
  355. // Set up the return value to say whether the pointer was cached
  356. *isCached = pointerIsCached;
  357. return (cacheItem);
  358. }
  359. //@@BEGIN_DDKSPLIT
  360. // NickM says we have to disable the cursor to stop nasty flashing occurring,
  361. // however there is a potential exploding flashing cursor syndrome that this may
  362. // cause.
  363. // Note that this problem only seems to cause us problems when switching between
  364. // mono and colour cursors.
  365. //@@END_DDKSPLIT
  366. #define DISABLE_CURSOR_MODE(){ \
  367. ULONG curCurMode, curLine; \
  368. ULONG start = (pP3RDinfo->y > 8) ? (pP3RDinfo->y - 8) : 0; \
  369. ULONG end = pP3RDinfo->y + 64; \
  370. do { \
  371. READ_GLINT_CTRL_REG (LineCount, curLine); \
  372. } while ((curLine >= start) && (curLine <= end)); \
  373. P3RD_READ_INDEX_REG(P3RD_CURSOR_MODE, curCurMode); \
  374. P3RD_LOAD_INDEX_REG(P3RD_CURSOR_MODE, (curCurMode & (~P3RD_CURSOR_MODE_ENABLED))); \
  375. }
  376. // Look-up table for masking the right edge of the given pointer bitmap:
  377. //
  378. BYTE gajMask[] = {
  379. 0x00, 0x80, 0xC0, 0xE0,
  380. 0xF0, 0xF8, 0xFC, 0xFE,
  381. };
  382. /******************************Public*Routine******************************\
  383. * VOID vShowPointerP3RD
  384. *
  385. * Show or hide the 3Dlabs P3RD hardware pointer.
  386. *
  387. \**************************************************************************/
  388. VOID
  389. vShowPointerP3RD(
  390. PPDEV ppdev,
  391. BOOL bShow)
  392. {
  393. ULONG cmr;
  394. GLINT_DECL_VARS;
  395. P3RD_DECL_VARS;
  396. GLINT_DECL_INIT;
  397. P3RD_DECL_INIT;
  398. DISPDBG((DBGLVL, "vShowPointerP3RD (%s)", bShow ? "on" : "off"));
  399. if (bShow)
  400. {
  401. // no need to sync since this case is called only if we've just moved
  402. // the cursor and that will already have done a sync.
  403. P3RD_LOAD_INDEX_REG(P3RD_CURSOR_MODE, (pP3RDinfo->cursorModeCurrent | P3RD_CURSOR_MODE_ENABLED));
  404. P3RD_MOVE_CURSOR (pP3RDinfo->x, pP3RDinfo->y);
  405. }
  406. else
  407. {
  408. // move the cursor off screen
  409. P3RD_LOAD_INDEX_REG(P3RD_CURSOR_Y_HIGH, 0xff);
  410. }
  411. }
  412. /******************************Public*Routine******************************\
  413. * VOID vMovePointerP3RD
  414. *
  415. * Move the 3Dlabs P3RD hardware pointer.
  416. *
  417. \**************************************************************************/
  418. VOID
  419. vMovePointerP3RD(
  420. PPDEV ppdev,
  421. LONG x,
  422. LONG y)
  423. {
  424. GLINT_DECL_VARS;
  425. P3RD_DECL_VARS;
  426. GLINT_DECL_INIT;
  427. P3RD_DECL_INIT;
  428. DISPDBG((DBGLVL, "vMovePointerP3RD to (%d, %d)", x, y));
  429. pP3RDinfo->x = x;
  430. pP3RDinfo->y = y;
  431. P3RD_SYNC_WITH_GLINT;
  432. P3RD_MOVE_CURSOR (x, y);
  433. }
  434. /******************************Public*Routine******************************\
  435. * BOOL bSetPointerShapeP3RD
  436. *
  437. * Set the 3Dlabs hardware pointer shape.
  438. *
  439. \**************************************************************************/
  440. UCHAR nibbleToByteP3RD[] = {
  441. 0x00, // 0000 --> 00000000
  442. 0x80, // 0001 --> 10000000
  443. 0x20, // 0010 --> 00100000
  444. 0xA0, // 0011 --> 10100000
  445. 0x08, // 0100 --> 00001000
  446. 0x88, // 0101 --> 10001000
  447. 0x28, // 0110 --> 00101000
  448. 0xA8, // 0111 --> 10101000
  449. 0x02, // 1000 --> 00000010
  450. 0x82, // 1001 --> 10000010
  451. 0x22, // 1010 --> 00100010
  452. 0xA2, // 1011 --> 10100010
  453. 0x0A, // 1100 --> 00001010
  454. 0x8A, // 1101 --> 10001010
  455. 0x2A, // 1110 --> 00101010
  456. 0xAA, // 1111 --> 10101010
  457. };
  458. BOOL
  459. bSetPointerShapeP3RD(
  460. PPDEV ppdev,
  461. SURFOBJ *pso, // defines AND and MASK bits for cursor
  462. SURFOBJ *psoColor, // we may handle some color cursors at some point
  463. XLATEOBJ* pxlo,
  464. LONG x, // If -1, pointer should be created hidden
  465. LONG y,
  466. LONG xHot,
  467. LONG yHot)
  468. {
  469. ULONG cx;
  470. ULONG cy;
  471. LONG i;
  472. LONG j;
  473. ULONG ulValue;
  474. BYTE* pjAndScan;
  475. BYTE* pjXorScan;
  476. BYTE* pjAnd;
  477. BYTE* pjXor;
  478. BYTE andByte;
  479. BYTE xorByte;
  480. BYTE jMask;
  481. LONG lDelta;
  482. LONG cpelFraction;
  483. LONG cjWhole;
  484. LONG cClear;
  485. LONG cRemPels;
  486. BOOL pointerIsCached;
  487. LONG cacheItem;
  488. LONG cursorBytes;
  489. LONG cursorRAMOff;
  490. ULONG lutIndex0, lutIndex1;
  491. GLINT_DECL_VARS;
  492. P3RD_DECL_VARS;
  493. GLINT_DECL_INIT;
  494. P3RD_DECL_INIT;
  495. DISPDBG((DBGLVL, "bSetPointerShapeP3RD started"));
  496. // Do we have a colour cursor ?
  497. if (psoColor != NULL)
  498. {
  499. HSURF hsurfDst = NULL; // We'll use these later.
  500. SURFOBJ * psoDst = NULL;
  501. if (psoColor->iType == STYPE_DEVBITMAP)
  502. {
  503. // it's an offscreen bitmap: we'll use its DIB
  504. DSURF *pdsurfSrc = (DSURF *)psoColor->dhsurf;
  505. psoColor = pdsurfSrc->pso;
  506. // If we have patching enabled then it could be that we aren't allowed
  507. // to directly access framebuffer memory, if that is the case then
  508. // we have to fall-back to software. Note that when running 3D apps there
  509. // won't be any off-screen memory so cursors will be hardware ones.
  510. // Note that bitmaps that were in off-screen and have been kicked back
  511. // into host memory will have pdsurfSrc->dt set to DT_DIB.
  512. if (glintInfo->GdiCantAccessFramebuffer && ((pdsurfSrc->dt & DT_DIB) == 0))
  513. {
  514. DISPDBG((DBGLVL, "declining off-screen cursor in a patched framebuffer"));
  515. return (FALSE);
  516. }
  517. }
  518. // Is it 15,16 or 32BPP.
  519. if(!(ppdev->iBitmapFormat == BMF_16BPP || ppdev->iBitmapFormat == BMF_32BPP))
  520. {
  521. // currently we only handle DIB cursors at 32bpp, 16bpp & 15bpp.
  522. DISPDBG((DBGLVL, "declining non-32bpp, non-16bpp colored cursor - iType(%d) iBitmapFormat(%d)", psoColor->iType, psoColor->iBitmapFormat));
  523. return FALSE;
  524. }
  525. // If we have a bitmap which we don't understand then we have to convert it using
  526. // the EngCopyBits() function.
  527. if ((pxlo != NULL && pxlo->flXlate != XO_TRIVIAL) ||
  528. (psoColor->iType != STYPE_BITMAP) )
  529. {
  530. RECTL rclDst;
  531. SIZEL sizlDst;
  532. ULONG DstPixelOrigin;
  533. POINTL ptlSrc;
  534. #if DBG
  535. if(pxlo != NULL && pxlo->flXlate != XO_TRIVIAL)
  536. {
  537. DISPDBG((DBGLVL, "colored cursor - nontrivial xlate: flXlate(%xh)", pxlo->flXlate));
  538. }
  539. #endif // DBG
  540. // Firstly we need to create a bitmap (hsurfDst) and a surface (psoDst)
  541. // which we can translate the cursor data in psoColor into.
  542. sizlDst.cy = pso->sizlBitmap.cy >> 1; // divide by 2 'cos cy includes AND and XOR masks
  543. sizlDst.cx = pso->sizlBitmap.cx;
  544. DISPDBG((DBGLVL, "Creating bitmap for destination: dimension %dx%d", sizlDst.cx, sizlDst.cy));
  545. hsurfDst = (HSURF) EngCreateBitmap(sizlDst, BMF_TOPDOWN, ppdev->iBitmapFormat, 0, NULL);
  546. if (hsurfDst == NULL)
  547. {
  548. DISPDBG((DBGLVL, "bSetPointerShapeP3RD: EngCreateBitmap failed"));
  549. return FALSE;
  550. }
  551. // Now we lock the bitmap to get ourselves a surface object.
  552. psoDst = EngLockSurface(hsurfDst);
  553. if (psoDst == NULL)
  554. {
  555. DISPDBG((DBGLVL, "bSetPointerShapeP3RD: EngLockSurface failed"));
  556. }
  557. else
  558. {
  559. // Now do the bitmap conversion using EngCopyBits(). The
  560. // destination rectangle is the minimum size and the source starts
  561. // from (0,0) into pso->pvScan0.
  562. rclDst.left = 0;
  563. rclDst.top = 0;
  564. rclDst.right = sizlDst.cx;
  565. rclDst.bottom = sizlDst.cy;
  566. ptlSrc.x = 0;
  567. ptlSrc.y = 0;
  568. DISPDBG((DBGLVL, "bSetPointerShapeP3RD: copying to bitmap"));
  569. if (!EngCopyBits(psoDst, psoColor, NULL, pxlo, &rclDst, &ptlSrc))
  570. {
  571. // Oh no copybits failed, free up the the surfaces & bitmaps.
  572. DISPDBG((DBGLVL, "bSetPointerShapeP3RD: EngLockSurface failed"));
  573. EngUnlockSurface(psoDst);
  574. EngDeleteSurface(hsurfDst);
  575. return FALSE;
  576. }
  577. else
  578. {
  579. // Copybits suceeded, set psoColor to point at the translated
  580. // data.
  581. DISPDBG((DBGLVL, "bSetPointerShapeP3RD: EngLockSurface OK"));
  582. psoColor = psoDst;
  583. }
  584. }
  585. }
  586. // Draw the cursor, this function will return an error if there are
  587. // too many colours in the pointer.
  588. if(!bSet15ColorPointerShapeP3RD(ppdev, pso, psoColor, x, y, xHot, yHot))
  589. {
  590. DISPDBG((DBGLVL, "declining colored cursor"));
  591. return FALSE;
  592. }
  593. // If we, earlier, translated psoColor into the framebuffer pixel format then
  594. // we now need to free the intermediate surfaces and bitmaps.
  595. if (psoDst)
  596. {
  597. EngUnlockSurface(psoDst);
  598. }
  599. if (hsurfDst)
  600. {
  601. EngDeleteSurface(hsurfDst);
  602. }
  603. DISPDBG((DBGLVL, "bSetPointerShapeP3RD done"));
  604. return(TRUE);
  605. }
  606. // If we are switching from a colour cursor to a mono one then disable
  607. // the cursor in the cursor mode. Note that this is potentially dangerous
  608. // and we are seeing screen flashes on occasions.
  609. if (pP3RDinfo->cursorSize != P3RD_CURSOR_SIZE_32_MONO &&
  610. pP3RDinfo->cursorSize != P3RD_CURSOR_SIZE_64_MONO)
  611. {
  612. DISABLE_CURSOR_MODE();
  613. }
  614. // Note that 'sizlBitmap.cy' accounts for the double height due to the inclusion of both the AND masks
  615. // and the XOR masks. We're only interested in the true pointer dimensions, so we divide by 2.
  616. cx = pso->sizlBitmap.cx;
  617. cy = pso->sizlBitmap.cy >> 1;
  618. // we can handle up to 64x64. cValid indicates the number of
  619. // bytes occupied by cursor on one line
  620. if (cx <= 32 && cy <= 32)
  621. {
  622. // 32 horiz pixels: 2 bits per pixel, 1 horiz line per 8 bytes
  623. pP3RDinfo->cursorSize = P3RD_CURSOR_SIZE_32_MONO;
  624. cursorBytes = 32 * 32 * 2 / 8;
  625. cClear = 8 - 2 * ((cx+7) / 8);
  626. cRemPels = (32 - cy) << 3;
  627. }
  628. else if (cx <= 64 && cy <= 64)
  629. {
  630. // 64 horiz pixels: 2 bits per pixel, 1 horiz line per 16 bytes
  631. pP3RDinfo->cursorSize = P3RD_CURSOR_SIZE_64_MONO;
  632. cursorBytes = 64 * 64 * 2 / 8;
  633. cClear = 16 - 2 * ((cx+7) / 8);
  634. cRemPels = (64 - cy) << 4;
  635. }
  636. else
  637. {
  638. DISPDBG((DBGLVL, "declining cursor: %d x %d is too big", cx, cy));
  639. return(FALSE); // cursor is too big to fit in the hardware
  640. }
  641. // Check to see if the pointer is cached, add it to the cache if it isn't
  642. cacheItem = HWPointerCacheCheckAndAdd (&(ppdev->HWPtrCache), cx, cy, pso->lDelta, pso->pvScan0, &pointerIsCached);
  643. DISPDBG((DBGLVL, "bSetPointerShapeP3RD: Add Cache iscac %d item %d", (int) pointerIsCached, cacheItem));
  644. pP3RDinfo->cursorModeCurrent = pP3RDinfo->cursorModeOff | P3RD_CURSOR_SEL(pP3RDinfo->cursorSize, cacheItem);
  645. // hide the pointer
  646. vShowPointerP3RD(ppdev, FALSE);
  647. if (!pointerIsCached)
  648. {
  649. // Now we're going to take the requested pointer AND masks and XOR
  650. // masks and interleave them by taking a nibble at a time from each,
  651. // expanding each out and or'ing together. Use the nibbleToByteP3RD array
  652. // to help this.
  653. //
  654. // 'psoMsk' is actually cy * 2 scans high; the first 'cy' scans
  655. // define the AND mask.
  656. pjAndScan = pso->pvScan0;
  657. lDelta = pso->lDelta;
  658. pjXorScan = pjAndScan + (cy * lDelta);
  659. cjWhole = cx >> 3; // Each byte accounts for 8 pels
  660. cpelFraction = cx & 0x7; // Number of fractional pels
  661. jMask = gajMask[cpelFraction];
  662. // we've got auto-increment turned on so just point to the first entry to write to
  663. // in the array then write repeatedly until the cursor pattern has been transferred
  664. cursorRAMOff = cacheItem * cursorBytes;
  665. P3RD_CURSOR_ARRAY_START(cursorRAMOff);
  666. for (i = cy; --i >= 0; pjXorScan += lDelta, pjAndScan += lDelta)
  667. {
  668. pjAnd = pjAndScan;
  669. pjXor = pjXorScan;
  670. // interleave nibbles from whole words. We are using Windows cursor mode.
  671. // Note, the AND bit occupies the higher bit position for each
  672. // 2bpp cursor pel; the XOR bit is in the lower bit position.
  673. // The nibbleToByteP3RD array expands each nibble to occupy the bit
  674. // positions for the AND bytes. So when we use it to calculate
  675. // the XOR bits we shift the result right by 1.
  676. //
  677. for (j = cjWhole; --j >= 0; ++pjAnd, ++pjXor)
  678. {
  679. andByte = *pjAnd;
  680. xorByte = *pjXor;
  681. ulValue = nibbleToByteP3RD[andByte >> 4] | (nibbleToByteP3RD[xorByte >> 4] >> 1);
  682. P3RD_LOAD_CURSOR_ARRAY (ulValue);
  683. andByte &= 0xf;
  684. xorByte &= 0xf;
  685. ulValue = nibbleToByteP3RD[andByte] | (nibbleToByteP3RD[xorByte] >> 1);
  686. P3RD_LOAD_CURSOR_ARRAY (ulValue);
  687. }
  688. if (cpelFraction)
  689. {
  690. andByte = *pjAnd & jMask;
  691. xorByte = *pjXor & jMask;
  692. ulValue = nibbleToByteP3RD[andByte >> 4] | (nibbleToByteP3RD[xorByte >> 4] >> 1);
  693. P3RD_LOAD_CURSOR_ARRAY (ulValue);
  694. andByte &= 0xf;
  695. xorByte &= 0xf;
  696. ulValue = nibbleToByteP3RD[andByte] | (nibbleToByteP3RD[xorByte] >> 1);
  697. P3RD_LOAD_CURSOR_ARRAY (ulValue);
  698. }
  699. // finally clear out any remaining cursor pels on this line.
  700. //
  701. if (cClear)
  702. {
  703. for (j = 0; j < cClear; ++j)
  704. {
  705. P3RD_LOAD_CURSOR_ARRAY (P3RD_CURSOR_2_COLOR_TRANSPARENT);
  706. }
  707. }
  708. }
  709. // if we've loaded fewer than the full number of lines configured in the
  710. // cursor RAM, clear out the remaining lines. cRemPels is precalculated to
  711. // be the number of lines * number of pels per line.
  712. //
  713. if (cRemPels > 0)
  714. {
  715. do
  716. {
  717. P3RD_LOAD_CURSOR_ARRAY (P3RD_CURSOR_2_COLOR_TRANSPARENT);
  718. }
  719. while (--cRemPels > 0);
  720. }
  721. }
  722. // now set-up the cursor colors
  723. // Norte that the P3 cursor has the color LUT upside down.
  724. lutIndex0 = P3RD_CALCULATE_LUT_INDEX (0);
  725. lutIndex1 = P3RD_CALCULATE_LUT_INDEX (1);
  726. P3RD_CURSOR_PALETTE_CURSOR_RGB(lutIndex0, 0x00, 0x00, 0x00);
  727. P3RD_CURSOR_PALETTE_CURSOR_RGB(lutIndex1, 0xFF, 0xFF, 0xFF);
  728. // If the new cursor is different to the last cursor then set up
  729. // the hot spot and other bits'n'pieces. As we currently only support
  730. // mono cursors we don't need to reload the cursor palette
  731. if (ppdev->HWPtrLastCursor != cacheItem || !pointerIsCached)
  732. {
  733. // Make this item the last item
  734. ppdev->HWPtrLastCursor = cacheItem;
  735. P3RD_CURSOR_HOTSPOT(xHot, yHot);
  736. }
  737. if (x != -1)
  738. {
  739. vMovePointerP3RD (ppdev, x, y);
  740. // need to explicitly show the pointer
  741. vShowPointerP3RD(ppdev, TRUE);
  742. }
  743. DISPDBG((DBGLVL, "bSetPointerShapeP3RD done"));
  744. return(TRUE);
  745. }
  746. /******************************Public*Routine******************************\
  747. * BOOL bSet3ColorPointerShapeP3RD
  748. *
  749. * stores the 3-color cursor in the RAMDAC: currently only 32bpp and 15/16bpp
  750. * cursors are supported
  751. *
  752. \**************************************************************************/
  753. BOOL
  754. bSet3ColorPointerShapeP3RD(
  755. PPDEV ppdev,
  756. SURFOBJ *psoMask, // defines AND and MASK bits for cursor
  757. SURFOBJ *psoColor, // we may handle some color cursors at some point
  758. LONG x, // If -1, pointer should be created hidden
  759. LONG y,
  760. LONG xHot,
  761. LONG yHot)
  762. {
  763. LONG cx, cy;
  764. LONG cxcyCache;
  765. LONG cjCacheRow, cjCacheRemx, cjCacheRemy, cj;
  766. BYTE *pjAndMask, *pj;
  767. ULONG *pulColor, *pul;
  768. LONG cjAndDelta, cjColorDelta;
  769. LONG iRow, iCol;
  770. BYTE AndBit, AndByte;
  771. ULONG CI2ColorIndex, CI2ColorData;
  772. ULONG ulColor;
  773. ULONG aulColorsIndexed[3];
  774. LONG Index, HighestIndex = 0;
  775. ULONG r, g, b;
  776. ULONG whichOne = 0;
  777. GLINT_DECL_VARS;
  778. P3RD_DECL_VARS;
  779. GLINT_DECL_INIT;
  780. P3RD_DECL_INIT;
  781. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD started"));
  782. cx = psoColor->sizlBitmap.cx;
  783. cy = psoColor->sizlBitmap.cy;
  784. if (cx <= 32 && cy <= 32)
  785. {
  786. ULONG curItem;
  787. cxcyCache = 32;
  788. // If we are using a mono/3-colour cursor in the first or second entry then
  789. // download to the third entry, otherwise use the first entry.
  790. curItem = (pP3RDinfo->cursorModeCurrent >> 1) & 0x7;
  791. if (curItem == 1 || curItem == 2)
  792. whichOne = 2;
  793. pP3RDinfo->cursorSize = P3RD_CURSOR_SIZE_32_3COLOR;
  794. pP3RDinfo->cursorModeCurrent = pP3RDinfo->cursorModeOff | P3RD_CURSOR_SEL(pP3RDinfo->cursorSize, whichOne) | P3RD_CURSOR_MODE_3COLOR;
  795. // We don't cache color cursors, because we want to force the mono cursor to use the
  796. // either the first or third entries we can't just do a HWPointerCacheInvalidate(), because
  797. // the mono cursor code will use the first entry or the time. So, if we want the
  798. // mono code to use the 3rd entry we say that first 2 cache entries are valid but mess them
  799. // up by incrementing the first byte, so that the cache check will always fail.
  800. ppdev->HWPtrCache.ptrCacheInUseCount = (BYTE) whichOne;
  801. for (iCol = 0; iCol < ppdev->HWPtrCache.ptrCacheInUseCount; iCol++)
  802. (*(((BYTE *) ppdev->HWPtrCache.ptrCacheData) + (iCol * SMALL_POINTER_MEM)))++;
  803. }
  804. else if (cx <= 64 && cy <= 64)
  805. {
  806. // 64x64 cursor : we'll cache it in cursor partition 0 and scrub the old cache
  807. cxcyCache = 64;
  808. pP3RDinfo->cursorSize = P3RD_CURSOR_SIZE_64_3COLOR;
  809. pP3RDinfo->cursorModeCurrent = pP3RDinfo->cursorModeOff | P3RD_CURSOR_SEL(pP3RDinfo->cursorSize, 0) | P3RD_CURSOR_MODE_3COLOR;
  810. // we don't cache color cursors
  811. HWPointerCacheInvalidate (&(ppdev->HWPtrCache));
  812. }
  813. else
  814. {
  815. DISPDBG((DBGLVL, "declining cursor: %d x %d is too big", cx, cy));
  816. return(FALSE); // cursor is too big to fit in the hardware
  817. }
  818. // work out the remaining bytes in the cache (in x and y) that will need clearing
  819. cjCacheRow = 2 * cxcyCache / 8;
  820. cjCacheRemx = cjCacheRow - 2 * ((cx+7) / 8);
  821. cjCacheRemy = (cxcyCache - cy) * cjCacheRow;
  822. // set-up a pointer to the 1bpp AND mask bitmap
  823. pjAndMask = psoMask->pvScan0;
  824. cjAndDelta = psoMask->lDelta;
  825. // set-up a pointer to the 32bpp color bitmap
  826. pulColor = psoColor->pvScan0;
  827. cjColorDelta = psoColor->lDelta;
  828. // Hide the pointer
  829. vShowPointerP3RD(ppdev, FALSE);
  830. // load the cursor array (we have auto-increment turned on so initialize to entry 0 here)
  831. P3RD_CURSOR_ARRAY_START(whichOne * (32 * 32 * 2 / 8));
  832. for (iRow = 0; iRow < cy; ++iRow, pjAndMask += cjAndDelta, (BYTE *)pulColor += cjColorDelta)
  833. {
  834. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: Row %d (of %d): pjAndMask(%p) pulColor(%p)", iRow, cy, pjAndMask, pulColor));
  835. pj = pjAndMask;
  836. pul = pulColor;
  837. CI2ColorIndex = CI2ColorData = 0;
  838. for (iCol = 0; iCol < cx; ++iCol, CI2ColorIndex += 2)
  839. {
  840. AndBit = (BYTE)(7 - (iCol & 7));
  841. if (AndBit == 7)
  842. {
  843. // we're onto the next byte of the and mask
  844. AndByte = *pj++;
  845. }
  846. if (CI2ColorIndex == 8)
  847. {
  848. // we've filled a byte with 4 CI2 colors
  849. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: writing cursor data %xh", CI2ColorData));
  850. P3RD_LOAD_CURSOR_ARRAY(CI2ColorData);
  851. CI2ColorData = 0;
  852. CI2ColorIndex = 0;
  853. }
  854. // get the source pixel
  855. if (ppdev->cPelSize == GLINTDEPTH32)
  856. {
  857. ulColor = *pul++;
  858. }
  859. else
  860. {
  861. ulColor = *(USHORT *)pul;
  862. (USHORT *)pul += 1;
  863. }
  864. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: Column %d (of %d) AndByte(%08xh) AndBit(%d) ulColor(%08xh)", iCol, cx, AndByte, AndBit, ulColor));
  865. //@@BEGIN_DDKSPLIT
  866. #if 0
  867. // TMM: We only used to assume a pixel was transparent if the
  868. // AND mask bit was set and the pixel was zero, I am pretty sure
  869. // that this is wrong. We also used to do some stuff with
  870. // inverse pixels but that was wrong as well.
  871. if(AndByte & (1 << AndBit))
  872. {
  873. // transparent and seeing as the CI2ColorData is initialized to 0 we don't
  874. // have to explicitly clear these bits - go on to the next pixel
  875. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: transparent - ignore"));
  876. continue;
  877. }
  878. #else
  879. //@@END_DDKSPLIT
  880. // Figure out what to do with it:-
  881. // AND Color Result
  882. // 0 X color
  883. // 1 0 transparent
  884. // 1 1 inverse
  885. if (AndByte & (1 << AndBit))
  886. {
  887. // Transparent or inverse
  888. if (ulColor == ppdev->ulWhite)
  889. {
  890. // color == white: inverse, but we don't support this. We've destroyed the cache for nothing
  891. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: failed - inverted colors aren't supported"));
  892. return(FALSE);
  893. }
  894. //@@BEGIN_DDKSPLIT
  895. // if we get here the color should be black. However, if the pointer surface has been translated it
  896. // might not be exactly black (e.g. as for the pointer at the start of Riven), so we don't do the test
  897. //if(ulColor == 0)
  898. //@@END_DDKSPLIT
  899. {
  900. // color == black: transparent and seeing as the CI2ColorData is initialized to 0 we don't
  901. //have to explicitly clear these bits - go on to the next pixel
  902. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: transparent - ignore"));
  903. continue;
  904. }
  905. }
  906. //@@BEGIN_DDKSPLIT
  907. #endif
  908. //@@END_DDKSPLIT
  909. // get the index for this color: first see if we've already indexed it
  910. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: looking up color %08xh", ulColor));
  911. for(Index = 0; Index < HighestIndex && aulColorsIndexed[Index] != ulColor; ++Index);
  912. if (Index == 3)
  913. {
  914. // too many colors in this cursor
  915. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: failed - cursor has more than 3 colors"));
  916. return(FALSE);
  917. }
  918. else if (Index == HighestIndex)
  919. {
  920. // we've found another color: add it to the color index
  921. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: adding %08xh to cursor palette", ulColor));
  922. aulColorsIndexed[HighestIndex++] = ulColor;
  923. }
  924. // add this pixel's index to the CI2 cursor data. NB. Need Index+1 as 0 == transparent
  925. CI2ColorData |= (Index + 1) << CI2ColorIndex;
  926. }
  927. // end of the cursor row: save the remaining indexed pixels then blank any unused columns
  928. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: writing remaining data for this row (%08xh) and %d trailing bytes", CI2ColorData, cjCacheRemx));
  929. P3RD_LOAD_CURSOR_ARRAY(CI2ColorData);
  930. if (cjCacheRemx)
  931. {
  932. for (cj = cjCacheRemx; --cj >=0;)
  933. {
  934. P3RD_LOAD_CURSOR_ARRAY(P3RD_CURSOR_3_COLOR_TRANSPARENT);
  935. }
  936. }
  937. }
  938. // end of cursor: blank any unused rows Nb. cjCacheRemy == cy blank rows * cj bytes per row
  939. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: writing %d trailing bytes for this cursor", cjCacheRemy));
  940. for (cj = cjCacheRemy; --cj >= 0;)
  941. {
  942. // 0 == transparent
  943. P3RD_LOAD_CURSOR_ARRAY(P3RD_CURSOR_3_COLOR_TRANSPARENT);
  944. }
  945. DISPDBG((DBGLVL, "bSet3ColorPointerShapeP3RD: setting up the cursor palette"));
  946. // now set-up the cursor palette
  947. for (iCol = 0; iCol < HighestIndex; ++iCol)
  948. {
  949. ULONG lutIndex;
  950. // the cursor colors are at native depth, convert them to 24bpp
  951. if (ppdev->cPelSize == GLINTDEPTH32)
  952. {
  953. // 32bpp
  954. b = 0xff & aulColorsIndexed[iCol];
  955. g = 0xff & (aulColorsIndexed[iCol] >> 8);
  956. r = 0xff & (aulColorsIndexed[iCol] >> 16);
  957. }
  958. else //(ppdev->cPelSize == GLINTDEPTH16)
  959. {
  960. if (ppdev->ulWhite == 0xffff)
  961. {
  962. // 16bpp
  963. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  964. g = (0x3f & (aulColorsIndexed[iCol] >> 5)) << 2;
  965. r = (0x1f & (aulColorsIndexed[iCol] >> 11)) << 3;
  966. }
  967. else
  968. {
  969. // 15bpp
  970. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  971. g = (0x1f & (aulColorsIndexed[iCol] >> 5)) << 3;
  972. r = (0x1f & (aulColorsIndexed[iCol] >> 10)) << 3;
  973. }
  974. }
  975. // The P3 cursor has the color LUT upside down.
  976. lutIndex = P3RD_CALCULATE_LUT_INDEX (iCol);
  977. P3RD_CURSOR_PALETTE_CURSOR_RGB(lutIndex, r, g, b);
  978. }
  979. // enable the cursor
  980. P3RD_CURSOR_HOTSPOT(xHot, yHot);
  981. if (x != -1)
  982. {
  983. vMovePointerP3RD (ppdev, x, y);
  984. // need to explicitly show the pointer
  985. vShowPointerP3RD(ppdev, TRUE);
  986. }
  987. DISPDBG((DBGLVL, "b3ColorSetPointerShapeP3RD done"));
  988. return(TRUE);
  989. }
  990. /******************************Public*Routine******************************\
  991. * BOOL bSet15ColorPointerShapeP3RD
  992. *
  993. * stores the 15-color cursor in the RAMDAC: currently only 32bpp and 15/16bpp
  994. * cursors are supported
  995. *
  996. \**************************************************************************/
  997. BOOL
  998. bSet15ColorPointerShapeP3RD(
  999. PPDEV ppdev,
  1000. SURFOBJ *psoMask, // defines AND and MASK bits for cursor
  1001. SURFOBJ *psoColor, // we may handle some color cursors at some point
  1002. LONG x, // If -1, pointer should be created hidden
  1003. LONG y,
  1004. LONG xHot,
  1005. LONG yHot)
  1006. {
  1007. LONG cx, cy;
  1008. LONG cxcyCache;
  1009. LONG cjCacheRow, cjCacheRemx, cjCacheRemy, cj;
  1010. BYTE *pjAndMask, *pj;
  1011. ULONG *pulColor, *pul;
  1012. LONG cjAndDelta, cjColorDelta;
  1013. LONG iRow, iCol;
  1014. BYTE AndBit, AndByte;
  1015. ULONG CI4ColorIndex, CI4ColorData;
  1016. ULONG ulColor;
  1017. ULONG aulColorsIndexed[15];
  1018. LONG Index, HighestIndex = 0;
  1019. ULONG r, g, b;
  1020. ULONG whichOne = 0;
  1021. GLINT_DECL_VARS;
  1022. P3RD_DECL_VARS;
  1023. GLINT_DECL_INIT;
  1024. P3RD_DECL_INIT;
  1025. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD started"));
  1026. // If we are switching from a mono cursor to a colour one then disable
  1027. // the cursor in the cursor mode. Note that this is potentially dangerous
  1028. // and we are seeing screen flashes on occasions.
  1029. if (pP3RDinfo->cursorSize == P3RD_CURSOR_SIZE_32_MONO || pP3RDinfo->cursorSize == P3RD_CURSOR_SIZE_64_MONO)
  1030. {
  1031. DISABLE_CURSOR_MODE();
  1032. }
  1033. cx = psoColor->sizlBitmap.cx;
  1034. cy = psoColor->sizlBitmap.cy;
  1035. if (cx <= 32 && cy <= 32)
  1036. {
  1037. ULONG curItem;
  1038. cxcyCache = 32;
  1039. // If we are using a mono cursor in the first or second entry, or we have a
  1040. // 15 colour cursor in the top half of cursor memory then download
  1041. // this colour cursor to the download to the 2nd half of cursor memory, otherwise
  1042. // download to the top half.
  1043. curItem = (pP3RDinfo->cursorModeCurrent >> 1) & 0x7;
  1044. if (curItem == 1 || curItem == 2 || curItem == 5)
  1045. whichOne = 1;
  1046. pP3RDinfo->cursorSize = P3RD_CURSOR_SIZE_32_15COLOR;
  1047. pP3RDinfo->cursorModeCurrent = pP3RDinfo->cursorModeOff | P3RD_CURSOR_SEL(pP3RDinfo->cursorSize, whichOne) | P3RD_CURSOR_MODE_15COLOR;
  1048. // We don't cache color cursors, because we want to force the mono cursor to use the
  1049. // either the first or third entries we can't just do a HWPointerCacheInvalidate(), because
  1050. // the mono cursor code will use the first entry or the time. So, if we want the
  1051. // mono code to use the 3rd entry we say that first 2 cache entries are valid but mess them
  1052. // up by incrementing the first byte, so that the cache check will always fail.
  1053. ppdev->HWPtrCache.ptrCacheInUseCount = (whichOne == 0) ? 2 : 0;
  1054. for (iCol = 0; iCol < ppdev->HWPtrCache.ptrCacheInUseCount; iCol++)
  1055. (*(((BYTE *) ppdev->HWPtrCache.ptrCacheData) + (iCol * SMALL_POINTER_MEM)))++;
  1056. }
  1057. else if (cx <= 64 && cy <= 64)
  1058. {
  1059. // it's too big to cache as a fifteen color cursor, but we might just be able to cache it
  1060. // if it has 3 or fewer colors
  1061. BOOL bRet;
  1062. bRet = bSet3ColorPointerShapeP3RD(ppdev, psoMask, psoColor, x, y, xHot, yHot);
  1063. return(bRet);
  1064. }
  1065. else
  1066. {
  1067. DISPDBG((DBGLVL, "declining cursor: %d x %d is too big", cx, cy));
  1068. return(FALSE); // cursor is too big to fit in the hardware
  1069. }
  1070. // work out the remaining bytes in the cache (in x and y) that will need clearing
  1071. cjCacheRow = 2 * cxcyCache / 8;
  1072. cjCacheRemx = cjCacheRow - 2 * ((cx+7) / 8);
  1073. cjCacheRemy = (cxcyCache - cy) * cjCacheRow;
  1074. // set-up a pointer to the 1bpp AND mask bitmap
  1075. pjAndMask = psoMask->pvScan0;
  1076. cjAndDelta = psoMask->lDelta;
  1077. // set-up a pointer to the 32bpp color bitmap
  1078. pulColor = psoColor->pvScan0;
  1079. cjColorDelta = psoColor->lDelta;
  1080. // hide the pointer
  1081. vShowPointerP3RD(ppdev, FALSE);
  1082. // load the cursor array (we have auto-increment turned on so initialize to entry 0 here)
  1083. P3RD_CURSOR_ARRAY_START(whichOne * (32 * 32 * 4 / 8));
  1084. for (iRow = 0; iRow < cy; ++iRow, pjAndMask += cjAndDelta, (BYTE *)pulColor += cjColorDelta)
  1085. {
  1086. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: Row %d (of %d): pjAndMask(%p) pulColor(%p)", iRow, cy, pjAndMask, pulColor));
  1087. pj = pjAndMask;
  1088. pul = pulColor;
  1089. CI4ColorIndex = CI4ColorData = 0;
  1090. for (iCol = 0; iCol < cx; ++iCol, CI4ColorIndex += 4)
  1091. {
  1092. AndBit = (BYTE)(7 - (iCol & 7));
  1093. if (AndBit == 7)
  1094. {
  1095. // we're onto the next byte of the and mask
  1096. AndByte = *pj++;
  1097. }
  1098. if (CI4ColorIndex == 8)
  1099. {
  1100. // we've filled a byte with 2 CI4 colors
  1101. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: writing cursor data %xh", CI4ColorData));
  1102. P3RD_LOAD_CURSOR_ARRAY(CI4ColorData);
  1103. CI4ColorData = 0;
  1104. CI4ColorIndex = 0;
  1105. }
  1106. // get the source pixel
  1107. if (ppdev->cPelSize == GLINTDEPTH32)
  1108. {
  1109. ulColor = *pul++;
  1110. }
  1111. else
  1112. {
  1113. ulColor = *(USHORT *)pul;
  1114. (USHORT *)pul += 1;
  1115. }
  1116. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: Column %d (of %d) AndByte(%08xh) AndBit(%d) ulColor(%08xh)", iCol, cx, AndByte, AndBit, ulColor));
  1117. //@@BEGIN_DDKSPLIT
  1118. #if 0
  1119. // TMM: We only used to assume a pixel was transparent if the
  1120. // AND mask bit was set and the pixel was zero, I am pretty sure
  1121. // that this is wrong. We also used to do some stuff with
  1122. // inverse pixels but that was wrong as well.
  1123. if(AndByte & (1 << AndBit))
  1124. {
  1125. // transparent and seeing as the CI2ColorData is initialized to 0 we don't
  1126. // have to explicitly clear these bits - go on to the next pixel
  1127. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: transparent - ignore"));
  1128. continue;
  1129. }
  1130. #else
  1131. //@@END_DDKSPLIT
  1132. // Figure out what to do with it:-
  1133. // AND Color Result
  1134. // 0 X color
  1135. // 1 0 transparent
  1136. // 1 1 inverse
  1137. if (AndByte & (1 << AndBit))
  1138. {
  1139. // Transparent or inverse
  1140. if(ulColor == ppdev->ulWhite)
  1141. {
  1142. // color == white: inverse, but we don't support this. We've destroyed the cache for nothing
  1143. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: failed - inverted colors aren't supported"));
  1144. return(FALSE);
  1145. }
  1146. // if we get here the color should be black. However, if the pointer surface has been translated it
  1147. // might not be exactly black (e.g. as for the pointer at the start of Riven), so we don't do the test
  1148. //if(ulColor == 0)
  1149. {
  1150. // color == black: transparent and seeing as the CI2ColorData is initialized to 0 we don't
  1151. //have to explicitly clear these bits - go on to the next pixel
  1152. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: transparent - ignore"));
  1153. continue;
  1154. }
  1155. }
  1156. //@@BEGIN_DDKSPLIT
  1157. #endif
  1158. //@@END_DDKSPLIT
  1159. // get the index for this color: first see if we've already indexed it
  1160. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: looking up color %08xh", ulColor));
  1161. for (Index = 0; Index < HighestIndex && aulColorsIndexed[Index] != ulColor; ++Index);
  1162. if (Index == 15)
  1163. {
  1164. // too many colors in this cursor
  1165. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: failed - cursor has more than 15 colors"));
  1166. return(FALSE);
  1167. }
  1168. else if (Index == HighestIndex)
  1169. {
  1170. // we've found another color: add it to the color index
  1171. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: adding %08xh to cursor palette", ulColor));
  1172. aulColorsIndexed[HighestIndex++] = ulColor;
  1173. }
  1174. // add this pixel's index to the CI4 cursor data. NB. Need Index+1 as 0 == transparent
  1175. CI4ColorData |= (Index + 1) << CI4ColorIndex;
  1176. }
  1177. // end of the cursor row: save the remaining indexed pixels then blank any unused columns
  1178. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: writing remaining data for this row (%08xh) and %d trailing bytes", CI4ColorData, cjCacheRemx));
  1179. P3RD_LOAD_CURSOR_ARRAY(CI4ColorData);
  1180. if (cjCacheRemx)
  1181. {
  1182. for (cj = cjCacheRemx; --cj >=0;)
  1183. {
  1184. P3RD_LOAD_CURSOR_ARRAY(P3RD_CURSOR_15_COLOR_TRANSPARENT);
  1185. }
  1186. }
  1187. }
  1188. // end of cursor: blank any unused rows Nb. cjCacheRemy == cy blank rows * cj bytes per row
  1189. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: writing %d trailing bytes for this cursor", cjCacheRemy));
  1190. for (cj = cjCacheRemy; --cj >= 0;)
  1191. {
  1192. // 0 == transparent
  1193. P3RD_LOAD_CURSOR_ARRAY(P3RD_CURSOR_15_COLOR_TRANSPARENT);
  1194. }
  1195. DISPDBG((DBGLVL, "bSet15ColorPointerShapeP3RD: setting up the cursor palette"));
  1196. // now set-up the cursor palette
  1197. for (iCol = 0; iCol < HighestIndex; ++iCol)
  1198. {
  1199. ULONG lutIndex;
  1200. // the cursor colors are at native depth, convert them to 24bpp
  1201. if (ppdev->cPelSize == GLINTDEPTH32)
  1202. {
  1203. // 32bpp
  1204. b = 0xff & aulColorsIndexed[iCol];
  1205. g = 0xff & (aulColorsIndexed[iCol] >> 8);
  1206. r = 0xff & (aulColorsIndexed[iCol] >> 16);
  1207. }
  1208. else //(ppdev->cPelSize == GLINTDEPTH16)
  1209. {
  1210. if (ppdev->ulWhite == 0xffff)
  1211. {
  1212. // 16bpp
  1213. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  1214. g = (0x3f & (aulColorsIndexed[iCol] >> 5)) << 2;
  1215. r = (0x1f & (aulColorsIndexed[iCol] >> 11)) << 3;
  1216. }
  1217. else
  1218. {
  1219. // 15bpp
  1220. b = (0x1f & aulColorsIndexed[iCol]) << 3;
  1221. g = (0x1f & (aulColorsIndexed[iCol] >> 5)) << 3;
  1222. r = (0x1f & (aulColorsIndexed[iCol] >> 10)) << 3;
  1223. }
  1224. }
  1225. // The P3 cursor has the color LUT upside down.
  1226. lutIndex = P3RD_CALCULATE_LUT_INDEX (iCol);
  1227. P3RD_CURSOR_PALETTE_CURSOR_RGB(lutIndex, r, g, b);
  1228. }
  1229. // enable the cursor
  1230. P3RD_CURSOR_HOTSPOT(xHot, yHot);
  1231. if (x != -1)
  1232. {
  1233. vMovePointerP3RD (ppdev, x, y);
  1234. // need to explicitly show the pointer
  1235. vShowPointerP3RD(ppdev, TRUE);
  1236. }
  1237. DISPDBG((DBGLVL, "b3ColorSetPointerShapeP3RD done"));
  1238. return(TRUE);
  1239. }
  1240. /******************************Public*Routine******************************\
  1241. * VOID vEnablePointerP3RD
  1242. *
  1243. * Get the hardware ready to use the 3Dlabs P3RD hardware pointer.
  1244. *
  1245. \**************************************************************************/
  1246. VOID
  1247. vEnablePointerP3RD(
  1248. PPDEV ppdev)
  1249. {
  1250. pP3RDRAMDAC pRamdac;
  1251. ULONG ul;
  1252. GLINT_DECL_VARS;
  1253. P3RD_DECL_VARS;
  1254. GLINT_DECL_INIT;
  1255. DISPDBG((DBGLVL, "vEnablePointerP3RD called"));
  1256. ppdev->pvPointerData = &ppdev->ajPointerData[0];
  1257. P3RD_DECL_INIT;
  1258. // get a pointer to the RAMDAC registers from the memory mapped
  1259. // control register space.
  1260. //
  1261. pRamdac = (pP3RDRAMDAC)(ppdev->pulRamdacBase);
  1262. // set up memory mapping for the control registers and save in the pointer
  1263. // specific area provided in ppdev.
  1264. //
  1265. P3RD_PAL_WR_ADDR = TRANSLATE_ADDR(&(pRamdac->RDPaletteWriteAddress));
  1266. P3RD_PAL_RD_ADDR = TRANSLATE_ADDR(&(pRamdac->RDPaletteAddressRead));
  1267. P3RD_PAL_DATA = TRANSLATE_ADDR(&(pRamdac->RDPaletteData));
  1268. P3RD_PIXEL_MASK = TRANSLATE_ADDR(&(pRamdac->RDPixelMask));
  1269. P3RD_INDEX_ADDR_HI = TRANSLATE_ADDR(&(pRamdac->RDIndexHigh));
  1270. P3RD_INDEX_ADDR_LO = TRANSLATE_ADDR(&(pRamdac->RDIndexLow));
  1271. P3RD_INDEX_DATA = TRANSLATE_ADDR(&(pRamdac->RDIndexedData));
  1272. P3RD_INDEX_CONTROL = TRANSLATE_ADDR(&(pRamdac->RDIndexControl));
  1273. // not used, but set-up zero anyway
  1274. ppdev->xPointerHot = 0;
  1275. ppdev->yPointerHot = 0;
  1276. // enable auto-increment
  1277. ul = READ_P3RDREG_ULONG(P3RD_INDEX_CONTROL);
  1278. ul |= P3RD_IDX_CTL_AUTOINCREMENT_ENABLED;
  1279. WRITE_P3RDREG_ULONG(P3RD_INDEX_CONTROL, ul);
  1280. P3RD_READ_INDEX_REG(P3RD_CURSOR_CONTROL, pP3RDinfo->cursorControl);
  1281. pP3RDinfo->cursorModeCurrent = pP3RDinfo->cursorModeOff = 0;
  1282. P3RD_LOAD_INDEX_REG(P3RD_CURSOR_MODE, pP3RDinfo->cursorModeOff);
  1283. P3RD_INDEX_REG(P3RD_CURSOR_X_LOW);
  1284. P3RD_LOAD_DATA(0); // cursor x low
  1285. P3RD_LOAD_DATA(0); // cursor x high
  1286. P3RD_LOAD_DATA(0); // cursor y low
  1287. P3RD_LOAD_DATA(0xff); // cursor y high
  1288. P3RD_LOAD_DATA(0); // cursor x hotspot
  1289. P3RD_LOAD_DATA(0); // cursor y hotspot
  1290. }
  1291. /******************************Public*Routine******************************\
  1292. * BOOL vDisablePointerP3RD
  1293. *
  1294. * Does basic pointer tidying up.
  1295. \**************************************************************************/
  1296. VOID vDisablePointerP3RD(PDEV * ppdev)
  1297. {
  1298. // Undraw the pointer, may not be necessary on P3, but we do it
  1299. // on P2.
  1300. vShowPointerP3RD(ppdev, FALSE);
  1301. }
  1302. //@@BEGIN_DDKSPLIT
  1303. #if 0
  1304. /******************************Public*Routine******************************\
  1305. * VOID vSetOverlayModeP3RD
  1306. *
  1307. * Enable or disable RAMDAC overlays for the P3RD RAMDAC.
  1308. *
  1309. *
  1310. \**************************************************************************/
  1311. VOID
  1312. vSetOverlayModeP3RD (PDEV * ppdev,
  1313. ULONG EnableOverlay, // 0 to disable, 1 to enable
  1314. ULONG TransparentColor)
  1315. {
  1316. ULONG p3rdVal;
  1317. GLINT_DECL_VARS;
  1318. P3RD_DECL_VARS;
  1319. GLINT_DECL_INIT;
  1320. P3RD_DECL_INIT;
  1321. P3RD_READ_INDEX_REG (P3RD_MISC_CONTROL, p3rdVal); // Read current setting
  1322. if (EnableOverlay == GLINT_ENABLE_OVERLAY)
  1323. {
  1324. // Enable Overlay
  1325. p3rdVal |= P3RD_MISC_CONTROL_OVERLAYS_ENABLED; // Enable overlays
  1326. p3rdVal |= P3RD_MISC_CONTROL_DIRECT_COLOR_ENABLED; // Enable direct colour
  1327. P3RD_LOAD_INDEX_REG (P3RD_MISC_CONTROL, p3rdVal);
  1328. P3RD_LOAD_INDEX_REG (P3RD_OVERLAY_KEY, TransparentColor); // Set transparent colour
  1329. }
  1330. else
  1331. {
  1332. // Disable Overlay
  1333. p3rdVal &= ~P3RD_MISC_CONTROL_OVERLAYS_ENABLED; // Disable overlays
  1334. p3rdVal &= ~P3RD_MISC_CONTROL_DIRECT_COLOR_ENABLED; // Disable direct colour
  1335. P3RD_LOAD_INDEX_REG (P3RD_MISC_CONTROL, p3rdVal);
  1336. }
  1337. }
  1338. VOID
  1339. vP3RDSetPixelMask(
  1340. PPDEV ppdev,
  1341. ULONG ulMask)
  1342. {
  1343. GLINT_DECL_VARS;
  1344. P3RD_DECL_VARS;
  1345. GLINT_DECL_INIT;
  1346. P3RD_DECL_INIT;
  1347. P3RD_SET_PIXEL_READMASK (ulMask);
  1348. }
  1349. /******************************Public*Routine******************************\
  1350. * BOOL bP3RDSwapCSBuffers
  1351. *
  1352. * Use the pixel read mask to perform color space double buffering. This is
  1353. * only called when we have 12bpp with interleaved nibbles. We do a polled
  1354. * wait for VBLANK before the swap. In the future we may do all this in the
  1355. * miniport via interrupts.
  1356. *
  1357. * Returns
  1358. * We should never be called if this is inappropriate so return TRUE.
  1359. *
  1360. \**************************************************************************/
  1361. BOOL
  1362. bP3RDSwapCSBuffers(
  1363. PPDEV ppdev,
  1364. LONG bufNo)
  1365. {
  1366. ULONG index;
  1367. ULONG color;
  1368. GLINT_DECL_VARS;
  1369. P3RD_DECL_VARS;
  1370. GLINT_DECL_INIT;
  1371. P3RD_DECL_INIT;
  1372. // work out the RAMDAC read pixel mask for the buffer, wait for VBLANK
  1373. // and switch it.
  1374. //
  1375. DISPDBG((DBGLVL, "loading the palette to swap to buffer %d", bufNo));
  1376. P3RD_PALETTE_START_WR (0);
  1377. GLINT_WAIT_FOR_VBLANK;
  1378. if (bufNo == 0)
  1379. {
  1380. for (index = 0; index < 16; ++index)
  1381. for (color = 0; color <= 0xff; color += 0x11)
  1382. P3RD_LOAD_PALETTE (color, color, color);
  1383. }
  1384. else
  1385. {
  1386. for (color = 0; color <= 0xff; color += 0x11)
  1387. for (index = 0; index < 16; ++index)
  1388. P3RD_LOAD_PALETTE (color, color, color);
  1389. }
  1390. return(TRUE);
  1391. }
  1392. /******************************Public*Routine******************************\
  1393. * BOOL bP3RDCheckCSBuffering
  1394. *
  1395. * Determine whether we can do color space double buffering in the current
  1396. * mode.
  1397. *
  1398. * Returns
  1399. * TRUE if we can do the color space double buffering, FALSE otherwise.
  1400. *
  1401. \**************************************************************************/
  1402. BOOL
  1403. bP3RDCheckCSBuffering(PPDEV ppdev)
  1404. {
  1405. // pixels must be 32 bits deep. White is set to the combined masks for
  1406. // each of red, green and blue. The pattern 0x0f0f0f is unique to
  1407. // interleaved 12 bpp mode.
  1408. //
  1409. return ((ppdev->cPelSize == 2) && (ppdev->ulWhite == 0x0f0f0f));
  1410. }
  1411. #endif
  1412. //@@END_DDKSPLIT