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.

481 lines
14 KiB

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