2 * Copyright © 2001 Keith Packard
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
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.
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.
26 * This file covers the initialization and teardown of UXA, and has various
27 * functions not responsible for performing rendering, pixmap migration, or
31 #ifdef HAVE_DIX_CONFIG_H
32 #include <dix-config.h>
38 #include <X11/fonts/fontstruct.h>
39 #include "dixfontstr.h"
42 #if HAS_DEVPRIVATEKEYREC
43 DevPrivateKeyRec uxa_screen_index;
49 * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
51 * @param pDrawable the drawable being requested.
53 * This function returns the backing pixmap for a drawable, whether it is a
54 * redirected window, unredirected window, or already a pixmap. Note that
55 * coordinate translation is needed when drawing to the backing pixmap of a
56 * redirected window, and the translation coordinates are provided by calling
57 * uxa_get_drawable_pixmap() on the drawable.
59 PixmapPtr uxa_get_drawable_pixmap(DrawablePtr pDrawable)
61 if (pDrawable->type == DRAWABLE_WINDOW)
62 return pDrawable->pScreen->
63 GetWindowPixmap((WindowPtr) pDrawable);
65 return (PixmapPtr) pDrawable;
69 * Sets the offsets to add to coordinates to make them address the same bits in
70 * the backing drawable. These coordinates are nonzero only for redirected
74 uxa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
78 if (pDrawable->type == DRAWABLE_WINDOW) {
79 *xp = -pPixmap->screen_x;
80 *yp = -pPixmap->screen_y;
90 * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
91 * memory, meaning that acceleration could probably be done to it, and that it
92 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
95 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
96 * deal with moving pixmaps in and out of system memory), UXA will give drivers
97 * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
99 * @return TRUE if the given drawable is in framebuffer memory.
101 Bool uxa_pixmap_is_offscreen(PixmapPtr p)
103 ScreenPtr pScreen = p->drawable.pScreen;
104 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
106 if (uxa_screen->info->pixmap_is_offscreen)
107 return uxa_screen->info->pixmap_is_offscreen(p);
113 * uxa_drawable_is_offscreen() is a convenience wrapper for
114 * uxa_pixmap_is_offscreen().
116 Bool uxa_drawable_is_offscreen(DrawablePtr pDrawable)
118 return uxa_pixmap_is_offscreen(uxa_get_drawable_pixmap(pDrawable));
122 * Returns the pixmap which backs a drawable, and the offsets to add to
123 * coordinates to make them address the same bits in the backing drawable.
125 PixmapPtr uxa_get_offscreen_pixmap(DrawablePtr drawable, int *xp, int *yp)
127 PixmapPtr pixmap = uxa_get_drawable_pixmap(drawable);
129 uxa_get_drawable_deltas(drawable, pixmap, xp, yp);
131 if (uxa_pixmap_is_offscreen(pixmap))
138 * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
140 * It deals with waiting for synchronization with the card, determining if
141 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
143 Bool uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
145 ScreenPtr pScreen = pDrawable->pScreen;
146 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
147 PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
148 Bool offscreen = uxa_pixmap_is_offscreen(pPixmap);
153 if (uxa_screen->info->prepare_access)
154 return (*uxa_screen->info->prepare_access) (pPixmap, access);
159 * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
161 * It deals with calling the driver's finish_access() only if necessary.
163 void uxa_finish_access(DrawablePtr pDrawable)
165 ScreenPtr pScreen = pDrawable->pScreen;
166 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
169 if (uxa_screen->info->finish_access == NULL)
172 pPixmap = uxa_get_drawable_pixmap(pDrawable);
173 if (!uxa_pixmap_is_offscreen(pPixmap))
176 (*uxa_screen->info->finish_access) (pPixmap);
180 * uxa_validate_gc() sets the ops to UXA's implementations, which may be
181 * accelerated or may sync the card and fall back to fb.
184 uxa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
186 /* fbValidateGC will do direct access to pixmaps if the tiling has
188 * Preempt fbValidateGC by doing its work and masking the change out, so
189 * that we can do the Prepare/finish_access.
192 if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
193 (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
194 fbGetRotatedPixmap(pGC) = 0;
197 if (pGC->fillStyle == FillTiled) {
198 PixmapPtr pOldTile, pNewTile;
200 pOldTile = pGC->tile.pixmap;
201 if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
202 pNewTile = fbGetRotatedPixmap(pGC);
204 pNewTile->drawable.bitsPerPixel !=
205 pDrawable->bitsPerPixel) {
208 DestroyPixmap) (pNewTile);
209 /* fb24_32ReformatTile will do direct access
210 * of a newly-allocated pixmap. This isn't a
211 * problem yet, since we don't put pixmaps in
212 * FB until at least one accelerated UXA op.
214 if (uxa_prepare_access
215 (&pOldTile->drawable, UXA_ACCESS_RO)) {
217 fb24_32ReformatTile(pOldTile,
220 uxa_finish_access(&pOldTile->drawable);
224 fbGetRotatedPixmap(pGC) = pOldTile;
225 pGC->tile.pixmap = pNewTile;
231 if (changes & GCTile) {
232 if (!pGC->tileIsPixel
233 && FbEvenTile(pGC->tile.pixmap->drawable.width *
234 pDrawable->bitsPerPixel)) {
235 if (uxa_prepare_access
236 (&pGC->tile.pixmap->drawable, UXA_ACCESS_RW)) {
237 fbPadPixmap(pGC->tile.pixmap);
238 uxa_finish_access(&pGC->tile.pixmap->drawable);
241 /* Mask out the GCTile change notification, now that we've
242 * done FB's job for it.
247 if (changes & GCStipple && pGC->stipple) {
248 /* We can't inline stipple handling like we do for GCTile
249 * because it sets fbgc privates.
251 if (uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RW)) {
252 fbValidateGC(pGC, changes, pDrawable);
253 uxa_finish_access(&pGC->stipple->drawable);
256 fbValidateGC(pGC, changes, pDrawable);
259 pGC->ops = (GCOps *) & uxa_ops;
262 static GCFuncs uxaGCFuncs = {
273 * uxa_create_gc makes a new GC and hooks up its funcs handler, so that
274 * uxa_validate_gc() will get called.
276 static int uxa_create_gc(GCPtr pGC)
278 if (!fbCreateGC(pGC))
281 pGC->funcs = &uxaGCFuncs;
286 Bool uxa_prepare_access_window(WindowPtr pWin)
288 if (pWin->backgroundState == BackgroundPixmap) {
289 if (!uxa_prepare_access
290 (&pWin->background.pixmap->drawable, UXA_ACCESS_RO))
294 if (pWin->borderIsPixel == FALSE) {
295 if (!uxa_prepare_access
296 (&pWin->border.pixmap->drawable, UXA_ACCESS_RO)) {
297 if (pWin->backgroundState == BackgroundPixmap)
298 uxa_finish_access(&pWin->background.pixmap->
306 void uxa_finish_access_window(WindowPtr pWin)
308 if (pWin->backgroundState == BackgroundPixmap)
309 uxa_finish_access(&pWin->background.pixmap->drawable);
311 if (pWin->borderIsPixel == FALSE)
312 uxa_finish_access(&pWin->border.pixmap->drawable);
315 static Bool uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
319 if (!uxa_prepare_access_window(pWin))
321 ret = fbChangeWindowAttributes(pWin, mask);
322 uxa_finish_access_window(pWin);
326 static RegionPtr uxa_bitmap_to_region(PixmapPtr pPix)
329 if (!uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO))
331 ret = fbPixmapToRegion(pPix);
332 uxa_finish_access(&pPix->drawable);
336 static void uxa_xorg_enable_disable_fb_access(int index, Bool enable)
338 ScreenPtr screen = screenInfo.screens[index];
339 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
341 if (!enable && uxa_screen->disableFbCount++ == 0)
342 uxa_screen->swappedOut = TRUE;
344 if (enable && --uxa_screen->disableFbCount == 0)
345 uxa_screen->swappedOut = FALSE;
347 if (uxa_screen->SavedEnableDisableFBAccess)
348 uxa_screen->SavedEnableDisableFBAccess(index, enable);
351 void uxa_set_fallback_debug(ScreenPtr screen, Bool enable)
353 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
355 uxa_screen->fallback_debug = enable;
358 void uxa_set_force_fallback(ScreenPtr screen, Bool value)
360 uxa_screen_t *uxa_screen = uxa_get_screen(screen);
362 uxa_screen->force_fallback = value;
366 * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
367 * screen private, before calling down to the next CloseSccreen.
369 static Bool uxa_close_screen(int i, ScreenPtr pScreen)
371 uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
372 ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
374 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
378 if (uxa_screen->solid_clear)
379 FreePicture(uxa_screen->solid_clear, 0);
380 if (uxa_screen->solid_black)
381 FreePicture(uxa_screen->solid_black, 0);
382 if (uxa_screen->solid_white)
383 FreePicture(uxa_screen->solid_white, 0);
384 for (n = 0; n < uxa_screen->solid_cache_size; n++)
385 FreePicture(uxa_screen->solid_cache[n].picture, 0);
387 uxa_glyphs_fini(pScreen);
389 if (pScreen->devPrivate) {
390 /* Destroy the pixmap created by miScreenInit() *before*
391 * chaining up as we finalize ourselves here and so this
392 * is the last chance we have of releasing our resources
393 * associated with the Pixmap. So do it first.
395 (void) (*pScreen->DestroyPixmap) (pScreen->devPrivate);
396 pScreen->devPrivate = NULL;
399 pScreen->CreateGC = uxa_screen->SavedCreateGC;
400 pScreen->CloseScreen = uxa_screen->SavedCloseScreen;
401 pScreen->GetImage = uxa_screen->SavedGetImage;
402 pScreen->GetSpans = uxa_screen->SavedGetSpans;
403 pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap;
404 pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
405 pScreen->CopyWindow = uxa_screen->SavedCopyWindow;
406 pScreen->ChangeWindowAttributes =
407 uxa_screen->SavedChangeWindowAttributes;
408 pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
409 scrn->EnableDisableFBAccess = uxa_screen->SavedEnableDisableFBAccess;
412 ps->Composite = uxa_screen->SavedComposite;
413 ps->CompositeRects = uxa_screen->SavedCompositeRects;
414 ps->Glyphs = uxa_screen->SavedGlyphs;
415 ps->Trapezoids = uxa_screen->SavedTrapezoids;
416 ps->AddTraps = uxa_screen->SavedAddTraps;
417 ps->Triangles = uxa_screen->SavedTriangles;
419 ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
425 return (*pScreen->CloseScreen) (i, pScreen);
429 * This function allocates a driver structure for UXA drivers to fill in. By
430 * having UXA allocate the structure, the driver structure can be extended
431 * without breaking ABI between UXA and the drivers. The driver's
432 * responsibility is to check beforehand that the UXA module has a matching
433 * major number and sufficient minor. Drivers are responsible for freeing the
434 * driver structure using free().
436 * @return a newly allocated, zero-filled driver structure
438 uxa_driver_t *uxa_driver_alloc(void)
440 return calloc(1, sizeof(uxa_driver_t));
444 * @param pScreen screen being initialized
445 * @param pScreenInfo UXA driver record
447 * uxa_driver_init sets up UXA given a driver record filled in by the driver.
448 * pScreenInfo should have been allocated by uxa_driver_alloc(). See the
449 * comments in _UxaDriver for what must be filled in and what is optional.
451 * @return TRUE if UXA was successfully initialized.
453 Bool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
455 uxa_screen_t *uxa_screen;
456 ScrnInfoPtr scrn = xf86Screens[screen->myNum];
461 if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
462 uxa_driver->uxa_minor > UXA_VERSION_MINOR) {
464 "UXA(%d): driver's UXA version requirements "
465 "(%d.%d) are incompatible with UXA version (%d.%d)\n",
466 screen->myNum, uxa_driver->uxa_major,
467 uxa_driver->uxa_minor, UXA_VERSION_MAJOR,
472 if (!uxa_driver->prepare_solid) {
474 "UXA(%d): uxa_driver_t::prepare_solid must be "
475 "non-NULL\n", screen->myNum);
479 if (!uxa_driver->prepare_copy) {
481 "UXA(%d): uxa_driver_t::prepare_copy must be "
482 "non-NULL\n", screen->myNum);
485 #if HAS_DIXREGISTERPRIVATEKEY
486 if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
489 uxa_screen = calloc(sizeof(uxa_screen_t), 1);
492 LogMessage(X_WARNING,
493 "UXA(%d): Failed to allocate screen private\n",
498 uxa_screen->info = uxa_driver;
500 dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen);
502 uxa_screen->force_fallback = FALSE;
504 uxa_screen->solid_cache_size = 0;
505 uxa_screen->solid_clear = 0;
506 uxa_screen->solid_black = 0;
507 uxa_screen->solid_white = 0;
509 // exaDDXDriverInit(screen);
512 * Replace various fb screen functions
514 uxa_screen->SavedCloseScreen = screen->CloseScreen;
515 screen->CloseScreen = uxa_close_screen;
517 uxa_screen->SavedCreateGC = screen->CreateGC;
518 screen->CreateGC = uxa_create_gc;
520 uxa_screen->SavedGetImage = screen->GetImage;
521 screen->GetImage = uxa_get_image;
523 uxa_screen->SavedGetSpans = screen->GetSpans;
524 screen->GetSpans = uxa_check_get_spans;
526 uxa_screen->SavedCopyWindow = screen->CopyWindow;
527 screen->CopyWindow = uxa_copy_window;
529 uxa_screen->SavedChangeWindowAttributes =
530 screen->ChangeWindowAttributes;
531 screen->ChangeWindowAttributes = uxa_change_window_attributes;
533 uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
534 screen->BitmapToRegion = uxa_bitmap_to_region;
536 uxa_screen->SavedEnableDisableFBAccess = scrn->EnableDisableFBAccess;
537 scrn->EnableDisableFBAccess = uxa_xorg_enable_disable_fb_access;
541 PictureScreenPtr ps = GetPictureScreenIfSet(screen);
543 uxa_screen->SavedComposite = ps->Composite;
544 ps->Composite = uxa_composite;
546 uxa_screen->SavedCompositeRects = ps->CompositeRects;
547 ps->CompositeRects = uxa_solid_rects;
549 uxa_screen->SavedGlyphs = ps->Glyphs;
550 ps->Glyphs = uxa_glyphs;
552 uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph;
553 ps->UnrealizeGlyph = uxa_glyph_unrealize;
555 uxa_screen->SavedTriangles = ps->Triangles;
556 ps->Triangles = uxa_triangles;
558 uxa_screen->SavedTrapezoids = ps->Trapezoids;
559 ps->Trapezoids = uxa_trapezoids;
561 uxa_screen->SavedAddTraps = ps->AddTraps;
562 ps->AddTraps = uxa_check_add_traps;
568 "UXA(%d): Driver registered support for the following"
569 " operations:\n", screen->myNum);
570 assert(uxa_driver->prepare_solid != NULL);
571 LogMessage(X_INFO, " solid\n");
572 assert(uxa_driver->prepare_copy != NULL);
573 LogMessage(X_INFO, " copy\n");
574 if (uxa_driver->prepare_composite != NULL) {
575 LogMessage(X_INFO, " composite (RENDER acceleration)\n");
577 if (uxa_driver->put_image != NULL) {
578 LogMessage(X_INFO, " put_image\n");
580 if (uxa_driver->get_image != NULL) {
581 LogMessage(X_INFO, " get_image\n");
587 Bool uxa_resources_init(ScreenPtr screen)
589 if (!uxa_glyphs_init(screen))
596 * uxa_driver_fini tears down UXA on a given screen.
598 * @param pScreen screen being torn down.
600 void uxa_driver_fini(ScreenPtr pScreen)
602 /*right now does nothing */