2 * Copyright © 2001 Keith Packard
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
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.
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.
26 * This file covers the initialization and teardown of EXA, and has various
27 * functions not responsible for performing rendering, pixmap migration, or
31 #ifdef HAVE_DIX_CONFIG_H
32 #include <dix-config.h>
40 DevPrivateKeyRec exaScreenPrivateKeyRec
;
43 static ShmFuncs exaShmFuncs
= { NULL
, NULL
};
47 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
48 * the beginning of the given pixmap.
50 * Note that drivers are free to, and often do, munge this offset as necessary
51 * for handing to the hardware -- for example, translating it into a different
52 * aperture. This function may need to be extended in the future if we grow
53 * support for having multiple card-accessible offscreen, such as an AGP memory
54 * pool alongside the framebuffer pool.
57 exaGetPixmapOffset(PixmapPtr pPix
)
59 ExaScreenPriv(pPix
->drawable
.pScreen
);
62 return (CARD8
*) pExaPixmap
->fb_ptr
- pExaScr
->info
->memoryBase
;
66 exaGetPixmapDriverPrivate(PixmapPtr pPix
)
70 return pExaPixmap
->driverPriv
;
74 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap.
76 * This is a helper to make driver code more obvious, due to the rather obscure
77 * naming of the pitch field in the pixmap.
80 exaGetPixmapPitch(PixmapPtr pPix
)
86 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video
87 * memory. Only valid when the pixmap is currently in framebuffer.
90 exaGetPixmapSize(PixmapPtr pPix
)
92 ExaPixmapPrivPtr pExaPixmap
;
94 pExaPixmap
= ExaGetPixmapPriv(pPix
);
95 if (pExaPixmap
!= NULL
)
96 return pExaPixmap
->fb_size
;
101 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable.
103 * @param pDrawable the drawable being requested.
105 * This function returns the backing pixmap for a drawable, whether it is a
106 * redirected window, unredirected window, or already a pixmap. Note that
107 * coordinate translation is needed when drawing to the backing pixmap of a
108 * redirected window, and the translation coordinates are provided by calling
109 * exaGetOffscreenPixmap() on the drawable.
112 exaGetDrawablePixmap(DrawablePtr pDrawable
)
114 if (pDrawable
->type
== DRAWABLE_WINDOW
)
115 return pDrawable
->pScreen
->GetWindowPixmap((WindowPtr
) pDrawable
);
117 return (PixmapPtr
) pDrawable
;
121 * Sets the offsets to add to coordinates to make them address the same bits in
122 * the backing drawable. These coordinates are nonzero only for redirected
126 exaGetDrawableDeltas(DrawablePtr pDrawable
, PixmapPtr pPixmap
, int *xp
, int *yp
)
129 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
130 *xp
= -pPixmap
->screen_x
;
131 *yp
= -pPixmap
->screen_y
;
141 * exaPixmapDirty() marks a pixmap as dirty, allowing for
142 * optimizations in pixmap migration when no changes have occurred.
145 exaPixmapDirty(PixmapPtr pPix
, int x1
, int y1
, int x2
, int y2
)
152 box
.x2
= min(x2
, pPix
->drawable
.width
);
153 box
.y2
= min(y2
, pPix
->drawable
.height
);
155 if (box
.x1
>= box
.x2
|| box
.y1
>= box
.y2
)
158 RegionInit(®ion
, &box
, 1);
159 DamageDamageRegion(&pPix
->drawable
, ®ion
);
160 RegionUninit(®ion
);
170 for (bits
= 0; val
!= 0; bits
++)
176 exaSetAccelBlock(ExaScreenPrivPtr pExaScr
, ExaPixmapPrivPtr pExaPixmap
,
177 int w
, int h
, int bpp
)
179 pExaPixmap
->accel_blocked
= 0;
181 if (pExaScr
->info
->maxPitchPixels
) {
182 int max_pitch
= pExaScr
->info
->maxPitchPixels
* bits_to_bytes(bpp
);
184 if (pExaPixmap
->fb_pitch
> max_pitch
)
185 pExaPixmap
->accel_blocked
|= EXA_RANGE_PITCH
;
188 if (pExaScr
->info
->maxPitchBytes
&&
189 pExaPixmap
->fb_pitch
> pExaScr
->info
->maxPitchBytes
)
190 pExaPixmap
->accel_blocked
|= EXA_RANGE_PITCH
;
192 if (w
> pExaScr
->info
->maxX
)
193 pExaPixmap
->accel_blocked
|= EXA_RANGE_WIDTH
;
195 if (h
> pExaScr
->info
->maxY
)
196 pExaPixmap
->accel_blocked
|= EXA_RANGE_HEIGHT
;
200 exaSetFbPitch(ExaScreenPrivPtr pExaScr
, ExaPixmapPrivPtr pExaPixmap
,
201 int w
, int h
, int bpp
)
203 if (pExaScr
->info
->flags
& EXA_OFFSCREEN_ALIGN_POT
&& w
!= 1)
204 pExaPixmap
->fb_pitch
= bits_to_bytes((1 << (exaLog2(w
- 1) + 1)) * bpp
);
206 pExaPixmap
->fb_pitch
= bits_to_bytes(w
* bpp
);
208 pExaPixmap
->fb_pitch
= EXA_ALIGN(pExaPixmap
->fb_pitch
,
209 pExaScr
->info
->pixmapPitchAlign
);
213 * Returns TRUE if the pixmap is not movable. This is the case where it's a
214 * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
215 * some X Server internal component (the score says it's pinned).
218 exaPixmapIsPinned(PixmapPtr pPix
)
222 if (pExaPixmap
== NULL
)
223 EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE
);
225 return pExaPixmap
->score
== EXA_PIXMAP_SCORE_PINNED
;
229 * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
230 * memory, meaning that acceleration could probably be done to it, and that it
231 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
234 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
235 * deal with moving pixmaps in and out of system memory), EXA will give drivers
236 * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE.
238 * @return TRUE if the given drawable is in framebuffer memory.
241 exaPixmapHasGpuCopy(PixmapPtr pPixmap
)
243 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
245 ExaScreenPriv(pScreen
);
247 if (!(pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
))
250 return (*pExaScr
->pixmap_has_gpu_copy
) (pPixmap
);
254 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy().
257 exaDrawableIsOffscreen(DrawablePtr pDrawable
)
259 return exaPixmapHasGpuCopy(exaGetDrawablePixmap(pDrawable
));
263 * Returns the pixmap which backs a drawable, and the offsets to add to
264 * coordinates to make them address the same bits in the backing drawable.
267 exaGetOffscreenPixmap(DrawablePtr pDrawable
, int *xp
, int *yp
)
269 PixmapPtr pPixmap
= exaGetDrawablePixmap(pDrawable
);
271 exaGetDrawableDeltas(pDrawable
, pPixmap
, xp
, yp
);
273 if (exaPixmapHasGpuCopy(pPixmap
))
280 * Returns TRUE if the pixmap GPU copy is being accessed.
283 ExaDoPrepareAccess(PixmapPtr pPixmap
, int index
)
285 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
287 ExaScreenPriv(pScreen
);
288 ExaPixmapPriv(pPixmap
);
289 Bool has_gpu_copy
, ret
;
292 if (!(pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
))
295 if (pExaPixmap
== NULL
)
296 EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE
);
298 /* Handle repeated / nested calls. */
299 for (i
= 0; i
< EXA_NUM_PREPARE_INDICES
; i
++) {
300 if (pExaScr
->access
[i
].pixmap
== pPixmap
) {
301 pExaScr
->access
[i
].count
++;
302 return pExaScr
->access
[i
].retval
;
306 /* If slot for this index is taken, find an empty slot */
307 if (pExaScr
->access
[index
].pixmap
) {
308 for (index
= EXA_NUM_PREPARE_INDICES
- 1; index
>= 0; index
--)
309 if (!pExaScr
->access
[index
].pixmap
)
313 /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */
314 if (pPixmap
->devPrivate
.ptr
!= NULL
) {
315 EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n", pPixmap
->devPrivate
.ptr
));
318 has_gpu_copy
= exaPixmapHasGpuCopy(pPixmap
);
320 if (has_gpu_copy
&& pExaPixmap
->fb_ptr
) {
321 pPixmap
->devPrivate
.ptr
= pExaPixmap
->fb_ptr
;
325 pPixmap
->devPrivate
.ptr
= pExaPixmap
->sys_ptr
;
329 /* Store so we can handle repeated / nested calls. */
330 pExaScr
->access
[index
].pixmap
= pPixmap
;
331 pExaScr
->access
[index
].count
= 1;
336 exaWaitSync(pScreen
);
338 if (pExaScr
->info
->PrepareAccess
== NULL
)
341 if (index
>= EXA_PREPARE_AUX_DEST
&&
342 !(pExaScr
->info
->flags
& EXA_SUPPORTS_PREPARE_AUX
)) {
343 if (pExaPixmap
->score
== EXA_PIXMAP_SCORE_PINNED
)
344 FatalError("Unsupported AUX indices used on a pinned pixmap.\n");
345 exaMoveOutPixmap(pPixmap
);
350 if (!(*pExaScr
->info
->PrepareAccess
) (pPixmap
, index
)) {
351 if (pExaPixmap
->score
== EXA_PIXMAP_SCORE_PINNED
&&
352 !(pExaScr
->info
->flags
& EXA_MIXED_PIXMAPS
))
353 FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
354 exaMoveOutPixmap(pPixmap
);
362 pExaScr
->access
[index
].retval
= ret
;
367 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
369 * It deals with waiting for synchronization with the card, determining if
370 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
373 exaPrepareAccess(DrawablePtr pDrawable
, int index
)
375 PixmapPtr pPixmap
= exaGetDrawablePixmap(pDrawable
);
377 ExaScreenPriv(pDrawable
->pScreen
);
379 if (pExaScr
->prepare_access_reg
)
380 pExaScr
->prepare_access_reg(pPixmap
, index
, NULL
);
382 (void) ExaDoPrepareAccess(pPixmap
, index
);
386 * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
388 * It deals with calling the driver's FinishAccess() only if necessary.
391 exaFinishAccess(DrawablePtr pDrawable
, int index
)
393 ScreenPtr pScreen
= pDrawable
->pScreen
;
395 ExaScreenPriv(pScreen
);
396 PixmapPtr pPixmap
= exaGetDrawablePixmap(pDrawable
);
398 ExaPixmapPriv(pPixmap
);
401 if (!(pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
))
404 if (pExaPixmap
== NULL
)
405 EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
407 /* Handle repeated / nested calls. */
408 for (i
= 0; i
< EXA_NUM_PREPARE_INDICES
; i
++) {
409 if (pExaScr
->access
[i
].pixmap
== pPixmap
) {
410 if (--pExaScr
->access
[i
].count
> 0)
416 /* Catch unbalanced Prepare/FinishAccess calls. */
417 if (i
== EXA_NUM_PREPARE_INDICES
)
418 EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", pPixmap
),);
420 pExaScr
->access
[i
].pixmap
= NULL
;
422 /* We always hide the devPrivate.ptr. */
423 pPixmap
->devPrivate
.ptr
= NULL
;
425 /* Only call FinishAccess if PrepareAccess was called and succeeded. */
426 if (!pExaScr
->info
->FinishAccess
|| !pExaScr
->access
[i
].retval
)
429 if (i
>= EXA_PREPARE_AUX_DEST
&&
430 !(pExaScr
->info
->flags
& EXA_SUPPORTS_PREPARE_AUX
)) {
431 ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
432 "unsupported index EXA_PREPARE_AUX*\n");
436 (*pExaScr
->info
->FinishAccess
) (pPixmap
, i
);
440 * Helper for things common to all schemes when a pixmap is destroyed
443 exaDestroyPixmap(PixmapPtr pPixmap
)
445 ExaScreenPriv(pPixmap
->drawable
.pScreen
);
448 /* Finish access if it was prepared (e.g. pixmap created during
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
;
461 * Here begins EXA's GC code.
462 * Do not ever access the fb/mi layer directly.
466 exaValidateGC(GCPtr pGC
, unsigned long changes
, DrawablePtr pDrawable
);
469 exaDestroyGC(GCPtr pGC
);
472 exaChangeGC(GCPtr pGC
, unsigned long mask
);
475 exaCopyGC(GCPtr pGCSrc
, unsigned long mask
, GCPtr pGCDst
);
478 exaChangeClip(GCPtr pGC
, int type
, pointer pvalue
, int nrects
);
481 exaCopyClip(GCPtr pGCDst
, GCPtr pGCSrc
);
484 exaDestroyClip(GCPtr pGC
);
486 const GCFuncs exaGCFuncs
= {
497 exaValidateGC(GCPtr pGC
, unsigned long changes
, DrawablePtr pDrawable
)
499 /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
500 * Do a few smart things so fbValidateGC can do it's work.
503 ScreenPtr pScreen
= pDrawable
->pScreen
;
505 ExaScreenPriv(pScreen
);
507 PixmapPtr pTile
= NULL
;
508 Bool finish_current_tile
= FALSE
;
510 /* Either of these conditions is enough to trigger access to a tile pixmap. */
511 /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */
512 if (pGC
->fillStyle
== FillTiled
||
513 ((changes
& GCTile
) && !pGC
->tileIsPixel
)) {
514 pTile
= pGC
->tile
.pixmap
;
516 /* Sometimes tile pixmaps are swapped, you need access to:
517 * - The current tile if it depth matches.
518 * - Or the rotated tile if that one matches depth and !(changes & GCTile).
519 * - Or the current tile pixmap and a newly created one.
521 if (pTile
&& pTile
->drawable
.depth
!= pDrawable
->depth
&&
522 !(changes
& GCTile
)) {
523 PixmapPtr pRotatedTile
= fbGetRotatedPixmap(pGC
);
526 pRotatedTile
->drawable
.depth
== pDrawable
->depth
)
527 pTile
= pRotatedTile
;
529 finish_current_tile
= TRUE
; /* CreatePixmap will be called. */
534 exaPrepareAccess(&pGC
->stipple
->drawable
, EXA_PREPARE_MASK
);
536 exaPrepareAccess(&pTile
->drawable
, EXA_PREPARE_SRC
);
538 /* Calls to Create/DestroyPixmap have to be identified as special. */
539 pExaScr
->fallback_counter
++;
540 swap(pExaGC
, pGC
, funcs
);
541 (*pGC
->funcs
->ValidateGC
) (pGC
, changes
, pDrawable
);
542 swap(pExaGC
, pGC
, funcs
);
543 pExaScr
->fallback_counter
--;
546 exaFinishAccess(&pTile
->drawable
, EXA_PREPARE_SRC
);
547 if (finish_current_tile
&& pGC
->tile
.pixmap
)
548 exaFinishAccess(&pGC
->tile
.pixmap
->drawable
, EXA_PREPARE_AUX_DEST
);
550 exaFinishAccess(&pGC
->stipple
->drawable
, EXA_PREPARE_MASK
);
553 /* Is exaPrepareAccessGC() needed? */
555 exaDestroyGC(GCPtr pGC
)
558 swap(pExaGC
, pGC
, funcs
);
559 (*pGC
->funcs
->DestroyGC
) (pGC
);
560 swap(pExaGC
, pGC
, funcs
);
564 exaChangeGC(GCPtr pGC
, unsigned long mask
)
567 swap(pExaGC
, pGC
, funcs
);
568 (*pGC
->funcs
->ChangeGC
) (pGC
, mask
);
569 swap(pExaGC
, pGC
, funcs
);
573 exaCopyGC(GCPtr pGCSrc
, unsigned long mask
, GCPtr pGCDst
)
576 swap(pExaGC
, pGCDst
, funcs
);
577 (*pGCDst
->funcs
->CopyGC
) (pGCSrc
, mask
, pGCDst
);
578 swap(pExaGC
, pGCDst
, funcs
);
582 exaChangeClip(GCPtr pGC
, int type
, pointer pvalue
, int nrects
)
585 swap(pExaGC
, pGC
, funcs
);
586 (*pGC
->funcs
->ChangeClip
) (pGC
, type
, pvalue
, nrects
);
587 swap(pExaGC
, pGC
, funcs
);
591 exaCopyClip(GCPtr pGCDst
, GCPtr pGCSrc
)
594 swap(pExaGC
, pGCDst
, funcs
);
595 (*pGCDst
->funcs
->CopyClip
) (pGCDst
, pGCSrc
);
596 swap(pExaGC
, pGCDst
, funcs
);
600 exaDestroyClip(GCPtr pGC
)
603 swap(pExaGC
, pGC
, funcs
);
604 (*pGC
->funcs
->DestroyClip
) (pGC
);
605 swap(pExaGC
, pGC
, funcs
);
609 * exaCreateGC makes a new GC and hooks up its funcs handler, so that
610 * exaValidateGC() will get called.
613 exaCreateGC(GCPtr pGC
)
615 ScreenPtr pScreen
= pGC
->pScreen
;
617 ExaScreenPriv(pScreen
);
621 swap(pExaScr
, pScreen
, CreateGC
);
622 if ((ret
= (*pScreen
->CreateGC
) (pGC
))) {
623 wrap(pExaGC
, pGC
, funcs
, (GCFuncs
*) &exaGCFuncs
);
624 wrap(pExaGC
, pGC
, ops
, (GCOps
*) &exaOps
);
626 swap(pExaScr
, pScreen
, CreateGC
);
632 exaChangeWindowAttributes(WindowPtr pWin
, unsigned long mask
)
635 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
637 ExaScreenPriv(pScreen
);
639 if ((mask
& CWBackPixmap
) && pWin
->backgroundState
== BackgroundPixmap
)
640 exaPrepareAccess(&pWin
->background
.pixmap
->drawable
, EXA_PREPARE_SRC
);
642 if ((mask
& CWBorderPixmap
) && pWin
->borderIsPixel
== FALSE
)
643 exaPrepareAccess(&pWin
->border
.pixmap
->drawable
, EXA_PREPARE_MASK
);
645 pExaScr
->fallback_counter
++;
646 swap(pExaScr
, pScreen
, ChangeWindowAttributes
);
647 ret
= pScreen
->ChangeWindowAttributes(pWin
, mask
);
648 swap(pExaScr
, pScreen
, ChangeWindowAttributes
);
649 pExaScr
->fallback_counter
--;
651 if ((mask
& CWBackPixmap
) && pWin
->backgroundState
== BackgroundPixmap
)
652 exaFinishAccess(&pWin
->background
.pixmap
->drawable
, EXA_PREPARE_SRC
);
653 if ((mask
& CWBorderPixmap
) && pWin
->borderIsPixel
== FALSE
)
654 exaFinishAccess(&pWin
->border
.pixmap
->drawable
, EXA_PREPARE_MASK
);
660 exaBitmapToRegion(PixmapPtr pPix
)
663 ScreenPtr pScreen
= pPix
->drawable
.pScreen
;
665 ExaScreenPriv(pScreen
);
667 exaPrepareAccess(&pPix
->drawable
, EXA_PREPARE_SRC
);
668 swap(pExaScr
, pScreen
, BitmapToRegion
);
669 ret
= (*pScreen
->BitmapToRegion
) (pPix
);
670 swap(pExaScr
, pScreen
, BitmapToRegion
);
671 exaFinishAccess(&pPix
->drawable
, EXA_PREPARE_SRC
);
677 exaCreateScreenResources(ScreenPtr pScreen
)
679 ExaScreenPriv(pScreen
);
680 PixmapPtr pScreenPixmap
;
683 swap(pExaScr
, pScreen
, CreateScreenResources
);
684 b
= pScreen
->CreateScreenResources(pScreen
);
685 swap(pExaScr
, pScreen
, CreateScreenResources
);
690 pScreenPixmap
= pScreen
->GetScreenPixmap(pScreen
);
693 ExaPixmapPriv(pScreenPixmap
);
695 exaSetAccelBlock(pExaScr
, pExaPixmap
,
696 pScreenPixmap
->drawable
.width
,
697 pScreenPixmap
->drawable
.height
,
698 pScreenPixmap
->drawable
.bitsPerPixel
);
705 ExaBlockHandler(ScreenPtr pScreen
, pointer pTimeout
,
708 ExaScreenPriv(pScreen
);
710 /* Move any deferred results from a software fallback to the driver pixmap */
711 if (pExaScr
->deferred_mixed_pixmap
)
712 exaMoveInPixmap_mixed(pExaScr
->deferred_mixed_pixmap
);
714 unwrap(pExaScr
, pScreen
, BlockHandler
);
715 (*pScreen
->BlockHandler
) (pScreen
, pTimeout
, pReadmask
);
716 wrap(pExaScr
, pScreen
, BlockHandler
, ExaBlockHandler
);
718 /* The rest only applies to classic EXA */
719 if (pExaScr
->info
->flags
& EXA_HANDLES_PIXMAPS
)
722 /* Try and keep the offscreen memory area tidy every now and then (at most
723 * once per second) when the server has been idle for at least 100ms.
725 if (pExaScr
->numOffscreenAvailable
> 1) {
726 CARD32 now
= GetTimeInMillis();
728 pExaScr
->nextDefragment
= now
+
729 max(100, (INT32
) (pExaScr
->lastDefragment
+ 1000 - now
));
730 AdjustWaitForDelay(pTimeout
, pExaScr
->nextDefragment
- now
);
735 ExaWakeupHandler(ScreenPtr pScreen
, unsigned long result
,
738 ExaScreenPriv(pScreen
);
740 unwrap(pExaScr
, pScreen
, WakeupHandler
);
741 (*pScreen
->WakeupHandler
) (pScreen
, result
, pReadmask
);
742 wrap(pExaScr
, pScreen
, WakeupHandler
, ExaWakeupHandler
);
744 if (result
== 0 && pExaScr
->numOffscreenAvailable
> 1) {
745 CARD32 now
= GetTimeInMillis();
747 if ((int) (now
- pExaScr
->nextDefragment
) > 0) {
748 ExaOffscreenDefragment(pScreen
);
749 pExaScr
->lastDefragment
= now
;
755 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
756 * screen private, before calling down to the next CloseSccreen.
759 exaCloseScreen(ScreenPtr pScreen
)
761 ExaScreenPriv(pScreen
);
762 PictureScreenPtr ps
= GetPictureScreenIfSet(pScreen
);
764 if (ps
->Glyphs
== exaGlyphs
)
765 exaGlyphsFini(pScreen
);
767 if (pScreen
->BlockHandler
== ExaBlockHandler
)
768 unwrap(pExaScr
, pScreen
, BlockHandler
);
769 if (pScreen
->WakeupHandler
== ExaWakeupHandler
)
770 unwrap(pExaScr
, pScreen
, WakeupHandler
);
771 unwrap(pExaScr
, pScreen
, CreateGC
);
772 unwrap(pExaScr
, pScreen
, CloseScreen
);
773 unwrap(pExaScr
, pScreen
, GetImage
);
774 unwrap(pExaScr
, pScreen
, GetSpans
);
775 if (pExaScr
->SavedCreatePixmap
)
776 unwrap(pExaScr
, pScreen
, CreatePixmap
);
777 if (pExaScr
->SavedDestroyPixmap
)
778 unwrap(pExaScr
, pScreen
, DestroyPixmap
);
779 if (pExaScr
->SavedModifyPixmapHeader
)
780 unwrap(pExaScr
, pScreen
, ModifyPixmapHeader
);
781 unwrap(pExaScr
, pScreen
, CopyWindow
);
782 unwrap(pExaScr
, pScreen
, ChangeWindowAttributes
);
783 unwrap(pExaScr
, pScreen
, BitmapToRegion
);
784 unwrap(pExaScr
, pScreen
, CreateScreenResources
);
785 if (pExaScr
->SavedSharePixmapBacking
)
786 unwrap(pExaScr
, pScreen
, SharePixmapBacking
);
787 if (pExaScr
->SavedSetSharedPixmapBacking
)
788 unwrap(pExaScr
, pScreen
, SetSharedPixmapBacking
);
789 unwrap(pExaScr
, ps
, Composite
);
790 if (pExaScr
->SavedGlyphs
)
791 unwrap(pExaScr
, ps
, Glyphs
);
792 unwrap(pExaScr
, ps
, Trapezoids
);
793 unwrap(pExaScr
, ps
, Triangles
);
794 unwrap(pExaScr
, ps
, AddTraps
);
798 return (*pScreen
->CloseScreen
) (pScreen
);
802 * This function allocates a driver structure for EXA drivers to fill in. By
803 * having EXA allocate the structure, the driver structure can be extended
804 * without breaking ABI between EXA and the drivers. The driver's
805 * responsibility is to check beforehand that the EXA module has a matching
806 * major number and sufficient minor. Drivers are responsible for freeing the
807 * driver structure using free().
809 * @return a newly allocated, zero-filled driver structure
814 return calloc(1, sizeof(ExaDriverRec
));
818 * @param pScreen screen being initialized
819 * @param pScreenInfo EXA driver record
821 * exaDriverInit sets up EXA given a driver record filled in by the driver.
822 * pScreenInfo should have been allocated by exaDriverAlloc(). See the
823 * comments in _ExaDriver for what must be filled in and what is optional.
825 * @return TRUE if EXA was successfully initialized.
828 exaDriverInit(ScreenPtr pScreen
, ExaDriverPtr pScreenInfo
)
830 ExaScreenPrivPtr pExaScr
;
836 if (pScreenInfo
->exa_major
!= EXA_VERSION_MAJOR
||
837 pScreenInfo
->exa_minor
> EXA_VERSION_MINOR
) {
838 LogMessage(X_ERROR
, "EXA(%d): driver's EXA version requirements "
839 "(%d.%d) are incompatible with EXA version (%d.%d)\n",
841 pScreenInfo
->exa_major
, pScreenInfo
->exa_minor
,
842 EXA_VERSION_MAJOR
, EXA_VERSION_MINOR
);
846 if (!pScreenInfo
->CreatePixmap
&& !pScreenInfo
->CreatePixmap2
) {
847 if (!pScreenInfo
->memoryBase
) {
848 LogMessage(X_ERROR
, "EXA(%d): ExaDriverRec::memoryBase "
849 "must be non-zero\n", pScreen
->myNum
);
853 if (!pScreenInfo
->memorySize
) {
854 LogMessage(X_ERROR
, "EXA(%d): ExaDriverRec::memorySize must be "
855 "non-zero\n", pScreen
->myNum
);
859 if (pScreenInfo
->offScreenBase
> pScreenInfo
->memorySize
) {
860 LogMessage(X_ERROR
, "EXA(%d): ExaDriverRec::offScreenBase must "
861 "be <= ExaDriverRec::memorySize\n", pScreen
->myNum
);
866 if (!pScreenInfo
->PrepareSolid
) {
867 LogMessage(X_ERROR
, "EXA(%d): ExaDriverRec::PrepareSolid must be "
868 "non-NULL\n", pScreen
->myNum
);
872 if (!pScreenInfo
->PrepareCopy
) {
873 LogMessage(X_ERROR
, "EXA(%d): ExaDriverRec::PrepareCopy must be "
874 "non-NULL\n", pScreen
->myNum
);
878 if (!pScreenInfo
->WaitMarker
) {
879 LogMessage(X_ERROR
, "EXA(%d): ExaDriverRec::WaitMarker must be "
880 "non-NULL\n", pScreen
->myNum
);
884 /* If the driver doesn't set any max pitch values, we'll just assume
885 * that there's a limitation by pixels, and that it's the same as
888 * We want maxPitchPixels or maxPitchBytes to be set so we can check
889 * pixmaps against the max pitch in exaCreatePixmap() -- it matters
890 * whether a pixmap is rejected because of its pitch or
891 * because of its width.
893 if (!pScreenInfo
->maxPitchPixels
&& !pScreenInfo
->maxPitchBytes
) {
894 pScreenInfo
->maxPitchPixels
= pScreenInfo
->maxX
;
897 ps
= GetPictureScreenIfSet(pScreen
);
899 if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec
, PRIVATE_SCREEN
, 0)) {
900 LogMessage(X_WARNING
, "EXA(%d): Failed to register screen private\n",
905 pExaScr
= calloc(sizeof(ExaScreenPrivRec
), 1);
907 LogMessage(X_WARNING
, "EXA(%d): Failed to allocate screen private\n",
912 pExaScr
->info
= pScreenInfo
;
914 dixSetPrivate(&pScreen
->devPrivates
, exaScreenPrivateKey
, pExaScr
);
916 pExaScr
->migration
= ExaMigrationAlways
;
918 exaDDXDriverInit(pScreen
);
920 if (!dixRegisterScreenSpecificPrivateKey
921 (pScreen
, &pExaScr
->gcPrivateKeyRec
, PRIVATE_GC
, sizeof(ExaGCPrivRec
))) {
922 LogMessage(X_WARNING
, "EXA(%d): Failed to allocate GC private\n",
928 * Replace various fb screen functions
930 if ((pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
) &&
931 (!(pExaScr
->info
->flags
& EXA_HANDLES_PIXMAPS
) ||
932 (pExaScr
->info
->flags
& EXA_MIXED_PIXMAPS
)))
933 wrap(pExaScr
, pScreen
, BlockHandler
, ExaBlockHandler
);
934 if ((pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
) &&
935 !(pExaScr
->info
->flags
& EXA_HANDLES_PIXMAPS
))
936 wrap(pExaScr
, pScreen
, WakeupHandler
, ExaWakeupHandler
);
937 wrap(pExaScr
, pScreen
, CreateGC
, exaCreateGC
);
938 wrap(pExaScr
, pScreen
, CloseScreen
, exaCloseScreen
);
939 wrap(pExaScr
, pScreen
, GetImage
, exaGetImage
);
940 wrap(pExaScr
, pScreen
, GetSpans
, ExaCheckGetSpans
);
941 wrap(pExaScr
, pScreen
, CopyWindow
, exaCopyWindow
);
942 wrap(pExaScr
, pScreen
, ChangeWindowAttributes
, exaChangeWindowAttributes
);
943 wrap(pExaScr
, pScreen
, BitmapToRegion
, exaBitmapToRegion
);
944 wrap(pExaScr
, pScreen
, CreateScreenResources
, exaCreateScreenResources
);
947 wrap(pExaScr
, ps
, Composite
, exaComposite
);
948 if (pScreenInfo
->PrepareComposite
) {
949 wrap(pExaScr
, ps
, Glyphs
, exaGlyphs
);
952 wrap(pExaScr
, ps
, Glyphs
, ExaCheckGlyphs
);
954 wrap(pExaScr
, ps
, Trapezoids
, exaTrapezoids
);
955 wrap(pExaScr
, ps
, Triangles
, exaTriangles
);
956 wrap(pExaScr
, ps
, AddTraps
, ExaCheckAddTraps
);
961 * Don't allow shared pixmaps.
963 ShmRegisterFuncs(pScreen
, &exaShmFuncs
);
966 * Hookup offscreen pixmaps
968 if (pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
) {
969 if (!dixRegisterScreenSpecificPrivateKey
970 (pScreen
, &pExaScr
->pixmapPrivateKeyRec
, PRIVATE_PIXMAP
,
971 sizeof(ExaPixmapPrivRec
))) {
972 LogMessage(X_WARNING
,
973 "EXA(%d): Failed to allocate pixmap private\n",
977 if (pExaScr
->info
->flags
& EXA_HANDLES_PIXMAPS
) {
978 if (pExaScr
->info
->flags
& EXA_MIXED_PIXMAPS
) {
979 wrap(pExaScr
, pScreen
, CreatePixmap
, exaCreatePixmap_mixed
);
980 wrap(pExaScr
, pScreen
, DestroyPixmap
, exaDestroyPixmap_mixed
);
981 wrap(pExaScr
, pScreen
, ModifyPixmapHeader
,
982 exaModifyPixmapHeader_mixed
);
983 wrap(pExaScr
, pScreen
, SharePixmapBacking
, exaSharePixmapBacking_mixed
);
984 wrap(pExaScr
, pScreen
, SetSharedPixmapBacking
, exaSetSharedPixmapBacking_mixed
);
986 pExaScr
->do_migration
= exaDoMigration_mixed
;
987 pExaScr
->pixmap_has_gpu_copy
= exaPixmapHasGpuCopy_mixed
;
988 pExaScr
->do_move_in_pixmap
= exaMoveInPixmap_mixed
;
989 pExaScr
->do_move_out_pixmap
= NULL
;
990 pExaScr
->prepare_access_reg
= exaPrepareAccessReg_mixed
;
993 wrap(pExaScr
, pScreen
, CreatePixmap
, exaCreatePixmap_driver
);
994 wrap(pExaScr
, pScreen
, DestroyPixmap
, exaDestroyPixmap_driver
);
995 wrap(pExaScr
, pScreen
, ModifyPixmapHeader
,
996 exaModifyPixmapHeader_driver
);
997 pExaScr
->do_migration
= NULL
;
998 pExaScr
->pixmap_has_gpu_copy
= exaPixmapHasGpuCopy_driver
;
999 pExaScr
->do_move_in_pixmap
= NULL
;
1000 pExaScr
->do_move_out_pixmap
= NULL
;
1001 pExaScr
->prepare_access_reg
= NULL
;
1005 wrap(pExaScr
, pScreen
, CreatePixmap
, exaCreatePixmap_classic
);
1006 wrap(pExaScr
, pScreen
, DestroyPixmap
, exaDestroyPixmap_classic
);
1007 wrap(pExaScr
, pScreen
, ModifyPixmapHeader
,
1008 exaModifyPixmapHeader_classic
);
1009 pExaScr
->do_migration
= exaDoMigration_classic
;
1010 pExaScr
->pixmap_has_gpu_copy
= exaPixmapHasGpuCopy_classic
;
1011 pExaScr
->do_move_in_pixmap
= exaMoveInPixmap_classic
;
1012 pExaScr
->do_move_out_pixmap
= exaMoveOutPixmap_classic
;
1013 pExaScr
->prepare_access_reg
= exaPrepareAccessReg_classic
;
1015 if (!(pExaScr
->info
->flags
& EXA_HANDLES_PIXMAPS
)) {
1016 LogMessage(X_INFO
, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
1018 pExaScr
->info
->memorySize
-
1019 pExaScr
->info
->offScreenBase
);
1022 LogMessage(X_INFO
, "EXA(%d): Driver allocated offscreen pixmaps\n",
1028 LogMessage(X_INFO
, "EXA(%d): No offscreen pixmaps\n", pScreen
->myNum
);
1030 if (!(pExaScr
->info
->flags
& EXA_HANDLES_PIXMAPS
)) {
1031 DBG_PIXMAP(("============== %ld < %ld\n", pExaScr
->info
->offScreenBase
,
1032 pExaScr
->info
->memorySize
));
1033 if (pExaScr
->info
->offScreenBase
< pExaScr
->info
->memorySize
) {
1034 if (!exaOffscreenInit(pScreen
)) {
1035 LogMessage(X_WARNING
,
1036 "EXA(%d): Offscreen pixmap setup failed\n",
1043 if (ps
->Glyphs
== exaGlyphs
)
1044 exaGlyphsInit(pScreen
);
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");
1055 if (pScreenInfo
->UploadToScreen
!= NULL
) {
1056 LogMessage(X_INFO
, " UploadToScreen\n");
1058 if (pScreenInfo
->DownloadFromScreen
!= NULL
) {
1059 LogMessage(X_INFO
, " DownloadFromScreen\n");
1066 * exaDriverFini tears down EXA on a given screen.
1068 * @param pScreen screen being torn down.
1071 exaDriverFini(ScreenPtr pScreen
)
1073 /*right now does nothing */
1077 * exaMarkSync() should be called after any asynchronous drawing by the hardware.
1079 * @param pScreen screen which drawing occurred on
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.
1088 exaMarkSync(ScreenPtr pScreen
)
1090 ExaScreenPriv(pScreen
);
1092 pExaScr
->info
->needsSync
= TRUE
;
1093 if (pExaScr
->info
->MarkSync
!= NULL
) {
1094 pExaScr
->info
->lastMarker
= (*pExaScr
->info
->MarkSync
) (pScreen
);
1099 * exaWaitSync() ensures that all drawing has been completed.
1101 * @param pScreen screen being synchronized.
1103 * Calls down into the driver to ensure that all previous drawing has completed.
1104 * It should always be called before relying on the framebuffer contents
1105 * reflecting previous drawing, from a CPU perspective.
1108 exaWaitSync(ScreenPtr pScreen
)
1110 ExaScreenPriv(pScreen
);
1112 if (pExaScr
->info
->needsSync
&& !pExaScr
->swappedOut
) {
1113 (*pExaScr
->info
->WaitMarker
) (pScreen
, pExaScr
->info
->lastMarker
);
1114 pExaScr
->info
->needsSync
= FALSE
;
1119 * Performs migration of the pixmaps according to the operation information
1120 * provided in pixmaps and can_accel and the migration scheme chosen in the
1124 exaDoMigration(ExaMigrationPtr pixmaps
, int npixmaps
, Bool can_accel
)
1126 ScreenPtr pScreen
= pixmaps
[0].pPix
->drawable
.pScreen
;
1128 ExaScreenPriv(pScreen
);
1130 if (!(pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
))
1133 if (pExaScr
->do_migration
)
1134 (*pExaScr
->do_migration
) (pixmaps
, npixmaps
, can_accel
);
1138 exaMoveInPixmap(PixmapPtr pPixmap
)
1140 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
1142 ExaScreenPriv(pScreen
);
1144 if (!(pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
))
1147 if (pExaScr
->do_move_in_pixmap
)
1148 (*pExaScr
->do_move_in_pixmap
) (pPixmap
);
1152 exaMoveOutPixmap(PixmapPtr pPixmap
)
1154 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
1156 ExaScreenPriv(pScreen
);
1158 if (!(pExaScr
->info
->flags
& EXA_OFFSCREEN_PIXMAPS
))
1161 if (pExaScr
->do_move_out_pixmap
)
1162 (*pExaScr
->do_move_out_pixmap
) (pPixmap
);