Source code of Windows XP (NT5)
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.

529 lines
15 KiB

  1. /*++
  2. Copyright (c) 1996-1997 Cirrus Logic, Inc.
  3. Copyright (c) 1996-1997 Microsoft Corporation.
  4. Module Name:
  5. G A M M A . C
  6. Abstract:
  7. While the DAC may generate a linear relationship between the value of a
  8. color and the visual appearence of that color, the human eyes do not work
  9. in the same manner. The process done by this module manipulates the
  10. meaning of colors to get the visual linearity effect.
  11. We cannot use float or double data type in the display driver; therefore,
  12. we need implement our MATH functions. Also, the driver binary size will
  13. increase around 30KB if we use the math functions.
  14. Registry subdirectory : System\CurrentControlSet\Services\cirrus\Device0
  15. Keys : "G Gamma", and "G Contrast"
  16. Environment:
  17. Kernel mode only
  18. Notes:
  19. *
  20. *
  21. * chu01 12-16-96 Enable color correction, Start coding
  22. * myf29 02-12-97 Support Gamma correction for 755x
  23. *
  24. *
  25. --*/
  26. //---------------------------------------------------------------------------
  27. // HEADER FILES
  28. //---------------------------------------------------------------------------
  29. #include "precomp.h"
  30. #ifdef GAMMACORRECT
  31. BOOL bEnableGammaCorrect(PPDEV ppdev);
  32. //---------------------------------------------------------------------------
  33. // MACRO DEFINITION
  34. //---------------------------------------------------------------------------
  35. #define FIXEDPREC 10
  36. #define FIXEDFUDGE (0x01L << FIXEDPREC)
  37. #define FIXEDIMASK (0xFFFFFFFFL << FIXEDPREC)
  38. #define FIXEDFMASK (~FIXEDIMASK)
  39. #define FixedSign(x) (((x) < 0x00000000) ? -1L : 1L)
  40. #define FixedAbs(x) (((x) < 0x00000000) ? -(x) : (x))
  41. #define FixedMakeInt(x) (((long) x)*FIXEDFUDGE)
  42. #define FixedTrunc(x) ((long) ((x) & FIXEDIMASK))
  43. #define FixedRound(x) (FixedTrunc((x) + (FIXEDFUDGE >> 1)))
  44. #define FixedInt(x) ((x) /FIXEDFUDGE)
  45. #define FixedFract(x) ((((FixedAbs(x)) - FixedTrunc(FixedAbs(x)))*1000)/FIXEDFUDGE)
  46. #define FixedAdd(x,y) ((x) + (y))
  47. #define FixedSub(x,y) ((x) - (y))
  48. #define FixedMul(x,y) ((((x) * (y))+(FIXEDFUDGE >> 1))/FIXEDFUDGE)
  49. #define FixedDiv(x,y) (long) ((y==0) ? 0x7FFFFFFFL : ((x)*FIXEDFUDGE) / (y))
  50. //---------------------------------------------------------------------------
  51. // VARABLES
  52. //---------------------------------------------------------------------------
  53. PGAMMA_VALUE GammaFactor ; // gamma facter for All, Blue, Green, Red
  54. PCONTRAST_VALUE ContrastFactor ; // contrast facter for All, Blue, Green, Red
  55. //------------------------------------------------------------------------------
  56. //
  57. // Function: UCHAR GammaCorrect(UCHAR gamma, UCHAR v)
  58. // {
  59. // UCHAR dv;
  60. // dv = (UCHAR)(256 * pow(v/256.0, pow(10, (gamma - 128)/128.0)));
  61. // return dv;
  62. // }
  63. //
  64. // Input:
  65. // gamma: new gamma factor from 0 to 255
  66. // color: color value for Red, Green, or Blue
  67. //
  68. // Output:
  69. // dv: new color value after gamma correction
  70. //
  71. //------------------------------------------------------------------------------
  72. UCHAR GammaCorrect(UCHAR gamma, UCHAR v)
  73. {
  74. UCHAR dv ;
  75. long Color, GammaF, Result ;
  76. DISPDBG((4, "GammaCorrect")) ;
  77. if ((gamma == 128) ||
  78. (gamma == 127) ||
  79. (gamma == 126))
  80. return v ;
  81. Color = FixedDiv(v, 256) ; // old color value
  82. if (Color == 0L) // in case then we don't need go though calculation
  83. return 0 ;
  84. GammaF = FixedDiv(gamma-128, 128) ; // new gamma factor
  85. Result = Power(Color, Power(FixedMake(10, 0, 1000), GammaF)) ;
  86. Result = (long)FixedInt(FixedMul(FixedMake(256, 0, 1000), Result)) ;
  87. dv = (UCHAR)Result ;
  88. return dv ;
  89. } // GammaCorrect
  90. //------------------------------------------------------------------------------
  91. // Function:long Power(long Base, long Exp)
  92. //
  93. // Input:
  94. // Base: base number of power function
  95. // Exp: exponential number
  96. //
  97. // Output:
  98. // 20 bits format of integer and fraction number
  99. // 0 = not use(or sign),
  100. // i = integer portion,
  101. // f = fraction portion
  102. // 0 + i + f = 32 bits
  103. // format = 000000000000iiiiiiiiiiiiiiiiiiiffffffffffffffffffff
  104. //
  105. //------------------------------------------------------------------------------
  106. long Power(long Base, long Exp)
  107. {
  108. int i, iSignExp;
  109. long lResult, lResultFract, lRoot;
  110. iSignExp = FixedSign(Exp); // get sing bit
  111. Exp = FixedAbs(Exp); // convert to positive
  112. // calculate integer expression
  113. lResult = FixedMakeInt(1);
  114. for(i = 0; i < FixedInt(Exp); i++)
  115. lResult = FixedMul(lResult,Base);
  116. // calculate fraction expression and add to integer result
  117. if(FixedFract(Exp) != 0) {
  118. lResultFract = FixedMakeInt(1);
  119. lRoot = FixedAbs(Base);
  120. for(i = 0x0; i < FIXEDPREC; i++) {
  121. lRoot = FixedSqrt(lRoot);
  122. if(((0x01L << (FIXEDPREC - 1 - i)) & Exp) != 0) {
  123. lResultFract = FixedMul(lResultFract, lRoot);
  124. }
  125. }
  126. lResult = FixedMul(lResult, lResultFract);
  127. }
  128. if(iSignExp == -1)
  129. lResult = FixedDiv(FixedMakeInt(1), lResult);
  130. return(lResult);
  131. } // Power
  132. //------------------------------------------------------------------------------
  133. //
  134. // Function:long FixedMake(long x, long y, long z)
  135. //
  136. // Input:
  137. // x: integer portion of the number
  138. // y: fraction portion of the number
  139. // z: precison after decimal
  140. //
  141. // Output:
  142. // 20 bits format of integer and fraction number
  143. // 0 = not use(or sign),
  144. // i = integer portion,
  145. // f = fraction portion
  146. // 0 + i + f = 32 bits
  147. // format = 000000000000iiiiiiiiiiiiiiiiiiiffffffffffffffffffff
  148. //
  149. //------------------------------------------------------------------------------
  150. long FixedMake(long x, long y, long z)
  151. {
  152. DISPDBG((4, "FixedMake")) ;
  153. if (x == 0)
  154. return((y * FIXEDFUDGE) / z);
  155. else
  156. return(FixedSign(x) * ((FixedAbs(x)*FIXEDFUDGE) | (((y * FIXEDFUDGE)/ z) & FIXEDFMASK)));
  157. } // FixedMake
  158. //------------------------------------------------------------------------------
  159. //
  160. // Function:long FixedSqrt(long Root)
  161. //
  162. // Input:
  163. // Root: number to square
  164. //
  165. // Output:
  166. // 20 bits format of integer and fraction number
  167. // 0 = not use(or sign),
  168. // i = integer portion,
  169. // f = fraction portion
  170. // 0 + i + f = 32 bits
  171. // format = 000000000000iiiiiiiiiiiiiiiiiiiffffffffffffffffffff
  172. //
  173. //------------------------------------------------------------------------------
  174. long FixedSqrt(long Root)
  175. {
  176. long lApprox;
  177. long lStart;
  178. long lEnd;
  179. if(FixedSign(Root) != 1)
  180. return(0);
  181. lStart = (long) FixedMakeInt(1);
  182. lEnd = Root;
  183. if(Root < lStart) {
  184. lEnd = lStart;
  185. lStart = Root;
  186. }
  187. lApprox = (lStart + lEnd) / 2;
  188. while(lStart != lEnd) {
  189. lApprox = (lStart + lEnd) / 2;
  190. if ((lApprox == lStart) || (lApprox == lEnd)) {
  191. lStart = lEnd = lApprox;
  192. }
  193. else {
  194. if(FixedMul(lApprox, lApprox) < Root) {
  195. lStart = lApprox;
  196. }
  197. else {
  198. lEnd = lApprox;
  199. }
  200. }
  201. } // end of while
  202. return(lApprox);
  203. }
  204. //
  205. // C O N T R A S T F A C T O R
  206. //
  207. //------------------------------------------------------------------------------
  208. //
  209. // Function:long CalcContrast(UCHAR contrast, UCHAR v)
  210. //
  211. // Input:
  212. //
  213. // Output:
  214. //
  215. //------------------------------------------------------------------------------
  216. UCHAR CalcContrast(UCHAR contrast, UCHAR v)
  217. {
  218. int dv;
  219. dv = ((((int)v - 128) * (int)contrast) / 128) + 128 ;
  220. if(dv < 0) dv = 0;
  221. if(dv > 255) dv = 255;
  222. return (unsigned char)dv;
  223. } // CalcContrast
  224. //
  225. // G A M M A F A C T O R
  226. //
  227. //---------------------------------------------------------------------------
  228. //
  229. // Routine Description:
  230. //
  231. // Arguments:
  232. //
  233. // Palette: Pointer to palette array
  234. // NumberOfEntryes: Number of palette entries need modified
  235. //
  236. // Return Value:
  237. //
  238. // None
  239. //
  240. //---------------------------------------------------------------------------
  241. VOID CalculateGamma(
  242. PDEV* ppdev,
  243. PVIDEO_CLUT pScreenClut,
  244. long NumberOfEntries )
  245. {
  246. UCHAR GammaRed, GammaGreen, GammaBlue, Red, Green, Blue ;
  247. UCHAR Contrast, ContrastRed, ContrastGreen, ContrastBlue ;
  248. UCHAR Brightness ;
  249. int PalSegment, PalOffset, i ;
  250. int iGamma ;
  251. PALETTEENTRY* ppalSrc ;
  252. PALETTEENTRY* ppalDest ;
  253. PALETTEENTRY* ppalEnd ;
  254. DISPDBG((2, "CalculateGamma")) ;
  255. Brightness = (LONG) GammaFactor >> 24 ;
  256. GammaBlue = (LONG) GammaFactor >> 16 ;
  257. GammaGreen = (LONG) GammaFactor >> 8 ;
  258. GammaRed = (LONG) GammaFactor >> 0 ;
  259. iGamma = (int)(Brightness - 128) + (int)GammaRed ;
  260. GammaRed = (UCHAR)iGamma ;
  261. if (iGamma < 0)
  262. GammaRed = 0 ;
  263. if (iGamma > 255)
  264. GammaRed = 255 ;
  265. iGamma = (int)(Brightness - 128) + (int)GammaGreen ;
  266. GammaGreen = (UCHAR)iGamma ;
  267. if (iGamma < 0)
  268. GammaGreen = 0 ;
  269. if (iGamma > 255)
  270. GammaGreen = 255 ;
  271. iGamma = (int)(Brightness - 128) + (int)GammaBlue ;
  272. GammaBlue = (UCHAR)iGamma ;
  273. if (iGamma < 0)
  274. GammaBlue = 0 ;
  275. if (iGamma > 255)
  276. GammaBlue = 255 ;
  277. Contrast = (LONG) ContrastFactor >> 0 ;
  278. ppalDest = (PALETTEENTRY*) pScreenClut->LookupTable;
  279. ppalEnd = &ppalDest[NumberOfEntries];
  280. i = 0 ;
  281. for (; ppalDest < ppalEnd; ppalDest++, i++)
  282. {
  283. Red = ppalDest->peRed ;
  284. Green = ppalDest->peGreen ;
  285. Blue = ppalDest->peBlue ;
  286. Red = GammaCorrect(GammaRed, Red) ;
  287. Green = GammaCorrect(GammaGreen, Green) ;
  288. Blue = GammaCorrect(GammaBlue, Blue) ;
  289. Red = CalcContrast(Contrast, Red) ;
  290. Green = CalcContrast(Contrast, Green) ;
  291. Blue = CalcContrast(Contrast, Blue) ;
  292. if (ppdev->iBitmapFormat == BMF_8BPP)
  293. {
  294. ppalDest->peRed = Red >> 2 ;
  295. ppalDest->peGreen = Green >> 2 ;
  296. ppalDest->peBlue = Blue >> 2 ;
  297. }
  298. else if ((ppdev->iBitmapFormat == BMF_16BPP) ||
  299. (ppdev->iBitmapFormat == BMF_24BPP))
  300. {
  301. ppalDest->peRed = Red ;
  302. ppalDest->peGreen = Green ;
  303. ppalDest->peBlue = Blue ;
  304. }
  305. }
  306. return ;
  307. } // CalulateGamma
  308. /******************************************************************************\
  309. *
  310. * Function: bEnableGammaCorrect
  311. *
  312. * Enable GammaTable. Called from DrvEnableSurface.
  313. *
  314. * Parameters: ppdev Pointer to phsyical device.
  315. *
  316. * Returns: TRUE : successful; FALSE: fail
  317. *
  318. \******************************************************************************/
  319. BOOL bEnableGammaCorrect(PDEV* ppdev)
  320. {
  321. BYTE srIndex, srData ;
  322. BYTE* pjPorts = ppdev->pjPorts ;
  323. int i ;
  324. DISPDBG((4, "bEnableGammaCorrect")) ;
  325. //
  326. // Enable Gamma correction. If needed; Otherwise, turn it off.
  327. //
  328. srIndex = CP_IN_BYTE(pjPorts, SR_INDEX) ; // i 3c4 srIndex
  329. CP_OUT_BYTE(pjPorts, SR_INDEX, 0x12) ; // o 3c4 12
  330. srData = CP_IN_BYTE(pjPorts, SR_DATA) ; // i 3c5 srData
  331. if (ppdev->flCaps & CAPS_GAMMA_CORRECT)
  332. {
  333. if ((ppdev->iBitmapFormat == BMF_16BPP) ||
  334. (ppdev->iBitmapFormat == BMF_24BPP))
  335. srData |= 0x40 ; // 3c5.12.D6 = 1
  336. else
  337. srData &= 0xBF ; // 3c5.12.D6 = 0
  338. }
  339. else
  340. srData &= 0xBF ; // 3c5.12.D6 = 0
  341. CP_OUT_BYTE(pjPorts, SR_DATA, srData) ; // o 3c5 srData
  342. CP_OUT_BYTE(pjPorts, SR_INDEX, srIndex) ; // o 3c4 srIndex
  343. if ( srData & 0x40 )
  344. {
  345. return TRUE ;
  346. }
  347. else
  348. {
  349. return FALSE ;
  350. }
  351. } // bEnableGammaCorrect
  352. //myf29 : for 755x Gamma Correct support begin
  353. /******************************************************************************\
  354. *
  355. * Function: bEnableGamma755x
  356. *
  357. * Enable Graphic GammaTable. Called from DrvAssertMode/DrvEscape
  358. *
  359. * Parameters: ppdev Pointer to phsyical device.
  360. *
  361. * Returns: TRUE : successful; FALSE: fail
  362. *
  363. \******************************************************************************/
  364. BOOL bEnableGamma755x(PDEV* ppdev)
  365. {
  366. BYTE crIndex, crData ;
  367. BYTE* pjPorts = ppdev->pjPorts ;
  368. BOOL status;
  369. DISPDBG((4, "bEnableGamma755x")) ;
  370. //
  371. // Enable Gamma correction. If needed; Otherwise, turn it off.
  372. //
  373. crIndex = CP_IN_BYTE(pjPorts, CRTC_INDEX) ; // i 3d4 crIndex
  374. status = FALSE;
  375. if (ppdev->flCaps & CAPS_GAMMA_CORRECT)
  376. {
  377. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x8E); // CR8E[2]=0
  378. crData = CP_IN_BYTE(pjPorts, CRTC_DATA);
  379. if ((ppdev->iBitmapFormat == BMF_16BPP) ||
  380. (ppdev->iBitmapFormat == BMF_24BPP))
  381. {
  382. crData &= 0xFB ; // CR8E[2] = 0
  383. status = TRUE;
  384. }
  385. else
  386. crData |= 0x04 ; // CR8E[2] = 1
  387. CP_OUT_BYTE(pjPorts, CRTC_DATA, crData) ; // o 3d5 crData
  388. }
  389. CP_OUT_BYTE(pjPorts, CRTC_INDEX, crIndex) ; // o 3d4 crIndex
  390. return(status);
  391. } // bEnableGamma755x
  392. /******************************************************************************\
  393. *
  394. * Function: bEnableGammaVideo755x
  395. *
  396. * Enable Video GammaTable. Called from DrvAssertMode/DrvEscape
  397. *
  398. * Parameters: ppdev Pointer to phsyical device.
  399. *
  400. * Returns: TRUE : successful; FALSE: fail
  401. *
  402. \******************************************************************************/
  403. BOOL bEnableGammaVideo755x(PDEV* ppdev)
  404. {
  405. BYTE crIndex, crData ;
  406. BYTE* pjPorts = ppdev->pjPorts ;
  407. BOOL status;
  408. DISPDBG((4, "bEnableGammaVideo755x")) ;
  409. //
  410. // Enable Gamma correction. If needed; Otherwise, turn it off.
  411. //
  412. crIndex = CP_IN_BYTE(pjPorts, CRTC_INDEX) ; // i 3d4 crIndex
  413. status = FALSE;
  414. if (ppdev->flCaps & CAPS_GAMMA_CORRECT)
  415. {
  416. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x36); // CR36[6]=1:enable VW LUT
  417. crData = CP_IN_BYTE(pjPorts, CRTC_DATA);
  418. // if ((ppdev->iBitmapFormat == BMF_16BPP) ||
  419. // (ppdev->iBitmapFormat == BMF_24BPP))
  420. {
  421. crData |= 0x40 ; // CR36[6] = 1
  422. CP_OUT_BYTE(pjPorts, CRTC_DATA, crData);
  423. CP_OUT_BYTE(pjPorts, CRTC_INDEX, 0x3F) ; // CR3F[4]=1:select VW
  424. crData = CP_IN_BYTE(pjPorts, CRTC_DATA);
  425. crData |= 0x10 ; // CR3F[4] = 1
  426. CP_OUT_BYTE(pjPorts, CRTC_DATA, crData);
  427. status = TRUE;
  428. }
  429. }
  430. CP_OUT_BYTE(pjPorts, CRTC_INDEX, crIndex) ; // o 3d4 crIndex
  431. return(status);
  432. } // bEnableGammaVideo755x
  433. //myf29 end
  434. #endif // GAMMACORRECT
  435.