http://bugs.freedesktop.org/show_bug.cgi?id=16001
--- Comment #5 from Tobias Diedrich <[EMAIL PROTECTED]> 2008-05-19 11:09:48 PST --- (In reply to comment #4) > Probably the values in the r200 gamma table are just wrong - at least > datasheets seem to indicate no difference between r200 and r300 in that area I sure hope these datasheets will also eventually be publicly available. :) http://www.x.org/docs/AMD/R3xx_3D_Registers.pdf looks promising in that regard. (And I'd also be interested in Imageon w100 datasheets for my Zaurus, but that's probably a rather small target group... I really _do_ wonder if this thing can do proper busmaster DMA) > I know there were some earlier complaints about gamma tables being wrong, but > IIRC noone really investigated this a bit deeper. I never noticed the problem on my r200 and the r300 with my old TFT (6bit S-IPS panel + dither), but on my new Samsung (8bit S-PVA panel) it much easier to spot . > (and for that matter, those segments which are defined on r100 too should be > the same as far as I can tell, except the offset for the two last segments, > and > they'd indeed pretty much be the same with those shifts). I suspected that r200 and r300 are the same, but without a r200 to test (I gave my old r200 away, unfortunately, and also don't have a AGP board here) I didn't want to touch that part of the code. :) > > | /* Set gamma */ > > | RADEONWaitForIdleMMIO(pScrn); > > | ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL) & > > ~RADEON_SCALER_GAMMA_SEL_MASK; > > | OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl | (gamma << 0x00000005)); > > > > breaks my overlay (pink screen) for 'gamma' values other than '0'. > Yup, that's r100 only (the test should be < CHIP_FAMILY_R200 though, not <= - See above, I wanted to keep the logic for chips other than r300 unchanged. > Maybe we should try to get rid of the tables entirely for > r200/r300 and just calculate all the segment values as needed, with arbitrary > gamma value. Something like this? (Still my debugging stuff, but works for me :)) --- xserver-xorg-video-ati-6.8.0/src/radeon_video.c 2008-02-19 02:10:46.000000000 +0100 +++ xserver-xorg-video-ati-6.8.0.patched_arbitrary_gamma/src/radeon_video.c 2008-05-16 23:14:53.000000000 +0200 @@ -106,6 +106,7 @@ static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity; static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults; static Atom xvGamma, xvColorspace; +static Atom xvOV0FlagControl, xvOV0Gamma00000f, xvOV0Gamma01001f, xvOV0Gamma02003f; static Atom xvCRTC; static Atom xvEncoding, xvFrequency, xvVolume, xvMute, xvDecBrightness, xvDecContrast, xvDecHue, xvDecColor, xvDecSaturation, @@ -367,7 +368,7 @@ #endif -#define NUM_ATTRIBUTES 22 +#define NUM_ATTRIBUTES 26 #define NUM_DEC_ATTRIBUTES (NUM_ATTRIBUTES+12) static XF86AttributeRec Attributes[NUM_DEC_ATTRIBUTES+1] = @@ -379,6 +380,10 @@ {XvSettable , 0, 1, "XV_SET_DEFAULTS"}, {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, {XvSettable | XvGettable, 0, ~0,"XV_COLORKEY"}, + {XvSettable | XvGettable, 0, ~0,"XV_OV0_FLAG_CNTL"}, + {XvSettable | XvGettable, 0, ~0,"XV_OV0_GAMMA_000_00F"}, + {XvSettable | XvGettable, 0, ~0,"XV_OV0_GAMMA_010_01F"}, + {XvSettable | XvGettable, 0, ~0,"XV_OV0_GAMMA_020_03F"}, {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, {XvSettable | XvGettable, 0, 255, "XV_OVERLAY_ALPHA"}, {XvSettable | XvGettable, 0, 255, "XV_GRAPHICS_ALPHA"}, @@ -679,9 +684,9 @@ static GAMMA_CURVE_R200 gamma_curve_r200[8] = { /* Gamma 1.0 */ - {0x00000040, 0x00000000, - 0x00000040, 0x00000020, - 0x00000080, 0x00000040, + {0x00000100, 0x00000000, + 0x00000100, 0x00000020, + 0x00000100, 0x00000040, 0x00000100, 0x00000080, 0x00000100, 0x00000100, 0x00000100, 0x00000100, @@ -840,8 +845,40 @@ 0.9135} }; + +static double gammafn(double x, double g) +{ + return pow(x, 1.0/g); +} + +static CARD32 calc_gamma_r300(CARD32 gamma, int idx) +{ + double y0, y1, y2, dy, range; + double g; + int offsets[] = {0x000, 0x010, 0x020, 0x040, 0x080, 0x0c0, + 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, + 0x300, 0x340, 0x380, 0x3c0, + 0x400}; + CARD32 offset, slope; + + idx = ClipValue(idx, 0, sizeof(offsets)/sizeof(int)-1); + g = (double)gamma / 1000.0; + + range = offsets[idx+1] - offsets[idx]; + y0 = gammafn((double)offsets[idx<4?idx:idx&~1]/(double)0x400, g); + y1 = gammafn((double)offsets[idx]/(double)0x400, g); + y2 = gammafn((double)offsets[idx+1]/(double)0x400, g); + dy = y2-y1; + + offset = y0*0x800+0.5; + slope = dy*0x40000/range+0.5; + + return offset | (slope << 0x10); +} + static void -RADEONSetOverlayGamma(ScrnInfoPtr pScrn, CARD32 gamma) +RADEONSetOverlayGamma(ScrnInfoPtr pScrn, CARD32 gamma, CARD32 user_gamma) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -850,64 +887,28 @@ /* Set gamma */ RADEONWaitForIdleMMIO(pScrn); ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL) & ~RADEON_SCALER_GAMMA_SEL_MASK; - OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl | (gamma << 0x00000005)); + OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl); /* Load gamma curve adjustments */ if (info->ChipFamily >= CHIP_FAMILY_R200) { - OUTREG(RADEON_OV0_GAMMA_000_00F, - (gamma_curve_r200[gamma].GAMMA_0_F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_0_F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_010_01F, - (gamma_curve_r200[gamma].GAMMA_10_1F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_10_1F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_020_03F, - (gamma_curve_r200[gamma].GAMMA_20_3F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_20_3F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_040_07F, - (gamma_curve_r200[gamma].GAMMA_40_7F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_40_7F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_080_0BF, - (gamma_curve_r200[gamma].GAMMA_80_BF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_80_BF_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_0C0_0FF, - (gamma_curve_r200[gamma].GAMMA_C0_FF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_C0_FF_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_100_13F, - (gamma_curve_r200[gamma].GAMMA_100_13F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_100_13F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_140_17F, - (gamma_curve_r200[gamma].GAMMA_140_17F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_140_17F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_180_1BF, - (gamma_curve_r200[gamma].GAMMA_180_1BF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_180_1BF_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_1C0_1FF, - (gamma_curve_r200[gamma].GAMMA_1C0_1FF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_1C0_1FF_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_200_23F, - (gamma_curve_r200[gamma].GAMMA_200_23F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_200_23F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_240_27F, - (gamma_curve_r200[gamma].GAMMA_240_27F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_240_27F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_280_2BF, - (gamma_curve_r200[gamma].GAMMA_280_2BF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_280_2BF_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_2C0_2FF, - (gamma_curve_r200[gamma].GAMMA_2C0_2FF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_2C0_2FF_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_300_33F, - (gamma_curve_r200[gamma].GAMMA_300_33F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_300_33F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_340_37F, - (gamma_curve_r200[gamma].GAMMA_340_37F_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_340_37F_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_380_3BF, - (gamma_curve_r200[gamma].GAMMA_380_3BF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_380_3BF_SLOPE << 0x00000010)); - OUTREG(RADEON_OV0_GAMMA_3C0_3FF, - (gamma_curve_r200[gamma].GAMMA_3C0_3FF_OFFSET << 0x00000000) | - (gamma_curve_r200[gamma].GAMMA_3C0_3FF_SLOPE << 0x00000010)); + OUTREG(RADEON_OV0_GAMMA_000_00F, calc_gamma_r300(user_gamma, 0)); + OUTREG(RADEON_OV0_GAMMA_010_01F, calc_gamma_r300(user_gamma, 1)); + OUTREG(RADEON_OV0_GAMMA_020_03F, calc_gamma_r300(user_gamma, 2)); + OUTREG(RADEON_OV0_GAMMA_040_07F, calc_gamma_r300(user_gamma, 3)); + OUTREG(RADEON_OV0_GAMMA_080_0BF, calc_gamma_r300(user_gamma, 4)); + OUTREG(RADEON_OV0_GAMMA_0C0_0FF, calc_gamma_r300(user_gamma, 5)); + OUTREG(RADEON_OV0_GAMMA_100_13F, calc_gamma_r300(user_gamma, 6)); + OUTREG(RADEON_OV0_GAMMA_140_17F, calc_gamma_r300(user_gamma, 7)); + OUTREG(RADEON_OV0_GAMMA_180_1BF, calc_gamma_r300(user_gamma, 8)); + OUTREG(RADEON_OV0_GAMMA_1C0_1FF, calc_gamma_r300(user_gamma, 9)); + OUTREG(RADEON_OV0_GAMMA_200_23F, calc_gamma_r300(user_gamma, 10)); + OUTREG(RADEON_OV0_GAMMA_240_27F, calc_gamma_r300(user_gamma, 11)); + OUTREG(RADEON_OV0_GAMMA_280_2BF, calc_gamma_r300(user_gamma, 12)); + OUTREG(RADEON_OV0_GAMMA_2C0_2FF, calc_gamma_r300(user_gamma, 13)); + OUTREG(RADEON_OV0_GAMMA_300_33F, calc_gamma_r300(user_gamma, 14)); + OUTREG(RADEON_OV0_GAMMA_340_37F, calc_gamma_r300(user_gamma, 15)); + OUTREG(RADEON_OV0_GAMMA_380_3BF, calc_gamma_r300(user_gamma, 16)); + OUTREG(RADEON_OV0_GAMMA_3C0_3FF, calc_gamma_r300(user_gamma, 17)); } else { OUTREG(RADEON_OV0_GAMMA_000_00F, (gamma_curve_r100[gamma].GAMMA_0_F_OFFSET << 0x00000000) | @@ -1080,7 +1081,7 @@ } /* set gamma */ - RADEONSetOverlayGamma(pScrn, gamma); + RADEONSetOverlayGamma(pScrn, gamma, user_gamma); /* color transforms */ OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma); @@ -1217,6 +1218,10 @@ xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); xvCRTC = MAKE_ATOM("XV_CRTC"); + xvOV0FlagControl = MAKE_ATOM("XV_OV0_FLAG_CNTL"); + xvOV0Gamma00000f = MAKE_ATOM("XV_OV0_GAMMA_000_00F"); + xvOV0Gamma01001f = MAKE_ATOM("XV_OV0_GAMMA_010_01F"); + xvOV0Gamma02003f = MAKE_ATOM("XV_OV0_GAMMA_020_03F"); xvOvAlpha = MAKE_ATOM("XV_OVERLAY_ALPHA"); xvGrAlpha = MAKE_ATOM("XV_GRAPHICS_ALPHA"); xvAlphaMode = MAKE_ATOM("XV_ALPHA_MODE"); @@ -1285,7 +1290,7 @@ * segments are programmable in the older Radeons. */ - RADEONSetOverlayGamma(pScrn, 0); /* gamma = 1.0 */ + RADEONSetOverlayGamma(pScrn, 0, 1000); /* gamma = 1.0 */ if(pPriv->VIP!=NULL){ RADEONVIP_reset(pScrn,pPriv); @@ -1868,6 +1873,22 @@ if(pPriv->i2c != NULL) RADEON_board_setmisc(pPriv); if(pPriv->uda1380 != NULL) xf86_uda1380_setvolume(pPriv->uda1380, value); } + else if(attribute == xvOV0FlagControl) + { + OUTREG(RADEON_OV0_FLAG_CNTL, value); + } + else if(attribute == xvOV0Gamma00000f) + { + OUTREG(RADEON_OV0_GAMMA_000_00F, value); + } + else if(attribute == xvOV0Gamma01001f) + { + OUTREG(RADEON_OV0_GAMMA_010_01F, value); + } + else if(attribute == xvOV0Gamma02003f) + { + OUTREG(RADEON_OV0_GAMMA_020_03F, value); + } else if(attribute == xvOverlayDeinterlacingMethod) { if(value<0)value = 0; @@ -1944,6 +1965,7 @@ pointer data) { RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; if (info->accelOn) RADEON_SYNC(info, pScrn); @@ -2025,6 +2047,14 @@ *value = pPriv->instance_id; else if(attribute == xvAdjustment) *value = pPriv->adjustment; + else if(attribute == xvOV0FlagControl) + *value = INREG(RADEON_OV0_FLAG_CNTL); + else if(attribute == xvOV0Gamma00000f) + *value = INREG(RADEON_OV0_GAMMA_000_00F); + else if(attribute == xvOV0Gamma01001f) + *value = INREG(RADEON_OV0_GAMMA_010_01F); + else if(attribute == xvOV0Gamma02003f) + *value = INREG(RADEON_OV0_GAMMA_020_03F); else return BadMatch; -- Configure bugmail: http://bugs.freedesktop.org/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug. _______________________________________________ xorg-driver-ati mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-driver-ati
