saa.c revision 25dbecb6
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 SAA, 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 "saa_priv.h" 38#include <X11/fonts/fontstruct.h> 39#include "regionstr.h" 40#include "saa.h" 41#include "saa_priv.h" 42 43#ifdef SAA_DEVPRIVATEKEYREC 44DevPrivateKeyRec saa_screen_index; 45DevPrivateKeyRec saa_pixmap_index; 46DevPrivateKeyRec saa_gc_index; 47#else 48int saa_screen_index = -1; 49int saa_pixmap_index = -1; 50int saa_gc_index = -1; 51#endif 52 53/** 54 * saa_get_drawable_pixmap() returns a backing pixmap for a given drawable. 55 * 56 * @param pDrawable the drawable being requested. 57 * 58 * This function returns the backing pixmap for a drawable, whether it is a 59 * redirected window, unredirected window, or already a pixmap. Note that 60 * coordinate translation is needed when drawing to the backing pixmap of a 61 * redirected window, and the translation coordinates are provided by calling 62 * saa_get_drawable_pixmap() on the drawable. 63 */ 64PixmapPtr 65saa_get_drawable_pixmap(DrawablePtr pDrawable) 66{ 67 if (pDrawable->type == DRAWABLE_WINDOW) 68 return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); 69 else 70 return (PixmapPtr) pDrawable; 71} 72 73/** 74 * Sets the offsets to add to coordinates to make them address the same bits in 75 * the backing drawable. These coordinates are nonzero only for redirected 76 * windows. 77 */ 78void 79saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap, 80 int *xp, int *yp) 81{ 82#ifdef COMPOSITE 83 if (pDrawable->type == DRAWABLE_WINDOW) { 84 *xp = -pPixmap->screen_x; 85 *yp = -pPixmap->screen_y; 86 return; 87 } 88#endif 89 90 *xp = 0; 91 *yp = 0; 92} 93 94/** 95 * Returns the pixmap which backs a drawable, and the offsets to add to 96 * coordinates to make them address the same bits in the backing drawable. 97 */ 98PixmapPtr 99saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp) 100{ 101 PixmapPtr pixmap = saa_get_drawable_pixmap(drawable); 102 103 saa_get_drawable_deltas(drawable, pixmap, xp, yp); 104 105 return pixmap; 106} 107 108static Bool 109saa_download_from_hw(PixmapPtr pix, RegionPtr readback) 110{ 111 struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); 112 struct saa_driver *driver = sscreen->driver; 113 struct saa_pixmap *spix = saa_pixmap(pix); 114 void *addr; 115 Bool ret; 116 117 if (spix->mapped_access) 118 driver->release_from_cpu(driver, pix, spix->mapped_access); 119 120 ret = driver->download_from_hw(driver, pix, readback); 121 122 if (spix->mapped_access) { 123 addr = driver->sync_for_cpu(driver, pix, spix->mapped_access); 124 if (addr != NULL) 125 spix->addr = addr; 126 } 127 128 return ret; 129} 130 131Bool 132saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access, 133 RegionPtr read_reg) 134{ 135 ScreenPtr pScreen = pix->drawable.pScreen; 136 struct saa_screen_priv *sscreen = saa_screen(pScreen); 137 struct saa_driver *driver = sscreen->driver; 138 struct saa_pixmap *spix = saa_pixmap(pix); 139 saa_access_t map_access = 0; 140 Bool ret = TRUE; 141 142 if (read_reg && REGION_NOTEMPTY(pScreen, read_reg)) 143 ret = saa_download_from_hw(pix, read_reg); 144 145 if (!ret) { 146 LogMessage(X_ERROR, "Prepare access pixmap failed.\n"); 147 return ret; 148 } 149 150 if ((access & SAA_ACCESS_R) != 0 && spix->read_access++ == 0) 151 map_access = SAA_ACCESS_R; 152 if ((access & SAA_ACCESS_W) != 0 && spix->write_access++ == 0) 153 map_access |= SAA_ACCESS_W; 154 155 if (map_access) { 156 if (spix->auth_loc != saa_loc_override) { 157 (void)driver->sync_for_cpu(driver, pix, map_access); 158 spix->addr = driver->map(driver, pix, map_access); 159 } else 160 spix->addr = spix->override; 161 spix->mapped_access |= map_access; 162 } 163 164 pix->devPrivate.ptr = spix->addr; 165 return TRUE; 166} 167 168void 169saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access) 170{ 171 struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); 172 struct saa_driver *driver = sscreen->driver; 173 struct saa_pixmap *spix = saa_pixmap(pix); 174 saa_access_t unmap_access = 0; 175 176 if ((access & SAA_ACCESS_R) != 0 && --spix->read_access == 0) 177 unmap_access = SAA_ACCESS_R; 178 if ((access & SAA_ACCESS_W) != 0 && --spix->write_access == 0) 179 unmap_access |= SAA_ACCESS_W; 180 181 if (spix->read_access < 0) 182 LogMessage(X_ERROR, "Incorrect read access.\n"); 183 if (spix->write_access < 0) 184 LogMessage(X_ERROR, "Incorrect write access.\n"); 185 186 if (unmap_access) { 187 if (spix->auth_loc != saa_loc_override) { 188 driver->unmap(driver, pix, unmap_access); 189 driver->release_from_cpu(driver, pix, unmap_access); 190 } 191 spix->mapped_access &= ~unmap_access; 192 } 193 if (!spix->mapped_access) { 194 spix->addr = NULL; 195 pix->devPrivate.ptr = SAA_INVALID_ADDRESS; 196 } 197} 198 199/* 200 * Callback that is called after a rendering operation. We try to 201 * determine whether it's a shadow damage or a hw damage and call the 202 * driver callback. 203 */ 204 205static void 206saa_report_damage(DamagePtr damage, RegionPtr reg, void *closure) 207{ 208 PixmapPtr pixmap = (PixmapPtr) closure; 209 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); 210 struct saa_driver *driver = saa_screen(pixmap->drawable.pScreen)->driver; 211 212 if (spix->read_access || spix->write_access) 213 LogMessage(X_ERROR, "Damage report inside prepare access.\n"); 214 215 driver->operation_complete(driver, pixmap); 216 DamageEmpty(damage); 217} 218 219/** 220 * saa_notify_destroy_damage - Handle destroy damage notification 221 * 222 * \param damage[in] damage Pointer to damage about to be destroyed 223 * \param closure[in] closure Closure. 224 * 225 * Makes sure that whatever code destroys a damage object clears the 226 * saa_pixmap damage pointer. This is extra protection. Typically 227 * saa_destroy_pixmap should be correct if the various subsystem 228 * DestroyPixmap functions are called in the right order. 229 */ 230static void 231saa_notify_destroy_damage(DamagePtr damage, void *closure) 232{ 233 PixmapPtr pixmap = (PixmapPtr) closure; 234 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); 235 236 if (spix->damage == damage) 237 spix->damage = NULL; 238} 239 240Bool 241saa_add_damage(PixmapPtr pixmap) 242{ 243 ScreenPtr pScreen = pixmap->drawable.pScreen; 244 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); 245 246 if (spix->damage) 247 return TRUE; 248 249 spix->damage = DamageCreate(saa_report_damage, saa_notify_destroy_damage, 250 DamageReportRawRegion, TRUE, pScreen, pixmap); 251 if (!spix->damage) 252 return FALSE; 253 254 DamageRegister(&pixmap->drawable, spix->damage); 255 DamageSetReportAfterOp(spix->damage, TRUE); 256 257 return TRUE; 258} 259 260static inline RegionPtr 261saa_pix_damage_region(struct saa_pixmap *spix) 262{ 263 return (spix->damage ? DamageRegion(spix->damage) : NULL); 264} 265 266Bool 267saa_pad_read(DrawablePtr draw) 268{ 269 ScreenPtr pScreen = draw->pScreen; 270 PixmapPtr pix; 271 int xp; 272 int yp; 273 BoxRec box; 274 RegionRec entire; 275 Bool ret; 276 277 (void)pScreen; 278 pix = saa_get_pixmap(draw, &xp, &yp); 279 280 box.x1 = draw->x + xp; 281 box.y1 = draw->y + yp; 282 box.x2 = box.x1 + draw->width; 283 box.y2 = box.y1 + draw->height; 284 285 REGION_INIT(pScreen, &entire, &box, 1); 286 ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); 287 REGION_UNINIT(pScreen, &entire); 288 return ret; 289} 290 291Bool 292saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h) 293{ 294 ScreenPtr pScreen = draw->pScreen; 295 PixmapPtr pix; 296 int xp; 297 int yp; 298 BoxRec box; 299 RegionRec entire; 300 Bool ret; 301 302 (void)pScreen; 303 pix = saa_get_pixmap(draw, &xp, &yp); 304 305 box.x1 = x + xp; 306 box.y1 = y + yp; 307 box.x2 = box.x1 + w; 308 box.y2 = box.y1 + h; 309 310 REGION_INIT(pScreen, &entire, &box, 1); 311 ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); 312 REGION_UNINIT(pScreen, &entire); 313 return ret; 314} 315 316/** 317 * Prepares a drawable destination for access, and maps it read-write. 318 * If check_read is TRUE, pGC should point to a valid GC. The drawable 319 * may then be mapped write-only if the pending operation admits. 320 */ 321 322Bool 323saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read, 324 saa_access_t * access) 325{ 326 int xp; 327 int yp; 328 PixmapPtr pixmap = saa_get_pixmap(draw, &xp, &yp); 329 struct saa_pixmap *spix = saa_pixmap(pixmap); 330 331 *access = SAA_ACCESS_W; 332 333 /* 334 * If the to-be-damaged area doesn't depend at all on previous 335 * rendered contents, we don't need to do any readback. 336 */ 337 338 if (check_read && !saa_gc_reads_destination(draw, pGC)) 339 return saa_prepare_access_pixmap(pixmap, *access, NULL); 340 341 *access |= SAA_ACCESS_R; 342 343 /* 344 * Read back the area to be damaged. 345 */ 346 347 return saa_prepare_access_pixmap(pixmap, *access, 348 saa_pix_damage_pending(spix)); 349} 350 351void 352saa_fad_read(DrawablePtr draw) 353{ 354 saa_finish_access_pixmap(saa_get_drawable_pixmap(draw), SAA_ACCESS_R); 355} 356 357void 358saa_fad_write(DrawablePtr draw, saa_access_t access) 359{ 360 PixmapPtr pix = saa_get_drawable_pixmap(draw); 361 struct saa_pixmap *spix = saa_pixmap(pix); 362 363 saa_finish_access_pixmap(pix, access); 364 if (spix->damage) 365 saa_pixmap_dirty(pix, FALSE, saa_pix_damage_pending(spix)); 366} 367 368Bool 369saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC) 370{ 371 return ((pGC->alu != GXcopy && pGC->alu != GXclear && pGC->alu != GXset && 372 pGC->alu != GXcopyInverted) || pGC->fillStyle == FillStippled || 373 pGC->clientClip != NULL || 374 !SAA_PM_IS_SOLID(pDrawable, pGC->planemask)); 375} 376 377Bool 378saa_op_reads_destination(CARD8 op) 379{ 380 /* FALSE (does not read destination) is the list of ops in the protocol 381 * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. 382 * That's just Clear and Src. ReduceCompositeOp() will already have 383 * converted con/disjoint clear/src to Clear or Src. 384 */ 385 switch (op) { 386 case PictOpClear: 387 case PictOpSrc: 388 return FALSE; 389 default: 390 return TRUE; 391 } 392} 393 394static void 395saa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 396{ 397 /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 398 * Do a few smart things so fbValidateGC can do it's work. 399 */ 400 401 ScreenPtr pScreen = pDrawable->pScreen; 402 struct saa_screen_priv *sscreen = saa_screen(pScreen); 403 struct saa_gc_priv *sgc = saa_gc(pGC); 404 PixmapPtr pTile = NULL; 405 Bool finish_current_tile = FALSE; 406 407 /* Either of these conditions is enough to trigger access to a tile pixmap. */ 408 /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */ 409 if (pGC->fillStyle == FillTiled 410 || ((changes & GCTile) && !pGC->tileIsPixel)) { 411 pTile = pGC->tile.pixmap; 412 413 /* Sometimes tile pixmaps are swapped, you need access to: 414 * - The current tile if it depth matches. 415 * - Or the rotated tile if that one matches depth and !(changes & GCTile). 416 * - Or the current tile pixmap and a newly created one. 417 */ 418 if (pTile && pTile->drawable.depth != pDrawable->depth 419 && !(changes & GCTile)) { 420 PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC); 421 422 if (pRotatedTile 423 && pRotatedTile->drawable.depth == pDrawable->depth) 424 pTile = pRotatedTile; 425 else 426 finish_current_tile = TRUE; /* CreatePixmap will be called. */ 427 } 428 } 429 430 if (pGC->stipple && !saa_pad_read(&pGC->stipple->drawable)) { 431 LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); 432 return; 433 } 434 435 if (pTile && !saa_pad_read(&pTile->drawable)) { 436 LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); 437 goto out_no_tile; 438 } 439 440 /* Calls to Create/DestroyPixmap have to be identified as special, so 441 * up sscreen->fallback_count. 442 */ 443 444 sscreen->fallback_count++; 445 saa_swap(sgc, pGC, funcs); 446 (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); 447 saa_swap(sgc, pGC, funcs); 448 449 if (finish_current_tile && pGC->tile.pixmap) 450 saa_fad_write(&pGC->tile.pixmap->drawable, SAA_ACCESS_W); 451 sscreen->fallback_count--; 452 453 if (pTile) 454 saa_fad_read(&pTile->drawable); 455 out_no_tile: 456 if (pGC->stipple) 457 saa_fad_read(&pGC->stipple->drawable); 458} 459 460static void 461saa_destroy_gc(GCPtr pGC) 462{ 463 struct saa_gc_priv *sgc = saa_gc(pGC); 464 465 saa_swap(sgc, pGC, funcs); 466 (*pGC->funcs->DestroyGC) (pGC); 467 saa_swap(sgc, pGC, funcs); 468} 469 470static void 471saa_change_gc(GCPtr pGC, unsigned long mask) 472{ 473 struct saa_gc_priv *sgc = saa_gc(pGC); 474 475 saa_swap(sgc, pGC, funcs); 476 (*pGC->funcs->ChangeGC) (pGC, mask); 477 saa_swap(sgc, pGC, funcs); 478} 479 480static void 481saa_copy_gc(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) 482{ 483 struct saa_gc_priv *sgc = saa_gc(pGCDst); 484 485 saa_swap(sgc, pGCDst, funcs); 486 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); 487 saa_swap(sgc, pGCDst, funcs); 488} 489 490static void 491saa_change_clip(GCPtr pGC, int type, pointer pvalue, int nrects) 492{ 493 struct saa_gc_priv *sgc = saa_gc(pGC); 494 495 saa_swap(sgc, pGC, funcs); 496 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); 497 saa_swap(sgc, pGC, funcs); 498} 499 500static void 501saa_copy_clip(GCPtr pGCDst, GCPtr pGCSrc) 502{ 503 struct saa_gc_priv *sgc = saa_gc(pGCDst); 504 505 saa_swap(sgc, pGCDst, funcs); 506 (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); 507 saa_swap(sgc, pGCDst, funcs); 508} 509 510static void 511saa_destroy_clip(GCPtr pGC) 512{ 513 struct saa_gc_priv *sgc = saa_gc(pGC); 514 515 saa_swap(sgc, pGC, funcs); 516 (*pGC->funcs->DestroyClip) (pGC); 517 saa_swap(sgc, pGC, funcs); 518} 519 520static GCFuncs saa_gc_funcs = { 521 saa_validate_gc, 522 saa_change_gc, 523 saa_copy_gc, 524 saa_destroy_gc, 525 saa_change_clip, 526 saa_destroy_clip, 527 saa_copy_clip 528}; 529 530/** 531 * saa_create_gc makes a new GC and hooks up its funcs handler, so that 532 * saa_validate_gc() will get called. 533 */ 534int 535saa_create_gc(GCPtr pGC) 536{ 537 ScreenPtr pScreen = pGC->pScreen; 538 struct saa_screen_priv *sscreen = saa_screen(pScreen); 539 struct saa_gc_priv *sgc = saa_gc(pGC); 540 Bool ret; 541 542 saa_swap(sscreen, pScreen, CreateGC); 543 ret = pScreen->CreateGC(pGC); 544 if (ret) { 545 saa_wrap(sgc, pGC, funcs, &saa_gc_funcs); 546 saa_wrap(sgc, pGC, ops, &saa_gc_ops); 547 } 548 saa_swap(sscreen, pScreen, CreateGC); 549 550 return ret; 551} 552 553static Bool 554saa_prepare_access_window(WindowPtr pWin) 555{ 556 if (pWin->backgroundState == BackgroundPixmap) { 557 if (!saa_pad_read(&pWin->background.pixmap->drawable)) 558 return FALSE; 559 } 560 561 if (pWin->borderIsPixel == FALSE) { 562 if (!saa_pad_read(&pWin->border.pixmap->drawable)) { 563 if (pWin->backgroundState == BackgroundPixmap) 564 saa_fad_read(&pWin->background.pixmap->drawable); 565 return FALSE; 566 } 567 } 568 return TRUE; 569} 570 571static void 572saa_finish_access_window(WindowPtr pWin) 573{ 574 if (pWin->backgroundState == BackgroundPixmap) 575 saa_fad_read(&pWin->background.pixmap->drawable); 576 577 if (pWin->borderIsPixel == FALSE) 578 saa_fad_read(&pWin->border.pixmap->drawable); 579} 580 581static Bool 582saa_change_window_attributes(WindowPtr pWin, unsigned long mask) 583{ 584 Bool ret; 585 586 if (!saa_prepare_access_window(pWin)) 587 return FALSE; 588 ret = fbChangeWindowAttributes(pWin, mask); 589 saa_finish_access_window(pWin); 590 return ret; 591} 592 593RegionPtr 594saa_bitmap_to_region(PixmapPtr pPix) 595{ 596 RegionPtr ret; 597 598 if (!saa_pad_read(&pPix->drawable)) 599 return NULL; 600 ret = fbPixmapToRegion(pPix); 601 saa_fad_read(&pPix->drawable); 602 return ret; 603} 604 605void 606saa_set_fallback_debug(ScreenPtr screen, Bool enable) 607{ 608 struct saa_screen_priv *sscreen = saa_screen(screen); 609 610 sscreen->fallback_debug = enable; 611} 612 613/** 614 * saa_early_close_screen() Makes sure we call saa_destroy_pixmap on the 615 * miScreenInit() pixmap _before_ damageCloseScreen, after which it will 616 * generate an invalid memory access. Also unwraps the functions we 617 * wrapped _after_ DamageSetup(). 618 */ 619static Bool 620saa_early_close_screen(CLOSE_SCREEN_ARGS_DECL) 621{ 622 struct saa_screen_priv *sscreen = saa_screen(pScreen); 623 624 if (pScreen->devPrivate) { 625 /* Destroy the pixmap created by miScreenInit() *before* 626 * chaining up as we finalize ourselves here and so this 627 * is the last chance we have of releasing our resources 628 * associated with the Pixmap. So do it first. 629 */ 630 (void)(*pScreen->DestroyPixmap) (pScreen->devPrivate); 631 pScreen->devPrivate = NULL; 632 } 633 634 saa_unwrap_early(sscreen, pScreen, CloseScreen); 635 saa_unwrap(sscreen, pScreen, DestroyPixmap); 636 637 return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 638} 639 640/** 641 * saa_close_screen() unwraps its wrapped screen functions and tears down SAA's 642 * screen private, before calling down to the next CloseScreen. 643 */ 644Bool 645saa_close_screen(CLOSE_SCREEN_ARGS_DECL) 646{ 647 struct saa_screen_priv *sscreen = saa_screen(pScreen); 648 struct saa_driver *driver = sscreen->driver; 649 650 saa_unwrap(sscreen, pScreen, CloseScreen); 651 saa_unwrap(sscreen, pScreen, CreateGC); 652 saa_unwrap(sscreen, pScreen, ChangeWindowAttributes); 653 saa_unwrap(sscreen, pScreen, CreatePixmap); 654 saa_unwrap(sscreen, pScreen, ModifyPixmapHeader); 655 saa_unwrap(sscreen, pScreen, BitmapToRegion); 656#ifdef RENDER 657 saa_render_takedown(pScreen); 658#endif 659 saa_unaccel_takedown(pScreen); 660 driver->takedown(driver); 661 662 free(sscreen); 663 664 return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 665} 666 667struct saa_driver * 668saa_get_driver(ScreenPtr pScreen) 669{ 670 return saa_screen(pScreen)->driver; 671} 672 673/** 674 * @param pScreen screen being initialized 675 * @param pScreenInfo SAA driver record 676 * 677 * saa_driver_init sets up SAA given a driver record filled in by the driver. 678 * pScreenInfo should have been allocated by saa_driver_alloc(). See the 679 * comments in _SaaDriver for what must be filled in and what is optional. 680 * 681 * @return TRUE if SAA was successfully initialized. 682 */ 683Bool 684saa_driver_init(ScreenPtr screen, struct saa_driver * saa_driver) 685{ 686 struct saa_screen_priv *sscreen; 687 688 if (!saa_driver) 689 return FALSE; 690 691 if (saa_driver->saa_major != SAA_VERSION_MAJOR || 692 saa_driver->saa_minor > SAA_VERSION_MINOR) { 693 LogMessage(X_ERROR, 694 "SAA(%d): driver's SAA version requirements " 695 "(%d.%d) are incompatible with SAA version (%d.%d)\n", 696 screen->myNum, saa_driver->saa_major, 697 saa_driver->saa_minor, SAA_VERSION_MAJOR, SAA_VERSION_MINOR); 698 return FALSE; 699 } 700#if 0 701 if (!saa_driver->prepare_solid) { 702 LogMessage(X_ERROR, 703 "SAA(%d): saa_driver_t::prepare_solid must be " 704 "non-NULL\n", screen->myNum); 705 return FALSE; 706 } 707 708 if (!saa_driver->prepare_copy) { 709 LogMessage(X_ERROR, 710 "SAA(%d): saa_driver_t::prepare_copy must be " 711 "non-NULL\n", screen->myNum); 712 return FALSE; 713 } 714#endif 715#ifdef SAA_DEVPRIVATEKEYREC 716 if (!dixRegisterPrivateKey(&saa_screen_index, PRIVATE_SCREEN, 0)) { 717 LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); 718 return FALSE; 719 } 720 if (!dixRegisterPrivateKey(&saa_pixmap_index, PRIVATE_PIXMAP, 721 saa_driver->pixmap_size)) { 722 LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); 723 return FALSE; 724 } 725 if (!dixRegisterPrivateKey(&saa_gc_index, PRIVATE_GC, 726 sizeof(struct saa_gc_priv))) { 727 LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); 728 return FALSE; 729 } 730#else 731 if (!dixRequestPrivate(&saa_screen_index, 0)) { 732 LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); 733 return FALSE; 734 } 735 if (!dixRequestPrivate(&saa_pixmap_index, saa_driver->pixmap_size)) { 736 LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); 737 return FALSE; 738 } 739 if (!dixRequestPrivate(&saa_gc_index, sizeof(struct saa_gc_priv))) { 740 LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); 741 return FALSE; 742 } 743#endif 744 745 sscreen = calloc(1, sizeof(*sscreen)); 746 747 if (!sscreen) { 748 LogMessage(X_WARNING, 749 "SAA(%d): Failed to allocate screen private\n", 750 screen->myNum); 751 return FALSE; 752 } 753 754 sscreen->driver = saa_driver; 755 dixSetPrivate(&screen->devPrivates, &saa_screen_index, sscreen); 756 757 /* 758 * Replace various fb screen functions 759 */ 760 761 saa_wrap(sscreen, screen, CloseScreen, saa_close_screen); 762 saa_wrap(sscreen, screen, CreateGC, saa_create_gc); 763 saa_wrap(sscreen, screen, ChangeWindowAttributes, 764 saa_change_window_attributes); 765 saa_wrap(sscreen, screen, CreatePixmap, saa_create_pixmap); 766 saa_wrap(sscreen, screen, ModifyPixmapHeader, saa_modify_pixmap_header); 767 saa_wrap(sscreen, screen, BitmapToRegion, saa_bitmap_to_region); 768 saa_unaccel_setup(screen); 769#ifdef RENDER 770 saa_render_setup(screen); 771#endif 772 773 /* 774 * Correct saa functionality relies on Damage, so set it up now. 775 * Note that this must happen _after_ wrapping the rendering functionality 776 * so that damage happens outside of saa. 777 */ 778 if (!DamageSetup(screen)) 779 return FALSE; 780 781 /* 782 * Wrap DestroyPixmap after DamageSetup, so that saa_destroy_pixmap is 783 * called _before_ damageDestroyPixmap. This is to make damageDestroyPixmap 784 * doesn't free objects pointed to by our damage pointers. 785 * 786 * Also wrap an early CloseScreen to perform actions needed to be done 787 * before damageCloseScreen and to unwrap DestroyPixmap correctly. 788 */ 789 saa_wrap(sscreen, screen, DestroyPixmap, saa_destroy_pixmap); 790 saa_wrap_early(sscreen, screen, CloseScreen, saa_early_close_screen); 791 792 return TRUE; 793} 794 795Bool 796saa_resources_init(ScreenPtr screen) 797{ 798/* if (!saa_glyphs_init(screen)) 799 return FALSE; 800*/ 801 return TRUE; 802} 803