I've been trying to get X-Video support working for the Radeon 8500. Although there were some changes made to the Radeon driver in CVS early this month, as of a 2002-06-23 CVS checkout, X-Video support still doesn't work: applications that try to use it just display a black area.
Since I'm using Red Hat 7.3, I looked at XFree86-4.2.0-51.22.src.rpm from Rawhide, but it doesn't have working X-Video support for the Radeon 8500, either. I noticed Ryan Lovett's post: On Sun, 16 Jun 2002, Ryan Lovett wrote: > To answer my own Xv question, I found a patch: > http://quark.fsb.hr/vedran/xfree86/radeon/radeon_xv > which applies to 4.2.0 and enables XVideo support. I went and grabbed the patch, but it didn't apply cleanly to the 2002-06-23 CVS checkout. So, I manually applied the patch, integrating the changes into my 2002-06-23 CVS checkout as best I could, and then rebuilt XFree86. The result: X-Video works! As an added bonus, the screen corruptions I was seeing when iconifying/de-iconifying under enlightenment are also gone. (Enlightenment animates iconifying/de-iconifying; it may have been using X-Video to do that, or the X-Video support patch may have squashed some other bug that enlightenment was tickling.) Could the patch attached to this message please be applied to CVS? This is the result of my integrating the patch located at http://quark.fsb.hr/vedran/xfree86/radeon/radeon_xv into the 2002-06-23 CVS snapshot. I'm sure there are probably some things that will need to be cleaned up with it, but at least after a day of using it, I haven't encountered any problems yet... Thanks, -- James Ralston, Information Technology Software Engineering Institute Carnegie Mellon University, Pittsburgh, PA, USA
This patch is based upon the following patch: http://quark.fsb.hr/vedran/xfree86/radeon/radeon_xv The above patch wouldn't apply cleanly to the 2002-06-23 CVS release, so I integrated it into the 2002-06-23 CVS release as best I could. The result of the integration is this patch (the file you are looking at). See these posts for more information: http://www.xfree86.org/pipermail/xpert/2002-June/018350.html http://www.xfree86.org/pipermail/xpert/2002-June/018365.html --- XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h.ati-radeon-8500-xv Sun Jun 23 15:36:56 2002 +++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h Mon +Jun 24 02:40:42 2002 @@ -594,15 +594,6 @@ #define RADEON_DST_Y 0x1420 #define RADEON_DST_Y_SUB 0x15a8 #define RADEON_DST_Y_X 0x1438 - -#define RADEON_FCP_CNTL 0x0910 -# define RADEON_FCP_CNTL__PCICLK 0 -# define RADEON_FCP_CNTL__PCLK 1 -# define RADEON_FCP_CNTL__PCLKb 2 -# define RADEON_FCP_CNTL__HREF 3 -# define RADEON_FCP_CNTL__GND 4 -# define RADEON_FCP_CNTL__HREFb 5 - #define RADEON_FLUSH_1 0x1704 #define RADEON_FLUSH_2 0x1708 #define RADEON_FLUSH_3 0x170c @@ -852,6 +843,8 @@ # define RADEON_SCALER_INT_EMU 0x20000000L # define RADEON_SCALER_ENABLE 0x40000000L # define RADEON_SCALER_SOFT_RESET 0x80000000L +# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L + #define RADEON_OV0_V_INC 0x0424 #define RADEON_OV0_P1_V_ACCUM_INIT 0x0428 # define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L @@ -899,12 +892,11 @@ #define RADEON_OV0_FOUR_TAP_COEF_3 0x04BC #define RADEON_OV0_FOUR_TAP_COEF_4 0x04C0 #define RADEON_OV0_COLOUR_CNTL 0x04E0 -#define RADEON_OV0_VIDEO_KEY_CLR 0x04E4 -#define RADEON_OV0_VIDEO_KEY_MSK 0x04E8 +#define RADEON_OV0_VIDEO_KEY_CLR_LOW 0x04E4 +#define RADEON_OV0_VIDEO_KEY_CLR_HIGH 0x04E8 #define RADEON_OV0_GRAPHICS_KEY_CLR_LOW 0x04EC #define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH 0x04F0 -#define RADEON_OV0_GRAPHICS_KEY_CLR 0x04EC -#define RADEON_OV0_GRAPHICS_KEY_MSK 0x04F0 + #define RADEON_OV0_KEY_CNTL 0x04F4 # define RADEON_VIDEO_KEY_FN_MASK 0x00000003L # define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L @@ -921,6 +913,44 @@ # define RADEON_CMP_MIX_AND 0x00000100L #define RADEON_OV0_TEST 0x04F8 +#define RADEON_OV0_GAMMA_0_F 0x0d40 +#define RADEON_OV0_GAMMA_10_1F 0x0d44 +#define RADEON_OV0_GAMMA_20_3F 0x0d48 +#define RADEON_OV0_GAMMA_40_7F 0x0d4c +/* the registers that control gamma in the 80-37f range do not + exist on pre-R200 radeons */ +#define RADEON_OV0_GAMMA_80_BF 0x0e00 +#define RADEON_OV0_GAMMA_C0_FF 0x0e04 +#define RADEON_OV0_GAMMA_100_13F 0x0e08 +#define RADEON_OV0_GAMMA_140_17F 0x0e0c +#define RADEON_OV0_GAMMA_180_1BF 0x0e10 +#define RADEON_OV0_GAMMA_1C0_1FF 0x0e14 +#define RADEON_OV0_GAMMA_200_23F 0x0e18 +#define RADEON_OV0_GAMMA_240_27F 0x0e1c +#define RADEON_OV0_GAMMA_280_2BF 0x0e20 +#define RADEON_OV0_GAMMA_2C0_2FF 0x0e24 +#define RADEON_OV0_GAMMA_300_33F 0x0e28 +#define RADEON_OV0_GAMMA_340_37F 0x0e2c +#define RADEON_OV0_GAMMA_380_3BF 0x0d50 +#define RADEON_OV0_GAMMA_3C0_3FF 0x0d54 +#define RADEON_OV0_LIN_TRANS_A 0x0d20 +#define RADEON_OV0_LIN_TRANS_B 0x0d24 +#define RADEON_OV0_LIN_TRANS_C 0x0d28 +#define RADEON_OV0_LIN_TRANS_D 0x0d2c +#define RADEON_OV0_LIN_TRANS_E 0x0d30 +#define RADEON_OV0_LIN_TRANS_F 0x0d34 + +/* capture related registers */ + +/* this is _not_ a PLL register, unlike in rage128 */ +#define RADEON_FCP_CNTL 0x0012 /* PLL */ +# define RADEON_FCP_CNTL__PCICLK 0 +# define RADEON_FCP_CNTL__PCLK 1 +# define RADEON_FCP_CNTL__PCLKb 2 +# define RADEON_FCP_CNTL__HREF 3 +# define RADEON_FCP_CNTL__GND 4 +# define RADEON_FCP_CNTL__HREFb 5 + #define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ # define RADEON_P2PLL_RESET (1 << 0) # define RADEON_P2PLL_SLEEP (1 << 1) --- XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c.ati-radeon-8500-xv Sun Jun 23 15:36:56 2002 +++ XFree86-4.2.0/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c Mon +Jun 24 02:47:02 2002 @@ -22,6 +22,8 @@ void RADEONInitVideo(ScreenPtr pScreen) {} #else +static void RADEONInitOffscreenImages(ScreenPtr); + static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr); static int RADEONSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); static int RADEONGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); @@ -39,15 +41,24 @@ static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now); - #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) -static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; - +static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer, + xvRedIntensity,xvGreenIntensity,xvBlueIntensity, + xvContrast, xvHue, xvColor, + xv_autopaint_colorkey, xv_set_defaults; typedef struct { + CARD32 transform_index; int brightness; int saturation; + int hue; + int contrast; + int red_intensity; + int green_intensity; + int blue_intensity; + int ecp_div; + Bool doubleBuffer; unsigned char currentBuffer; FBLinearPtr linear; @@ -56,9 +67,13 @@ CARD32 videoStatus; Time offTime; Time freeTime; + Bool autopaint_colorkey; } RADEONPortPrivRec, *RADEONPortPrivPtr; +#define GET_PORT_PRIVATE(pScrn) \ + (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + void RADEONInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -67,9 +82,10 @@ XF86VideoAdaptorPtr newAdaptor = NULL; int num_adaptors; - if(info->accel && info->accel->FillSolidRects) - newAdaptor = RADEONSetupImageVideo(pScreen); - + if(info->accel && info->accel->FillSolidRects) { + newAdaptor = RADEONSetupImageVideo(pScreen); + RADEONInitOffscreenImages(pScreen); + } num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); if(newAdaptor) { @@ -116,14 +132,22 @@ }; -#define NUM_ATTRIBUTES 4 - -static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = +#define NUM_ATTRIBUTES 9+3 +static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] = { - {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, - {XvSettable | XvGettable, -64, 63, "XV_BRIGHTNESS"}, - {XvSettable | XvGettable, 0, 31, "XV_SATURATION"}, - {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} + {XvSettable , 0, 1, "XV_SET_DEFAULTS"}, + {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}, + {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"}, + {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, + {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, + {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, + {XvSettable | XvGettable, -1000, 1000, "XV_COLOR"}, + {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}, + {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, + {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, + {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, + { 0, 0, 0, NULL} /* just a place holder so I don't have to be fancy with commas +*/ }; #define NUM_IMAGES 4 @@ -136,62 +160,256 @@ XVIMAGE_I420 }; -static void RADEONSetColorKey(ScrnInfoPtr pScrn, CARD32 colorKey) +/* Reference color space transform data */ +typedef struct tagREF_TRANSFORM +{ + float RefLuma; + float RefRCb; + float RefRCr; + float RefGCb; + float RefGCr; + float RefBCb; + float RefBCr; +} REF_TRANSFORM; + +/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */ +REF_TRANSFORM trans[2] = +{ + {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */ + {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */ +}; + + +/* Gamma curve definition */ +typedef struct +{ + unsigned int gammaReg; + unsigned int gammaSlope; + unsigned int gammaOffset; +}GAMMA_SETTINGS; + +/* Recommended gamma curve parameters */ +GAMMA_SETTINGS def_gamma[18] = +{ + {RADEON_OV0_GAMMA_0_F, 0x100, 0x0000}, + {RADEON_OV0_GAMMA_10_1F, 0x100, 0x0020}, + {RADEON_OV0_GAMMA_20_3F, 0x100, 0x0040}, + {RADEON_OV0_GAMMA_40_7F, 0x100, 0x0080}, + {RADEON_OV0_GAMMA_80_BF, 0x100, 0x0100}, + {RADEON_OV0_GAMMA_C0_FF, 0x100, 0x0100}, + {RADEON_OV0_GAMMA_100_13F, 0x100, 0x0200}, + {RADEON_OV0_GAMMA_140_17F, 0x100, 0x0200}, + {RADEON_OV0_GAMMA_180_1BF, 0x100, 0x0300}, + {RADEON_OV0_GAMMA_1C0_1FF, 0x100, 0x0300}, + {RADEON_OV0_GAMMA_200_23F, 0x100, 0x0400}, + {RADEON_OV0_GAMMA_240_27F, 0x100, 0x0400}, + {RADEON_OV0_GAMMA_280_2BF, 0x100, 0x0500}, + {RADEON_OV0_GAMMA_2C0_2FF, 0x100, 0x0500}, + {RADEON_OV0_GAMMA_300_33F, 0x100, 0x0600}, + {RADEON_OV0_GAMMA_340_37F, 0x100, 0x0600}, + {RADEON_OV0_GAMMA_380_3BF, 0x100, 0x0700}, + {RADEON_OV0_GAMMA_3C0_3FF, 0x100, 0x0700} +}; + +/**************************************************************************** + * SetTransform * + * Function: Calculates and sets color space transform from supplied * + * reference transform, gamma, brightness, contrast, hue and * + * saturation. * + * Inputs: bright - brightness * + * cont - contrast * + * sat - saturation * + * hue - hue * + * red_intensity - intensity of red component * + * green_intensity - intensity of green component * + * blue_intensity - intensity of blue component * + * ref - index to the table of refernce transforms * + * Outputs: NONE * + ****************************************************************************/ + +static void RADEONSetTransform( ScrnInfoPtr pScrn, + float bright, float cont, float sat, + float hue, + float red_intensity, float green_intensity, float +blue_intensity, + CARD32 ref) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + float OvHueSin, OvHueCos; + float CAdjLuma, CAdjOff; + float CAdjRCb, CAdjRCr; + float CAdjGCb, CAdjGCr; + float CAdjBCb, CAdjBCr; + float RedAdj,GreenAdj,BlueAdj; + float OvLuma, OvROff, OvGOff, OvBOff; + float OvRCb, OvRCr; + float OvGCb, OvGCr; + float OvBCb, OvBCr; + float Loff = 64.0; + float Coff = 512.0f; + + CARD32 dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff; + CARD32 dwOvRCb, dwOvRCr; + CARD32 dwOvGCb, dwOvGCr; + CARD32 dwOvBCb, dwOvBCr; + + if (ref >= 2) return; + + OvHueSin = sin(hue); + OvHueCos = cos(hue); + + CAdjLuma = cont * trans[ref].RefLuma; + CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0; + RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0; + GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0; + BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0; + + CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr; + CAdjRCr = sat * OvHueCos * trans[ref].RefRCr; + CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr); + CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr); + CAdjBCb = sat * OvHueCos * trans[ref].RefBCb; + CAdjBCr = sat * OvHueSin * trans[ref].RefBCb; + + #if 0 /* default constants */ + CAdjLuma = 1.16455078125; + + CAdjRCb = 0.0; + CAdjRCr = 1.59619140625; + CAdjGCb = -0.39111328125; + CAdjGCr = -0.8125; + CAdjBCb = 2.01708984375; + CAdjBCr = 0; + #endif + OvLuma = CAdjLuma; + OvRCb = CAdjRCb; + OvRCr = CAdjRCr; + OvGCb = CAdjGCb; + OvGCr = CAdjGCr; + OvBCb = CAdjBCb; + OvBCr = CAdjBCr; + OvROff = RedAdj + CAdjOff - + OvLuma * Loff - (OvRCb + OvRCr) * Coff; + OvGOff = GreenAdj + CAdjOff - + OvLuma * Loff - (OvGCb + OvGCr) * Coff; + OvBOff = BlueAdj + CAdjOff - + OvLuma * Loff - (OvBCb + OvBCr) * Coff; + #if 0 /* default constants */ + OvROff = -888.5; + OvGOff = 545; + OvBOff = -1104; + #endif + + dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff; + dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff; + dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff; + /* Whatever docs say about R200 having 3.8 format instead of 3.11 + as in Radeon is a lie + Or more precisely the location of bit fields is a lie */ + if(1 || !info->IsR200) + { + dwOvLuma =(((INT32)(OvLuma * 2048.0))&0x7fff)<<17; + dwOvRCb = (((INT32)(OvRCb * 2048.0))&0x7fff)<<1; + dwOvRCr = (((INT32)(OvRCr * 2048.0))&0x7fff)<<17; + dwOvGCb = (((INT32)(OvGCb * 2048.0))&0x7fff)<<1; + dwOvGCr = (((INT32)(OvGCr * 2048.0))&0x7fff)<<17; + dwOvBCb = (((INT32)(OvBCb * 2048.0))&0x7fff)<<1; + dwOvBCr = (((INT32)(OvBCr * 2048.0))&0x7fff)<<17; + } + else + { + dwOvLuma = (((INT32)(OvLuma * 256.0))&0x7ff)<<20; + dwOvRCb = (((INT32)(OvRCb * 256.0))&0x7ff)<<4; + dwOvRCr = (((INT32)(OvRCr * 256.0))&0x7ff)<<20; + dwOvGCb = (((INT32)(OvGCb * 256.0))&0x7ff)<<4; + dwOvGCr = (((INT32)(OvGCr * 256.0))&0x7ff)<<20; + dwOvBCb = (((INT32)(OvBCb * 256.0))&0x7ff)<<4; + dwOvBCr = (((INT32)(OvBCr * 256.0))&0x7ff)<<20; + } + OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma); + OUTREG(RADEON_OV0_LIN_TRANS_B, dwOvROff | dwOvRCr); + OUTREG(RADEON_OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma); + OUTREG(RADEON_OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr); + OUTREG(RADEON_OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma); + OUTREG(RADEON_OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr); + +} + +static void RADEONSetColorKey(ScrnInfoPtr pScrn, CARD32 pixel) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 min, max; - CARD8 r, g, b; + CARD8 R, G, B; - if (info->CurrentLayout.depth > 8) - { - CARD32 rbits, gbits, bbits; + R = (pixel & pScrn->mask.red) >> pScrn->offset.red; + G = (pixel & pScrn->mask.green) >> pScrn->offset.green; + B = (pixel & pScrn->mask.blue) >> pScrn->offset.blue; - rbits = (colorKey & pScrn->mask.red) >> pScrn->offset.red; - gbits = (colorKey & pScrn->mask.green) >> pScrn->offset.green; - bbits = (colorKey & pScrn->mask.blue) >> pScrn->offset.blue; - - r = rbits << (8 - pScrn->weight.red); - g = gbits << (8 - pScrn->weight.green); - b = bbits << (8 - pScrn->weight.blue); - } - else + RADEONWaitForFifo(pScrn, 2); + if(pScrn->offset.green == 5) + { /* 5.6.5 mode, + note that these values depend on DAC_CNTL.EXPAND_MODE setting */ + R = (R<<3); + G = (G<<2); + B = (B<<3); + OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_HIGH, ((R | 0x7)<<16) | ((G | 0x3) <<8) | +(B | 0x7) | (0xff << 24)); + } else { - CARD32 bits; - - bits = colorKey & ((1 << info->CurrentLayout.depth) - 1); - r = bits; - g = bits; - b = bits; + OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_HIGH, ((R)<<16) | ((G) <<8) | (B) | (0xff +<< 24)); } - min = (r << 16) | (g << 8) | (b); - max = (0xff << 24) | (r << 16) | (g << 8) | (b); - - RADEONWaitForFifo(pScrn, 2); - OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_HIGH, max); - OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_LOW, min); + OUTREG(RADEON_OV0_GRAPHICS_KEY_CLR_LOW, (R<<16) | (G<<8) | (B) | (0x00 << 24)); } + static void RADEONResetVideo(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; + int i; RADEONWaitForIdle(pScrn); OUTREG(RADEON_OV0_SCALE_CNTL, 0x80000000); OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0); /* maybe */ - OUTREG(RADEON_OV0_EXCLUSIVE_HORZ, 0); OUTREG(RADEON_OV0_FILTER_CNTL, 0x0000000f); - OUTREG(RADEON_OV0_KEY_CNTL, RADEON_GRAPHIC_KEY_FN_EQ | - RADEON_VIDEO_KEY_FN_FALSE | + OUTREG(RADEON_OV0_KEY_CNTL, RADEON_GRAPHIC_KEY_FN_EQ | + RADEON_VIDEO_KEY_FN_FALSE | RADEON_CMP_MIX_OR); OUTREG(RADEON_OV0_TEST, 0); OUTREG(RADEON_FCP_CNTL, RADEON_FCP_CNTL__GND); OUTREG(RADEON_CAP0_TRIG_CNTL, 0); RADEONSetColorKey(pScrn, pPriv->colorKey); + + if(!info->IsR200) + { + OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000); + OUTREG(RADEON_OV0_LIN_TRANS_B, 0x198a190e); + OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a2f9da); + OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf2fe0442); + OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a22046); + OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f); + } + else + { + OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000); + OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e); + OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0); + OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442); + OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040); + OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f); + + /* Default Gamma, + Of 18 segments for gamma cure, all segments in R200 are +programmable, + while only lower 4 and upper 2 segments are programmable in +Radeon*/ + for(i=0; i<18; i++) + { + OUTREG(def_gamma[i].gammaReg, + (def_gamma[i].gammaSlope<<16) | +def_gamma[i].gammaOffset); + } + } + } @@ -201,6 +419,7 @@ XF86VideoAdaptorPtr adapt; RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv; + unsigned char *RADEONMMIO = info->MMIO; if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) return NULL; @@ -214,18 +433,34 @@ adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); adapt->pPortPrivates[0].ptr = (pointer)pPriv; - xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); - xvSaturation = MAKE_ATOM("XV_SATURATION"); - xvColorKey = MAKE_ATOM("XV_COLORKEY"); - xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); - - pPriv->colorKey = info->videoKey; +/* TODO... colorKey = info->videoKey (info->videoKey +should be loaded from XF86Config in radeon_driver.c*/ + pPriv->colorKey = (1<<8) | (2<<8) | (3<<8); pPriv->doubleBuffer = TRUE; - pPriv->videoStatus = 0; pPriv->brightness = 0; - pPriv->saturation = 16; + pPriv->transform_index = 0; + pPriv->saturation = 0; + pPriv->contrast = 0; + pPriv->red_intensity = 0; + pPriv->green_intensity = 0; + pPriv->blue_intensity = 0; + pPriv->hue = 0; + + pPriv->currentBuffer = 0; + pPriv->autopaint_colorkey = TRUE; + + /* Unlike older Mach64 chips, RADEON has only two ECP settings: 0 for PIXCLK < +175Mhz, and 1 (divide by 2) + for higher clocks, sure makes life nicer */ + if(info->ModeReg.dot_clock_freq < 17500) pPriv->ecp_div = 0; + else pPriv->ecp_div = 1; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to +%d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div); + + OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | +(pPriv->ecp_div << 8)); + + info->adaptor = adapt; + return adapt; } @@ -233,7 +468,6 @@ RADEONSetupImageVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv; XF86VideoAdaptorPtr adapt; @@ -263,11 +497,26 @@ adapt->PutImage = RADEONPutImage; adapt->QueryImageAttributes = RADEONQueryImageAttributes; - info->adaptor = adapt; + + pPriv = (RADEONPortPrivPtr)(adapt->pPortPrivates[0].ptr); REGION_INIT(pScreen, &(pPriv->clip), NullBox, 0); - + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvColor = MAKE_ATOM("XV_COLOR"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); + xvHue = MAKE_ATOM("XV_HUE"); + xvRedIntensity = MAKE_ATOM("XV_RED_INTENSITY"); + xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY"); + xvBlueIntensity = MAKE_ATOM("XV_BLUE_INTENSITY"); + + xv_autopaint_colorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + xv_set_defaults = MAKE_ATOM("XV_SET_DEFAULTS"); + RADEONResetVideo(pScrn); return adapt; @@ -420,7 +669,6 @@ } } } - static int RADEONSetPortAttribute( ScrnInfoPtr pScrn, @@ -428,29 +676,97 @@ INT32 value, pointer data ){ -/* RADEONInfoPtr info = RADEONPTR(pScrn); */ -/* unsigned char *RADEONMMIO = info->MMIO; */ + RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; + info->accel->Sync(pScrn); + + +#define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0) +#define RTFBrightness(a) (((a)*1.0)/2000.0) +#define RTFIntensity(a) (((a)*1.0)/2000.0) +#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0) +#define RTFHue(a) (((a)*3.1416)/1000.0) + + if(attribute == xv_autopaint_colorkey) { + pPriv->autopaint_colorkey = value; + } else + if(attribute == xv_set_defaults) { + RADEONSetPortAttribute(pScrn, xv_autopaint_colorkey, TRUE, data); + RADEONSetPortAttribute(pScrn, xvBrightness, 0, data); + RADEONSetPortAttribute(pScrn, xvSaturation, 0, data); + RADEONSetPortAttribute(pScrn, xvContrast, 0, data); + RADEONSetPortAttribute(pScrn, xvHue, 0, data); + RADEONSetPortAttribute(pScrn, xvRedIntensity, 0, data); + RADEONSetPortAttribute(pScrn, xvGreenIntensity,0, data); + RADEONSetPortAttribute(pScrn, xvBlueIntensity, 0, data); + + RADEONSetPortAttribute(pScrn, xvDoubleBuffer, 0, data); + } else if(attribute == xvBrightness) { - if((value < -64) || (value > 63)) - return BadValue; pPriv->brightness = value; -#if 0 - OUTREG(RADEON_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | - (pPriv->saturation << 8) | - (pPriv->saturation << 16)); -#endif + RADEONSetTransform(pScrn, RTFBrightness(pPriv->brightness), +RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), + RTFIntensity(pPriv->red_intensity), + RTFIntensity(pPriv->green_intensity), + RTFIntensity(pPriv->blue_intensity), + pPriv->transform_index); } else - if(attribute == xvSaturation) { - if((value < 0) || (value > 31)) - return BadValue; + if((attribute == xvSaturation) || (attribute == xvColor)) { + if(value<-1000)value = -1000; + if(value>1000)value = 1000; pPriv->saturation = value; -#if 0 - OUTREG(RADEON_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | - (pPriv->saturation << 8) | - (pPriv->saturation << 16)); -#endif + RADEONSetTransform(pScrn, RTFBrightness(pPriv->brightness), +RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), + RTFIntensity(pPriv->red_intensity), + RTFIntensity(pPriv->green_intensity), + RTFIntensity(pPriv->blue_intensity), + pPriv->transform_index); + } else + if(attribute == xvContrast) { + pPriv->contrast = value; + RADEONSetTransform(pScrn, RTFBrightness(pPriv->brightness), +RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), + RTFIntensity(pPriv->red_intensity), + RTFIntensity(pPriv->green_intensity), + RTFIntensity(pPriv->blue_intensity), + pPriv->transform_index); + } else + if(attribute == xvHue) { + pPriv->hue = value; + RADEONSetTransform(pScrn, RTFBrightness(pPriv->brightness), +RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), + RTFIntensity(pPriv->red_intensity), + RTFIntensity(pPriv->green_intensity), + RTFIntensity(pPriv->blue_intensity), + pPriv->transform_index); + } else + if(attribute == xvRedIntensity) { + pPriv->red_intensity = value; + RADEONSetTransform(pScrn, RTFBrightness(pPriv->brightness), +RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), + RTFIntensity(pPriv->red_intensity), + RTFIntensity(pPriv->green_intensity), + RTFIntensity(pPriv->blue_intensity), + pPriv->transform_index); + } else + if(attribute == xvGreenIntensity) { + pPriv->green_intensity = value; + RADEONSetTransform(pScrn, RTFBrightness(pPriv->brightness), +RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), + RTFIntensity(pPriv->red_intensity), + RTFIntensity(pPriv->green_intensity), + RTFIntensity(pPriv->blue_intensity), + pPriv->transform_index); + } else + if(attribute == xvBlueIntensity) { + pPriv->blue_intensity = value; + RADEONSetTransform(pScrn, RTFBrightness(pPriv->brightness), +RTFContrast(pPriv->contrast), + RTFSaturation(pPriv->saturation), RTFHue(pPriv->hue), + RTFIntensity(pPriv->red_intensity), + RTFIntensity(pPriv->green_intensity), + RTFIntensity(pPriv->blue_intensity), + pPriv->transform_index); } else if(attribute == xvDoubleBuffer) { if((value < 0) || (value > 1)) @@ -462,7 +778,8 @@ RADEONSetColorKey (pScrn, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); - } else return BadMatch; + } else + return BadMatch; return Success; } @@ -474,25 +791,46 @@ INT32 *value, pointer data ){ + RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data; + info->accel->Sync(pScrn); + + if(attribute == xv_autopaint_colorkey) { + *value = pPriv->autopaint_colorkey; + } else if(attribute == xvBrightness) { *value = pPriv->brightness; } else - if(attribute == xvSaturation) { + if((attribute == xvSaturation) || (attribute == xvColor)) { *value = pPriv->saturation; } else + if(attribute == xvContrast) { + *value = pPriv->contrast; + } else + if(attribute == xvHue) { + *value = pPriv->hue; + } else + if(attribute == xvRedIntensity) { + *value = pPriv->red_intensity; + } else + if(attribute == xvGreenIntensity) { + *value = pPriv->green_intensity; + } else + if(attribute == xvBlueIntensity) { + *value = pPriv->blue_intensity; + } else if(attribute == xvDoubleBuffer) { *value = pPriv->doubleBuffer ? 1 : 0; } else if(attribute == xvColorKey) { *value = pPriv->colorKey; - } else return BadMatch; + } else + return BadMatch; return Success; } - static void RADEONQueryBestSize( ScrnInfoPtr pScrn, @@ -633,9 +971,22 @@ int v_inc, h_inc, step_by, tmp; int p1_h_accum_init, p23_h_accum_init; int p1_v_accum_init; + int ecp_div; - v_inc = (src_h << 20) / drw_h; - h_inc = (src_w << 12) / drw_w; + /* Unlike older Mach64 chips, RADEON has only two ECP settings: 0 for PIXCLK < +175Mhz, and 1 (divide by 2) + for higher clocks, sure makes life nicer + + Here we need to find ecp_div again, as the user may have switched resolutions +*/ + if(info->ModeReg.dot_clock_freq < 17500) ecp_div = 0; + else ecp_div = 1; + + OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | +(ecp_div << 8)); + + v_inc = (src_h << (20 + + ((pScrn->currentMode->Flags & V_INTERLACE)?1:0) + - ((pScrn->currentMode->Flags & V_DBLSCAN)?1:0))) / drw_h; + h_inc = ((src_w << (12 + + ecp_div)) / drw_w); step_by = 1; while(h_inc >= (2 << 12)) { @@ -662,14 +1013,18 @@ left = (left >> 16) & 7; + RADEONWaitForFifo(pScrn, 2); OUTREG(RADEON_OV0_REG_LOAD_CNTL, 1); + RADEONWaitForIdle(pScrn); while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & (1 << 3))); - RADEONWaitForFifo(pScrn, 15); + RADEONWaitForFifo(pScrn, 1); OUTREG(RADEON_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); + + RADEONWaitForFifo(pScrn, 11); OUTREG(RADEON_OV0_STEP_BY, step_by | (step_by << 8)); - OUTREG(RADEON_OV0_Y_X_START, (dstBox->x1 + 8) | (dstBox->y1 << 16)); - OUTREG(RADEON_OV0_Y_X_END, (dstBox->x2 + 8) | (dstBox->y2 << 16)); + OUTREG(RADEON_OV0_Y_X_START, dstBox->x1 | +((dstBox->y1*((pScrn->currentMode->Flags & V_DBLSCAN)?2:1)) << 16)); + OUTREG(RADEON_OV0_Y_X_END, dstBox->x2 | +((dstBox->y2*((pScrn->currentMode->Flags & V_DBLSCAN)?2:1)) << 16)); OUTREG(RADEON_OV0_V_INC, v_inc); OUTREG(RADEON_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); OUTREG(RADEON_OV0_VID_BUF_PITCH0_VALUE, pitch); @@ -760,7 +1115,7 @@ xb = src_x + src_w; ya = src_y; yb = src_y + src_h; - + dstBox.x1 = drw_x; dstBox.x2 = drw_x + drw_w; dstBox.y1 = drw_y; @@ -863,7 +1218,7 @@ if(!RegionsEqual(&pPriv->clip, clipBoxes)) { REGION_COPY(pScreen, &pPriv->clip, clipBoxes); /* draw these */ - (*info->accel->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, + if(pPriv->autopaint_colorkey)(*info->accel->FillSolidRects)(pScrn, +pPriv->colorKey, GXcopy, (CARD32)~0, REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes)); @@ -950,5 +1305,219 @@ info->VideoTimerCallback = NULL; } +/****************** Offscreen stuff ***************/ +typedef struct { + FBLinearPtr linear; + Bool isOn; +} OffscreenPrivRec, * OffscreenPrivPtr; + +static int +RADEONAllocateSurface( + ScrnInfoPtr pScrn, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +){ + FBLinearPtr linear; + int pitch, fbpitch, size, bpp; + OffscreenPrivPtr pPriv; + if((w > 1024) || (h > 1024)) + return BadAlloc; + + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + bpp = pScrn->bitsPerPixel >> 3; + fbpitch = bpp * pScrn->displayWidth; + size = ((pitch * h) + bpp - 1) / bpp; + + if(!(linear = RADEONAllocateMemory(pScrn, NULL, size))) + return BadAlloc; + + surface->width = w; + surface->height = h; + + if(!(surface->pitches = xalloc(sizeof(int)))) { + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(surface->offsets = xalloc(sizeof(int)))) { + xfree(surface->pitches); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { + xfree(surface->pitches); + xfree(surface->offsets); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + + pPriv->linear = linear; + pPriv->isOn = FALSE; + + surface->pScrn = pScrn; + surface->id = id; + surface->pitches[0] = pitch; + surface->offsets[0] = linear->offset * bpp; + surface->devPrivate.ptr = (pointer)pPriv; + + return Success; +} + +static int +RADEONStopSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + RADEONInfoPtr info = RADEONPTR(surface->pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if(pPriv->isOn) { + OUTREG(RADEON_OV0_SCALE_CNTL, 0); + pPriv->isOn = FALSE; + } + return Success; +} + + +static int +RADEONFreeSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) + RADEONStopSurface(surface); + xf86FreeOffscreenLinear(pPriv->linear); + xfree(surface->pitches); + xfree(surface->offsets); + xfree(surface->devPrivate.ptr); + + return Success; +} + +static int +RADEONGetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value +){ + return RADEONGetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + +static int +RADEONSetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value +){ + return RADEONSetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + + +static int +RADEONDisplaySurface( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + ScrnInfoPtr pScrn = surface->pScrn; + + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr; + + + + INT32 x1, y1, x2, y2; + BoxRec dstBox; + + if(src_w > (drw_w << 4)) + drw_w = src_w >> 4; + if(src_h > (drw_h << 4)) + drw_h = src_h >> 4; + + + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!RADEONClipVideo(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + surface->width, surface->height)) + { + return Success; + } + + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + RADEONResetVideo(pScrn); + + RADEONDisplayVideo(pScrn, surface->id, surface->offsets[0], surface->offsets[0], + surface->width, surface->height, surface->pitches[0], + x1, x2, y1, &dstBox, src_w, src_h, drw_w, drw_h); + + if(portPriv->autopaint_colorkey)(*info->accel->FillSolidRects)(pScrn, +portPriv->colorKey, GXcopy, + (CARD32)~0, + REGION_NUM_RECTS(clipBoxes), + REGION_RECTS(clipBoxes)); + + + pPriv->isOn = TRUE; + /* we've prempted the XvImage stream so set its free timer */ + if(portPriv->videoStatus & CLIENT_VIDEO_ON) { + REGION_EMPTY(pScrn->pScreen, &portPriv->clip); + UpdateCurrentTime(); + portPriv->videoStatus = FREE_TIMER; + portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + info->VideoTimerCallback = RADEONVideoTimerCallback; + } + + return Success; +} + + +static void +RADEONInitOffscreenImages(ScreenPtr pScreen) +{ +/* ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn);*/ + XF86OffscreenImagePtr offscreenImages; + /* need to free this someplace */ + + if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) + return; + + offscreenImages[0].image = &Images[0]; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | + VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].alloc_surface = RADEONAllocateSurface; + offscreenImages[0].free_surface = RADEONFreeSurface; + offscreenImages[0].display = RADEONDisplaySurface; + offscreenImages[0].stop = RADEONStopSurface; + offscreenImages[0].setAttribute = RADEONSetSurfaceAttribute; + offscreenImages[0].getAttribute = RADEONGetSurfaceAttribute; + offscreenImages[0].max_width = 1024; + offscreenImages[0].max_height = 1024; + offscreenImages[0].num_attributes = NUM_ATTRIBUTES; + offscreenImages[0].attributes = Attributes; + + + xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); +} #endif /* !XvExtension */