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