exa.c revision 4642e01f
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 40static int exaScreenPrivateKeyIndex; 41DevPrivateKey exaScreenPrivateKey = &exaScreenPrivateKeyIndex; 42static int exaPixmapPrivateKeyIndex; 43DevPrivateKey exaPixmapPrivateKey = &exaPixmapPrivateKeyIndex; 44 45#ifdef MITSHM 46static ShmFuncs exaShmFuncs = { NULL, NULL }; 47#endif 48 49static _X_INLINE void* 50ExaGetPixmapAddress(PixmapPtr p) 51{ 52 ExaPixmapPriv(p); 53 54 if (pExaPixmap->offscreen && pExaPixmap->fb_ptr) 55 return pExaPixmap->fb_ptr; 56 else 57 return pExaPixmap->sys_ptr; 58} 59 60/** 61 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of 62 * the beginning of the given pixmap. 63 * 64 * Note that drivers are free to, and often do, munge this offset as necessary 65 * for handing to the hardware -- for example, translating it into a different 66 * aperture. This function may need to be extended in the future if we grow 67 * support for having multiple card-accessible offscreen, such as an AGP memory 68 * pool alongside the framebuffer pool. 69 */ 70unsigned long 71exaGetPixmapOffset(PixmapPtr pPix) 72{ 73 ExaScreenPriv (pPix->drawable.pScreen); 74 75 return ((unsigned long)ExaGetPixmapAddress(pPix) - 76 (unsigned long)pExaScr->info->memoryBase); 77} 78 79void * 80exaGetPixmapDriverPrivate(PixmapPtr pPix) 81{ 82 ExaPixmapPriv(pPix); 83 84 return pExaPixmap->driverPriv; 85} 86 87/** 88 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. 89 * 90 * This is a helper to make driver code more obvious, due to the rather obscure 91 * naming of the pitch field in the pixmap. 92 */ 93unsigned long 94exaGetPixmapPitch(PixmapPtr pPix) 95{ 96 return pPix->devKind; 97} 98 99/** 100 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video 101 * memory. Only valid when the pixmap is currently in framebuffer. 102 */ 103unsigned long 104exaGetPixmapSize(PixmapPtr pPix) 105{ 106 ExaPixmapPrivPtr pExaPixmap; 107 108 pExaPixmap = ExaGetPixmapPriv(pPix); 109 if (pExaPixmap != NULL) 110 return pExaPixmap->fb_size; 111 return 0; 112} 113 114/** 115 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. 116 * 117 * @param pDrawable the drawable being requested. 118 * 119 * This function returns the backing pixmap for a drawable, whether it is a 120 * redirected window, unredirected window, or already a pixmap. Note that 121 * coordinate translation is needed when drawing to the backing pixmap of a 122 * redirected window, and the translation coordinates are provided by calling 123 * exaGetOffscreenPixmap() on the drawable. 124 */ 125PixmapPtr 126exaGetDrawablePixmap(DrawablePtr pDrawable) 127{ 128 if (pDrawable->type == DRAWABLE_WINDOW) 129 return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable); 130 else 131 return (PixmapPtr) pDrawable; 132} 133 134/** 135 * Sets the offsets to add to coordinates to make them address the same bits in 136 * the backing drawable. These coordinates are nonzero only for redirected 137 * windows. 138 */ 139void 140exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, 141 int *xp, int *yp) 142{ 143#ifdef COMPOSITE 144 if (pDrawable->type == DRAWABLE_WINDOW) { 145 *xp = -pPixmap->screen_x; 146 *yp = -pPixmap->screen_y; 147 return; 148 } 149#endif 150 151 *xp = 0; 152 *yp = 0; 153} 154 155/** 156 * exaPixmapDirty() marks a pixmap as dirty, allowing for 157 * optimizations in pixmap migration when no changes have occurred. 158 */ 159void 160exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) 161{ 162 ExaPixmapPriv(pPix); 163 BoxRec box; 164 RegionPtr pDamageReg; 165 RegionRec region; 166 167 if (!pExaPixmap || !pExaPixmap->pDamage) 168 return; 169 170 box.x1 = max(x1, 0); 171 box.y1 = max(y1, 0); 172 box.x2 = min(x2, pPix->drawable.width); 173 box.y2 = min(y2, pPix->drawable.height); 174 175 if (box.x1 >= box.x2 || box.y1 >= box.y2) 176 return; 177 178 pDamageReg = DamageRegion(pExaPixmap->pDamage); 179 180 REGION_INIT(pScreen, ®ion, &box, 1); 181 REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); 182 REGION_UNINIT(pScreen, ®ion); 183} 184 185static Bool 186exaDestroyPixmap (PixmapPtr pPixmap) 187{ 188 ScreenPtr pScreen = pPixmap->drawable.pScreen; 189 ExaScreenPriv(pScreen); 190 191 if (pPixmap->refcnt == 1) 192 { 193 ExaPixmapPriv (pPixmap); 194 195 if (pExaPixmap->driverPriv) { 196 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 197 pExaPixmap->driverPriv = NULL; 198 } 199 200 if (pExaPixmap->area) 201 { 202 DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", 203 (void*)pPixmap->drawable.id, 204 ExaGetPixmapPriv(pPixmap)->area->offset, 205 pPixmap->drawable.width, 206 pPixmap->drawable.height)); 207 /* Free the offscreen area */ 208 exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area); 209 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 210 pPixmap->devKind = pExaPixmap->sys_pitch; 211 } 212 REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys); 213 REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB); 214 } 215 return fbDestroyPixmap (pPixmap); 216} 217 218static int 219exaLog2(int val) 220{ 221 int bits; 222 223 if (val <= 0) 224 return 0; 225 for (bits = 0; val != 0; bits++) 226 val >>= 1; 227 return bits - 1; 228} 229 230static void 231exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 232 int w, int h, int bpp) 233{ 234 pExaPixmap->accel_blocked = 0; 235 236 if (pExaScr->info->maxPitchPixels) { 237 int max_pitch = pExaScr->info->maxPitchPixels * (bpp + 7) / 8; 238 239 if (pExaPixmap->fb_pitch > max_pitch) 240 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 241 } 242 243 if (pExaScr->info->maxPitchBytes && 244 pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes) 245 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; 246 247 if (w > pExaScr->info->maxX) 248 pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH; 249 250 if (h > pExaScr->info->maxY) 251 pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT; 252} 253 254static void 255exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, 256 int w, int h, int bpp) 257{ 258 if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) 259 pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8; 260 else 261 pExaPixmap->fb_pitch = w * bpp / 8; 262 263 pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, 264 pExaScr->info->pixmapPitchAlign); 265} 266 267/** 268 * exaCreatePixmap() creates a new pixmap. 269 * 270 * If width and height are 0, this won't be a full-fledged pixmap and it will 271 * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because 272 * ModifyPixmapHeader() would break migration. These types of pixmaps are used 273 * for scratch pixmaps, or to represent the visible screen. 274 */ 275static PixmapPtr 276exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, 277 unsigned usage_hint) 278{ 279 PixmapPtr pPixmap; 280 ExaPixmapPrivPtr pExaPixmap; 281 int driver_alloc = 0; 282 int bpp; 283 ExaScreenPriv(pScreen); 284 285 if (w > 32767 || h > 32767) 286 return NullPixmap; 287 288 if (!pExaScr->info->CreatePixmap) { 289 pPixmap = fbCreatePixmap (pScreen, w, h, depth, usage_hint); 290 } else { 291 driver_alloc = 1; 292 pPixmap = fbCreatePixmap(pScreen, 0, 0, depth, usage_hint); 293 } 294 295 if (!pPixmap) 296 return NULL; 297 298 pExaPixmap = ExaGetPixmapPriv(pPixmap); 299 pExaPixmap->driverPriv = NULL; 300 301 bpp = pPixmap->drawable.bitsPerPixel; 302 303 if (driver_alloc) { 304 size_t paddedWidth, datasize; 305 306 paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); 307 if (paddedWidth / 4 > 32767 || h > 32767) 308 return NullPixmap; 309 310 exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 311 312 if (paddedWidth < pExaPixmap->fb_pitch) 313 paddedWidth = pExaPixmap->fb_pitch; 314 315 datasize = h * paddedWidth; 316 317 /* Set this before driver hooks, to allow for !offscreen pixmaps. 318 * !offscreen pixmaps have a valid pointer at all times. 319 */ 320 pPixmap->devPrivate.ptr = NULL; 321 322 pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0); 323 if (!pExaPixmap->driverPriv) { 324 fbDestroyPixmap(pPixmap); 325 return NULL; 326 } 327 328 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, 329 paddedWidth, NULL); 330 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 331 pExaPixmap->fb_ptr = NULL; 332 pExaPixmap->pDamage = NULL; 333 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 334 335 } else { 336 pExaPixmap->driverPriv = NULL; 337 /* Scratch pixmaps may have w/h equal to zero, and may not be 338 * migrated. 339 */ 340 if (!w || !h) 341 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 342 else 343 pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; 344 345 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; 346 pExaPixmap->sys_pitch = pPixmap->devKind; 347 348 pPixmap->devPrivate.ptr = NULL; 349 pExaPixmap->offscreen = FALSE; 350 351 pExaPixmap->fb_ptr = NULL; 352 exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); 353 pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; 354 355 if (pExaPixmap->fb_pitch > 131071) { 356 fbDestroyPixmap(pPixmap); 357 return NULL; 358 } 359 360 /* Set up damage tracking */ 361 pExaPixmap->pDamage = DamageCreate (NULL, NULL, 362 DamageReportNone, TRUE, 363 pScreen, pPixmap); 364 365 if (pExaPixmap->pDamage == NULL) { 366 fbDestroyPixmap (pPixmap); 367 return NULL; 368 } 369 370 DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); 371 /* This ensures that pending damage reflects the current operation. */ 372 /* This is used by exa to optimize migration. */ 373 DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); 374 } 375 376 pExaPixmap->area = NULL; 377 378 /* None of the pixmap bits are valid initially */ 379 REGION_NULL(pScreen, &pExaPixmap->validSys); 380 REGION_NULL(pScreen, &pExaPixmap->validFB); 381 382 exaSetAccelBlock(pExaScr, pExaPixmap, 383 w, h, bpp); 384 385 return pPixmap; 386} 387 388static Bool 389exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, 390 int bitsPerPixel, int devKind, pointer pPixData) 391{ 392 ExaScreenPrivPtr pExaScr; 393 ExaPixmapPrivPtr pExaPixmap; 394 Bool ret; 395 396 if (!pPixmap) 397 return FALSE; 398 399 pExaScr = ExaGetScreenPriv(pPixmap->drawable.pScreen); 400 pExaPixmap = ExaGetPixmapPriv(pPixmap); 401 402 if (pExaPixmap) { 403 if (pPixData) 404 pExaPixmap->sys_ptr = pPixData; 405 406 if (devKind > 0) 407 pExaPixmap->sys_pitch = devKind; 408 409 if (width > 0 && height > 0 && bitsPerPixel > 0) { 410 exaSetFbPitch(pExaScr, pExaPixmap, 411 width, height, bitsPerPixel); 412 413 exaSetAccelBlock(pExaScr, pExaPixmap, 414 width, height, bitsPerPixel); 415 } 416 } 417 418 419 if (pExaScr->info->ModifyPixmapHeader) { 420 ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, 421 bitsPerPixel, devKind, pPixData); 422 if (ret == TRUE) 423 return ret; 424 } 425 return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth, 426 bitsPerPixel, devKind, pPixData); 427} 428 429/** 430 * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen 431 * memory, meaning that acceleration could probably be done to it, and that it 432 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 433 * with the CPU. 434 * 435 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 436 * deal with moving pixmaps in and out of system memory), EXA will give drivers 437 * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE. 438 * 439 * @return TRUE if the given drawable is in framebuffer memory. 440 */ 441Bool 442exaPixmapIsOffscreen(PixmapPtr p) 443{ 444 ScreenPtr pScreen = p->drawable.pScreen; 445 ExaScreenPriv(pScreen); 446 ExaPixmapPriv(p); 447 void *save_ptr; 448 Bool ret; 449 450 save_ptr = p->devPrivate.ptr; 451 452 if (!save_ptr && pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) 453 p->devPrivate.ptr = ExaGetPixmapAddress(p); 454 455 if (pExaScr->info->PixmapIsOffscreen) 456 ret = pExaScr->info->PixmapIsOffscreen(p); 457 else 458 ret = ((unsigned long) ((CARD8 *) p->devPrivate.ptr - 459 (CARD8 *) pExaScr->info->memoryBase) < 460 pExaScr->info->memorySize); 461 462 p->devPrivate.ptr = save_ptr; 463 464 return ret; 465} 466 467/** 468 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen(). 469 */ 470Bool 471exaDrawableIsOffscreen (DrawablePtr pDrawable) 472{ 473 return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable)); 474} 475 476/** 477 * Returns the pixmap which backs a drawable, and the offsets to add to 478 * coordinates to make them address the same bits in the backing drawable. 479 */ 480PixmapPtr 481exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) 482{ 483 PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 484 485 exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp); 486 487 if (exaPixmapIsOffscreen (pPixmap)) 488 return pPixmap; 489 else 490 return NULL; 491} 492 493void 494ExaDoPrepareAccess(DrawablePtr pDrawable, int index) 495{ 496 ScreenPtr pScreen = pDrawable->pScreen; 497 ExaScreenPriv (pScreen); 498 PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 499 Bool offscreen = exaPixmapIsOffscreen(pPixmap); 500 501 /* Unhide pixmap pointer */ 502 if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 503 pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); 504 } 505 506 if (!offscreen) 507 return; 508 509 exaWaitSync (pDrawable->pScreen); 510 511 if (pExaScr->info->PrepareAccess == NULL) 512 return; 513 514 if (index >= EXA_PREPARE_AUX0 && 515 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 516 exaMoveOutPixmap (pPixmap); 517 return; 518 } 519 520 if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 521 ExaPixmapPriv (pPixmap); 522 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) 523 FatalError("Driver failed PrepareAccess on a pinned pixmap\n"); 524 exaMoveOutPixmap (pPixmap); 525 } 526} 527 528void 529exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg) 530{ 531 ExaMigrationRec pixmaps[1]; 532 533 pixmaps[0].as_dst = index == EXA_PREPARE_DEST; 534 pixmaps[0].as_src = index != EXA_PREPARE_DEST; 535 pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); 536 pixmaps[0].pReg = pReg; 537 538 exaDoMigration(pixmaps, 1, FALSE); 539 540 ExaDoPrepareAccess(pDrawable, index); 541} 542 543/** 544 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 545 * 546 * It deals with waiting for synchronization with the card, determining if 547 * PrepareAccess() is necessary, and working around PrepareAccess() failure. 548 */ 549void 550exaPrepareAccess(DrawablePtr pDrawable, int index) 551{ 552 exaPrepareAccessReg(pDrawable, index, NULL); 553} 554 555/** 556 * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. 557 * 558 * It deals with calling the driver's FinishAccess() only if necessary. 559 */ 560void 561exaFinishAccess(DrawablePtr pDrawable, int index) 562{ 563 ScreenPtr pScreen = pDrawable->pScreen; 564 ExaScreenPriv (pScreen); 565 PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); 566 ExaPixmapPriv (pPixmap); 567 568 /* Rehide pixmap pointer if we're doing that. */ 569 if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 570 pPixmap->devPrivate.ptr = NULL; 571 } 572 573 if (pExaScr->info->FinishAccess == NULL) 574 return; 575 576 if (!exaPixmapIsOffscreen (pPixmap)) 577 return; 578 579 if (index >= EXA_PREPARE_AUX0 && 580 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 581 ErrorF("EXA bug: Trying to call driver FinishAccess hook with " 582 "unsupported index EXA_PREPARE_AUX*\n"); 583 return; 584 } 585 586 (*pExaScr->info->FinishAccess) (pPixmap, index); 587} 588 589/** 590 * exaValidateGC() sets the ops to EXA's implementations, which may be 591 * accelerated or may sync the card and fall back to fb. 592 */ 593static void 594exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 595{ 596 /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 597 * Preempt fbValidateGC by doing its work and masking the change out, so 598 * that we can do the Prepare/FinishAccess. 599 */ 600#ifdef FB_24_32BIT 601 if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { 602 (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); 603 fbGetRotatedPixmap(pGC) = 0; 604 } 605 606 if (pGC->fillStyle == FillTiled) { 607 PixmapPtr pOldTile, pNewTile; 608 609 pOldTile = pGC->tile.pixmap; 610 if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 611 { 612 pNewTile = fbGetRotatedPixmap(pGC); 613 if (!pNewTile || 614 pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 615 { 616 if (pNewTile) 617 (*pGC->pScreen->DestroyPixmap) (pNewTile); 618 /* fb24_32ReformatTile will do direct access of a newly- 619 * allocated pixmap. This isn't a problem yet, since we don't 620 * put pixmaps in FB until at least one accelerated EXA op. 621 */ 622 exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 623 pNewTile = fb24_32ReformatTile (pOldTile, 624 pDrawable->bitsPerPixel); 625 exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); 626 exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); 627 } 628 if (pNewTile) 629 { 630 fbGetRotatedPixmap(pGC) = pOldTile; 631 pGC->tile.pixmap = pNewTile; 632 changes |= GCTile; 633 } 634 } 635 } 636#endif 637 if (changes & GCTile) { 638 if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * 639 pDrawable->bitsPerPixel)) 640 { 641 exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); 642 fbPadPixmap (pGC->tile.pixmap); 643 exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); 644 exaPixmapDirty(pGC->tile.pixmap, 0, 0, 645 pGC->tile.pixmap->drawable.width, 646 pGC->tile.pixmap->drawable.height); 647 } 648 /* Mask out the GCTile change notification, now that we've done FB's 649 * job for it. 650 */ 651 changes &= ~GCTile; 652 } 653 654 exaPrepareAccessGC(pGC); 655 fbValidateGC (pGC, changes, pDrawable); 656 exaFinishAccessGC(pGC); 657 658 pGC->ops = (GCOps *) &exaOps; 659} 660 661static GCFuncs exaGCFuncs = { 662 exaValidateGC, 663 miChangeGC, 664 miCopyGC, 665 miDestroyGC, 666 miChangeClip, 667 miDestroyClip, 668 miCopyClip 669}; 670 671/** 672 * exaCreateGC makes a new GC and hooks up its funcs handler, so that 673 * exaValidateGC() will get called. 674 */ 675static int 676exaCreateGC (GCPtr pGC) 677{ 678 if (!fbCreateGC (pGC)) 679 return FALSE; 680 681 pGC->funcs = &exaGCFuncs; 682 683 return TRUE; 684} 685 686static Bool 687exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 688{ 689 Bool ret; 690 691 if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 692 exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 693 694 if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 695 exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 696 697 ret = fbChangeWindowAttributes(pWin, mask); 698 699 if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) 700 exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); 701 702 if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 703 exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); 704 705 return ret; 706} 707 708static RegionPtr 709exaBitmapToRegion(PixmapPtr pPix) 710{ 711 RegionPtr ret; 712 exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC); 713 ret = fbPixmapToRegion(pPix); 714 exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC); 715 return ret; 716} 717 718static Bool 719exaCreateScreenResources(ScreenPtr pScreen) 720{ 721 ExaScreenPriv(pScreen); 722 PixmapPtr pScreenPixmap; 723 Bool b; 724 725 pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources; 726 b = pScreen->CreateScreenResources(pScreen); 727 pScreen->CreateScreenResources = exaCreateScreenResources; 728 729 if (!b) 730 return FALSE; 731 732 pScreenPixmap = pScreen->GetScreenPixmap(pScreen); 733 734 if (pScreenPixmap) { 735 ExaPixmapPriv(pScreenPixmap); 736 737 exaSetAccelBlock(pExaScr, pExaPixmap, 738 pScreenPixmap->drawable.width, 739 pScreenPixmap->drawable.height, 740 pScreenPixmap->drawable.bitsPerPixel); 741 } 742 743 return TRUE; 744} 745 746/** 747 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's 748 * screen private, before calling down to the next CloseSccreen. 749 */ 750static Bool 751exaCloseScreen(int i, ScreenPtr pScreen) 752{ 753 ExaScreenPriv(pScreen); 754#ifdef RENDER 755 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 756#endif 757 758 if (ps->Glyphs == exaGlyphs) 759 exaGlyphsFini(pScreen); 760 761 pScreen->CreateGC = pExaScr->SavedCreateGC; 762 pScreen->CloseScreen = pExaScr->SavedCloseScreen; 763 pScreen->GetImage = pExaScr->SavedGetImage; 764 pScreen->GetSpans = pExaScr->SavedGetSpans; 765 pScreen->CreatePixmap = pExaScr->SavedCreatePixmap; 766 pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap; 767 pScreen->CopyWindow = pExaScr->SavedCopyWindow; 768 pScreen->ChangeWindowAttributes = pExaScr->SavedChangeWindowAttributes; 769 pScreen->BitmapToRegion = pExaScr->SavedBitmapToRegion; 770 pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources; 771#ifdef RENDER 772 if (ps) { 773 ps->Composite = pExaScr->SavedComposite; 774 ps->Glyphs = pExaScr->SavedGlyphs; 775 ps->Trapezoids = pExaScr->SavedTrapezoids; 776 ps->Triangles = pExaScr->SavedTriangles; 777 ps->AddTraps = pExaScr->SavedAddTraps; 778 } 779#endif 780 781 xfree (pExaScr); 782 783 return (*pScreen->CloseScreen) (i, pScreen); 784} 785 786/** 787 * This function allocates a driver structure for EXA drivers to fill in. By 788 * having EXA allocate the structure, the driver structure can be extended 789 * without breaking ABI between EXA and the drivers. The driver's 790 * responsibility is to check beforehand that the EXA module has a matching 791 * major number and sufficient minor. Drivers are responsible for freeing the 792 * driver structure using xfree(). 793 * 794 * @return a newly allocated, zero-filled driver structure 795 */ 796ExaDriverPtr 797exaDriverAlloc(void) 798{ 799 return xcalloc(1, sizeof(ExaDriverRec)); 800} 801 802/** 803 * @param pScreen screen being initialized 804 * @param pScreenInfo EXA driver record 805 * 806 * exaDriverInit sets up EXA given a driver record filled in by the driver. 807 * pScreenInfo should have been allocated by exaDriverAlloc(). See the 808 * comments in _ExaDriver for what must be filled in and what is optional. 809 * 810 * @return TRUE if EXA was successfully initialized. 811 */ 812Bool 813exaDriverInit (ScreenPtr pScreen, 814 ExaDriverPtr pScreenInfo) 815{ 816 ExaScreenPrivPtr pExaScr; 817#ifdef RENDER 818 PictureScreenPtr ps; 819#endif 820 821 if (!pScreenInfo) 822 return FALSE; 823 824 if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || 825 pScreenInfo->exa_minor > EXA_VERSION_MINOR) 826 { 827 LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " 828 "(%d.%d) are incompatible with EXA version (%d.%d)\n", 829 pScreen->myNum, 830 pScreenInfo->exa_major, pScreenInfo->exa_minor, 831 EXA_VERSION_MAJOR, EXA_VERSION_MINOR); 832 return FALSE; 833 } 834 835 if (!pScreenInfo->CreatePixmap) { 836 if (!pScreenInfo->memoryBase) { 837 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase " 838 "must be non-zero\n", pScreen->myNum); 839 return FALSE; 840 } 841 842 if (!pScreenInfo->memorySize) { 843 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " 844 "non-zero\n", pScreen->myNum); 845 return FALSE; 846 } 847 848 if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { 849 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must " 850 "be <= ExaDriverRec::memorySize\n", pScreen->myNum); 851 return FALSE; 852 } 853 } 854 855 if (!pScreenInfo->PrepareSolid) { 856 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " 857 "non-NULL\n", pScreen->myNum); 858 return FALSE; 859 } 860 861 if (!pScreenInfo->PrepareCopy) { 862 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " 863 "non-NULL\n", pScreen->myNum); 864 return FALSE; 865 } 866 867 if (!pScreenInfo->WaitMarker) { 868 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " 869 "non-NULL\n", pScreen->myNum); 870 return FALSE; 871 } 872 873 /* If the driver doesn't set any max pitch values, we'll just assume 874 * that there's a limitation by pixels, and that it's the same as 875 * maxX. 876 * 877 * We want maxPitchPixels or maxPitchBytes to be set so we can check 878 * pixmaps against the max pitch in exaCreatePixmap() -- it matters 879 * whether a pixmap is rejected because of its pitch or 880 * because of its width. 881 */ 882 if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) 883 { 884 pScreenInfo->maxPitchPixels = pScreenInfo->maxX; 885 } 886 887#ifdef RENDER 888 ps = GetPictureScreenIfSet(pScreen); 889#endif 890 891 pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1); 892 893 if (!pExaScr) { 894 LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", 895 pScreen->myNum); 896 return FALSE; 897 } 898 899 pExaScr->info = pScreenInfo; 900 901 dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr); 902 903 pExaScr->migration = ExaMigrationAlways; 904 905 exaDDXDriverInit(pScreen); 906 907 /* 908 * Replace various fb screen functions 909 */ 910 pExaScr->SavedCloseScreen = pScreen->CloseScreen; 911 pScreen->CloseScreen = exaCloseScreen; 912 913 pExaScr->SavedCreateGC = pScreen->CreateGC; 914 pScreen->CreateGC = exaCreateGC; 915 916 pExaScr->SavedGetImage = pScreen->GetImage; 917 pScreen->GetImage = exaGetImage; 918 919 pExaScr->SavedGetSpans = pScreen->GetSpans; 920 pScreen->GetSpans = ExaCheckGetSpans; 921 922 pExaScr->SavedCopyWindow = pScreen->CopyWindow; 923 pScreen->CopyWindow = exaCopyWindow; 924 925 pExaScr->SavedChangeWindowAttributes = pScreen->ChangeWindowAttributes; 926 pScreen->ChangeWindowAttributes = exaChangeWindowAttributes; 927 928 pExaScr->SavedBitmapToRegion = pScreen->BitmapToRegion; 929 pScreen->BitmapToRegion = exaBitmapToRegion; 930 931 pExaScr->SavedCreateScreenResources = pScreen->CreateScreenResources; 932 pScreen->CreateScreenResources = exaCreateScreenResources; 933 934#ifdef RENDER 935 if (ps) { 936 pExaScr->SavedComposite = ps->Composite; 937 ps->Composite = exaComposite; 938 939 if (pScreenInfo->PrepareComposite) { 940 pExaScr->SavedGlyphs = ps->Glyphs; 941 ps->Glyphs = exaGlyphs; 942 } 943 944 pExaScr->SavedTriangles = ps->Triangles; 945 ps->Triangles = exaTriangles; 946 947 pExaScr->SavedTrapezoids = ps->Trapezoids; 948 ps->Trapezoids = exaTrapezoids; 949 950 pExaScr->SavedAddTraps = ps->AddTraps; 951 ps->AddTraps = ExaCheckAddTraps; 952 } 953#endif 954 955#ifdef MITSHM 956 /* 957 * Don't allow shared pixmaps. 958 */ 959 ShmRegisterFuncs(pScreen, &exaShmFuncs); 960#endif 961 /* 962 * Hookup offscreen pixmaps 963 */ 964 if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) 965 { 966 if (!dixRequestPrivate(exaPixmapPrivateKey, sizeof(ExaPixmapPrivRec))) { 967 LogMessage(X_WARNING, 968 "EXA(%d): Failed to allocate pixmap private\n", 969 pScreen->myNum); 970 return FALSE; 971 } 972 pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; 973 pScreen->CreatePixmap = exaCreatePixmap; 974 975 pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap; 976 pScreen->DestroyPixmap = exaDestroyPixmap; 977 978 pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader; 979 pScreen->ModifyPixmapHeader = exaModifyPixmapHeader; 980 if (!pExaScr->info->CreatePixmap) { 981 LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", 982 pScreen->myNum, 983 pExaScr->info->memorySize - pExaScr->info->offScreenBase); 984 } else { 985 LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n", 986 pScreen->myNum); 987 988 } 989 } 990 else 991 LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); 992 993 if (!pExaScr->info->CreatePixmap) { 994 DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, 995 pExaScr->info->memorySize)); 996 if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { 997 if (!exaOffscreenInit (pScreen)) { 998 LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n", 999 pScreen->myNum); 1000 return FALSE; 1001 } 1002 } 1003 } 1004 1005 if (ps->Glyphs == exaGlyphs) 1006 exaGlyphsInit(pScreen); 1007 1008 LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" 1009 " operations:\n", pScreen->myNum); 1010 assert(pScreenInfo->PrepareSolid != NULL); 1011 LogMessage(X_INFO, " Solid\n"); 1012 assert(pScreenInfo->PrepareCopy != NULL); 1013 LogMessage(X_INFO, " Copy\n"); 1014 if (pScreenInfo->PrepareComposite != NULL) { 1015 LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); 1016 } 1017 if (pScreenInfo->UploadToScreen != NULL) { 1018 LogMessage(X_INFO, " UploadToScreen\n"); 1019 } 1020 if (pScreenInfo->DownloadFromScreen != NULL) { 1021 LogMessage(X_INFO, " DownloadFromScreen\n"); 1022 } 1023 1024 return TRUE; 1025} 1026 1027/** 1028 * exaDriverFini tears down EXA on a given screen. 1029 * 1030 * @param pScreen screen being torn down. 1031 */ 1032void 1033exaDriverFini (ScreenPtr pScreen) 1034{ 1035 /*right now does nothing*/ 1036} 1037 1038/** 1039 * exaMarkSync() should be called after any asynchronous drawing by the hardware. 1040 * 1041 * @param pScreen screen which drawing occurred on 1042 * 1043 * exaMarkSync() sets a flag to indicate that some asynchronous drawing has 1044 * happened and a WaitSync() will be necessary before relying on the contents of 1045 * offscreen memory from the CPU's perspective. It also calls an optional 1046 * driver MarkSync() callback, the return value of which may be used to do partial 1047 * synchronization with the hardware in the future. 1048 */ 1049void exaMarkSync(ScreenPtr pScreen) 1050{ 1051 ExaScreenPriv(pScreen); 1052 1053 pExaScr->info->needsSync = TRUE; 1054 if (pExaScr->info->MarkSync != NULL) { 1055 pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen); 1056 } 1057} 1058 1059/** 1060 * exaWaitSync() ensures that all drawing has been completed. 1061 * 1062 * @param pScreen screen being synchronized. 1063 * 1064 * Calls down into the driver to ensure that all previous drawing has completed. 1065 * It should always be called before relying on the framebuffer contents 1066 * reflecting previous drawing, from a CPU perspective. 1067 */ 1068void exaWaitSync(ScreenPtr pScreen) 1069{ 1070 ExaScreenPriv(pScreen); 1071 1072 if (pExaScr->info->needsSync && !pExaScr->swappedOut) { 1073 (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker); 1074 pExaScr->info->needsSync = FALSE; 1075 } 1076} 1077