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