exa.c revision 4642e01f
1/*
2 * Copyright � 2001 Keith Packard
3 *
4 * Partly based on code that is Copyright � The XFree86 Project Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission.  Keith Packard makes no
13 * representations about the suitability of this software for any purpose.  It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25/** @file
26 * This file covers the initialization and teardown of EXA, and has various
27 * functions not responsible for performing rendering, pixmap migration, or
28 * memory management.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H
32#include <dix-config.h>
33#endif
34
35#include <stdlib.h>
36
37#include "exa_priv.h"
38#include "exa.h"
39
40static int exaScreenPrivateKeyIndex;
41DevPrivateKey exaScreenPrivateKey = &exaScreenPrivateKeyIndex;
42static int exaPixmapPrivateKeyIndex;
43DevPrivateKey exaPixmapPrivateKey = &exaPixmapPrivateKeyIndex;
44
45#ifdef MITSHM
46static ShmFuncs exaShmFuncs = { NULL, NULL };
47#endif
48
49static _X_INLINE void*
50ExaGetPixmapAddress(PixmapPtr p)
51{
52    ExaPixmapPriv(p);
53
54    if (pExaPixmap->offscreen && pExaPixmap->fb_ptr)
55	return pExaPixmap->fb_ptr;
56    else
57	return pExaPixmap->sys_ptr;
58}
59
60/**
61 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
62 * the beginning of the given pixmap.
63 *
64 * Note that drivers are free to, and often do, munge this offset as necessary
65 * for handing to the hardware -- for example, translating it into a different
66 * aperture.  This function may need to be extended in the future if we grow
67 * support for having multiple card-accessible offscreen, such as an AGP memory
68 * pool alongside the framebuffer pool.
69 */
70unsigned long
71exaGetPixmapOffset(PixmapPtr pPix)
72{
73    ExaScreenPriv (pPix->drawable.pScreen);
74
75    return ((unsigned long)ExaGetPixmapAddress(pPix) -
76	    (unsigned long)pExaScr->info->memoryBase);
77}
78
79void *
80exaGetPixmapDriverPrivate(PixmapPtr pPix)
81{
82    ExaPixmapPriv(pPix);
83
84    return pExaPixmap->driverPriv;
85}
86
87/**
88 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap.
89 *
90 * This is a helper to make driver code more obvious, due to the rather obscure
91 * naming of the pitch field in the pixmap.
92 */
93unsigned long
94exaGetPixmapPitch(PixmapPtr pPix)
95{
96    return pPix->devKind;
97}
98
99/**
100 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video
101 * memory. Only valid when the pixmap is currently in framebuffer.
102 */
103unsigned long
104exaGetPixmapSize(PixmapPtr pPix)
105{
106    ExaPixmapPrivPtr pExaPixmap;
107
108    pExaPixmap = ExaGetPixmapPriv(pPix);
109    if (pExaPixmap != NULL)
110	return pExaPixmap->fb_size;
111    return 0;
112}
113
114/**
115 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable.
116 *
117 * @param pDrawable the drawable being requested.
118 *
119 * This function returns the backing pixmap for a drawable, whether it is a
120 * redirected window, unredirected window, or already a pixmap.  Note that
121 * coordinate translation is needed when drawing to the backing pixmap of a
122 * redirected window, and the translation coordinates are provided by calling
123 * exaGetOffscreenPixmap() on the drawable.
124 */
125PixmapPtr
126exaGetDrawablePixmap(DrawablePtr pDrawable)
127{
128     if (pDrawable->type == DRAWABLE_WINDOW)
129	return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable);
130     else
131	return (PixmapPtr) pDrawable;
132}
133
134/**
135 * Sets the offsets to add to coordinates to make them address the same bits in
136 * the backing drawable. These coordinates are nonzero only for redirected
137 * windows.
138 */
139void
140exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
141		      int *xp, int *yp)
142{
143#ifdef COMPOSITE
144    if (pDrawable->type == DRAWABLE_WINDOW) {
145	*xp = -pPixmap->screen_x;
146	*yp = -pPixmap->screen_y;
147	return;
148    }
149#endif
150
151    *xp = 0;
152    *yp = 0;
153}
154
155/**
156 * exaPixmapDirty() marks a pixmap as dirty, allowing for
157 * optimizations in pixmap migration when no changes have occurred.
158 */
159void
160exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
161{
162    ExaPixmapPriv(pPix);
163    BoxRec box;
164    RegionPtr pDamageReg;
165    RegionRec region;
166
167    if (!pExaPixmap || !pExaPixmap->pDamage)
168	return;
169
170    box.x1 = max(x1, 0);
171    box.y1 = max(y1, 0);
172    box.x2 = min(x2, pPix->drawable.width);
173    box.y2 = min(y2, pPix->drawable.height);
174
175    if (box.x1 >= box.x2 || box.y1 >= box.y2)
176	return;
177
178    pDamageReg = DamageRegion(pExaPixmap->pDamage);
179
180    REGION_INIT(pScreen, &region, &box, 1);
181    REGION_UNION(pScreen, pDamageReg, pDamageReg, &region);
182    REGION_UNINIT(pScreen, &region);
183}
184
185static Bool
186exaDestroyPixmap (PixmapPtr pPixmap)
187{
188    ScreenPtr	pScreen = pPixmap->drawable.pScreen;
189    ExaScreenPriv(pScreen);
190
191    if (pPixmap->refcnt == 1)
192    {
193	ExaPixmapPriv (pPixmap);
194
195	if (pExaPixmap->driverPriv) {
196	    pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
197	    pExaPixmap->driverPriv = NULL;
198	}
199
200	if (pExaPixmap->area)
201	{
202	    DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
203                        (void*)pPixmap->drawable.id,
204			 ExaGetPixmapPriv(pPixmap)->area->offset,
205			 pPixmap->drawable.width,
206			 pPixmap->drawable.height));
207	    /* Free the offscreen area */
208	    exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
209	    pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
210	    pPixmap->devKind = pExaPixmap->sys_pitch;
211	}
212	REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys);
213	REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
214    }
215    return fbDestroyPixmap (pPixmap);
216}
217
218static int
219exaLog2(int val)
220{
221    int bits;
222
223    if (val <= 0)
224	return 0;
225    for (bits = 0; val != 0; bits++)
226	val >>= 1;
227    return bits - 1;
228}
229
230static void
231exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
232                 int w, int h, int bpp)
233{
234    pExaPixmap->accel_blocked = 0;
235
236    if (pExaScr->info->maxPitchPixels) {
237        int max_pitch = pExaScr->info->maxPitchPixels * (bpp + 7) / 8;
238
239        if (pExaPixmap->fb_pitch > max_pitch)
240            pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
241    }
242
243    if (pExaScr->info->maxPitchBytes &&
244        pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes)
245        pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
246
247    if (w > pExaScr->info->maxX)
248        pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH;
249
250    if (h > pExaScr->info->maxY)
251        pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT;
252}
253
254static void
255exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
256              int w, int h, int bpp)
257{
258    if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
259        pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8;
260    else
261        pExaPixmap->fb_pitch = w * bpp / 8;
262
263    pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
264                                     pExaScr->info->pixmapPitchAlign);
265}
266
267/**
268 * exaCreatePixmap() creates a new pixmap.
269 *
270 * If width and height are 0, this won't be a full-fledged pixmap and it will
271 * get ModifyPixmapHeader() called on it later.  So, we mark it as pinned, because
272 * ModifyPixmapHeader() would break migration.  These types of pixmaps are used
273 * for scratch pixmaps, or to represent the visible screen.
274 */
275static PixmapPtr
276exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
277		unsigned usage_hint)
278{
279    PixmapPtr		pPixmap;
280    ExaPixmapPrivPtr	pExaPixmap;
281    int                 driver_alloc = 0;
282    int			bpp;
283    ExaScreenPriv(pScreen);
284
285    if (w > 32767 || h > 32767)
286	return NullPixmap;
287
288    if (!pExaScr->info->CreatePixmap) {
289        pPixmap = fbCreatePixmap (pScreen, w, h, depth, usage_hint);
290    } else {
291        driver_alloc = 1;
292        pPixmap = fbCreatePixmap(pScreen, 0, 0, depth, usage_hint);
293    }
294
295    if (!pPixmap)
296        return NULL;
297
298    pExaPixmap = ExaGetPixmapPriv(pPixmap);
299    pExaPixmap->driverPriv = NULL;
300
301    bpp = pPixmap->drawable.bitsPerPixel;
302
303    if (driver_alloc) {
304        size_t paddedWidth, datasize;
305
306	paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
307        if (paddedWidth / 4 > 32767 || h > 32767)
308            return NullPixmap;
309
310        exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
311
312        if (paddedWidth < pExaPixmap->fb_pitch)
313            paddedWidth = pExaPixmap->fb_pitch;
314
315        datasize = h * paddedWidth;
316
317	/* Set this before driver hooks, to allow for !offscreen pixmaps.
318	 * !offscreen pixmaps have a valid pointer at all times.
319	 */
320	pPixmap->devPrivate.ptr = NULL;
321
322        pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
323        if (!pExaPixmap->driverPriv) {
324             fbDestroyPixmap(pPixmap);
325             return NULL;
326        }
327
328        (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
329                                       paddedWidth, NULL);
330        pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
331        pExaPixmap->fb_ptr = NULL;
332        pExaPixmap->pDamage = NULL;
333        pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
334
335    } else {
336        pExaPixmap->driverPriv = NULL;
337        /* Scratch pixmaps may have w/h equal to zero, and may not be
338	 * migrated.
339	 */
340        if (!w || !h)
341	    pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
342        else
343            pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
344
345        pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
346        pExaPixmap->sys_pitch = pPixmap->devKind;
347
348        pPixmap->devPrivate.ptr = NULL;
349        pExaPixmap->offscreen = FALSE;
350
351        pExaPixmap->fb_ptr = NULL;
352        exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
353        pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
354
355        if (pExaPixmap->fb_pitch > 131071) {
356	     fbDestroyPixmap(pPixmap);
357	     return NULL;
358        }
359
360	/* Set up damage tracking */
361	pExaPixmap->pDamage = DamageCreate (NULL, NULL,
362					    DamageReportNone, TRUE,
363					    pScreen, pPixmap);
364
365	if (pExaPixmap->pDamage == NULL) {
366	    fbDestroyPixmap (pPixmap);
367	    return NULL;
368	}
369
370	DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
371	/* This ensures that pending damage reflects the current operation. */
372	/* This is used by exa to optimize migration. */
373	DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
374    }
375
376    pExaPixmap->area = NULL;
377
378    /* None of the pixmap bits are valid initially */
379    REGION_NULL(pScreen, &pExaPixmap->validSys);
380    REGION_NULL(pScreen, &pExaPixmap->validFB);
381
382    exaSetAccelBlock(pExaScr, pExaPixmap,
383                     w, h, bpp);
384
385    return pPixmap;
386}
387
388static Bool
389exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
390		      int bitsPerPixel, int devKind, pointer pPixData)
391{
392    ExaScreenPrivPtr pExaScr;
393    ExaPixmapPrivPtr pExaPixmap;
394    Bool ret;
395
396    if (!pPixmap)
397        return FALSE;
398
399    pExaScr = ExaGetScreenPriv(pPixmap->drawable.pScreen);
400    pExaPixmap = ExaGetPixmapPriv(pPixmap);
401
402    if (pExaPixmap) {
403        if (pPixData)
404            pExaPixmap->sys_ptr = pPixData;
405
406        if (devKind > 0)
407            pExaPixmap->sys_pitch = devKind;
408
409        if (width > 0 && height > 0 && bitsPerPixel > 0) {
410            exaSetFbPitch(pExaScr, pExaPixmap,
411                          width, height, bitsPerPixel);
412
413            exaSetAccelBlock(pExaScr, pExaPixmap,
414                             width, height, bitsPerPixel);
415        }
416    }
417
418
419    if (pExaScr->info->ModifyPixmapHeader) {
420	ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
421						bitsPerPixel, devKind, pPixData);
422	if (ret == TRUE)
423	    return ret;
424    }
425    return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
426					    bitsPerPixel, devKind, pPixData);
427}
428
429/**
430 * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen
431 * memory, meaning that acceleration could probably be done to it, and that it
432 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
433 * with the CPU.
434 *
435 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
436 * deal with moving pixmaps in and out of system memory), EXA will give drivers
437 * pixmaps as arguments for which exaPixmapIsOffscreen() is TRUE.
438 *
439 * @return TRUE if the given drawable is in framebuffer memory.
440 */
441Bool
442exaPixmapIsOffscreen(PixmapPtr p)
443{
444    ScreenPtr	pScreen = p->drawable.pScreen;
445    ExaScreenPriv(pScreen);
446    ExaPixmapPriv(p);
447    void *save_ptr;
448    Bool ret;
449
450    save_ptr = p->devPrivate.ptr;
451
452    if (!save_ptr && pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS))
453	p->devPrivate.ptr = ExaGetPixmapAddress(p);
454
455    if (pExaScr->info->PixmapIsOffscreen)
456	ret = pExaScr->info->PixmapIsOffscreen(p);
457    else
458       ret = ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
459			       (CARD8 *) pExaScr->info->memoryBase) <
460	      pExaScr->info->memorySize);
461
462    p->devPrivate.ptr = save_ptr;
463
464    return ret;
465}
466
467/**
468 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapIsOffscreen().
469 */
470Bool
471exaDrawableIsOffscreen (DrawablePtr pDrawable)
472{
473    return exaPixmapIsOffscreen (exaGetDrawablePixmap (pDrawable));
474}
475
476/**
477 * Returns the pixmap which backs a drawable, and the offsets to add to
478 * coordinates to make them address the same bits in the backing drawable.
479 */
480PixmapPtr
481exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
482{
483    PixmapPtr	pPixmap = exaGetDrawablePixmap (pDrawable);
484
485    exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp);
486
487    if (exaPixmapIsOffscreen (pPixmap))
488	return pPixmap;
489    else
490	return NULL;
491}
492
493void
494ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
495{
496    ScreenPtr	    pScreen = pDrawable->pScreen;
497    ExaScreenPriv  (pScreen);
498    PixmapPtr	    pPixmap = exaGetDrawablePixmap (pDrawable);
499    Bool	    offscreen = exaPixmapIsOffscreen(pPixmap);
500
501    /* Unhide pixmap pointer */
502    if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
503	pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
504    }
505
506    if (!offscreen)
507	return;
508
509    exaWaitSync (pDrawable->pScreen);
510
511    if (pExaScr->info->PrepareAccess == NULL)
512	return;
513
514    if (index >= EXA_PREPARE_AUX0 &&
515	!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
516	exaMoveOutPixmap (pPixmap);
517	return;
518    }
519
520    if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
521	ExaPixmapPriv (pPixmap);
522	if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
523	    FatalError("Driver failed PrepareAccess on a pinned pixmap\n");
524	exaMoveOutPixmap (pPixmap);
525    }
526}
527
528void
529exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
530{
531    ExaMigrationRec pixmaps[1];
532
533    pixmaps[0].as_dst = index == EXA_PREPARE_DEST;
534    pixmaps[0].as_src = index != EXA_PREPARE_DEST;
535    pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
536    pixmaps[0].pReg = pReg;
537
538    exaDoMigration(pixmaps, 1, FALSE);
539
540    ExaDoPrepareAccess(pDrawable, index);
541}
542
543/**
544 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
545 *
546 * It deals with waiting for synchronization with the card, determining if
547 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
548 */
549void
550exaPrepareAccess(DrawablePtr pDrawable, int index)
551{
552    exaPrepareAccessReg(pDrawable, index, NULL);
553}
554
555/**
556 * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
557 *
558 * It deals with calling the driver's FinishAccess() only if necessary.
559 */
560void
561exaFinishAccess(DrawablePtr pDrawable, int index)
562{
563    ScreenPtr	    pScreen = pDrawable->pScreen;
564    ExaScreenPriv  (pScreen);
565    PixmapPtr	    pPixmap = exaGetDrawablePixmap (pDrawable);
566    ExaPixmapPriv  (pPixmap);
567
568    /* Rehide pixmap pointer if we're doing that. */
569    if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
570	pPixmap->devPrivate.ptr = NULL;
571    }
572
573    if (pExaScr->info->FinishAccess == NULL)
574	return;
575
576    if (!exaPixmapIsOffscreen (pPixmap))
577	return;
578
579    if (index >= EXA_PREPARE_AUX0 &&
580	!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
581	ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
582	       "unsupported index EXA_PREPARE_AUX*\n");
583	return;
584    }
585
586    (*pExaScr->info->FinishAccess) (pPixmap, index);
587}
588
589/**
590 * exaValidateGC() sets the ops to EXA's implementations, which may be
591 * accelerated or may sync the card and fall back to fb.
592 */
593static void
594exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
595{
596    /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
597     * Preempt fbValidateGC by doing its work and masking the change out, so
598     * that we can do the Prepare/FinishAccess.
599     */
600#ifdef FB_24_32BIT
601    if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
602	(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
603	fbGetRotatedPixmap(pGC) = 0;
604    }
605
606    if (pGC->fillStyle == FillTiled) {
607	PixmapPtr	pOldTile, pNewTile;
608
609	pOldTile = pGC->tile.pixmap;
610	if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
611	{
612	    pNewTile = fbGetRotatedPixmap(pGC);
613	    if (!pNewTile ||
614		pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
615	    {
616		if (pNewTile)
617		    (*pGC->pScreen->DestroyPixmap) (pNewTile);
618		/* fb24_32ReformatTile will do direct access of a newly-
619		 * allocated pixmap.  This isn't a problem yet, since we don't
620		 * put pixmaps in FB until at least one accelerated EXA op.
621		 */
622		exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
623		pNewTile = fb24_32ReformatTile (pOldTile,
624						pDrawable->bitsPerPixel);
625		exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height);
626		exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
627	    }
628	    if (pNewTile)
629	    {
630		fbGetRotatedPixmap(pGC) = pOldTile;
631		pGC->tile.pixmap = pNewTile;
632		changes |= GCTile;
633	    }
634	}
635    }
636#endif
637    if (changes & GCTile) {
638	if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
639					     pDrawable->bitsPerPixel))
640	{
641	    exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
642	    fbPadPixmap (pGC->tile.pixmap);
643	    exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
644	    exaPixmapDirty(pGC->tile.pixmap, 0, 0,
645			   pGC->tile.pixmap->drawable.width,
646			   pGC->tile.pixmap->drawable.height);
647	}
648	/* Mask out the GCTile change notification, now that we've done FB's
649	 * job for it.
650	 */
651	changes &= ~GCTile;
652    }
653
654    exaPrepareAccessGC(pGC);
655    fbValidateGC (pGC, changes, pDrawable);
656    exaFinishAccessGC(pGC);
657
658    pGC->ops = (GCOps *) &exaOps;
659}
660
661static GCFuncs	exaGCFuncs = {
662    exaValidateGC,
663    miChangeGC,
664    miCopyGC,
665    miDestroyGC,
666    miChangeClip,
667    miDestroyClip,
668    miCopyClip
669};
670
671/**
672 * exaCreateGC makes a new GC and hooks up its funcs handler, so that
673 * exaValidateGC() will get called.
674 */
675static int
676exaCreateGC (GCPtr pGC)
677{
678    if (!fbCreateGC (pGC))
679	return FALSE;
680
681    pGC->funcs = &exaGCFuncs;
682
683    return TRUE;
684}
685
686static Bool
687exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
688{
689    Bool ret;
690
691    if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
692        exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
693
694    if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
695        exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
696
697    ret = fbChangeWindowAttributes(pWin, mask);
698
699    if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
700        exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
701
702    if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
703        exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
704
705    return ret;
706}
707
708static RegionPtr
709exaBitmapToRegion(PixmapPtr pPix)
710{
711  RegionPtr ret;
712  exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC);
713  ret = fbPixmapToRegion(pPix);
714  exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC);
715  return ret;
716}
717
718static Bool
719exaCreateScreenResources(ScreenPtr pScreen)
720{
721    ExaScreenPriv(pScreen);
722    PixmapPtr pScreenPixmap;
723    Bool b;
724
725    pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources;
726    b = pScreen->CreateScreenResources(pScreen);
727    pScreen->CreateScreenResources = exaCreateScreenResources;
728
729    if (!b)
730        return FALSE;
731
732    pScreenPixmap = pScreen->GetScreenPixmap(pScreen);
733
734    if (pScreenPixmap) {
735        ExaPixmapPriv(pScreenPixmap);
736
737        exaSetAccelBlock(pExaScr, pExaPixmap,
738                         pScreenPixmap->drawable.width,
739                         pScreenPixmap->drawable.height,
740                         pScreenPixmap->drawable.bitsPerPixel);
741    }
742
743    return TRUE;
744}
745
746/**
747 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
748 * screen private, before calling down to the next CloseSccreen.
749 */
750static Bool
751exaCloseScreen(int i, ScreenPtr pScreen)
752{
753    ExaScreenPriv(pScreen);
754#ifdef RENDER
755    PictureScreenPtr	ps = GetPictureScreenIfSet(pScreen);
756#endif
757
758    if (ps->Glyphs == exaGlyphs)
759	exaGlyphsFini(pScreen);
760
761    pScreen->CreateGC = pExaScr->SavedCreateGC;
762    pScreen->CloseScreen = pExaScr->SavedCloseScreen;
763    pScreen->GetImage = pExaScr->SavedGetImage;
764    pScreen->GetSpans = pExaScr->SavedGetSpans;
765    pScreen->CreatePixmap = pExaScr->SavedCreatePixmap;
766    pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap;
767    pScreen->CopyWindow = pExaScr->SavedCopyWindow;
768    pScreen->ChangeWindowAttributes = pExaScr->SavedChangeWindowAttributes;
769    pScreen->BitmapToRegion = pExaScr->SavedBitmapToRegion;
770    pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources;
771#ifdef RENDER
772    if (ps) {
773	ps->Composite = pExaScr->SavedComposite;
774	ps->Glyphs = pExaScr->SavedGlyphs;
775	ps->Trapezoids = pExaScr->SavedTrapezoids;
776	ps->Triangles = pExaScr->SavedTriangles;
777	ps->AddTraps = pExaScr->SavedAddTraps;
778    }
779#endif
780
781    xfree (pExaScr);
782
783    return (*pScreen->CloseScreen) (i, pScreen);
784}
785
786/**
787 * This function allocates a driver structure for EXA drivers to fill in.  By
788 * having EXA allocate the structure, the driver structure can be extended
789 * without breaking ABI between EXA and the drivers.  The driver's
790 * responsibility is to check beforehand that the EXA module has a matching
791 * major number and sufficient minor.  Drivers are responsible for freeing the
792 * driver structure using xfree().
793 *
794 * @return a newly allocated, zero-filled driver structure
795 */
796ExaDriverPtr
797exaDriverAlloc(void)
798{
799    return xcalloc(1, sizeof(ExaDriverRec));
800}
801
802/**
803 * @param pScreen screen being initialized
804 * @param pScreenInfo EXA driver record
805 *
806 * exaDriverInit sets up EXA given a driver record filled in by the driver.
807 * pScreenInfo should have been allocated by exaDriverAlloc().  See the
808 * comments in _ExaDriver for what must be filled in and what is optional.
809 *
810 * @return TRUE if EXA was successfully initialized.
811 */
812Bool
813exaDriverInit (ScreenPtr		pScreen,
814               ExaDriverPtr	pScreenInfo)
815{
816    ExaScreenPrivPtr pExaScr;
817#ifdef RENDER
818    PictureScreenPtr ps;
819#endif
820
821    if (!pScreenInfo)
822	return FALSE;
823
824    if (pScreenInfo->exa_major != EXA_VERSION_MAJOR ||
825	pScreenInfo->exa_minor > EXA_VERSION_MINOR)
826    {
827	LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements "
828		   "(%d.%d) are incompatible with EXA version (%d.%d)\n",
829		   pScreen->myNum,
830		   pScreenInfo->exa_major, pScreenInfo->exa_minor,
831		   EXA_VERSION_MAJOR, EXA_VERSION_MINOR);
832	return FALSE;
833    }
834
835    if (!pScreenInfo->CreatePixmap) {
836	if (!pScreenInfo->memoryBase) {
837	    LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase "
838		       "must be non-zero\n", pScreen->myNum);
839	    return FALSE;
840	}
841
842	if (!pScreenInfo->memorySize) {
843	    LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be "
844		       "non-zero\n", pScreen->myNum);
845	    return FALSE;
846	}
847
848	if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) {
849	    LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must "
850		       "be <= ExaDriverRec::memorySize\n", pScreen->myNum);
851	    return FALSE;
852	}
853    }
854
855    if (!pScreenInfo->PrepareSolid) {
856	LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be "
857		   "non-NULL\n", pScreen->myNum);
858	return FALSE;
859    }
860
861    if (!pScreenInfo->PrepareCopy) {
862	LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be "
863		   "non-NULL\n", pScreen->myNum);
864	return FALSE;
865    }
866
867    if (!pScreenInfo->WaitMarker) {
868	LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be "
869		   "non-NULL\n", pScreen->myNum);
870	return FALSE;
871    }
872
873    /* If the driver doesn't set any max pitch values, we'll just assume
874     * that there's a limitation by pixels, and that it's the same as
875     * maxX.
876     *
877     * We want maxPitchPixels or maxPitchBytes to be set so we can check
878     * pixmaps against the max pitch in exaCreatePixmap() -- it matters
879     * whether a pixmap is rejected because of its pitch or
880     * because of its width.
881     */
882    if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes)
883    {
884        pScreenInfo->maxPitchPixels = pScreenInfo->maxX;
885    }
886
887#ifdef RENDER
888    ps = GetPictureScreenIfSet(pScreen);
889#endif
890
891    pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1);
892
893    if (!pExaScr) {
894        LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
895		   pScreen->myNum);
896	return FALSE;
897    }
898
899    pExaScr->info = pScreenInfo;
900
901    dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr);
902
903    pExaScr->migration = ExaMigrationAlways;
904
905    exaDDXDriverInit(pScreen);
906
907    /*
908     * Replace various fb screen functions
909     */
910    pExaScr->SavedCloseScreen = pScreen->CloseScreen;
911    pScreen->CloseScreen = exaCloseScreen;
912
913    pExaScr->SavedCreateGC = pScreen->CreateGC;
914    pScreen->CreateGC = exaCreateGC;
915
916    pExaScr->SavedGetImage = pScreen->GetImage;
917    pScreen->GetImage = exaGetImage;
918
919    pExaScr->SavedGetSpans = pScreen->GetSpans;
920    pScreen->GetSpans = ExaCheckGetSpans;
921
922    pExaScr->SavedCopyWindow = pScreen->CopyWindow;
923    pScreen->CopyWindow = exaCopyWindow;
924
925    pExaScr->SavedChangeWindowAttributes = pScreen->ChangeWindowAttributes;
926    pScreen->ChangeWindowAttributes = exaChangeWindowAttributes;
927
928    pExaScr->SavedBitmapToRegion = pScreen->BitmapToRegion;
929    pScreen->BitmapToRegion = exaBitmapToRegion;
930
931    pExaScr->SavedCreateScreenResources = pScreen->CreateScreenResources;
932    pScreen->CreateScreenResources = exaCreateScreenResources;
933
934#ifdef RENDER
935    if (ps) {
936        pExaScr->SavedComposite = ps->Composite;
937	ps->Composite = exaComposite;
938
939	if (pScreenInfo->PrepareComposite) {
940	    pExaScr->SavedGlyphs = ps->Glyphs;
941	    ps->Glyphs = exaGlyphs;
942	}
943
944	pExaScr->SavedTriangles = ps->Triangles;
945	ps->Triangles = exaTriangles;
946
947	pExaScr->SavedTrapezoids = ps->Trapezoids;
948	ps->Trapezoids = exaTrapezoids;
949
950	pExaScr->SavedAddTraps = ps->AddTraps;
951	ps->AddTraps = ExaCheckAddTraps;
952    }
953#endif
954
955#ifdef MITSHM
956    /*
957     * Don't allow shared pixmaps.
958     */
959    ShmRegisterFuncs(pScreen, &exaShmFuncs);
960#endif
961    /*
962     * Hookup offscreen pixmaps
963     */
964    if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)
965    {
966	if (!dixRequestPrivate(exaPixmapPrivateKey, sizeof(ExaPixmapPrivRec))) {
967            LogMessage(X_WARNING,
968		       "EXA(%d): Failed to allocate pixmap private\n",
969		       pScreen->myNum);
970	    return FALSE;
971        }
972        pExaScr->SavedCreatePixmap = pScreen->CreatePixmap;
973	pScreen->CreatePixmap = exaCreatePixmap;
974
975        pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap;
976	pScreen->DestroyPixmap = exaDestroyPixmap;
977
978	pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader;
979	pScreen->ModifyPixmapHeader = exaModifyPixmapHeader;
980	if (!pExaScr->info->CreatePixmap) {
981	    LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
982		       pScreen->myNum,
983		       pExaScr->info->memorySize - pExaScr->info->offScreenBase);
984	} else {
985	    LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n",
986		       pScreen->myNum);
987
988	}
989    }
990    else
991        LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum);
992
993    if (!pExaScr->info->CreatePixmap) {
994	DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase,
995		    pExaScr->info->memorySize));
996	if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
997	    if (!exaOffscreenInit (pScreen)) {
998		LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n",
999			   pScreen->myNum);
1000		return FALSE;
1001	    }
1002	}
1003    }
1004
1005    if (ps->Glyphs == exaGlyphs)
1006	exaGlyphsInit(pScreen);
1007
1008    LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
1009	       " operations:\n", pScreen->myNum);
1010    assert(pScreenInfo->PrepareSolid != NULL);
1011    LogMessage(X_INFO, "        Solid\n");
1012    assert(pScreenInfo->PrepareCopy != NULL);
1013    LogMessage(X_INFO, "        Copy\n");
1014    if (pScreenInfo->PrepareComposite != NULL) {
1015	LogMessage(X_INFO, "        Composite (RENDER acceleration)\n");
1016    }
1017    if (pScreenInfo->UploadToScreen != NULL) {
1018	LogMessage(X_INFO, "        UploadToScreen\n");
1019    }
1020    if (pScreenInfo->DownloadFromScreen != NULL) {
1021	LogMessage(X_INFO, "        DownloadFromScreen\n");
1022    }
1023
1024    return TRUE;
1025}
1026
1027/**
1028 * exaDriverFini tears down EXA on a given screen.
1029 *
1030 * @param pScreen screen being torn down.
1031 */
1032void
1033exaDriverFini (ScreenPtr pScreen)
1034{
1035    /*right now does nothing*/
1036}
1037
1038/**
1039 * exaMarkSync() should be called after any asynchronous drawing by the hardware.
1040 *
1041 * @param pScreen screen which drawing occurred on
1042 *
1043 * exaMarkSync() sets a flag to indicate that some asynchronous drawing has
1044 * happened and a WaitSync() will be necessary before relying on the contents of
1045 * offscreen memory from the CPU's perspective.  It also calls an optional
1046 * driver MarkSync() callback, the return value of which may be used to do partial
1047 * synchronization with the hardware in the future.
1048 */
1049void exaMarkSync(ScreenPtr pScreen)
1050{
1051    ExaScreenPriv(pScreen);
1052
1053    pExaScr->info->needsSync = TRUE;
1054    if (pExaScr->info->MarkSync != NULL) {
1055        pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen);
1056    }
1057}
1058
1059/**
1060 * exaWaitSync() ensures that all drawing has been completed.
1061 *
1062 * @param pScreen screen being synchronized.
1063 *
1064 * Calls down into the driver to ensure that all previous drawing has completed.
1065 * It should always be called before relying on the framebuffer contents
1066 * reflecting previous drawing, from a CPU perspective.
1067 */
1068void exaWaitSync(ScreenPtr pScreen)
1069{
1070    ExaScreenPriv(pScreen);
1071
1072    if (pExaScr->info->needsSync && !pExaScr->swappedOut) {
1073        (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker);
1074        pExaScr->info->needsSync = FALSE;
1075    }
1076}
1077