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