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