gx_video.c revision 04007eba
1/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPDIs2IED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 * */ 25 26/* 27 * File Contents: This file consists of main Xfree video supported routines. 28 * 29 * Project: Geode Xfree Frame buffer device driver. 30 * */ 31 32/* 33 * Fixes & Extensions to support Y800 greyscale modes 34 * Alan Hourihane <alanh@fairlite.demon.co.uk> 35 36 * code to allocate offscreen memory from EXA - is borrowed from Radeon 37 */ 38 39#ifdef HAVE_CONFIG_H 40#include "config.h" 41#endif 42 43#include <stdlib.h> 44#include <string.h> 45 46#include "xf86.h" 47#include "xf86_OSproc.h" 48#include "compiler.h" 49#include "xf86PciInfo.h" 50#include "xf86Pci.h" 51#include "xf86fbman.h" 52#include "regionstr.h" 53 54#include "geode.h" 55#include "xf86xv.h" 56#include <X11/extensions/Xv.h> 57#ifdef HAVE_XAA_H 58#include "xaa.h" 59#include "xaalocal.h" 60#endif 61#include "dixstruct.h" 62#include "fourcc.h" 63#include "geode_fourcc.h" 64 65#define OFF_DELAY 200 /* milliseconds */ 66#define FREE_DELAY 60000 67 68#define OFF_TIMER 0x01 69#define FREE_TIMER 0x02 70#define CLIENT_VIDEO_ON 0x04 71 72#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 73#define XV_PROFILE 0 74#define REINIT 1 75 76#ifndef XvExtension 77#error "It didn't work!" 78void 79GXInitVideo(ScreenPtr pScrn) 80{ 81} 82 83void 84GXResetVideo(ScrnInfoPtr pScrni) 85{ 86} 87 88void 89GXSetVideoPosition() 90{ 91} 92#else 93 94#define DBUF 1 95void GXResetVideo(ScrnInfoPtr pScrni); 96static XF86VideoAdaptorPtr GXSetupImageVideo(ScreenPtr); 97static void GXInitOffscreenImages(ScreenPtr); 98static void GXStopVideo(ScrnInfoPtr, pointer, Bool); 99static int GXSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 100static int GXGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); 101static void GXQueryBestSize(ScrnInfoPtr, Bool, 102 short, short, short, short, unsigned int *, 103 unsigned int *, pointer); 104static int GXPutImage(ScrnInfoPtr, short, short, short, short, short, short, 105 short, short, int, unsigned char *, short, short, Bool, 106 RegionPtr, pointer, DrawablePtr pDraw); 107 108static void GXBlockHandler(BLOCKHANDLER_ARGS_DECL); 109void GXSetVideoPosition(int x, int y, int width, int height, 110 short src_w, short src_h, short drw_w, 111 short drw_h, int id, int offset, ScrnInfoPtr pScrni); 112 113extern void GXAccelSync(ScrnInfoPtr pScrni); 114 115int DeltaX, DeltaY; 116 117unsigned long graphics_lut[256]; 118static int lutflag = 0; 119 120#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 121 122static Atom xvColorKey, xvColorKeyMode, xvFilter 123#if DBUF 124, xvDoubleBuffer 125#endif 126; 127 128#define PALETTE_ADDRESS 0x038 129#define PALETTE_DATA 0x040 130#define DISPLAY_CONFIG 0x008 131#define MISC 0x050 132 133static void 134get_gamma_ram(unsigned long *lut) 135{ 136 137 int i; 138 139 gfx_write_vid32(PALETTE_ADDRESS, 0); 140 141 for (i = 0; i < 256; i++) 142 lut[i] = gfx_read_vid32(PALETTE_DATA); 143} 144 145/*---------------------------------------------------------------------------- 146 * GXInitVideo 147 * 148 * Description :This is the initialization routine.It creates a new video 149 * adapter and calls GXSetupImageVideo to initialize the adaptor 150 * by filling XF86VideoAdaptorREc.Then it lists the existing 151 * adaptors and adds the new one to it. Finally the list of 152 * XF86VideoAdaptorPtr pointers are passed to the 153 * xf86XVScreenInit(). 154 * 155 * Parameters. 156 * pScrn :Screen handler pointer having screen information. 157 * 158 * Returns :none 159 * 160 * Comments :none 161 *---------------------------------------------------------------------------- 162 */ 163void 164GXInitVideo(ScreenPtr pScrn) 165{ 166 GeodeRec *pGeode; 167 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 168 169 pGeode = GEODEPTR(pScrni); 170 171 if (!pGeode->NoAccel) { 172 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; 173 XF86VideoAdaptorPtr newAdaptor = NULL; 174 175 int num_adaptors; 176 177 newAdaptor = GXSetupImageVideo(pScrn); 178 GXInitOffscreenImages(pScrn); 179 180 num_adaptors = xf86XVListGenericAdaptors(pScrni, &adaptors); 181 182 if (newAdaptor) { 183 if (!num_adaptors) { 184 num_adaptors = 1; 185 adaptors = &newAdaptor; 186 } 187 else { 188 newAdaptors = /* need to free this someplace */ 189 malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr *)); 190 if (newAdaptors) { 191 memcpy(newAdaptors, adaptors, num_adaptors * 192 sizeof(XF86VideoAdaptorPtr)); 193 newAdaptors[num_adaptors] = newAdaptor; 194 adaptors = newAdaptors; 195 num_adaptors++; 196 } 197 } 198 } 199 200 if (num_adaptors) 201 xf86XVScreenInit(pScrn, adaptors, num_adaptors); 202 203 if (newAdaptors) 204 free(newAdaptors); 205 } 206} 207 208/* client libraries expect an encoding */ 209static XF86VideoEncodingRec DummyEncoding[1] = { 210 { 211 0, 212 "XV_IMAGE", 213 1024, 1024, 214 {1, 1} 215 } 216}; 217 218#define NUM_FORMATS 4 219 220static XF86VideoFormatRec Formats[NUM_FORMATS] = { 221 {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} 222}; 223 224#if DBUF 225#define NUM_ATTRIBUTES 4 226#else 227#define NUM_ATTRIBUTES 3 228#endif 229 230static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { 231#if DBUF 232 {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}, 233#endif 234 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 235 {XvSettable | XvGettable, 0, 1, "XV_FILTER"}, 236 {XvSettable | XvGettable, 0, 1, "XV_COLORKEYMODE"} 237}; 238 239#define NUM_IMAGES 8 240 241static XF86ImageRec Images[NUM_IMAGES] = { 242 XVIMAGE_UYVY, 243 XVIMAGE_YUY2, 244 XVIMAGE_Y2YU, 245 XVIMAGE_YVYU, 246 XVIMAGE_Y800, 247 XVIMAGE_I420, 248 XVIMAGE_YV12, 249 XVIMAGE_RGB565 250}; 251 252typedef struct { 253 void *area; 254 int offset; 255 RegionRec clip; 256 CARD32 filter; 257 CARD32 colorKey; 258 CARD32 colorKeyMode; 259 CARD32 videoStatus; 260 Time offTime; 261 Time freeTime; 262#if DBUF 263 Bool doubleBuffer; 264 int currentBuffer; 265#endif 266} GeodePortPrivRec, *GeodePortPrivPtr; 267 268#define GET_PORT_PRIVATE(pScrni) \ 269 (GeodePortPrivRec *)((GEODEPTR(pScrni))->adaptor->pPortPrivates[0].ptr) 270 271/*---------------------------------------------------------------------------- 272 * GXSetColorKey 273 * 274 * Description :This function reads the color key for the pallete and 275 * sets the video color key register. 276 * 277 * Parameters. 278 * ScreenInfoPtr 279 * pScrni :Screen pointer having screen information. 280 * pPriv :Video port private data 281 * 282 * Returns :none 283 * 284 * Comments :none 285 * 286 *---------------------------------------------------------------------------- 287 */ 288static INT32 289GXSetColorkey(ScrnInfoPtr pScrni, GeodePortPrivRec * pPriv) 290{ 291 int red, green, blue; 292 unsigned long key; 293 294 switch (pScrni->depth) { 295 case 8: 296 GFX(get_display_palette_entry(pPriv->colorKey & 0xFF, &key)); 297 red = ((key >> 16) & 0xFF); 298 green = ((key >> 8) & 0xFF); 299 blue = (key & 0xFF); 300 break; 301 case 16: 302 red = (pPriv->colorKey & pScrni->mask.red) >> 303 pScrni->offset.red << (8 - pScrni->weight.red); 304 green = (pPriv->colorKey & pScrni->mask.green) >> 305 pScrni->offset.green << (8 - pScrni->weight.green); 306 blue = (pPriv->colorKey & pScrni->mask.blue) >> 307 pScrni->offset.blue << (8 - pScrni->weight.blue); 308 break; 309 default: 310 /* for > 16 bpp we send in the mask in xf86SetWeight. This 311 * function is providing the offset by 1 more. So we take 312 * this as a special case and subtract 1 for > 16 313 */ 314 red = (pPriv->colorKey & pScrni->mask.red) >> 315 (pScrni->offset.red - 1) << (8 - pScrni->weight.red); 316 green = (pPriv->colorKey & pScrni->mask.green) >> 317 (pScrni->offset.green - 1) << (8 - pScrni->weight.green); 318 blue = (pPriv->colorKey & pScrni->mask.blue) >> 319 (pScrni->offset.blue - 1) << (8 - pScrni->weight.blue); 320 break; 321 } 322 323 GFX(set_video_color_key((blue | (green << 8) | (red << 16)), 0xFFFFFF, 324 (pPriv->colorKeyMode == 0))); 325 REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 326 return 0; 327} 328 329/*---------------------------------------------------------------------------- 330 * GXResetVideo 331 * 332 * Description : This function resets the video 333 * 334 * Parameters. 335 * pScrni :Screen pointer having screen information. 336 * 337 * Returns :None 338 * 339 * Comments :none 340 * 341 *---------------------------------------------------------------------------- 342 */ 343void 344GXResetVideo(ScrnInfoPtr pScrni) 345{ 346 GeodeRec *pGeode = GEODEPTR(pScrni); 347 348 if (!pGeode->NoAccel) { 349 GeodePortPrivRec *pPriv = pGeode->adaptor->pPortPrivates[0].ptr; 350 351 GXAccelSync(pScrni); 352 GXSetColorkey(pScrni, pPriv); 353 GFX(set_video_filter(pPriv->filter, pPriv->filter)); 354 } 355} 356 357/*---------------------------------------------------------------------------- 358 * GXSetupImageVideo 359 * 360 * Description : This function allocates space for a Videoadaptor and 361 * initializes the XF86VideoAdaptorPtr record. 362 * 363 * Parameters. 364 * pScrn :Screen handler pointer having screen information. 365 * 366 * Returns :pointer to the initialized video adaptor record. 367 * 368 * Comments :none 369 *---------------------------------------------------------------------------- 370 */ 371static XF86VideoAdaptorPtr 372GXSetupImageVideo(ScreenPtr pScrn) 373{ 374 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 375 GeodeRec *pGeode = GEODEPTR(pScrni); 376 XF86VideoAdaptorPtr adapt; 377 GeodePortPrivRec *pPriv; 378 379 if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + 380 sizeof(GeodePortPrivRec) + sizeof(DevUnion)))) 381 return NULL; 382 383 adapt->type = XvWindowMask | XvInputMask | XvImageMask; 384 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 385 adapt->name = "Advanced Micro Devices"; 386 adapt->nEncodings = 1; 387 adapt->pEncodings = DummyEncoding; 388 adapt->nFormats = NUM_FORMATS; 389 adapt->pFormats = Formats; 390 adapt->nPorts = 1; 391 adapt->pPortPrivates = (DevUnion *) (&adapt[1]); 392 pPriv = (GeodePortPrivRec *) (&adapt->pPortPrivates[1]); 393 adapt->pPortPrivates[0].ptr = (pointer) (pPriv); 394 adapt->pAttributes = Attributes; 395 adapt->nImages = NUM_IMAGES; 396 adapt->nAttributes = NUM_ATTRIBUTES; 397 adapt->pImages = Images; 398 adapt->PutVideo = NULL; 399 adapt->PutStill = NULL; 400 adapt->GetVideo = NULL; 401 adapt->GetStill = NULL; 402 adapt->StopVideo = GXStopVideo; 403 adapt->SetPortAttribute = GXSetPortAttribute; 404 adapt->GetPortAttribute = GXGetPortAttribute; 405 adapt->QueryBestSize = GXQueryBestSize; 406 adapt->PutImage = GXPutImage; 407 adapt->QueryImageAttributes = GeodeQueryImageAttributes; 408 409 pPriv->filter = 0; 410 pPriv->colorKey = 0; 411 pPriv->colorKeyMode = 0; 412 pPriv->videoStatus = 0; 413#if DBUF 414 pPriv->doubleBuffer = TRUE; 415 pPriv->currentBuffer = 0; /* init to first buffer */ 416#endif 417 418 /* gotta uninit this someplace */ 419#if defined(REGION_NULL) 420 REGION_NULL(pScrn, &pPriv->clip); 421#else 422 REGION_INIT(pScrn, &pPriv->clip, NullBox, 0); 423#endif 424 425 pGeode->adaptor = adapt; 426 427 pGeode->BlockHandler = pScrn->BlockHandler; 428 pScrn->BlockHandler = GXBlockHandler; 429 430 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 431 xvColorKeyMode = MAKE_ATOM("XV_COLORKEYMODE"); 432 xvFilter = MAKE_ATOM("XV_FILTER"); 433#if DBUF 434 xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER"); 435#endif 436 437 GXResetVideo(pScrni); 438 439 return adapt; 440} 441 442/*---------------------------------------------------------------------------- 443 * GXStopVideo 444 * 445 * Description :This function is used to stop input and output video 446 * 447 * Parameters. 448 * pScrni :Screen handler pointer having screen information. 449 * data :Pointer to the video port's private data 450 * exit :Flag indicating whether the offscreen areas used for 451 * video to be deallocated or not. 452 * 453 * Returns :none 454 * 455 * Comments :none 456 *---------------------------------------------------------------------------- 457 */ 458static void 459GXStopVideo(ScrnInfoPtr pScrni, pointer data, Bool exit) 460{ 461 GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 462 GeodeRec *pGeode = GEODEPTR(pScrni); 463 464 REGION_EMPTY(pScrni->pScreen, &pPriv->clip); 465 466 GXAccelSync(pScrni); 467 if (exit) { 468 if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 469 GFX(set_video_enable(0)); 470 471 /* If we have saved graphics LUT data - restore it */ 472 /* Otherwise, turn bypass on */ 473 474 if (lutflag) 475 GFX(set_graphics_palette(graphics_lut)); 476 else 477 GFX(set_video_palette_bypass(1)); 478 479 lutflag = 0; 480 } 481 482 if (pPriv->area) { 483#ifdef XF86EXA 484 if (pGeode->useEXA) 485 exaOffscreenFree(pScrni->pScreen, pPriv->area); 486#endif 487 488 if (!pGeode->useEXA) 489 xf86FreeOffscreenArea(pPriv->area); 490 491 pPriv->area = NULL; 492 } 493 494 pPriv->videoStatus = 0; 495 pGeode->OverlayON = FALSE; 496 } 497 else { 498 if (pPriv->videoStatus & CLIENT_VIDEO_ON) { 499 pPriv->videoStatus |= OFF_TIMER; 500 pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 501 } 502 } 503} 504 505/*---------------------------------------------------------------------------- 506 * GXSetPortAttribute 507 * 508 * Description :This function is used to set the attributes of a port 509 * like colorkeymode, double buffer support and filter. 510 * 511 * Parameters. 512 * pScrni :Screen handler pointer having screen information. 513 * data :Pointer to the video port's private data 514 * attribute :The port attribute to be set 515 * value :Value of the attribute to be set. 516 * 517 * Returns :Sucess if the attribute is supported, else BadMatch 518 * 519 * Comments :none 520 *---------------------------------------------------------------------------- 521 */ 522static int 523GXSetPortAttribute(ScrnInfoPtr pScrni, 524 Atom attribute, INT32 value, pointer data) 525{ 526 GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 527 528 GXAccelSync(pScrni); 529 if (attribute == xvColorKey) { 530 pPriv->colorKey = value; 531 GXSetColorkey(pScrni, pPriv); 532 } 533#if DBUF 534 else if (attribute == xvDoubleBuffer) { 535 if ((value < 0) || (value > 1)) 536 return BadValue; 537 pPriv->doubleBuffer = value; 538 } 539#endif 540 else if (attribute == xvColorKeyMode) { 541 pPriv->colorKeyMode = value; 542 GXSetColorkey(pScrni, pPriv); 543 } 544 else if (attribute == xvFilter) { 545 if ((value < 0) || (value > 1)) 546 return BadValue; 547 pPriv->filter = value; 548 } 549 else 550 return BadMatch; 551 552 return Success; 553} 554 555/*---------------------------------------------------------------------------- 556 * GXGetPortAttribute 557 * 558 * Description :This function is used to get the attributes of a port 559 * like hue, saturation,brightness or contrast. 560 * 561 * Parameters. 562 * pScrni :Screen handler pointer having screen information. 563 * data :Pointer to the video port's private data 564 * attribute :The port attribute to be read 565 * value :Pointer to the value of the attribute to be read. 566 * 567 * Returns :Sucess if the attribute is supported, else BadMatch 568 * 569 * Comments :none 570 *---------------------------------------------------------------------------- 571 */ 572static int 573GXGetPortAttribute(ScrnInfoPtr pScrni, 574 Atom attribute, INT32 *value, pointer data) 575{ 576 GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 577 578 if (attribute == xvColorKey) { 579 *value = pPriv->colorKey; 580 } 581#if DBUF 582 else if (attribute == xvDoubleBuffer) { 583 *value = (pPriv->doubleBuffer) ? 1 : 0; 584 } 585#endif 586 else if (attribute == xvColorKeyMode) { 587 *value = pPriv->colorKeyMode; 588 } 589 else if (attribute == xvFilter) { 590 *value = pPriv->filter; 591 } 592 else 593 return BadMatch; 594 595 return Success; 596} 597 598/*---------------------------------------------------------------------------- 599 * GXQueryBestSize 600 * 601 * Description :This function provides a way to query what the 602 * destination dimensions would end up being if they were to 603 * request that an area vid_w by vid_h from the video stream 604 * be scaled to rectangle of drw_w by drw_h on the screen. 605 * 606 * Parameters. 607 * pScrni :Screen handler pointer having screen information. 608 * data :Pointer to the video port's private data 609 * vid_w,vid_h :Width and height of the video data. 610 * drw_w,drw_h :Width and height of the scaled rectangle. 611 * p_w,p_h :Width and height of the destination rectangle. 612 * 613 * Returns :None 614 * 615 * Comments :None 616 *---------------------------------------------------------------------------- 617 */ 618static void 619GXQueryBestSize(ScrnInfoPtr pScrni, 620 Bool motion, 621 short vid_w, short vid_h, 622 short drw_w, short drw_h, 623 unsigned int *p_w, unsigned int *p_h, pointer data) 624{ 625 *p_w = drw_w; 626 *p_h = drw_h; 627 628 if (*p_w > 16384) 629 *p_w = 16384; 630} 631 632/*---------------------------------------------------------------------------- 633 * GXCopyData420 634 * 635 * Description : Copies data from src to destination 636 * 637 * Parameters. 638 * src : pointer to the source data 639 * dst : pointer to destination data 640 * srcPitch : pitch of the srcdata 641 * dstPitch : pitch of the destination data 642 * h & w : height and width of source data 643 * 644 * Returns :None 645 * 646 * Comments :None 647 *---------------------------------------------------------------------------- 648 */ 649static void 650GXCopyData420(unsigned char *src, unsigned char *dst, 651 int srcPitch, int dstPitch, int h, int w) 652{ 653 while (h--) { 654 memcpy(dst, src, w); 655 src += srcPitch; 656 dst += dstPitch; 657 } 658} 659 660/*---------------------------------------------------------------------------- 661 * GXCopyData422 662 * 663 * Description : Copies data from src to destination 664 * 665 * Parameters. 666 * src : pointer to the source data 667 * dst : pointer to destination data 668 * srcPitch : pitch of the srcdata 669 * dstPitch : pitch of the destination data 670 * h & w : height and width of source data 671 * 672 * Returns :None 673 * 674 * Comments :None 675 *---------------------------------------------------------------------------- 676 */ 677static void 678GXCopyData422(unsigned char *src, unsigned char *dst, 679 int srcPitch, int dstPitch, int h, int w) 680{ 681 w <<= 1; 682 while (h--) { 683 memcpy(dst, src, w); 684 src += srcPitch; 685 dst += dstPitch; 686 } 687} 688 689#ifdef XF86EXA 690static void 691GXVideoSave(ScreenPtr pScreen, ExaOffscreenArea * area) 692{ 693 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScreen); 694 GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni); 695 696 if (area == pPriv->area) 697 pPriv->area = NULL; 698} 699#endif 700 701static int 702GXAllocateMemory(ScrnInfoPtr pScrni, void **memp, int numlines) 703{ 704 ScreenPtr pScrn = xf86ScrnToScreen(pScrni); 705 GeodeRec *pGeode = GEODEPTR(pScrni); 706 707 //long displayWidth = pGeode->Pitch / ((pScrni->bitsPerPixel + 7) / 8); 708 int size = numlines * pGeode->displayWidth; 709 710#if XF86EXA 711 if (pGeode->useEXA) { 712 ExaOffscreenArea *area = *memp; 713 714 if (area != NULL) { 715 if (area->size >= size) 716 return area->offset; 717 718 exaOffscreenFree(pScrni->pScreen, area); 719 } 720 721 area = exaOffscreenAlloc(pScrni->pScreen, size, 16, 722 TRUE, GXVideoSave, NULL); 723 *memp = area; 724 725 return area == NULL ? 0 : area->offset; 726 } 727#endif 728 729 if (!pGeode->useEXA) { 730 FBAreaPtr area = *memp; 731 FBAreaPtr new_area; 732 733 if (area) { 734 if ((area->box.y2 - area->box.y1) >= numlines) 735 return (area->box.y1 * pGeode->Pitch); 736 737 if (xf86ResizeOffscreenArea(area, pGeode->displayWidth, numlines)) 738 return (area->box.y1 * pGeode->Pitch); 739 740 xf86FreeOffscreenArea(area); 741 } 742 743 new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth, 744 numlines, 0, NULL, NULL, NULL); 745 746 if (!new_area) { 747 int max_w, max_h; 748 749 xf86QueryLargestOffscreenArea(pScrn, &max_w, &max_h, 0, 750 FAVOR_WIDTH_THEN_AREA, 751 PRIORITY_EXTREME); 752 753 if ((max_w < pGeode->displayWidth) || (max_h < numlines)) { 754 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 755 "No room - how sad %x, %x, %x, %x\n", max_w, 756 pGeode->displayWidth, max_h, numlines); 757 return 0; 758 } 759 760 xf86PurgeUnlockedOffscreenAreas(pScrn); 761 new_area = xf86AllocateOffscreenArea(pScrn, pGeode->displayWidth, 762 numlines, 0, NULL, NULL, NULL); 763 } 764 765 return (new_area->box.y1 * pGeode->Pitch); 766 } 767 768 return 0; 769} 770 771static BoxRec dstBox; 772static int srcPitch = 0, srcPitch2 = 0, dstPitch = 0, dstPitch2 = 0; 773static INT32 Bx1, Bx2, By1, By2; 774static int top, left, npixels, nlines; 775static int offset, s1offset = 0, s2offset = 0, s3offset = 0; 776static unsigned char *dst_start; 777static int d2offset = 0, d3offset = 0; 778 779#if 0 780static Bool 781RegionsIntersect(BoxPtr pRcl1, BoxPtr pRcl2, BoxPtr pRclResult) 782{ 783 pRclResult->x1 = max(pRcl1->x1, pRcl2->x1); 784 pRclResult->x2 = min(pRcl1->x2, pRcl2->x2); 785 786 if (pRclResult->x1 <= pRclResult->x2) { 787 pRclResult->y1 = max(pRcl1->y1, pRcl2->y1); 788 pRclResult->y2 = min(pRcl1->y2, pRcl2->y2); 789 790 if (pRclResult->y1 <= pRclResult->y2) { 791 return (TRUE); 792 } 793 } 794 795 return (FALSE); 796} 797#endif 798 799void 800GXSetVideoPosition(int x, int y, int width, int height, 801 short src_w, short src_h, short drw_w, short drw_h, 802 int id, int offset, ScrnInfoPtr pScrni) 803{ 804 GeodeRec *pGeode = GEODEPTR(pScrni); 805 long ystart, xend, yend; 806 unsigned long lines = 0; 807 unsigned long y_extra, uv_extra = 0; 808 unsigned long startAddress; 809 810#if 0 811 BoxRec ovly, display, result; 812#endif 813 814 xend = x + drw_w; 815 yend = y + drw_h; 816 817 /* Take care of panning when panel is present */ 818 819 startAddress = gfx_get_display_offset(); 820 DeltaY = startAddress / pGeode->Pitch; 821 DeltaX = startAddress & (pGeode->Pitch - 1); 822 DeltaX /= (pScrni->bitsPerPixel >> 3); 823 824#if 0 825 /* Thhis code is pretty dang broken - comment it out for now */ 826 827 if (pGeode->Panel) { 828 ovly.x1 = x; 829 ovly.x2 = x + pGeode->video_dstw; 830 ovly.y1 = y; 831 ovly.y2 = y + pGeode->video_dsth; 832 833 display.x1 = DeltaX; 834 display.x2 = DeltaX + pGeode->FPBX; 835 display.y1 = DeltaY; 836 display.y2 = DeltaY + pGeode->FPBY; 837 x = xend = 0; 838 if (RegionsIntersect(&display, &ovly, &result)) { 839 x = ovly.x1 - DeltaX; 840 xend = ovly.x2 - DeltaX; 841 y = ovly.y1 - DeltaY; 842 yend = ovly.y2 - DeltaY; 843 } 844 } 845#endif 846 847 /* TOP CLIPPING */ 848 849 if (y < 0) { 850 if (src_h < drw_h) 851 lines = (-y) * src_h / drw_h; 852 else 853 lines = (-y); 854 ystart = 0; 855 drw_h += y; 856 y_extra = lines * dstPitch; 857 uv_extra = (lines >> 1) * (dstPitch2); 858 } 859 else { 860 ystart = y; 861 lines = 0; 862 y_extra = 0; 863 } 864 865 GFX(set_video_window(x, ystart, xend - x, yend - ystart)); 866 867 if ((id == FOURCC_Y800) || (id == FOURCC_I420) || (id == FOURCC_YV12)) { 868 GFX(set_video_yuv_offsets(offset + y_extra, 869 offset + d3offset + uv_extra, 870 offset + d2offset + uv_extra)); 871 } 872 else { 873 GFX(set_video_offset(offset + y_extra)); 874 } 875} 876 877/*---------------------------------------------------------------------------- 878 * GXDisplayVideo 879 * 880 * Description :This function sets up the video registers for playing video 881 * It sets up the video format,width, height & position of the 882 * video window ,video offsets( y,u,v) and video pitches(y,u,v) 883 * 884 * Parameters 885 * 886 * Returns :None 887 * 888 * Comments :None 889 *---------------------------------------------------------------------------- 890 */ 891 892static void 893GXDisplayVideo(ScrnInfoPtr pScrni, 894 int id, 895 int offset, 896 short width, short height, 897 int pitch, 898 int x1, int y1, int x2, int y2, 899 BoxPtr dstBox, short src_w, short src_h, short drw_w, 900 short drw_h) 901{ 902 GeodeRec *pGeode = GEODEPTR(pScrni); 903 unsigned long dcfg, misc; 904 905 GXAccelSync(pScrni); 906 907 /* If the gamma LUT is already loaded with graphics data, then save it 908 * off 909 */ 910 911 if (id != FOURCC_RGB565) { 912 dcfg = gfx_read_vid32(DISPLAY_CONFIG); 913 misc = gfx_read_vid32(MISC); 914 915 lutflag = (!(misc & 1) && (dcfg & (1 << 21))); 916 917 if (lutflag) 918 get_gamma_ram(graphics_lut); 919 920 /* Set the video gamma ram */ 921 GFX(set_video_palette(NULL)); 922 } 923 924 GFX(set_video_enable(1)); 925 926 switch (id) { 927 case FOURCC_UYVY: /* UYVY */ 928 GFX(set_video_format(VIDEO_FORMAT_UYVY)); 929 GFX(set_video_size(width, height)); 930 break; 931 case FOURCC_Y800: /* Y800 - greyscale - we munge it! */ 932 case FOURCC_YV12: /* YV12 */ 933 case FOURCC_I420: /* I420 */ 934 GFX(set_video_format(VIDEO_FORMAT_Y0Y1Y2Y3)); 935 GFX(set_video_size(width, height)); 936 GFX(set_video_yuv_pitch(dstPitch, dstPitch2)); 937 break; 938 case FOURCC_YUY2: /* YUY2 */ 939 GFX(set_video_format(VIDEO_FORMAT_YUYV)); 940 GFX(set_video_size(width, height)); 941 break; 942 case FOURCC_Y2YU: /* Y2YU */ 943 GFX(set_video_format(VIDEO_FORMAT_Y2YU)); 944 GFX(set_video_size(width, height)); 945 break; 946 case FOURCC_YVYU: /* YVYU */ 947 GFX(set_video_format(VIDEO_FORMAT_YVYU)); 948 GFX(set_video_size(width, height)); 949 break; 950 case FOURCC_RGB565: 951 GFX(set_video_format(VIDEO_FORMAT_RGB)); 952 GFX(set_video_size(width, height)); 953 break; 954 955 } 956 957 if (pGeode->Panel) { 958 pGeode->video_x = dstBox->x1; 959 pGeode->video_y = dstBox->y1; 960 pGeode->video_w = width; 961 pGeode->video_h = height; 962 pGeode->video_srcw = src_w; 963 pGeode->video_srch = src_h; 964 pGeode->video_dstw = drw_w; 965 pGeode->video_dsth = drw_h; 966 pGeode->video_offset = offset; 967 pGeode->video_id = id; 968 pGeode->video_scrnptr = pScrni; 969 } 970 971 if ((drw_w >= src_w) && (drw_h >= src_h)) 972 GFX(set_video_scale(width, height, drw_w, drw_h)); 973 else if (drw_w < src_w) 974 GFX(set_video_scale(drw_w, height, drw_w, drw_h)); 975 else if (drw_h < src_h) 976 GFX(set_video_scale(width, drw_h, drw_w, drw_h)); 977 978 GXSetVideoPosition(dstBox->x1, dstBox->y1, width, height, src_w, 979 src_h, drw_w, drw_h, id, offset, pScrni); 980} 981 982/* Used by LX as well */ 983 984Bool 985RegionsEqual(RegionPtr A, RegionPtr B) 986{ 987 int *dataA, *dataB; 988 int num; 989 990 num = REGION_NUM_RECTS(A); 991 if (num != REGION_NUM_RECTS(B)) { 992 return FALSE; 993 } 994 995 if ((A->extents.x1 != B->extents.x1) || 996 (A->extents.x2 != B->extents.x2) || 997 (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2)) 998 return FALSE; 999 1000 dataA = (int *) REGION_RECTS(A); 1001 dataB = (int *) REGION_RECTS(B); 1002 1003 while (num--) { 1004 if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) 1005 return FALSE; 1006 1007 dataA += 2; 1008 dataB += 2; 1009 } 1010 1011 return TRUE; 1012} 1013 1014/*---------------------------------------------------------------------------- 1015 * GXPutImage :This function writes a single frame of video into a 1016 * drawable. The position and size of the source rectangle is 1017 * specified by src_x,src_y, src_w and src_h. This data is 1018 * stored in a system memory buffer at buf. The position and 1019 * size of the destination rectangle is specified by drw_x, 1020 * drw_y,drw_w,drw_h.The data is in the format indicated by the 1021 * image descriptor and represents a source of size width by 1022 * height. If sync is TRUE the driver should not return from 1023 * this function until it is through reading the data from buf. 1024 * Returning when sync is TRUE indicates that it is safe for the 1025 * data at buf to be replaced,freed, or modified. 1026 * 1027 * Parameters. 1028 * 1029 * Returns :None 1030 * 1031 * Comments :None 1032 *---------------------------------------------------------------------------- 1033 */ 1034 1035static int 1036GXPutImage(ScrnInfoPtr pScrni, 1037 short src_x, short src_y, 1038 short drw_x, short drw_y, 1039 short src_w, short src_h, 1040 short drw_w, short drw_h, 1041 int id, unsigned char *buf, 1042 short width, short height, Bool sync, RegionPtr clipBoxes, 1043 pointer data, DrawablePtr pDraw) 1044{ 1045 GeodePortPrivRec *pPriv = (GeodePortPrivRec *) data; 1046 GeodeRec *pGeode = GEODEPTR(pScrni); 1047 int new_h; 1048 1049#if REINIT 1050 BOOL ReInitVideo = FALSE; 1051 static BOOL DoReinitAgain = 0; 1052#endif 1053 1054#if XV_PROFILE 1055 long oldtime, newtime; 1056 1057 UpdateCurrentTime(); 1058 oldtime = currentTime.milliseconds; 1059#endif 1060 1061#if REINIT 1062/* update cliplist */ 1063 if (!RegionsEqual(&pPriv->clip, clipBoxes)) { 1064 ReInitVideo = TRUE; 1065 } 1066 1067 if (DoReinitAgain) 1068 ReInitVideo = TRUE; 1069 1070 if (ReInitVideo) { 1071 DEBUGMSG(1, (0, X_NONE, "Regional Not Equal - Init\n")); 1072#endif 1073 DoReinitAgain = ~DoReinitAgain; 1074 if (drw_w > 16384) 1075 drw_w = 16384; 1076 1077 /* Clip */ 1078 Bx1 = src_x; 1079 Bx2 = src_x + src_w; 1080 By1 = src_y; 1081 By2 = src_y + src_h; 1082 1083 if ((Bx1 >= Bx2) || (By1 >= By2)) 1084 return Success; 1085 1086 dstBox.x1 = drw_x; 1087 dstBox.x2 = drw_x + drw_w; 1088 dstBox.y1 = drw_y; 1089 dstBox.y2 = drw_y + drw_h; 1090 1091 dstBox.x1 -= pScrni->frameX0; 1092 dstBox.x2 -= pScrni->frameX0; 1093 dstBox.y1 -= pScrni->frameY0; 1094 dstBox.y2 -= pScrni->frameY0; 1095 1096 switch (id) { 1097 case FOURCC_YV12: 1098 case FOURCC_I420: 1099 srcPitch = (width + 3) & ~3; /* of luma */ 1100 dstPitch = (width + 31) & ~31; 1101 1102 s2offset = srcPitch * height; 1103 d2offset = dstPitch * height; 1104 1105 srcPitch2 = ((width >> 1) + 3) & ~3; 1106 dstPitch2 = ((width >> 1) + 15) & ~15; 1107 1108 s3offset = (srcPitch2 * (height >> 1)) + s2offset; 1109 d3offset = (dstPitch2 * (height >> 1)) + d2offset; 1110 1111 new_h = dstPitch * height; /* Y */ 1112 new_h += (dstPitch2 * height); /* U+V */ 1113 new_h += pGeode->Pitch - 1; 1114 new_h /= pGeode->Pitch; 1115 break; 1116 case FOURCC_UYVY: 1117 case FOURCC_YUY2: 1118 case FOURCC_Y800: 1119 case FOURCC_RGB565: 1120 default: 1121 dstPitch = ((width << 1) + 3) & ~3; 1122 srcPitch = (width << 1); 1123 new_h = ((dstPitch * height) + pGeode->Pitch - 1) / pGeode->Pitch; 1124 break; 1125 } 1126#if DBUF 1127 if (pPriv->doubleBuffer) 1128 new_h <<= 1; 1129#endif 1130 1131 if (!(pPriv->offset = GXAllocateMemory(pScrni, &pPriv->area, new_h))) { 1132 xf86DrvMsg(pScrni->scrnIndex, X_ERROR, 1133 "Could not allocate area of size %d\n", new_h); 1134 return BadAlloc; 1135 } 1136 1137 /* copy data */ 1138 top = By1; 1139 left = Bx1 & ~1; 1140 npixels = ((Bx2 + 1) & ~1) - left; 1141 1142 switch (id) { 1143 case FOURCC_YV12: 1144 case FOURCC_I420: 1145 { 1146 int tmp; 1147 1148 top &= ~1; 1149 1150 offset = pPriv->offset + (top * dstPitch); 1151 1152#if DBUF 1153 if (pPriv->doubleBuffer && pPriv->currentBuffer) 1154 offset += (new_h >> 1) * pGeode->Pitch; 1155#endif 1156 dst_start = pGeode->FBBase + offset + left; 1157 tmp = ((top >> 1) * srcPitch2) + (left >> 1); 1158 s2offset += tmp; 1159 s3offset += tmp; 1160 if (id == FOURCC_I420) { 1161 tmp = s2offset; 1162 s2offset = s3offset; 1163 s3offset = tmp; 1164 } 1165 nlines = ((By2 + 1) & ~1) - top; 1166 } 1167 break; 1168 case FOURCC_UYVY: 1169 case FOURCC_YUY2: 1170 case FOURCC_Y800: 1171 case FOURCC_RGB565: 1172 default: 1173 left <<= 1; 1174 buf += (top * srcPitch) + left; 1175 nlines = By2 - top; 1176 offset = (pPriv->offset) + (top * dstPitch); 1177 1178#if DBUF 1179 if (pPriv->doubleBuffer && pPriv->currentBuffer) 1180 offset += (new_h >> 1) * pGeode->Pitch; 1181#endif 1182 dst_start = pGeode->FBBase + offset + left; 1183 break; 1184 } 1185 s1offset = (top * srcPitch) + left; 1186#if REINIT 1187 /* update cliplist */ 1188 REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes); 1189 1190 if (pPriv->colorKeyMode == 0) { 1191 xf86XVFillKeyHelper(pScrni->pScreen, pPriv->colorKey, clipBoxes); 1192 } 1193 1194 GXDisplayVideo(pScrni, id, offset, width, height, dstPitch, 1195 Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h); 1196 } 1197#endif 1198 switch (id) { 1199 case FOURCC_Y800: 1200 /* This is shared between LX and GX, so it lives in amd_common.c */ 1201 GeodeCopyGreyscale(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1202 break; 1203 case FOURCC_YV12: 1204 case FOURCC_I420: 1205 GXCopyData420(buf + s1offset, dst_start, srcPitch, dstPitch, nlines, 1206 npixels); 1207 GXCopyData420(buf + s2offset, dst_start + d2offset, srcPitch2, 1208 dstPitch2, nlines >> 1, npixels >> 1); 1209 GXCopyData420(buf + s3offset, dst_start + d3offset, srcPitch2, 1210 dstPitch2, nlines >> 1, npixels >> 1); 1211 break; 1212 case FOURCC_UYVY: 1213 case FOURCC_YUY2: 1214 case FOURCC_RGB565: 1215 default: 1216 GXCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels); 1217 break; 1218 } 1219#if !REINIT 1220 /* update cliplist */ 1221 REGION_COPY(pScrni->pScreen, &pPriv->clip, clipBoxes); 1222 if (pPriv->colorKeyMode == 0) { 1223 /* draw these */ 1224 XAAFillSolidRects(pScrni, pPriv->colorKey, GXcopy, ~0, 1225 REGION_NUM_RECTS(clipBoxes), REGION_RECTS(clipBoxes)); 1226 } 1227 1228 GXDisplayVideo(pScrni, id, offset, width, height, dstPitch, 1229 Bx1, By1, Bx2, By2, &dstBox, src_w, src_h, drw_w, drw_h); 1230#endif 1231 1232#if XV_PROFILE 1233 UpdateCurrentTime(); 1234 newtime = currentTime.milliseconds; 1235 DEBUGMSG(1, (0, X_NONE, "PI %d\n", newtime - oldtime)); 1236#endif 1237 1238#if DBUF 1239 pPriv->currentBuffer ^= 1; 1240#endif 1241 1242 pPriv->videoStatus = CLIENT_VIDEO_ON; 1243 pGeode->OverlayON = TRUE; 1244 return Success; 1245} 1246 1247/*---------------------------------------------------------------------------- 1248 * GXQueryImageAttributes 1249 * 1250 * Description :This function is called to let the driver specify how data 1251 * for a particular image of size width by height should be 1252 * stored. 1253 * 1254 * Parameters. 1255 * pScrni :Screen handler pointer having screen information. 1256 * id :Id for the video format 1257 * width :width of the image (can be modified by the driver) 1258 * height :height of the image (can be modified by the driver) 1259 * Returns : Size of the memory required for storing this image 1260 * 1261 * Comments :None 1262 * 1263 *---------------------------------------------------------------------------- 1264 */ 1265 1266int 1267GeodeQueryImageAttributes(ScrnInfoPtr pScrni, 1268 int id, unsigned short *w, unsigned short *h, 1269 int *pitches, int *offsets) 1270{ 1271 int size; 1272 int tmp; 1273 1274 DEBUGMSG(0, (0, X_NONE, "QueryImageAttributes %X\n", id)); 1275 1276 if (*w > 1024) 1277 *w = 1024; 1278 if (*h > 1024) 1279 *h = 1024; 1280 1281 *w = (*w + 1) & ~1; 1282 if (offsets) 1283 offsets[0] = 0; 1284 1285 switch (id) { 1286 case FOURCC_YV12: 1287 case FOURCC_I420: 1288 *h = (*h + 1) & ~1; 1289 size = (*w + 3) & ~3; 1290 if (pitches) 1291 pitches[0] = size; 1292 1293 size *= *h; 1294 if (offsets) 1295 offsets[1] = size; 1296 1297 tmp = ((*w >> 1) + 3) & ~3; 1298 if (pitches) 1299 pitches[1] = pitches[2] = tmp; 1300 1301 tmp *= (*h >> 1); 1302 size += tmp; 1303 if (offsets) 1304 offsets[2] = size; 1305 1306 size += tmp; 1307 break; 1308 case FOURCC_UYVY: 1309 case FOURCC_YUY2: 1310 case FOURCC_Y800: 1311 default: 1312 size = *w << 1; 1313 if (pitches) 1314 pitches[0] = size; 1315 1316 size *= *h; 1317 break; 1318 } 1319 return size; 1320} 1321 1322static void 1323GXBlockHandler(BLOCKHANDLER_ARGS_DECL) 1324{ 1325 SCREEN_PTR(arg); 1326 ScrnInfoPtr pScrni = xf86ScreenToScrn(pScrn); 1327 GeodeRec *pGeode = GEODEPTR(pScrni); 1328 GeodePortPrivRec *pPriv = GET_PORT_PRIVATE(pScrni); 1329 1330 pScrn->BlockHandler = pGeode->BlockHandler; 1331 (*pScrn->BlockHandler) (BLOCKHANDLER_ARGS); 1332 pScrn->BlockHandler = GXBlockHandler; 1333 1334 if (pPriv->videoStatus & TIMER_MASK) { 1335 GXAccelSync(pScrni); 1336 UpdateCurrentTime(); 1337 if (pPriv->videoStatus & OFF_TIMER) { 1338 if (pPriv->offTime < currentTime.milliseconds) { 1339 GFX(set_video_enable(0)); 1340 1341 /* If we have saved graphics LUT data - restore it */ 1342 /* Otherwise, turn bypass on */ 1343 1344 if (lutflag) 1345 GFX(set_graphics_palette(graphics_lut)); 1346 else 1347 GFX(set_video_palette_bypass(1)); 1348 1349 lutflag = 0; 1350 1351 pPriv->videoStatus = FREE_TIMER; 1352 pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1353 } 1354 } 1355 else { /* FREE_TIMER */ 1356 if (pPriv->freeTime < currentTime.milliseconds) { 1357 1358 if (pPriv->area) { 1359#ifdef XF86EXA 1360 if (pGeode->useEXA) 1361 exaOffscreenFree(pScrn, pPriv->area); 1362#endif 1363 if (!pGeode->useEXA) 1364 xf86FreeOffscreenArea(pPriv->area); 1365 1366 pPriv->area = NULL; 1367 } 1368 1369 pPriv->videoStatus = 0; 1370 } 1371 } 1372 } 1373} 1374 1375/****************** Offscreen stuff ***************/ 1376 1377typedef struct { 1378 void *area; 1379 int offset; 1380 Bool isOn; 1381} OffscreenPrivRec, *OffscreenPrivPtr; 1382 1383/*---------------------------------------------------------------------------- 1384 * GXAllocateSurface 1385 * 1386 * Description :This function allocates an area of w by h in the offscreen 1387 * 1388 * Parameters. 1389 * pScrni :Screen handler pointer having screen information. 1390 * 1391 * Returns :None 1392 * 1393 * Comments :None 1394 *---------------------------------------------------------------------------- 1395 */ 1396static int 1397GXAllocateSurface(ScrnInfoPtr pScrni, 1398 int id, unsigned short w, unsigned short h, 1399 XF86SurfacePtr surface) 1400{ 1401 void *area = NULL; 1402 int pitch, fbpitch, numlines; 1403 OffscreenPrivRec *pPriv; 1404 1405 if ((w > 1024) || (h > 1024)) 1406 return BadAlloc; 1407 1408 w = (w + 1) & ~1; 1409 pitch = ((w << 1) + 15) & ~15; 1410 fbpitch = pScrni->bitsPerPixel * pScrni->displayWidth >> 3; 1411 numlines = ((pitch * h) + fbpitch - 1) / fbpitch; 1412 1413 if (!(offset = GXAllocateMemory(pScrni, &area, numlines))) 1414 return BadAlloc; 1415 1416 surface->width = w; 1417 surface->height = h; 1418 1419 if (!(surface->pitches = malloc(sizeof(int)))) 1420 return BadAlloc; 1421 1422 if (!(surface->offsets = malloc(sizeof(int)))) { 1423 free(surface->pitches); 1424 return BadAlloc; 1425 } 1426 1427 if (!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { 1428 free(surface->pitches); 1429 free(surface->offsets); 1430 return BadAlloc; 1431 } 1432 1433 pPriv->area = area; 1434 pPriv->offset = offset; 1435 1436 pPriv->isOn = FALSE; 1437 1438 surface->pScrn = pScrni; 1439 surface->id = id; 1440 surface->pitches[0] = pitch; 1441 surface->offsets[0] = offset; 1442 surface->devPrivate.ptr = (pointer) pPriv; 1443 1444 return Success; 1445} 1446 1447static int 1448GXStopSurface(XF86SurfacePtr surface) 1449{ 1450 OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr; 1451 1452 if (pPriv->isOn) { 1453 pPriv->isOn = FALSE; 1454 } 1455 1456 return Success; 1457} 1458 1459static int 1460GXFreeSurface(XF86SurfacePtr surface) 1461{ 1462 OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr; 1463 1464 if (pPriv->isOn) 1465 GXStopSurface(surface); 1466 1467 xf86FreeOffscreenArea(pPriv->area); 1468 free(surface->pitches); 1469 free(surface->offsets); 1470 free(surface->devPrivate.ptr); 1471 1472 return Success; 1473} 1474 1475static int 1476GXGetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 *value) 1477{ 1478 return GXGetPortAttribute(pScrni, attribute, value, 1479 (pointer) (GET_PORT_PRIVATE(pScrni))); 1480} 1481 1482static int 1483GXSetSurfaceAttribute(ScrnInfoPtr pScrni, Atom attribute, INT32 value) 1484{ 1485 return GXSetPortAttribute(pScrni, attribute, value, 1486 (pointer) (GET_PORT_PRIVATE(pScrni))); 1487} 1488 1489static int 1490GXDisplaySurface(XF86SurfacePtr surface, 1491 short src_x, short src_y, 1492 short drw_x, short drw_y, 1493 short src_w, short src_h, short drw_w, short drw_h, 1494 RegionPtr clipBoxes) 1495{ 1496 OffscreenPrivRec *pPriv = (OffscreenPrivRec *) surface->devPrivate.ptr; 1497 ScrnInfoPtr pScrni = surface->pScrn; 1498 GeodePortPrivRec *portPriv = GET_PORT_PRIVATE(pScrni); 1499 INT32 x1, y1, x2, y2; 1500 BoxRec dstBox; 1501 1502 DEBUGMSG(0, (0, X_NONE, "DisplaySuface\n")); 1503 x1 = src_x; 1504 x2 = src_x + src_w; 1505 y1 = src_y; 1506 y2 = src_y + src_h; 1507 1508 dstBox.x1 = drw_x; 1509 dstBox.x2 = drw_x + drw_w; 1510 dstBox.y1 = drw_y; 1511 dstBox.y2 = drw_y + drw_h; 1512 1513 if ((x1 >= x2) || (y1 >= y2)) 1514 return Success; 1515 1516 dstBox.x1 -= pScrni->frameX0; 1517 dstBox.x2 -= pScrni->frameX0; 1518 dstBox.y1 -= pScrni->frameY0; 1519 dstBox.y2 -= pScrni->frameY0; 1520 1521 xf86XVFillKeyHelper(pScrni->pScreen, portPriv->colorKey, clipBoxes); 1522 1523 GXDisplayVideo(pScrni, surface->id, surface->offsets[0], 1524 surface->width, surface->height, surface->pitches[0], 1525 x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); 1526 1527 pPriv->isOn = TRUE; 1528 if (portPriv->videoStatus & CLIENT_VIDEO_ON) { 1529 REGION_EMPTY(pScrni->pScreen, &portPriv->clip); 1530 UpdateCurrentTime(); 1531 portPriv->videoStatus = FREE_TIMER; 1532 portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; 1533 } 1534 1535 return Success; 1536} 1537 1538/*---------------------------------------------------------------------------- 1539 * GXInitOffscreenImages 1540 * 1541 * Description :This function sets up the offscreen memory management. It 1542 * fills in the XF86OffscreenImagePtr structure with functions to 1543 * handle offscreen memory operations. 1544 * 1545 * Parameters. 1546 * pScrn :Screen handler pointer having screen information. 1547 * 1548 * Returns : None 1549 * 1550 * Comments :None 1551 *---------------------------------------------------------------------------- 1552 */ 1553static void 1554GXInitOffscreenImages(ScreenPtr pScrn) 1555{ 1556 XF86OffscreenImagePtr offscreenImages; 1557 1558 /* need to free this someplace */ 1559 if (!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) 1560 return; 1561 1562 offscreenImages[0].image = &Images[0]; 1563 offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 1564 offscreenImages[0].alloc_surface = GXAllocateSurface; 1565 offscreenImages[0].free_surface = GXFreeSurface; 1566 offscreenImages[0].display = GXDisplaySurface; 1567 offscreenImages[0].stop = GXStopSurface; 1568 offscreenImages[0].setAttribute = GXSetSurfaceAttribute; 1569 offscreenImages[0].getAttribute = GXGetSurfaceAttribute; 1570 offscreenImages[0].max_width = 1024; 1571 offscreenImages[0].max_height = 1024; 1572 offscreenImages[0].num_attributes = NUM_ATTRIBUTES; 1573 offscreenImages[0].attributes = Attributes; 1574 1575 xf86XVRegisterOffscreenImages(pScrn, offscreenImages, 1); 1576} 1577 1578#endif /* !XvExtension */ 1579