1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 2001 Keith Packard
3428d7b3dSmrg *
4428d7b3dSmrg * Partly based on code that is Copyright © The XFree86 Project Inc.
5428d7b3dSmrg *
6428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
7428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that
8428d7b3dSmrg * the above copyright notice appear in all copies and that both that
9428d7b3dSmrg * copyright notice and this permission notice appear in supporting
10428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in
11428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without
12428d7b3dSmrg * specific, written prior permission.  Keith Packard makes no
13428d7b3dSmrg * representations about the suitability of this software for any purpose.  It
14428d7b3dSmrg * is provided "as is" without express or implied warranty.
15428d7b3dSmrg *
16428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE.
23428d7b3dSmrg */
24428d7b3dSmrg
25428d7b3dSmrg/** @file
26428d7b3dSmrg * This file covers the initialization and teardown of UXA, and has various
27428d7b3dSmrg * functions not responsible for performing rendering, pixmap migration, or
28428d7b3dSmrg * memory management.
29428d7b3dSmrg */
30428d7b3dSmrg
31428d7b3dSmrg#ifdef HAVE_DIX_CONFIG_H
32428d7b3dSmrg#include <dix-config.h>
33428d7b3dSmrg#endif
34428d7b3dSmrg
35428d7b3dSmrg#include <stdlib.h>
36428d7b3dSmrg
37428d7b3dSmrg#include "uxa-priv.h"
38428d7b3dSmrg#include <X11/fonts/fontstruct.h>
39428d7b3dSmrg#include "dixfontstr.h"
40428d7b3dSmrg#include "uxa.h"
41428d7b3dSmrg
42428d7b3dSmrg#if HAS_DEVPRIVATEKEYREC
43428d7b3dSmrgDevPrivateKeyRec uxa_screen_index;
44428d7b3dSmrg#else
45428d7b3dSmrgint uxa_screen_index;
46428d7b3dSmrg#endif
47428d7b3dSmrg
48428d7b3dSmrg/**
49428d7b3dSmrg * uxa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
50428d7b3dSmrg *
51428d7b3dSmrg * @param pDrawable the drawable being requested.
52428d7b3dSmrg *
53428d7b3dSmrg * This function returns the backing pixmap for a drawable, whether it is a
54428d7b3dSmrg * redirected window, unredirected window, or already a pixmap.  Note that
55428d7b3dSmrg * coordinate translation is needed when drawing to the backing pixmap of a
56428d7b3dSmrg * redirected window, and the translation coordinates are provided by calling
57428d7b3dSmrg * uxa_get_drawable_pixmap() on the drawable.
58428d7b3dSmrg */
59428d7b3dSmrgPixmapPtr uxa_get_drawable_pixmap(DrawablePtr pDrawable)
60428d7b3dSmrg{
61428d7b3dSmrg	if (pDrawable->type == DRAWABLE_WINDOW)
62428d7b3dSmrg		return pDrawable->pScreen->
63428d7b3dSmrg		    GetWindowPixmap((WindowPtr) pDrawable);
64428d7b3dSmrg	else
65428d7b3dSmrg		return (PixmapPtr) pDrawable;
66428d7b3dSmrg}
67428d7b3dSmrg
68428d7b3dSmrg/**
69428d7b3dSmrg * Sets the offsets to add to coordinates to make them address the same bits in
70428d7b3dSmrg * the backing drawable. These coordinates are nonzero only for redirected
71428d7b3dSmrg * windows.
72428d7b3dSmrg */
73428d7b3dSmrgvoid
74428d7b3dSmrguxa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
75428d7b3dSmrg			int *xp, int *yp)
76428d7b3dSmrg{
77428d7b3dSmrg#ifdef COMPOSITE
78428d7b3dSmrg	if (pDrawable->type == DRAWABLE_WINDOW) {
79428d7b3dSmrg		*xp = -pPixmap->screen_x;
80428d7b3dSmrg		*yp = -pPixmap->screen_y;
81428d7b3dSmrg		return;
82428d7b3dSmrg	}
83428d7b3dSmrg#endif
84428d7b3dSmrg
85428d7b3dSmrg	*xp = 0;
86428d7b3dSmrg	*yp = 0;
87428d7b3dSmrg}
88428d7b3dSmrg
89428d7b3dSmrg/**
90428d7b3dSmrg * uxa_pixmap_is_offscreen() is used to determine if a pixmap is in offscreen
91428d7b3dSmrg * memory, meaning that acceleration could probably be done to it, and that it
92428d7b3dSmrg * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
93428d7b3dSmrg * with the CPU.
94428d7b3dSmrg *
95428d7b3dSmrg * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
96428d7b3dSmrg * deal with moving pixmaps in and out of system memory), UXA will give drivers
97428d7b3dSmrg * pixmaps as arguments for which uxa_pixmap_is_offscreen() is TRUE.
98428d7b3dSmrg *
99428d7b3dSmrg * @return TRUE if the given drawable is in framebuffer memory.
100428d7b3dSmrg */
101428d7b3dSmrgBool uxa_pixmap_is_offscreen(PixmapPtr p)
102428d7b3dSmrg{
103428d7b3dSmrg	ScreenPtr pScreen = p->drawable.pScreen;
104428d7b3dSmrg	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
105428d7b3dSmrg
106428d7b3dSmrg	if (uxa_screen->info->pixmap_is_offscreen)
107428d7b3dSmrg		return uxa_screen->info->pixmap_is_offscreen(p);
108428d7b3dSmrg
109428d7b3dSmrg	return FALSE;
110428d7b3dSmrg}
111428d7b3dSmrg
112428d7b3dSmrg/**
113428d7b3dSmrg * uxa_drawable_is_offscreen() is a convenience wrapper for
114428d7b3dSmrg * uxa_pixmap_is_offscreen().
115428d7b3dSmrg */
116428d7b3dSmrgBool uxa_drawable_is_offscreen(DrawablePtr pDrawable)
117428d7b3dSmrg{
118428d7b3dSmrg	return uxa_pixmap_is_offscreen(uxa_get_drawable_pixmap(pDrawable));
119428d7b3dSmrg}
120428d7b3dSmrg
121428d7b3dSmrg/**
122428d7b3dSmrg  * Returns the pixmap which backs a drawable, and the offsets to add to
123428d7b3dSmrg  * coordinates to make them address the same bits in the backing drawable.
124428d7b3dSmrg  */
125428d7b3dSmrgPixmapPtr uxa_get_offscreen_pixmap(DrawablePtr drawable, int *xp, int *yp)
126428d7b3dSmrg{
127428d7b3dSmrg	PixmapPtr pixmap = uxa_get_drawable_pixmap(drawable);
128428d7b3dSmrg
129428d7b3dSmrg	uxa_get_drawable_deltas(drawable, pixmap, xp, yp);
130428d7b3dSmrg
131428d7b3dSmrg	if (uxa_pixmap_is_offscreen(pixmap))
132428d7b3dSmrg		return pixmap;
133428d7b3dSmrg	else
134428d7b3dSmrg		return NULL;
135428d7b3dSmrg}
136428d7b3dSmrg
137428d7b3dSmrg/**
138428d7b3dSmrg * uxa_prepare_access() is UXA's wrapper for the driver's PrepareAccess() handler.
139428d7b3dSmrg *
140428d7b3dSmrg * It deals with waiting for synchronization with the card, determining if
141428d7b3dSmrg * PrepareAccess() is necessary, and working around PrepareAccess() failure.
142428d7b3dSmrg */
143428d7b3dSmrgBool uxa_prepare_access(DrawablePtr pDrawable, uxa_access_t access)
144428d7b3dSmrg{
145428d7b3dSmrg	ScreenPtr pScreen = pDrawable->pScreen;
146428d7b3dSmrg	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
147428d7b3dSmrg	PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable);
148428d7b3dSmrg	Bool offscreen = uxa_pixmap_is_offscreen(pPixmap);
149428d7b3dSmrg
150428d7b3dSmrg	if (!offscreen)
151428d7b3dSmrg		return TRUE;
152428d7b3dSmrg
153428d7b3dSmrg	if (uxa_screen->info->prepare_access)
154428d7b3dSmrg		return (*uxa_screen->info->prepare_access) (pPixmap, access);
155428d7b3dSmrg	return TRUE;
156428d7b3dSmrg}
157428d7b3dSmrg
158428d7b3dSmrg/**
159428d7b3dSmrg * uxa_finish_access() is UXA's wrapper for the driver's finish_access() handler.
160428d7b3dSmrg *
161428d7b3dSmrg * It deals with calling the driver's finish_access() only if necessary.
162428d7b3dSmrg */
163428d7b3dSmrgvoid uxa_finish_access(DrawablePtr pDrawable, uxa_access_t access)
164428d7b3dSmrg{
165428d7b3dSmrg	ScreenPtr pScreen = pDrawable->pScreen;
166428d7b3dSmrg	uxa_screen_t *uxa_screen = uxa_get_screen(pScreen);
167428d7b3dSmrg	PixmapPtr pPixmap;
168428d7b3dSmrg
169428d7b3dSmrg	if (uxa_screen->info->finish_access == NULL)
170428d7b3dSmrg		return;
171428d7b3dSmrg
172428d7b3dSmrg	pPixmap = uxa_get_drawable_pixmap(pDrawable);
173428d7b3dSmrg	if (!uxa_pixmap_is_offscreen(pPixmap))
174428d7b3dSmrg		return;
175428d7b3dSmrg
176428d7b3dSmrg	(*uxa_screen->info->finish_access) (pPixmap, access);
177428d7b3dSmrg}
178428d7b3dSmrg
179428d7b3dSmrg/**
180428d7b3dSmrg * uxa_validate_gc() sets the ops to UXA's implementations, which may be
181428d7b3dSmrg * accelerated or may sync the card and fall back to fb.
182428d7b3dSmrg */
183428d7b3dSmrgstatic void
184428d7b3dSmrguxa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
185428d7b3dSmrg{
186428d7b3dSmrg	/* fbValidateGC will do direct access to pixmaps if the tiling has
187428d7b3dSmrg	 * changed.
188428d7b3dSmrg	 * Preempt fbValidateGC by doing its work and masking the change out, so
189428d7b3dSmrg	 * that we can do the Prepare/finish_access.
190428d7b3dSmrg	 */
191428d7b3dSmrg
192428d7b3dSmrg#ifdef FB_24_32BIT
193428d7b3dSmrg	if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
194428d7b3dSmrg		(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
195428d7b3dSmrg		fbGetRotatedPixmap(pGC) = 0;
196428d7b3dSmrg	}
197428d7b3dSmrg
198428d7b3dSmrg	if (pGC->fillStyle == FillTiled) {
199428d7b3dSmrg		PixmapPtr pOldTile, pNewTile;
200428d7b3dSmrg
201428d7b3dSmrg		pOldTile = pGC->tile.pixmap;
202428d7b3dSmrg		if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) {
203428d7b3dSmrg			pNewTile = fbGetRotatedPixmap(pGC);
204428d7b3dSmrg			if (!pNewTile ||
205428d7b3dSmrg			    pNewTile->drawable.bitsPerPixel !=
206428d7b3dSmrg			    pDrawable->bitsPerPixel) {
207428d7b3dSmrg				if (pNewTile)
208428d7b3dSmrg					(*pGC->pScreen->
209428d7b3dSmrg					 DestroyPixmap) (pNewTile);
210428d7b3dSmrg				/* fb24_32ReformatTile will do direct access
211428d7b3dSmrg				 * of a newly-allocated pixmap.  This isn't a
212428d7b3dSmrg				 * problem yet, since we don't put pixmaps in
213428d7b3dSmrg				 * FB until at least one accelerated UXA op.
214428d7b3dSmrg				 */
215428d7b3dSmrg				if (uxa_prepare_access
216428d7b3dSmrg				    (&pOldTile->drawable, UXA_ACCESS_RO)) {
217428d7b3dSmrg					pNewTile =
218428d7b3dSmrg					    fb24_32ReformatTile(pOldTile,
219428d7b3dSmrg								pDrawable->
220428d7b3dSmrg								bitsPerPixel);
221428d7b3dSmrg					uxa_finish_access(&pOldTile->drawable, UXA_ACCESS_RO);
222428d7b3dSmrg				}
223428d7b3dSmrg			}
224428d7b3dSmrg			if (pNewTile) {
225428d7b3dSmrg				fbGetRotatedPixmap(pGC) = pOldTile;
226428d7b3dSmrg				pGC->tile.pixmap = pNewTile;
227428d7b3dSmrg				changes |= GCTile;
228428d7b3dSmrg			}
229428d7b3dSmrg		}
230428d7b3dSmrg	}
231428d7b3dSmrg#endif
232428d7b3dSmrg	if (changes & GCTile) {
233428d7b3dSmrg		if (!pGC->tileIsPixel
234428d7b3dSmrg		    && FbEvenTile(pGC->tile.pixmap->drawable.width *
235428d7b3dSmrg				  pDrawable->bitsPerPixel)) {
236428d7b3dSmrg			if (uxa_prepare_access
237428d7b3dSmrg			    (&pGC->tile.pixmap->drawable, UXA_ACCESS_RW)) {
238428d7b3dSmrg				fbPadPixmap(pGC->tile.pixmap);
239428d7b3dSmrg				uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RW);
240428d7b3dSmrg			}
241428d7b3dSmrg		}
242428d7b3dSmrg		/* Mask out the GCTile change notification, now that we've
243428d7b3dSmrg		 * done FB's job for it.
244428d7b3dSmrg		 */
245428d7b3dSmrg		changes &= ~GCTile;
246428d7b3dSmrg	}
247428d7b3dSmrg
248428d7b3dSmrg	if (changes & GCStipple && pGC->stipple) {
249428d7b3dSmrg		/* We can't inline stipple handling like we do for GCTile
250428d7b3dSmrg		 * because it sets fbgc privates.
251428d7b3dSmrg		 */
252428d7b3dSmrg		if (uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RW)) {
253428d7b3dSmrg			fbValidateGC(pGC, changes, pDrawable);
254428d7b3dSmrg			uxa_finish_access(&pGC->stipple->drawable, UXA_ACCESS_RW);
255428d7b3dSmrg		}
256428d7b3dSmrg	} else {
257428d7b3dSmrg		fbValidateGC(pGC, changes, pDrawable);
258428d7b3dSmrg	}
259428d7b3dSmrg
260428d7b3dSmrg	pGC->ops = (GCOps *) & uxa_ops;
261428d7b3dSmrg}
262428d7b3dSmrg
263428d7b3dSmrgstatic GCFuncs uxaGCFuncs = {
264428d7b3dSmrg	uxa_validate_gc,
265428d7b3dSmrg	miChangeGC,
266428d7b3dSmrg	miCopyGC,
267428d7b3dSmrg	miDestroyGC,
268428d7b3dSmrg	miChangeClip,
269428d7b3dSmrg	miDestroyClip,
270428d7b3dSmrg	miCopyClip
271428d7b3dSmrg};
272428d7b3dSmrg
273428d7b3dSmrg/**
274428d7b3dSmrg * uxa_create_gc makes a new GC and hooks up its funcs handler, so that
275428d7b3dSmrg * uxa_validate_gc() will get called.
276428d7b3dSmrg */
277428d7b3dSmrgstatic int uxa_create_gc(GCPtr pGC)
278428d7b3dSmrg{
279428d7b3dSmrg	if (!fbCreateGC(pGC))
280428d7b3dSmrg		return FALSE;
281428d7b3dSmrg
282428d7b3dSmrg	pGC->funcs = &uxaGCFuncs;
283428d7b3dSmrg
284428d7b3dSmrg	return TRUE;
285428d7b3dSmrg}
286428d7b3dSmrg
287428d7b3dSmrgBool uxa_prepare_access_window(WindowPtr pWin)
288428d7b3dSmrg{
289428d7b3dSmrg	if (pWin->backgroundState == BackgroundPixmap) {
290428d7b3dSmrg		if (!uxa_prepare_access
291428d7b3dSmrg		    (&pWin->background.pixmap->drawable, UXA_ACCESS_RO))
292428d7b3dSmrg			return FALSE;
293428d7b3dSmrg	}
294428d7b3dSmrg
295428d7b3dSmrg	if (pWin->borderIsPixel == FALSE) {
296428d7b3dSmrg		if (!uxa_prepare_access
297428d7b3dSmrg		    (&pWin->border.pixmap->drawable, UXA_ACCESS_RO)) {
298428d7b3dSmrg			if (pWin->backgroundState == BackgroundPixmap)
299428d7b3dSmrg				uxa_finish_access(&pWin->background.pixmap->
300428d7b3dSmrg						  drawable, UXA_ACCESS_RO);
301428d7b3dSmrg			return FALSE;
302428d7b3dSmrg		}
303428d7b3dSmrg	}
304428d7b3dSmrg	return TRUE;
305428d7b3dSmrg}
306428d7b3dSmrg
307428d7b3dSmrgvoid uxa_finish_access_window(WindowPtr pWin)
308428d7b3dSmrg{
309428d7b3dSmrg	if (pWin->backgroundState == BackgroundPixmap)
310428d7b3dSmrg		uxa_finish_access(&pWin->background.pixmap->drawable, UXA_ACCESS_RO);
311428d7b3dSmrg
312428d7b3dSmrg	if (pWin->borderIsPixel == FALSE)
313428d7b3dSmrg		uxa_finish_access(&pWin->border.pixmap->drawable, UXA_ACCESS_RO);
314428d7b3dSmrg}
315428d7b3dSmrg
316428d7b3dSmrgstatic Bool uxa_change_window_attributes(WindowPtr pWin, unsigned long mask)
317428d7b3dSmrg{
318428d7b3dSmrg	Bool ret;
319428d7b3dSmrg
320428d7b3dSmrg	if (!uxa_prepare_access_window(pWin))
321428d7b3dSmrg		return FALSE;
322428d7b3dSmrg	ret = fbChangeWindowAttributes(pWin, mask);
323428d7b3dSmrg	uxa_finish_access_window(pWin);
324428d7b3dSmrg	return ret;
325428d7b3dSmrg}
326428d7b3dSmrg
327428d7b3dSmrgstatic RegionPtr uxa_bitmap_to_region(PixmapPtr pPix)
328428d7b3dSmrg{
329428d7b3dSmrg	RegionPtr ret;
330428d7b3dSmrg	if (!uxa_prepare_access(&pPix->drawable, UXA_ACCESS_RO))
331428d7b3dSmrg		return NULL;
332428d7b3dSmrg	ret = fbPixmapToRegion(pPix);
333428d7b3dSmrg	uxa_finish_access(&pPix->drawable, UXA_ACCESS_RO);
334428d7b3dSmrg	return ret;
335428d7b3dSmrg}
336428d7b3dSmrg
337428d7b3dSmrgvoid uxa_set_fallback_debug(ScreenPtr screen, Bool enable)
338428d7b3dSmrg{
339428d7b3dSmrg	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
340428d7b3dSmrg
341428d7b3dSmrg	uxa_screen->fallback_debug = enable;
342428d7b3dSmrg}
343428d7b3dSmrg
344428d7b3dSmrgvoid uxa_set_force_fallback(ScreenPtr screen, Bool value)
345428d7b3dSmrg{
346428d7b3dSmrg	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
347428d7b3dSmrg
348428d7b3dSmrg	uxa_screen->force_fallback = value;
349428d7b3dSmrg}
350428d7b3dSmrg
351428d7b3dSmrg/**
352428d7b3dSmrg * uxa_close_screen() unwraps its wrapped screen functions and tears down UXA's
353428d7b3dSmrg * screen private, before calling down to the next CloseSccreen.
354428d7b3dSmrg */
355428d7b3dSmrgstatic Bool uxa_close_screen(CLOSE_SCREEN_ARGS_DECL)
356428d7b3dSmrg{
357428d7b3dSmrg	uxa_screen_t *uxa_screen = uxa_get_screen(screen);
358428d7b3dSmrg#ifdef RENDER
359428d7b3dSmrg	PictureScreenPtr ps = GetPictureScreenIfSet(screen);
360428d7b3dSmrg#endif
361428d7b3dSmrg	int n;
362428d7b3dSmrg
363428d7b3dSmrg	if (uxa_screen->solid_clear)
364428d7b3dSmrg		FreePicture(uxa_screen->solid_clear, 0);
365428d7b3dSmrg	if (uxa_screen->solid_black)
366428d7b3dSmrg		FreePicture(uxa_screen->solid_black, 0);
367428d7b3dSmrg	if (uxa_screen->solid_white)
368428d7b3dSmrg		FreePicture(uxa_screen->solid_white, 0);
369428d7b3dSmrg	for (n = 0; n < uxa_screen->solid_cache_size; n++)
370428d7b3dSmrg		FreePicture(uxa_screen->solid_cache[n].picture, 0);
371428d7b3dSmrg
372428d7b3dSmrg	uxa_glyphs_fini(screen);
373428d7b3dSmrg
374428d7b3dSmrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,15,99,903,0)
375428d7b3dSmrg	if (screen->devPrivate) {
376428d7b3dSmrg		/* Destroy the pixmap created by miScreenInit() *before*
377428d7b3dSmrg		 * chaining up as we finalize ourselves here and so this
378428d7b3dSmrg		 * is the last chance we have of releasing our resources
379428d7b3dSmrg		 * associated with the Pixmap. So do it first.
380428d7b3dSmrg		 */
381428d7b3dSmrg		(void) (*screen->DestroyPixmap) (screen->devPrivate);
382428d7b3dSmrg		screen->devPrivate = NULL;
383428d7b3dSmrg	}
384428d7b3dSmrg#endif
385428d7b3dSmrg
386428d7b3dSmrg	screen->CreateGC = uxa_screen->SavedCreateGC;
387428d7b3dSmrg	screen->CloseScreen = uxa_screen->SavedCloseScreen;
388428d7b3dSmrg	screen->GetImage = uxa_screen->SavedGetImage;
389428d7b3dSmrg	screen->GetSpans = uxa_screen->SavedGetSpans;
390428d7b3dSmrg	screen->CreatePixmap = uxa_screen->SavedCreatePixmap;
391428d7b3dSmrg	screen->DestroyPixmap = uxa_screen->SavedDestroyPixmap;
392428d7b3dSmrg	screen->CopyWindow = uxa_screen->SavedCopyWindow;
393428d7b3dSmrg	screen->ChangeWindowAttributes =
394428d7b3dSmrg	    uxa_screen->SavedChangeWindowAttributes;
395428d7b3dSmrg	screen->BitmapToRegion = uxa_screen->SavedBitmapToRegion;
396428d7b3dSmrg#ifdef RENDER
397428d7b3dSmrg	if (ps) {
398428d7b3dSmrg		ps->Composite = uxa_screen->SavedComposite;
399428d7b3dSmrg		ps->Glyphs = uxa_screen->SavedGlyphs;
400428d7b3dSmrg		ps->Trapezoids = uxa_screen->SavedTrapezoids;
401428d7b3dSmrg		ps->AddTraps = uxa_screen->SavedAddTraps;
402428d7b3dSmrg		ps->Triangles = uxa_screen->SavedTriangles;
403428d7b3dSmrg
404428d7b3dSmrg		ps->UnrealizeGlyph = uxa_screen->SavedUnrealizeGlyph;
405428d7b3dSmrg	}
406428d7b3dSmrg#endif
407428d7b3dSmrg
408428d7b3dSmrg	free(uxa_screen);
409428d7b3dSmrg
410428d7b3dSmrg	return (*screen->CloseScreen) (CLOSE_SCREEN_ARGS);
411428d7b3dSmrg}
412428d7b3dSmrg
413428d7b3dSmrg/**
414428d7b3dSmrg * This function allocates a driver structure for UXA drivers to fill in.  By
415428d7b3dSmrg * having UXA allocate the structure, the driver structure can be extended
416428d7b3dSmrg * without breaking ABI between UXA and the drivers.  The driver's
417428d7b3dSmrg * responsibility is to check beforehand that the UXA module has a matching
418428d7b3dSmrg * major number and sufficient minor.  Drivers are responsible for freeing the
419428d7b3dSmrg * driver structure using free().
420428d7b3dSmrg *
421428d7b3dSmrg * @return a newly allocated, zero-filled driver structure
422428d7b3dSmrg */
423428d7b3dSmrguxa_driver_t *uxa_driver_alloc(void)
424428d7b3dSmrg{
425428d7b3dSmrg	return calloc(1, sizeof(uxa_driver_t));
426428d7b3dSmrg}
427428d7b3dSmrg
428428d7b3dSmrg/**
429428d7b3dSmrg * @param screen screen being initialized
430428d7b3dSmrg * @param pScreenInfo UXA driver record
431428d7b3dSmrg *
432428d7b3dSmrg * uxa_driver_init sets up UXA given a driver record filled in by the driver.
433428d7b3dSmrg * pScreenInfo should have been allocated by uxa_driver_alloc().  See the
434428d7b3dSmrg * comments in _UxaDriver for what must be filled in and what is optional.
435428d7b3dSmrg *
436428d7b3dSmrg * @return TRUE if UXA was successfully initialized.
437428d7b3dSmrg */
438428d7b3dSmrgBool uxa_driver_init(ScreenPtr screen, uxa_driver_t * uxa_driver)
439428d7b3dSmrg{
440428d7b3dSmrg	uxa_screen_t *uxa_screen;
441428d7b3dSmrg
442428d7b3dSmrg	if (!uxa_driver)
443428d7b3dSmrg		return FALSE;
444428d7b3dSmrg
445428d7b3dSmrg	if (uxa_driver->uxa_major != UXA_VERSION_MAJOR ||
446428d7b3dSmrg	    uxa_driver->uxa_minor > UXA_VERSION_MINOR) {
447428d7b3dSmrg		LogMessage(X_ERROR,
448428d7b3dSmrg			   "UXA(%d): driver's UXA version requirements "
449428d7b3dSmrg			   "(%d.%d) are incompatible with UXA version (%d.%d)\n",
450428d7b3dSmrg			   screen->myNum, uxa_driver->uxa_major,
451428d7b3dSmrg			   uxa_driver->uxa_minor, UXA_VERSION_MAJOR,
452428d7b3dSmrg			   UXA_VERSION_MINOR);
453428d7b3dSmrg		return FALSE;
454428d7b3dSmrg	}
455428d7b3dSmrg
456428d7b3dSmrg	if (!uxa_driver->prepare_solid) {
457428d7b3dSmrg		LogMessage(X_ERROR,
458428d7b3dSmrg			   "UXA(%d): uxa_driver_t::prepare_solid must be "
459428d7b3dSmrg			   "non-NULL\n", screen->myNum);
460428d7b3dSmrg		return FALSE;
461428d7b3dSmrg	}
462428d7b3dSmrg
463428d7b3dSmrg	if (!uxa_driver->prepare_copy) {
464428d7b3dSmrg		LogMessage(X_ERROR,
465428d7b3dSmrg			   "UXA(%d): uxa_driver_t::prepare_copy must be "
466428d7b3dSmrg			   "non-NULL\n", screen->myNum);
467428d7b3dSmrg		return FALSE;
468428d7b3dSmrg	}
469428d7b3dSmrg#if HAS_DIXREGISTERPRIVATEKEY
470428d7b3dSmrg	if (!dixRegisterPrivateKey(&uxa_screen_index, PRIVATE_SCREEN, 0))
471428d7b3dSmrg	    return FALSE;
472428d7b3dSmrg#endif
473428d7b3dSmrg	uxa_screen = calloc(sizeof(uxa_screen_t), 1);
474428d7b3dSmrg
475428d7b3dSmrg	if (!uxa_screen) {
476428d7b3dSmrg		LogMessage(X_WARNING,
477428d7b3dSmrg			   "UXA(%d): Failed to allocate screen private\n",
478428d7b3dSmrg			   screen->myNum);
479428d7b3dSmrg		return FALSE;
480428d7b3dSmrg	}
481428d7b3dSmrg
482428d7b3dSmrg	uxa_screen->info = uxa_driver;
483428d7b3dSmrg
484428d7b3dSmrg	dixSetPrivate(&screen->devPrivates, &uxa_screen_index, uxa_screen);
485428d7b3dSmrg
486428d7b3dSmrg	uxa_screen->force_fallback = FALSE;
487428d7b3dSmrg
488428d7b3dSmrg	uxa_screen->solid_cache_size = 0;
489428d7b3dSmrg	uxa_screen->solid_clear = 0;
490428d7b3dSmrg	uxa_screen->solid_black = 0;
491428d7b3dSmrg	uxa_screen->solid_white = 0;
492428d7b3dSmrg
493428d7b3dSmrg//    exaDDXDriverInit(screen);
494428d7b3dSmrg
495428d7b3dSmrg	/*
496428d7b3dSmrg	 * Replace various fb screen functions
497428d7b3dSmrg	 */
498428d7b3dSmrg	uxa_screen->SavedCloseScreen = screen->CloseScreen;
499428d7b3dSmrg	screen->CloseScreen = uxa_close_screen;
500428d7b3dSmrg
501428d7b3dSmrg	uxa_screen->SavedCreateGC = screen->CreateGC;
502428d7b3dSmrg	screen->CreateGC = uxa_create_gc;
503428d7b3dSmrg
504428d7b3dSmrg	uxa_screen->SavedGetImage = screen->GetImage;
505428d7b3dSmrg	screen->GetImage = uxa_get_image;
506428d7b3dSmrg
507428d7b3dSmrg	uxa_screen->SavedGetSpans = screen->GetSpans;
508428d7b3dSmrg	screen->GetSpans = uxa_get_spans;
509428d7b3dSmrg
510428d7b3dSmrg	uxa_screen->SavedCopyWindow = screen->CopyWindow;
511428d7b3dSmrg	screen->CopyWindow = uxa_copy_window;
512428d7b3dSmrg
513428d7b3dSmrg	uxa_screen->SavedChangeWindowAttributes =
514428d7b3dSmrg	    screen->ChangeWindowAttributes;
515428d7b3dSmrg	screen->ChangeWindowAttributes = uxa_change_window_attributes;
516428d7b3dSmrg
517428d7b3dSmrg	uxa_screen->SavedBitmapToRegion = screen->BitmapToRegion;
518428d7b3dSmrg	screen->BitmapToRegion = uxa_bitmap_to_region;
519428d7b3dSmrg
520428d7b3dSmrg#ifdef RENDER
521428d7b3dSmrg	{
522428d7b3dSmrg		PictureScreenPtr ps = GetPictureScreenIfSet(screen);
523428d7b3dSmrg		if (ps) {
524428d7b3dSmrg			uxa_screen->SavedComposite = ps->Composite;
525428d7b3dSmrg			ps->Composite = uxa_composite;
526428d7b3dSmrg
527428d7b3dSmrg			uxa_screen->SavedGlyphs = ps->Glyphs;
528428d7b3dSmrg			ps->Glyphs = uxa_glyphs;
529428d7b3dSmrg
530428d7b3dSmrg			uxa_screen->SavedUnrealizeGlyph = ps->UnrealizeGlyph;
531428d7b3dSmrg			ps->UnrealizeGlyph = uxa_glyph_unrealize;
532428d7b3dSmrg
533428d7b3dSmrg			uxa_screen->SavedTriangles = ps->Triangles;
534428d7b3dSmrg			ps->Triangles = uxa_triangles;
535428d7b3dSmrg
536428d7b3dSmrg			uxa_screen->SavedTrapezoids = ps->Trapezoids;
537428d7b3dSmrg			ps->Trapezoids = uxa_trapezoids;
538428d7b3dSmrg
539428d7b3dSmrg			uxa_screen->SavedAddTraps = ps->AddTraps;
540428d7b3dSmrg			ps->AddTraps = uxa_add_traps;
541428d7b3dSmrg		}
542428d7b3dSmrg	}
543428d7b3dSmrg#endif
544428d7b3dSmrg
545428d7b3dSmrg	LogMessage(X_INFO,
546428d7b3dSmrg		   "UXA(%d): Driver registered support for the following"
547428d7b3dSmrg		   " operations:\n", screen->myNum);
548428d7b3dSmrg	assert(uxa_driver->prepare_solid != NULL);
549428d7b3dSmrg	LogMessage(X_INFO, "        solid\n");
550428d7b3dSmrg	assert(uxa_driver->prepare_copy != NULL);
551428d7b3dSmrg	LogMessage(X_INFO, "        copy\n");
552428d7b3dSmrg	if (uxa_driver->prepare_composite != NULL) {
553428d7b3dSmrg		LogMessage(X_INFO, "        composite (RENDER acceleration)\n");
554428d7b3dSmrg	}
555428d7b3dSmrg	if (uxa_driver->put_image != NULL) {
556428d7b3dSmrg		LogMessage(X_INFO, "        put_image\n");
557428d7b3dSmrg	}
558428d7b3dSmrg	if (uxa_driver->get_image != NULL) {
559428d7b3dSmrg		LogMessage(X_INFO, "        get_image\n");
560428d7b3dSmrg	}
561428d7b3dSmrg
562428d7b3dSmrg	return TRUE;
563428d7b3dSmrg}
564428d7b3dSmrg
565428d7b3dSmrgBool uxa_resources_init(ScreenPtr screen)
566428d7b3dSmrg{
567428d7b3dSmrg	if (!uxa_glyphs_init(screen))
568428d7b3dSmrg		return FALSE;
569428d7b3dSmrg
570428d7b3dSmrg	return TRUE;
571428d7b3dSmrg}
572428d7b3dSmrg
573428d7b3dSmrg/**
574428d7b3dSmrg * uxa_driver_fini tears down UXA on a given screen.
575428d7b3dSmrg *
576428d7b3dSmrg * @param pScreen screen being torn down.
577428d7b3dSmrg */
578428d7b3dSmrgvoid uxa_driver_fini(ScreenPtr pScreen)
579428d7b3dSmrg{
580428d7b3dSmrg	/*right now does nothing */
581428d7b3dSmrg}
582