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