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#include <stdlib.h> 36 37#include "exa_priv.h" 38#include "exa.h" 39 40DevPrivateKeyRec exaScreenPrivateKeyRec; 41 42#ifdef MITSHM 43static ShmFuncs exaShmFuncs = { NULL, NULL }; 44#endif 45 46/** 47 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of 48 * the beginning of the given pixmap. 49 * 50 * Note that drivers are free to, and often do, munge this offset as necessary 51 * for handing to the hardware -- for example, translating it into a different 52 * aperture. This function may need to be extended in the future if we grow 53 * support for having multiple card-accessible offscreen, such as an AGP memory 54 * pool alongside the framebuffer pool. 55 */ 56unsigned long 57exaGetPixmapOffset(PixmapPtr pPix) 58{ 59 ExaScreenPriv(pPix->drawable.pScreen); 60 ExaPixmapPriv(pPix); 61 62 return (CARD8 *) pExaPixmap->fb_ptr - pExaScr->info->memoryBase; 63} 64 65void * 66exaGetPixmapDriverPrivate(PixmapPtr pPix) 67{ 68 ExaPixmapPriv(pPix); 69 70 return pExaPixmap->driverPriv; 71} 72 73/** 74 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. 75 * 76 * This is a helper to make driver code more obvious, due to the rather obscure 77 * naming of the pitch field in the pixmap. 78 */ 79unsigned long 80exaGetPixmapPitch(PixmapPtr pPix) 81{ 82 return pPix->devKind; 83} 84 85/** 86 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video 87 * memory. Only valid when the pixmap is currently in framebuffer. 88 */ 89unsigned long 90exaGetPixmapSize(PixmapPtr pPix) 91{ 92 ExaPixmapPrivPtr pExaPixmap; 93 94 pExaPixmap = ExaGetPixmapPriv(pPix); 95 if (pExaPixmap != NULL) 96 return pExaPixmap->fb_size; 97 return 0; 98} 99 100/** 101 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. 102 * 103 * @param pDrawable the drawable being requested. 104 * 105 * This function returns the backing pixmap for a drawable, whether it is a 106 * redirected window, unredirected window, or already a pixmap. Note that 107 * coordinate translation is needed when drawing to the backing pixmap of a 108 * redirected window, and the translation coordinates are provided by calling 109 * exaGetOffscreenPixmap() on the drawable. 110 */ 111PixmapPtr 112exaGetDrawablePixmap(DrawablePtr pDrawable) 113{ 114 if (pDrawable->type == DRAWABLE_WINDOW) 115 return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); 116 else 117 return (PixmapPtr) pDrawable; 118} 119 120/** 121 * Sets the offsets to add to coordinates to make them address the same bits in 122 * the backing drawable. These coordinates are nonzero only for redirected 123 * windows. 124 */ 125void 126exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap, int *xp, int *yp) 127{ 128#ifdef COMPOSITE 129 if (pDrawable->type == DRAWABLE_WINDOW) { 130 *xp = -pPixmap->screen_x; 131 *yp = -pPixmap->screen_y; 132 return; 133 } 134#endif 135 136 *xp = 0; 137 *yp = 0; 138} 139 140/** 141 * exaPixmapDirty() marks a pixmap as dirty, allowing for 142 * optimizations in pixmap migration when no changes have occurred. 143 */ 144void 145exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2) 146{ 147 BoxRec box; 148 RegionRec region; 149 150 box.x1 = max(x1, 0); 151 box.y1 = max(y1, 0); 152 box.x2 = min(x2, pPix->drawable.width); 153 box.y2 = min(y2, pPix->drawable.height); 154 155 if (box.x1 >= box.x2 || box.y1 >= box.y2) 156 return; 157 158 RegionInit(®ion, &box, 1); 159 DamageDamageRegion(&pPix->drawable, ®ion); 160 RegionUninit(®ion); 161} 162 163static int 164exaLog2(int val) 165{ 166 int bits; 167 168 if (val <= 0) 169 return 0; 170 for (bits = 0; val != 0; bits++) 171 val >>= 1; 172 return bits - 1; 173} 174 175void 176exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 177 int w, int h, int bpp) 178{ 179 pExaPixmap->accel_blocked = 0; 180 181 if (pExaScr->info->maxPitchPixels) { 182 int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp); 183 184 if (pExaPixmap->fb_pitch > max_pitch) 185 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 186 } 187 188 if (pExaScr->info->maxPitchBytes && 189 pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes) 190 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 191 192 if (w > pExaScr->info->maxX) 193 pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH; 194 195 if (h > pExaScr->info->maxY) 196 pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT; 197} 198 199void 200exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 201 int w, int h, int bpp) 202{ 203 if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) 204 pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp); 205 else 206 pExaPixmap->fb_pitch = bits_to_bytes(w * bpp); 207 208 pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, 209 pExaScr->info->pixmapPitchAlign); 210} 211 212/** 213 * Returns TRUE if the pixmap is not movable. This is the case where it's a 214 * pixmap which has no private (almost always bad) or it's a scratch pixmap created by 215 * some X Server internal component (the score says it's pinned). 216 */ 217Bool 218exaPixmapIsPinned(PixmapPtr pPix) 219{ 220 ExaPixmapPriv(pPix); 221 222 if (pExaPixmap == NULL) 223 EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE); 224 225 return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED; 226} 227 228/** 229 * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen 230 * memory, meaning that acceleration could probably be done to it, and that it 231 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 232 * with the CPU. 233 * 234 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 235 * deal with moving pixmaps in and out of system memory), EXA will give drivers 236 * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE. 237 * 238 * @return TRUE if the given drawable is in framebuffer memory. 239 */ 240Bool 241exaPixmapHasGpuCopy(PixmapPtr pPixmap) 242{ 243 ScreenPtr pScreen = pPixmap->drawable.pScreen; 244 245 ExaScreenPriv(pScreen); 246 247 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 248 return FALSE; 249 250 return (*pExaScr->pixmap_has_gpu_copy) (pPixmap); 251} 252 253/** 254 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy(). 255 */ 256Bool 257exaDrawableIsOffscreen(DrawablePtr pDrawable) 258{ 259 return exaPixmapHasGpuCopy(exaGetDrawablePixmap(pDrawable)); 260} 261 262/** 263 * Returns the pixmap which backs a drawable, and the offsets to add to 264 * coordinates to make them address the same bits in the backing drawable. 265 */ 266PixmapPtr 267exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp) 268{ 269 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 270 271 exaGetDrawableDeltas(pDrawable, pPixmap, xp, yp); 272 273 if (exaPixmapHasGpuCopy(pPixmap)) 274 return pPixmap; 275 else 276 return NULL; 277} 278 279/** 280 * Returns TRUE if the pixmap GPU copy is being accessed. 281 */ 282Bool 283ExaDoPrepareAccess(PixmapPtr pPixmap, int index) 284{ 285 ScreenPtr pScreen = pPixmap->drawable.pScreen; 286 287 ExaScreenPriv(pScreen); 288 ExaPixmapPriv(pPixmap); 289 Bool has_gpu_copy, ret; 290 int i; 291 292 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 293 return FALSE; 294 295 if (pExaPixmap == NULL) 296 EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE); 297 298 /* Handle repeated / nested calls. */ 299 for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 300 if (pExaScr->access[i].pixmap == pPixmap) { 301 pExaScr->access[i].count++; 302 return pExaScr->access[i].retval; 303 } 304 } 305 306 /* If slot for this index is taken, find an empty slot */ 307 if (pExaScr->access[index].pixmap) { 308 for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--) 309 if (!pExaScr->access[index].pixmap) 310 break; 311 } 312 313 /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */ 314 if (pPixmap->devPrivate.ptr != NULL) { 315 EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n", pPixmap->devPrivate.ptr)); 316 } 317 318 has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); 319 320 if (has_gpu_copy && pExaPixmap->fb_ptr) { 321 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 322 ret = TRUE; 323 } 324 else { 325 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 326 ret = FALSE; 327 } 328 329 /* Store so we can handle repeated / nested calls. */ 330 pExaScr->access[index].pixmap = pPixmap; 331 pExaScr->access[index].count = 1; 332 333 if (!has_gpu_copy) 334 goto out; 335 336 exaWaitSync(pScreen); 337 338 if (pExaScr->info->PrepareAccess == NULL) 339 goto out; 340 341 if (index >= EXA_PREPARE_AUX_DEST && 342 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 343 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) 344 FatalError("Unsupported AUX indices used on a pinned pixmap.\n"); 345 exaMoveOutPixmap(pPixmap); 346 ret = FALSE; 347 goto out; 348 } 349 350 if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 351 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED && 352 !(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) 353 FatalError("Driver failed PrepareAccess on a pinned pixmap.\n"); 354 exaMoveOutPixmap(pPixmap); 355 ret = FALSE; 356 goto out; 357 } 358 359 ret = TRUE; 360 361 out: 362 pExaScr->access[index].retval = ret; 363 return ret; 364} 365 366/** 367 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 368 * 369 * It deals with waiting for synchronization with the card, determining if 370 * PrepareAccess() is necessary, and working around PrepareAccess() failure. 371 */ 372void 373exaPrepareAccess(DrawablePtr pDrawable, int index) 374{ 375 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 376 377 ExaScreenPriv(pDrawable->pScreen); 378 379 if (pExaScr->prepare_access_reg) 380 pExaScr->prepare_access_reg(pPixmap, index, NULL); 381 else 382 (void) ExaDoPrepareAccess(pPixmap, index); 383} 384 385/** 386 * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. 387 * 388 * It deals with calling the driver's FinishAccess() only if necessary. 389 */ 390void 391exaFinishAccess(DrawablePtr pDrawable, int index) 392{ 393 ScreenPtr pScreen = pDrawable->pScreen; 394 395 ExaScreenPriv(pScreen); 396 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); 397 398 ExaPixmapPriv(pPixmap); 399 int i; 400 401 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 402 return; 403 404 if (pExaPixmap == NULL) 405 EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),); 406 407 /* Handle repeated / nested calls. */ 408 for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 409 if (pExaScr->access[i].pixmap == pPixmap) { 410 if (--pExaScr->access[i].count > 0) 411 return; 412 break; 413 } 414 } 415 416 /* Catch unbalanced Prepare/FinishAccess calls. */ 417 if (i == EXA_NUM_PREPARE_INDICES) 418 EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", pPixmap),); 419 420 pExaScr->access[i].pixmap = NULL; 421 422 /* We always hide the devPrivate.ptr. */ 423 pPixmap->devPrivate.ptr = NULL; 424 425 /* Only call FinishAccess if PrepareAccess was called and succeeded. */ 426 if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval) 427 return; 428 429 if (i >= EXA_PREPARE_AUX_DEST && 430 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 431 ErrorF("EXA bug: Trying to call driver FinishAccess hook with " 432 "unsupported index EXA_PREPARE_AUX*\n"); 433 return; 434 } 435 436 (*pExaScr->info->FinishAccess) (pPixmap, i); 437} 438 439/** 440 * Helper for things common to all schemes when a pixmap is destroyed 441 */ 442void 443exaDestroyPixmap(PixmapPtr pPixmap) 444{ 445 ExaScreenPriv(pPixmap->drawable.pScreen); 446 int i; 447 448 /* Finish access if it was prepared (e.g. pixmap created during 449 * software fallback) 450 */ 451 for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { 452 if (pExaScr->access[i].pixmap == pPixmap) { 453 exaFinishAccess(&pPixmap->drawable, i); 454 pExaScr->access[i].pixmap = NULL; 455 break; 456 } 457 } 458} 459 460/** 461 * Here begins EXA's GC code. 462 * Do not ever access the fb/mi layer directly. 463 */ 464 465static void 466 exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable); 467 468static void 469 exaDestroyGC(GCPtr pGC); 470 471static void 472 exaChangeGC(GCPtr pGC, unsigned long mask); 473 474static void 475 exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); 476 477static void 478 exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects); 479 480static void 481 exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc); 482 483static void 484 exaDestroyClip(GCPtr pGC); 485 486const GCFuncs exaGCFuncs = { 487 exaValidateGC, 488 exaChangeGC, 489 exaCopyGC, 490 exaDestroyGC, 491 exaChangeClip, 492 exaDestroyClip, 493 exaCopyClip 494}; 495 496static void 497exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 498{ 499 /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 500 * Do a few smart things so fbValidateGC can do its work. 501 */ 502 503 ScreenPtr pScreen = pDrawable->pScreen; 504 505 ExaScreenPriv(pScreen); 506 ExaGCPriv(pGC); 507 PixmapPtr pTile = NULL; 508 509 /* Either of these conditions is enough to trigger access to a tile pixmap. 510 * With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid 511 * tile pixmap pointer. 512 */ 513 if (pGC->fillStyle == FillTiled || 514 ((changes & GCTile) && !pGC->tileIsPixel)) { 515 pTile = pGC->tile.pixmap; 516 } 517 518 if (pGC->stipple) 519 exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 520 if (pTile) 521 exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC); 522 523 /* Calls to Create/DestroyPixmap have to be identified as special. */ 524 pExaScr->fallback_counter++; 525 swap(pExaGC, pGC, funcs); 526 (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); 527 swap(pExaGC, pGC, funcs); 528 pExaScr->fallback_counter--; 529 530 if (pTile) 531 exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC); 532 if (pGC->stipple) 533 exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); 534} 535 536/* Is exaPrepareAccessGC() needed? */ 537static void 538exaDestroyGC(GCPtr pGC) 539{ 540 ExaGCPriv(pGC); 541 swap(pExaGC, pGC, funcs); 542 (*pGC->funcs->DestroyGC) (pGC); 543 swap(pExaGC, pGC, funcs); 544} 545 546static void 547exaChangeGC(GCPtr pGC, unsigned long mask) 548{ 549 ExaGCPriv(pGC); 550 swap(pExaGC, pGC, funcs); 551 (*pGC->funcs->ChangeGC) (pGC, mask); 552 swap(pExaGC, pGC, funcs); 553} 554 555static void 556exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) 557{ 558 ExaGCPriv(pGCDst); 559 swap(pExaGC, pGCDst, funcs); 560 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); 561 swap(pExaGC, pGCDst, funcs); 562} 563 564static void 565exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects) 566{ 567 ExaGCPriv(pGC); 568 swap(pExaGC, pGC, funcs); 569 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); 570 swap(pExaGC, pGC, funcs); 571} 572 573static void 574exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc) 575{ 576 ExaGCPriv(pGCDst); 577 swap(pExaGC, pGCDst, funcs); 578 (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); 579 swap(pExaGC, pGCDst, funcs); 580} 581 582static void 583exaDestroyClip(GCPtr pGC) 584{ 585 ExaGCPriv(pGC); 586 swap(pExaGC, pGC, funcs); 587 (*pGC->funcs->DestroyClip) (pGC); 588 swap(pExaGC, pGC, funcs); 589} 590 591/** 592 * exaCreateGC makes a new GC and hooks up its funcs handler, so that 593 * exaValidateGC() will get called. 594 */ 595static int 596exaCreateGC(GCPtr pGC) 597{ 598 ScreenPtr pScreen = pGC->pScreen; 599 600 ExaScreenPriv(pScreen); 601 ExaGCPriv(pGC); 602 Bool ret; 603 604 swap(pExaScr, pScreen, CreateGC); 605 if ((ret = (*pScreen->CreateGC) (pGC))) { 606 wrap(pExaGC, pGC, funcs, &exaGCFuncs); 607 wrap(pExaGC, pGC, ops, &exaOps); 608 } 609 swap(pExaScr, pScreen, CreateGC); 610 611 return ret; 612} 613 614static Bool 615exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 616{ 617 Bool ret; 618 ScreenPtr pScreen = pWin->drawable.pScreen; 619 620 ExaScreenPriv(pScreen); 621 622 if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 623 exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 624 625 if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 626 exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 627 628 pExaScr->fallback_counter++; 629 swap(pExaScr, pScreen, ChangeWindowAttributes); 630 ret = pScreen->ChangeWindowAttributes(pWin, mask); 631 swap(pExaScr, pScreen, ChangeWindowAttributes); 632 pExaScr->fallback_counter--; 633 634 if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 635 exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 636 if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 637 exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 638 639 return ret; 640} 641 642static RegionPtr 643exaBitmapToRegion(PixmapPtr pPix) 644{ 645 RegionPtr ret; 646 ScreenPtr pScreen = pPix->drawable.pScreen; 647 648 ExaScreenPriv(pScreen); 649 650 exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC); 651 swap(pExaScr, pScreen, BitmapToRegion); 652 ret = (*pScreen->BitmapToRegion) (pPix); 653 swap(pExaScr, pScreen, BitmapToRegion); 654 exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC); 655 656 return ret; 657} 658 659static Bool 660exaCreateScreenResources(ScreenPtr pScreen) 661{ 662 ExaScreenPriv(pScreen); 663 PixmapPtr pScreenPixmap; 664 Bool b; 665 666 swap(pExaScr, pScreen, CreateScreenResources); 667 b = pScreen->CreateScreenResources(pScreen); 668 swap(pExaScr, pScreen, CreateScreenResources); 669 670 if (!b) 671 return FALSE; 672 673 pScreenPixmap = pScreen->GetScreenPixmap(pScreen); 674 675 if (pScreenPixmap) { 676 ExaPixmapPriv(pScreenPixmap); 677 678 exaSetAccelBlock(pExaScr, pExaPixmap, 679 pScreenPixmap->drawable.width, 680 pScreenPixmap->drawable.height, 681 pScreenPixmap->drawable.bitsPerPixel); 682 } 683 684 return TRUE; 685} 686 687static void 688ExaBlockHandler(ScreenPtr pScreen, void *pTimeout) 689{ 690 ExaScreenPriv(pScreen); 691 692 /* Move any deferred results from a software fallback to the driver pixmap */ 693 if (pExaScr->deferred_mixed_pixmap) 694 exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap); 695 696 unwrap(pExaScr, pScreen, BlockHandler); 697 (*pScreen->BlockHandler) (pScreen, pTimeout); 698 wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); 699 700 /* The rest only applies to classic EXA */ 701 if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) 702 return; 703 704 /* Try and keep the offscreen memory area tidy every now and then (at most 705 * once per second) when the server has been idle for at least 100ms. 706 */ 707 if (pExaScr->numOffscreenAvailable > 1) { 708 CARD32 now = GetTimeInMillis(); 709 710 pExaScr->nextDefragment = now + 711 max(100, (INT32) (pExaScr->lastDefragment + 1000 - now)); 712 AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now); 713 } 714} 715 716static void 717ExaWakeupHandler(ScreenPtr pScreen, int result) 718{ 719 ExaScreenPriv(pScreen); 720 721 unwrap(pExaScr, pScreen, WakeupHandler); 722 (*pScreen->WakeupHandler) (pScreen, result); 723 wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); 724 725 if (result == 0 && pExaScr->numOffscreenAvailable > 1) { 726 CARD32 now = GetTimeInMillis(); 727 728 if ((int) (now - pExaScr->nextDefragment) > 0) { 729 ExaOffscreenDefragment(pScreen); 730 pExaScr->lastDefragment = now; 731 } 732 } 733} 734 735/** 736 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's 737 * screen private, before calling down to the next CloseSccreen. 738 */ 739static Bool 740exaCloseScreen(ScreenPtr pScreen) 741{ 742 ExaScreenPriv(pScreen); 743 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 744 745 if (ps->Glyphs == exaGlyphs) 746 exaGlyphsFini(pScreen); 747 748 if (pScreen->BlockHandler == ExaBlockHandler) 749 unwrap(pExaScr, pScreen, BlockHandler); 750 if (pScreen->WakeupHandler == ExaWakeupHandler) 751 unwrap(pExaScr, pScreen, WakeupHandler); 752 unwrap(pExaScr, pScreen, CreateGC); 753 unwrap(pExaScr, pScreen, CloseScreen); 754 unwrap(pExaScr, pScreen, GetImage); 755 unwrap(pExaScr, pScreen, GetSpans); 756 if (pExaScr->SavedCreatePixmap) 757 unwrap(pExaScr, pScreen, CreatePixmap); 758 if (pExaScr->SavedDestroyPixmap) 759 unwrap(pExaScr, pScreen, DestroyPixmap); 760 if (pExaScr->SavedModifyPixmapHeader) 761 unwrap(pExaScr, pScreen, ModifyPixmapHeader); 762 unwrap(pExaScr, pScreen, CopyWindow); 763 unwrap(pExaScr, pScreen, ChangeWindowAttributes); 764 unwrap(pExaScr, pScreen, BitmapToRegion); 765 unwrap(pExaScr, pScreen, CreateScreenResources); 766 if (pExaScr->SavedSharePixmapBacking) 767 unwrap(pExaScr, pScreen, SharePixmapBacking); 768 if (pExaScr->SavedSetSharedPixmapBacking) 769 unwrap(pExaScr, pScreen, SetSharedPixmapBacking); 770 unwrap(pExaScr, ps, Composite); 771 if (pExaScr->SavedGlyphs) 772 unwrap(pExaScr, ps, Glyphs); 773 unwrap(pExaScr, ps, Trapezoids); 774 unwrap(pExaScr, ps, Triangles); 775 unwrap(pExaScr, ps, AddTraps); 776 777 free(pExaScr); 778 779 return (*pScreen->CloseScreen) (pScreen); 780} 781 782/** 783 * This function allocates a driver structure for EXA drivers to fill in. By 784 * having EXA allocate the structure, the driver structure can be extended 785 * without breaking ABI between EXA and the drivers. The driver's 786 * responsibility is to check beforehand that the EXA module has a matching 787 * major number and sufficient minor. Drivers are responsible for freeing the 788 * driver structure using free(). 789 * 790 * @return a newly allocated, zero-filled driver structure 791 */ 792ExaDriverPtr 793exaDriverAlloc(void) 794{ 795 return calloc(1, sizeof(ExaDriverRec)); 796} 797 798/** 799 * @param pScreen screen being initialized 800 * @param pScreenInfo EXA driver record 801 * 802 * exaDriverInit sets up EXA given a driver record filled in by the driver. 803 * pScreenInfo should have been allocated by exaDriverAlloc(). See the 804 * comments in _ExaDriver for what must be filled in and what is optional. 805 * 806 * @return TRUE if EXA was successfully initialized. 807 */ 808Bool 809exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo) 810{ 811 ExaScreenPrivPtr pExaScr; 812 PictureScreenPtr ps; 813 814 if (!pScreenInfo) 815 return FALSE; 816 817 if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || 818 pScreenInfo->exa_minor > EXA_VERSION_MINOR) { 819 LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " 820 "(%d.%d) are incompatible with EXA version (%d.%d)\n", 821 pScreen->myNum, 822 pScreenInfo->exa_major, pScreenInfo->exa_minor, 823 EXA_VERSION_MAJOR, EXA_VERSION_MINOR); 824 return FALSE; 825 } 826 827 if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) { 828 if (!pScreenInfo->memoryBase) { 829 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase " 830 "must be non-zero\n", pScreen->myNum); 831 return FALSE; 832 } 833 834 if (!pScreenInfo->memorySize) { 835 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " 836 "non-zero\n", pScreen->myNum); 837 return FALSE; 838 } 839 840 if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { 841 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must " 842 "be <= ExaDriverRec::memorySize\n", pScreen->myNum); 843 return FALSE; 844 } 845 } 846 847 if (!pScreenInfo->PrepareSolid) { 848 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " 849 "non-NULL\n", pScreen->myNum); 850 return FALSE; 851 } 852 853 if (!pScreenInfo->PrepareCopy) { 854 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " 855 "non-NULL\n", pScreen->myNum); 856 return FALSE; 857 } 858 859 if (!pScreenInfo->WaitMarker) { 860 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " 861 "non-NULL\n", pScreen->myNum); 862 return FALSE; 863 } 864 865 /* If the driver doesn't set any max pitch values, we'll just assume 866 * that there's a limitation by pixels, and that it's the same as 867 * maxX. 868 * 869 * We want maxPitchPixels or maxPitchBytes to be set so we can check 870 * pixmaps against the max pitch in exaCreatePixmap() -- it matters 871 * whether a pixmap is rejected because of its pitch or 872 * because of its width. 873 */ 874 if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) { 875 pScreenInfo->maxPitchPixels = pScreenInfo->maxX; 876 } 877 878 ps = GetPictureScreenIfSet(pScreen); 879 880 if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) { 881 LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n", 882 pScreen->myNum); 883 return FALSE; 884 } 885 886 pExaScr = calloc(sizeof(ExaScreenPrivRec), 1); 887 if (!pExaScr) { 888 LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", 889 pScreen->myNum); 890 return FALSE; 891 } 892 893 pExaScr->info = pScreenInfo; 894 895 dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr); 896 897 pExaScr->migration = ExaMigrationAlways; 898 899 exaDDXDriverInit(pScreen); 900 901 if (!dixRegisterScreenSpecificPrivateKey 902 (pScreen, &pExaScr->gcPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) { 903 LogMessage(X_WARNING, "EXA(%d): Failed to allocate GC private\n", 904 pScreen->myNum); 905 return FALSE; 906 } 907 908 /* 909 * Replace various fb screen functions 910 */ 911 if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 912 (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) || 913 (pExaScr->info->flags & EXA_MIXED_PIXMAPS))) 914 wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); 915 if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && 916 !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) 917 wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); 918 wrap(pExaScr, pScreen, CreateGC, exaCreateGC); 919 wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen); 920 wrap(pExaScr, pScreen, GetImage, exaGetImage); 921 wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans); 922 wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow); 923 wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes); 924 wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion); 925 wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources); 926 927 if (ps) { 928 wrap(pExaScr, ps, Composite, exaComposite); 929 if (pScreenInfo->PrepareComposite) { 930 wrap(pExaScr, ps, Glyphs, exaGlyphs); 931 } 932 else { 933 wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs); 934 } 935 wrap(pExaScr, ps, Trapezoids, exaTrapezoids); 936 wrap(pExaScr, ps, Triangles, exaTriangles); 937 wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps); 938 } 939 940#ifdef MITSHM 941 /* 942 * Don't allow shared pixmaps. 943 */ 944 ShmRegisterFuncs(pScreen, &exaShmFuncs); 945#endif 946 /* 947 * Hookup offscreen pixmaps 948 */ 949 if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) { 950 if (!dixRegisterScreenSpecificPrivateKey 951 (pScreen, &pExaScr->pixmapPrivateKeyRec, PRIVATE_PIXMAP, 952 sizeof(ExaPixmapPrivRec))) { 953 LogMessage(X_WARNING, 954 "EXA(%d): Failed to allocate pixmap private\n", 955 pScreen->myNum); 956 return FALSE; 957 } 958 if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) { 959 if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) { 960 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed); 961 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed); 962 wrap(pExaScr, pScreen, ModifyPixmapHeader, 963 exaModifyPixmapHeader_mixed); 964 wrap(pExaScr, pScreen, SharePixmapBacking, exaSharePixmapBacking_mixed); 965 wrap(pExaScr, pScreen, SetSharedPixmapBacking, exaSetSharedPixmapBacking_mixed); 966 967 pExaScr->do_migration = exaDoMigration_mixed; 968 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed; 969 pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed; 970 pExaScr->do_move_out_pixmap = NULL; 971 pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed; 972 } 973 else { 974 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver); 975 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver); 976 wrap(pExaScr, pScreen, ModifyPixmapHeader, 977 exaModifyPixmapHeader_driver); 978 pExaScr->do_migration = NULL; 979 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_driver; 980 pExaScr->do_move_in_pixmap = NULL; 981 pExaScr->do_move_out_pixmap = NULL; 982 pExaScr->prepare_access_reg = NULL; 983 } 984 } 985 else { 986 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic); 987 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic); 988 wrap(pExaScr, pScreen, ModifyPixmapHeader, 989 exaModifyPixmapHeader_classic); 990 pExaScr->do_migration = exaDoMigration_classic; 991 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic; 992 pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic; 993 pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic; 994 pExaScr->prepare_access_reg = exaPrepareAccessReg_classic; 995 } 996 if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 997 LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", 998 pScreen->myNum, 999 pExaScr->info->memorySize - 1000 pExaScr->info->offScreenBase); 1001 } 1002 else { 1003 LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n", 1004 pScreen->myNum); 1005 1006 } 1007 } 1008 else 1009 LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); 1010 1011 if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 1012 DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, 1013 pExaScr->info->memorySize)); 1014 if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { 1015 if (!exaOffscreenInit(pScreen)) { 1016 LogMessage(X_WARNING, 1017 "EXA(%d): Offscreen pixmap setup failed\n", 1018 pScreen->myNum); 1019 return FALSE; 1020 } 1021 } 1022 } 1023 1024 if (ps->Glyphs == exaGlyphs) 1025 exaGlyphsInit(pScreen); 1026 1027 LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" 1028 " operations:\n", pScreen->myNum); 1029 assert(pScreenInfo->PrepareSolid != NULL); 1030 LogMessage(X_INFO, " Solid\n"); 1031 assert(pScreenInfo->PrepareCopy != NULL); 1032 LogMessage(X_INFO, " Copy\n"); 1033 if (pScreenInfo->PrepareComposite != NULL) { 1034 LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); 1035 } 1036 if (pScreenInfo->UploadToScreen != NULL) { 1037 LogMessage(X_INFO, " UploadToScreen\n"); 1038 } 1039 if (pScreenInfo->DownloadFromScreen != NULL) { 1040 LogMessage(X_INFO, " DownloadFromScreen\n"); 1041 } 1042 1043 return TRUE; 1044} 1045 1046/** 1047 * exaDriverFini tears down EXA on a given screen. 1048 * 1049 * @param pScreen screen being torn down. 1050 */ 1051void 1052exaDriverFini(ScreenPtr pScreen) 1053{ 1054 /*right now does nothing */ 1055} 1056 1057/** 1058 * exaMarkSync() should be called after any asynchronous drawing by the hardware. 1059 * 1060 * @param pScreen screen which drawing occurred on 1061 * 1062 * exaMarkSync() sets a flag to indicate that some asynchronous drawing has 1063 * happened and a WaitSync() will be necessary before relying on the contents of 1064 * offscreen memory from the CPU's perspective. It also calls an optional 1065 * driver MarkSync() callback, the return value of which may be used to do partial 1066 * synchronization with the hardware in the future. 1067 */ 1068void 1069exaMarkSync(ScreenPtr pScreen) 1070{ 1071 ExaScreenPriv(pScreen); 1072 1073 pExaScr->info->needsSync = TRUE; 1074 if (pExaScr->info->MarkSync != NULL) { 1075 pExaScr->info->lastMarker = (*pExaScr->info->MarkSync) (pScreen); 1076 } 1077} 1078 1079/** 1080 * exaWaitSync() ensures that all drawing has been completed. 1081 * 1082 * @param pScreen screen being synchronized. 1083 * 1084 * Calls down into the driver to ensure that all previous drawing has completed. 1085 * It should always be called before relying on the framebuffer contents 1086 * reflecting previous drawing, from a CPU perspective. 1087 */ 1088void 1089exaWaitSync(ScreenPtr pScreen) 1090{ 1091 ExaScreenPriv(pScreen); 1092 1093 if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 1094 (*pExaScr->info->WaitMarker) (pScreen, pExaScr->info->lastMarker); 1095 pExaScr->info->needsSync = FALSE; 1096 } 1097} 1098 1099/** 1100 * Performs migration of the pixmaps according to the operation information 1101 * provided in pixmaps and can_accel and the migration scheme chosen in the 1102 * config file. 1103 */ 1104void 1105exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) 1106{ 1107 ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; 1108 1109 ExaScreenPriv(pScreen); 1110 1111 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 1112 return; 1113 1114 if (pExaScr->do_migration) 1115 (*pExaScr->do_migration) (pixmaps, npixmaps, can_accel); 1116} 1117 1118void 1119exaMoveInPixmap(PixmapPtr pPixmap) 1120{ 1121 ScreenPtr pScreen = pPixmap->drawable.pScreen; 1122 1123 ExaScreenPriv(pScreen); 1124 1125 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 1126 return; 1127 1128 if (pExaScr->do_move_in_pixmap) 1129 (*pExaScr->do_move_in_pixmap) (pPixmap); 1130} 1131 1132void 1133exaMoveOutPixmap(PixmapPtr pPixmap) 1134{ 1135 ScreenPtr pScreen = pPixmap->drawable.pScreen; 1136 1137 ExaScreenPriv(pScreen); 1138 1139 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) 1140 return; 1141 1142 if (pExaScr->do_move_out_pixmap) 1143 (*pExaScr->do_move_out_pixmap) (pPixmap); 1144} 1145