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
40DevPrivateKeyRec exaScreenPrivateKeyRec;
41DevPrivateKeyRec exaPixmapPrivateKeyRec;
42DevPrivateKeyRec exaGCPrivateKeyRec;
43
44#ifdef MITSHM
45static ShmFuncs exaShmFuncs = { NULL, NULL };
46#endif
47
48/**
49 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
50 * the beginning of the given pixmap.
51 *
52 * Note that drivers are free to, and often do, munge this offset as necessary
53 * for handing to the hardware -- for example, translating it into a different
54 * aperture.  This function may need to be extended in the future if we grow
55 * support for having multiple card-accessible offscreen, such as an AGP memory
56 * pool alongside the framebuffer pool.
57 */
58unsigned long
59exaGetPixmapOffset(PixmapPtr pPix)
60{
61    ExaScreenPriv (pPix->drawable.pScreen);
62    ExaPixmapPriv (pPix);
63
64    return (CARD8 *)pExaPixmap->fb_ptr - pExaScr->info->memoryBase;
65}
66
67void *
68exaGetPixmapDriverPrivate(PixmapPtr pPix)
69{
70    ExaPixmapPriv(pPix);
71
72    return pExaPixmap->driverPriv;
73}
74
75/**
76 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap.
77 *
78 * This is a helper to make driver code more obvious, due to the rather obscure
79 * naming of the pitch field in the pixmap.
80 */
81unsigned long
82exaGetPixmapPitch(PixmapPtr pPix)
83{
84    return pPix->devKind;
85}
86
87/**
88 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video
89 * memory. Only valid when the pixmap is currently in framebuffer.
90 */
91unsigned long
92exaGetPixmapSize(PixmapPtr pPix)
93{
94    ExaPixmapPrivPtr pExaPixmap;
95
96    pExaPixmap = ExaGetPixmapPriv(pPix);
97    if (pExaPixmap != NULL)
98	return pExaPixmap->fb_size;
99    return 0;
100}
101
102/**
103 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable.
104 *
105 * @param pDrawable the drawable being requested.
106 *
107 * This function returns the backing pixmap for a drawable, whether it is a
108 * redirected window, unredirected window, or already a pixmap.  Note that
109 * coordinate translation is needed when drawing to the backing pixmap of a
110 * redirected window, and the translation coordinates are provided by calling
111 * exaGetOffscreenPixmap() on the drawable.
112 */
113PixmapPtr
114exaGetDrawablePixmap(DrawablePtr pDrawable)
115{
116     if (pDrawable->type == DRAWABLE_WINDOW)
117	return pDrawable->pScreen->GetWindowPixmap ((WindowPtr) pDrawable);
118     else
119	return (PixmapPtr) pDrawable;
120}
121
122/**
123 * Sets the offsets to add to coordinates to make them address the same bits in
124 * the backing drawable. These coordinates are nonzero only for redirected
125 * windows.
126 */
127void
128exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap,
129		      int *xp, int *yp)
130{
131#ifdef COMPOSITE
132    if (pDrawable->type == DRAWABLE_WINDOW) {
133	*xp = -pPixmap->screen_x;
134	*yp = -pPixmap->screen_y;
135	return;
136    }
137#endif
138
139    *xp = 0;
140    *yp = 0;
141}
142
143/**
144 * exaPixmapDirty() marks a pixmap as dirty, allowing for
145 * optimizations in pixmap migration when no changes have occurred.
146 */
147void
148exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
149{
150    BoxRec box;
151    RegionRec region;
152
153    box.x1 = max(x1, 0);
154    box.y1 = max(y1, 0);
155    box.x2 = min(x2, pPix->drawable.width);
156    box.y2 = min(y2, pPix->drawable.height);
157
158    if (box.x1 >= box.x2 || box.y1 >= box.y2)
159	return;
160
161    RegionInit(&region, &box, 1);
162    DamageDamageRegion(&pPix->drawable, &region);
163    RegionUninit(&region);
164}
165
166static int
167exaLog2(int val)
168{
169    int bits;
170
171    if (val <= 0)
172	return 0;
173    for (bits = 0; val != 0; bits++)
174	val >>= 1;
175    return bits - 1;
176}
177
178void
179exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
180                 int w, int h, int bpp)
181{
182    pExaPixmap->accel_blocked = 0;
183
184    if (pExaScr->info->maxPitchPixels) {
185        int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp);
186
187        if (pExaPixmap->fb_pitch > max_pitch)
188            pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
189    }
190
191    if (pExaScr->info->maxPitchBytes &&
192        pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes)
193        pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
194
195    if (w > pExaScr->info->maxX)
196        pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH;
197
198    if (h > pExaScr->info->maxY)
199        pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT;
200}
201
202void
203exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
204              int w, int h, int bpp)
205{
206    if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
207        pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp);
208    else
209        pExaPixmap->fb_pitch = bits_to_bytes(w * bpp);
210
211    pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
212                                     pExaScr->info->pixmapPitchAlign);
213}
214
215/**
216 * Returns TRUE if the pixmap is not movable.  This is the case where it's a
217 * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
218 * some X Server internal component (the score says it's pinned).
219 */
220Bool
221exaPixmapIsPinned (PixmapPtr pPix)
222{
223    ExaPixmapPriv (pPix);
224
225    if (pExaPixmap == NULL)
226	EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
227
228    return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
229}
230
231/**
232 * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
233 * memory, meaning that acceleration could probably be done to it, and that it
234 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
235 * with the CPU.
236 *
237 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
238 * deal with moving pixmaps in and out of system memory), EXA will give drivers
239 * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE.
240 *
241 * @return TRUE if the given drawable is in framebuffer memory.
242 */
243Bool
244exaPixmapHasGpuCopy(PixmapPtr pPixmap)
245{
246    ScreenPtr	pScreen = pPixmap->drawable.pScreen;
247    ExaScreenPriv(pScreen);
248
249    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
250	return FALSE;
251
252    return (*pExaScr->pixmap_has_gpu_copy)(pPixmap);
253}
254
255/**
256 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy().
257 */
258Bool
259exaDrawableIsOffscreen (DrawablePtr pDrawable)
260{
261    return exaPixmapHasGpuCopy (exaGetDrawablePixmap (pDrawable));
262}
263
264/**
265 * Returns the pixmap which backs a drawable, and the offsets to add to
266 * coordinates to make them address the same bits in the backing drawable.
267 */
268PixmapPtr
269exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
270{
271    PixmapPtr	pPixmap = exaGetDrawablePixmap (pDrawable);
272
273    exaGetDrawableDeltas (pDrawable, pPixmap, xp, yp);
274
275    if (exaPixmapHasGpuCopy (pPixmap))
276	return pPixmap;
277    else
278	return NULL;
279}
280
281/**
282 * Returns TRUE if the pixmap GPU copy is being accessed.
283 */
284Bool
285ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
286{
287    ScreenPtr pScreen = pPixmap->drawable.pScreen;
288    ExaScreenPriv (pScreen);
289    ExaPixmapPriv(pPixmap);
290    Bool has_gpu_copy, ret;
291    int i;
292
293    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
294	return FALSE;
295
296    if (pExaPixmap == NULL)
297	EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE);
298
299    /* Handle repeated / nested calls. */
300    for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
301	if (pExaScr->access[i].pixmap == pPixmap) {
302	    pExaScr->access[i].count++;
303	    return pExaScr->access[i].retval;
304	}
305    }
306
307    /* If slot for this index is taken, find an empty slot */
308    if (pExaScr->access[index].pixmap) {
309	for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--)
310	    if (!pExaScr->access[index].pixmap)
311		break;
312    }
313
314    /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */
315    if (pPixmap->devPrivate.ptr != NULL) {
316	EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n",
317			     pPixmap->devPrivate.ptr));
318    }
319
320    has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
321
322    if (has_gpu_copy && pExaPixmap->fb_ptr) {
323	pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
324	ret = TRUE;
325    } else {
326	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
327	ret = FALSE;
328    }
329
330    /* Store so we can handle repeated / nested calls. */
331    pExaScr->access[index].pixmap = pPixmap;
332    pExaScr->access[index].count = 1;
333
334    if (!has_gpu_copy)
335	goto out;
336
337    exaWaitSync (pScreen);
338
339    if (pExaScr->info->PrepareAccess == NULL)
340	goto out;
341
342    if (index >= EXA_PREPARE_AUX_DEST &&
343	!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
344	if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
345	    FatalError("Unsupported AUX indices used on a pinned pixmap.\n");
346	exaMoveOutPixmap (pPixmap);
347	ret = FALSE;
348	goto out;
349    }
350
351    if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
352	if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED &&
353	    !(pExaScr->info->flags & EXA_MIXED_PIXMAPS))
354	    FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
355	exaMoveOutPixmap (pPixmap);
356	ret = FALSE;
357	goto out;
358    }
359
360    ret = TRUE;
361
362out:
363    pExaScr->access[index].retval = ret;
364    return ret;
365}
366
367/**
368 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
369 *
370 * It deals with waiting for synchronization with the card, determining if
371 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
372 */
373void
374exaPrepareAccess(DrawablePtr pDrawable, int index)
375{
376    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
377    ExaScreenPriv(pDrawable->pScreen);
378
379    if (pExaScr->prepare_access_reg)
380	pExaScr->prepare_access_reg(pPixmap, index, NULL);
381    else
382	(void)ExaDoPrepareAccess(pPixmap, index);
383}
384
385/**
386 * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
387 *
388 * It deals with calling the driver's FinishAccess() only if necessary.
389 */
390void
391exaFinishAccess(DrawablePtr pDrawable, int index)
392{
393    ScreenPtr	    pScreen = pDrawable->pScreen;
394    ExaScreenPriv  (pScreen);
395    PixmapPtr	    pPixmap = exaGetDrawablePixmap (pDrawable);
396    ExaPixmapPriv  (pPixmap);
397    int i;
398
399    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
400	return;
401
402    if (pExaPixmap == NULL)
403	EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
404
405    /* Handle repeated / nested calls. */
406    for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
407	if (pExaScr->access[i].pixmap == pPixmap) {
408	    if (--pExaScr->access[i].count > 0)
409		return;
410	    break;
411	}
412    }
413
414    /* Catch unbalanced Prepare/FinishAccess calls. */
415    if (i == EXA_NUM_PREPARE_INDICES)
416      EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n",
417				  pPixmap),);
418
419    pExaScr->access[i].pixmap = NULL;
420
421    /* We always hide the devPrivate.ptr. */
422    pPixmap->devPrivate.ptr = NULL;
423
424    /* Only call FinishAccess if PrepareAccess was called and succeeded. */
425    if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval)
426	return;
427
428    if (i >= EXA_PREPARE_AUX_DEST &&
429	!(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
430	ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
431	       "unsupported index EXA_PREPARE_AUX*\n");
432	return;
433    }
434
435    (*pExaScr->info->FinishAccess) (pPixmap, i);
436}
437
438
439/**
440 * Helper for things common to all schemes when a pixmap is destroyed
441 */
442void
443exaDestroyPixmap(PixmapPtr pPixmap)
444{
445    ExaScreenPriv(pPixmap->drawable.pScreen);
446    int i;
447
448    /* Finish access if it was prepared (e.g. pixmap created during
449     * software fallback)
450     */
451    for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
452	if (pExaScr->access[i].pixmap == pPixmap) {
453	    exaFinishAccess(&pPixmap->drawable, i);
454	    pExaScr->access[i].pixmap = NULL;
455	    break;
456	}
457    }
458}
459
460
461/**
462 * Here begins EXA's GC code.
463 * Do not ever access the fb/mi layer directly.
464 */
465
466static void
467exaValidateGC(GCPtr pGC,
468		unsigned long changes,
469		DrawablePtr pDrawable);
470
471static void
472exaDestroyGC(GCPtr pGC);
473
474static void
475exaChangeGC (GCPtr pGC,
476		unsigned long mask);
477
478static void
479exaCopyGC (GCPtr pGCSrc,
480	      unsigned long mask,
481	      GCPtr	 pGCDst);
482
483static void
484exaChangeClip (GCPtr pGC,
485		int type,
486		pointer pvalue,
487		int nrects);
488
489static void
490exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
491
492static void
493exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
494
495static void
496exaDestroyClip(GCPtr pGC);
497
498const GCFuncs exaGCFuncs = {
499    exaValidateGC,
500    exaChangeGC,
501    exaCopyGC,
502    exaDestroyGC,
503    exaChangeClip,
504    exaDestroyClip,
505    exaCopyClip
506};
507
508static void
509exaValidateGC(GCPtr pGC,
510		unsigned long changes,
511		DrawablePtr pDrawable)
512{
513    /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
514     * Do a few smart things so fbValidateGC can do it's work.
515     */
516
517    ScreenPtr pScreen = pDrawable->pScreen;
518    ExaScreenPriv(pScreen);
519    ExaGCPriv(pGC);
520    PixmapPtr pTile = NULL;
521    Bool finish_current_tile = FALSE;
522
523    /* Either of these conditions is enough to trigger access to a tile pixmap. */
524    /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */
525    if (pGC->fillStyle == FillTiled || ((changes & GCTile) && !pGC->tileIsPixel)) {
526	pTile = pGC->tile.pixmap;
527
528	/* Sometimes tile pixmaps are swapped, you need access to:
529	 * - The current tile if it depth matches.
530	 * - Or the rotated tile if that one matches depth and !(changes & GCTile).
531	 * - Or the current tile pixmap and a newly created one.
532	 */
533	if (pTile && pTile->drawable.depth != pDrawable->depth && !(changes & GCTile)) {
534	    PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC);
535	    if (pRotatedTile && pRotatedTile->drawable.depth == pDrawable->depth)
536		pTile = pRotatedTile;
537	    else
538		finish_current_tile = TRUE; /* CreatePixmap will be called. */
539	}
540    }
541
542    if (pGC->stipple)
543        exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
544    if (pTile)
545	exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC);
546
547    /* Calls to Create/DestroyPixmap have to be identified as special. */
548    pExaScr->fallback_counter++;
549    swap(pExaGC, pGC, funcs);
550    (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
551    swap(pExaGC, pGC, funcs);
552    pExaScr->fallback_counter--;
553
554    if (pTile)
555	exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC);
556    if (finish_current_tile && pGC->tile.pixmap)
557	exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_AUX_DEST);
558    if (pGC->stipple)
559	exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
560}
561
562/* Is exaPrepareAccessGC() needed? */
563static void
564exaDestroyGC(GCPtr pGC)
565{
566    ExaGCPriv(pGC);
567    swap(pExaGC, pGC, funcs);
568    (*pGC->funcs->DestroyGC)(pGC);
569    swap(pExaGC, pGC, funcs);
570}
571
572static void
573exaChangeGC (GCPtr pGC,
574		unsigned long mask)
575{
576    ExaGCPriv(pGC);
577    swap(pExaGC, pGC, funcs);
578    (*pGC->funcs->ChangeGC) (pGC, mask);
579    swap(pExaGC, pGC, funcs);
580}
581
582static void
583exaCopyGC (GCPtr pGCSrc,
584	      unsigned long mask,
585	      GCPtr	 pGCDst)
586{
587    ExaGCPriv(pGCDst);
588    swap(pExaGC, pGCDst, funcs);
589    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
590    swap(pExaGC, pGCDst, funcs);
591}
592
593static void
594exaChangeClip (GCPtr pGC,
595		int type,
596		pointer pvalue,
597		int nrects)
598{
599    ExaGCPriv(pGC);
600    swap(pExaGC, pGC, funcs);
601    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
602    swap(pExaGC, pGC, funcs);
603}
604
605static void
606exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
607{
608    ExaGCPriv(pGCDst);
609    swap(pExaGC, pGCDst, funcs);
610    (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc);
611    swap(pExaGC, pGCDst, funcs);
612}
613
614static void
615exaDestroyClip(GCPtr pGC)
616{
617    ExaGCPriv(pGC);
618    swap(pExaGC, pGC, funcs);
619    (*pGC->funcs->DestroyClip)(pGC);
620    swap(pExaGC, pGC, funcs);
621}
622
623/**
624 * exaCreateGC makes a new GC and hooks up its funcs handler, so that
625 * exaValidateGC() will get called.
626 */
627static int
628exaCreateGC (GCPtr pGC)
629{
630    ScreenPtr pScreen = pGC->pScreen;
631    ExaScreenPriv(pScreen);
632    ExaGCPriv(pGC);
633    Bool ret;
634
635    swap(pExaScr, pScreen, CreateGC);
636    if ((ret = (*pScreen->CreateGC) (pGC))) {
637	wrap(pExaGC, pGC, funcs, (GCFuncs *) &exaGCFuncs);
638	wrap(pExaGC, pGC, ops, (GCOps *) &exaOps);
639    }
640    swap(pExaScr, pScreen, CreateGC);
641
642    return ret;
643}
644
645static Bool
646exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
647{
648    Bool ret;
649    ScreenPtr pScreen = pWin->drawable.pScreen;
650    ExaScreenPriv(pScreen);
651
652    if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
653	exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
654
655    if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
656	exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
657
658    pExaScr->fallback_counter++;
659    swap(pExaScr, pScreen, ChangeWindowAttributes);
660    ret = pScreen->ChangeWindowAttributes(pWin, mask);
661    swap(pExaScr, pScreen, ChangeWindowAttributes);
662    pExaScr->fallback_counter--;
663
664    if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
665	exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
666    if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
667	exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
668
669    return ret;
670}
671
672static RegionPtr
673exaBitmapToRegion(PixmapPtr pPix)
674{
675    RegionPtr ret;
676    ScreenPtr pScreen = pPix->drawable.pScreen;
677    ExaScreenPriv(pScreen);
678
679    exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC);
680    swap(pExaScr, pScreen, BitmapToRegion);
681    ret = (*pScreen->BitmapToRegion)(pPix);
682    swap(pExaScr, pScreen, BitmapToRegion);
683    exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC);
684
685    return ret;
686}
687
688static Bool
689exaCreateScreenResources(ScreenPtr pScreen)
690{
691    ExaScreenPriv(pScreen);
692    PixmapPtr pScreenPixmap;
693    Bool b;
694
695    swap(pExaScr, pScreen, CreateScreenResources);
696    b = pScreen->CreateScreenResources(pScreen);
697    swap(pExaScr, pScreen, CreateScreenResources);
698
699    if (!b)
700        return FALSE;
701
702    pScreenPixmap = pScreen->GetScreenPixmap(pScreen);
703
704    if (pScreenPixmap) {
705        ExaPixmapPriv(pScreenPixmap);
706
707        exaSetAccelBlock(pExaScr, pExaPixmap,
708                         pScreenPixmap->drawable.width,
709                         pScreenPixmap->drawable.height,
710                         pScreenPixmap->drawable.bitsPerPixel);
711    }
712
713    return TRUE;
714}
715
716static void
717ExaBlockHandler(int screenNum, pointer blockData, pointer pTimeout,
718		pointer pReadmask)
719{
720    ScreenPtr pScreen = screenInfo.screens[screenNum];
721    ExaScreenPriv(pScreen);
722
723    /* Move any deferred results from a software fallback to the driver pixmap */
724    if (pExaScr->deferred_mixed_pixmap)
725	exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
726
727    unwrap(pExaScr, pScreen, BlockHandler);
728    (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
729    wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
730
731    /* The rest only applies to classic EXA */
732    if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
733	return;
734
735    /* Try and keep the offscreen memory area tidy every now and then (at most
736     * once per second) when the server has been idle for at least 100ms.
737     */
738    if (pExaScr->numOffscreenAvailable > 1) {
739	CARD32 now = GetTimeInMillis();
740
741	pExaScr->nextDefragment = now +
742	    max(100, (INT32)(pExaScr->lastDefragment + 1000 - now));
743	AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now);
744    }
745}
746
747static void
748ExaWakeupHandler(int screenNum, pointer wakeupData, unsigned long result,
749		 pointer pReadmask)
750{
751    ScreenPtr pScreen = screenInfo.screens[screenNum];
752    ExaScreenPriv(pScreen);
753
754    unwrap(pExaScr, pScreen, WakeupHandler);
755    (*pScreen->WakeupHandler) (screenNum, wakeupData, result, pReadmask);
756    wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
757
758    if (result == 0 && pExaScr->numOffscreenAvailable > 1) {
759	CARD32 now = GetTimeInMillis();
760
761	if ((int)(now - pExaScr->nextDefragment) > 0) {
762	    ExaOffscreenDefragment(pScreen);
763	    pExaScr->lastDefragment = now;
764	}
765    }
766}
767
768/**
769 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
770 * screen private, before calling down to the next CloseSccreen.
771 */
772static Bool
773exaCloseScreen(int i, ScreenPtr pScreen)
774{
775    ExaScreenPriv(pScreen);
776    PictureScreenPtr	ps = GetPictureScreenIfSet(pScreen);
777
778    if (ps->Glyphs == exaGlyphs)
779	exaGlyphsFini(pScreen);
780
781    if (pScreen->BlockHandler == ExaBlockHandler)
782	unwrap(pExaScr, pScreen, BlockHandler);
783    if (pScreen->WakeupHandler == ExaWakeupHandler)
784	unwrap(pExaScr, pScreen, WakeupHandler);
785    unwrap(pExaScr, pScreen, CreateGC);
786    unwrap(pExaScr, pScreen, CloseScreen);
787    unwrap(pExaScr, pScreen, GetImage);
788    unwrap(pExaScr, pScreen, GetSpans);
789    if (pExaScr->SavedCreatePixmap)
790	unwrap(pExaScr, pScreen, CreatePixmap);
791    if (pExaScr->SavedDestroyPixmap)
792	unwrap(pExaScr, pScreen, DestroyPixmap);
793    if (pExaScr->SavedModifyPixmapHeader)
794	unwrap(pExaScr, pScreen, ModifyPixmapHeader);
795    unwrap(pExaScr, pScreen, CopyWindow);
796    unwrap(pExaScr, pScreen, ChangeWindowAttributes);
797    unwrap(pExaScr, pScreen, BitmapToRegion);
798    unwrap(pExaScr, pScreen, CreateScreenResources);
799    unwrap(pExaScr, ps, Composite);
800    if (pExaScr->SavedGlyphs)
801	unwrap(pExaScr, ps, Glyphs);
802    unwrap(pExaScr, ps, Trapezoids);
803    unwrap(pExaScr, ps, Triangles);
804    unwrap(pExaScr, ps, AddTraps);
805
806    free(pExaScr);
807
808    return (*pScreen->CloseScreen) (i, pScreen);
809}
810
811/**
812 * This function allocates a driver structure for EXA drivers to fill in.  By
813 * having EXA allocate the structure, the driver structure can be extended
814 * without breaking ABI between EXA and the drivers.  The driver's
815 * responsibility is to check beforehand that the EXA module has a matching
816 * major number and sufficient minor.  Drivers are responsible for freeing the
817 * driver structure using free().
818 *
819 * @return a newly allocated, zero-filled driver structure
820 */
821ExaDriverPtr
822exaDriverAlloc(void)
823{
824    return calloc(1, sizeof(ExaDriverRec));
825}
826
827/**
828 * @param pScreen screen being initialized
829 * @param pScreenInfo EXA driver record
830 *
831 * exaDriverInit sets up EXA given a driver record filled in by the driver.
832 * pScreenInfo should have been allocated by exaDriverAlloc().  See the
833 * comments in _ExaDriver for what must be filled in and what is optional.
834 *
835 * @return TRUE if EXA was successfully initialized.
836 */
837Bool
838exaDriverInit (ScreenPtr		pScreen,
839               ExaDriverPtr	pScreenInfo)
840{
841    ExaScreenPrivPtr pExaScr;
842    PictureScreenPtr ps;
843
844    if (!pScreenInfo)
845	return FALSE;
846
847    if (pScreenInfo->exa_major != EXA_VERSION_MAJOR ||
848	pScreenInfo->exa_minor > EXA_VERSION_MINOR)
849    {
850	LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements "
851		   "(%d.%d) are incompatible with EXA version (%d.%d)\n",
852		   pScreen->myNum,
853		   pScreenInfo->exa_major, pScreenInfo->exa_minor,
854		   EXA_VERSION_MAJOR, EXA_VERSION_MINOR);
855	return FALSE;
856    }
857
858    if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) {
859	if (!pScreenInfo->memoryBase) {
860	    LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase "
861		       "must be non-zero\n", pScreen->myNum);
862	    return FALSE;
863	}
864
865	if (!pScreenInfo->memorySize) {
866	    LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be "
867		       "non-zero\n", pScreen->myNum);
868	    return FALSE;
869	}
870
871	if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) {
872	    LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must "
873		       "be <= ExaDriverRec::memorySize\n", pScreen->myNum);
874	    return FALSE;
875	}
876    }
877
878    if (!pScreenInfo->PrepareSolid) {
879	LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be "
880		   "non-NULL\n", pScreen->myNum);
881	return FALSE;
882    }
883
884    if (!pScreenInfo->PrepareCopy) {
885	LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be "
886		   "non-NULL\n", pScreen->myNum);
887	return FALSE;
888    }
889
890    if (!pScreenInfo->WaitMarker) {
891	LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be "
892		   "non-NULL\n", pScreen->myNum);
893	return FALSE;
894    }
895
896    /* If the driver doesn't set any max pitch values, we'll just assume
897     * that there's a limitation by pixels, and that it's the same as
898     * maxX.
899     *
900     * We want maxPitchPixels or maxPitchBytes to be set so we can check
901     * pixmaps against the max pitch in exaCreatePixmap() -- it matters
902     * whether a pixmap is rejected because of its pitch or
903     * because of its width.
904     */
905    if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes)
906    {
907        pScreenInfo->maxPitchPixels = pScreenInfo->maxX;
908    }
909
910    ps = GetPictureScreenIfSet(pScreen);
911
912    if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) {
913        LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n",
914		   pScreen->myNum);
915	return FALSE;
916    }
917
918    pExaScr = calloc (sizeof (ExaScreenPrivRec), 1);
919    if (!pExaScr) {
920        LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
921		   pScreen->myNum);
922	return FALSE;
923    }
924
925    pExaScr->info = pScreenInfo;
926
927    dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr);
928
929    pExaScr->migration = ExaMigrationAlways;
930
931    exaDDXDriverInit(pScreen);
932
933    if (!dixRegisterPrivateKey(&exaGCPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) {
934	LogMessage(X_WARNING,
935	       "EXA(%d): Failed to allocate GC private\n",
936	       pScreen->myNum);
937	return FALSE;
938    }
939
940    /*
941     * Replace various fb screen functions
942     */
943    if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
944	(!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) ||
945	 (pExaScr->info->flags & EXA_MIXED_PIXMAPS)))
946	wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
947    if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) &&
948	!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS))
949	wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
950    wrap(pExaScr, pScreen, CreateGC, exaCreateGC);
951    wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen);
952    wrap(pExaScr, pScreen, GetImage, exaGetImage);
953    wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans);
954    wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow);
955    wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes);
956    wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion);
957    wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources);
958
959    if (ps) {
960	wrap(pExaScr, ps, Composite, exaComposite);
961	if (pScreenInfo->PrepareComposite) {
962	    wrap(pExaScr, ps, Glyphs, exaGlyphs);
963	} else {
964	    wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs);
965	}
966	wrap(pExaScr, ps, Trapezoids, exaTrapezoids);
967	wrap(pExaScr, ps, Triangles, exaTriangles);
968	wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps);
969    }
970
971#ifdef MITSHM
972    /*
973     * Don't allow shared pixmaps.
974     */
975    ShmRegisterFuncs(pScreen, &exaShmFuncs);
976#endif
977    /*
978     * Hookup offscreen pixmaps
979     */
980    if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)
981    {
982	if (!dixRegisterPrivateKey(&exaPixmapPrivateKeyRec, PRIVATE_PIXMAP, sizeof(ExaPixmapPrivRec))) {
983            LogMessage(X_WARNING,
984		       "EXA(%d): Failed to allocate pixmap private\n",
985		       pScreen->myNum);
986	    return FALSE;
987        }
988	if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) {
989	    if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) {
990		wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed);
991		wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed);
992		wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_mixed);
993		pExaScr->do_migration = exaDoMigration_mixed;
994		pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed;
995		pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed;
996		pExaScr->do_move_out_pixmap = NULL;
997		pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed;
998	    } else {
999		wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
1000		wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
1001		wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_driver);
1002		pExaScr->do_migration = NULL;
1003		pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_driver;
1004		pExaScr->do_move_in_pixmap = NULL;
1005		pExaScr->do_move_out_pixmap = NULL;
1006		pExaScr->prepare_access_reg = NULL;
1007	    }
1008	} else {
1009	    wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
1010	    wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic);
1011	    wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_classic);
1012	    pExaScr->do_migration = exaDoMigration_classic;
1013	    pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic;
1014	    pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic;
1015	    pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic;
1016	    pExaScr->prepare_access_reg = exaPrepareAccessReg_classic;
1017	}
1018	if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
1019	    LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
1020		       pScreen->myNum,
1021		       pExaScr->info->memorySize - pExaScr->info->offScreenBase);
1022	} else {
1023	    LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n",
1024		       pScreen->myNum);
1025
1026	}
1027    }
1028    else
1029        LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum);
1030
1031    if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
1032	DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase,
1033		    pExaScr->info->memorySize));
1034	if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
1035	    if (!exaOffscreenInit (pScreen)) {
1036		LogMessage(X_WARNING, "EXA(%d): Offscreen pixmap setup failed\n",
1037			   pScreen->myNum);
1038		return FALSE;
1039	    }
1040	}
1041    }
1042
1043    if (ps->Glyphs == exaGlyphs)
1044	exaGlyphsInit(pScreen);
1045
1046    LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
1047	       " operations:\n", pScreen->myNum);
1048    assert(pScreenInfo->PrepareSolid != NULL);
1049    LogMessage(X_INFO, "        Solid\n");
1050    assert(pScreenInfo->PrepareCopy != NULL);
1051    LogMessage(X_INFO, "        Copy\n");
1052    if (pScreenInfo->PrepareComposite != NULL) {
1053	LogMessage(X_INFO, "        Composite (RENDER acceleration)\n");
1054    }
1055    if (pScreenInfo->UploadToScreen != NULL) {
1056	LogMessage(X_INFO, "        UploadToScreen\n");
1057    }
1058    if (pScreenInfo->DownloadFromScreen != NULL) {
1059	LogMessage(X_INFO, "        DownloadFromScreen\n");
1060    }
1061
1062    return TRUE;
1063}
1064
1065/**
1066 * exaDriverFini tears down EXA on a given screen.
1067 *
1068 * @param pScreen screen being torn down.
1069 */
1070void
1071exaDriverFini (ScreenPtr pScreen)
1072{
1073    /*right now does nothing*/
1074}
1075
1076/**
1077 * exaMarkSync() should be called after any asynchronous drawing by the hardware.
1078 *
1079 * @param pScreen screen which drawing occurred on
1080 *
1081 * exaMarkSync() sets a flag to indicate that some asynchronous drawing has
1082 * happened and a WaitSync() will be necessary before relying on the contents of
1083 * offscreen memory from the CPU's perspective.  It also calls an optional
1084 * driver MarkSync() callback, the return value of which may be used to do partial
1085 * synchronization with the hardware in the future.
1086 */
1087void exaMarkSync(ScreenPtr pScreen)
1088{
1089    ExaScreenPriv(pScreen);
1090
1091    pExaScr->info->needsSync = TRUE;
1092    if (pExaScr->info->MarkSync != NULL) {
1093        pExaScr->info->lastMarker = (*pExaScr->info->MarkSync)(pScreen);
1094    }
1095}
1096
1097/**
1098 * exaWaitSync() ensures that all drawing has been completed.
1099 *
1100 * @param pScreen screen being synchronized.
1101 *
1102 * Calls down into the driver to ensure that all previous drawing has completed.
1103 * It should always be called before relying on the framebuffer contents
1104 * reflecting previous drawing, from a CPU perspective.
1105 */
1106void exaWaitSync(ScreenPtr pScreen)
1107{
1108    ExaScreenPriv(pScreen);
1109
1110    if (pExaScr->info->needsSync && !pExaScr->swappedOut) {
1111        (*pExaScr->info->WaitMarker)(pScreen, pExaScr->info->lastMarker);
1112        pExaScr->info->needsSync = FALSE;
1113    }
1114}
1115
1116/**
1117 * Performs migration of the pixmaps according to the operation information
1118 * provided in pixmaps and can_accel and the migration scheme chosen in the
1119 * config file.
1120 */
1121void
1122exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
1123{
1124    ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
1125    ExaScreenPriv(pScreen);
1126
1127    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
1128	return;
1129
1130    if (pExaScr->do_migration)
1131	(*pExaScr->do_migration)(pixmaps, npixmaps, can_accel);
1132}
1133
1134void
1135exaMoveInPixmap (PixmapPtr pPixmap)
1136{
1137    ScreenPtr pScreen = pPixmap->drawable.pScreen;
1138    ExaScreenPriv(pScreen);
1139
1140    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
1141	return;
1142
1143    if (pExaScr->do_move_in_pixmap)
1144	(*pExaScr->do_move_in_pixmap)(pPixmap);
1145}
1146
1147void
1148exaMoveOutPixmap (PixmapPtr pPixmap)
1149{
1150    ScreenPtr pScreen = pPixmap->drawable.pScreen;
1151    ExaScreenPriv(pScreen);
1152
1153    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
1154	return;
1155
1156    if (pExaScr->do_move_out_pixmap)
1157	(*pExaScr->do_move_out_pixmap)(pPixmap);
1158}
1159