uxa.c revision 03b705cf
103b705cfSriastradh/*
203b705cfSriastradh * Copyright © 2001 Keith Packard
303b705cfSriastradh *
403b705cfSriastradh * Partly based on code that is Copyright © The XFree86 Project Inc.
503b705cfSriastradh *
603b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its
703b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that
803b705cfSriastradh * the above copyright notice appear in all copies and that both that
903b705cfSriastradh * copyright notice and this permission notice appear in supporting
1003b705cfSriastradh * documentation, and that the name of Keith Packard not be used in
1103b705cfSriastradh * advertising or publicity pertaining to distribution of the software without
1203b705cfSriastradh * specific, written prior permission.  Keith Packard makes no
1303b705cfSriastradh * representations about the suitability of this software for any purpose.  It
1403b705cfSriastradh * is provided "as is" without express or implied warranty.
1503b705cfSriastradh *
1603b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1703b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1803b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1903b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2003b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2103b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2203b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE.
2303b705cfSriastradh */
2403b705cfSriastradh
2503b705cfSriastradh/** @file
2603b705cfSriastradh * This file covers the initialization and teardown of UXA, and has various
2703b705cfSriastradh * functions not responsible for performing rendering, pixmap migration, or
2803b705cfSriastradh * memory management.
2903b705cfSriastradh */
3003b705cfSriastradh
3103b705cfSriastradh#ifdef HAVE_DIX_CONFIG_H
3203b705cfSriastradh#include <dix-config.h>
3303b705cfSriastradh#endif
3403b705cfSriastradh
3503b705cfSriastradh#include <stdlib.h>
3603b705cfSriastradh
3703b705cfSriastradh#include "uxa-priv.h"
3803b705cfSriastradh#include <X11/fonts/fontstruct.h>
3903b705cfSriastradh#include "dixfontstr.h"
4003b705cfSriastradh#include "uxa.h"
4103b705cfSriastradh#include "uxa-glamor.h"
4203b705cfSriastradh
4303b705cfSriastradh#if HAS_DEVPRIVATEKEYREC
4403b705cfSriastradhDevPrivateKeyRec uxa_screen_index;
4503b705cfSriastradh#else
4603b705cfSriastradhint uxa_screen_index;
4703b705cfSriastradh#endif
4803b705cfSriastradh
4903b705cfSriastradh/**
5003b705cfSriastradh * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
5103b705cfSriastradh *
5203b705cfSriastradh * @param pDrawable the drawable being requested.
5303b705cfSriastradh *
5403b705cfSriastradh * This function returns the backing pixmap for a drawable, whether it is a
5503b705cfSriastradh * redirected window, unredirected window, or already a pixmap.  Note that
5603b705cfSriastradh * coordinate translation is needed when drawing to the backing pixmap of a
5703b705cfSriastradh * redirected window, and the translation coordinates are provided by calling
5803b705cfSriastradh * uxa_get_drawable_pixmap() on the drawable.
5903b705cfSriastradh */
6003b705cfSriastradhPixmapPtr uxa_get_drawable_pixmap(DrawablePtr pDrawable)
6103b705cfSriastradh{
6203b705cfSriastradh	if (pDrawable->type == DRAWABLE_WINDOW)
6303b705cfSriastradh		return pDrawable->pScreen->
6403b705cfSriastradh		    GetWindowPixmap((WindowPtr) pDrawable);
6503b705cfSriastradh	else
6603b705cfSriastradh		return (PixmapPtr) pDrawable;
6703b705cfSriastradh}
6803b705cfSriastradh
6903b705cfSriastradh/**
7003b705cfSriastradh * Sets the offsets to add to coordinates to make them address the same bits in
7103b705cfSriastradh * the backing drawable. These coordinates are nonzero only for redirected
7203b705cfSriastradh * windows.
7303b705cfSriastradh */
7403b705cfSriastradhvoid
7503b705cfSriastradhuxa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
7603b705cfSriastradh			int *xp, int *yp)
7703b705cfSriastradh{
7803b705cfSriastradh#ifdef COMPOSITE
7903b705cfSriastradh	if (pDrawable->type == DRAWABLE_WINDOW) {
8003b705cfSriastradh		*xp = -pPixmap->screen_x;
8103b705cfSriastradh		*yp = -pPixmap->screen_y;
8203b705cfSriastradh		return;
8303b705cfSriastradh	}
8403b705cfSriastradh#endif
8503b705cfSriastradh
8603b705cfSriastradh	*xp = 0;
8703b705cfSriastradh	*yp = 0;
8803b705cfSriastradh}
8903b705cfSriastradh
9003b705cfSriastradh/**
9103b705cfSriastradh * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
9203b705cfSriastradh * memory, meaning that acceleration could probably be done to it, and that it
9303b705cfSriastradh * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
9403b705cfSriastradh * with the CPU.
9503b705cfSriastradh *
9603b705cfSriastradh * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
9703b705cfSriastradh * deal with moving pixmaps in and out of system memory), UXA will give drivers
9803b705cfSriastradh * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
9903b705cfSriastradh *
10003b705cfSriastradh * @return TRUE if the given drawable is in framebuffer memory.
10103b705cfSriastradh */
10203b705cfSriastradhBool uxa_pixmap_is_offscreen(PixmapPtr p)
10303b705cfSriastradh{
10403b705cfSriastradh	ScreenPtr pScreen = p->drawable.pScreen;
10503b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
10603b705cfSriastradh
10703b705cfSriastradh	if (uxa_screen->info->pixmap_is_offscreen)
10803b705cfSriastradh		return uxa_screen->info->pixmap_is_offscreen(p);
10903b705cfSriastradh
11003b705cfSriastradh	return FALSE;
11103b705cfSriastradh}
11203b705cfSriastradh
11303b705cfSriastradh/**
11403b705cfSriastradh * uxa_drawable_is_offscreen() is a convenience wrapper for
11503b705cfSriastradh * uxa_pixmap_is_offscreen().
11603b705cfSriastradh */
11703b705cfSriastradhBool uxa_drawable_is_offscreen(DrawablePtr pDrawable)
11803b705cfSriastradh{
11903b705cfSriastradh	return uxa_pixmap_is_offscreen(uxa_get_drawable_pixmap(pDrawable));
12003b705cfSriastradh}
12103b705cfSriastradh
12203b705cfSriastradh/**
12303b705cfSriastradh  * Returns the pixmap which backs a drawable, and the offsets to add to
12403b705cfSriastradh  * coordinates to make them address the same bits in the backing drawable.
12503b705cfSriastradh  */
12603b705cfSriastradhPixmapPtr uxa_get_offscreen_pixmap(DrawablePtr drawable, int *xp, int *yp)
12703b705cfSriastradh{
12803b705cfSriastradh	PixmapPtr pixmap = uxa_get_drawable_pixmap(drawable);
12903b705cfSriastradh
13003b705cfSriastradh	uxa_get_drawable_deltas(drawable, pixmap, xp, yp);
13103b705cfSriastradh
13203b705cfSriastradh	if (uxa_pixmap_is_offscreen(pixmap))
13303b705cfSriastradh		return pixmap;
13403b705cfSriastradh	else
13503b705cfSriastradh		return NULL;
13603b705cfSriastradh}
13703b705cfSriastradh
13803b705cfSriastradh/**
13903b705cfSriastradh * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
14003b705cfSriastradh *
14103b705cfSriastradh * It deals with waiting for synchronization with the card, determining if
14203b705cfSriastradh * PrepareAccess() is necessary, and working around PrepareAccess() failure.
14303b705cfSriastradh */
14403b705cfSriastradhBool uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
14503b705cfSriastradh{
14603b705cfSriastradh	ScreenPtr pScreen = pDrawable->pScreen;
14703b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
14803b705cfSriastradh	PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
14903b705cfSriastradh	Bool offscreen = uxa_pixmap_is_offscreen(pPixmap);
15003b705cfSriastradh
15103b705cfSriastradh	if (!offscreen)
15203b705cfSriastradh		return TRUE;
15303b705cfSriastradh
15403b705cfSriastradh	if (uxa_screen->info->prepare_access)
15503b705cfSriastradh		return (*uxa_screen->info->prepare_access) (pPixmap, access);
15603b705cfSriastradh	return TRUE;
15703b705cfSriastradh}
15803b705cfSriastradh
15903b705cfSriastradh/**
16003b705cfSriastradh * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
16103b705cfSriastradh *
16203b705cfSriastradh * It deals with calling the driver's finish_access() only if necessary.
16303b705cfSriastradh */
16403b705cfSriastradhvoid uxa_finish_access(DrawablePtr pDrawable, uxa_access_t access)
16503b705cfSriastradh{
16603b705cfSriastradh	ScreenPtr pScreen = pDrawable->pScreen;
16703b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
16803b705cfSriastradh	PixmapPtr pPixmap;
16903b705cfSriastradh
17003b705cfSriastradh	if (uxa_screen->info->finish_access == NULL)
17103b705cfSriastradh		return;
17203b705cfSriastradh
17303b705cfSriastradh	pPixmap = uxa_get_drawable_pixmap(pDrawable);
17403b705cfSriastradh	if (!uxa_pixmap_is_offscreen(pPixmap))
17503b705cfSriastradh		return;
17603b705cfSriastradh
17703b705cfSriastradh	(*uxa_screen->info->finish_access) (pPixmap, access);
17803b705cfSriastradh}
17903b705cfSriastradh
18003b705cfSriastradh/**
18103b705cfSriastradh * uxa_validate_gc() sets the ops to UXA's implementations, which may be
18203b705cfSriastradh * accelerated or may sync the card and fall back to fb.
18303b705cfSriastradh */
18403b705cfSriastradhstatic void
18503b705cfSriastradhuxa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
18603b705cfSriastradh{
18703b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(pGC->pScreen);
18803b705cfSriastradh	/* fbValidateGC will do direct access to pixmaps if the tiling has
18903b705cfSriastradh	 * changed.
19003b705cfSriastradh	 * Preempt fbValidateGC by doing its work and masking the change out, so
19103b705cfSriastradh	 * that we can do the Prepare/finish_access.
19203b705cfSriastradh	 */
19303b705cfSriastradh
19403b705cfSriastradh	/* If we are using GLAMOR, then the tile or stipple pixmap
19503b705cfSriastradh	 * may be pure GLAMOR pixmap, then we should let the glamor
19603b705cfSriastradh	 * to do the validation.
19703b705cfSriastradh	 */
19803b705cfSriastradh	if (uxa_screen->info->flags & UXA_USE_GLAMOR) {
19903b705cfSriastradh		glamor_validate_gc(pGC, changes, pDrawable);
20003b705cfSriastradh		goto set_ops;
20103b705cfSriastradh	}
20203b705cfSriastradh#ifdef FB_24_32BIT
20303b705cfSriastradh	if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
20403b705cfSriastradh		(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
20503b705cfSriastradh		fbGetRotatedPixmap(pGC) = 0;
20603b705cfSriastradh	}
20703b705cfSriastradh
20803b705cfSriastradh	if (pGC->fillStyle == FillTiled) {
20903b705cfSriastradh		PixmapPtr pOldTile, pNewTile;
21003b705cfSriastradh
21103b705cfSriastradh		pOldTile = pGC->tile.pixmap;
21203b705cfSriastradh		if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
21303b705cfSriastradh			pNewTile = fbGetRotatedPixmap(pGC);
21403b705cfSriastradh			if (!pNewTile ||
21503b705cfSriastradh			    pNewTile->drawable.bitsPerPixel !=
21603b705cfSriastradh			    pDrawable->bitsPerPixel) {
21703b705cfSriastradh				if (pNewTile)
21803b705cfSriastradh					(*pGC->pScreen->
21903b705cfSriastradh					 DestroyPixmap) (pNewTile);
22003b705cfSriastradh				/* fb24_32ReformatTile will do direct access
22103b705cfSriastradh				 * of a newly-allocated pixmap.  This isn't a
22203b705cfSriastradh				 * problem yet, since we don't put pixmaps in
22303b705cfSriastradh				 * FB until at least one accelerated UXA op.
22403b705cfSriastradh				 */
22503b705cfSriastradh				if (uxa_prepare_access
22603b705cfSriastradh				    (&pOldTile->drawable, UXA_ACCESS_RO)) {
22703b705cfSriastradh					pNewTile =
22803b705cfSriastradh					    fb24_32ReformatTile(pOldTile,
22903b705cfSriastradh								pDrawable->
23003b705cfSriastradh								bitsPerPixel);
23103b705cfSriastradh					uxa_finish_access(&pOldTile->drawable, UXA_ACCESS_RO);
23203b705cfSriastradh				}
23303b705cfSriastradh			}
23403b705cfSriastradh			if (pNewTile) {
23503b705cfSriastradh				fbGetRotatedPixmap(pGC) = pOldTile;
23603b705cfSriastradh				pGC->tile.pixmap = pNewTile;
23703b705cfSriastradh				changes |= GCTile;
23803b705cfSriastradh			}
23903b705cfSriastradh		}
24003b705cfSriastradh	}
24103b705cfSriastradh#endif
24203b705cfSriastradh	if (changes & GCTile) {
24303b705cfSriastradh		if (!pGC->tileIsPixel
24403b705cfSriastradh		    && FbEvenTile(pGC->tile.pixmap->drawable.width *
24503b705cfSriastradh				  pDrawable->bitsPerPixel)) {
24603b705cfSriastradh			if (uxa_prepare_access
24703b705cfSriastradh			    (&pGC->tile.pixmap->drawable, UXA_ACCESS_RW)) {
24803b705cfSriastradh				fbPadPixmap(pGC->tile.pixmap);
24903b705cfSriastradh				uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RW);
25003b705cfSriastradh			}
25103b705cfSriastradh		}
25203b705cfSriastradh		/* Mask out the GCTile change notification, now that we've
25303b705cfSriastradh		 * done FB's job for it.
25403b705cfSriastradh		 */
25503b705cfSriastradh		changes &= ~GCTile;
25603b705cfSriastradh	}
25703b705cfSriastradh
25803b705cfSriastradh	if (changes & GCStipple && pGC->stipple) {
25903b705cfSriastradh		/* We can't inline stipple handling like we do for GCTile
26003b705cfSriastradh		 * because it sets fbgc privates.
26103b705cfSriastradh		 */
26203b705cfSriastradh		if (uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RW)) {
26303b705cfSriastradh			fbValidateGC(pGC, changes, pDrawable);
26403b705cfSriastradh			uxa_finish_access(&pGC->stipple->drawable, UXA_ACCESS_RW);
26503b705cfSriastradh		}
26603b705cfSriastradh	} else {
26703b705cfSriastradh		fbValidateGC(pGC, changes, pDrawable);
26803b705cfSriastradh	}
26903b705cfSriastradh
27003b705cfSriastradhset_ops:
27103b705cfSriastradh	pGC->ops = (GCOps *) & uxa_ops;
27203b705cfSriastradh}
27303b705cfSriastradh
27403b705cfSriastradhstatic GCFuncs uxaGCFuncs = {
27503b705cfSriastradh	uxa_validate_gc,
27603b705cfSriastradh	miChangeGC,
27703b705cfSriastradh	miCopyGC,
27803b705cfSriastradh	miDestroyGC,
27903b705cfSriastradh	miChangeClip,
28003b705cfSriastradh	miDestroyClip,
28103b705cfSriastradh	miCopyClip
28203b705cfSriastradh};
28303b705cfSriastradh
28403b705cfSriastradh/**
28503b705cfSriastradh * uxa_create_gc makes a new GC and hooks up its funcs handler, so that
28603b705cfSriastradh * uxa_validate_gc() will get called.
28703b705cfSriastradh */
28803b705cfSriastradhstatic int uxa_create_gc(GCPtr pGC)
28903b705cfSriastradh{
29003b705cfSriastradh	if (!fbCreateGC(pGC))
29103b705cfSriastradh		return FALSE;
29203b705cfSriastradh
29303b705cfSriastradh	pGC->funcs = &uxaGCFuncs;
29403b705cfSriastradh
29503b705cfSriastradh	return TRUE;
29603b705cfSriastradh}
29703b705cfSriastradh
29803b705cfSriastradhBool uxa_prepare_access_window(WindowPtr pWin)
29903b705cfSriastradh{
30003b705cfSriastradh	if (pWin->backgroundState == BackgroundPixmap) {
30103b705cfSriastradh		if (!uxa_prepare_access
30203b705cfSriastradh		    (&pWin->background.pixmap->drawable, UXA_ACCESS_RO))
30303b705cfSriastradh			return FALSE;
30403b705cfSriastradh	}
30503b705cfSriastradh
30603b705cfSriastradh	if (pWin->borderIsPixel == FALSE) {
30703b705cfSriastradh		if (!uxa_prepare_access
30803b705cfSriastradh		    (&pWin->border.pixmap->drawable, UXA_ACCESS_RO)) {
30903b705cfSriastradh			if (pWin->backgroundState == BackgroundPixmap)
31003b705cfSriastradh				uxa_finish_access(&pWin->background.pixmap->
31103b705cfSriastradh						  drawable, UXA_ACCESS_RO);
31203b705cfSriastradh			return FALSE;
31303b705cfSriastradh		}
31403b705cfSriastradh	}
31503b705cfSriastradh	return TRUE;
31603b705cfSriastradh}
31703b705cfSriastradh
31803b705cfSriastradhvoid uxa_finish_access_window(WindowPtr pWin)
31903b705cfSriastradh{
32003b705cfSriastradh	if (pWin->backgroundState == BackgroundPixmap)
32103b705cfSriastradh		uxa_finish_access(&pWin->background.pixmap->drawable, UXA_ACCESS_RO);
32203b705cfSriastradh
32303b705cfSriastradh	if (pWin->borderIsPixel == FALSE)
32403b705cfSriastradh		uxa_finish_access(&pWin->border.pixmap->drawable, UXA_ACCESS_RO);
32503b705cfSriastradh}
32603b705cfSriastradh
32703b705cfSriastradhstatic Bool uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
32803b705cfSriastradh{
32903b705cfSriastradh	Bool ret;
33003b705cfSriastradh
33103b705cfSriastradh	if (!uxa_prepare_access_window(pWin))
33203b705cfSriastradh		return FALSE;
33303b705cfSriastradh	ret = fbChangeWindowAttributes(pWin, mask);
33403b705cfSriastradh	uxa_finish_access_window(pWin);
33503b705cfSriastradh	return ret;
33603b705cfSriastradh}
33703b705cfSriastradh
33803b705cfSriastradhstatic RegionPtr uxa_bitmap_to_region(PixmapPtr pPix)
33903b705cfSriastradh{
34003b705cfSriastradh	RegionPtr ret;
34103b705cfSriastradh	if (!uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO))
34203b705cfSriastradh		return NULL;
34303b705cfSriastradh	ret = fbPixmapToRegion(pPix);
34403b705cfSriastradh	uxa_finish_access(&pPix->drawable, UXA_ACCESS_RO);
34503b705cfSriastradh	return ret;
34603b705cfSriastradh}
34703b705cfSriastradh
34803b705cfSriastradhvoid uxa_set_fallback_debug(ScreenPtr screen, Bool enable)
34903b705cfSriastradh{
35003b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
35103b705cfSriastradh
35203b705cfSriastradh	uxa_screen->fallback_debug = enable;
35303b705cfSriastradh}
35403b705cfSriastradh
35503b705cfSriastradhvoid uxa_set_force_fallback(ScreenPtr screen, Bool value)
35603b705cfSriastradh{
35703b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
35803b705cfSriastradh
35903b705cfSriastradh	uxa_screen->force_fallback = value;
36003b705cfSriastradh}
36103b705cfSriastradh
36203b705cfSriastradh/**
36303b705cfSriastradh * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
36403b705cfSriastradh * screen private, before calling down to the next CloseSccreen.
36503b705cfSriastradh */
36603b705cfSriastradhstatic Bool uxa_close_screen(CLOSE_SCREEN_ARGS_DECL)
36703b705cfSriastradh{
36803b705cfSriastradh	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
36903b705cfSriastradh#ifdef RENDER
37003b705cfSriastradh	PictureScreenPtr ps = GetPictureScreenIfSet(screen);
37103b705cfSriastradh#endif
37203b705cfSriastradh	int n;
37303b705cfSriastradh
37403b705cfSriastradh	if (uxa_screen->solid_clear)
37503b705cfSriastradh		FreePicture(uxa_screen->solid_clear, 0);
37603b705cfSriastradh	if (uxa_screen->solid_black)
37703b705cfSriastradh		FreePicture(uxa_screen->solid_black, 0);
37803b705cfSriastradh	if (uxa_screen->solid_white)
37903b705cfSriastradh		FreePicture(uxa_screen->solid_white, 0);
38003b705cfSriastradh	for (n = 0; n < uxa_screen->solid_cache_size; n++)
38103b705cfSriastradh		FreePicture(uxa_screen->solid_cache[n].picture, 0);
38203b705cfSriastradh
38303b705cfSriastradh	uxa_glyphs_fini(screen);
38403b705cfSriastradh
38503b705cfSriastradh	if (screen->devPrivate) {
38603b705cfSriastradh		/* Destroy the pixmap created by miScreenInit() *before*
38703b705cfSriastradh		 * chaining up as we finalize ourselves here and so this
38803b705cfSriastradh		 * is the last chance we have of releasing our resources
38903b705cfSriastradh		 * associated with the Pixmap. So do it first.
39003b705cfSriastradh		 */
39103b705cfSriastradh		(void) (*screen->DestroyPixmap) (screen->devPrivate);
39203b705cfSriastradh		screen->devPrivate = NULL;
39303b705cfSriastradh	}
39403b705cfSriastradh
39503b705cfSriastradh	screen->CreateGC = uxa_screen->SavedCreateGC;
39603b705cfSriastradh	screen->CloseScreen = uxa_screen->SavedCloseScreen;
39703b705cfSriastradh	screen->GetImage = uxa_screen->SavedGetImage;
39803b705cfSriastradh	screen->GetSpans = uxa_screen->SavedGetSpans;
39903b705cfSriastradh	screen->CreatePixmap = uxa_screen->SavedCreatePixmap;
40003b705cfSriastradh	screen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
40103b705cfSriastradh	screen->CopyWindow = uxa_screen->SavedCopyWindow;
40203b705cfSriastradh	screen->ChangeWindowAttributes =
40303b705cfSriastradh	    uxa_screen->SavedChangeWindowAttributes;
40403b705cfSriastradh	screen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
40503b705cfSriastradh#ifdef RENDER
40603b705cfSriastradh	if (ps) {
40703b705cfSriastradh		ps->Composite = uxa_screen->SavedComposite;
40803b705cfSriastradh		ps->Glyphs = uxa_screen->SavedGlyphs;
40903b705cfSriastradh		ps->Trapezoids = uxa_screen->SavedTrapezoids;
41003b705cfSriastradh		ps->AddTraps = uxa_screen->SavedAddTraps;
41103b705cfSriastradh		ps->Triangles = uxa_screen->SavedTriangles;
41203b705cfSriastradh
41303b705cfSriastradh		ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
41403b705cfSriastradh	}
41503b705cfSriastradh#endif
41603b705cfSriastradh
41703b705cfSriastradh	free(uxa_screen);
41803b705cfSriastradh
41903b705cfSriastradh	return (*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
42003b705cfSriastradh}
42103b705cfSriastradh
42203b705cfSriastradh/**
42303b705cfSriastradh * This function allocates a driver structure for UXA drivers to fill in.  By
42403b705cfSriastradh * having UXA allocate the structure, the driver structure can be extended
42503b705cfSriastradh * without breaking ABI between UXA and the drivers.  The driver's
42603b705cfSriastradh * responsibility is to check beforehand that the UXA module has a matching
42703b705cfSriastradh * major number and sufficient minor.  Drivers are responsible for freeing the
42803b705cfSriastradh * driver structure using free().
42903b705cfSriastradh *
43003b705cfSriastradh * @return a newly allocated, zero-filled driver structure
43103b705cfSriastradh */
43203b705cfSriastradhuxa_driver_t *uxa_driver_alloc(void)
43303b705cfSriastradh{
43403b705cfSriastradh	return calloc(1, sizeof(uxa_driver_t));
43503b705cfSriastradh}
43603b705cfSriastradh
43703b705cfSriastradh/**
43803b705cfSriastradh * @param screen screen being initialized
43903b705cfSriastradh * @param pScreenInfo UXA driver record
44003b705cfSriastradh *
44103b705cfSriastradh * uxa_driver_init sets up UXA given a driver record filled in by the driver.
44203b705cfSriastradh * pScreenInfo should have been allocated by uxa_driver_alloc().  See the
44303b705cfSriastradh * comments in _UxaDriver for what must be filled in and what is optional.
44403b705cfSriastradh *
44503b705cfSriastradh * @return TRUE if UXA was successfully initialized.
44603b705cfSriastradh */
44703b705cfSriastradhBool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
44803b705cfSriastradh{
44903b705cfSriastradh	uxa_screen_t *uxa_screen;
45003b705cfSriastradh
45103b705cfSriastradh	if (!uxa_driver)
45203b705cfSriastradh		return FALSE;
45303b705cfSriastradh
45403b705cfSriastradh	if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
45503b705cfSriastradh	    uxa_driver->uxa_minor > UXA_VERSION_MINOR) {
45603b705cfSriastradh		LogMessage(X_ERROR,
45703b705cfSriastradh			   "UXA(%d): driver's UXA version requirements "
45803b705cfSriastradh			   "(%d.%d) are incompatible with UXA version (%d.%d)\n",
45903b705cfSriastradh			   screen->myNum, uxa_driver->uxa_major,
46003b705cfSriastradh			   uxa_driver->uxa_minor, UXA_VERSION_MAJOR,
46103b705cfSriastradh			   UXA_VERSION_MINOR);
46203b705cfSriastradh		return FALSE;
46303b705cfSriastradh	}
46403b705cfSriastradh
46503b705cfSriastradh	if (!uxa_driver->prepare_solid) {
46603b705cfSriastradh		LogMessage(X_ERROR,
46703b705cfSriastradh			   "UXA(%d): uxa_driver_t::prepare_solid must be "
46803b705cfSriastradh			   "non-NULL\n", screen->myNum);
46903b705cfSriastradh		return FALSE;
47003b705cfSriastradh	}
47103b705cfSriastradh
47203b705cfSriastradh	if (!uxa_driver->prepare_copy) {
47303b705cfSriastradh		LogMessage(X_ERROR,
47403b705cfSriastradh			   "UXA(%d): uxa_driver_t::prepare_copy must be "
47503b705cfSriastradh			   "non-NULL\n", screen->myNum);
47603b705cfSriastradh		return FALSE;
47703b705cfSriastradh	}
47803b705cfSriastradh#if HAS_DIXREGISTERPRIVATEKEY
47903b705cfSriastradh	if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
48003b705cfSriastradh	    return FALSE;
48103b705cfSriastradh#endif
48203b705cfSriastradh	uxa_screen = calloc(sizeof(uxa_screen_t), 1);
48303b705cfSriastradh
48403b705cfSriastradh	if (!uxa_screen) {
48503b705cfSriastradh		LogMessage(X_WARNING,
48603b705cfSriastradh			   "UXA(%d): Failed to allocate screen private\n",
48703b705cfSriastradh			   screen->myNum);
48803b705cfSriastradh		return FALSE;
48903b705cfSriastradh	}
49003b705cfSriastradh
49103b705cfSriastradh	uxa_screen->info = uxa_driver;
49203b705cfSriastradh
49303b705cfSriastradh	dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen);
49403b705cfSriastradh
49503b705cfSriastradh	uxa_screen->force_fallback = FALSE;
49603b705cfSriastradh
49703b705cfSriastradh	uxa_screen->solid_cache_size = 0;
49803b705cfSriastradh	uxa_screen->solid_clear = 0;
49903b705cfSriastradh	uxa_screen->solid_black = 0;
50003b705cfSriastradh	uxa_screen->solid_white = 0;
50103b705cfSriastradh
50203b705cfSriastradh//    exaDDXDriverInit(screen);
50303b705cfSriastradh
50403b705cfSriastradh	/*
50503b705cfSriastradh	 * Replace various fb screen functions
50603b705cfSriastradh	 */
50703b705cfSriastradh	uxa_screen->SavedCloseScreen = screen->CloseScreen;
50803b705cfSriastradh	screen->CloseScreen = uxa_close_screen;
50903b705cfSriastradh
51003b705cfSriastradh	uxa_screen->SavedCreateGC = screen->CreateGC;
51103b705cfSriastradh	screen->CreateGC = uxa_create_gc;
51203b705cfSriastradh
51303b705cfSriastradh	uxa_screen->SavedGetImage = screen->GetImage;
51403b705cfSriastradh	screen->GetImage = uxa_get_image;
51503b705cfSriastradh
51603b705cfSriastradh	uxa_screen->SavedGetSpans = screen->GetSpans;
51703b705cfSriastradh	screen->GetSpans = uxa_get_spans;
51803b705cfSriastradh
51903b705cfSriastradh	uxa_screen->SavedCopyWindow = screen->CopyWindow;
52003b705cfSriastradh	screen->CopyWindow = uxa_copy_window;
52103b705cfSriastradh
52203b705cfSriastradh	uxa_screen->SavedChangeWindowAttributes =
52303b705cfSriastradh	    screen->ChangeWindowAttributes;
52403b705cfSriastradh	screen->ChangeWindowAttributes = uxa_change_window_attributes;
52503b705cfSriastradh
52603b705cfSriastradh	uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
52703b705cfSriastradh	screen->BitmapToRegion = uxa_bitmap_to_region;
52803b705cfSriastradh
52903b705cfSriastradh#ifdef RENDER
53003b705cfSriastradh	{
53103b705cfSriastradh		PictureScreenPtr ps = GetPictureScreenIfSet(screen);
53203b705cfSriastradh		if (ps) {
53303b705cfSriastradh			uxa_screen->SavedComposite = ps->Composite;
53403b705cfSriastradh			ps->Composite = uxa_composite;
53503b705cfSriastradh
53603b705cfSriastradh			uxa_screen->SavedGlyphs = ps->Glyphs;
53703b705cfSriastradh			ps->Glyphs = uxa_glyphs;
53803b705cfSriastradh
53903b705cfSriastradh			uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph;
54003b705cfSriastradh			ps->UnrealizeGlyph = uxa_glyph_unrealize;
54103b705cfSriastradh
54203b705cfSriastradh			uxa_screen->SavedTriangles = ps->Triangles;
54303b705cfSriastradh			ps->Triangles = uxa_triangles;
54403b705cfSriastradh
54503b705cfSriastradh			uxa_screen->SavedTrapezoids = ps->Trapezoids;
54603b705cfSriastradh			ps->Trapezoids = uxa_trapezoids;
54703b705cfSriastradh
54803b705cfSriastradh			uxa_screen->SavedAddTraps = ps->AddTraps;
54903b705cfSriastradh			ps->AddTraps = uxa_add_traps;
55003b705cfSriastradh		}
55103b705cfSriastradh	}
55203b705cfSriastradh#endif
55303b705cfSriastradh
55403b705cfSriastradh	LogMessage(X_INFO,
55503b705cfSriastradh		   "UXA(%d): Driver registered support for the following"
55603b705cfSriastradh		   " operations:\n", screen->myNum);
55703b705cfSriastradh	assert(uxa_driver->prepare_solid != NULL);
55803b705cfSriastradh	LogMessage(X_INFO, "        solid\n");
55903b705cfSriastradh	assert(uxa_driver->prepare_copy != NULL);
56003b705cfSriastradh	LogMessage(X_INFO, "        copy\n");
56103b705cfSriastradh	if (uxa_driver->prepare_composite != NULL) {
56203b705cfSriastradh		LogMessage(X_INFO, "        composite (RENDER acceleration)\n");
56303b705cfSriastradh	}
56403b705cfSriastradh	if (uxa_driver->put_image != NULL) {
56503b705cfSriastradh		LogMessage(X_INFO, "        put_image\n");
56603b705cfSriastradh	}
56703b705cfSriastradh	if (uxa_driver->get_image != NULL) {
56803b705cfSriastradh		LogMessage(X_INFO, "        get_image\n");
56903b705cfSriastradh	}
57003b705cfSriastradh
57103b705cfSriastradh	return TRUE;
57203b705cfSriastradh}
57303b705cfSriastradh
57403b705cfSriastradhBool uxa_resources_init(ScreenPtr screen)
57503b705cfSriastradh{
57603b705cfSriastradh	if (!uxa_glyphs_init(screen))
57703b705cfSriastradh		return FALSE;
57803b705cfSriastradh
57903b705cfSriastradh	return TRUE;
58003b705cfSriastradh}
58103b705cfSriastradh
58203b705cfSriastradh/**
58303b705cfSriastradh * uxa_driver_fini tears down UXA on a given screen.
58403b705cfSriastradh *
58503b705cfSriastradh * @param pScreen screen being torn down.
58603b705cfSriastradh */
58703b705cfSriastradhvoid uxa_driver_fini(ScreenPtr pScreen)
58803b705cfSriastradh{
58903b705cfSriastradh	/*right now does nothing */
59003b705cfSriastradh}
591