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 UXA, 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 "uxa-priv.h" 38#include <X11/fonts/fontstruct.h> 39#include "dixfontstr.h" 40#include "uxa.h" 41 42DevPrivateKeyRec uxa_screen_index; 43 44/** 45 * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable. 46 * 47 * @param pDrawable the drawable being requested. 48 * 49 * This function returns the backing pixmap for a drawable, whether it is a 50 * redirected window, unredirected window, or already a pixmap. Note that 51 * coordinate translation is needed when drawing to the backing pixmap of a 52 * redirected window, and the translation coordinates are provided by calling 53 * uxa_get_drawable_pixmap() on the drawable. 54 */ 55PixmapPtr 56uxa_get_drawable_pixmap(DrawablePtr pDrawable) 57{ 58 if (pDrawable->type == DRAWABLE_WINDOW) 59 return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable); 60 else 61 return (PixmapPtr) pDrawable; 62} 63 64/** 65 * Sets the offsets to add to coordinates to make them address the same bits in 66 * the backing drawable. These coordinates are nonzero only for redirected 67 * windows. 68 */ 69void 70uxa_get_drawable_deltas (DrawablePtr pDrawable, PixmapPtr pPixmap, 71 int *xp, int *yp) 72{ 73#ifdef COMPOSITE 74 if (pDrawable->type == DRAWABLE_WINDOW) { 75 *xp = -pPixmap->screen_x; 76 *yp = -pPixmap->screen_y; 77 return; 78 } 79#endif 80 81 *xp = 0; 82 *yp = 0; 83} 84 85/** 86 * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen 87 * memory, meaning that acceleration could probably be done to it, and that it 88 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 89 * with the CPU. 90 * 91 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 92 * deal with moving pixmaps in and out of system memory), UXA will give drivers 93 * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE. 94 * 95 * @return TRUE if the given drawable is in framebuffer memory. 96 */ 97Bool 98uxa_pixmap_is_offscreen(PixmapPtr p) 99{ 100 ScreenPtr pScreen = p->drawable.pScreen; 101 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 102 103 if (uxa_screen->info->pixmap_is_offscreen) 104 return uxa_screen->info->pixmap_is_offscreen(p); 105 106 return FALSE; 107} 108 109/** 110 * uxa_drawable_is_offscreen() is a convenience wrapper for uxa_pixmap_is_offscreen(). 111 */ 112Bool 113uxa_drawable_is_offscreen (DrawablePtr pDrawable) 114{ 115 return uxa_pixmap_is_offscreen (uxa_get_drawable_pixmap (pDrawable)); 116} 117 118/** 119 * Returns the pixmap which backs a drawable, and the offsets to add to 120 * coordinates to make them address the same bits in the backing drawable. 121 */ 122PixmapPtr 123uxa_get_offscreen_pixmap (DrawablePtr drawable, int *xp, int *yp) 124{ 125 PixmapPtr pixmap = uxa_get_drawable_pixmap (drawable); 126 127 uxa_get_drawable_deltas (drawable, pixmap, xp, yp); 128 129 if (uxa_pixmap_is_offscreen (pixmap)) 130 return pixmap; 131 else 132 return NULL; 133} 134 135 136 137/** 138 * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler. 139 * 140 * It deals with waiting for synchronization with the card, determining if 141 * PrepareAccess() is necessary, and working around PrepareAccess() failure. 142 */ 143Bool 144uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access) 145{ 146 ScreenPtr pScreen = pDrawable->pScreen; 147 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 148 PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable); 149 Bool offscreen = uxa_pixmap_is_offscreen(pPixmap); 150 151 if (!offscreen) 152 return TRUE; 153 154 if (uxa_screen->info->prepare_access) 155 return (*uxa_screen->info->prepare_access) (pPixmap, access); 156 return TRUE; 157} 158 159/** 160 * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler. 161 * 162 * It deals with calling the driver's finish_access() only if necessary. 163 */ 164void 165uxa_finish_access(DrawablePtr pDrawable) 166{ 167 ScreenPtr pScreen = pDrawable->pScreen; 168 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 169 PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable); 170 171 if (uxa_screen->info->finish_access == NULL) 172 return; 173 174 if (!uxa_pixmap_is_offscreen (pPixmap)) 175 return; 176 177 (*uxa_screen->info->finish_access) (pPixmap); 178} 179 180/** 181 * uxa_validate_gc() sets the ops to UXA's implementations, which may be 182 * accelerated or may sync the card and fall back to fb. 183 */ 184static void 185uxa_validate_gc (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 186{ 187 /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 188 * Preempt fbValidateGC by doing its work and masking the change out, so 189 * that we can do the Prepare/finish_access. 190 */ 191#ifdef FB_24_32BIT 192 if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { 193 (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); 194 fbGetRotatedPixmap(pGC) = 0; 195 } 196 197 if (pGC->fillStyle == FillTiled) { 198 PixmapPtr pOldTile, pNewTile; 199 200 pOldTile = pGC->tile.pixmap; 201 if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 202 { 203 pNewTile = fbGetRotatedPixmap(pGC); 204 if (!pNewTile || 205 pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) 206 { 207 if (pNewTile) 208 (*pGC->pScreen->DestroyPixmap) (pNewTile); 209 /* fb24_32ReformatTile will do direct access of a newly- 210 * allocated pixmap. This isn't a problem yet, since we don't 211 * put pixmaps in FB until at least one accelerated UXA op. 212 */ 213 if (uxa_prepare_access(&pOldTile->drawable, UXA_ACCESS_RO)) { 214 pNewTile = fb24_32ReformatTile (pOldTile, 215 pDrawable->bitsPerPixel); 216 uxa_finish_access(&pOldTile->drawable); 217 } 218 } 219 if (pNewTile) 220 { 221 fbGetRotatedPixmap(pGC) = pOldTile; 222 pGC->tile.pixmap = pNewTile; 223 changes |= GCTile; 224 } 225 } 226 } 227#endif 228 if (changes & GCTile) { 229 if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * 230 pDrawable->bitsPerPixel)) 231 { 232 if (uxa_prepare_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RW)) { 233 fbPadPixmap (pGC->tile.pixmap); 234 uxa_finish_access(&pGC->tile.pixmap->drawable); 235 } 236 } 237 /* Mask out the GCTile change notification, now that we've done FB's 238 * job for it. 239 */ 240 changes &= ~GCTile; 241 } 242 243 if (changes & GCStipple && pGC->stipple) { 244 /* We can't inline stipple handling like we do for GCTile because it sets 245 * fbgc privates. 246 */ 247 if (uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RW)) { 248 fbValidateGC (pGC, changes, pDrawable); 249 uxa_finish_access(&pGC->stipple->drawable); 250 } 251 } else { 252 fbValidateGC (pGC, changes, pDrawable); 253 } 254 255 pGC->ops = (GCOps *) &uxa_ops; 256} 257 258static GCFuncs uxaGCFuncs = { 259 uxa_validate_gc, 260 miChangeGC, 261 miCopyGC, 262 miDestroyGC, 263 miChangeClip, 264 miDestroyClip, 265 miCopyClip 266}; 267 268/** 269 * uxa_create_gc makes a new GC and hooks up its funcs handler, so that 270 * uxa_validate_gc() will get called. 271 */ 272static int 273uxa_create_gc (GCPtr pGC) 274{ 275 if (!fbCreateGC (pGC)) 276 return FALSE; 277 278 pGC->funcs = &uxaGCFuncs; 279 280 return TRUE; 281} 282 283Bool 284uxa_prepare_access_window(WindowPtr pWin) 285{ 286 if (pWin->backgroundState == BackgroundPixmap) { 287 if (!uxa_prepare_access(&pWin->background.pixmap->drawable, UXA_ACCESS_RO)) 288 return FALSE; 289 } 290 291 if (pWin->borderIsPixel == FALSE) { 292 if (!uxa_prepare_access(&pWin->border.pixmap->drawable, UXA_ACCESS_RO)) { 293 if (pWin->backgroundState == BackgroundPixmap) 294 uxa_finish_access(&pWin->background.pixmap->drawable); 295 return FALSE; 296 } 297 } 298 return TRUE; 299} 300 301void 302uxa_finish_access_window(WindowPtr pWin) 303{ 304 if (pWin->backgroundState == BackgroundPixmap) 305 uxa_finish_access(&pWin->background.pixmap->drawable); 306 307 if (pWin->borderIsPixel == FALSE) 308 uxa_finish_access(&pWin->border.pixmap->drawable); 309} 310 311static Bool 312uxa_change_window_attributes(WindowPtr pWin, unsigned long mask) 313{ 314 Bool ret; 315 316 if (!uxa_prepare_access_window(pWin)) 317 return FALSE; 318 ret = fbChangeWindowAttributes(pWin, mask); 319 uxa_finish_access_window(pWin); 320 return ret; 321} 322 323static RegionPtr 324uxa_bitmap_to_region(PixmapPtr pPix) 325{ 326 RegionPtr ret; 327 if (!uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO)) 328 return NULL; 329 ret = fbPixmapToRegion(pPix); 330 uxa_finish_access(&pPix->drawable); 331 return ret; 332} 333 334static void 335uxa_xorg_enable_disable_fb_access (int index, Bool enable) 336{ 337 ScreenPtr screen = screenInfo.screens[index]; 338 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 339 340 if (!enable && uxa_screen->disableFbCount++ == 0) 341 uxa_screen->swappedOut = TRUE; 342 343 if (enable && --uxa_screen->disableFbCount == 0) 344 uxa_screen->swappedOut = FALSE; 345 346 if (uxa_screen->SavedEnableDisableFBAccess) 347 uxa_screen->SavedEnableDisableFBAccess(index, enable); 348} 349 350void 351uxa_set_fallback_debug (ScreenPtr screen, Bool enable) 352{ 353 uxa_screen_t *uxa_screen = uxa_get_screen(screen); 354 355 uxa_screen->fallback_debug = enable; 356} 357 358/** 359 * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's 360 * screen private, before calling down to the next CloseSccreen. 361 */ 362static Bool 363uxa_close_screen(int i, ScreenPtr pScreen) 364{ 365 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 366 ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; 367#ifdef RENDER 368 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 369#endif 370 371 uxa_glyphs_fini(pScreen); 372 373 pScreen->CreateGC = uxa_screen->SavedCreateGC; 374 pScreen->CloseScreen = uxa_screen->SavedCloseScreen; 375 pScreen->GetImage = uxa_screen->SavedGetImage; 376 pScreen->GetSpans = uxa_screen->SavedGetSpans; 377 pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap; 378 pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap; 379 pScreen->CopyWindow = uxa_screen->SavedCopyWindow; 380 pScreen->ChangeWindowAttributes = uxa_screen->SavedChangeWindowAttributes; 381 pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion; 382 scrn->EnableDisableFBAccess = uxa_screen->SavedEnableDisableFBAccess; 383#ifdef RENDER 384 if (ps) { 385 ps->Composite = uxa_screen->SavedComposite; 386 ps->Glyphs = uxa_screen->SavedGlyphs; 387 ps->Trapezoids = uxa_screen->SavedTrapezoids; 388 ps->AddTraps = uxa_screen->SavedAddTraps; 389 ps->Triangles = uxa_screen->SavedTriangles; 390 } 391#endif 392 393 xfree (uxa_screen); 394 395 return (*pScreen->CloseScreen) (i, pScreen); 396} 397 398/** 399 * This function allocates a driver structure for UXA drivers to fill in. By 400 * having UXA allocate the structure, the driver structure can be extended 401 * without breaking ABI between UXA and the drivers. The driver's 402 * responsibility is to check beforehand that the UXA module has a matching 403 * major number and sufficient minor. Drivers are responsible for freeing the 404 * driver structure using xfree(). 405 * 406 * @return a newly allocated, zero-filled driver structure 407 */ 408uxa_driver_t * 409uxa_driver_alloc(void) 410{ 411 return xcalloc(1, sizeof(uxa_driver_t)); 412} 413 414/** 415 * @param pScreen screen being initialized 416 * @param pScreenInfo UXA driver record 417 * 418 * uxa_driver_init sets up UXA given a driver record filled in by the driver. 419 * pScreenInfo should have been allocated by uxa_driver_alloc(). See the 420 * comments in _UxaDriver for what must be filled in and what is optional. 421 * 422 * @return TRUE if UXA was successfully initialized. 423 */ 424Bool 425uxa_driver_init(ScreenPtr screen, uxa_driver_t *uxa_driver) 426{ 427 uxa_screen_t *uxa_screen; 428 ScrnInfoPtr scrn = xf86Screens[screen->myNum]; 429#ifdef RENDER 430 PictureScreenPtr ps; 431#endif 432 433 if (!uxa_driver) 434 return FALSE; 435 436 if (uxa_driver->uxa_major != UXA_VERSION_MAJOR || 437 uxa_driver->uxa_minor > UXA_VERSION_MINOR) 438 { 439 LogMessage(X_ERROR, "UXA(%d): driver's UXA version requirements " 440 "(%d.%d) are incompatible with UXA version (%d.%d)\n", 441 screen->myNum, 442 uxa_driver->uxa_major, uxa_driver->uxa_minor, 443 UXA_VERSION_MAJOR, UXA_VERSION_MINOR); 444 return FALSE; 445 } 446 447 if (!uxa_driver->prepare_solid) { 448 LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_solid must be " 449 "non-NULL\n", screen->myNum); 450 return FALSE; 451 } 452 453 if (!uxa_driver->prepare_copy) { 454 LogMessage(X_ERROR, "UXA(%d): uxa_driver_t::prepare_copy must be " 455 "non-NULL\n", screen->myNum); 456 return FALSE; 457 } 458 459#ifdef RENDER 460 ps = GetPictureScreenIfSet(screen); 461#endif 462 463#if HAS_DIXREGISTERPRIVATEKEY 464 if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0)) 465 return FALSE; 466#endif 467 uxa_screen = xcalloc (sizeof (uxa_screen_t), 1); 468 469 if (!uxa_screen) { 470 LogMessage(X_WARNING, "UXA(%d): Failed to allocate screen private\n", 471 screen->myNum); 472 return FALSE; 473 } 474 475 uxa_screen->info = uxa_driver; 476 477 dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen); 478 479// exaDDXDriverInit(screen); 480 481 /* 482 * Replace various fb screen functions 483 */ 484 uxa_screen->SavedCloseScreen = screen->CloseScreen; 485 screen->CloseScreen = uxa_close_screen; 486 487 uxa_screen->SavedCreateGC = screen->CreateGC; 488 screen->CreateGC = uxa_create_gc; 489 490 uxa_screen->SavedGetImage = screen->GetImage; 491 screen->GetImage = uxa_get_image; 492 493 uxa_screen->SavedGetSpans = screen->GetSpans; 494 screen->GetSpans = uxa_check_get_spans; 495 496 uxa_screen->SavedCopyWindow = screen->CopyWindow; 497 screen->CopyWindow = uxa_copy_window; 498 499 uxa_screen->SavedChangeWindowAttributes = screen->ChangeWindowAttributes; 500 screen->ChangeWindowAttributes = uxa_change_window_attributes; 501 502 uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion; 503 screen->BitmapToRegion = uxa_bitmap_to_region; 504 505 uxa_screen->SavedEnableDisableFBAccess = scrn->EnableDisableFBAccess; 506 scrn->EnableDisableFBAccess = uxa_xorg_enable_disable_fb_access; 507 508#ifdef RENDER 509 if (ps) { 510 uxa_screen->SavedComposite = ps->Composite; 511 ps->Composite = uxa_composite; 512 513 uxa_screen->SavedGlyphs = ps->Glyphs; 514 ps->Glyphs = uxa_glyphs; 515 516 uxa_screen->SavedTriangles = ps->Triangles; 517 ps->Triangles = uxa_triangles; 518 519 uxa_screen->SavedTrapezoids = ps->Trapezoids; 520 ps->Trapezoids = uxa_trapezoids; 521 522 uxa_screen->SavedAddTraps = ps->AddTraps; 523 ps->AddTraps = uxa_check_add_traps; 524 } 525#endif 526 527#ifdef MITSHM 528 /* Re-register with the MI funcs, which don't allow shared pixmaps. 529 * Shared pixmaps are almost always a performance loss for us, but this 530 * still allows for SHM PutImage. 531 */ 532 ShmRegisterFuncs(screen, &uxa_shm_funcs); 533#endif 534 535 uxa_glyphs_init(screen); 536 537 LogMessage(X_INFO, "UXA(%d): Driver registered support for the following" 538 " operations:\n", screen->myNum); 539 assert(uxa_driver->prepare_solid != NULL); 540 LogMessage(X_INFO, " solid\n"); 541 assert(uxa_driver->prepare_copy != NULL); 542 LogMessage(X_INFO, " copy\n"); 543 if (uxa_driver->prepare_composite != NULL) { 544 LogMessage(X_INFO, " composite (RENDER acceleration)\n"); 545 } 546 if (uxa_driver->put_image != NULL) { 547 LogMessage(X_INFO, " put_image\n"); 548 } 549 if (uxa_driver->get_image != NULL) { 550 LogMessage(X_INFO, " get_image\n"); 551 } 552 553 return TRUE; 554} 555 556/** 557 * uxa_driver_fini tears down UXA on a given screen. 558 * 559 * @param pScreen screen being torn down. 560 */ 561void 562uxa_driver_fini (ScreenPtr pScreen) 563{ 564 /*right now does nothing*/ 565} 566