Imported Upstream version 1.15.1
[deb_xorg-server.git] / exa / exa.c
CommitLineData
a09e091a
JB
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;
41
42#ifdef MITSHM
43static ShmFuncs exaShmFuncs = { NULL, NULL };
44#endif
45
46/**
47 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
48 * the beginning of the given pixmap.
49 *
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.
55 */
56unsigned long
57exaGetPixmapOffset(PixmapPtr pPix)
58{
59 ExaScreenPriv(pPix->drawable.pScreen);
60 ExaPixmapPriv(pPix);
61
62 return (CARD8 *) pExaPixmap->fb_ptr - pExaScr->info->memoryBase;
63}
64
65void *
66exaGetPixmapDriverPrivate(PixmapPtr pPix)
67{
68 ExaPixmapPriv(pPix);
69
70 return pExaPixmap->driverPriv;
71}
72
73/**
74 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap.
75 *
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.
78 */
79unsigned long
80exaGetPixmapPitch(PixmapPtr pPix)
81{
82 return pPix->devKind;
83}
84
85/**
86 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video
87 * memory. Only valid when the pixmap is currently in framebuffer.
88 */
89unsigned long
90exaGetPixmapSize(PixmapPtr pPix)
91{
92 ExaPixmapPrivPtr pExaPixmap;
93
94 pExaPixmap = ExaGetPixmapPriv(pPix);
95 if (pExaPixmap != NULL)
96 return pExaPixmap->fb_size;
97 return 0;
98}
99
100/**
101 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable.
102 *
103 * @param pDrawable the drawable being requested.
104 *
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.
110 */
111PixmapPtr
112exaGetDrawablePixmap(DrawablePtr pDrawable)
113{
114 if (pDrawable->type == DRAWABLE_WINDOW)
115 return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable);
116 else
117 return (PixmapPtr) pDrawable;
118}
119
120/**
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
123 * windows.
124 */
125void
126exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap, int *xp, int *yp)
127{
128#ifdef COMPOSITE
129 if (pDrawable->type == DRAWABLE_WINDOW) {
130 *xp = -pPixmap->screen_x;
131 *yp = -pPixmap->screen_y;
132 return;
133 }
134#endif
135
136 *xp = 0;
137 *yp = 0;
138}
139
140/**
141 * exaPixmapDirty() marks a pixmap as dirty, allowing for
142 * optimizations in pixmap migration when no changes have occurred.
143 */
144void
145exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2)
146{
147 BoxRec box;
148 RegionRec region;
149
150 box.x1 = max(x1, 0);
151 box.y1 = max(y1, 0);
152 box.x2 = min(x2, pPix->drawable.width);
153 box.y2 = min(y2, pPix->drawable.height);
154
155 if (box.x1 >= box.x2 || box.y1 >= box.y2)
156 return;
157
158 RegionInit(&region, &box, 1);
159 DamageDamageRegion(&pPix->drawable, &region);
160 RegionUninit(&region);
161}
162
163static int
164exaLog2(int val)
165{
166 int bits;
167
168 if (val <= 0)
169 return 0;
170 for (bits = 0; val != 0; bits++)
171 val >>= 1;
172 return bits - 1;
173}
174
175void
176exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
177 int w, int h, int bpp)
178{
179 pExaPixmap->accel_blocked = 0;
180
181 if (pExaScr->info->maxPitchPixels) {
182 int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp);
183
184 if (pExaPixmap->fb_pitch > max_pitch)
185 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
186 }
187
188 if (pExaScr->info->maxPitchBytes &&
189 pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes)
190 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
191
192 if (w > pExaScr->info->maxX)
193 pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH;
194
195 if (h > pExaScr->info->maxY)
196 pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT;
197}
198
199void
200exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
201 int w, int h, int bpp)
202{
203 if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
204 pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp);
205 else
206 pExaPixmap->fb_pitch = bits_to_bytes(w * bpp);
207
208 pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
209 pExaScr->info->pixmapPitchAlign);
210}
211
212/**
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).
216 */
217Bool
218exaPixmapIsPinned(PixmapPtr pPix)
219{
220 ExaPixmapPriv(pPix);
221
222 if (pExaPixmap == NULL)
223 EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
224
225 return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
226}
227
228/**
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
232 * with the CPU.
233 *
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.
237 *
238 * @return TRUE if the given drawable is in framebuffer memory.
239 */
240Bool
241exaPixmapHasGpuCopy(PixmapPtr pPixmap)
242{
243 ScreenPtr pScreen = pPixmap->drawable.pScreen;
244
245 ExaScreenPriv(pScreen);
246
247 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
248 return FALSE;
249
250 return (*pExaScr->pixmap_has_gpu_copy) (pPixmap);
251}
252
253/**
254 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy().
255 */
256Bool
257exaDrawableIsOffscreen(DrawablePtr pDrawable)
258{
259 return exaPixmapHasGpuCopy(exaGetDrawablePixmap(pDrawable));
260}
261
262/**
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.
265 */
266PixmapPtr
267exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp)
268{
269 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
270
271 exaGetDrawableDeltas(pDrawable, pPixmap, xp, yp);
272
273 if (exaPixmapHasGpuCopy(pPixmap))
274 return pPixmap;
275 else
276 return NULL;
277}
278
279/**
280 * Returns TRUE if the pixmap GPU copy is being accessed.
281 */
282Bool
283ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
284{
285 ScreenPtr pScreen = pPixmap->drawable.pScreen;
286
287 ExaScreenPriv(pScreen);
288 ExaPixmapPriv(pPixmap);
289 Bool has_gpu_copy, ret;
290 int i;
291
292 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
293 return FALSE;
294
295 if (pExaPixmap == NULL)
296 EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE);
297
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;
303 }
304 }
305
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)
310 break;
311 }
312
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));
316 }
317
318 has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
319
320 if (has_gpu_copy && pExaPixmap->fb_ptr) {
321 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
322 ret = TRUE;
323 }
324 else {
325 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
326 ret = FALSE;
327 }
328
329 /* Store so we can handle repeated / nested calls. */
330 pExaScr->access[index].pixmap = pPixmap;
331 pExaScr->access[index].count = 1;
332
333 if (!has_gpu_copy)
334 goto out;
335
336 exaWaitSync(pScreen);
337
338 if (pExaScr->info->PrepareAccess == NULL)
339 goto out;
340
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);
346 ret = FALSE;
347 goto out;
348 }
349
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);
355 ret = FALSE;
356 goto out;
357 }
358
359 ret = TRUE;
360
361 out:
362 pExaScr->access[index].retval = ret;
363 return ret;
364}
365
366/**
367 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
368 *
369 * It deals with waiting for synchronization with the card, determining if
370 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
371 */
372void
373exaPrepareAccess(DrawablePtr pDrawable, int index)
374{
375 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
376
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
395 ExaScreenPriv(pScreen);
396 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
397
398 ExaPixmapPriv(pPixmap);
399 int i;
400
401 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
402 return;
403
404 if (pExaPixmap == NULL)
405 EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
406
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)
411 return;
412 break;
413 }
414 }
415
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),);
419
420 pExaScr->access[i].pixmap = NULL;
421
422 /* We always hide the devPrivate.ptr. */
423 pPixmap->devPrivate.ptr = NULL;
424
425 /* Only call FinishAccess if PrepareAccess was called and succeeded. */
426 if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval)
427 return;
428
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");
433 return;
434 }
435
436 (*pExaScr->info->FinishAccess) (pPixmap, i);
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 * Here begins EXA's GC code.
462 * Do not ever access the fb/mi layer directly.
463 */
464
465static void
466 exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable);
467
468static void
469 exaDestroyGC(GCPtr pGC);
470
471static void
472 exaChangeGC(GCPtr pGC, unsigned long mask);
473
474static void
475 exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
476
477static void
478 exaChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
479
480static void
481 exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
482
483static void
484 exaDestroyClip(GCPtr pGC);
485
486const GCFuncs exaGCFuncs = {
487 exaValidateGC,
488 exaChangeGC,
489 exaCopyGC,
490 exaDestroyGC,
491 exaChangeClip,
492 exaDestroyClip,
493 exaCopyClip
494};
495
496static void
497exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
498{
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.
501 */
502
503 ScreenPtr pScreen = pDrawable->pScreen;
504
505 ExaScreenPriv(pScreen);
506 ExaGCPriv(pGC);
507 PixmapPtr pTile = NULL;
508 Bool finish_current_tile = FALSE;
509
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;
515
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.
520 */
521 if (pTile && pTile->drawable.depth != pDrawable->depth &&
522 !(changes & GCTile)) {
523 PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC);
524
525 if (pRotatedTile &&
526 pRotatedTile->drawable.depth == pDrawable->depth)
527 pTile = pRotatedTile;
528 else
529 finish_current_tile = TRUE; /* CreatePixmap will be called. */
530 }
531 }
532
533 if (pGC->stipple)
534 exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
535 if (pTile)
536 exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC);
537
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--;
544
545 if (pTile)
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);
549 if (pGC->stipple)
550 exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
551}
552
553/* Is exaPrepareAccessGC() needed? */
554static void
555exaDestroyGC(GCPtr pGC)
556{
557 ExaGCPriv(pGC);
558 swap(pExaGC, pGC, funcs);
559 (*pGC->funcs->DestroyGC) (pGC);
560 swap(pExaGC, pGC, funcs);
561}
562
563static void
564exaChangeGC(GCPtr pGC, unsigned long mask)
565{
566 ExaGCPriv(pGC);
567 swap(pExaGC, pGC, funcs);
568 (*pGC->funcs->ChangeGC) (pGC, mask);
569 swap(pExaGC, pGC, funcs);
570}
571
572static void
573exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
574{
575 ExaGCPriv(pGCDst);
576 swap(pExaGC, pGCDst, funcs);
577 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
578 swap(pExaGC, pGCDst, funcs);
579}
580
581static void
582exaChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
583{
584 ExaGCPriv(pGC);
585 swap(pExaGC, pGC, funcs);
586 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
587 swap(pExaGC, pGC, funcs);
588}
589
590static void
591exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
592{
593 ExaGCPriv(pGCDst);
594 swap(pExaGC, pGCDst, funcs);
595 (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc);
596 swap(pExaGC, pGCDst, funcs);
597}
598
599static void
600exaDestroyClip(GCPtr pGC)
601{
602 ExaGCPriv(pGC);
603 swap(pExaGC, pGC, funcs);
604 (*pGC->funcs->DestroyClip) (pGC);
605 swap(pExaGC, pGC, funcs);
606}
607
608/**
609 * exaCreateGC makes a new GC and hooks up its funcs handler, so that
610 * exaValidateGC() will get called.
611 */
612static int
613exaCreateGC(GCPtr pGC)
614{
615 ScreenPtr pScreen = pGC->pScreen;
616
617 ExaScreenPriv(pScreen);
618 ExaGCPriv(pGC);
619 Bool ret;
620
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);
625 }
626 swap(pExaScr, pScreen, CreateGC);
627
628 return ret;
629}
630
631static Bool
632exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
633{
634 Bool ret;
635 ScreenPtr pScreen = pWin->drawable.pScreen;
636
637 ExaScreenPriv(pScreen);
638
639 if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
640 exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
641
642 if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
643 exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
644
645 pExaScr->fallback_counter++;
646 swap(pExaScr, pScreen, ChangeWindowAttributes);
647 ret = pScreen->ChangeWindowAttributes(pWin, mask);
648 swap(pExaScr, pScreen, ChangeWindowAttributes);
649 pExaScr->fallback_counter--;
650
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);
655
656 return ret;
657}
658
659static RegionPtr
660exaBitmapToRegion(PixmapPtr pPix)
661{
662 RegionPtr ret;
663 ScreenPtr pScreen = pPix->drawable.pScreen;
664
665 ExaScreenPriv(pScreen);
666
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);
672
673 return ret;
674}
675
676static Bool
677exaCreateScreenResources(ScreenPtr pScreen)
678{
679 ExaScreenPriv(pScreen);
680 PixmapPtr pScreenPixmap;
681 Bool b;
682
683 swap(pExaScr, pScreen, CreateScreenResources);
684 b = pScreen->CreateScreenResources(pScreen);
685 swap(pExaScr, pScreen, CreateScreenResources);
686
687 if (!b)
688 return FALSE;
689
690 pScreenPixmap = pScreen->GetScreenPixmap(pScreen);
691
692 if (pScreenPixmap) {
693 ExaPixmapPriv(pScreenPixmap);
694
695 exaSetAccelBlock(pExaScr, pExaPixmap,
696 pScreenPixmap->drawable.width,
697 pScreenPixmap->drawable.height,
698 pScreenPixmap->drawable.bitsPerPixel);
699 }
700
701 return TRUE;
702}
703
704static void
705ExaBlockHandler(ScreenPtr pScreen, pointer pTimeout,
706 pointer pReadmask)
707{
708 ExaScreenPriv(pScreen);
709
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);
713
714 unwrap(pExaScr, pScreen, BlockHandler);
715 (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
716 wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler);
717
718 /* The rest only applies to classic EXA */
719 if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
720 return;
721
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.
724 */
725 if (pExaScr->numOffscreenAvailable > 1) {
726 CARD32 now = GetTimeInMillis();
727
728 pExaScr->nextDefragment = now +
729 max(100, (INT32) (pExaScr->lastDefragment + 1000 - now));
730 AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now);
731 }
732}
733
734static void
735ExaWakeupHandler(ScreenPtr pScreen, unsigned long result,
736 pointer pReadmask)
737{
738 ExaScreenPriv(pScreen);
739
740 unwrap(pExaScr, pScreen, WakeupHandler);
741 (*pScreen->WakeupHandler) (pScreen, result, pReadmask);
742 wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler);
743
744 if (result == 0 && pExaScr->numOffscreenAvailable > 1) {
745 CARD32 now = GetTimeInMillis();
746
747 if ((int) (now - pExaScr->nextDefragment) > 0) {
748 ExaOffscreenDefragment(pScreen);
749 pExaScr->lastDefragment = now;
750 }
751 }
752}
753
754/**
755 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
756 * screen private, before calling down to the next CloseSccreen.
757 */
758static Bool
759exaCloseScreen(ScreenPtr pScreen)
760{
761 ExaScreenPriv(pScreen);
762 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
763
764 if (ps->Glyphs == exaGlyphs)
765 exaGlyphsFini(pScreen);
766
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);
795
796 free(pExaScr);
797
798 return (*pScreen->CloseScreen) (pScreen);
799}
800
801/**
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().
808 *
809 * @return a newly allocated, zero-filled driver structure
810 */
811ExaDriverPtr
812exaDriverAlloc(void)
813{
814 return calloc(1, sizeof(ExaDriverRec));
815}
816
817/**
818 * @param pScreen screen being initialized
819 * @param pScreenInfo EXA driver record
820 *
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.
824 *
825 * @return TRUE if EXA was successfully initialized.
826 */
827Bool
828exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo)
829{
830 ExaScreenPrivPtr pExaScr;
831 PictureScreenPtr ps;
832
833 if (!pScreenInfo)
834 return FALSE;
835
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",
840 pScreen->myNum,
841 pScreenInfo->exa_major, pScreenInfo->exa_minor,
842 EXA_VERSION_MAJOR, EXA_VERSION_MINOR);
843 return FALSE;
844 }
845
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);
850 return FALSE;
851 }
852
853 if (!pScreenInfo->memorySize) {
854 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be "
855 "non-zero\n", pScreen->myNum);
856 return FALSE;
857 }
858
859 if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) {
860 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must "
861 "be <= ExaDriverRec::memorySize\n", pScreen->myNum);
862 return FALSE;
863 }
864 }
865
866 if (!pScreenInfo->PrepareSolid) {
867 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be "
868 "non-NULL\n", pScreen->myNum);
869 return FALSE;
870 }
871
872 if (!pScreenInfo->PrepareCopy) {
873 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be "
874 "non-NULL\n", pScreen->myNum);
875 return FALSE;
876 }
877
878 if (!pScreenInfo->WaitMarker) {
879 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be "
880 "non-NULL\n", pScreen->myNum);
881 return FALSE;
882 }
883
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
886 * maxX.
887 *
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.
892 */
893 if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) {
894 pScreenInfo->maxPitchPixels = pScreenInfo->maxX;
895 }
896
897 ps = GetPictureScreenIfSet(pScreen);
898
899 if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) {
900 LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n",
901 pScreen->myNum);
902 return FALSE;
903 }
904
905 pExaScr = calloc(sizeof(ExaScreenPrivRec), 1);
906 if (!pExaScr) {
907 LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
908 pScreen->myNum);
909 return FALSE;
910 }
911
912 pExaScr->info = pScreenInfo;
913
914 dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr);
915
916 pExaScr->migration = ExaMigrationAlways;
917
918 exaDDXDriverInit(pScreen);
919
920 if (!dixRegisterScreenSpecificPrivateKey
921 (pScreen, &pExaScr->gcPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) {
922 LogMessage(X_WARNING, "EXA(%d): Failed to allocate GC private\n",
923 pScreen->myNum);
924 return FALSE;
925 }
926
927 /*
928 * Replace various fb screen functions
929 */
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);
945
946 if (ps) {
947 wrap(pExaScr, ps, Composite, exaComposite);
948 if (pScreenInfo->PrepareComposite) {
949 wrap(pExaScr, ps, Glyphs, exaGlyphs);
950 }
951 else {
952 wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs);
953 }
954 wrap(pExaScr, ps, Trapezoids, exaTrapezoids);
955 wrap(pExaScr, ps, Triangles, exaTriangles);
956 wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps);
957 }
958
959#ifdef MITSHM
960 /*
961 * Don't allow shared pixmaps.
962 */
963 ShmRegisterFuncs(pScreen, &exaShmFuncs);
964#endif
965 /*
966 * Hookup offscreen pixmaps
967 */
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",
974 pScreen->myNum);
975 return FALSE;
976 }
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);
985
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;
991 }
992 else {
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;
1002 }
1003 }
1004 else {
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;
1014 }
1015 if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
1016 LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
1017 pScreen->myNum,
1018 pExaScr->info->memorySize -
1019 pExaScr->info->offScreenBase);
1020 }
1021 else {
1022 LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n",
1023 pScreen->myNum);
1024
1025 }
1026 }
1027 else
1028 LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum);
1029
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",
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
1088exaMarkSync(ScreenPtr pScreen)
1089{
1090 ExaScreenPriv(pScreen);
1091
1092 pExaScr->info->needsSync = TRUE;
1093 if (pExaScr->info->MarkSync != NULL) {
1094 pExaScr->info->lastMarker = (*pExaScr->info->MarkSync) (pScreen);
1095 }
1096}
1097
1098/**
1099 * exaWaitSync() ensures that all drawing has been completed.
1100 *
1101 * @param pScreen screen being synchronized.
1102 *
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.
1106 */
1107void
1108exaWaitSync(ScreenPtr pScreen)
1109{
1110 ExaScreenPriv(pScreen);
1111
1112 if (pExaScr->info->needsSync && !pExaScr->swappedOut) {
1113 (*pExaScr->info->WaitMarker) (pScreen, pExaScr->info->lastMarker);
1114 pExaScr->info->needsSync = FALSE;
1115 }
1116}
1117
1118/**
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
1121 * config file.
1122 */
1123void
1124exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
1125{
1126 ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
1127
1128 ExaScreenPriv(pScreen);
1129
1130 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
1131 return;
1132
1133 if (pExaScr->do_migration)
1134 (*pExaScr->do_migration) (pixmaps, npixmaps, can_accel);
1135}
1136
1137void
1138exaMoveInPixmap(PixmapPtr pPixmap)
1139{
1140 ScreenPtr pScreen = pPixmap->drawable.pScreen;
1141
1142 ExaScreenPriv(pScreen);
1143
1144 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
1145 return;
1146
1147 if (pExaScr->do_move_in_pixmap)
1148 (*pExaScr->do_move_in_pixmap) (pPixmap);
1149}
1150
1151void
1152exaMoveOutPixmap(PixmapPtr pPixmap)
1153{
1154 ScreenPtr pScreen = pPixmap->drawable.pScreen;
1155
1156 ExaScreenPriv(pScreen);
1157
1158 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
1159 return;
1160
1161 if (pExaScr->do_move_out_pixmap)
1162 (*pExaScr->do_move_out_pixmap) (pPixmap);
1163}