📄 r128_video.c
字号:
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c,v 1.30 2003/11/10 18:22:18 tsi Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include "r128.h"#include "r128_reg.h"#ifdef XF86DRI#include "r128_common.h"#include "r128_sarea.h"#endif#include "xf86.h"#include "dixstruct.h"#include <X11/extensions/Xv.h>#include "fourcc.h"#define OFF_DELAY 250 /* milliseconds */#define FREE_DELAY 15000#define OFF_TIMER 0x01#define FREE_TIMER 0x02#define CLIENT_VIDEO_ON 0x04#define TIMER_MASK (OFF_TIMER | FREE_TIMER)static XF86VideoAdaptorPtr R128SetupImageVideo(ScreenPtr);static int R128SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);static int R128GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);static void R128StopVideo(ScrnInfoPtr, pointer, Bool);static void R128QueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);static int R128PutImage(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);static int R128QueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *);static void R128ResetVideo(ScrnInfoPtr);static void R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now);#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;typedef struct { int brightness; int saturation; Bool doubleBuffer; unsigned char currentBuffer; FBLinearPtr linear; RegionRec clip; CARD32 colorKey; CARD32 videoStatus; Time offTime; Time freeTime; int ecp_div;} R128PortPrivRec, *R128PortPrivPtr;static void R128ECP(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; int dot_clock = info->ModeReg.dot_clock_freq; if (dot_clock < 12500) pPriv->ecp_div = 0; else if (dot_clock < 25000) pPriv->ecp_div = 1; else pPriv->ecp_div = 2; OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, pPriv->ecp_div<<8, ~R128_ECP_DIV_MASK);}void R128InitVideo(ScreenPtr pScreen){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; XF86VideoAdaptorPtr newAdaptor = NULL; int num_adaptors; newAdaptor = R128SetupImageVideo(pScreen); num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); if(newAdaptor) { if(!num_adaptors) { num_adaptors = 1; adaptors = &newAdaptor; } else { newAdaptors = /* need to free this someplace */ xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); if(newAdaptors) { memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); newAdaptors[num_adaptors] = newAdaptor; adaptors = newAdaptors; num_adaptors++; } } } if(num_adaptors) xf86XVScreenInit(pScreen, adaptors, num_adaptors); if(newAdaptors) xfree(newAdaptors);}#define MAXWIDTH 2048#define MAXHEIGHT 2048/* client libraries expect an encoding */static XF86VideoEncodingRec DummyEncoding ={ 0, "XV_IMAGE", MAXWIDTH, MAXHEIGHT, {1, 1}};#define NUM_FORMATS 12static XF86VideoFormatRec Formats[NUM_FORMATS] ={ {8, TrueColor}, {8, DirectColor}, {8, PseudoColor}, {8, GrayScale}, {8, StaticGray}, {8, StaticColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, {15, DirectColor}, {16, DirectColor}, {24, DirectColor}};#define NUM_ATTRIBUTES 4static XF86AttributeRec Attributes[NUM_ATTRIBUTES] ={ {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"}};#define NUM_IMAGES 4static XF86ImageRec Images[NUM_IMAGES] ={ XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420};static voidR128ResetVideo(ScrnInfoPtr pScrn){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; OUTREG(R128_OV0_SCALE_CNTL, 0x80000000); OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0); OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0); /* maybe */ OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f); OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | (pPriv->saturation << 8) | (pPriv->saturation << 16)); OUTREG(R128_OV0_GRAPHICS_KEY_MSK, (1 << pScrn->depth) - 1); OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey); OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE); OUTREG(R128_OV0_TEST, 0);}static XF86VideoAdaptorPtrR128AllocAdaptor(ScrnInfoPtr pScrn){ XF86VideoAdaptorPtr adapt; R128InfoPtr info = R128PTR(pScrn); R128PortPrivPtr pPriv; if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) return NULL; if(!(pPriv = xcalloc(1, sizeof(R128PortPrivRec) + sizeof(DevUnion)))) { xfree(adapt); return NULL; } 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; pPriv->doubleBuffer = TRUE; pPriv->videoStatus = 0; pPriv->brightness = 0; pPriv->saturation = 16; pPriv->currentBuffer = 0; R128ECP(pScrn, pPriv); return adapt;}static XF86VideoAdaptorPtrR128SetupImageVideo(ScreenPtr pScreen){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; R128InfoPtr info = R128PTR(pScrn); R128PortPrivPtr pPriv; XF86VideoAdaptorPtr adapt; if(!(adapt = R128AllocAdaptor(pScrn))) return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask; adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; adapt->name = "ATI Rage128 Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = &DummyEncoding; adapt->nFormats = NUM_FORMATS; adapt->pFormats = Formats; adapt->nPorts = 1; adapt->nAttributes = NUM_ATTRIBUTES; adapt->pAttributes = Attributes; adapt->nImages = NUM_IMAGES; adapt->pImages = Images; adapt->PutVideo = NULL; adapt->PutStill = NULL; adapt->GetVideo = NULL; adapt->GetStill = NULL; adapt->StopVideo = R128StopVideo; adapt->SetPortAttribute = R128SetPortAttribute; adapt->GetPortAttribute = R128GetPortAttribute; adapt->QueryBestSize = R128QueryBestSize; adapt->PutImage = R128PutImage; adapt->QueryImageAttributes = R128QueryImageAttributes; info->adaptor = adapt; pPriv = (R128PortPrivPtr)(adapt->pPortPrivates[0].ptr); REGION_NULL(pScreen, &(pPriv->clip)); R128ResetVideo(pScrn); return adapt;}static voidR128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128PortPrivPtr pPriv = (R128PortPrivPtr)data; REGION_EMPTY(pScrn->pScreen, &pPriv->clip); if(cleanup) { if(pPriv->videoStatus & CLIENT_VIDEO_ON) { OUTREG(R128_OV0_SCALE_CNTL, 0); } if(pPriv->linear) { xf86FreeOffscreenLinear(pPriv->linear); pPriv->linear = NULL; } pPriv->videoStatus = 0; } else { if(pPriv->videoStatus & CLIENT_VIDEO_ON) { pPriv->videoStatus |= OFF_TIMER; pPriv->offTime = currentTime.milliseconds + OFF_DELAY; } }}static intR128SetPortAttribute( ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128PortPrivPtr pPriv = (R128PortPrivPtr)data; if(attribute == xvBrightness) { if((value < -64) || (value > 63)) return BadValue; pPriv->brightness = value; OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | (pPriv->saturation << 8) | (pPriv->saturation << 16)); } else if(attribute == xvSaturation) { if((value < 0) || (value > 31)) return BadValue; pPriv->saturation = value; OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | (pPriv->saturation << 8) | (pPriv->saturation << 16)); } else if(attribute == xvDoubleBuffer) { if((value < 0) || (value > 1)) return BadValue; pPriv->doubleBuffer = value; } else if(attribute == xvColorKey) { pPriv->colorKey = value; OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } else return BadMatch; return Success;}static intR128GetPortAttribute( ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data){ R128PortPrivPtr pPriv = (R128PortPrivPtr)data; if(attribute == xvBrightness) { *value = pPriv->brightness; } else if(attribute == xvSaturation) { *value = pPriv->saturation; } else if(attribute == xvDoubleBuffer) { *value = pPriv->doubleBuffer ? 1 : 0; } else if(attribute == xvColorKey) { *value = pPriv->colorKey; } else return BadMatch; return Success;}static voidR128QueryBestSize( ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, pointer data){ if(vid_w > (drw_w << 4)) drw_w = vid_w >> 4; if(vid_h > (drw_h << 4)) drw_h = vid_h >> 4; *p_w = drw_w; *p_h = drw_h;}/* * * R128DMA - abuse the texture blit ioctl to transfer rectangular blocks * * The block is split into 'passes' pieces of 'hpass' lines which fit entirely * into an indirect buffer * */static BoolR128DMA( R128InfoPtr info, unsigned char *src, unsigned char *dst, int srcPitch, int dstPitch, int h, int w){#ifdef XF86DRI#define BUFSIZE (R128_BUFFER_SIZE - R128_HOSTDATA_BLIT_OFFSET)#define MAXPASSES (MAXHEIGHT/(BUFSIZE/(MAXWIDTH*2))+1) unsigned char *buf; int err=-1, i, idx, offset, hpass, passes, srcpassbytes, dstpassbytes; int sizes[MAXPASSES], list[MAXPASSES]; drmDMAReq req; drmR128Blit blit; /* Verify conditions and bail out as early as possible */ if (!info->directRenderingEnabled || !info->DMAForXv) return FALSE; if ((hpass = min(h,(BUFSIZE/w))) == 0) return FALSE; if ((passes = (h+hpass-1)/hpass) > MAXPASSES) return FALSE; /* Request indirect buffers */ srcpassbytes = w*hpass; req.context = info->drmCtx; req.send_count = 0; req.send_list = NULL; req.send_sizes = NULL; req.flags = DRM_DMA_LARGER_OK; req.request_count = passes; req.request_size = srcpassbytes + R128_HOSTDATA_BLIT_OFFSET; req.request_list = &list[0]; req.request_sizes = &sizes[0]; req.granted_count = 0; if (drmDMA(info->drmFD, &req)) return FALSE; if (req.granted_count < passes) { drmFreeBufs(info->drmFD, req.granted_count, req.request_list); return FALSE; } /* Copy parts of the block into buffers and fire them */ dstpassbytes = hpass*dstPitch; dstPitch /= 8; for (i=0, offset=dst-info->FB; i<passes; i++, offset+=dstpassbytes) { if (i == (passes-1) && (h % hpass) != 0) { hpass = h % hpass; srcpassbytes = w*hpass; } idx = req.request_list[i]; buf = (unsigned char *) info->buffers->list[idx].address + R128_HOSTDATA_BLIT_OFFSET; if (srcPitch == w) { memcpy(buf, src, srcpassbytes); src += srcpassbytes; } else { int count = hpass; while(count--) { memcpy(buf, src, w); src += srcPitch; buf += w; } } blit.idx = idx; blit.offset = offset; blit.pitch = dstPitch; blit.format = (R128_DATATYPE_CI8 >> 16); blit.x = (offset % 32); blit.y = 0; blit.width = w; blit.height = hpass; if ((err = drmCommandWrite(info->drmFD, DRM_R128_BLIT, &blit, sizeof(drmR128Blit))) < 0) break; } drmFreeBufs(info->drmFD, req.granted_count, req.request_list); return (err==0) ? TRUE : FALSE;#else /* This is to avoid cluttering the rest of the code with '#ifdef XF86DRI' */ return FALSE;#endif /* XF86DRI */}static voidR128CopyData422( R128InfoPtr info, unsigned char *src, unsigned char *dst, int srcPitch, int dstPitch, int h, int w){ w <<= 1; /* Attempt data transfer with DMA and fall back to memcpy */ if (!R128DMA(info, src, dst, srcPitch, dstPitch, h, w)) { while(h--) { memcpy(dst, src, w); src += srcPitch; dst += dstPitch; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -