uxa.c revision d514b0f3
1d514b0f3Smrg/* 2d514b0f3Smrg * Copyright © 2001 Keith Packard 3d514b0f3Smrg * 4d514b0f3Smrg * Partly based on code that is Copyright © The XFree86 Project Inc. 5d514b0f3Smrg * 6d514b0f3Smrg * Permission to use, copy, modify, distribute, and sell this software and its 7d514b0f3Smrg * documentation for any purpose is hereby granted without fee, provided that 8d514b0f3Smrg * the above copyright notice appear in all copies and that both that 9d514b0f3Smrg * copyright notice and this permission notice appear in supporting 10d514b0f3Smrg * documentation, and that the name of Keith Packard not be used in 11d514b0f3Smrg * advertising or publicity pertaining to distribution of the software without 12d514b0f3Smrg * specific, written prior permission. Keith Packard makes no 13d514b0f3Smrg * representations about the suitability of this software for any purpose. It 14d514b0f3Smrg * is provided "as is" without express or implied warranty. 15d514b0f3Smrg * 16d514b0f3Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17d514b0f3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18d514b0f3Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19d514b0f3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20d514b0f3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21d514b0f3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22d514b0f3Smrg * PERFORMANCE OF THIS SOFTWARE. 23d514b0f3Smrg */ 24d514b0f3Smrg 25d514b0f3Smrg/** @file 26d514b0f3Smrg * This file covers the initialization and teardown of UXA, and has various 27d514b0f3Smrg * functions not responsible for performing rendering, pixmap migration, or 28d514b0f3Smrg * memory management. 29d514b0f3Smrg */ 30d514b0f3Smrg 31d514b0f3Smrg#ifdef HAVE_DIX_CONFIG_H 32d514b0f3Smrg#include <dix-config.h> 33d514b0f3Smrg#endif 34d514b0f3Smrg 35d514b0f3Smrg#include <stdlib.h> 36d514b0f3Smrg 37d514b0f3Smrg#include "uxa-priv.h" 38d514b0f3Smrg#include "uxa.h" 39d514b0f3Smrg 40d514b0f3Smrg#if HAS_DEVPRIVATEKEYREC 41d514b0f3SmrgDevPrivateKeyRec uxa_screen_index; 42d514b0f3Smrg#else 43d514b0f3Smrgint uxa_screen_index; 44d514b0f3Smrg#endif 45d514b0f3Smrg 46d514b0f3Smrg/** 47d514b0f3Smrg * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable. 48d514b0f3Smrg * 49d514b0f3Smrg * @param pDrawable the drawable being requested. 50d514b0f3Smrg * 51d514b0f3Smrg * This function returns the backing pixmap for a drawable, whether it is a 52d514b0f3Smrg * redirected window, unredirected window, or already a pixmap. Note that 53d514b0f3Smrg * coordinate translation is needed when drawing to the backing pixmap of a 54d514b0f3Smrg * redirected window, and the translation coordinates are provided by calling 55d514b0f3Smrg * uxa_get_drawable_pixmap() on the drawable. 56d514b0f3Smrg */ 57d514b0f3SmrgPixmapPtr uxa_get_drawable_pixmap(DrawablePtr pDrawable) 58d514b0f3Smrg{ 59d514b0f3Smrg if (pDrawable->type == DRAWABLE_WINDOW) 60d514b0f3Smrg return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); 61d514b0f3Smrg else 62d514b0f3Smrg return (PixmapPtr) pDrawable; 63d514b0f3Smrg} 64d514b0f3Smrg 65d514b0f3Smrg/** 66d514b0f3Smrg * Sets the offsets to add to coordinates to make them address the same bits in 67d514b0f3Smrg * the backing drawable. These coordinates are nonzero only for redirected 68d514b0f3Smrg * windows. 69d514b0f3Smrg */ 70d514b0f3Smrgvoid 71d514b0f3Smrguxa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap, 72d514b0f3Smrg int *xp, int *yp) 73d514b0f3Smrg{ 74d514b0f3Smrg#ifdef COMPOSITE 75d514b0f3Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 76d514b0f3Smrg *xp = -pPixmap->screen_x; 77d514b0f3Smrg *yp = -pPixmap->screen_y; 78d514b0f3Smrg return; 79d514b0f3Smrg } 80d514b0f3Smrg#endif 81d514b0f3Smrg 82d514b0f3Smrg *xp = 0; 83d514b0f3Smrg *yp = 0; 84d514b0f3Smrg} 85d514b0f3Smrg 86d514b0f3Smrg/** 87d514b0f3Smrg * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen 88d514b0f3Smrg * memory, meaning that acceleration could probably be done to it, and that it 89d514b0f3Smrg * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it 90d514b0f3Smrg * with the CPU. 91d514b0f3Smrg * 92d514b0f3Smrg * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly 93d514b0f3Smrg * deal with moving pixmaps in and out of system memory), UXA will give drivers 94d514b0f3Smrg * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE. 95d514b0f3Smrg * 96d514b0f3Smrg * @return TRUE if the given drawable is in framebuffer memory. 97d514b0f3Smrg */ 98d514b0f3SmrgBool uxa_pixmap_is_offscreen(PixmapPtr p) 99d514b0f3Smrg{ 100d514b0f3Smrg ScreenPtr pScreen = p->drawable.pScreen; 101d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 102d514b0f3Smrg 103d514b0f3Smrg if (uxa_screen->info->pixmap_is_offscreen) 104d514b0f3Smrg return uxa_screen->info->pixmap_is_offscreen(p); 105d514b0f3Smrg 106d514b0f3Smrg return FALSE; 107d514b0f3Smrg} 108d514b0f3Smrg 109d514b0f3Smrg/** 110d514b0f3Smrg * uxa_drawable_is_offscreen() is a convenience wrapper for 111d514b0f3Smrg * uxa_pixmap_is_offscreen(). 112d514b0f3Smrg */ 113d514b0f3SmrgBool uxa_drawable_is_offscreen(DrawablePtr pDrawable) 114d514b0f3Smrg{ 115d514b0f3Smrg return uxa_pixmap_is_offscreen(uxa_get_drawable_pixmap(pDrawable)); 116d514b0f3Smrg} 117d514b0f3Smrg 118d514b0f3Smrg/** 119d514b0f3Smrg * Returns the pixmap which backs a drawable, and the offsets to add to 120d514b0f3Smrg * coordinates to make them address the same bits in the backing drawable. 121d514b0f3Smrg */ 122d514b0f3SmrgPixmapPtr uxa_get_offscreen_pixmap(DrawablePtr drawable, int *xp, int *yp) 123d514b0f3Smrg{ 124d514b0f3Smrg PixmapPtr pixmap = uxa_get_drawable_pixmap(drawable); 125d514b0f3Smrg 126d514b0f3Smrg uxa_get_drawable_deltas(drawable, pixmap, xp, yp); 127d514b0f3Smrg 128d514b0f3Smrg if (uxa_pixmap_is_offscreen(pixmap)) 129d514b0f3Smrg return pixmap; 130d514b0f3Smrg else 131d514b0f3Smrg return NULL; 132d514b0f3Smrg} 133d514b0f3Smrg 134d514b0f3Smrg/** 135d514b0f3Smrg * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler. 136d514b0f3Smrg * 137d514b0f3Smrg * It deals with waiting for synchronization with the card, determining if 138d514b0f3Smrg * PrepareAccess() is necessary, and working around PrepareAccess() failure. 139d514b0f3Smrg */ 140d514b0f3SmrgBool uxa_prepare_access(DrawablePtr pDrawable, RegionPtr region, uxa_access_t access) 141d514b0f3Smrg{ 142d514b0f3Smrg ScreenPtr pScreen = pDrawable->pScreen; 143d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 144d514b0f3Smrg int xoff, yoff; 145d514b0f3Smrg PixmapPtr pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 146d514b0f3Smrg BoxRec box; 147d514b0f3Smrg RegionRec region_rec; 148d514b0f3Smrg Bool result; 149d514b0f3Smrg 150d514b0f3Smrg if (!pPixmap) 151d514b0f3Smrg return TRUE; 152d514b0f3Smrg 153d514b0f3Smrg if (!region) 154d514b0f3Smrg { 155d514b0f3Smrg box.x1 = 0; 156d514b0f3Smrg box.y1 = 0; 157d514b0f3Smrg box.x2 = pDrawable->width; 158d514b0f3Smrg box.y2 = pDrawable->height; 159d514b0f3Smrg 160d514b0f3Smrg REGION_INIT (pScreen, ®ion_rec, &box, 1); 161d514b0f3Smrg region = ®ion_rec; 162d514b0f3Smrg } 163d514b0f3Smrg else 164d514b0f3Smrg { 165d514b0f3Smrg /* The driver expects a region in drawable coordinates */ 166d514b0f3Smrg REGION_TRANSLATE (pScreen, region, xoff, yoff); 167d514b0f3Smrg } 168d514b0f3Smrg 169d514b0f3Smrg result = TRUE; 170d514b0f3Smrg 171d514b0f3Smrg if (uxa_screen->info->prepare_access) 172d514b0f3Smrg result = (*uxa_screen->info->prepare_access) (pPixmap, region, access); 173d514b0f3Smrg 174d514b0f3Smrg if (region == ®ion_rec) 175d514b0f3Smrg REGION_UNINIT (pScreen, ®ion_rec); 176d514b0f3Smrg 177d514b0f3Smrg return result; 178d514b0f3Smrg} 179d514b0f3Smrg 180d514b0f3Smrg/** 181d514b0f3Smrg * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler. 182d514b0f3Smrg * 183d514b0f3Smrg * It deals with calling the driver's finish_access() only if necessary. 184d514b0f3Smrg */ 185d514b0f3Smrgvoid uxa_finish_access(DrawablePtr pDrawable) 186d514b0f3Smrg{ 187d514b0f3Smrg ScreenPtr pScreen = pDrawable->pScreen; 188d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 189d514b0f3Smrg PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); 190d514b0f3Smrg 191d514b0f3Smrg if (uxa_screen->info->finish_access == NULL) 192d514b0f3Smrg return; 193d514b0f3Smrg 194d514b0f3Smrg if (!uxa_pixmap_is_offscreen(pPixmap)) 195d514b0f3Smrg return; 196d514b0f3Smrg 197d514b0f3Smrg (*uxa_screen->info->finish_access) (pPixmap); 198d514b0f3Smrg} 199d514b0f3Smrg 200d514b0f3Smrg/** 201d514b0f3Smrg * uxa_validate_gc() sets the ops to UXA's implementations, which may be 202d514b0f3Smrg * accelerated or may sync the card and fall back to fb. 203d514b0f3Smrg */ 204d514b0f3Smrgstatic void 205d514b0f3Smrguxa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 206d514b0f3Smrg{ 207d514b0f3Smrg /* fbValidateGC will do direct access to pixmaps if the tiling has 208d514b0f3Smrg * changed. 209d514b0f3Smrg * Preempt fbValidateGC by doing its work and masking the change out, so 210d514b0f3Smrg * that we can do the Prepare/finish_access. 211d514b0f3Smrg */ 212d514b0f3Smrg#ifdef FB_24_32BIT 213d514b0f3Smrg if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { 214d514b0f3Smrg (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); 215d514b0f3Smrg fbGetRotatedPixmap(pGC) = 0; 216d514b0f3Smrg } 217d514b0f3Smrg 218d514b0f3Smrg if (pGC->fillStyle == FillTiled) { 219d514b0f3Smrg PixmapPtr pOldTile, pNewTile; 220d514b0f3Smrg 221d514b0f3Smrg pOldTile = pGC->tile.pixmap; 222d514b0f3Smrg if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) { 223d514b0f3Smrg pNewTile = fbGetRotatedPixmap(pGC); 224d514b0f3Smrg if (!pNewTile || 225d514b0f3Smrg pNewTile->drawable.bitsPerPixel != 226d514b0f3Smrg pDrawable->bitsPerPixel) { 227d514b0f3Smrg if (pNewTile) 228d514b0f3Smrg (*pGC->pScreen-> 229d514b0f3Smrg DestroyPixmap) (pNewTile); 230d514b0f3Smrg /* fb24_32ReformatTile will do direct access 231d514b0f3Smrg * of a newly-allocated pixmap. This isn't a 232d514b0f3Smrg * problem yet, since we don't put pixmaps in 233d514b0f3Smrg * FB until at least one accelerated UXA op. 234d514b0f3Smrg */ 235d514b0f3Smrg if (uxa_prepare_access 236d514b0f3Smrg (&pOldTile->drawable, NULL, UXA_ACCESS_RO)) { 237d514b0f3Smrg pNewTile = 238d514b0f3Smrg fb24_32ReformatTile(pOldTile, 239d514b0f3Smrg pDrawable-> 240d514b0f3Smrg bitsPerPixel); 241d514b0f3Smrg uxa_finish_access(&pOldTile->drawable); 242d514b0f3Smrg } 243d514b0f3Smrg } 244d514b0f3Smrg if (pNewTile) { 245d514b0f3Smrg fbGetRotatedPixmap(pGC) = pOldTile; 246d514b0f3Smrg pGC->tile.pixmap = pNewTile; 247d514b0f3Smrg changes |= GCTile; 248d514b0f3Smrg } 249d514b0f3Smrg } 250d514b0f3Smrg } 251d514b0f3Smrg#endif 252d514b0f3Smrg if (changes & GCTile) { 253d514b0f3Smrg if (!pGC->tileIsPixel 254d514b0f3Smrg && FbEvenTile(pGC->tile.pixmap->drawable.width * 255d514b0f3Smrg pDrawable->bitsPerPixel)) { 256d514b0f3Smrg if (uxa_prepare_access 257d514b0f3Smrg (&pGC->tile.pixmap->drawable, NULL, UXA_ACCESS_RW)) { 258d514b0f3Smrg fbPadPixmap(pGC->tile.pixmap); 259d514b0f3Smrg uxa_finish_access(&pGC->tile.pixmap->drawable); 260d514b0f3Smrg } 261d514b0f3Smrg } 262d514b0f3Smrg /* Mask out the GCTile change notification, now that we've 263d514b0f3Smrg * done FB's job for it. 264d514b0f3Smrg */ 265d514b0f3Smrg changes &= ~GCTile; 266d514b0f3Smrg } 267d514b0f3Smrg 268d514b0f3Smrg if (changes & GCStipple && pGC->stipple) { 269d514b0f3Smrg /* We can't inline stipple handling like we do for GCTile 270d514b0f3Smrg * because it sets fbgc privates. 271d514b0f3Smrg */ 272d514b0f3Smrg if (uxa_prepare_access(&pGC->stipple->drawable, NULL, UXA_ACCESS_RW)) { 273d514b0f3Smrg fbValidateGC(pGC, changes, pDrawable); 274d514b0f3Smrg uxa_finish_access(&pGC->stipple->drawable); 275d514b0f3Smrg } 276d514b0f3Smrg } else { 277d514b0f3Smrg fbValidateGC(pGC, changes, pDrawable); 278d514b0f3Smrg } 279d514b0f3Smrg 280d514b0f3Smrg pGC->ops = (GCOps *)&uxa_ops; 281d514b0f3Smrg} 282d514b0f3Smrg 283d514b0f3Smrgstatic GCFuncs uxaGCFuncs = { 284d514b0f3Smrg uxa_validate_gc, 285d514b0f3Smrg miChangeGC, 286d514b0f3Smrg miCopyGC, 287d514b0f3Smrg miDestroyGC, 288d514b0f3Smrg miChangeClip, 289d514b0f3Smrg miDestroyClip, 290d514b0f3Smrg miCopyClip 291d514b0f3Smrg}; 292d514b0f3Smrg 293d514b0f3Smrg/** 294d514b0f3Smrg * uxa_create_gc makes a new GC and hooks up its funcs handler, so that 295d514b0f3Smrg * uxa_validate_gc() will get called. 296d514b0f3Smrg */ 297d514b0f3Smrgstatic int uxa_create_gc(GCPtr pGC) 298d514b0f3Smrg{ 299d514b0f3Smrg if (!fbCreateGC(pGC)) 300d514b0f3Smrg return FALSE; 301d514b0f3Smrg 302d514b0f3Smrg pGC->funcs = &uxaGCFuncs; 303d514b0f3Smrg 304d514b0f3Smrg return TRUE; 305d514b0f3Smrg} 306d514b0f3Smrg 307d514b0f3SmrgBool uxa_prepare_access_window(WindowPtr pWin) 308d514b0f3Smrg{ 309d514b0f3Smrg if (pWin->backgroundState == BackgroundPixmap) { 310d514b0f3Smrg if (!uxa_prepare_access 311d514b0f3Smrg (&pWin->background.pixmap->drawable, NULL, UXA_ACCESS_RO)) 312d514b0f3Smrg return FALSE; 313d514b0f3Smrg } 314d514b0f3Smrg 315d514b0f3Smrg if (pWin->borderIsPixel == FALSE) { 316d514b0f3Smrg if (!uxa_prepare_access 317d514b0f3Smrg (&pWin->border.pixmap->drawable, NULL, UXA_ACCESS_RO)) { 318d514b0f3Smrg if (pWin->backgroundState == BackgroundPixmap) 319d514b0f3Smrg uxa_finish_access(&pWin->background.pixmap-> 320d514b0f3Smrg drawable); 321d514b0f3Smrg return FALSE; 322d514b0f3Smrg } 323d514b0f3Smrg } 324d514b0f3Smrg return TRUE; 325d514b0f3Smrg} 326d514b0f3Smrg 327d514b0f3Smrgvoid uxa_finish_access_window(WindowPtr pWin) 328d514b0f3Smrg{ 329d514b0f3Smrg if (pWin->backgroundState == BackgroundPixmap) 330d514b0f3Smrg uxa_finish_access(&pWin->background.pixmap->drawable); 331d514b0f3Smrg 332d514b0f3Smrg if (pWin->borderIsPixel == FALSE) 333d514b0f3Smrg uxa_finish_access(&pWin->border.pixmap->drawable); 334d514b0f3Smrg} 335d514b0f3Smrg 336d514b0f3Smrgstatic Bool uxa_change_window_attributes(WindowPtr pWin, unsigned long mask) 337d514b0f3Smrg{ 338d514b0f3Smrg Bool ret; 339d514b0f3Smrg Bool need_access = !!(mask & (CWBackPixmap | CWBorderPixmap)); 340d514b0f3Smrg 341d514b0f3Smrg if (need_access) 342d514b0f3Smrg { 343d514b0f3Smrg if (!uxa_prepare_access_window(pWin)) 344d514b0f3Smrg return FALSE; 345d514b0f3Smrg } 346d514b0f3Smrg ret = fbChangeWindowAttributes(pWin, mask); 347d514b0f3Smrg if (need_access) 348d514b0f3Smrg uxa_finish_access_window(pWin); 349d514b0f3Smrg return ret; 350d514b0f3Smrg} 351d514b0f3Smrg 352d514b0f3Smrgstatic RegionPtr uxa_bitmap_to_region(PixmapPtr pPix) 353d514b0f3Smrg{ 354d514b0f3Smrg RegionPtr ret; 355d514b0f3Smrg if (!uxa_prepare_access(&pPix->drawable, NULL, UXA_ACCESS_RO)) 356d514b0f3Smrg return NULL; 357d514b0f3Smrg ret = fbPixmapToRegion(pPix); 358d514b0f3Smrg uxa_finish_access(&pPix->drawable); 359d514b0f3Smrg return ret; 360d514b0f3Smrg} 361d514b0f3Smrg 362d514b0f3Smrgstatic void uxa_xorg_enable_disable_fb_access(SCRN_ARG_TYPE arg, Bool enable) 363d514b0f3Smrg{ 364d514b0f3Smrg SCRN_INFO_PTR(arg); 365d514b0f3Smrg ScreenPtr pScreen = pScrn->pScreen; 366d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 367d514b0f3Smrg 368d514b0f3Smrg if (!enable && uxa_screen->disableFbCount++ == 0) 369d514b0f3Smrg uxa_screen->swappedOut = TRUE; 370d514b0f3Smrg 371d514b0f3Smrg if (enable && --uxa_screen->disableFbCount == 0) 372d514b0f3Smrg uxa_screen->swappedOut = FALSE; 373d514b0f3Smrg 374d514b0f3Smrg if (uxa_screen->SavedEnableDisableFBAccess) 375d514b0f3Smrg uxa_screen->SavedEnableDisableFBAccess(arg, enable); 376d514b0f3Smrg} 377d514b0f3Smrg 378d514b0f3Smrgvoid uxa_set_fallback_debug(ScreenPtr screen, Bool enable) 379d514b0f3Smrg{ 380d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen(screen); 381d514b0f3Smrg 382d514b0f3Smrg uxa_screen->fallback_debug = enable; 383d514b0f3Smrg} 384d514b0f3Smrg 385d514b0f3Smrgvoid uxa_set_force_fallback(ScreenPtr screen, Bool value) 386d514b0f3Smrg{ 387d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen(screen); 388d514b0f3Smrg 389d514b0f3Smrg uxa_screen->force_fallback = value; 390d514b0f3Smrg} 391d514b0f3Smrg 392d514b0f3SmrgBool uxa_swapped_out(ScreenPtr screen) 393d514b0f3Smrg{ 394d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen (screen); 395d514b0f3Smrg 396d514b0f3Smrg return uxa_screen->swappedOut; 397d514b0f3Smrg} 398d514b0f3Smrg 399d514b0f3Smrg/** 400d514b0f3Smrg * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's 401d514b0f3Smrg * screen private, before calling down to the next CloseSccreen. 402d514b0f3Smrg */ 403d514b0f3Smrgstatic Bool uxa_close_screen(CLOSE_SCREEN_ARGS_DECL) 404d514b0f3Smrg{ 405d514b0f3Smrg uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 406d514b0f3Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); 407d514b0f3Smrg#ifdef RENDER 408d514b0f3Smrg PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); 409d514b0f3Smrg#endif 410d514b0f3Smrg int n; 411d514b0f3Smrg 412d514b0f3Smrg if (uxa_screen->solid_clear) 413d514b0f3Smrg FreePicture(uxa_screen->solid_clear, 0); 414d514b0f3Smrg if (uxa_screen->solid_black) 415d514b0f3Smrg FreePicture(uxa_screen->solid_black, 0); 416d514b0f3Smrg if (uxa_screen->solid_white) 417d514b0f3Smrg FreePicture(uxa_screen->solid_white, 0); 418d514b0f3Smrg for (n = 0; n < uxa_screen->solid_cache_size; n++) 419d514b0f3Smrg FreePicture(uxa_screen->solid_cache[n].picture, 0); 420d514b0f3Smrg 421d514b0f3Smrg uxa_glyphs_fini(pScreen); 422d514b0f3Smrg 423d514b0f3Smrg pScreen->CreateGC = uxa_screen->SavedCreateGC; 424d514b0f3Smrg pScreen->CloseScreen = uxa_screen->SavedCloseScreen; 425d514b0f3Smrg pScreen->GetImage = uxa_screen->SavedGetImage; 426d514b0f3Smrg pScreen->GetSpans = uxa_screen->SavedGetSpans; 427d514b0f3Smrg pScreen->CreatePixmap = uxa_screen->SavedCreatePixmap; 428d514b0f3Smrg pScreen->DestroyPixmap = uxa_screen->SavedDestroyPixmap; 429d514b0f3Smrg pScreen->CopyWindow = uxa_screen->SavedCopyWindow; 430d514b0f3Smrg pScreen->ChangeWindowAttributes = 431d514b0f3Smrg uxa_screen->SavedChangeWindowAttributes; 432d514b0f3Smrg pScreen->BitmapToRegion = uxa_screen->SavedBitmapToRegion; 433d514b0f3Smrg scrn->EnableDisableFBAccess = uxa_screen->SavedEnableDisableFBAccess; 434d514b0f3Smrg#ifdef RENDER 435d514b0f3Smrg if (ps) { 436d514b0f3Smrg ps->Composite = uxa_screen->SavedComposite; 437d514b0f3Smrg ps->CompositeRects = uxa_screen->SavedCompositeRects; 438d514b0f3Smrg ps->Glyphs = uxa_screen->SavedGlyphs; 439d514b0f3Smrg ps->Trapezoids = uxa_screen->SavedTrapezoids; 440d514b0f3Smrg ps->AddTraps = uxa_screen->SavedAddTraps; 441d514b0f3Smrg ps->Triangles = uxa_screen->SavedTriangles; 442d514b0f3Smrg 443d514b0f3Smrg ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph; 444d514b0f3Smrg } 445d514b0f3Smrg#endif 446d514b0f3Smrg 447d514b0f3Smrg free(uxa_screen); 448d514b0f3Smrg 449d514b0f3Smrg return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 450d514b0f3Smrg} 451d514b0f3Smrg 452d514b0f3Smrg/** 453d514b0f3Smrg * This function allocates a driver structure for UXA drivers to fill in. By 454d514b0f3Smrg * having UXA allocate the structure, the driver structure can be extended 455d514b0f3Smrg * without breaking ABI between UXA and the drivers. The driver's 456d514b0f3Smrg * responsibility is to check beforehand that the UXA module has a matching 457d514b0f3Smrg * major number and sufficient minor. Drivers are responsible for freeing the 458d514b0f3Smrg * driver structure using xfree(). 459d514b0f3Smrg * 460d514b0f3Smrg * @return a newly allocated, zero-filled driver structure 461d514b0f3Smrg */ 462d514b0f3Smrguxa_driver_t *uxa_driver_alloc(void) 463d514b0f3Smrg{ 464d514b0f3Smrg return calloc(1, sizeof(uxa_driver_t)); 465d514b0f3Smrg} 466d514b0f3Smrg 467d514b0f3Smrg/** 468d514b0f3Smrg * @param pScreen screen being initialized 469d514b0f3Smrg * @param pScreenInfo UXA driver record 470d514b0f3Smrg * 471d514b0f3Smrg * uxa_driver_init sets up UXA given a driver record filled in by the driver. 472d514b0f3Smrg * pScreenInfo should have been allocated by uxa_driver_alloc(). See the 473d514b0f3Smrg * comments in _UxaDriver for what must be filled in and what is optional. 474d514b0f3Smrg * 475d514b0f3Smrg * @return TRUE if UXA was successfully initialized. 476d514b0f3Smrg */ 477d514b0f3SmrgBool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver) 478d514b0f3Smrg{ 479d514b0f3Smrg uxa_screen_t *uxa_screen; 480d514b0f3Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 481d514b0f3Smrg 482d514b0f3Smrg if (!uxa_driver) 483d514b0f3Smrg return FALSE; 484d514b0f3Smrg 485d514b0f3Smrg if (uxa_driver->uxa_major != UXA_VERSION_MAJOR || 486d514b0f3Smrg uxa_driver->uxa_minor > UXA_VERSION_MINOR) { 487d514b0f3Smrg LogMessage(X_ERROR, 488d514b0f3Smrg "UXA(%d): driver's UXA version requirements " 489d514b0f3Smrg "(%d.%d) are incompatible with UXA version (%d.%d)\n", 490d514b0f3Smrg screen->myNum, uxa_driver->uxa_major, 491d514b0f3Smrg uxa_driver->uxa_minor, UXA_VERSION_MAJOR, 492d514b0f3Smrg UXA_VERSION_MINOR); 493d514b0f3Smrg return FALSE; 494d514b0f3Smrg } 495d514b0f3Smrg 496d514b0f3Smrg if (!uxa_driver->prepare_solid) { 497d514b0f3Smrg LogMessage(X_ERROR, 498d514b0f3Smrg "UXA(%d): uxa_driver_t::prepare_solid must be " 499d514b0f3Smrg "non-NULL\n", screen->myNum); 500d514b0f3Smrg return FALSE; 501d514b0f3Smrg } 502d514b0f3Smrg 503d514b0f3Smrg if (!uxa_driver->prepare_copy) { 504d514b0f3Smrg LogMessage(X_ERROR, 505d514b0f3Smrg "UXA(%d): uxa_driver_t::prepare_copy must be " 506d514b0f3Smrg "non-NULL\n", screen->myNum); 507d514b0f3Smrg return FALSE; 508d514b0f3Smrg } 509d514b0f3Smrg#if HAS_DIXREGISTERPRIVATEKEY 510d514b0f3Smrg if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0)) 511d514b0f3Smrg return FALSE; 512d514b0f3Smrg#endif 513d514b0f3Smrg uxa_screen = calloc(sizeof(uxa_screen_t), 1); 514d514b0f3Smrg 515d514b0f3Smrg if (!uxa_screen) { 516d514b0f3Smrg LogMessage(X_WARNING, 517d514b0f3Smrg "UXA(%d): Failed to allocate screen private\n", 518d514b0f3Smrg screen->myNum); 519d514b0f3Smrg return FALSE; 520d514b0f3Smrg } 521d514b0f3Smrg 522d514b0f3Smrg uxa_screen->info = uxa_driver; 523d514b0f3Smrg 524d514b0f3Smrg dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen); 525d514b0f3Smrg 526d514b0f3Smrg uxa_screen->force_fallback = FALSE; 527d514b0f3Smrg 528d514b0f3Smrg uxa_screen->solid_cache_size = 0; 529d514b0f3Smrg uxa_screen->solid_clear = 0; 530d514b0f3Smrg uxa_screen->solid_black = 0; 531d514b0f3Smrg uxa_screen->solid_white = 0; 532d514b0f3Smrg 533d514b0f3Smrg// exaDDXDriverInit(screen); 534d514b0f3Smrg 535d514b0f3Smrg /* 536d514b0f3Smrg * Replace various fb screen functions 537d514b0f3Smrg */ 538d514b0f3Smrg uxa_screen->SavedCloseScreen = screen->CloseScreen; 539d514b0f3Smrg screen->CloseScreen = uxa_close_screen; 540d514b0f3Smrg 541d514b0f3Smrg uxa_screen->SavedCreateGC = screen->CreateGC; 542d514b0f3Smrg screen->CreateGC = uxa_create_gc; 543d514b0f3Smrg 544d514b0f3Smrg uxa_screen->SavedGetImage = screen->GetImage; 545d514b0f3Smrg screen->GetImage = uxa_get_image; 546d514b0f3Smrg 547d514b0f3Smrg uxa_screen->SavedGetSpans = screen->GetSpans; 548d514b0f3Smrg screen->GetSpans = uxa_check_get_spans; 549d514b0f3Smrg 550d514b0f3Smrg uxa_screen->SavedCopyWindow = screen->CopyWindow; 551d514b0f3Smrg screen->CopyWindow = uxa_copy_window; 552d514b0f3Smrg 553d514b0f3Smrg uxa_screen->SavedChangeWindowAttributes = 554d514b0f3Smrg screen->ChangeWindowAttributes; 555d514b0f3Smrg screen->ChangeWindowAttributes = uxa_change_window_attributes; 556d514b0f3Smrg 557d514b0f3Smrg uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion; 558d514b0f3Smrg screen->BitmapToRegion = uxa_bitmap_to_region; 559d514b0f3Smrg 560d514b0f3Smrg uxa_screen->SavedEnableDisableFBAccess = scrn->EnableDisableFBAccess; 561d514b0f3Smrg scrn->EnableDisableFBAccess = uxa_xorg_enable_disable_fb_access; 562d514b0f3Smrg 563d514b0f3Smrg#ifdef RENDER 564d514b0f3Smrg { 565d514b0f3Smrg PictureScreenPtr ps = GetPictureScreenIfSet(screen); 566d514b0f3Smrg if (ps) { 567d514b0f3Smrg uxa_screen->SavedComposite = ps->Composite; 568d514b0f3Smrg ps->Composite = uxa_composite; 569d514b0f3Smrg 570d514b0f3Smrg uxa_screen->SavedCompositeRects = ps->CompositeRects; 571d514b0f3Smrg ps->CompositeRects = uxa_solid_rects; 572d514b0f3Smrg 573d514b0f3Smrg uxa_screen->SavedGlyphs = ps->Glyphs; 574d514b0f3Smrg ps->Glyphs = uxa_glyphs; 575d514b0f3Smrg 576d514b0f3Smrg uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph; 577d514b0f3Smrg ps->UnrealizeGlyph = uxa_glyph_unrealize; 578d514b0f3Smrg 579d514b0f3Smrg uxa_screen->SavedTriangles = ps->Triangles; 580d514b0f3Smrg ps->Triangles = uxa_triangles; 581d514b0f3Smrg 582d514b0f3Smrg uxa_screen->SavedTrapezoids = ps->Trapezoids; 583d514b0f3Smrg ps->Trapezoids = uxa_trapezoids; 584d514b0f3Smrg 585d514b0f3Smrg uxa_screen->SavedAddTraps = ps->AddTraps; 586d514b0f3Smrg ps->AddTraps = uxa_check_add_traps; 587d514b0f3Smrg } 588d514b0f3Smrg } 589d514b0f3Smrg#endif 590d514b0f3Smrg 591d514b0f3Smrg LogMessage(X_INFO, 592d514b0f3Smrg "UXA(%d): Driver registered support for the following" 593d514b0f3Smrg " operations:\n", screen->myNum); 594d514b0f3Smrg assert(uxa_driver->prepare_solid != NULL); 595d514b0f3Smrg LogMessage(X_INFO, " solid\n"); 596d514b0f3Smrg assert(uxa_driver->prepare_copy != NULL); 597d514b0f3Smrg LogMessage(X_INFO, " copy\n"); 598d514b0f3Smrg if (uxa_driver->prepare_composite != NULL) { 599d514b0f3Smrg LogMessage(X_INFO, " composite (RENDER acceleration)\n"); 600d514b0f3Smrg } 601d514b0f3Smrg if (uxa_driver->put_image != NULL) { 602d514b0f3Smrg LogMessage(X_INFO, " put_image\n"); 603d514b0f3Smrg } 604d514b0f3Smrg if (uxa_driver->get_image != NULL) { 605d514b0f3Smrg LogMessage(X_INFO, " get_image\n"); 606d514b0f3Smrg } 607d514b0f3Smrg 608d514b0f3Smrg return TRUE; 609d514b0f3Smrg} 610d514b0f3Smrg 611d514b0f3Smrg/** 612d514b0f3Smrg * uxa_driver_fini tears down UXA on a given screen. 613d514b0f3Smrg * 614d514b0f3Smrg * @param pScreen screen being torn down. 615d514b0f3Smrg */ 616d514b0f3Smrgvoid uxa_driver_fini(ScreenPtr pScreen) 617d514b0f3Smrg{ 618d514b0f3Smrg /*right now does nothing */ 619d514b0f3Smrg} 620d514b0f3Smrg 621d514b0f3SmrgBool uxa_resources_init(ScreenPtr screen) 622d514b0f3Smrg{ 623d514b0f3Smrg if (!uxa_glyphs_init(screen)) 624d514b0f3Smrg return FALSE; 625d514b0f3Smrg 626d514b0f3Smrg return TRUE; 627d514b0f3Smrg} 628