r128_video.c revision c582b7e3
1c582b7e3Smrg 2c582b7e3Smrg#ifdef HAVE_CONFIG_H 3c582b7e3Smrg#include "config.h" 4c582b7e3Smrg#endif 5c582b7e3Smrg 6c582b7e3Smrg#include <string.h> 7c582b7e3Smrg 8c582b7e3Smrg#include "r128.h" 9c582b7e3Smrg#include "r128_reg.h" 10c582b7e3Smrg 11c582b7e3Smrg#ifdef XF86DRI 12c582b7e3Smrg#include "r128_common.h" 13c582b7e3Smrg#include "r128_sarea.h" 14c582b7e3Smrg#endif 15c582b7e3Smrg 16c582b7e3Smrg#include "xf86.h" 17c582b7e3Smrg#include "dixstruct.h" 18c582b7e3Smrg 19c582b7e3Smrg#include <X11/extensions/Xv.h> 20c582b7e3Smrg#include "fourcc.h" 21c582b7e3Smrg 22c582b7e3Smrg#define OFF_DELAY 250 /* milliseconds */ 23c582b7e3Smrg#define FREE_DELAY 15000 24c582b7e3Smrg 25c582b7e3Smrg#define OFF_TIMER 0x01 26c582b7e3Smrg#define FREE_TIMER 0x02 27c582b7e3Smrg#define CLIENT_VIDEO_ON 0x04 28c582b7e3Smrg 29c582b7e3Smrg#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 30c582b7e3Smrg 31c582b7e3Smrgstatic XF86VideoAdaptorPtr R128SetupImageVideo(ScreenPtr); 32c582b7e3Smrgstatic int R128SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 33c582b7e3Smrgstatic int R128GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); 34c582b7e3Smrgstatic void R128StopVideo(ScrnInfoPtr, pointer, Bool); 35c582b7e3Smrgstatic void R128QueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, 36c582b7e3Smrg unsigned int *, unsigned int *, pointer); 37c582b7e3Smrgstatic int R128PutImage(ScrnInfoPtr, short, short, short, short, short, 38c582b7e3Smrg short, short, short, int, unsigned char*, short, 39c582b7e3Smrg short, Bool, RegionPtr, pointer, DrawablePtr); 40c582b7e3Smrgstatic int R128QueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 41c582b7e3Smrg unsigned short *, int *, int *); 42c582b7e3Smrg 43c582b7e3Smrg 44c582b7e3Smrgstatic void R128ResetVideo(ScrnInfoPtr); 45c582b7e3Smrg 46c582b7e3Smrgstatic void R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now); 47c582b7e3Smrg 48c582b7e3Smrg 49c582b7e3Smrg#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 50c582b7e3Smrg 51c582b7e3Smrgstatic Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; 52c582b7e3Smrg 53c582b7e3Smrg 54c582b7e3Smrgtypedef struct { 55c582b7e3Smrg int brightness; 56c582b7e3Smrg int saturation; 57c582b7e3Smrg Bool doubleBuffer; 58c582b7e3Smrg unsigned char currentBuffer; 59c582b7e3Smrg FBLinearPtr linear; 60c582b7e3Smrg RegionRec clip; 61c582b7e3Smrg CARD32 colorKey; 62c582b7e3Smrg CARD32 videoStatus; 63c582b7e3Smrg Time offTime; 64c582b7e3Smrg Time freeTime; 65c582b7e3Smrg int ecp_div; 66c582b7e3Smrg} R128PortPrivRec, *R128PortPrivPtr; 67c582b7e3Smrg 68c582b7e3Smrgstatic void R128ECP(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv) 69c582b7e3Smrg{ 70c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 71c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 72c582b7e3Smrg int dot_clock = info->ModeReg.dot_clock_freq; 73c582b7e3Smrg 74c582b7e3Smrg if (dot_clock < 12500) pPriv->ecp_div = 0; 75c582b7e3Smrg else if (dot_clock < 25000) pPriv->ecp_div = 1; 76c582b7e3Smrg else pPriv->ecp_div = 2; 77c582b7e3Smrg 78c582b7e3Smrg OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, pPriv->ecp_div<<8, ~R128_ECP_DIV_MASK); 79c582b7e3Smrg} 80c582b7e3Smrg 81c582b7e3Smrgvoid R128InitVideo(ScreenPtr pScreen) 82c582b7e3Smrg{ 83c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 84c582b7e3Smrg XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 85c582b7e3Smrg XF86VideoAdaptorPtr newAdaptor = NULL; 86c582b7e3Smrg int num_adaptors; 87c582b7e3Smrg 88c582b7e3Smrg newAdaptor = R128SetupImageVideo(pScreen); 89c582b7e3Smrg 90c582b7e3Smrg num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 91c582b7e3Smrg 92c582b7e3Smrg if(newAdaptor) { 93c582b7e3Smrg if(!num_adaptors) { 94c582b7e3Smrg num_adaptors = 1; 95c582b7e3Smrg adaptors = &newAdaptor; 96c582b7e3Smrg } else { 97c582b7e3Smrg newAdaptors = /* need to free this someplace */ 98c582b7e3Smrg xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); 99c582b7e3Smrg if(newAdaptors) { 100c582b7e3Smrg memcpy(newAdaptors, adaptors, num_adaptors * 101c582b7e3Smrg sizeof(XF86VideoAdaptorPtr)); 102c582b7e3Smrg newAdaptors[num_adaptors] = newAdaptor; 103c582b7e3Smrg adaptors = newAdaptors; 104c582b7e3Smrg num_adaptors++; 105c582b7e3Smrg } 106c582b7e3Smrg } 107c582b7e3Smrg } 108c582b7e3Smrg 109c582b7e3Smrg if(num_adaptors) 110c582b7e3Smrg xf86XVScreenInit(pScreen, adaptors, num_adaptors); 111c582b7e3Smrg 112c582b7e3Smrg if(newAdaptors) 113c582b7e3Smrg xfree(newAdaptors); 114c582b7e3Smrg} 115c582b7e3Smrg 116c582b7e3Smrg#define MAXWIDTH 2048 117c582b7e3Smrg#define MAXHEIGHT 2048 118c582b7e3Smrg 119c582b7e3Smrg/* client libraries expect an encoding */ 120c582b7e3Smrgstatic XF86VideoEncodingRec DummyEncoding = 121c582b7e3Smrg{ 122c582b7e3Smrg 0, 123c582b7e3Smrg "XV_IMAGE", 124c582b7e3Smrg MAXWIDTH, MAXHEIGHT, 125c582b7e3Smrg {1, 1} 126c582b7e3Smrg}; 127c582b7e3Smrg 128c582b7e3Smrg#define NUM_FORMATS 12 129c582b7e3Smrg 130c582b7e3Smrgstatic XF86VideoFormatRec Formats[NUM_FORMATS] = 131c582b7e3Smrg{ 132c582b7e3Smrg {8, TrueColor}, {8, DirectColor}, {8, PseudoColor}, 133c582b7e3Smrg {8, GrayScale}, {8, StaticGray}, {8, StaticColor}, 134c582b7e3Smrg {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, 135c582b7e3Smrg {15, DirectColor}, {16, DirectColor}, {24, DirectColor} 136c582b7e3Smrg}; 137c582b7e3Smrg 138c582b7e3Smrg 139c582b7e3Smrg#define NUM_ATTRIBUTES 4 140c582b7e3Smrg 141c582b7e3Smrgstatic XF86AttributeRec Attributes[NUM_ATTRIBUTES] = 142c582b7e3Smrg{ 143c582b7e3Smrg {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 144c582b7e3Smrg {XvSettable | XvGettable, -64, 63, "XV_BRIGHTNESS"}, 145c582b7e3Smrg {XvSettable | XvGettable, 0, 31, "XV_SATURATION"}, 146c582b7e3Smrg {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"} 147c582b7e3Smrg}; 148c582b7e3Smrg 149c582b7e3Smrg#define NUM_IMAGES 4 150c582b7e3Smrg 151c582b7e3Smrgstatic XF86ImageRec Images[NUM_IMAGES] = 152c582b7e3Smrg{ 153c582b7e3Smrg XVIMAGE_YUY2, 154c582b7e3Smrg XVIMAGE_UYVY, 155c582b7e3Smrg XVIMAGE_YV12, 156c582b7e3Smrg XVIMAGE_I420 157c582b7e3Smrg}; 158c582b7e3Smrg 159c582b7e3Smrgstatic void 160c582b7e3SmrgR128ResetVideo(ScrnInfoPtr pScrn) 161c582b7e3Smrg{ 162c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 163c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 164c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 165c582b7e3Smrg 166c582b7e3Smrg 167c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x80000000); 168c582b7e3Smrg OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0); 169c582b7e3Smrg OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0); /* maybe */ 170c582b7e3Smrg OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f); 171c582b7e3Smrg OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | 172c582b7e3Smrg (pPriv->saturation << 8) | 173c582b7e3Smrg (pPriv->saturation << 16)); 174c582b7e3Smrg OUTREG(R128_OV0_GRAPHICS_KEY_MSK, (1 << pScrn->depth) - 1); 175c582b7e3Smrg OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey); 176c582b7e3Smrg OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE); 177c582b7e3Smrg OUTREG(R128_OV0_TEST, 0); 178c582b7e3Smrg} 179c582b7e3Smrg 180c582b7e3Smrg 181c582b7e3Smrgstatic XF86VideoAdaptorPtr 182c582b7e3SmrgR128AllocAdaptor(ScrnInfoPtr pScrn) 183c582b7e3Smrg{ 184c582b7e3Smrg XF86VideoAdaptorPtr adapt; 185c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 186c582b7e3Smrg R128PortPrivPtr pPriv; 187c582b7e3Smrg 188c582b7e3Smrg if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) 189c582b7e3Smrg return NULL; 190c582b7e3Smrg 191c582b7e3Smrg if(!(pPriv = xcalloc(1, sizeof(R128PortPrivRec) + sizeof(DevUnion)))) 192c582b7e3Smrg { 193c582b7e3Smrg xfree(adapt); 194c582b7e3Smrg return NULL; 195c582b7e3Smrg } 196c582b7e3Smrg 197c582b7e3Smrg adapt->pPortPrivates = (DevUnion*)(&pPriv[1]); 198c582b7e3Smrg adapt->pPortPrivates[0].ptr = (pointer)pPriv; 199c582b7e3Smrg 200c582b7e3Smrg xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 201c582b7e3Smrg xvSaturation = MAKE_ATOM("XV_SATURATION"); 202c582b7e3Smrg xvColorKey = MAKE_ATOM("XV_COLORKEY"); 203c582b7e3Smrg xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 204c582b7e3Smrg 205c582b7e3Smrg pPriv->colorKey = info->videoKey; 206c582b7e3Smrg pPriv->doubleBuffer = TRUE; 207c582b7e3Smrg pPriv->videoStatus = 0; 208c582b7e3Smrg pPriv->brightness = 0; 209c582b7e3Smrg pPriv->saturation = 16; 210c582b7e3Smrg pPriv->currentBuffer = 0; 211c582b7e3Smrg R128ECP(pScrn, pPriv); 212c582b7e3Smrg 213c582b7e3Smrg return adapt; 214c582b7e3Smrg} 215c582b7e3Smrg 216c582b7e3Smrgstatic XF86VideoAdaptorPtr 217c582b7e3SmrgR128SetupImageVideo(ScreenPtr pScreen) 218c582b7e3Smrg{ 219c582b7e3Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 220c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 221c582b7e3Smrg R128PortPrivPtr pPriv; 222c582b7e3Smrg XF86VideoAdaptorPtr adapt; 223c582b7e3Smrg 224c582b7e3Smrg if(!(adapt = R128AllocAdaptor(pScrn))) 225c582b7e3Smrg return NULL; 226c582b7e3Smrg 227c582b7e3Smrg adapt->type = XvWindowMask | XvInputMask | XvImageMask; 228c582b7e3Smrg adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 229c582b7e3Smrg adapt->name = "ATI Rage128 Video Overlay"; 230c582b7e3Smrg adapt->nEncodings = 1; 231c582b7e3Smrg adapt->pEncodings = &DummyEncoding; 232c582b7e3Smrg adapt->nFormats = NUM_FORMATS; 233c582b7e3Smrg adapt->pFormats = Formats; 234c582b7e3Smrg adapt->nPorts = 1; 235c582b7e3Smrg adapt->nAttributes = NUM_ATTRIBUTES; 236c582b7e3Smrg adapt->pAttributes = Attributes; 237c582b7e3Smrg adapt->nImages = NUM_IMAGES; 238c582b7e3Smrg adapt->pImages = Images; 239c582b7e3Smrg adapt->PutVideo = NULL; 240c582b7e3Smrg adapt->PutStill = NULL; 241c582b7e3Smrg adapt->GetVideo = NULL; 242c582b7e3Smrg adapt->GetStill = NULL; 243c582b7e3Smrg adapt->StopVideo = R128StopVideo; 244c582b7e3Smrg adapt->SetPortAttribute = R128SetPortAttribute; 245c582b7e3Smrg adapt->GetPortAttribute = R128GetPortAttribute; 246c582b7e3Smrg adapt->QueryBestSize = R128QueryBestSize; 247c582b7e3Smrg adapt->PutImage = R128PutImage; 248c582b7e3Smrg adapt->QueryImageAttributes = R128QueryImageAttributes; 249c582b7e3Smrg 250c582b7e3Smrg info->adaptor = adapt; 251c582b7e3Smrg 252c582b7e3Smrg pPriv = (R128PortPrivPtr)(adapt->pPortPrivates[0].ptr); 253c582b7e3Smrg REGION_NULL(pScreen, &(pPriv->clip)); 254c582b7e3Smrg 255c582b7e3Smrg R128ResetVideo(pScrn); 256c582b7e3Smrg 257c582b7e3Smrg return adapt; 258c582b7e3Smrg} 259c582b7e3Smrg 260c582b7e3Smrgstatic void 261c582b7e3SmrgR128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup) 262c582b7e3Smrg{ 263c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 264c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 265c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 266c582b7e3Smrg 267c582b7e3Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 268c582b7e3Smrg 269c582b7e3Smrg if(cleanup) { 270c582b7e3Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 271c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0); 272c582b7e3Smrg } 273c582b7e3Smrg if(pPriv->linear) { 274c582b7e3Smrg xf86FreeOffscreenLinear(pPriv->linear); 275c582b7e3Smrg pPriv->linear = NULL; 276c582b7e3Smrg } 277c582b7e3Smrg pPriv->videoStatus = 0; 278c582b7e3Smrg } else { 279c582b7e3Smrg if(pPriv->videoStatus & CLIENT_VIDEO_ON) { 280c582b7e3Smrg pPriv->videoStatus |= OFF_TIMER; 281c582b7e3Smrg pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 282c582b7e3Smrg } 283c582b7e3Smrg } 284c582b7e3Smrg} 285c582b7e3Smrg 286c582b7e3Smrgstatic int 287c582b7e3SmrgR128SetPortAttribute( 288c582b7e3Smrg ScrnInfoPtr pScrn, 289c582b7e3Smrg Atom attribute, 290c582b7e3Smrg INT32 value, 291c582b7e3Smrg pointer data 292c582b7e3Smrg){ 293c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 294c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 295c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 296c582b7e3Smrg 297c582b7e3Smrg if(attribute == xvBrightness) { 298c582b7e3Smrg if((value < -64) || (value > 63)) 299c582b7e3Smrg return BadValue; 300c582b7e3Smrg pPriv->brightness = value; 301c582b7e3Smrg 302c582b7e3Smrg OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | 303c582b7e3Smrg (pPriv->saturation << 8) | 304c582b7e3Smrg (pPriv->saturation << 16)); 305c582b7e3Smrg } else 306c582b7e3Smrg if(attribute == xvSaturation) { 307c582b7e3Smrg if((value < 0) || (value > 31)) 308c582b7e3Smrg return BadValue; 309c582b7e3Smrg pPriv->saturation = value; 310c582b7e3Smrg 311c582b7e3Smrg OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) | 312c582b7e3Smrg (pPriv->saturation << 8) | 313c582b7e3Smrg (pPriv->saturation << 16)); 314c582b7e3Smrg } else 315c582b7e3Smrg if(attribute == xvDoubleBuffer) { 316c582b7e3Smrg if((value < 0) || (value > 1)) 317c582b7e3Smrg return BadValue; 318c582b7e3Smrg pPriv->doubleBuffer = value; 319c582b7e3Smrg } else 320c582b7e3Smrg if(attribute == xvColorKey) { 321c582b7e3Smrg pPriv->colorKey = value; 322c582b7e3Smrg OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey); 323c582b7e3Smrg 324c582b7e3Smrg REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 325c582b7e3Smrg } else return BadMatch; 326c582b7e3Smrg 327c582b7e3Smrg return Success; 328c582b7e3Smrg} 329c582b7e3Smrg 330c582b7e3Smrgstatic int 331c582b7e3SmrgR128GetPortAttribute( 332c582b7e3Smrg ScrnInfoPtr pScrn, 333c582b7e3Smrg Atom attribute, 334c582b7e3Smrg INT32 *value, 335c582b7e3Smrg pointer data 336c582b7e3Smrg){ 337c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 338c582b7e3Smrg 339c582b7e3Smrg if(attribute == xvBrightness) { 340c582b7e3Smrg *value = pPriv->brightness; 341c582b7e3Smrg } else 342c582b7e3Smrg if(attribute == xvSaturation) { 343c582b7e3Smrg *value = pPriv->saturation; 344c582b7e3Smrg } else 345c582b7e3Smrg if(attribute == xvDoubleBuffer) { 346c582b7e3Smrg *value = pPriv->doubleBuffer ? 1 : 0; 347c582b7e3Smrg } else 348c582b7e3Smrg if(attribute == xvColorKey) { 349c582b7e3Smrg *value = pPriv->colorKey; 350c582b7e3Smrg } else return BadMatch; 351c582b7e3Smrg 352c582b7e3Smrg return Success; 353c582b7e3Smrg} 354c582b7e3Smrg 355c582b7e3Smrg 356c582b7e3Smrgstatic void 357c582b7e3SmrgR128QueryBestSize( 358c582b7e3Smrg ScrnInfoPtr pScrn, 359c582b7e3Smrg Bool motion, 360c582b7e3Smrg short vid_w, short vid_h, 361c582b7e3Smrg short drw_w, short drw_h, 362c582b7e3Smrg unsigned int *p_w, unsigned int *p_h, 363c582b7e3Smrg pointer data 364c582b7e3Smrg){ 365c582b7e3Smrg if(vid_w > (drw_w << 4)) 366c582b7e3Smrg drw_w = vid_w >> 4; 367c582b7e3Smrg if(vid_h > (drw_h << 4)) 368c582b7e3Smrg drw_h = vid_h >> 4; 369c582b7e3Smrg 370c582b7e3Smrg *p_w = drw_w; 371c582b7e3Smrg *p_h = drw_h; 372c582b7e3Smrg} 373c582b7e3Smrg 374c582b7e3Smrg 375c582b7e3Smrg/* 376c582b7e3Smrg * 377c582b7e3Smrg * R128DMA - abuse the texture blit ioctl to transfer rectangular blocks 378c582b7e3Smrg * 379c582b7e3Smrg * The block is split into 'passes' pieces of 'hpass' lines which fit entirely 380c582b7e3Smrg * into an indirect buffer 381c582b7e3Smrg * 382c582b7e3Smrg */ 383c582b7e3Smrg 384c582b7e3Smrgstatic Bool 385c582b7e3SmrgR128DMA( 386c582b7e3Smrg R128InfoPtr info, 387c582b7e3Smrg unsigned char *src, 388c582b7e3Smrg unsigned char *dst, 389c582b7e3Smrg int srcPitch, 390c582b7e3Smrg int dstPitch, 391c582b7e3Smrg int h, 392c582b7e3Smrg int w 393c582b7e3Smrg){ 394c582b7e3Smrg 395c582b7e3Smrg#ifdef XF86DRI 396c582b7e3Smrg 397c582b7e3Smrg#define BUFSIZE (R128_BUFFER_SIZE - R128_HOSTDATA_BLIT_OFFSET) 398c582b7e3Smrg#define MAXPASSES (MAXHEIGHT/(BUFSIZE/(MAXWIDTH*2))+1) 399c582b7e3Smrg 400c582b7e3Smrg unsigned char *fb = (CARD8*)info->FB; 401c582b7e3Smrg unsigned char *buf; 402c582b7e3Smrg int err=-1, i, idx, offset, hpass, passes, srcpassbytes, dstpassbytes; 403c582b7e3Smrg int sizes[MAXPASSES], list[MAXPASSES]; 404c582b7e3Smrg drmDMAReq req; 405c582b7e3Smrg drmR128Blit blit; 406c582b7e3Smrg 407c582b7e3Smrg /* Verify conditions and bail out as early as possible */ 408c582b7e3Smrg if (!info->directRenderingEnabled || !info->DMAForXv) 409c582b7e3Smrg return FALSE; 410c582b7e3Smrg 411c582b7e3Smrg if ((hpass = min(h,(BUFSIZE/w))) == 0) 412c582b7e3Smrg return FALSE; 413c582b7e3Smrg 414c582b7e3Smrg if ((passes = (h+hpass-1)/hpass) > MAXPASSES) 415c582b7e3Smrg return FALSE; 416c582b7e3Smrg 417c582b7e3Smrg /* Request indirect buffers */ 418c582b7e3Smrg srcpassbytes = w*hpass; 419c582b7e3Smrg 420c582b7e3Smrg req.context = info->drmCtx; 421c582b7e3Smrg req.send_count = 0; 422c582b7e3Smrg req.send_list = NULL; 423c582b7e3Smrg req.send_sizes = NULL; 424c582b7e3Smrg req.flags = DRM_DMA_LARGER_OK; 425c582b7e3Smrg req.request_count = passes; 426c582b7e3Smrg req.request_size = srcpassbytes + R128_HOSTDATA_BLIT_OFFSET; 427c582b7e3Smrg req.request_list = &list[0]; 428c582b7e3Smrg req.request_sizes = &sizes[0]; 429c582b7e3Smrg req.granted_count = 0; 430c582b7e3Smrg 431c582b7e3Smrg if (drmDMA(info->drmFD, &req)) 432c582b7e3Smrg return FALSE; 433c582b7e3Smrg 434c582b7e3Smrg if (req.granted_count < passes) { 435c582b7e3Smrg drmFreeBufs(info->drmFD, req.granted_count, req.request_list); 436c582b7e3Smrg return FALSE; 437c582b7e3Smrg } 438c582b7e3Smrg 439c582b7e3Smrg /* Copy parts of the block into buffers and fire them */ 440c582b7e3Smrg dstpassbytes = hpass*dstPitch; 441c582b7e3Smrg dstPitch /= 8; 442c582b7e3Smrg 443c582b7e3Smrg for (i=0, offset=dst-fb; i<passes; i++, offset+=dstpassbytes) { 444c582b7e3Smrg if (i == (passes-1) && (h % hpass) != 0) { 445c582b7e3Smrg hpass = h % hpass; 446c582b7e3Smrg srcpassbytes = w*hpass; 447c582b7e3Smrg } 448c582b7e3Smrg 449c582b7e3Smrg idx = req.request_list[i]; 450c582b7e3Smrg buf = (unsigned char *) info->buffers->list[idx].address + R128_HOSTDATA_BLIT_OFFSET; 451c582b7e3Smrg 452c582b7e3Smrg if (srcPitch == w) { 453c582b7e3Smrg memcpy(buf, src, srcpassbytes); 454c582b7e3Smrg src += srcpassbytes; 455c582b7e3Smrg } else { 456c582b7e3Smrg int count = hpass; 457c582b7e3Smrg while(count--) { 458c582b7e3Smrg memcpy(buf, src, w); 459c582b7e3Smrg src += srcPitch; 460c582b7e3Smrg buf += w; 461c582b7e3Smrg } 462c582b7e3Smrg } 463c582b7e3Smrg 464c582b7e3Smrg blit.idx = idx; 465c582b7e3Smrg blit.offset = offset; 466c582b7e3Smrg blit.pitch = dstPitch; 467c582b7e3Smrg blit.format = (R128_DATATYPE_CI8 >> 16); 468c582b7e3Smrg blit.x = (offset % 32); 469c582b7e3Smrg blit.y = 0; 470c582b7e3Smrg blit.width = w; 471c582b7e3Smrg blit.height = hpass; 472c582b7e3Smrg 473c582b7e3Smrg if ((err = drmCommandWrite(info->drmFD, DRM_R128_BLIT, 474c582b7e3Smrg &blit, sizeof(drmR128Blit))) < 0) 475c582b7e3Smrg break; 476c582b7e3Smrg } 477c582b7e3Smrg 478c582b7e3Smrg drmFreeBufs(info->drmFD, req.granted_count, req.request_list); 479c582b7e3Smrg 480c582b7e3Smrg return (err==0) ? TRUE : FALSE; 481c582b7e3Smrg 482c582b7e3Smrg#else 483c582b7e3Smrg 484c582b7e3Smrg /* This is to avoid cluttering the rest of the code with '#ifdef XF86DRI' */ 485c582b7e3Smrg return FALSE; 486c582b7e3Smrg 487c582b7e3Smrg#endif /* XF86DRI */ 488c582b7e3Smrg 489c582b7e3Smrg} 490c582b7e3Smrg 491c582b7e3Smrg 492c582b7e3Smrgstatic void 493c582b7e3SmrgR128CopyData422( 494c582b7e3Smrg R128InfoPtr info, 495c582b7e3Smrg unsigned char *src, 496c582b7e3Smrg unsigned char *dst, 497c582b7e3Smrg int srcPitch, 498c582b7e3Smrg int dstPitch, 499c582b7e3Smrg int h, 500c582b7e3Smrg int w 501c582b7e3Smrg){ 502c582b7e3Smrg w <<= 1; 503c582b7e3Smrg 504c582b7e3Smrg /* Attempt data transfer with DMA and fall back to memcpy */ 505c582b7e3Smrg 506c582b7e3Smrg if (!R128DMA(info, src, dst, srcPitch, dstPitch, h, w)) { 507c582b7e3Smrg while(h--) { 508c582b7e3Smrg memcpy(dst, src, w); 509c582b7e3Smrg src += srcPitch; 510c582b7e3Smrg dst += dstPitch; 511c582b7e3Smrg } 512c582b7e3Smrg } 513c582b7e3Smrg} 514c582b7e3Smrg 515c582b7e3Smrgstatic void 516c582b7e3SmrgR128CopyData420( 517c582b7e3Smrg R128InfoPtr info, 518c582b7e3Smrg unsigned char *src1, 519c582b7e3Smrg unsigned char *src2, 520c582b7e3Smrg unsigned char *src3, 521c582b7e3Smrg unsigned char *dst1, 522c582b7e3Smrg unsigned char *dst2, 523c582b7e3Smrg unsigned char *dst3, 524c582b7e3Smrg int srcPitch, 525c582b7e3Smrg int srcPitch2, 526c582b7e3Smrg int dstPitch, 527c582b7e3Smrg int h, 528c582b7e3Smrg int w 529c582b7e3Smrg){ 530c582b7e3Smrg int count; 531c582b7e3Smrg 532c582b7e3Smrg /* Attempt data transfer with DMA and fall back to memcpy */ 533c582b7e3Smrg 534c582b7e3Smrg if (!R128DMA(info, src1, dst1, srcPitch, dstPitch, h, w)) { 535c582b7e3Smrg count = h; 536c582b7e3Smrg while(count--) { 537c582b7e3Smrg memcpy(dst1, src1, w); 538c582b7e3Smrg src1 += srcPitch; 539c582b7e3Smrg dst1 += dstPitch; 540c582b7e3Smrg } 541c582b7e3Smrg } 542c582b7e3Smrg 543c582b7e3Smrg w >>= 1; 544c582b7e3Smrg h >>= 1; 545c582b7e3Smrg dstPitch >>= 1; 546c582b7e3Smrg 547c582b7e3Smrg if (!R128DMA(info, src2, dst2, srcPitch2, dstPitch, h, w)) { 548c582b7e3Smrg count = h; 549c582b7e3Smrg while(count--) { 550c582b7e3Smrg memcpy(dst2, src2, w); 551c582b7e3Smrg src2 += srcPitch2; 552c582b7e3Smrg dst2 += dstPitch; 553c582b7e3Smrg } 554c582b7e3Smrg } 555c582b7e3Smrg 556c582b7e3Smrg if (!R128DMA(info, src3, dst3, srcPitch2, dstPitch, h, w)) { 557c582b7e3Smrg count = h; 558c582b7e3Smrg while(count--) { 559c582b7e3Smrg memcpy(dst3, src3, w); 560c582b7e3Smrg src3 += srcPitch2; 561c582b7e3Smrg dst3 += dstPitch; 562c582b7e3Smrg } 563c582b7e3Smrg } 564c582b7e3Smrg} 565c582b7e3Smrg 566c582b7e3Smrg 567c582b7e3Smrgstatic FBLinearPtr 568c582b7e3SmrgR128AllocateMemory( 569c582b7e3Smrg ScrnInfoPtr pScrn, 570c582b7e3Smrg FBLinearPtr linear, 571c582b7e3Smrg int size 572c582b7e3Smrg){ 573c582b7e3Smrg ScreenPtr pScreen; 574c582b7e3Smrg FBLinearPtr new_linear; 575c582b7e3Smrg 576c582b7e3Smrg if(linear) { 577c582b7e3Smrg if(linear->size >= size) 578c582b7e3Smrg return linear; 579c582b7e3Smrg 580c582b7e3Smrg if(xf86ResizeOffscreenLinear(linear, size)) 581c582b7e3Smrg return linear; 582c582b7e3Smrg 583c582b7e3Smrg xf86FreeOffscreenLinear(linear); 584c582b7e3Smrg } 585c582b7e3Smrg 586c582b7e3Smrg pScreen = screenInfo.screens[pScrn->scrnIndex]; 587c582b7e3Smrg 588c582b7e3Smrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 589c582b7e3Smrg NULL, NULL, NULL); 590c582b7e3Smrg 591c582b7e3Smrg if(!new_linear) { 592c582b7e3Smrg int max_size; 593c582b7e3Smrg 594c582b7e3Smrg xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, 595c582b7e3Smrg PRIORITY_EXTREME); 596c582b7e3Smrg 597c582b7e3Smrg if(max_size < size) 598c582b7e3Smrg return NULL; 599c582b7e3Smrg 600c582b7e3Smrg xf86PurgeUnlockedOffscreenAreas(pScreen); 601c582b7e3Smrg new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, 602c582b7e3Smrg NULL, NULL, NULL); 603c582b7e3Smrg } 604c582b7e3Smrg 605c582b7e3Smrg return new_linear; 606c582b7e3Smrg} 607c582b7e3Smrg 608c582b7e3Smrgstatic void 609c582b7e3SmrgR128DisplayVideo422( 610c582b7e3Smrg ScrnInfoPtr pScrn, 611c582b7e3Smrg int id, 612c582b7e3Smrg int offset, 613c582b7e3Smrg short width, short height, 614c582b7e3Smrg int pitch, 615c582b7e3Smrg int left, int right, int top, 616c582b7e3Smrg BoxPtr dstBox, 617c582b7e3Smrg short src_w, short src_h, 618c582b7e3Smrg short drw_w, short drw_h 619c582b7e3Smrg){ 620c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 621c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 622c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 623c582b7e3Smrg int v_inc, h_inc, step_by, tmp; 624c582b7e3Smrg int p1_h_accum_init, p23_h_accum_init; 625c582b7e3Smrg int p1_v_accum_init; 626c582b7e3Smrg 627c582b7e3Smrg R128ECP(pScrn, pPriv); 628c582b7e3Smrg 629c582b7e3Smrg v_inc = (src_h << 20) / drw_h; 630c582b7e3Smrg h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; 631c582b7e3Smrg step_by = 1; 632c582b7e3Smrg 633c582b7e3Smrg while(h_inc >= (2 << 12)) { 634c582b7e3Smrg step_by++; 635c582b7e3Smrg h_inc >>= 1; 636c582b7e3Smrg } 637c582b7e3Smrg 638c582b7e3Smrg /* keep everything in 16.16 */ 639c582b7e3Smrg 640c582b7e3Smrg offset += ((left >> 16) & ~7) << 1; 641c582b7e3Smrg 642c582b7e3Smrg tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); 643c582b7e3Smrg p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 644c582b7e3Smrg ((tmp << 12) & 0xf0000000); 645c582b7e3Smrg 646c582b7e3Smrg tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); 647c582b7e3Smrg p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 648c582b7e3Smrg ((tmp << 12) & 0x70000000); 649c582b7e3Smrg 650c582b7e3Smrg tmp = (top & 0x0000ffff) + 0x00018000; 651c582b7e3Smrg p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; 652c582b7e3Smrg 653c582b7e3Smrg left = (left >> 16) & 7; 654c582b7e3Smrg 655c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 1); 656c582b7e3Smrg while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); 657c582b7e3Smrg 658c582b7e3Smrg OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); 659c582b7e3Smrg OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); 660c582b7e3Smrg OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); 661c582b7e3Smrg OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); 662c582b7e3Smrg OUTREG(R128_OV0_V_INC, v_inc); 663c582b7e3Smrg OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); 664c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); 665c582b7e3Smrg OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); 666c582b7e3Smrg left >>= 1; width >>= 1; 667c582b7e3Smrg OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16)); 668c582b7e3Smrg OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16)); 669c582b7e3Smrg OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset & 0xfffffff0); 670c582b7e3Smrg OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 671c582b7e3Smrg OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0); 672c582b7e3Smrg OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 673c582b7e3Smrg OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 674c582b7e3Smrg 675c582b7e3Smrg if(id == FOURCC_UYVY) 676c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8C03); 677c582b7e3Smrg else 678c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03); 679c582b7e3Smrg 680c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 0); 681c582b7e3Smrg} 682c582b7e3Smrg 683c582b7e3Smrgstatic void 684c582b7e3SmrgR128DisplayVideo420( 685c582b7e3Smrg ScrnInfoPtr pScrn, 686c582b7e3Smrg short width, short height, 687c582b7e3Smrg int pitch, 688c582b7e3Smrg int offset1, int offset2, int offset3, 689c582b7e3Smrg int left, int right, int top, 690c582b7e3Smrg BoxPtr dstBox, 691c582b7e3Smrg short src_w, short src_h, 692c582b7e3Smrg short drw_w, short drw_h 693c582b7e3Smrg){ 694c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 695c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 696c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 697c582b7e3Smrg int v_inc, h_inc, step_by, tmp, leftUV; 698c582b7e3Smrg int p1_h_accum_init, p23_h_accum_init; 699c582b7e3Smrg int p1_v_accum_init, p23_v_accum_init; 700c582b7e3Smrg 701c582b7e3Smrg v_inc = (src_h << 20) / drw_h; 702c582b7e3Smrg h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; 703c582b7e3Smrg step_by = 1; 704c582b7e3Smrg 705c582b7e3Smrg while(h_inc >= (2 << 12)) { 706c582b7e3Smrg step_by++; 707c582b7e3Smrg h_inc >>= 1; 708c582b7e3Smrg } 709c582b7e3Smrg 710c582b7e3Smrg /* keep everything in 16.16 */ 711c582b7e3Smrg 712c582b7e3Smrg offset1 += (left >> 16) & ~15; 713c582b7e3Smrg offset2 += (left >> 17) & ~15; 714c582b7e3Smrg offset3 += (left >> 17) & ~15; 715c582b7e3Smrg 716c582b7e3Smrg tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); 717c582b7e3Smrg p1_h_accum_init = ((tmp << 4) & 0x000f8000) | 718c582b7e3Smrg ((tmp << 12) & 0xf0000000); 719c582b7e3Smrg 720c582b7e3Smrg tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); 721c582b7e3Smrg p23_h_accum_init = ((tmp << 4) & 0x000f8000) | 722c582b7e3Smrg ((tmp << 12) & 0x70000000); 723c582b7e3Smrg 724c582b7e3Smrg tmp = (top & 0x0000ffff) + 0x00018000; 725c582b7e3Smrg p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; 726c582b7e3Smrg 727c582b7e3Smrg tmp = ((top >> 1) & 0x0000ffff) + 0x00018000; 728c582b7e3Smrg p23_v_accum_init = ((tmp << 4) & 0x01ff8000) | 0x00000001; 729c582b7e3Smrg 730c582b7e3Smrg leftUV = (left >> 17) & 15; 731c582b7e3Smrg left = (left >> 16) & 15; 732c582b7e3Smrg 733c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 1); 734c582b7e3Smrg while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); 735c582b7e3Smrg 736c582b7e3Smrg OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); 737c582b7e3Smrg OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); 738c582b7e3Smrg OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); 739c582b7e3Smrg OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); 740c582b7e3Smrg OUTREG(R128_OV0_V_INC, v_inc); 741c582b7e3Smrg OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); 742c582b7e3Smrg src_h = (src_h + 1) >> 1; 743c582b7e3Smrg OUTREG(R128_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | ((src_h - 1) << 16)); 744c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); 745c582b7e3Smrg OUTREG(R128_OV0_VID_BUF_PITCH1_VALUE, pitch >> 1); 746c582b7e3Smrg OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); 747c582b7e3Smrg width >>= 1; 748c582b7e3Smrg OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (leftUV << 16)); 749c582b7e3Smrg OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (leftUV << 16)); 750c582b7e3Smrg OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0); 751c582b7e3Smrg OUTREG(R128_OV0_VID_BUF1_BASE_ADRS, (offset2 & 0xfffffff0) | 0x00000001); 752c582b7e3Smrg OUTREG(R128_OV0_VID_BUF2_BASE_ADRS, (offset3 & 0xfffffff0) | 0x00000001); 753c582b7e3Smrg OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); 754c582b7e3Smrg OUTREG(R128_OV0_P23_V_ACCUM_INIT, p23_v_accum_init); 755c582b7e3Smrg OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); 756c582b7e3Smrg OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); 757c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8A03); 758c582b7e3Smrg 759c582b7e3Smrg OUTREG(R128_OV0_REG_LOAD_CNTL, 0); 760c582b7e3Smrg} 761c582b7e3Smrg 762c582b7e3Smrg 763c582b7e3Smrg 764c582b7e3Smrgstatic int 765c582b7e3SmrgR128PutImage( 766c582b7e3Smrg ScrnInfoPtr pScrn, 767c582b7e3Smrg short src_x, short src_y, 768c582b7e3Smrg short drw_x, short drw_y, 769c582b7e3Smrg short src_w, short src_h, 770c582b7e3Smrg short drw_w, short drw_h, 771c582b7e3Smrg int id, unsigned char* buf, 772c582b7e3Smrg short width, short height, 773c582b7e3Smrg Bool Sync, 774c582b7e3Smrg RegionPtr clipBoxes, pointer data, 775c582b7e3Smrg DrawablePtr pDraw 776c582b7e3Smrg){ 777c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 778c582b7e3Smrg R128PortPrivPtr pPriv = (R128PortPrivPtr)data; 779c582b7e3Smrg unsigned char *fb = (CARD8*)info->FB; 780c582b7e3Smrg INT32 xa, xb, ya, yb; 781c582b7e3Smrg int new_size, offset, s1offset, s2offset, s3offset; 782c582b7e3Smrg int srcPitch, srcPitch2, dstPitch; 783c582b7e3Smrg int d1line, d2line, d3line, d1offset, d2offset, d3offset; 784c582b7e3Smrg int top, left, npixels, nlines, bpp; 785c582b7e3Smrg BoxRec dstBox; 786c582b7e3Smrg CARD32 tmp; 787c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 788c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 789c582b7e3Smrg CARD32 config_cntl = INREG(R128_CONFIG_CNTL); 790c582b7e3Smrg 791c582b7e3Smrg /* We need to disable byte swapping, or the data gets mangled */ 792c582b7e3Smrg OUTREG(R128_CONFIG_CNTL, config_cntl & 793c582b7e3Smrg ~(APER_0_BIG_ENDIAN_16BPP_SWAP | APER_0_BIG_ENDIAN_32BPP_SWAP)); 794c582b7e3Smrg#endif 795c582b7e3Smrg 796c582b7e3Smrg /* 797c582b7e3Smrg * s1offset, s2offset, s3offset - byte offsets to the Y, U and V planes 798c582b7e3Smrg * of the source. 799c582b7e3Smrg * 800c582b7e3Smrg * d1offset, d2offset, d3offset - byte offsets to the Y, U and V planes 801c582b7e3Smrg * of the destination. 802c582b7e3Smrg * 803c582b7e3Smrg * offset - byte offset within the framebuffer to where the destination 804c582b7e3Smrg * is stored. 805c582b7e3Smrg * 806c582b7e3Smrg * d1line, d2line, d3line - byte offsets within the destination to the 807c582b7e3Smrg * first displayed scanline in each plane. 808c582b7e3Smrg * 809c582b7e3Smrg */ 810c582b7e3Smrg 811c582b7e3Smrg if(src_w > (drw_w << 4)) 812c582b7e3Smrg drw_w = src_w >> 4; 813c582b7e3Smrg if(src_h > (drw_h << 4)) 814c582b7e3Smrg drw_h = src_h >> 4; 815c582b7e3Smrg 816c582b7e3Smrg /* Clip */ 817c582b7e3Smrg xa = src_x; 818c582b7e3Smrg xb = src_x + src_w; 819c582b7e3Smrg ya = src_y; 820c582b7e3Smrg yb = src_y + src_h; 821c582b7e3Smrg 822c582b7e3Smrg dstBox.x1 = drw_x; 823c582b7e3Smrg dstBox.x2 = drw_x + drw_w; 824c582b7e3Smrg dstBox.y1 = drw_y; 825c582b7e3Smrg dstBox.y2 = drw_y + drw_h; 826c582b7e3Smrg 827c582b7e3Smrg if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, 828c582b7e3Smrg clipBoxes, width, height)) 829c582b7e3Smrg return Success; 830c582b7e3Smrg 831c582b7e3Smrg dstBox.x1 -= pScrn->frameX0; 832c582b7e3Smrg dstBox.x2 -= pScrn->frameX0; 833c582b7e3Smrg dstBox.y1 -= pScrn->frameY0; 834c582b7e3Smrg dstBox.y2 -= pScrn->frameY0; 835c582b7e3Smrg 836c582b7e3Smrg bpp = pScrn->bitsPerPixel >> 3; 837c582b7e3Smrg 838c582b7e3Smrg switch(id) { 839c582b7e3Smrg case FOURCC_YV12: 840c582b7e3Smrg case FOURCC_I420: 841c582b7e3Smrg srcPitch = (width + 3) & ~3; 842c582b7e3Smrg srcPitch2 = ((width >> 1) + 3) & ~3; 843c582b7e3Smrg dstPitch = (width + 31) & ~31; /* of luma */ 844c582b7e3Smrg new_size = ((dstPitch * (height + (height >> 1))) + bpp - 1) / bpp; 845c582b7e3Smrg s1offset = 0; 846c582b7e3Smrg s2offset = srcPitch * height; 847c582b7e3Smrg s3offset = (srcPitch2 * (height >> 1)) + s2offset; 848c582b7e3Smrg break; 849c582b7e3Smrg case FOURCC_UYVY: 850c582b7e3Smrg case FOURCC_YUY2: 851c582b7e3Smrg default: 852c582b7e3Smrg srcPitch = width << 1; 853c582b7e3Smrg srcPitch2 = 0; 854c582b7e3Smrg dstPitch = ((width << 1) + 15) & ~15; 855c582b7e3Smrg new_size = ((dstPitch * height) + bpp - 1) / bpp; 856c582b7e3Smrg s1offset = 0; 857c582b7e3Smrg s2offset = 0; 858c582b7e3Smrg s3offset = 0; 859c582b7e3Smrg break; 860c582b7e3Smrg } 861c582b7e3Smrg 862c582b7e3Smrg if(!(pPriv->linear = R128AllocateMemory(pScrn, pPriv->linear, 863c582b7e3Smrg pPriv->doubleBuffer ? (new_size << 1) : new_size))) 864c582b7e3Smrg { 865c582b7e3Smrg return BadAlloc; 866c582b7e3Smrg } 867c582b7e3Smrg 868c582b7e3Smrg pPriv->currentBuffer ^= 1; 869c582b7e3Smrg 870c582b7e3Smrg /* copy data */ 871c582b7e3Smrg top = ya >> 16; 872c582b7e3Smrg left = (xa >> 16) & ~1; 873c582b7e3Smrg npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; 874c582b7e3Smrg 875c582b7e3Smrg offset = pPriv->linear->offset * bpp; 876c582b7e3Smrg if(pPriv->doubleBuffer) 877c582b7e3Smrg offset += pPriv->currentBuffer * new_size * bpp; 878c582b7e3Smrg 879c582b7e3Smrg switch(id) { 880c582b7e3Smrg case FOURCC_YV12: 881c582b7e3Smrg case FOURCC_I420: 882c582b7e3Smrg d1line = top * dstPitch; 883c582b7e3Smrg d2line = (height * dstPitch) + ((top >> 1) * (dstPitch >> 1)); 884c582b7e3Smrg d3line = d2line + ((height >> 1) * (dstPitch >> 1)); 885c582b7e3Smrg 886c582b7e3Smrg top &= ~1; 887c582b7e3Smrg 888c582b7e3Smrg d1offset = (top * dstPitch) + left + offset; 889c582b7e3Smrg d2offset = d2line + (left >> 1) + offset; 890c582b7e3Smrg d3offset = d3line + (left >> 1) + offset; 891c582b7e3Smrg 892c582b7e3Smrg s1offset += (top * srcPitch) + left; 893c582b7e3Smrg tmp = ((top >> 1) * srcPitch2) + (left >> 1); 894c582b7e3Smrg s2offset += tmp; 895c582b7e3Smrg s3offset += tmp; 896c582b7e3Smrg if(id == FOURCC_YV12) { 897c582b7e3Smrg tmp = s2offset; 898c582b7e3Smrg s2offset = s3offset; 899c582b7e3Smrg s3offset = tmp; 900c582b7e3Smrg } 901c582b7e3Smrg 902c582b7e3Smrg nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; 903c582b7e3Smrg R128CopyData420(info, buf + s1offset, buf + s2offset, buf + s3offset, 904c582b7e3Smrg fb + d1offset, fb + d2offset, fb + d3offset, 905c582b7e3Smrg srcPitch, srcPitch2, dstPitch, nlines, npixels); 906c582b7e3Smrg break; 907c582b7e3Smrg case FOURCC_UYVY: 908c582b7e3Smrg case FOURCC_YUY2: 909c582b7e3Smrg default: 910c582b7e3Smrg left <<= 1; 911c582b7e3Smrg d1line = top * dstPitch; 912c582b7e3Smrg d2line = 0; 913c582b7e3Smrg d3line = 0; 914c582b7e3Smrg d1offset = d1line + left + offset; 915c582b7e3Smrg d2offset = 0; 916c582b7e3Smrg d3offset = 0; 917c582b7e3Smrg s1offset += (top * srcPitch) + left; 918c582b7e3Smrg nlines = ((yb + 0xffff) >> 16) - top; 919c582b7e3Smrg R128CopyData422(info, buf + s1offset, fb + d1offset, 920c582b7e3Smrg srcPitch, dstPitch, nlines, npixels); 921c582b7e3Smrg break; 922c582b7e3Smrg } 923c582b7e3Smrg 924c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 925c582b7e3Smrg /* restore byte swapping */ 926c582b7e3Smrg OUTREG(R128_CONFIG_CNTL, config_cntl); 927c582b7e3Smrg#endif 928c582b7e3Smrg 929c582b7e3Smrg /* update cliplist */ 930c582b7e3Smrg if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 931c582b7e3Smrg REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 932c582b7e3Smrg /* draw these */ 933c582b7e3Smrg xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 934c582b7e3Smrg } 935c582b7e3Smrg 936c582b7e3Smrg 937c582b7e3Smrg switch(id) { 938c582b7e3Smrg case FOURCC_YV12: 939c582b7e3Smrg case FOURCC_I420: 940c582b7e3Smrg R128DisplayVideo420(pScrn, width, height, dstPitch, 941c582b7e3Smrg offset + d1line, offset + d2line, offset + d3line, 942c582b7e3Smrg xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); 943c582b7e3Smrg break; 944c582b7e3Smrg case FOURCC_UYVY: 945c582b7e3Smrg case FOURCC_YUY2: 946c582b7e3Smrg default: 947c582b7e3Smrg R128DisplayVideo422(pScrn, id, offset + d1line, width, height, dstPitch, 948c582b7e3Smrg xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); 949c582b7e3Smrg break; 950c582b7e3Smrg } 951c582b7e3Smrg 952c582b7e3Smrg pPriv->videoStatus = CLIENT_VIDEO_ON; 953c582b7e3Smrg 954c582b7e3Smrg info->VideoTimerCallback = R128VideoTimerCallback; 955c582b7e3Smrg 956c582b7e3Smrg return Success; 957c582b7e3Smrg} 958c582b7e3Smrg 959c582b7e3Smrg 960c582b7e3Smrgstatic int 961c582b7e3SmrgR128QueryImageAttributes( 962c582b7e3Smrg ScrnInfoPtr pScrn, 963c582b7e3Smrg int id, 964c582b7e3Smrg unsigned short *w, unsigned short *h, 965c582b7e3Smrg int *pitches, int *offsets 966c582b7e3Smrg){ 967c582b7e3Smrg int size, tmp; 968c582b7e3Smrg 969c582b7e3Smrg if(*w > MAXWIDTH) *w = MAXWIDTH; 970c582b7e3Smrg if(*h > MAXHEIGHT) *h = MAXHEIGHT; 971c582b7e3Smrg 972c582b7e3Smrg *w = (*w + 1) & ~1; 973c582b7e3Smrg if(offsets) offsets[0] = 0; 974c582b7e3Smrg 975c582b7e3Smrg switch(id) { 976c582b7e3Smrg case FOURCC_YV12: 977c582b7e3Smrg case FOURCC_I420: 978c582b7e3Smrg *h = (*h + 1) & ~1; 979c582b7e3Smrg size = (*w + 3) & ~3; 980c582b7e3Smrg if(pitches) pitches[0] = size; 981c582b7e3Smrg size *= *h; 982c582b7e3Smrg if(offsets) offsets[1] = size; 983c582b7e3Smrg tmp = ((*w >> 1) + 3) & ~3; 984c582b7e3Smrg if(pitches) pitches[1] = pitches[2] = tmp; 985c582b7e3Smrg tmp *= (*h >> 1); 986c582b7e3Smrg size += tmp; 987c582b7e3Smrg if(offsets) offsets[2] = size; 988c582b7e3Smrg size += tmp; 989c582b7e3Smrg break; 990c582b7e3Smrg case FOURCC_UYVY: 991c582b7e3Smrg case FOURCC_YUY2: 992c582b7e3Smrg default: 993c582b7e3Smrg size = *w << 1; 994c582b7e3Smrg if(pitches) pitches[0] = size; 995c582b7e3Smrg size *= *h; 996c582b7e3Smrg break; 997c582b7e3Smrg } 998c582b7e3Smrg 999c582b7e3Smrg return size; 1000c582b7e3Smrg} 1001c582b7e3Smrg 1002c582b7e3Smrgstatic void 1003c582b7e3SmrgR128VideoTimerCallback(ScrnInfoPtr pScrn, Time now) 1004c582b7e3Smrg{ 1005c582b7e3Smrg R128InfoPtr info = R128PTR(pScrn); 1006c582b7e3Smrg R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; 1007c582b7e3Smrg 1008c582b7e3Smrg if(pPriv->videoStatus & TIMER_MASK) { 1009c582b7e3Smrg if(pPriv->videoStatus & OFF_TIMER) { 1010c582b7e3Smrg if(pPriv->offTime < now) { 1011c582b7e3Smrg unsigned char *R128MMIO = info->MMIO; 1012c582b7e3Smrg OUTREG(R128_OV0_SCALE_CNTL, 0); 1013c582b7e3Smrg pPriv->videoStatus = FREE_TIMER; 1014c582b7e3Smrg pPriv->freeTime = now + FREE_DELAY; 1015c582b7e3Smrg } 1016c582b7e3Smrg } else { /* FREE_TIMER */ 1017c582b7e3Smrg if(pPriv->freeTime < now) { 1018c582b7e3Smrg if(pPriv->linear) { 1019c582b7e3Smrg xf86FreeOffscreenLinear(pPriv->linear); 1020c582b7e3Smrg pPriv->linear = NULL; 1021c582b7e3Smrg } 1022c582b7e3Smrg pPriv->videoStatus = 0; 1023c582b7e3Smrg info->VideoTimerCallback = NULL; 1024c582b7e3Smrg } 1025c582b7e3Smrg } 1026c582b7e3Smrg } else /* shouldn't get here */ 1027c582b7e3Smrg info->VideoTimerCallback = NULL; 1028c582b7e3Smrg} 1029