exa.c revision 05b261ec
1/* 2 * Copyright � 2001 Keith Packard 3 * 4 * Partly based on code that is Copyright � The XFree86 Project Inc. 5 * 6 * Permission to use, copy, modify, distribute, and sell this software and its 7 * documentation for any purpose is hereby granted without fee, provided that 8 * the above copyright notice appear in all copies and that both that 9 * copyright notice and this permission notice appear in supporting 10 * documentation, and that the name of Keith Packard not be used in 11 * advertising or publicity pertaining to distribution of the software without 12 * specific, written prior permission. Keith Packard makes no 13 * representations about the suitability of this software for any purpose. It 14 * is provided "as is" without express or implied warranty. 15 * 16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 * PERFORMANCE OF THIS SOFTWARE. 23 */ 24 25/** @file 26 * This file covers the initialization and teardown of EXA, and has various 27 * functions not responsible for performing rendering, pixmap migration, or 28 * memory management. 29 */ 30 31#ifdef HAVE_DIX_CONFIG_H 32#include <dix-config.h> 33#endif 34 35#ifdef MITSHM 36#include "shmint.h" 37#endif 38 39#include <stdlib.h> 40 41#include "exa_priv.h" 42#include <X11/fonts/fontstruct.h> 43#include "dixfontstr.h" 44#include "exa.h" 45#include "cw.h" 46 47static int exaGeneration; 48int exaScreenPrivateIndex; 49int exaPixmapPrivateIndex; 50 51/** 52 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of 53 * the beginning of the given pixmap. 54 * 55 * Note that drivers are free to, and often do, munge this offset as necessary 56 * for handing to the hardware -- for example, translating it into a different 57 * aperture. This function may need to be extended in the future if we grow 58 * support for having multiple card-accessible offscreen, such as an AGP memory 59 * pool alongside the framebuffer pool. 60 */ 61unsigned long 62exaGetPixmapOffset(PixmapPtr pPix) 63{ 64 ExaScreenPriv (pPix->drawable.pScreen); 65 ExaPixmapPriv (pPix); 66 void *ptr; 67 68 /* Return the offscreen pointer if we've hidden the data. */ 69 if (pPix->devPrivate.ptr == NULL) 70 ptr = pExaPixmap->fb_ptr; 71 else 72 ptr = pPix->devPrivate.ptr; 73 74 return ((unsigned long)ptr - (unsigned long)pExaScr->info->memoryBase); 75} 76 77/** 78 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. 79 * 80 * This is a helper to make driver code more obvious, due to the rather obscure 81 * naming of the pitch field in the pixmap. 82 */ 83unsigned long 84exaGetPixmapPitch(PixmapPtr pPix) 85{ 86 return pPix->devKind; 87} 88 89/** 90 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video 91 * memory. Only valid when the pixmap is currently in framebuffer. 92 */ 93unsigned long 94exaGetPixmapSize(PixmapPtr pPix) 95{ 96 ExaPixmapPrivPtr pExaPixmap; 97 98 pExaPixmap = ExaGetPixmapPriv(pPix); 99 if (pExaPixmap != NULL) 100 return pExaPixmap->fb_size; 101 return 0; 102} 103 104/** 105 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. 106 * 107 * @param pDrawable the drawable being requested. 108 * 109 * This function returns the backing pixmap for a drawable, whether it is a 110 * redirected window, unredirected window, or already a pixmap. Note that 111 * coordinate translation is needed when drawing to the backing pixmap of a 112 * redirected window, and the translation coordinates are provided by calling 113 * exaGetOffscreenPixmap() on the drawable. 114 */ 115PixmapPtr 116exaGetDrawablePixmap(DrawablePtr pDrawable) 117{ 118 if (pDrawable->type == DRAWABLE_WINDOW) 119 return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable); 120 else 121 return (PixmapPtr) pDrawable; 122} 123 124/** 125 * Sets the offsets to add to coordinates to make them address the same bits in 126 * the backing drawable. These coordinates are nonzero only for redirected 127 * windows. 128 */ 129void 130exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, 131 int *xp, int *yp) 132{ 133#ifdef COMPOSITE 134 if (pDrawable->type == DRAWABLE_WINDOW) { 135 *xp = -pPixmap->screen_x; 136 *yp = -pPixmap->screen_y; 137 return; 138 } 139#endif 140 141 *xp = 0; 142 *yp = 0; 143} 144 145/** 146 * exaPixmapDirty() marks a pixmap as dirty, allowing for 147 * optimizations in pixmap migration when no changes have occurred. 148 */ 149void 150exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) 151{ 152 ExaPixmapPriv(pPix); 153 BoxRec box; 154 RegionPtr pDamageReg; 155 RegionRec region; 156 157 if (!pExaPixmap) 158 return; 159 160 box.x1 = max(x1, 0); 161 box.y1 = max(y1, 0); 162 box.x2 = min(x2, pPix->drawable.width); 163 box.y2 = min(y2, pPix->drawable.height); 164 165 if (box.x1 >= box.x2 || box.y1 >= box.y2) 166 return; 167 168 pDamageReg = DamageRegion(pExaPixmap->pDamage); 169 170 REGION_INIT(pScreen, ®ion, &box, 1); 171 REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); 172 REGION_UNINIT(pScreen, ®ion); 173} 174 175static Bool 176exaDestroyPixmap (PixmapPtr pPixmap) 177{ 178 if (pPixmap->refcnt == 1) 179 { 180 ExaPixmapPriv (pPixmap); 181 if (pExaPixmap->area) 182 { 183 DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", 184 (void*)pPixmap->drawable.id, 185 ExaGetPixmapPriv(pPixmap)->area->offset, 186 pPixmap->drawable.width, 187 pPixmap->drawable.height)); 188 /* Free the offscreen area */ 189 exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area); 190 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 191 pPixmap->devKind = pExaPixmap->sys_pitch; 192 } 193 REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg); 194 } 195 return fbDestroyPixmap (pPixmap); 196} 197 198static int 199exaLog2(int val) 200{ 201 int bits; 202 203 if (val <= 0) 204 return 0; 205 for (bits = 0; val != 0; bits++) 206 val >>= 1; 207 return bits - 1; 208} 209 210/** 211 * exaCreatePixmap() creates a new pixmap. 212 * 213 * If width and height are 0, this won't be a full-fledged pixmap and it will 214 * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because 215 * ModifyPixmapHeader() would break migration. These types of pixmaps are used 216 * for scratch pixmaps, or to represent the visible screen. 217 */ 218static PixmapPtr 219exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth) 220{ 221 PixmapPtr pPixmap; 222 ExaPixmapPrivPtr pExaPixmap; 223 int bpp; 224 ExaScreenPriv(pScreen); 225 226 if (w > 32767 || h > 32767) 227 return NullPixmap; 228 229 pPixmap = fbCreatePixmap (pScreen, w, h, depth); 230 if (!pPixmap) 231 return NULL; 232 pExaPixmap = ExaGetPixmapPriv(pPixmap); 233 234 bpp = pPixmap->drawable.bitsPerPixel; 235 236 /* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */ 237 if (!w || !h) 238 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 239 else 240 pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; 241 242 pExaPixmap->area = NULL; 243 244 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 245 pExaPixmap->sys_pitch = pPixmap->devKind; 246 247 pExaPixmap->fb_ptr = NULL; 248 if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) 249 pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; 250 else 251 pExaPixmap->fb_pitch = w * bpp / 8; 252 pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, 253 pExaScr->info->pixmapPitchAlign); 254 pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; 255 256 if (pExaPixmap->fb_pitch > 131071) { 257 fbDestroyPixmap(pPixmap); 258 return NULL; 259 } 260 261 /* Set up damage tracking */ 262 pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE, 263 pScreen, pPixmap); 264 265 if (pExaPixmap->pDamage == NULL) { 266 fbDestroyPixmap (pPixmap); 267 return NULL; 268 } 269 270 DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); 271 DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); 272 273 /* None of the pixmap bits are valid initially */ 274 REGION_NULL(pScreen, &pExaPixmap->validReg); 275 276 return pPixmap; 277} 278 279/** 280 * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen 281 * memory, meaning that acceleration could probably be done to it, and that it 282 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 283 * with the CPU. 284 * 285 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 286 * deal with moving pixmaps in and out of system memory), EXA will give drivers 287 * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE. 288 * 289 * @return TRUE if the given drawable is in framebuffer memory. 290 */ 291Bool 292exaPixmapIsOffscreen(PixmapPtr p) 293{ 294 ScreenPtr pScreen = p->drawable.pScreen; 295 ExaScreenPriv(pScreen); 296 297 /* If the devPrivate.ptr is NULL, it's offscreen but we've hidden the data. 298 */ 299 if (p->devPrivate.ptr == NULL) 300 return TRUE; 301 302 if (pExaScr->info->PixmapIsOffscreen) 303 return pExaScr->info->PixmapIsOffscreen(p); 304 305 return ((unsigned long) ((CARD8 *) p->devPrivate.ptr - 306 (CARD8 *) pExaScr->info->memoryBase) < 307 pExaScr->info->memorySize); 308} 309 310/** 311 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen(). 312 */ 313Bool 314exaDrawableIsOffscreen (DrawablePtr pDrawable) 315{ 316 return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable)); 317} 318 319/** 320 * Returns the pixmap which backs a drawable, and the offsets to add to 321 * coordinates to make them address the same bits in the backing drawable. 322 */ 323PixmapPtr 324exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) 325{ 326 PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 327 328 exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp); 329 330 if (exaPixmapIsOffscreen (pPixmap)) 331 return pPixmap; 332 else 333 return NULL; 334} 335 336/** 337 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 338 * 339 * It deals with waiting for synchronization with the card, determining if 340 * PrepareAccess() is necessary, and working around PrepareAccess() failure. 341 */ 342void 343exaPrepareAccess(DrawablePtr pDrawable, int index) 344{ 345 ScreenPtr pScreen = pDrawable->pScreen; 346 ExaScreenPriv (pScreen); 347 PixmapPtr pPixmap; 348 349 pPixmap = exaGetDrawablePixmap (pDrawable); 350 351 if (exaPixmapIsOffscreen (pPixmap)) 352 exaWaitSync (pDrawable->pScreen); 353 else 354 return; 355 356 /* Unhide pixmap pointer */ 357 if (pPixmap->devPrivate.ptr == NULL) { 358 ExaPixmapPriv (pPixmap); 359 360 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 361 } 362 363 if (pExaScr->info->PrepareAccess == NULL) 364 return; 365 366 if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 367 ExaPixmapPriv (pPixmap); 368 if (pExaPixmap->score != EXA_PIXMAP_SCORE_PINNED) 369 FatalError("Driver failed PrepareAccess on a pinned pixmap\n"); 370 exaMoveOutPixmap (pPixmap); 371 } 372} 373 374/** 375 * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. 376 * 377 * It deals with calling the driver's FinishAccess() only if necessary. 378 */ 379void 380exaFinishAccess(DrawablePtr pDrawable, int index) 381{ 382 ScreenPtr pScreen = pDrawable->pScreen; 383 ExaScreenPriv (pScreen); 384 PixmapPtr pPixmap; 385 ExaPixmapPrivPtr pExaPixmap; 386 387 pPixmap = exaGetDrawablePixmap (pDrawable); 388 389 pExaPixmap = ExaGetPixmapPriv(pPixmap); 390 391 /* Rehide pixmap pointer if we're doing that. */ 392 if (pExaPixmap != NULL && pExaScr->hideOffscreenPixmapData && 393 pExaPixmap->fb_ptr == pPixmap->devPrivate.ptr) 394 { 395 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 396 } 397 398 if (pExaScr->info->FinishAccess == NULL) 399 return; 400 401 if (!exaPixmapIsOffscreen (pPixmap)) 402 return; 403 404 (*pExaScr->info->FinishAccess) (pPixmap, index); 405} 406 407/** 408 * exaValidateGC() sets the ops to EXA's implementations, which may be 409 * accelerated or may sync the card and fall back to fb. 410 */ 411static void 412exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 413{ 414 /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 415 * Preempt fbValidateGC by doing its work and masking the change out, so 416 * that we can do the Prepare/FinishAccess. 417 */ 418#ifdef FB_24_32BIT 419 if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { 420 (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); 421 fbGetRotatedPixmap(pGC) = 0; 422 } 423 424 if (pGC->fillStyle == FillTiled) { 425 PixmapPtr pOldTile, pNewTile; 426 427 pOldTile = pGC->tile.pixmap; 428 if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 429 { 430 pNewTile = fbGetRotatedPixmap(pGC); 431 if (!pNewTile || 432 pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 433 { 434 if (pNewTile) 435 (*pGC->pScreen->DestroyPixmap) (pNewTile); 436 /* fb24_32ReformatTile will do direct access of a newly- 437 * allocated pixmap. This isn't a problem yet, since we don't 438 * put pixmaps in FB until at least one accelerated EXA op. 439 */ 440 exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 441 pNewTile = fb24_32ReformatTile (pOldTile, 442 pDrawable->bitsPerPixel); 443 exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); 444 exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 445 } 446 if (pNewTile) 447 { 448 fbGetRotatedPixmap(pGC) = pOldTile; 449 pGC->tile.pixmap = pNewTile; 450 changes |= GCTile; 451 } 452 } 453 } 454#endif 455 if (changes & GCTile) { 456 if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * 457 pDrawable->bitsPerPixel)) 458 { 459 /* XXX This fixes corruption with tiled pixmaps, but may just be a 460 * workaround for broken drivers 461 */ 462 exaMoveOutPixmap(pGC->tile.pixmap); 463 fbPadPixmap (pGC->tile.pixmap); 464 exaPixmapDirty(pGC->tile.pixmap, 0, 0, 465 pGC->tile.pixmap->drawable.width, 466 pGC->tile.pixmap->drawable.height); 467 } 468 /* Mask out the GCTile change notification, now that we've done FB's 469 * job for it. 470 */ 471 changes &= ~GCTile; 472 } 473 474 fbValidateGC (pGC, changes, pDrawable); 475 476 pGC->ops = (GCOps *) &exaOps; 477} 478 479static GCFuncs exaGCFuncs = { 480 exaValidateGC, 481 miChangeGC, 482 miCopyGC, 483 miDestroyGC, 484 miChangeClip, 485 miDestroyClip, 486 miCopyClip 487}; 488 489/** 490 * exaCreateGC makes a new GC and hooks up its funcs handler, so that 491 * exaValidateGC() will get called. 492 */ 493static int 494exaCreateGC (GCPtr pGC) 495{ 496 if (!fbCreateGC (pGC)) 497 return FALSE; 498 499 pGC->funcs = &exaGCFuncs; 500 501 return TRUE; 502} 503 504/** 505 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's 506 * screen private, before calling down to the next CloseSccreen. 507 */ 508static Bool 509exaCloseScreen(int i, ScreenPtr pScreen) 510{ 511 ExaScreenPriv(pScreen); 512#ifdef RENDER 513 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 514#endif 515 516 pScreen->CreateGC = pExaScr->SavedCreateGC; 517 pScreen->CloseScreen = pExaScr->SavedCloseScreen; 518 pScreen->GetImage = pExaScr->SavedGetImage; 519 pScreen->GetSpans = pExaScr->SavedGetSpans; 520 pScreen->PaintWindowBackground = pExaScr->SavedPaintWindowBackground; 521 pScreen->PaintWindowBorder = pExaScr->SavedPaintWindowBorder; 522 pScreen->CreatePixmap = pExaScr->SavedCreatePixmap; 523 pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap; 524 pScreen->CopyWindow = pExaScr->SavedCopyWindow; 525#ifdef RENDER 526 if (ps) { 527 ps->Composite = pExaScr->SavedComposite; 528 ps->Glyphs = pExaScr->SavedGlyphs; 529 ps->Trapezoids = pExaScr->SavedTrapezoids; 530 } 531#endif 532 533 xfree (pExaScr); 534 535 return (*pScreen->CloseScreen) (i, pScreen); 536} 537 538/** 539 * This function allocates a driver structure for EXA drivers to fill in. By 540 * having EXA allocate the structure, the driver structure can be extended 541 * without breaking ABI between EXA and the drivers. The driver's 542 * responsibility is to check beforehand that the EXA module has a matching 543 * major number and sufficient minor. Drivers are responsible for freeing the 544 * driver structure using xfree(). 545 * 546 * @return a newly allocated, zero-filled driver structure 547 */ 548ExaDriverPtr 549exaDriverAlloc(void) 550{ 551 return xcalloc(1, sizeof(ExaDriverRec)); 552} 553 554/** 555 * @param pScreen screen being initialized 556 * @param pScreenInfo EXA driver record 557 * 558 * exaDriverInit sets up EXA given a driver record filled in by the driver. 559 * pScreenInfo should have been allocated by exaDriverAlloc(). See the 560 * comments in _ExaDriver for what must be filled in and what is optional. 561 * 562 * @return TRUE if EXA was successfully initialized. 563 */ 564Bool 565exaDriverInit (ScreenPtr pScreen, 566 ExaDriverPtr pScreenInfo) 567{ 568 ExaScreenPrivPtr pExaScr; 569#ifdef RENDER 570 PictureScreenPtr ps; 571#endif 572 573 if (!pScreenInfo) 574 return FALSE; 575 576 if (!pScreenInfo->memoryBase) { 577 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase must be " 578 "non-zero\n", pScreen->myNum); 579 return FALSE; 580 } 581 582 if (!pScreenInfo->memorySize) { 583 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " 584 "non-zero\n", pScreen->myNum); 585 return FALSE; 586 } 587 588 if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { 589 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must be <= " 590 "ExaDriverRec::memorySize\n", pScreen->myNum); 591 return FALSE; 592 } 593 594 if (!pScreenInfo->PrepareSolid) { 595 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " 596 "non-NULL\n", pScreen->myNum); 597 return FALSE; 598 } 599 600 if (!pScreenInfo->PrepareCopy) { 601 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " 602 "non-NULL\n", pScreen->myNum); 603 return FALSE; 604 } 605 606 if (!pScreenInfo->WaitMarker) { 607 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " 608 "non-NULL\n", pScreen->myNum); 609 return FALSE; 610 } 611 612 if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || 613 pScreenInfo->exa_minor > EXA_VERSION_MINOR) 614 { 615 LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " 616 "(%d.%d) are incompatible with EXA version (%d.%d)\n", 617 pScreen->myNum, 618 pScreenInfo->exa_major, pScreenInfo->exa_minor, 619 EXA_VERSION_MAJOR, EXA_VERSION_MINOR); 620 return FALSE; 621 } 622 623#ifdef RENDER 624 ps = GetPictureScreenIfSet(pScreen); 625#endif 626 if (exaGeneration != serverGeneration) 627 { 628 exaScreenPrivateIndex = AllocateScreenPrivateIndex(); 629 exaPixmapPrivateIndex = AllocatePixmapPrivateIndex(); 630 exaGeneration = serverGeneration; 631 } 632 633 pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1); 634 635 if (!pExaScr) { 636 LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", 637 pScreen->myNum); 638 return FALSE; 639 } 640 641 pExaScr->info = pScreenInfo; 642 643 pScreen->devPrivates[exaScreenPrivateIndex].ptr = (pointer) pExaScr; 644 645 pExaScr->migration = ExaMigrationAlways; 646 647 exaDDXDriverInit(pScreen); 648 649 /* 650 * Replace various fb screen functions 651 */ 652 pExaScr->SavedCloseScreen = pScreen->CloseScreen; 653 pScreen->CloseScreen = exaCloseScreen; 654 655 pExaScr->SavedCreateGC = pScreen->CreateGC; 656 pScreen->CreateGC = exaCreateGC; 657 658 pExaScr->SavedGetImage = pScreen->GetImage; 659 pScreen->GetImage = exaGetImage; 660 661 pExaScr->SavedGetSpans = pScreen->GetSpans; 662 pScreen->GetSpans = exaGetSpans; 663 664 pExaScr->SavedCopyWindow = pScreen->CopyWindow; 665 pScreen->CopyWindow = exaCopyWindow; 666 667 pExaScr->SavedPaintWindowBackground = pScreen->PaintWindowBackground; 668 pScreen->PaintWindowBackground = exaPaintWindow; 669 670 pExaScr->SavedPaintWindowBorder = pScreen->PaintWindowBorder; 671 pScreen->PaintWindowBorder = exaPaintWindow; 672 673 pScreen->BackingStoreFuncs.SaveAreas = ExaCheckSaveAreas; 674 pScreen->BackingStoreFuncs.RestoreAreas = ExaCheckRestoreAreas; 675#ifdef RENDER 676 if (ps) { 677 pExaScr->SavedComposite = ps->Composite; 678 ps->Composite = exaComposite; 679 680 pExaScr->SavedRasterizeTrapezoid = ps->RasterizeTrapezoid; 681 ps->RasterizeTrapezoid = exaRasterizeTrapezoid; 682 683 pExaScr->SavedAddTriangles = ps->AddTriangles; 684 ps->AddTriangles = exaAddTriangles; 685 686 pExaScr->SavedGlyphs = ps->Glyphs; 687 ps->Glyphs = exaGlyphs; 688 689 pExaScr->SavedTrapezoids = ps->Trapezoids; 690 ps->Trapezoids = exaTrapezoids; 691 } 692#endif 693 694#ifdef MITSHM 695 /* Re-register with the MI funcs, which don't allow shared pixmaps. 696 * Shared pixmaps are almost always a performance loss for us, but this 697 * still allows for SHM PutImage. 698 */ 699 ShmRegisterFuncs(pScreen, NULL); 700#endif 701 /* 702 * Hookup offscreen pixmaps 703 */ 704 if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 705 pExaScr->info->offScreenBase < pExaScr->info->memorySize) 706 { 707 if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, 708 sizeof (ExaPixmapPrivRec))) { 709 LogMessage(X_WARNING, 710 "EXA(%d): Failed to allocate pixmap private\n", 711 pScreen->myNum); 712 return FALSE; 713 } 714 pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; 715 pScreen->CreatePixmap = exaCreatePixmap; 716 717 pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap; 718 pScreen->DestroyPixmap = exaDestroyPixmap; 719 720 LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %d bytes\n", 721 pScreen->myNum, 722 pExaScr->info->memorySize - pExaScr->info->offScreenBase); 723 } 724 else 725 { 726 LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); 727 if (!AllocatePixmapPrivate(pScreen, exaPixmapPrivateIndex, 0)) 728 return FALSE; 729 } 730 731 DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, 732 pExaScr->info->memorySize)); 733 if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { 734 if (!exaOffscreenInit (pScreen)) { 735 LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", 736 pScreen->myNum); 737 return FALSE; 738 } 739 } 740 741 LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" 742 " operations:\n", pScreen->myNum); 743 assert(pScreenInfo->PrepareSolid != NULL); 744 LogMessage(X_INFO, " Solid\n"); 745 assert(pScreenInfo->PrepareCopy != NULL); 746 LogMessage(X_INFO, " Copy\n"); 747 if (pScreenInfo->PrepareComposite != NULL) { 748 LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); 749 } 750 if (pScreenInfo->UploadToScreen != NULL) { 751 LogMessage(X_INFO, " UploadToScreen\n"); 752 } 753 if (pScreenInfo->DownloadFromScreen != NULL) { 754 LogMessage(X_INFO, " DownloadFromScreen\n"); 755 } 756 757 return TRUE; 758} 759 760/** 761 * exaDriverFini tears down EXA on a given screen. 762 * 763 * @param pScreen screen being torn down. 764 */ 765void 766exaDriverFini (ScreenPtr pScreen) 767{ 768 /*right now does nothing*/ 769} 770 771/** 772 * exaMarkSync() should be called after any asynchronous drawing by the hardware. 773 * 774 * @param pScreen screen which drawing occurred on 775 * 776 * exaMarkSync() sets a flag to indicate that some asynchronous drawing has 777 * happened and a WaitSync() will be necessary before relying on the contents of 778 * offscreen memory from the CPU's perspective. It also calls an optional 779 * driver MarkSync() callback, the return value of which may be used to do partial 780 * synchronization with the hardware in the future. 781 */ 782void exaMarkSync(ScreenPtr pScreen) 783{ 784 ExaScreenPriv(pScreen); 785 786 pExaScr->info->needsSync = TRUE; 787 if (pExaScr->info->MarkSync != NULL) { 788 pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen); 789 } 790} 791 792/** 793 * exaWaitSync() ensures that all drawing has been completed. 794 * 795 * @param pScreen screen being synchronized. 796 * 797 * Calls down into the driver to ensure that all previous drawing has completed. 798 * It should always be called before relying on the framebuffer contents 799 * reflecting previous drawing, from a CPU perspective. 800 */ 801void exaWaitSync(ScreenPtr pScreen) 802{ 803 ExaScreenPriv(pScreen); 804 805 if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 806 (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker); 807 pExaScr->info->needsSync = FALSE; 808 } 809} 810