13bfa90b6Smrg/* 23bfa90b6Smrg * Copyright © 2001 Keith Packard 33bfa90b6Smrg * 43bfa90b6Smrg * Partly based on code that is Copyright © The XFree86 Project Inc. 53bfa90b6Smrg * 63bfa90b6Smrg * Permission to use, copy, modify, distribute, and sell this software and its 73bfa90b6Smrg * documentation for any purpose is hereby granted without fee, provided that 83bfa90b6Smrg * the above copyright notice appear in all copies and that both that 93bfa90b6Smrg * copyright notice and this permission notice appear in supporting 103bfa90b6Smrg * documentation, and that the name of Keith Packard not be used in 113bfa90b6Smrg * advertising or publicity pertaining to distribution of the software without 123bfa90b6Smrg * specific, written prior permission. Keith Packard makes no 133bfa90b6Smrg * representations about the suitability of this software for any purpose. It 143bfa90b6Smrg * is provided "as is" without express or implied warranty. 153bfa90b6Smrg * 163bfa90b6Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 173bfa90b6Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 183bfa90b6Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 193bfa90b6Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 203bfa90b6Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 213bfa90b6Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 223bfa90b6Smrg * PERFORMANCE OF THIS SOFTWARE. 233bfa90b6Smrg */ 243bfa90b6Smrg 253bfa90b6Smrg/** @file 263bfa90b6Smrg * This file covers the initialization and teardown of SAA, and has various 273bfa90b6Smrg * functions not responsible for performing rendering, pixmap migration, or 283bfa90b6Smrg * memory management. 293bfa90b6Smrg */ 303bfa90b6Smrg 313bfa90b6Smrg#ifdef HAVE_DIX_CONFIG_H 323bfa90b6Smrg#include <dix-config.h> 333bfa90b6Smrg#endif 343bfa90b6Smrg 353bfa90b6Smrg#include <stdlib.h> 363bfa90b6Smrg 373bfa90b6Smrg#include "saa_priv.h" 383bfa90b6Smrg#include <X11/fonts/fontstruct.h> 393bfa90b6Smrg#include "regionstr.h" 403bfa90b6Smrg#include "saa.h" 413bfa90b6Smrg#include "saa_priv.h" 423bfa90b6Smrg 433bfa90b6Smrg#ifdef SAA_DEVPRIVATEKEYREC 443bfa90b6SmrgDevPrivateKeyRec saa_screen_index; 453bfa90b6SmrgDevPrivateKeyRec saa_pixmap_index; 463bfa90b6SmrgDevPrivateKeyRec saa_gc_index; 473bfa90b6Smrg#else 483bfa90b6Smrgint saa_screen_index = -1; 493bfa90b6Smrgint saa_pixmap_index = -1; 503bfa90b6Smrgint saa_gc_index = -1; 513bfa90b6Smrg#endif 523bfa90b6Smrg 533bfa90b6Smrg/** 543bfa90b6Smrg * saa_get_drawable_pixmap() returns a backing pixmap for a given drawable. 553bfa90b6Smrg * 563bfa90b6Smrg * @param pDrawable the drawable being requested. 573bfa90b6Smrg * 583bfa90b6Smrg * This function returns the backing pixmap for a drawable, whether it is a 593bfa90b6Smrg * redirected window, unredirected window, or already a pixmap. Note that 603bfa90b6Smrg * coordinate translation is needed when drawing to the backing pixmap of a 613bfa90b6Smrg * redirected window, and the translation coordinates are provided by calling 623bfa90b6Smrg * saa_get_drawable_pixmap() on the drawable. 633bfa90b6Smrg */ 643bfa90b6SmrgPixmapPtr 653bfa90b6Smrgsaa_get_drawable_pixmap(DrawablePtr pDrawable) 663bfa90b6Smrg{ 673bfa90b6Smrg if (pDrawable->type == DRAWABLE_WINDOW) 683bfa90b6Smrg return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); 693bfa90b6Smrg else 703bfa90b6Smrg return (PixmapPtr) pDrawable; 713bfa90b6Smrg} 723bfa90b6Smrg 733bfa90b6Smrg/** 743bfa90b6Smrg * Sets the offsets to add to coordinates to make them address the same bits in 753bfa90b6Smrg * the backing drawable. These coordinates are nonzero only for redirected 763bfa90b6Smrg * windows. 773bfa90b6Smrg */ 783bfa90b6Smrgvoid 793bfa90b6Smrgsaa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap, 803bfa90b6Smrg int *xp, int *yp) 813bfa90b6Smrg{ 823bfa90b6Smrg#ifdef COMPOSITE 833bfa90b6Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 843bfa90b6Smrg *xp = -pPixmap->screen_x; 853bfa90b6Smrg *yp = -pPixmap->screen_y; 863bfa90b6Smrg return; 873bfa90b6Smrg } 883bfa90b6Smrg#endif 893bfa90b6Smrg 903bfa90b6Smrg *xp = 0; 913bfa90b6Smrg *yp = 0; 923bfa90b6Smrg} 933bfa90b6Smrg 943bfa90b6Smrg/** 953bfa90b6Smrg * Returns the pixmap which backs a drawable, and the offsets to add to 963bfa90b6Smrg * coordinates to make them address the same bits in the backing drawable. 973bfa90b6Smrg */ 983bfa90b6SmrgPixmapPtr 993bfa90b6Smrgsaa_get_pixmap(DrawablePtr drawable, int *xp, int *yp) 1003bfa90b6Smrg{ 1013bfa90b6Smrg PixmapPtr pixmap = saa_get_drawable_pixmap(drawable); 1023bfa90b6Smrg 1033bfa90b6Smrg saa_get_drawable_deltas(drawable, pixmap, xp, yp); 1043bfa90b6Smrg 1053bfa90b6Smrg return pixmap; 1063bfa90b6Smrg} 1073bfa90b6Smrg 1083bfa90b6Smrgstatic Bool 1093bfa90b6Smrgsaa_download_from_hw(PixmapPtr pix, RegionPtr readback) 1103bfa90b6Smrg{ 1113bfa90b6Smrg struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); 1123bfa90b6Smrg struct saa_driver *driver = sscreen->driver; 1133bfa90b6Smrg struct saa_pixmap *spix = saa_pixmap(pix); 1143bfa90b6Smrg void *addr; 1153bfa90b6Smrg Bool ret; 1163bfa90b6Smrg 1173bfa90b6Smrg if (spix->mapped_access) 1183bfa90b6Smrg driver->release_from_cpu(driver, pix, spix->mapped_access); 1193bfa90b6Smrg 1203bfa90b6Smrg ret = driver->download_from_hw(driver, pix, readback); 1213bfa90b6Smrg 1223bfa90b6Smrg if (spix->mapped_access) { 1233bfa90b6Smrg addr = driver->sync_for_cpu(driver, pix, spix->mapped_access); 1243bfa90b6Smrg if (addr != NULL) 1253bfa90b6Smrg spix->addr = addr; 1263bfa90b6Smrg } 1273bfa90b6Smrg 1283bfa90b6Smrg return ret; 1293bfa90b6Smrg} 1303bfa90b6Smrg 1313bfa90b6SmrgBool 1323bfa90b6Smrgsaa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access, 1333bfa90b6Smrg RegionPtr read_reg) 1343bfa90b6Smrg{ 1353bfa90b6Smrg ScreenPtr pScreen = pix->drawable.pScreen; 1363bfa90b6Smrg struct saa_screen_priv *sscreen = saa_screen(pScreen); 1373bfa90b6Smrg struct saa_driver *driver = sscreen->driver; 1383bfa90b6Smrg struct saa_pixmap *spix = saa_pixmap(pix); 1393bfa90b6Smrg saa_access_t map_access = 0; 1403bfa90b6Smrg Bool ret = TRUE; 1413bfa90b6Smrg 1423bfa90b6Smrg if (read_reg && REGION_NOTEMPTY(pScreen, read_reg)) 1433bfa90b6Smrg ret = saa_download_from_hw(pix, read_reg); 1443bfa90b6Smrg 1453bfa90b6Smrg if (!ret) { 1463bfa90b6Smrg LogMessage(X_ERROR, "Prepare access pixmap failed.\n"); 1473bfa90b6Smrg return ret; 1483bfa90b6Smrg } 1493bfa90b6Smrg 1503bfa90b6Smrg if ((access & SAA_ACCESS_R) != 0 && spix->read_access++ == 0) 1513bfa90b6Smrg map_access = SAA_ACCESS_R; 1523bfa90b6Smrg if ((access & SAA_ACCESS_W) != 0 && spix->write_access++ == 0) 1533bfa90b6Smrg map_access |= SAA_ACCESS_W; 1543bfa90b6Smrg 1553bfa90b6Smrg if (map_access) { 1563bfa90b6Smrg if (spix->auth_loc != saa_loc_override) { 1573bfa90b6Smrg (void)driver->sync_for_cpu(driver, pix, map_access); 1583bfa90b6Smrg spix->addr = driver->map(driver, pix, map_access); 1593bfa90b6Smrg } else 1603bfa90b6Smrg spix->addr = spix->override; 1613bfa90b6Smrg spix->mapped_access |= map_access; 1623bfa90b6Smrg } 1633bfa90b6Smrg 1643bfa90b6Smrg pix->devPrivate.ptr = spix->addr; 1653bfa90b6Smrg return TRUE; 1663bfa90b6Smrg} 1673bfa90b6Smrg 1683bfa90b6Smrgvoid 1693bfa90b6Smrgsaa_finish_access_pixmap(PixmapPtr pix, saa_access_t access) 1703bfa90b6Smrg{ 1713bfa90b6Smrg struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); 1723bfa90b6Smrg struct saa_driver *driver = sscreen->driver; 1733bfa90b6Smrg struct saa_pixmap *spix = saa_pixmap(pix); 1743bfa90b6Smrg saa_access_t unmap_access = 0; 1753bfa90b6Smrg 1763bfa90b6Smrg if ((access & SAA_ACCESS_R) != 0 && --spix->read_access == 0) 1773bfa90b6Smrg unmap_access = SAA_ACCESS_R; 1783bfa90b6Smrg if ((access & SAA_ACCESS_W) != 0 && --spix->write_access == 0) 1793bfa90b6Smrg unmap_access |= SAA_ACCESS_W; 1803bfa90b6Smrg 1813bfa90b6Smrg if (spix->read_access < 0) 1823bfa90b6Smrg LogMessage(X_ERROR, "Incorrect read access.\n"); 1833bfa90b6Smrg if (spix->write_access < 0) 1843bfa90b6Smrg LogMessage(X_ERROR, "Incorrect write access.\n"); 1853bfa90b6Smrg 1863bfa90b6Smrg if (unmap_access) { 1873bfa90b6Smrg if (spix->auth_loc != saa_loc_override) { 1883bfa90b6Smrg driver->unmap(driver, pix, unmap_access); 1893bfa90b6Smrg driver->release_from_cpu(driver, pix, unmap_access); 1903bfa90b6Smrg } 1913bfa90b6Smrg spix->mapped_access &= ~unmap_access; 1923bfa90b6Smrg } 1933bfa90b6Smrg if (!spix->mapped_access) { 1943bfa90b6Smrg spix->addr = NULL; 1953bfa90b6Smrg pix->devPrivate.ptr = SAA_INVALID_ADDRESS; 1963bfa90b6Smrg } 1973bfa90b6Smrg} 1983bfa90b6Smrg 1993bfa90b6Smrg/* 2003bfa90b6Smrg * Callback that is called after a rendering operation. We try to 2013bfa90b6Smrg * determine whether it's a shadow damage or a hw damage and call the 2023bfa90b6Smrg * driver callback. 2033bfa90b6Smrg */ 2043bfa90b6Smrg 2053bfa90b6Smrgstatic void 2063bfa90b6Smrgsaa_report_damage(DamagePtr damage, RegionPtr reg, void *closure) 2073bfa90b6Smrg{ 2083bfa90b6Smrg PixmapPtr pixmap = (PixmapPtr) closure; 2093bfa90b6Smrg struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); 2103bfa90b6Smrg struct saa_driver *driver = saa_screen(pixmap->drawable.pScreen)->driver; 2113bfa90b6Smrg 2123bfa90b6Smrg if (spix->read_access || spix->write_access) 2133bfa90b6Smrg LogMessage(X_ERROR, "Damage report inside prepare access.\n"); 2143bfa90b6Smrg 2153bfa90b6Smrg driver->operation_complete(driver, pixmap); 2163bfa90b6Smrg DamageEmpty(damage); 2173bfa90b6Smrg} 2183bfa90b6Smrg 21925dbecb6Smrg/** 22025dbecb6Smrg * saa_notify_destroy_damage - Handle destroy damage notification 22125dbecb6Smrg * 22225dbecb6Smrg * \param damage[in] damage Pointer to damage about to be destroyed 22325dbecb6Smrg * \param closure[in] closure Closure. 22425dbecb6Smrg * 22525dbecb6Smrg * Makes sure that whatever code destroys a damage object clears the 22625dbecb6Smrg * saa_pixmap damage pointer. This is extra protection. Typically 22725dbecb6Smrg * saa_destroy_pixmap should be correct if the various subsystem 22825dbecb6Smrg * DestroyPixmap functions are called in the right order. 22925dbecb6Smrg */ 23025dbecb6Smrgstatic void 23125dbecb6Smrgsaa_notify_destroy_damage(DamagePtr damage, void *closure) 23225dbecb6Smrg{ 23325dbecb6Smrg PixmapPtr pixmap = (PixmapPtr) closure; 23425dbecb6Smrg struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); 23525dbecb6Smrg 23625dbecb6Smrg if (spix->damage == damage) 23725dbecb6Smrg spix->damage = NULL; 23825dbecb6Smrg} 23925dbecb6Smrg 2403bfa90b6SmrgBool 2413bfa90b6Smrgsaa_add_damage(PixmapPtr pixmap) 2423bfa90b6Smrg{ 2433bfa90b6Smrg ScreenPtr pScreen = pixmap->drawable.pScreen; 2443bfa90b6Smrg struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); 2453bfa90b6Smrg 2463bfa90b6Smrg if (spix->damage) 2473bfa90b6Smrg return TRUE; 2483bfa90b6Smrg 24925dbecb6Smrg spix->damage = DamageCreate(saa_report_damage, saa_notify_destroy_damage, 2503bfa90b6Smrg DamageReportRawRegion, TRUE, pScreen, pixmap); 2513bfa90b6Smrg if (!spix->damage) 2523bfa90b6Smrg return FALSE; 2533bfa90b6Smrg 2543bfa90b6Smrg DamageRegister(&pixmap->drawable, spix->damage); 2553bfa90b6Smrg DamageSetReportAfterOp(spix->damage, TRUE); 2563bfa90b6Smrg 2573bfa90b6Smrg return TRUE; 2583bfa90b6Smrg} 2593bfa90b6Smrg 2603bfa90b6Smrgstatic inline RegionPtr 2613bfa90b6Smrgsaa_pix_damage_region(struct saa_pixmap *spix) 2623bfa90b6Smrg{ 2633bfa90b6Smrg return (spix->damage ? DamageRegion(spix->damage) : NULL); 2643bfa90b6Smrg} 2653bfa90b6Smrg 2663bfa90b6SmrgBool 2673bfa90b6Smrgsaa_pad_read(DrawablePtr draw) 2683bfa90b6Smrg{ 2693bfa90b6Smrg ScreenPtr pScreen = draw->pScreen; 2703bfa90b6Smrg PixmapPtr pix; 2713bfa90b6Smrg int xp; 2723bfa90b6Smrg int yp; 2733bfa90b6Smrg BoxRec box; 2743bfa90b6Smrg RegionRec entire; 2753bfa90b6Smrg Bool ret; 2763bfa90b6Smrg 2773bfa90b6Smrg (void)pScreen; 2783bfa90b6Smrg pix = saa_get_pixmap(draw, &xp, &yp); 2793bfa90b6Smrg 2803bfa90b6Smrg box.x1 = draw->x + xp; 2813bfa90b6Smrg box.y1 = draw->y + yp; 2823bfa90b6Smrg box.x2 = box.x1 + draw->width; 2833bfa90b6Smrg box.y2 = box.y1 + draw->height; 2843bfa90b6Smrg 2853bfa90b6Smrg REGION_INIT(pScreen, &entire, &box, 1); 2863bfa90b6Smrg ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); 2873bfa90b6Smrg REGION_UNINIT(pScreen, &entire); 2883bfa90b6Smrg return ret; 2893bfa90b6Smrg} 2903bfa90b6Smrg 2913bfa90b6SmrgBool 2923bfa90b6Smrgsaa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h) 2933bfa90b6Smrg{ 2943bfa90b6Smrg ScreenPtr pScreen = draw->pScreen; 2953bfa90b6Smrg PixmapPtr pix; 2963bfa90b6Smrg int xp; 2973bfa90b6Smrg int yp; 2983bfa90b6Smrg BoxRec box; 2993bfa90b6Smrg RegionRec entire; 3003bfa90b6Smrg Bool ret; 3013bfa90b6Smrg 3023bfa90b6Smrg (void)pScreen; 3033bfa90b6Smrg pix = saa_get_pixmap(draw, &xp, &yp); 3043bfa90b6Smrg 3053bfa90b6Smrg box.x1 = x + xp; 3063bfa90b6Smrg box.y1 = y + yp; 3073bfa90b6Smrg box.x2 = box.x1 + w; 3083bfa90b6Smrg box.y2 = box.y1 + h; 3093bfa90b6Smrg 3103bfa90b6Smrg REGION_INIT(pScreen, &entire, &box, 1); 3113bfa90b6Smrg ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); 3123bfa90b6Smrg REGION_UNINIT(pScreen, &entire); 3133bfa90b6Smrg return ret; 3143bfa90b6Smrg} 3153bfa90b6Smrg 3163bfa90b6Smrg/** 3173bfa90b6Smrg * Prepares a drawable destination for access, and maps it read-write. 3183bfa90b6Smrg * If check_read is TRUE, pGC should point to a valid GC. The drawable 3193bfa90b6Smrg * may then be mapped write-only if the pending operation admits. 3203bfa90b6Smrg */ 3213bfa90b6Smrg 3223bfa90b6SmrgBool 3233bfa90b6Smrgsaa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read, 3243bfa90b6Smrg saa_access_t * access) 3253bfa90b6Smrg{ 3263bfa90b6Smrg int xp; 3273bfa90b6Smrg int yp; 3283bfa90b6Smrg PixmapPtr pixmap = saa_get_pixmap(draw, &xp, &yp); 3293bfa90b6Smrg struct saa_pixmap *spix = saa_pixmap(pixmap); 3303bfa90b6Smrg 3313bfa90b6Smrg *access = SAA_ACCESS_W; 3323bfa90b6Smrg 3333bfa90b6Smrg /* 3343bfa90b6Smrg * If the to-be-damaged area doesn't depend at all on previous 3353bfa90b6Smrg * rendered contents, we don't need to do any readback. 3363bfa90b6Smrg */ 3373bfa90b6Smrg 3383bfa90b6Smrg if (check_read && !saa_gc_reads_destination(draw, pGC)) 3393bfa90b6Smrg return saa_prepare_access_pixmap(pixmap, *access, NULL); 3403bfa90b6Smrg 3413bfa90b6Smrg *access |= SAA_ACCESS_R; 3423bfa90b6Smrg 3433bfa90b6Smrg /* 3443bfa90b6Smrg * Read back the area to be damaged. 3453bfa90b6Smrg */ 3463bfa90b6Smrg 3473bfa90b6Smrg return saa_prepare_access_pixmap(pixmap, *access, 3483bfa90b6Smrg saa_pix_damage_pending(spix)); 3493bfa90b6Smrg} 3503bfa90b6Smrg 3513bfa90b6Smrgvoid 3523bfa90b6Smrgsaa_fad_read(DrawablePtr draw) 3533bfa90b6Smrg{ 3543bfa90b6Smrg saa_finish_access_pixmap(saa_get_drawable_pixmap(draw), SAA_ACCESS_R); 3553bfa90b6Smrg} 3563bfa90b6Smrg 3573bfa90b6Smrgvoid 3583bfa90b6Smrgsaa_fad_write(DrawablePtr draw, saa_access_t access) 3593bfa90b6Smrg{ 3603bfa90b6Smrg PixmapPtr pix = saa_get_drawable_pixmap(draw); 3613bfa90b6Smrg struct saa_pixmap *spix = saa_pixmap(pix); 3623bfa90b6Smrg 3633bfa90b6Smrg saa_finish_access_pixmap(pix, access); 3643bfa90b6Smrg if (spix->damage) 3653bfa90b6Smrg saa_pixmap_dirty(pix, FALSE, saa_pix_damage_pending(spix)); 3663bfa90b6Smrg} 3673bfa90b6Smrg 3683bfa90b6SmrgBool 3693bfa90b6Smrgsaa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC) 3703bfa90b6Smrg{ 3713bfa90b6Smrg return ((pGC->alu != GXcopy && pGC->alu != GXclear && pGC->alu != GXset && 3723bfa90b6Smrg pGC->alu != GXcopyInverted) || pGC->fillStyle == FillStippled || 373591e32d7Ssnj pGC->clientClip != NULL || 3743bfa90b6Smrg !SAA_PM_IS_SOLID(pDrawable, pGC->planemask)); 3753bfa90b6Smrg} 3763bfa90b6Smrg 3773bfa90b6SmrgBool 3783bfa90b6Smrgsaa_op_reads_destination(CARD8 op) 3793bfa90b6Smrg{ 3803bfa90b6Smrg /* FALSE (does not read destination) is the list of ops in the protocol 3813bfa90b6Smrg * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. 3823bfa90b6Smrg * That's just Clear and Src. ReduceCompositeOp() will already have 3833bfa90b6Smrg * converted con/disjoint clear/src to Clear or Src. 3843bfa90b6Smrg */ 3853bfa90b6Smrg switch (op) { 3863bfa90b6Smrg case PictOpClear: 3873bfa90b6Smrg case PictOpSrc: 3883bfa90b6Smrg return FALSE; 3893bfa90b6Smrg default: 3903bfa90b6Smrg return TRUE; 3913bfa90b6Smrg } 3923bfa90b6Smrg} 3933bfa90b6Smrg 3943bfa90b6Smrgstatic void 3953bfa90b6Smrgsaa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) 3963bfa90b6Smrg{ 3973bfa90b6Smrg /* fbValidateGC will do direct access to pixmaps if the tiling has changed. 3983bfa90b6Smrg * Do a few smart things so fbValidateGC can do it's work. 3993bfa90b6Smrg */ 4003bfa90b6Smrg 4013bfa90b6Smrg ScreenPtr pScreen = pDrawable->pScreen; 4023bfa90b6Smrg struct saa_screen_priv *sscreen = saa_screen(pScreen); 4033bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGC); 4043bfa90b6Smrg PixmapPtr pTile = NULL; 4053bfa90b6Smrg Bool finish_current_tile = FALSE; 4063bfa90b6Smrg 4073bfa90b6Smrg /* Either of these conditions is enough to trigger access to a tile pixmap. */ 4083bfa90b6Smrg /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */ 4093bfa90b6Smrg if (pGC->fillStyle == FillTiled 4103bfa90b6Smrg || ((changes & GCTile) && !pGC->tileIsPixel)) { 4113bfa90b6Smrg pTile = pGC->tile.pixmap; 4123bfa90b6Smrg 4133bfa90b6Smrg /* Sometimes tile pixmaps are swapped, you need access to: 4143bfa90b6Smrg * - The current tile if it depth matches. 4153bfa90b6Smrg * - Or the rotated tile if that one matches depth and !(changes & GCTile). 4163bfa90b6Smrg * - Or the current tile pixmap and a newly created one. 4173bfa90b6Smrg */ 4183bfa90b6Smrg if (pTile && pTile->drawable.depth != pDrawable->depth 4193bfa90b6Smrg && !(changes & GCTile)) { 4203bfa90b6Smrg PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC); 4213bfa90b6Smrg 4223bfa90b6Smrg if (pRotatedTile 4233bfa90b6Smrg && pRotatedTile->drawable.depth == pDrawable->depth) 4243bfa90b6Smrg pTile = pRotatedTile; 4253bfa90b6Smrg else 4263bfa90b6Smrg finish_current_tile = TRUE; /* CreatePixmap will be called. */ 4273bfa90b6Smrg } 4283bfa90b6Smrg } 4293bfa90b6Smrg 4303bfa90b6Smrg if (pGC->stipple && !saa_pad_read(&pGC->stipple->drawable)) { 4313bfa90b6Smrg LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); 4323bfa90b6Smrg return; 4333bfa90b6Smrg } 4343bfa90b6Smrg 4353bfa90b6Smrg if (pTile && !saa_pad_read(&pTile->drawable)) { 4363bfa90b6Smrg LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); 4373bfa90b6Smrg goto out_no_tile; 4383bfa90b6Smrg } 4393bfa90b6Smrg 4403bfa90b6Smrg /* Calls to Create/DestroyPixmap have to be identified as special, so 4413bfa90b6Smrg * up sscreen->fallback_count. 4423bfa90b6Smrg */ 4433bfa90b6Smrg 4443bfa90b6Smrg sscreen->fallback_count++; 4453bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4463bfa90b6Smrg (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); 4473bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4483bfa90b6Smrg 4493bfa90b6Smrg if (finish_current_tile && pGC->tile.pixmap) 4503bfa90b6Smrg saa_fad_write(&pGC->tile.pixmap->drawable, SAA_ACCESS_W); 4513bfa90b6Smrg sscreen->fallback_count--; 4523bfa90b6Smrg 4533bfa90b6Smrg if (pTile) 4543bfa90b6Smrg saa_fad_read(&pTile->drawable); 4553bfa90b6Smrg out_no_tile: 4563bfa90b6Smrg if (pGC->stipple) 4573bfa90b6Smrg saa_fad_read(&pGC->stipple->drawable); 4583bfa90b6Smrg} 4593bfa90b6Smrg 4603bfa90b6Smrgstatic void 4613bfa90b6Smrgsaa_destroy_gc(GCPtr pGC) 4623bfa90b6Smrg{ 4633bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGC); 4643bfa90b6Smrg 4653bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4663bfa90b6Smrg (*pGC->funcs->DestroyGC) (pGC); 4673bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4683bfa90b6Smrg} 4693bfa90b6Smrg 4703bfa90b6Smrgstatic void 4713bfa90b6Smrgsaa_change_gc(GCPtr pGC, unsigned long mask) 4723bfa90b6Smrg{ 4733bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGC); 4743bfa90b6Smrg 4753bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4763bfa90b6Smrg (*pGC->funcs->ChangeGC) (pGC, mask); 4773bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4783bfa90b6Smrg} 4793bfa90b6Smrg 4803bfa90b6Smrgstatic void 4813bfa90b6Smrgsaa_copy_gc(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) 4823bfa90b6Smrg{ 4833bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGCDst); 4843bfa90b6Smrg 4853bfa90b6Smrg saa_swap(sgc, pGCDst, funcs); 4863bfa90b6Smrg (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); 4873bfa90b6Smrg saa_swap(sgc, pGCDst, funcs); 4883bfa90b6Smrg} 4893bfa90b6Smrg 4903bfa90b6Smrgstatic void 4913bfa90b6Smrgsaa_change_clip(GCPtr pGC, int type, pointer pvalue, int nrects) 4923bfa90b6Smrg{ 4933bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGC); 4943bfa90b6Smrg 4953bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4963bfa90b6Smrg (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); 4973bfa90b6Smrg saa_swap(sgc, pGC, funcs); 4983bfa90b6Smrg} 4993bfa90b6Smrg 5003bfa90b6Smrgstatic void 5013bfa90b6Smrgsaa_copy_clip(GCPtr pGCDst, GCPtr pGCSrc) 5023bfa90b6Smrg{ 5033bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGCDst); 5043bfa90b6Smrg 5053bfa90b6Smrg saa_swap(sgc, pGCDst, funcs); 5063bfa90b6Smrg (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); 5073bfa90b6Smrg saa_swap(sgc, pGCDst, funcs); 5083bfa90b6Smrg} 5093bfa90b6Smrg 5103bfa90b6Smrgstatic void 5113bfa90b6Smrgsaa_destroy_clip(GCPtr pGC) 5123bfa90b6Smrg{ 5133bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGC); 5143bfa90b6Smrg 5153bfa90b6Smrg saa_swap(sgc, pGC, funcs); 5163bfa90b6Smrg (*pGC->funcs->DestroyClip) (pGC); 5173bfa90b6Smrg saa_swap(sgc, pGC, funcs); 5183bfa90b6Smrg} 5193bfa90b6Smrg 5203bfa90b6Smrgstatic GCFuncs saa_gc_funcs = { 5213bfa90b6Smrg saa_validate_gc, 5223bfa90b6Smrg saa_change_gc, 5233bfa90b6Smrg saa_copy_gc, 5243bfa90b6Smrg saa_destroy_gc, 5253bfa90b6Smrg saa_change_clip, 5263bfa90b6Smrg saa_destroy_clip, 5273bfa90b6Smrg saa_copy_clip 5283bfa90b6Smrg}; 5293bfa90b6Smrg 5303bfa90b6Smrg/** 5313bfa90b6Smrg * saa_create_gc makes a new GC and hooks up its funcs handler, so that 5323bfa90b6Smrg * saa_validate_gc() will get called. 5333bfa90b6Smrg */ 5343bfa90b6Smrgint 5353bfa90b6Smrgsaa_create_gc(GCPtr pGC) 5363bfa90b6Smrg{ 5373bfa90b6Smrg ScreenPtr pScreen = pGC->pScreen; 5383bfa90b6Smrg struct saa_screen_priv *sscreen = saa_screen(pScreen); 5393bfa90b6Smrg struct saa_gc_priv *sgc = saa_gc(pGC); 5403bfa90b6Smrg Bool ret; 5413bfa90b6Smrg 5423bfa90b6Smrg saa_swap(sscreen, pScreen, CreateGC); 5433bfa90b6Smrg ret = pScreen->CreateGC(pGC); 5443bfa90b6Smrg if (ret) { 5453bfa90b6Smrg saa_wrap(sgc, pGC, funcs, &saa_gc_funcs); 5463bfa90b6Smrg saa_wrap(sgc, pGC, ops, &saa_gc_ops); 5473bfa90b6Smrg } 5483bfa90b6Smrg saa_swap(sscreen, pScreen, CreateGC); 5493bfa90b6Smrg 5503bfa90b6Smrg return ret; 5513bfa90b6Smrg} 5523bfa90b6Smrg 5533bfa90b6Smrgstatic Bool 5543bfa90b6Smrgsaa_prepare_access_window(WindowPtr pWin) 5553bfa90b6Smrg{ 5563bfa90b6Smrg if (pWin->backgroundState == BackgroundPixmap) { 5573bfa90b6Smrg if (!saa_pad_read(&pWin->background.pixmap->drawable)) 5583bfa90b6Smrg return FALSE; 5593bfa90b6Smrg } 5603bfa90b6Smrg 5613bfa90b6Smrg if (pWin->borderIsPixel == FALSE) { 5623bfa90b6Smrg if (!saa_pad_read(&pWin->border.pixmap->drawable)) { 5633bfa90b6Smrg if (pWin->backgroundState == BackgroundPixmap) 5643bfa90b6Smrg saa_fad_read(&pWin->background.pixmap->drawable); 5653bfa90b6Smrg return FALSE; 5663bfa90b6Smrg } 5673bfa90b6Smrg } 5683bfa90b6Smrg return TRUE; 5693bfa90b6Smrg} 5703bfa90b6Smrg 5713bfa90b6Smrgstatic void 5723bfa90b6Smrgsaa_finish_access_window(WindowPtr pWin) 5733bfa90b6Smrg{ 5743bfa90b6Smrg if (pWin->backgroundState == BackgroundPixmap) 5753bfa90b6Smrg saa_fad_read(&pWin->background.pixmap->drawable); 5763bfa90b6Smrg 5773bfa90b6Smrg if (pWin->borderIsPixel == FALSE) 5783bfa90b6Smrg saa_fad_read(&pWin->border.pixmap->drawable); 5793bfa90b6Smrg} 5803bfa90b6Smrg 5813bfa90b6Smrgstatic Bool 5823bfa90b6Smrgsaa_change_window_attributes(WindowPtr pWin, unsigned long mask) 5833bfa90b6Smrg{ 5843bfa90b6Smrg Bool ret; 5853bfa90b6Smrg 5863bfa90b6Smrg if (!saa_prepare_access_window(pWin)) 5873bfa90b6Smrg return FALSE; 5883bfa90b6Smrg ret = fbChangeWindowAttributes(pWin, mask); 5893bfa90b6Smrg saa_finish_access_window(pWin); 5903bfa90b6Smrg return ret; 5913bfa90b6Smrg} 5923bfa90b6Smrg 5933bfa90b6SmrgRegionPtr 5943bfa90b6Smrgsaa_bitmap_to_region(PixmapPtr pPix) 5953bfa90b6Smrg{ 5963bfa90b6Smrg RegionPtr ret; 5973bfa90b6Smrg 5983bfa90b6Smrg if (!saa_pad_read(&pPix->drawable)) 5993bfa90b6Smrg return NULL; 6003bfa90b6Smrg ret = fbPixmapToRegion(pPix); 6013bfa90b6Smrg saa_fad_read(&pPix->drawable); 6023bfa90b6Smrg return ret; 6033bfa90b6Smrg} 6043bfa90b6Smrg 6053bfa90b6Smrgvoid 6063bfa90b6Smrgsaa_set_fallback_debug(ScreenPtr screen, Bool enable) 6073bfa90b6Smrg{ 6083bfa90b6Smrg struct saa_screen_priv *sscreen = saa_screen(screen); 6093bfa90b6Smrg 6103bfa90b6Smrg sscreen->fallback_debug = enable; 6113bfa90b6Smrg} 6123bfa90b6Smrg 6133bfa90b6Smrg/** 61425dbecb6Smrg * saa_early_close_screen() Makes sure we call saa_destroy_pixmap on the 61525dbecb6Smrg * miScreenInit() pixmap _before_ damageCloseScreen, after which it will 61625dbecb6Smrg * generate an invalid memory access. Also unwraps the functions we 61725dbecb6Smrg * wrapped _after_ DamageSetup(). 6183bfa90b6Smrg */ 61925dbecb6Smrgstatic Bool 62025dbecb6Smrgsaa_early_close_screen(CLOSE_SCREEN_ARGS_DECL) 6213bfa90b6Smrg{ 6223bfa90b6Smrg struct saa_screen_priv *sscreen = saa_screen(pScreen); 6233bfa90b6Smrg 6243bfa90b6Smrg if (pScreen->devPrivate) { 6253bfa90b6Smrg /* Destroy the pixmap created by miScreenInit() *before* 6263bfa90b6Smrg * chaining up as we finalize ourselves here and so this 6273bfa90b6Smrg * is the last chance we have of releasing our resources 6283bfa90b6Smrg * associated with the Pixmap. So do it first. 6293bfa90b6Smrg */ 6303bfa90b6Smrg (void)(*pScreen->DestroyPixmap) (pScreen->devPrivate); 6313bfa90b6Smrg pScreen->devPrivate = NULL; 6323bfa90b6Smrg } 6333bfa90b6Smrg 63425dbecb6Smrg saa_unwrap_early(sscreen, pScreen, CloseScreen); 63525dbecb6Smrg saa_unwrap(sscreen, pScreen, DestroyPixmap); 63625dbecb6Smrg 63725dbecb6Smrg return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 63825dbecb6Smrg} 63925dbecb6Smrg 64025dbecb6Smrg/** 64125dbecb6Smrg * saa_close_screen() unwraps its wrapped screen functions and tears down SAA's 64225dbecb6Smrg * screen private, before calling down to the next CloseScreen. 64325dbecb6Smrg */ 64425dbecb6SmrgBool 64525dbecb6Smrgsaa_close_screen(CLOSE_SCREEN_ARGS_DECL) 64625dbecb6Smrg{ 64725dbecb6Smrg struct saa_screen_priv *sscreen = saa_screen(pScreen); 64825dbecb6Smrg struct saa_driver *driver = sscreen->driver; 64925dbecb6Smrg 6503bfa90b6Smrg saa_unwrap(sscreen, pScreen, CloseScreen); 6513bfa90b6Smrg saa_unwrap(sscreen, pScreen, CreateGC); 6523bfa90b6Smrg saa_unwrap(sscreen, pScreen, ChangeWindowAttributes); 6533bfa90b6Smrg saa_unwrap(sscreen, pScreen, CreatePixmap); 6543bfa90b6Smrg saa_unwrap(sscreen, pScreen, ModifyPixmapHeader); 6553bfa90b6Smrg saa_unwrap(sscreen, pScreen, BitmapToRegion); 6563bfa90b6Smrg#ifdef RENDER 6573bfa90b6Smrg saa_render_takedown(pScreen); 6583bfa90b6Smrg#endif 6593bfa90b6Smrg saa_unaccel_takedown(pScreen); 6603bfa90b6Smrg driver->takedown(driver); 6613bfa90b6Smrg 6623bfa90b6Smrg free(sscreen); 6633bfa90b6Smrg 6643bfa90b6Smrg return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 6653bfa90b6Smrg} 6663bfa90b6Smrg 6673bfa90b6Smrgstruct saa_driver * 6683bfa90b6Smrgsaa_get_driver(ScreenPtr pScreen) 6693bfa90b6Smrg{ 6703bfa90b6Smrg return saa_screen(pScreen)->driver; 6713bfa90b6Smrg} 6723bfa90b6Smrg 6733bfa90b6Smrg/** 6743bfa90b6Smrg * @param pScreen screen being initialized 6753bfa90b6Smrg * @param pScreenInfo SAA driver record 6763bfa90b6Smrg * 6773bfa90b6Smrg * saa_driver_init sets up SAA given a driver record filled in by the driver. 6783bfa90b6Smrg * pScreenInfo should have been allocated by saa_driver_alloc(). See the 6793bfa90b6Smrg * comments in _SaaDriver for what must be filled in and what is optional. 6803bfa90b6Smrg * 6813bfa90b6Smrg * @return TRUE if SAA was successfully initialized. 6823bfa90b6Smrg */ 6833bfa90b6SmrgBool 6843bfa90b6Smrgsaa_driver_init(ScreenPtr screen, struct saa_driver * saa_driver) 6853bfa90b6Smrg{ 6863bfa90b6Smrg struct saa_screen_priv *sscreen; 6873bfa90b6Smrg 6883bfa90b6Smrg if (!saa_driver) 6893bfa90b6Smrg return FALSE; 6903bfa90b6Smrg 6913bfa90b6Smrg if (saa_driver->saa_major != SAA_VERSION_MAJOR || 6923bfa90b6Smrg saa_driver->saa_minor > SAA_VERSION_MINOR) { 6933bfa90b6Smrg LogMessage(X_ERROR, 6943bfa90b6Smrg "SAA(%d): driver's SAA version requirements " 6953bfa90b6Smrg "(%d.%d) are incompatible with SAA version (%d.%d)\n", 6963bfa90b6Smrg screen->myNum, saa_driver->saa_major, 6973bfa90b6Smrg saa_driver->saa_minor, SAA_VERSION_MAJOR, SAA_VERSION_MINOR); 6983bfa90b6Smrg return FALSE; 6993bfa90b6Smrg } 7003bfa90b6Smrg#if 0 7013bfa90b6Smrg if (!saa_driver->prepare_solid) { 7023bfa90b6Smrg LogMessage(X_ERROR, 7033bfa90b6Smrg "SAA(%d): saa_driver_t::prepare_solid must be " 7043bfa90b6Smrg "non-NULL\n", screen->myNum); 7053bfa90b6Smrg return FALSE; 7063bfa90b6Smrg } 7073bfa90b6Smrg 7083bfa90b6Smrg if (!saa_driver->prepare_copy) { 7093bfa90b6Smrg LogMessage(X_ERROR, 7103bfa90b6Smrg "SAA(%d): saa_driver_t::prepare_copy must be " 7113bfa90b6Smrg "non-NULL\n", screen->myNum); 7123bfa90b6Smrg return FALSE; 7133bfa90b6Smrg } 7143bfa90b6Smrg#endif 7153bfa90b6Smrg#ifdef SAA_DEVPRIVATEKEYREC 7163bfa90b6Smrg if (!dixRegisterPrivateKey(&saa_screen_index, PRIVATE_SCREEN, 0)) { 7173bfa90b6Smrg LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); 7183bfa90b6Smrg return FALSE; 7193bfa90b6Smrg } 7203bfa90b6Smrg if (!dixRegisterPrivateKey(&saa_pixmap_index, PRIVATE_PIXMAP, 7213bfa90b6Smrg saa_driver->pixmap_size)) { 7223bfa90b6Smrg LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); 7233bfa90b6Smrg return FALSE; 7243bfa90b6Smrg } 7253bfa90b6Smrg if (!dixRegisterPrivateKey(&saa_gc_index, PRIVATE_GC, 7263bfa90b6Smrg sizeof(struct saa_gc_priv))) { 7273bfa90b6Smrg LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); 7283bfa90b6Smrg return FALSE; 7293bfa90b6Smrg } 7303bfa90b6Smrg#else 7313bfa90b6Smrg if (!dixRequestPrivate(&saa_screen_index, 0)) { 7323bfa90b6Smrg LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); 7333bfa90b6Smrg return FALSE; 7343bfa90b6Smrg } 7353bfa90b6Smrg if (!dixRequestPrivate(&saa_pixmap_index, saa_driver->pixmap_size)) { 7363bfa90b6Smrg LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); 7373bfa90b6Smrg return FALSE; 7383bfa90b6Smrg } 7393bfa90b6Smrg if (!dixRequestPrivate(&saa_gc_index, sizeof(struct saa_gc_priv))) { 7403bfa90b6Smrg LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); 7413bfa90b6Smrg return FALSE; 7423bfa90b6Smrg } 7433bfa90b6Smrg#endif 7443bfa90b6Smrg 7453bfa90b6Smrg sscreen = calloc(1, sizeof(*sscreen)); 7463bfa90b6Smrg 7473bfa90b6Smrg if (!sscreen) { 7483bfa90b6Smrg LogMessage(X_WARNING, 7493bfa90b6Smrg "SAA(%d): Failed to allocate screen private\n", 7503bfa90b6Smrg screen->myNum); 7513bfa90b6Smrg return FALSE; 7523bfa90b6Smrg } 7533bfa90b6Smrg 7543bfa90b6Smrg sscreen->driver = saa_driver; 7553bfa90b6Smrg dixSetPrivate(&screen->devPrivates, &saa_screen_index, sscreen); 7563bfa90b6Smrg 7573bfa90b6Smrg /* 7583bfa90b6Smrg * Replace various fb screen functions 7593bfa90b6Smrg */ 7603bfa90b6Smrg 7613bfa90b6Smrg saa_wrap(sscreen, screen, CloseScreen, saa_close_screen); 7623bfa90b6Smrg saa_wrap(sscreen, screen, CreateGC, saa_create_gc); 7633bfa90b6Smrg saa_wrap(sscreen, screen, ChangeWindowAttributes, 7643bfa90b6Smrg saa_change_window_attributes); 7653bfa90b6Smrg saa_wrap(sscreen, screen, CreatePixmap, saa_create_pixmap); 7663bfa90b6Smrg saa_wrap(sscreen, screen, ModifyPixmapHeader, saa_modify_pixmap_header); 7673bfa90b6Smrg saa_wrap(sscreen, screen, BitmapToRegion, saa_bitmap_to_region); 7683bfa90b6Smrg saa_unaccel_setup(screen); 7693bfa90b6Smrg#ifdef RENDER 7703bfa90b6Smrg saa_render_setup(screen); 7713bfa90b6Smrg#endif 7723bfa90b6Smrg 77325dbecb6Smrg /* 77425dbecb6Smrg * Correct saa functionality relies on Damage, so set it up now. 77525dbecb6Smrg * Note that this must happen _after_ wrapping the rendering functionality 77625dbecb6Smrg * so that damage happens outside of saa. 77725dbecb6Smrg */ 77825dbecb6Smrg if (!DamageSetup(screen)) 77925dbecb6Smrg return FALSE; 78025dbecb6Smrg 78125dbecb6Smrg /* 78225dbecb6Smrg * Wrap DestroyPixmap after DamageSetup, so that saa_destroy_pixmap is 78325dbecb6Smrg * called _before_ damageDestroyPixmap. This is to make damageDestroyPixmap 78425dbecb6Smrg * doesn't free objects pointed to by our damage pointers. 78525dbecb6Smrg * 78625dbecb6Smrg * Also wrap an early CloseScreen to perform actions needed to be done 78725dbecb6Smrg * before damageCloseScreen and to unwrap DestroyPixmap correctly. 78825dbecb6Smrg */ 78925dbecb6Smrg saa_wrap(sscreen, screen, DestroyPixmap, saa_destroy_pixmap); 79025dbecb6Smrg saa_wrap_early(sscreen, screen, CloseScreen, saa_early_close_screen); 79125dbecb6Smrg 7923bfa90b6Smrg return TRUE; 7933bfa90b6Smrg} 7943bfa90b6Smrg 7953bfa90b6SmrgBool 7963bfa90b6Smrgsaa_resources_init(ScreenPtr screen) 7973bfa90b6Smrg{ 7983bfa90b6Smrg/* if (!saa_glyphs_init(screen)) 7993bfa90b6Smrg return FALSE; 8003bfa90b6Smrg*/ 8013bfa90b6Smrg return TRUE; 8023bfa90b6Smrg} 803