1/********************************************************************** 2Copyright 2002 by Shigehiro Nomura. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, distribute, and sell this software and 7its documentation for any purpose is hereby granted without fee, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Shigehiro Nomura not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. Shigehiro Nomura 13and its suppliers make no representations about the suitability of this 14software for any purpose. It is provided "as is" without express or 15implied warranty. 16 17SHIGEHIRO NOMURA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19EVENT SHALL SHIGEHIRO NOMURA AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24**********************************************************************/ 25 26/* 27 * Copyright 2002 SuSE Linux AG, Author: Egbert Eich 28 */ 29 30#ifdef HAVE_CONFIG_H 31#include "config.h" 32#endif 33 34#include "neo.h" 35#include "neo_video.h" 36 37#define nElems(x) (sizeof(x) / sizeof(x[0])) 38#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 39 40#include "dixstruct.h" 41 42static XF86VideoAdaptorPtr NEOSetupVideo(ScreenPtr); 43 44static int NEOPutVideo(ScrnInfoPtr, short, short, short, short, 45 short, short, short, short, RegionPtr, pointer, 46 DrawablePtr); 47 48static void NEOStopVideo(ScrnInfoPtr, pointer, Bool); 49static int NEOSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 50static int NEOGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); 51static void NEOQueryBestSize(ScrnInfoPtr, Bool, short, short, short, 52 short, unsigned int *, unsigned int *, pointer); 53static int NEOPutImage(ScrnInfoPtr, short, short, short, short, short, short, 54 short, short, int, unsigned char *, short, short, Bool, 55 RegionPtr, pointer, DrawablePtr); 56static int NEOQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 57 unsigned short *, int *, int *); 58 59static void NEODisplayVideo(ScrnInfoPtr, int, int, short, short, int, int, 60 int, int, int, BoxPtr, short, short, short, short); 61 62static void NEOInitOffscreenImages(ScreenPtr); 63static FBLinearPtr NEOAllocateMemory(ScrnInfoPtr, FBLinearPtr, int); 64 65static int NEOAllocSurface(ScrnInfoPtr, int, unsigned short, unsigned short, 66 XF86SurfacePtr); 67static int NEOFreeSurface(XF86SurfacePtr); 68static int NEODisplaySurface(XF86SurfacePtr, short, short, short, short, 69 short, short, short, short, RegionPtr clipBoxes); 70static int NEOStopSurface(XF86SurfacePtr); 71static int NEOGetSurfaceAttribute(ScrnInfoPtr, Atom, INT32 *); 72static int NEOSetSurfaceAttribute(ScrnInfoPtr, Atom, INT32); 73 74static Atom xvColorKey, xvBrightness, xvInterlace; 75 76void 77NEOInitVideo(ScreenPtr pScreen) 78{ 79 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 80 NEOPtr nPtr = NEOPTR(pScrn); 81 XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL; 82 XF86VideoAdaptorPtr newAdaptor = NULL; 83 int numAdaptors; 84 85 numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors); 86 87 if (nPtr->NeoChipset > NM2070 88 && nPtr->NeoMMIOBase2 != NULL){ 89 nPtr->video = TRUE; 90 newAdaptor = NEOSetupVideo(pScreen); 91 NEOInitOffscreenImages(pScreen); 92 } else 93 nPtr->video = FALSE; 94 95 if (newAdaptor){ 96 if (!numAdaptors){ 97 numAdaptors = 1; 98 overlayAdaptors = &newAdaptor; 99 } else { 100 newAdaptors = malloc((numAdaptors + 1) 101 * sizeof(XF86VideoAdaptorPtr*)); 102 if (newAdaptors){ 103 memcpy(newAdaptors, overlayAdaptors, 104 numAdaptors * sizeof(XF86VideoAdaptorPtr)); 105 newAdaptors[numAdaptors++] = newAdaptor; 106 overlayAdaptors = newAdaptors; 107 } 108 } 109 } 110 111 if (numAdaptors) 112 xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors); 113 114 if (newAdaptors) 115 free(newAdaptors); 116} 117 118static XF86VideoEncodingRec NEOVideoEncodings[] = 119{ 120 { 121 NEO_VIDEO_VIDEO, 122 "XV_VIDEO", 123 1024, 1024, 124 {1, 1} 125 }, 126 { 127 NEO_VIDEO_IMAGE, 128 "XV_IMAGE", 129 1024, 1024, 130 {1, 1} 131 } 132}; 133 134static XF86VideoFormatRec NEOVideoFormats[] = 135{ 136 { 8, PseudoColor }, 137 { 15, TrueColor }, 138 { 16, TrueColor }, 139 { 24, TrueColor }, 140}; 141 142static XF86AttributeRec NEOVideoAttributes[] = 143{ 144 { 145 XvSettable | XvGettable, 146 0x000000, 0xFFFFFF, 147 "XV_COLORKEY" 148 }, 149 { 150 XvSettable | XvGettable, 151 -128, 127, 152 "XV_BRIGHTNESS" 153 }, 154 { 155 XvSettable | XvGettable, 156 0,2, 157 "XV_INTERLACE" 158 }, 159}; 160 161static XF86ImageRec NEOVideoImages[] = 162{ 163 XVIMAGE_YUY2, 164 XVIMAGE_YV12, 165 XVIMAGE_I420, 166 { 167 FOURCC_RV15, 168 XvRGB, 169 LSBFirst, 170 { 'R', 'V' ,'1', '5', 171 0x00,'5',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 172 16, 173 XvPacked, 174 1, 175 15, 0x001F, 0x03E0, 0x7C00, 176 0, 0, 0, 177 0, 0, 0, 178 0, 0, 0, 179 { 'R', 'V', 'B' }, 180 XvTopToBottom 181 }, 182 { 183 FOURCC_RV16, 184 XvRGB, 185 LSBFirst, 186 { 'R', 'V' ,'1', '6', 187 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 188 16, 189 XvPacked, 190 1, 191 16, 0xF800, 0x07E0, 0x001F, 192 0, 0, 0, 193 0, 0, 0, 194 0, 0, 0, 195 { 'R', 'V', 'B' }, 196 XvTopToBottom 197 } 198}; 199 200static XF86VideoAdaptorPtr 201NEOSetupVideo(ScreenPtr pScreen) 202{ 203 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 204 NEOPtr nPtr = NEOPTR(pScrn); 205 NEOPortPtr pPriv; 206 XF86VideoAdaptorPtr overlayAdaptor; 207 int i; 208 209#ifdef DEBUG 210 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetupVideo\n"); 211#endif 212 if ((overlayAdaptor = calloc(1, sizeof(XF86VideoAdaptorRec) + 213 sizeof(DevUnion) + 214 sizeof(NEOPortRec))) == NULL){ 215 return (NULL); 216 } 217 218 overlayAdaptor->type = XvInputMask | XvImageMask | XvWindowMask 219 | XvOutputMask | XvVideoMask; 220 overlayAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 221 overlayAdaptor->name = "NeoMagic Video Engine"; 222 overlayAdaptor->nEncodings = nElems(NEOVideoEncodings); 223 overlayAdaptor->pEncodings = NEOVideoEncodings; 224 for (i = 0; i < nElems(NEOVideoEncodings); i++){ 225 NEOVideoEncodings[i].width = 1024; 226 NEOVideoEncodings[i].height = 1024; 227 } 228 overlayAdaptor->nFormats = nElems(NEOVideoFormats); 229 overlayAdaptor->pFormats = NEOVideoFormats; 230 overlayAdaptor->nPorts = 1; 231 overlayAdaptor->pPortPrivates = (DevUnion*) &overlayAdaptor[1]; 232 overlayAdaptor->pPortPrivates[0].ptr = 233 (pointer) &overlayAdaptor->pPortPrivates[1]; 234 overlayAdaptor->nAttributes = nElems(NEOVideoAttributes); 235 overlayAdaptor->pAttributes = NEOVideoAttributes; 236 overlayAdaptor->nImages = nElems(NEOVideoImages); 237 overlayAdaptor->pImages = NEOVideoImages; 238 239 overlayAdaptor->PutVideo = NEOPutVideo; 240 overlayAdaptor->PutStill = NULL; 241 overlayAdaptor->GetVideo = NULL; 242 overlayAdaptor->GetStill = NULL; 243 244 overlayAdaptor->StopVideo = NEOStopVideo; 245 overlayAdaptor->SetPortAttribute = NEOSetPortAttribute; 246 overlayAdaptor->GetPortAttribute = NEOGetPortAttribute; 247 overlayAdaptor->QueryBestSize = NEOQueryBestSize; 248 overlayAdaptor->PutImage = NEOPutImage; 249 overlayAdaptor->QueryImageAttributes = NEOQueryImageAttributes; 250 251 pPriv = (NEOPortPtr)overlayAdaptor->pPortPrivates[0].ptr; 252 pPriv->colorKey = nPtr->videoKey; 253 pPriv->interlace = nPtr->interlace; 254 pPriv->videoStatus = 0; 255 pPriv->brightness = 0; 256 REGION_NULL(pScreen, &pPriv->clip); 257 nPtr->overlayAdaptor = overlayAdaptor; 258 259 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 260 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 261 xvInterlace = MAKE_ATOM("XV_INTERLACE"); 262 263 NEOResetVideo(pScrn); 264 265 return (overlayAdaptor); 266} 267 268void 269NEOResetVideo(ScrnInfoPtr pScrn) 270{ 271 NEOPtr nPtr = NEOPTR(pScrn); 272 NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr; 273 int r, g, b; 274 VGA_HWP(pScrn); 275 276#ifdef DEBUG 277 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOResetVideo\n"); 278#endif 279 switch (pScrn->depth){ 280 case 8: 281 OUTGR(0xc6, pPriv->colorKey & 0); 282 OUTGR(0xc5, pPriv->colorKey & 0xff); 283 OUTGR(0xc7, pPriv->colorKey & 0); 284 break; 285 default: 286 r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 287 g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 288 b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 289 OUTGR(0xc5, r); 290 OUTGR(0xc6, g); 291 OUTGR(0xc7, b); 292 break; 293 } 294 OUTGR(0xc4, pPriv->brightness); 295} 296 297static int 298NEOPutVideo(ScrnInfoPtr pScrn, 299 short src_x, short src_y, short drw_x, short drw_y, 300 short src_w, short src_h, short drw_w, short drw_h, 301 RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 302{ 303 NEOPortPtr pPriv = (NEOPortPtr)data; 304 NEOPtr nPtr = NEOPTR(pScrn); 305 CARD32 src_pitch, offset; 306 int xscale, yscale; 307 BoxRec dstBox; 308 INT32 x1, y1, x2, y2; 309 int size, bpp; 310 unsigned char capctrl; 311 VGA_HWP(pScrn); 312 313#ifdef DEBUG 314 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: src: %d %d %d %d\n", 315 src_x, src_y, src_w, src_h); 316 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: drw: %d %d %d %d\n", 317 drw_x, drw_y, drw_w, drw_h); 318#endif 319 if (src_w > 720) 320 src_w = 720; 321 if (src_h > 576) 322 src_h = 576; 323 if (pPriv->interlace != 2) 324 src_h /= 2; 325 x1 = src_x; 326 y1 = src_y; 327 x2 = src_x + src_w; 328 y2 = src_y + src_h; 329 330 dstBox.x1 = drw_x; 331 dstBox.y1 = drw_y; 332 dstBox.x2 = drw_x + drw_w; 333 dstBox.y2 = drw_y + drw_h; 334 335 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 336 clipBoxes, src_w, src_h)){ 337 return(Success); 338 } 339#ifdef DEBUG 340 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: %d %d %d %d\n", 341 x1, y1, x2, y2); 342#endif 343 344 dstBox.x1 -= pScrn->frameX0; 345 dstBox.y1 -= pScrn->frameY0; 346 dstBox.x2 -= pScrn->frameX0; 347 dstBox.y2 -= pScrn->frameY0; 348#ifdef DEBUG 349 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: dstBox %d %d %d %d\n", 350 dstBox.x1, dstBox.y1, dstBox.x2, dstBox.y2); 351#endif 352 353 bpp = (pScrn->bitsPerPixel + 1) >> 3; 354 src_pitch = (src_w + 7) & ~7; 355 356 xscale = 0x1000; 357 if (src_w <= drw_w){ 358 xscale = (src_w * 0x1000 / drw_w) & 0xffff; 359 } 360 361 yscale = 0x1000; 362 if (src_h <= drw_h){ 363 yscale = (src_h * 0x1000 / drw_h) & 0xffff; 364 } 365 366 size = src_h * src_pitch * 2; 367 368 if (size > nPtr->overlay){ 369 if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) 370 == NULL){ 371 return (BadAlloc); 372 } 373 } else { 374 pPriv->linear = NULL; 375 } 376 377 if (pPriv->linear == NULL){ 378 offset = nPtr->overlay_offset; 379 } else { 380 offset = pPriv->linear->offset * bpp; 381 } 382 383#ifdef DEBUG 384 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: offset=0x%x\n", offset); 385#endif 386 WAIT_ENGINE_IDLE(); 387 memset(nPtr->NeoFbBase + offset, 0, size); 388 389 if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)){ 390 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 391 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 392 } 393 394 x1 >>= 16; 395 y1 >>= 16; 396 x2 >>= 16; 397 y2 >>= 16; 398 399 switch (nPtr->NeoChipset) { 400 default: 401 case NM2090: 402 case NM2093: 403 case NM2097: 404 case NM2160: 405 offset/=2; 406 OUTGR(0xbc, 0x4f); 407 break; 408 case NM2200: 409 case NM2230: 410 case NM2360: 411 case NM2380: 412 OUTGR(0xbc, 0x2e); 413 break; 414 } 415 416 417 OUTGR(0xb1, (((dstBox.x2-1) >> 4) & 0xf0) | ((dstBox.x1 >> 8) & 0x0f)); 418 OUTGR(0xb2, dstBox.x1); 419 OUTGR(0xb3, dstBox.x2 - 1); 420 OUTGR(0xb4, (((dstBox.y2 - 1) >> 4) & 0xf0) | ((dstBox.y1 >> 8) & 0x0f)); 421 OUTGR(0xb5, dstBox.y1); 422 OUTGR(0xb6, dstBox.y2 - 1); 423 OUTGR(0xb7, offset >> 16); 424 OUTGR(0xb8, offset >> 8); 425 OUTGR(0xb9, offset ); 426 OUTGR(0xba, src_pitch >> 8); 427 OUTGR(0xbb, src_pitch); 428 429 OUTGR(0xc0, xscale >> 8); 430 OUTGR(0xc1, xscale); 431 OUTGR(0xc2, yscale >> 8); 432 OUTGR(0xc3, yscale); 433 OUTGR(0xbf, 0x02); 434 435 OUTGR(0x0a, 0x21); 436 437 OUTSR(0x0c, offset ); 438 OUTSR(0x0d, offset >> 8); 439 OUTSR(0x0e, offset >> 16); 440 OUTSR(0x1a, src_pitch); 441 OUTSR(0x1b, src_pitch>>8); 442 443 OUTSR(0x17, 0 + x1); 444 OUTSR(0x18, 0 + x2 -1); 445 OUTSR(0x19, (((0 + x2 - 1) >> 4) & 0xf0) | (((0 + x1) >> 8) & 0x0f)); 446 447 OUTSR(0x14, 14 + y1); 448 OUTSR(0x15, 14 + y2 - 2); 449 OUTSR(0x16, (((14 + y2 - 1) >> 4) & 0xf0) | (((14 + y1) >> 8) & 0x0f)); 450 451 OUTSR(0x1c, 0xfb); 452 OUTSR(0x1d, 0x00); 453 OUTSR(0x1e, 0xe2); 454 OUTSR(0x1f, 0x02); 455 456 OUTSR(0x09, 0x11); 457 OUTSR(0x0a, 0x00); 458 459 capctrl = 0x21; 460 switch (pPriv->interlace){ 461 case 0: /* Combine 2 fields */ 462 break; 463 case 1: /* one field only */ 464 capctrl |= 0x80; 465 break; 466 case 2: /* Interlaced fields */ 467 capctrl |= 0x40; 468 break; 469 } 470 OUTSR(0x08, capctrl); 471 472#if 0 473 OUTGR(0x0a, 0x01); 474#endif 475 OUTGR(0xb0, 0x03); 476 477 pPriv->videoStatus = CLIENT_VIDEO_ON; 478 return (Success); 479} 480 481static void 482NEOStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) 483{ 484 NEOPortPtr pPriv = (NEOPortPtr)data; 485 NEOPtr nPtr = NEOPTR(pScrn); 486 VGA_HWP(pScrn); 487 488#ifdef DEBUG 489 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo\n"); 490#endif 491 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 492 493 if (exit){ 494 if (pPriv->videoStatus & CLIENT_VIDEO_ON){ 495#ifdef DEBUG 496 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo: stop capture\n"); 497#endif 498 OUTGR(0xb0, 0x02); 499 OUTGR(0x0a, 0x21); 500 OUTSR(0x08, 0xa0); 501#if 0 502 OUTGR(0x0a, 0x01); 503#endif 504 } 505 if (pPriv->linear != NULL){ 506 xf86FreeOffscreenLinear(pPriv->linear); 507 pPriv->linear = NULL; 508 } 509 pPriv->videoStatus = 0; 510 } else { 511 if (pPriv->videoStatus & CLIENT_VIDEO_ON){ 512 OUTGR(0xb0, 0x02); 513 OUTGR(0x0a, 0x21); 514 OUTSR(0x08, 0xa0); 515#if 0 516 OUTGR(0x0a, 0x01); 517#endif 518 pPriv->videoStatus |= OFF_TIMER; 519 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 520 } 521 } 522} 523 524static int 525NEOSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, 526 pointer data) 527{ 528 NEOPortPtr pPriv = (NEOPortPtr)data; 529 NEOPtr nPtr = NEOPTR(pScrn); 530 VGA_HWP(pScrn); 531 532#ifdef DEBUG 533 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetPortAttribute\n"); 534#endif 535 if (attribute == xvColorKey){ 536 int r, g, b; 537 538 pPriv->colorKey = value; 539 switch (pScrn->depth){ 540 case 8: 541 OUTGR(0xc6, pPriv->colorKey & 0xff); 542 OUTGR(0xc5, 0x00); 543 OUTGR(0xc7, 0x00); 544 break; 545 default: 546 r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; 547 g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; 548 b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; 549 OUTGR(0xc5, r); 550 OUTGR(0xc6, g); 551 OUTGR(0xc7, b); 552 } 553 } else if (attribute == xvBrightness){ 554 if ((value < -128) || (value > 127)){ 555 return (BadValue); 556 } 557 pPriv->brightness = value; 558 OUTGR(0xc4, value); 559 } else if (attribute == xvInterlace){ 560 if (value < 0 || value > 2){ 561 return (BadValue); 562 } 563 pPriv->interlace = value; 564 } else { 565 return (BadMatch); 566 } 567 return (Success); 568} 569 570static int 571NEOGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, 572 pointer data) 573{ 574 NEOPortPtr pPriv = (NEOPortPtr)data; 575 576#ifdef DEBUG 577 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetPortAttribute\n"); 578#endif 579 if (attribute == xvColorKey){ 580 *value = pPriv->colorKey; 581 } else if (attribute == xvBrightness){ 582 *value = pPriv->brightness; 583 } else if (attribute == xvInterlace){ 584 *value = pPriv->interlace; 585 } else { 586 return (BadMatch); 587 } 588 return (Success); 589} 590 591static void 592NEOQueryBestSize(ScrnInfoPtr pScrn, Bool motion, 593 short vid_w, short vid_h, short drw_w, short drw_h, 594 unsigned int *p_w, unsigned int *p_h, 595 pointer data) 596{ 597#ifdef DEBUG 598 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryBestSize\n"); 599#endif 600 *p_w = min(drw_w, 1024); 601 *p_h = min(drw_h, 1024); 602} 603 604static int 605NEOPutImage(ScrnInfoPtr pScrn, 606 short src_x, short src_y, short drw_x, short drw_y, 607 short src_w, short src_h, short drw_w, short drw_h, 608 int id, unsigned char *buf, short width, short height, 609 Bool sync, RegionPtr clipBoxes, pointer data, 610 DrawablePtr pDraw) 611{ 612 NEOPtr nPtr = NEOPTR(pScrn); 613 NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr; 614 INT32 x1, y1, x2, y2; 615 int bpp; 616 int srcPitch, srcPitch2 = 0, dstPitch, size; 617 BoxRec dstBox; 618 CARD32 offset, offset2 = 0, offset3 = 0, tmp; 619 int left, top, nPixels, nLines; 620 unsigned char *dstStart; 621 622#ifdef DEBUG 623 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutImage\n"); 624#endif 625 626 x1 = src_x; 627 y1 = src_y; 628 x2 = src_x + src_w; 629 y2 = src_y + src_h; 630 631 dstBox.x1 = drw_x; 632 dstBox.y1 = drw_y; 633 dstBox.x2 = drw_x + drw_w; 634 dstBox.y2 = drw_y + drw_h; 635 636 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, 637 clipBoxes, width, height)){ 638 return (Success); 639 } 640 641 dstBox.x1 -= pScrn->frameX0; 642 dstBox.y1 -= pScrn->frameY0; 643 dstBox.x2 -= pScrn->frameX0; 644 dstBox.y2 -= pScrn->frameY0; 645 646 bpp = ((pScrn->bitsPerPixel + 1) >> 3); 647 648 switch (id){ 649 case FOURCC_YV12: 650 srcPitch = (width + 3) & ~3; 651 offset2 = srcPitch * height; 652 srcPitch2 = ((width >> 1) + 3) & ~3; 653 offset3 = offset2 + (srcPitch2 * (height >> 1)); 654 dstPitch = ((width << 1) + 15) & ~15; 655 break; 656 case FOURCC_I420: 657 srcPitch = (width + 3) & ~3; 658 offset3 = srcPitch * height; 659 srcPitch2 = ((width >> 1) + 3) & ~3; 660 offset2 = offset3 + (srcPitch2 * (height >> 1)); 661 dstPitch = ((width << 1) + 15) & ~15; 662 break; 663 case FOURCC_YUY2: 664 case FOURCC_RV15: 665 case FOURCC_RV16: 666 default: 667 srcPitch = width << 1; 668 dstPitch = (srcPitch + 15) & ~15; 669 break; 670 } 671 672 size = dstPitch * height; 673 if (size > nPtr->overlay){ 674 if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) 675 == NULL){ 676 return (BadAlloc); 677 } 678 } else { 679 pPriv->linear = NULL; 680 } 681 682 top = y1 >> 16; 683 left = (x1 >> 16) & ~1; 684 nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left; 685 left <<= 1; 686 687 if (pPriv->linear == NULL){ 688 offset = nPtr->overlay_offset; 689 } else { 690 offset = pPriv->linear->offset * bpp; 691 } 692 693#ifdef DEBUG 694 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"offset=%x\n", offset); 695#endif 696 697 dstStart = (unsigned char *)(nPtr->NeoFbBase + offset + left); 698 699 switch (id){ 700 case FOURCC_YV12: 701 case FOURCC_I420: 702 top &= ~1; 703 tmp = ((top >> 1) * srcPitch2) + (left >> 2); 704 offset2 += tmp; 705 offset3 += tmp; 706 nLines = ((((y2 + 0xFFFF) >> 16) + 1) & ~1) - top; 707 xf86XVCopyYUV12ToPacked(buf + (top * srcPitch) + (left >> 1), 708 buf + offset2, buf + offset3, 709 dstStart, srcPitch, srcPitch2, 710 dstPitch, nLines, nPixels); 711 break; 712 default: 713 buf += (top * srcPitch) + left; 714 nLines = ((y2 + 0xFFFF) >> 16) - top; 715 xf86XVCopyPacked(buf, dstStart, srcPitch, dstPitch, 716 nLines, nPixels << 1); 717 } 718 719 if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)){ 720 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 721 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 722 } 723 NEODisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1, 724 x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 725 726 pPriv->videoStatus = CLIENT_VIDEO_ON; 727 return (Success); 728 729} 730 731static int 732NEOQueryImageAttributes(ScrnInfoPtr pScrn, int id, 733 unsigned short *width, unsigned short *height, 734 int *pitches, int *offsets) 735{ 736 int size, tmp; 737 738#ifdef DEBUG 739 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryImageAttributes\n"); 740#endif 741 if (*width > 1024){ 742 *width = 1024; 743 } 744 if (*height > 1024){ 745 *height = 1024; 746 } 747 748 *width = (*width + 1) & ~1; 749 if (offsets != NULL){ 750 offsets[0] = 0; 751 } 752 753 switch (id){ 754 case FOURCC_YV12: 755 case FOURCC_I420: 756 *height = (*height + 1) & ~1; 757 size = (*width + 3) & ~3; 758 if (pitches != NULL){ 759 pitches[0] = size; 760 } 761 size *= *height; 762 if (offsets != NULL){ 763 offsets[1] = size; 764 } 765 tmp = ((*width >> 1) + 3) & ~3; 766 if (pitches != NULL){ 767 pitches[1] = pitches[2] = tmp; 768 } 769 tmp *= (*height >> 1); 770 size += tmp; 771 if (offsets != NULL){ 772 offsets[2] = size; 773 } 774 size += tmp; 775 break; 776 case FOURCC_YUY2: 777 case FOURCC_RV15: 778 case FOURCC_RV16: 779 default: 780 size = *width * 2; 781 if (pitches != NULL){ 782 pitches[0] = size; 783 } 784 size *= *height; 785 break; 786 } 787 return (size); 788} 789 790static void 791NEODisplayVideo(ScrnInfoPtr pScrn, int id, int offset, 792 short width, short height, int pitch, 793 int x1, int y1, int x2, int y2, BoxPtr dstBox, 794 short src_w, short src_h, short drw_w, short drw_h) 795{ 796 NEOPtr nPtr = NEOPTR(pScrn); 797 int hstretch, vstretch, fmt; 798 VGA_HWP(pScrn); 799#ifdef DEBUG 800 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo\n"); 801 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo src_w=%d, src_h=%d, pitch=%d, drw_w=%d, drw_h=%d\n", src_w, src_h, pitch, drw_w, drw_h); 802#endif 803#define WIDTH_THRESHOLD 160 804 if (dstBox->x2 >= pScrn->virtualX) { 805 /* 806 * This is a hack to work around a problem when video is moved 807 * across the right border. 808 */ 809 int diff_s = (width - ((x2 - x1) >> 16)) & ~1; 810 int diff_d = (drw_w - dstBox->x2 + dstBox->x1) & ~1; 811 812 offset -= 2 * ((diff_s > diff_d) ? diff_d : diff_s); 813 dstBox->x1 -= diff_d; 814 } else if (dstBox->x2 - dstBox->x1 < WIDTH_THRESHOLD) { 815 /* 816 * When the video window is less than about 160 pixel wide 817 * it will be distoreted. We attempt to fix it by actually 818 * making it wider and relying on the color key to prevent 819 * it from appearing outside of the video. 820 */ 821 int pre, post; 822 int scale = 1; 823 824 if (dstBox->x1 < WIDTH_THRESHOLD) { 825 pre = dstBox->x1; 826 post = 160 - pre; 827 } else { 828 pre = 160; 829 post = 0; 830 } 831 offset -= 2 * scale * pre; 832 dstBox->x1 -= pre; 833 dstBox->x2 += post; 834 } 835 if (nPtr->videoHZoom != 1.0) { 836 if ((dstBox->x2 += 5) > pScrn->virtualX) 837 dstBox->x2 = pScrn->virtualX; 838 if (dstBox->x1 > 0) dstBox->x1 += 2; 839 } 840 841 fmt = 0x00; 842 switch (id){ 843 case FOURCC_YV12: 844 case FOURCC_I420: 845 case FOURCC_YUY2: 846 fmt = 0x00; 847 break; 848 case FOURCC_RV15: 849 case FOURCC_RV16: 850 fmt = 0x20; 851 break; 852 } 853 854 offset += (x1 >> 15) & ~0x03; 855 856 switch (nPtr->NeoChipset) { 857 default: 858 case NM2090: 859 case NM2093: 860 case NM2097: 861 case NM2160: 862 offset/=2; 863 pitch/=2; 864 OUTGR(0xbc, 0x4f); 865 break; 866 case NM2200: 867 case NM2230: 868 case NM2360: 869 case NM2380: 870 OUTGR(0xbc, 0x2e); 871 break; 872 } 873 874 /* factor 4 for granularity */ 875 hstretch = (double)0x1000 * 4 / (int)(nPtr->videoHZoom * 4); 876 if (drw_w > src_w) 877 hstretch = (((int)src_w) * hstretch) / (int) drw_w; 878 879 vstretch = (double)0x1000 / nPtr->videoVZoom; 880 if (drw_h > src_h) 881 vstretch = (((int)src_h) * vstretch )/ (int) drw_h; 882 883 OUTGR(0xb1, (((dstBox->x2 - 1) >> 4) & 0xf0) | ((dstBox->x1 >> 8) & 0x0f)); 884 OUTGR(0xb2, dstBox->x1); 885 OUTGR(0xb3, dstBox->x2 - 1); 886 OUTGR(0xb4, (((dstBox->y2 - 1) >> 4) & 0xf0) | ((dstBox->y1 >> 8) & 0x0f)); 887 OUTGR(0xb5, dstBox->y1); 888 OUTGR(0xb6, dstBox->y2 - 1); 889 OUTGR(0xb7, offset >> 16); 890 OUTGR(0xb8, offset >> 8); 891 OUTGR(0xb9, offset ); 892 OUTGR(0xba, pitch >> 8); 893 OUTGR(0xbb, pitch); 894 895 OUTGR(0xbd, 0x02); 896 OUTGR(0xbe, 0x00); 897 OUTGR(0xbf, 0x02); 898 899 OUTGR(0xc0, hstretch >> 8); 900 OUTGR(0xc1, hstretch); 901 OUTGR(0xc2, vstretch >> 8); 902 OUTGR(0xc3, vstretch); 903 904 OUTGR(0xb0, fmt | 0x03); 905 906 OUTGR(0x0a, 0x21); 907 OUTSR(0x08, 0xa0); 908 OUTGR(0x0a, 0x01); 909} 910 911static void 912NEOInitOffscreenImages(ScreenPtr pScreen) 913{ 914 XF86OffscreenImagePtr offscreenImages; 915 916#ifdef DEBUG 917 xf86DrvMsg(xf86ScreenToScrn(pScreen)->scrnIndex,X_INFO,"NEOInitOffscreenImages\n"); 918#endif 919 if ((offscreenImages = malloc(sizeof(XF86OffscreenImageRec))) == NULL){ 920 return; 921 } 922 923 offscreenImages->image = NEOVideoImages; 924 offscreenImages->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 925 offscreenImages->alloc_surface = NEOAllocSurface; 926 offscreenImages->free_surface = NEOFreeSurface; 927 offscreenImages->display = NEODisplaySurface; 928 offscreenImages->stop = NEOStopSurface; 929 offscreenImages->getAttribute = NEOGetSurfaceAttribute; 930 offscreenImages->setAttribute = NEOSetSurfaceAttribute; 931 offscreenImages->max_width = 1024; 932 offscreenImages->max_height = 1024; 933 offscreenImages->num_attributes = nElems(NEOVideoAttributes); 934 offscreenImages->attributes = NEOVideoAttributes; 935 936 xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); 937} 938 939static FBLinearPtr 940NEOAllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) 941{ 942 ScreenPtr pScreen; 943 FBLinearPtr new_linear; 944 int bytespp = pScrn->bitsPerPixel >> 3; 945 946 /* convert size in bytes into number of pixels */ 947 size = (size + bytespp - 1) / bytespp; 948#ifdef DEBUG 949 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 950 "NEOAllocateMemory: linear=%x, size=%d\n", linear, size); 951#endif 952 if (linear){ 953#ifdef DEBUG 954 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 955 "NEOAllocateMemory: linear->size=%d\n", linear->size); 956#endif 957 if (linear->size >= size){ 958 return (linear); 959 } 960 961 if (xf86ResizeOffscreenLinear(linear, size)){ 962 return (linear); 963 } 964 965 xf86FreeOffscreenLinear(linear); 966 } 967 968 969 pScreen = xf86ScrnToScreen(pScrn); 970 if ((new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL, 971 NULL, NULL)) == NULL){ 972 int max_size; 973 974 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 975 PRIORITY_EXTREME); 976#ifdef DEBUG 977 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 978 "NEOAllocateMemory: max_size=%d\n", max_size); 979#endif 980 if (max_size < size){ 981 return (NULL); 982 } 983 984 xf86PurgeUnlockedOffscreenAreas(pScreen); 985 new_linear = xf86AllocateOffscreenLinear(pScreen, 986 size, 16, NULL, NULL, NULL); 987 } 988 989 return (new_linear); 990} 991 992static int 993NEOAllocSurface(ScrnInfoPtr pScrn, int id, 994 unsigned short width, unsigned short height, 995 XF86SurfacePtr surface) 996{ 997 int pitch, size; 998 NEOOffscreenPtr pPriv; 999 FBLinearPtr linear; 1000 1001#ifdef DEBUG 1002 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocSurface\n"); 1003#endif 1004 if (width > 1024 || height > 1024){ 1005 return (BadAlloc); 1006 } 1007 1008 width = (width + 1) & ~1; 1009 pitch = ((width << 1) + 15) & ~15; 1010 size = pitch * height; 1011 1012 if ((linear = NEOAllocateMemory(pScrn, NULL, size)) == NULL){ 1013 return (BadAlloc); 1014 } 1015 1016 surface->width = width; 1017 surface->height = height; 1018 if ((surface->pitches = malloc(sizeof(int))) == NULL){ 1019 xf86FreeOffscreenLinear(linear); 1020 return (BadAlloc); 1021 } 1022 if ((surface->offsets = malloc(sizeof(int))) == NULL){ 1023 free(surface->pitches); 1024 xf86FreeOffscreenLinear(linear); 1025 return (BadAlloc); 1026 } 1027 1028 if ((pPriv = malloc(sizeof(NEOOffscreenRec))) == NULL){ 1029 free(surface->pitches); 1030 free(surface->offsets); 1031 xf86FreeOffscreenLinear(linear); 1032 return (BadAlloc); 1033 } 1034 1035 pPriv->linear = linear; 1036 pPriv->isOn = FALSE; 1037 1038 surface->pScrn = pScrn; 1039 surface->id = id; 1040 surface->pitches[0] = pitch; 1041 surface->offsets[0] = linear->offset << 1; 1042 surface->devPrivate.ptr = (pointer)pPriv; 1043 return (Success); 1044} 1045 1046static int 1047NEOFreeSurface(XF86SurfacePtr surface) 1048{ 1049 NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; 1050 1051#ifdef DEBUG 1052 xf86DrvMsg(0,X_INFO,"NEOFreeSurface\n"); 1053#endif 1054 if (pPriv->isOn) 1055 NEOStopSurface(surface); 1056 1057 xf86FreeOffscreenLinear(pPriv->linear); 1058 free(surface->pitches); 1059 free(surface->offsets); 1060 free(surface->devPrivate.ptr); 1061 return (Success); 1062} 1063 1064static int 1065NEODisplaySurface(XF86SurfacePtr surface, 1066 short src_x, short src_y, short drw_x, short drw_y, 1067 short src_w, short src_h, short drw_w, short drw_h, 1068 RegionPtr clipBoxes) 1069{ 1070 NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; 1071 NEOPtr nPtr = NEOPTR(surface->pScrn); 1072 NEOPortPtr portPriv = nPtr->overlayAdaptor->pPortPrivates[0].ptr; 1073 INT32 x1, y1, x2, y2; 1074 BoxRec dstBox; 1075 1076#ifdef DEBUG 1077 xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEODisplaySurface\n"); 1078#endif 1079 x1 = src_x; 1080 x2 = src_x + src_w; 1081 y1 = src_y; 1082 y2 = src_y + src_h; 1083 1084 dstBox.x1 = drw_x; 1085 dstBox.x2 = drw_x + drw_w; 1086 dstBox.y1 = drw_y; 1087 dstBox.y2 = drw_y + drw_h; 1088 if (!xf86XVClipVideoHelper( &dstBox, &x1, &x2, &y1, &y2, 1089 clipBoxes, surface->width, surface->height)){ 1090 return (Success); 1091 } 1092 1093 dstBox.x1 -= surface->pScrn->frameX0; 1094 dstBox.y1 -= surface->pScrn->frameY0; 1095 dstBox.x2 -= surface->pScrn->frameX0; 1096 dstBox.y2 -= surface->pScrn->frameY0; 1097 1098 xf86XVFillKeyHelper(surface->pScrn->pScreen, portPriv->colorKey, 1099 clipBoxes); 1100 NEOResetVideo(surface->pScrn); 1101 NEODisplayVideo(surface->pScrn, surface->id, surface->offsets[0], 1102 surface->width, surface->height, surface->pitches[0], 1103 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1104 1105 pPriv->isOn = TRUE; 1106 if (portPriv->videoStatus & CLIENT_VIDEO_ON){ 1107 REGION_EMPTY(surface->pScrn->pScreen, &portPriv->clip); 1108 UpdateCurrentTime(); 1109 portPriv->videoStatus = FREE_TIMER; 1110 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1111 } 1112 return (Success); 1113} 1114 1115static int 1116NEOStopSurface(XF86SurfacePtr surface) 1117{ 1118 NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr; 1119 1120#ifdef DEBUG 1121 xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEOStopSurface\n"); 1122#endif 1123 if (pPriv->isOn){ 1124 NEOPtr nPtr = NEOPTR(surface->pScrn); 1125 VGA_HWP(surface->pScrn); 1126 OUTGR(0xb0, 0x02); 1127 pPriv->isOn = FALSE; 1128 } 1129 return (Success); 1130} 1131 1132static int 1133NEOGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value) 1134{ 1135 NEOPtr nPtr = NEOPTR(pScrn); 1136 1137#ifdef DEBUG 1138 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetSurfaceAttribute\n"); 1139#endif 1140 return (NEOGetPortAttribute(pScrn, 1141 attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr)); 1142} 1143 1144static int 1145NEOSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value) 1146{ 1147 NEOPtr nPtr = NEOPTR(pScrn); 1148 1149#ifdef DEBUG 1150 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetSurfaceAttribute\n"); 1151#endif 1152 return (NEOSetPortAttribute(pScrn, 1153 attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr)); 1154} 1155