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.

538 lines
16 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: palette.c
  8. *
  9. * Content: Palette support.
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "glint.h"
  16. #include <math.h>
  17. // Global Table defining the 20 Window default colours. For 256 colour
  18. // palettes the first 10 must be put at the beginning of the palette
  19. // and the last 10 at the end of the palette.
  20. PALETTEENTRY gapalBase[20] =
  21. {
  22. { 0, 0, 0, 0 }, // 0
  23. { 0x80,0, 0, 0 }, // 1
  24. { 0, 0x80,0, 0 }, // 2
  25. { 0x80,0x80,0, 0 }, // 3
  26. { 0, 0, 0x80,0 }, // 4
  27. { 0x80,0, 0x80,0 }, // 5
  28. { 0, 0x80,0x80,0 }, // 6
  29. { 0xC0,0xC0,0xC0,0 }, // 7
  30. { 192, 220, 192, 0 }, // 8
  31. { 166, 202, 240, 0 }, // 9
  32. { 255, 251, 240, 0 }, // 10
  33. { 160, 160, 164, 0 }, // 11
  34. { 0x80,0x80,0x80,0 }, // 12
  35. { 0xFF,0, 0 ,0 }, // 13
  36. { 0, 0xFF,0 ,0 }, // 14
  37. { 0xFF,0xFF,0 ,0 }, // 15
  38. { 0 ,0, 0xFF,0 }, // 16
  39. { 0xFF,0, 0xFF,0 }, // 17
  40. { 0, 0xFF,0xFF,0 }, // 18
  41. { 0xFF,0xFF,0xFF,0 }, // 19
  42. };
  43. /******************************Public*Routine******************************\
  44. * BOOL bInitializePalette
  45. *
  46. * Initializes default palette for PDEV.
  47. *
  48. \**************************************************************************/
  49. BOOL bInitializePalette(
  50. PDEV* ppdev,
  51. DEVINFO* pdi)
  52. {
  53. PALETTEENTRY* ppal;
  54. PALETTEENTRY* ppalTmp;
  55. ULONG ulLoop;
  56. ULONG ulMask;
  57. BYTE jRed;
  58. BYTE jGre;
  59. BYTE jBlu;
  60. HPALETTE hpal;
  61. DISPDBG((DBGLVL, "bInitializePalette called"));
  62. // mask is zero for palette driven modes
  63. ulMask = ppdev->flRed | ppdev->flGreen | ppdev->flBlue;
  64. if ((ppdev->iBitmapFormat == BMF_8BPP) && (ulMask == 0))
  65. {
  66. // Allocate our palette:
  67. ppal = (PALETTEENTRY*)ENGALLOCMEM(FL_ZERO_MEMORY,
  68. (sizeof(PALETTEENTRY) * 256), ALLOC_TAG_GDI(F));
  69. if (ppal == NULL)
  70. {
  71. goto ReturnFalse;
  72. }
  73. ppdev->pPal = ppal;
  74. // Generate 256 (8*8*4) RGB combinations to fill the palette
  75. jRed = 0;
  76. jGre = 0;
  77. jBlu = 0;
  78. ppalTmp = ppal;
  79. for (ulLoop = 256; ulLoop != 0; ulLoop--)
  80. {
  81. ppalTmp->peRed = jRed;
  82. ppalTmp->peGreen = jGre;
  83. ppalTmp->peBlue = jBlu;
  84. ppalTmp->peFlags = 0;
  85. ppalTmp++;
  86. if (!(jRed += 32))
  87. {
  88. if (!(jGre += 32))
  89. {
  90. jBlu += 64;
  91. }
  92. }
  93. }
  94. // Fill in Windows reserved colours from the WIN 3.0 DDK
  95. // The Window Manager reserved the first and last 10 colours for
  96. // painting windows borders and for non-palette managed applications.
  97. for (ulLoop = 0; ulLoop < 10; ulLoop++)
  98. {
  99. // First 10
  100. ppal[ulLoop] = gapalBase[ulLoop];
  101. // Last 10
  102. ppal[246 + ulLoop] = gapalBase[ulLoop+10];
  103. }
  104. // Create handle for palette.
  105. hpal = EngCreatePalette(PAL_INDEXED, 256, (ULONG*) ppal, 0, 0, 0);
  106. }
  107. else
  108. {
  109. DISPDBG((DBGLVL, "creating True Color palette, "
  110. "masks rgb = 0x%x, 0x%x, 0x%x",
  111. ppdev->flRed, ppdev->flGreen, ppdev->flBlue));
  112. hpal = EngCreatePalette(PAL_BITFIELDS, 0, NULL,
  113. ppdev->flRed, ppdev->flGreen, ppdev->flBlue);
  114. }
  115. ppdev->hpalDefault = hpal;
  116. pdi->hpalDefault = hpal;
  117. if (hpal == 0)
  118. {
  119. goto ReturnFalse;
  120. }
  121. return(TRUE);
  122. ReturnFalse:
  123. DISPDBG((WRNLVL, "Failed bInitializePalette"));
  124. return(FALSE);
  125. }
  126. /******************************Public*Routine******************************\
  127. * VOID vUninitializePalette
  128. *
  129. * Frees resources allocated by bInitializePalette.
  130. *
  131. * Note: In an error case, this may be called before bInitializePalette.
  132. *
  133. \**************************************************************************/
  134. VOID vUninitializePalette(PDEV* ppdev)
  135. {
  136. // Delete the default palette if we created one:
  137. if (ppdev->hpalDefault != 0)
  138. {
  139. EngDeletePalette(ppdev->hpalDefault);
  140. }
  141. if (ppdev->pPal != (PALETTEENTRY*) NULL)
  142. {
  143. ENGFREEMEM(ppdev->pPal);
  144. }
  145. }
  146. /******************************Public*Routine******************************\
  147. * BOOL bEnablePalette
  148. *
  149. * Initialize the hardware's 8bpp palette registers.
  150. *
  151. \**************************************************************************/
  152. BOOL bEnablePalette(PDEV* ppdev)
  153. {
  154. BYTE ajClutSpace[MAX_CLUT_SIZE];
  155. PVIDEO_CLUT pScreenClut;
  156. ULONG ulReturnedDataLength;
  157. ULONG ulMask;
  158. DISPDBG((DBGLVL, "bEnablePalette called"));
  159. ulMask = ppdev->flRed | ppdev->flGreen | ppdev->flBlue;
  160. if ((ppdev->iBitmapFormat == BMF_8BPP) && (ulMask == 0))
  161. {
  162. // Fill in pScreenClut header info:
  163. pScreenClut = (PVIDEO_CLUT) ajClutSpace;
  164. pScreenClut->NumEntries = 256;
  165. pScreenClut->FirstEntry = 0;
  166. // Copy colours in:
  167. //@@BEGIN_DDKSPLIT
  168. #pragma prefast(suppress: 203, "pScreenClut points to sufficient ajClutSpace (PREfast bug 611168)")
  169. //@@END_DDKSPLIT
  170. RtlCopyMemory(pScreenClut->LookupTable, ppdev->pPal,
  171. sizeof(ULONG) * 256);
  172. // Set palette registers:
  173. if (EngDeviceIoControl(ppdev->hDriver,
  174. IOCTL_VIDEO_SET_COLOR_REGISTERS,
  175. pScreenClut,
  176. MAX_CLUT_SIZE,
  177. NULL,
  178. 0,
  179. &ulReturnedDataLength))
  180. {
  181. DISPDBG((WRNLVL, "Failed bEnablePalette"));
  182. return(FALSE);
  183. }
  184. }
  185. DISPDBG((DBGLVL, "Passed bEnablePalette"));
  186. return(TRUE);
  187. }
  188. /******************************Public*Routine******************************\
  189. * VOID vDisablePalette
  190. *
  191. * Undoes anything done in bEnablePalette.
  192. *
  193. \**************************************************************************/
  194. VOID vDisablePalette(
  195. PDEV* ppdev)
  196. {
  197. // Nothin' to do
  198. }
  199. /******************************Public*Routine******************************\
  200. * VOID vAssertModePalette
  201. *
  202. * Sets/resets the palette in preparation for full-screen/graphics mode.
  203. *
  204. \**************************************************************************/
  205. VOID vAssertModePalette(
  206. PDEV* ppdev,
  207. BOOL bEnable)
  208. {
  209. // USER immediately calls DrvSetPalette after switching out of
  210. // full-screen, so we don't have to worry about resetting the
  211. // palette here.
  212. #if(_WIN32_WINNT >= 0x500)
  213. // UPDATE: Windows 2000 in multi-monitor mode: DrvSetPalette only sent
  214. // to the primary monitor on exit from fullscreen (and then only if the
  215. // primary is in 8bpp mode). If the primary is not 8bpp indexed, but
  216. // the secondary is, there is no DrvSetPalette for the secondary, even
  217. // though it was sent DrvAssertMode(FALSE)
  218. if(bEnable)
  219. bEnablePalette(ppdev);
  220. else
  221. vDisablePalette(ppdev);
  222. #endif
  223. }
  224. /******************************Public*Routine******************************\
  225. * BOOL DrvSetPalette
  226. *
  227. * DDI entry point for manipulating the palette.
  228. *
  229. \**************************************************************************/
  230. BOOL DrvSetPalette(
  231. DHPDEV dhpdev,
  232. PALOBJ* ppalo,
  233. FLONG fl,
  234. ULONG iStart,
  235. ULONG cColors)
  236. {
  237. BYTE ajClutSpace[MAX_CLUT_SIZE];
  238. PVIDEO_CLUT pScreenClut;
  239. PVIDEO_CLUTDATA pScreenClutData;
  240. PDEV* ppdev;
  241. ULONG ulMask;
  242. UNREFERENCED_PARAMETER(fl);
  243. ppdev = (PDEV*) dhpdev;
  244. ulMask = ppdev->flRed | ppdev->flGreen | ppdev->flBlue;
  245. if (ulMask != 0)
  246. {
  247. DISPDBG((WRNLVL, "DrvSetPalette: trying to set true color palette"));
  248. return FALSE;
  249. }
  250. // Fill in pScreenClut header info:
  251. pScreenClut = (PVIDEO_CLUT) ajClutSpace;
  252. pScreenClut->NumEntries = (USHORT) cColors;
  253. pScreenClut->FirstEntry = (USHORT) iStart;
  254. pScreenClutData = (PVIDEO_CLUTDATA) (&(pScreenClut->LookupTable[0]));
  255. if (cColors != PALOBJ_cGetColors(ppalo, iStart, cColors,
  256. (ULONG*) pScreenClutData))
  257. {
  258. DISPDBG((WRNLVL, "DrvSetPalette failed PALOBJ_cGetColors\n"));
  259. goto ReturnFalse;
  260. }
  261. // Set the high reserved byte in each palette entry to 0.
  262. while(cColors--)
  263. {
  264. pScreenClutData[cColors].Unused = 0;
  265. }
  266. // Set palette registers
  267. if (EngDeviceIoControl(ppdev->hDriver,
  268. IOCTL_VIDEO_SET_COLOR_REGISTERS,
  269. (PVOID)pScreenClut,
  270. MAX_CLUT_SIZE,
  271. NULL,
  272. 0,
  273. &cColors))
  274. {
  275. DISPDBG((WRNLVL, "DrvSetPalette failed DeviceIoControl\n"));
  276. goto ReturnFalse;
  277. }
  278. return(TRUE);
  279. ReturnFalse:
  280. return(FALSE);
  281. }
  282. /******************************Public*Routine******************************\
  283. * BOOL bInstallGammaLUT
  284. *
  285. * Load a given gamma LUT into the RAMDAC and also save it in the registry.
  286. *
  287. \**************************************************************************/
  288. BOOL
  289. bInstallGammaLUT(PPDEV ppdev, PVIDEO_CLUT pScreenClut, BOOL waitVBlank)
  290. {
  291. ULONG ulReturnedDataLength;
  292. BOOL bRet;
  293. GLINT_DECL;
  294. // only do this for 15, 16 or 32 bpp. Not 15/16 for RGB640.
  295. if ((ppdev->ulWhite == 0x0f0f0f) || (ppdev->cPelSize == 0) ||
  296. ((ppdev->flCaps & CAPS_RGB640_POINTER) && (ppdev->cPelSize == 1)))
  297. {
  298. return FALSE;
  299. }
  300. if (glintInfo->OverlayMode == GLINT_ENABLE_OVERLAY)
  301. {
  302. DISPDBG((WRNLVL, "Overlays enabled. cannot install GAMMA LUT"));
  303. return FALSE;
  304. }
  305. if (pScreenClut->NumEntries == 0)
  306. {
  307. DISPDBG((WRNLVL, "bInstallGammaLUT: Empty LUT"));
  308. return TRUE;
  309. }
  310. // Set palette registers.
  311. if (waitVBlank)
  312. {
  313. GLINT_WAIT_FOR_VBLANK;
  314. }
  315. bRet = !EngDeviceIoControl(
  316. ppdev->hDriver,
  317. IOCTL_VIDEO_SET_COLOR_REGISTERS,
  318. pScreenClut,
  319. MAX_CLUT_SIZE,
  320. NULL,
  321. 0,
  322. &ulReturnedDataLength);
  323. //@@BEGIN_DDKSPLIT
  324. #if 0
  325. // if we succeeded save the ramp in the registry and locally
  326. if (bRet)
  327. {
  328. bGlintRegistrySaveGammaLUT(ppdev, pScreenClut);
  329. }
  330. #endif
  331. //@@END_DDKSPLIT
  332. return(bRet);
  333. }
  334. /******************************Public*Routine******************************\
  335. * VOID vSetNewGammaValue
  336. *
  337. * Loads up a true color palette with the specified gamma correction factor.
  338. * This is straightforward for 24 bit true color. For 15 and 16 bpp we rely
  339. * on the miniport having enabled the palette for sparse lookup. i.e. each
  340. * 5 or 6 bit component is shifted left to create an 8 bit component before
  341. * the lookup.
  342. *
  343. * Note: the display driver shouldn't really do anything with floats or
  344. * doubles. I restrict their use to this function which is why the gamma
  345. * value is presented as a 16.16 fixed point number. And this function must
  346. * be called only from within an OPELGL escape. On NT 4 FP regs are saved
  347. * and restored for OGL escapes only.
  348. *
  349. \**************************************************************************/
  350. VOID
  351. vSetNewGammaValue(PPDEV ppdev, ULONG ulgv, BOOL waitVBlank)
  352. {
  353. PVIDEO_CLUTDATA pScreenClutData;
  354. BYTE ajClutSpace[MAX_CLUT_SIZE];
  355. PVIDEO_CLUT pScreenClut;
  356. ULONG i;
  357. UCHAR gc;
  358. double gv;
  359. double dcol;
  360. GLINT_DECL;
  361. // gamma can't be zero or we blow up
  362. if (ulgv == 0)
  363. {
  364. DISPDBG((WRNLVL, "can't use gamma value of zero"));
  365. return;
  366. }
  367. // only do this for 15, 16 or 32 bpp.
  368. if ((ppdev->ulWhite == 0x0f0f0f) || (ppdev->cPelSize == 0))
  369. {
  370. return;
  371. }
  372. pScreenClut = (PVIDEO_CLUT) ajClutSpace;
  373. pScreenClut->NumEntries = 256;
  374. pScreenClut->FirstEntry = 0;
  375. pScreenClutData = (PVIDEO_CLUTDATA) (&(pScreenClut->LookupTable[0]));
  376. //
  377. // special case gamma of 1.0 so we can load the LUT at startup without
  378. // needing any floating point calculations. NT 4 only allows FP ops in
  379. // an OGL escape. Can't use FLOATOBJ because we need to use pow().
  380. //
  381. if (ulgv == 0x10000)
  382. {
  383. for (i = 0; i < 256; ++i)
  384. {
  385. pScreenClutData[i].Red = (UCHAR)i;
  386. pScreenClutData[i].Green = (UCHAR)i;
  387. pScreenClutData[i].Blue = (UCHAR)i;
  388. pScreenClutData[i].Unused = 0;
  389. }
  390. }
  391. else
  392. {
  393. // pre-work out 1/gamma
  394. gv = (double)(ulgv >> 16) + (double)(ulgv & 0xffff) / 65536.0;
  395. gv = 1.0 / gv;
  396. for (i = 0; i < 256; ++i)
  397. {
  398. dcol = (double)i;
  399. gc = (UCHAR)(255.0 * pow((dcol/255.0), gv));
  400. pScreenClutData[i].Red = gc;
  401. pScreenClutData[i].Green = gc;
  402. pScreenClutData[i].Blue = gc;
  403. pScreenClutData[i].Unused = 0;
  404. }
  405. }
  406. if (bInstallGammaLUT(ppdev, pScreenClut, waitVBlank))
  407. {
  408. RtlCopyMemory(&glintInfo->gammaLUT, pScreenClut, MAX_CLUT_SIZE);
  409. }
  410. }
  411. //*****************************************************************************
  412. // FUNC: DrvIcmSetDeviceGammaRamp
  413. // ARGS: dhpdev (I) - handle to physical device object
  414. // iFormat (I) - always IGRF_RGB_256WORDS
  415. // lpRamp (I) - when iFormat == IGRF_RGB_256WORDS, this points to a
  416. // GAMMARAMP structure
  417. // RETN: TRUE if successful
  418. //-----------------------------------------------------------------------------
  419. // Sets the hardware Gamma ramp
  420. //*****************************************************************************
  421. BOOL DrvIcmSetDeviceGammaRamp(DHPDEV dhpdev, ULONG iFormat, VOID *pRamp)
  422. {
  423. BOOL bRet = FALSE;
  424. PDEV *ppdev = (PDEV *) dhpdev;
  425. GAMMARAMP *pgr = (GAMMARAMP *)pRamp;
  426. PVIDEO_CLUTDATA pScreenClutData;
  427. BYTE ajClutSpace[MAX_CLUT_SIZE];
  428. PVIDEO_CLUT pScreenClut;
  429. ULONG i;
  430. ULONG cj;
  431. DISPDBG((DBGLVL, "DrvIcmSetDeviceGammaRamp"));
  432. if(iFormat == IGRF_RGB_256WORDS)
  433. {
  434. pScreenClut = (PVIDEO_CLUT) ajClutSpace;
  435. pScreenClut->NumEntries = 256;
  436. pScreenClut->FirstEntry = 0;
  437. pScreenClutData = (PVIDEO_CLUTDATA) (&(pScreenClut->LookupTable[0]));
  438. for (i = 0; i < 256; ++i)
  439. {
  440. pScreenClutData[i].Red = (UCHAR)(pgr->Red[i] >> 8);
  441. pScreenClutData[i].Green = (UCHAR)(pgr->Green[i] >> 8);
  442. pScreenClutData[i].Blue = (UCHAR)(pgr->Blue[i] >> 8);
  443. pScreenClutData[i].Unused = 0;
  444. }
  445. bRet = bInstallGammaLUT(ppdev, pScreenClut, FALSE);
  446. }
  447. return(bRet);
  448. }