2 * Copyright © 2006 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * Eric Anholt <eric@anholt.net>
25 * Michel Dänzer <michel@tungstengraphics.com>
29 #ifdef HAVE_DIX_CONFIG_H
30 #include <dix-config.h>
39 #define DBG_MIGRATE(a) ErrorF a
41 #define DBG_MIGRATE(a)
45 * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
46 * and exaCopyDirtyToFb both needed to do this loop.
49 exaMemcpyBox(PixmapPtr pPixmap
, BoxPtr pbox
, CARD8
*src
, int src_pitch
,
50 CARD8
*dst
, int dst_pitch
)
52 int i
, cpp
= pPixmap
->drawable
.bitsPerPixel
/ 8;
53 int bytes
= (pbox
->x2
- pbox
->x1
) * cpp
;
55 src
+= pbox
->y1
* src_pitch
+ pbox
->x1
* cpp
;
56 dst
+= pbox
->y1
* dst_pitch
+ pbox
->x1
* cpp
;
58 for (i
= pbox
->y2
- pbox
->y1
; i
; i
--) {
59 memcpy(dst
, src
, bytes
);
66 * Returns TRUE if the pixmap is dirty (has been modified in its current
67 * location compared to the other), or lacks a private for tracking
71 exaPixmapIsDirty(PixmapPtr pPix
)
75 if (pExaPixmap
== NULL
)
76 EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE
);
78 if (!pExaPixmap
->pDamage
)
81 return RegionNotEmpty(DamageRegion(pExaPixmap
->pDamage
)) ||
82 !RegionEqual(&pExaPixmap
->validSys
, &pExaPixmap
->validFB
);
86 * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
87 * to be considered "should be in framebuffer". That's just anything that has
88 * had more acceleration than fallbacks, or has no score yet.
90 * Only valid if using a migration scheme that tracks score.
93 exaPixmapShouldBeInFB(PixmapPtr pPix
)
97 if (exaPixmapIsPinned(pPix
))
100 return pExaPixmap
->score
>= 0;
104 * If the pixmap is currently dirty, this copies at least the dirty area from
105 * FB to system or vice versa. Both areas must be allocated.
108 exaCopyDirty(ExaMigrationPtr migrate
, RegionPtr pValidDst
, RegionPtr pValidSrc
,
109 Bool (*transfer
) (PixmapPtr pPix
, int x
, int y
, int w
, int h
,
110 char *sys
, int sys_pitch
), int fallback_index
,
111 void (*sync
) (ScreenPtr pScreen
))
113 PixmapPtr pPixmap
= migrate
->pPix
;
115 ExaPixmapPriv(pPixmap
);
116 RegionPtr damage
= DamageRegion(pExaPixmap
->pDamage
);
118 Bool save_use_gpu_copy
;
122 Bool access_prepared
= FALSE
;
123 Bool need_sync
= FALSE
;
125 /* Damaged bits are valid in current copy but invalid in other one */
126 if (pExaPixmap
->use_gpu_copy
) {
127 RegionUnion(&pExaPixmap
->validFB
, &pExaPixmap
->validFB
, damage
);
128 RegionSubtract(&pExaPixmap
->validSys
, &pExaPixmap
->validSys
, damage
);
131 RegionUnion(&pExaPixmap
->validSys
, &pExaPixmap
->validSys
, damage
);
132 RegionSubtract(&pExaPixmap
->validFB
, &pExaPixmap
->validFB
, damage
);
137 /* Copy bits valid in source but not in destination */
138 RegionNull(&CopyReg
);
139 RegionSubtract(&CopyReg
, pValidSrc
, pValidDst
);
141 if (migrate
->as_dst
) {
142 ExaScreenPriv(pPixmap
->drawable
.pScreen
);
144 /* XXX: The pending damage region will be marked as damaged after the
145 * operation, so it should serve as an upper bound for the region that
146 * needs to be synchronized for the operation. Unfortunately, this
147 * causes corruption in some cases, e.g. when starting compiz. See
148 * https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
150 if (pExaScr
->optimize_migration
) {
151 RegionPtr pending_damage
= DamagePendingRegion(pExaPixmap
->pDamage
);
154 if (RegionNil(pending_damage
)) {
155 static Bool firsttime
= TRUE
;
158 ErrorF("%s: Pending damage region empty!\n", __func__
);
164 /* Try to prevent destination valid region from growing too many
165 * rects by filling it up to the extents of the union of the
166 * destination valid region and the pending damage region.
168 if (RegionNumRects(pValidDst
) > 10) {
170 BoxPtr pValidExt
, pDamageExt
;
173 pValidExt
= RegionExtents(pValidDst
);
174 pDamageExt
= RegionExtents(pending_damage
);
176 box
.x1
= min(pValidExt
->x1
, pDamageExt
->x1
);
177 box
.y1
= min(pValidExt
->y1
, pDamageExt
->y1
);
178 box
.x2
= max(pValidExt
->x2
, pDamageExt
->x2
);
179 box
.y2
= max(pValidExt
->y2
, pDamageExt
->y2
);
181 RegionInit(&closure
, &box
, 0);
182 RegionIntersect(&CopyReg
, &CopyReg
, &closure
);
185 RegionIntersect(&CopyReg
, &CopyReg
, pending_damage
);
188 /* The caller may provide a region to be subtracted from the calculated
189 * dirty region. This is to avoid migration of bits that don't
190 * contribute to the result of the operation.
193 RegionSubtract(&CopyReg
, &CopyReg
, migrate
->pReg
);
196 /* The caller may restrict the region to be migrated for source pixmaps
197 * to what's relevant for the operation.
200 RegionIntersect(&CopyReg
, &CopyReg
, migrate
->pReg
);
203 pBox
= RegionRects(&CopyReg
);
204 nbox
= RegionNumRects(&CopyReg
);
206 save_use_gpu_copy
= pExaPixmap
->use_gpu_copy
;
207 save_pitch
= pPixmap
->devKind
;
208 pExaPixmap
->use_gpu_copy
= TRUE
;
209 pPixmap
->devKind
= pExaPixmap
->fb_pitch
;
212 pBox
->x1
= max(pBox
->x1
, 0);
213 pBox
->y1
= max(pBox
->y1
, 0);
214 pBox
->x2
= min(pBox
->x2
, pPixmap
->drawable
.width
);
215 pBox
->y2
= min(pBox
->y2
, pPixmap
->drawable
.height
);
217 if (pBox
->x1
>= pBox
->x2
|| pBox
->y1
>= pBox
->y2
)
220 if (!transfer
|| !transfer(pPixmap
,
224 (char *) (pExaPixmap
->sys_ptr
225 + pBox
->y1
* pExaPixmap
->sys_pitch
228 pPixmap
->drawable
.bitsPerPixel
/
229 8), pExaPixmap
->sys_pitch
)) {
230 if (!access_prepared
) {
231 ExaDoPrepareAccess(pPixmap
, fallback_index
);
232 access_prepared
= TRUE
;
234 if (fallback_index
== EXA_PREPARE_DEST
) {
235 exaMemcpyBox(pPixmap
, pBox
,
236 pExaPixmap
->sys_ptr
, pExaPixmap
->sys_pitch
,
237 pPixmap
->devPrivate
.ptr
, pPixmap
->devKind
);
240 exaMemcpyBox(pPixmap
, pBox
,
241 pPixmap
->devPrivate
.ptr
, pPixmap
->devKind
,
242 pExaPixmap
->sys_ptr
, pExaPixmap
->sys_pitch
);
251 pExaPixmap
->use_gpu_copy
= save_use_gpu_copy
;
252 pPixmap
->devKind
= save_pitch
;
254 /* Try to prevent source valid region from growing too many rects by
255 * removing parts of it which are also in the destination valid region.
256 * Removing anything beyond that would lead to data loss.
258 if (RegionNumRects(pValidSrc
) > 20)
259 RegionSubtract(pValidSrc
, pValidSrc
, pValidDst
);
261 /* The copied bits are now valid in destination */
262 RegionUnion(pValidDst
, pValidDst
, &CopyReg
);
264 RegionUninit(&CopyReg
);
267 exaFinishAccess(&pPixmap
->drawable
, fallback_index
);
268 else if (need_sync
&& sync
)
269 sync(pPixmap
->drawable
.pScreen
);
273 * If the pixmap is currently dirty, this copies at least the dirty area from
274 * the framebuffer memory copy to the system memory copy. Both areas must be
278 exaCopyDirtyToSys(ExaMigrationPtr migrate
)
280 PixmapPtr pPixmap
= migrate
->pPix
;
282 ExaScreenPriv(pPixmap
->drawable
.pScreen
);
283 ExaPixmapPriv(pPixmap
);
285 exaCopyDirty(migrate
, &pExaPixmap
->validSys
, &pExaPixmap
->validFB
,
286 pExaScr
->info
->DownloadFromScreen
, EXA_PREPARE_SRC
,
291 * If the pixmap is currently dirty, this copies at least the dirty area from
292 * the system memory copy to the framebuffer memory copy. Both areas must be
296 exaCopyDirtyToFb(ExaMigrationPtr migrate
)
298 PixmapPtr pPixmap
= migrate
->pPix
;
300 ExaScreenPriv(pPixmap
->drawable
.pScreen
);
301 ExaPixmapPriv(pPixmap
);
303 exaCopyDirty(migrate
, &pExaPixmap
->validFB
, &pExaPixmap
->validSys
,
304 pExaScr
->info
->UploadToScreen
, EXA_PREPARE_DEST
, NULL
);
308 * Allocates a framebuffer copy of the pixmap if necessary, and then copies
309 * any necessary pixmap data into the framebuffer copy and points the pixmap at
312 * Note that when first allocated, a pixmap will have FALSE dirty flag.
313 * This is intentional because pixmap data starts out undefined. So if we move
314 * it in due to the first operation against it being accelerated, it will have
315 * undefined framebuffer contents that we didn't have to upload. If we do
316 * moveouts (and moveins) after the first movein, then we will only have to copy
317 * back and forth if the pixmap was written to after the last synchronization of
318 * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away)
319 * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
320 * all the data, since it's almost surely all valid now.
323 exaDoMoveInPixmap(ExaMigrationPtr migrate
)
325 PixmapPtr pPixmap
= migrate
->pPix
;
326 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
328 ExaScreenPriv(pScreen
);
329 ExaPixmapPriv(pPixmap
);
331 /* If we're VT-switched away, no touching card memory allowed. */
332 if (pExaScr
->swappedOut
)
335 /* If we're not allowed to move, then fail. */
336 if (exaPixmapIsPinned(pPixmap
))
339 /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of
340 * fragility in EXA, and <8bpp is probably not used enough any more to care
341 * (at least, not in acceleratd paths).
343 if (pPixmap
->drawable
.bitsPerPixel
< 8)
346 if (pExaPixmap
->accel_blocked
)
349 if (pExaPixmap
->area
== NULL
) {
351 exaOffscreenAlloc(pScreen
, pExaPixmap
->fb_size
,
352 pExaScr
->info
->pixmapOffsetAlign
, FALSE
,
353 exaPixmapSave
, (pointer
) pPixmap
);
354 if (pExaPixmap
->area
== NULL
)
357 pExaPixmap
->fb_ptr
= (CARD8
*) pExaScr
->info
->memoryBase
+
358 pExaPixmap
->area
->offset
;
361 exaCopyDirtyToFb(migrate
);
363 if (exaPixmapHasGpuCopy(pPixmap
))
366 DBG_MIGRATE(("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap
,
367 (ExaGetPixmapPriv(pPixmap
)->area
?
368 ExaGetPixmapPriv(pPixmap
)->area
->offset
: 0),
369 pPixmap
->drawable
.width
,
370 pPixmap
->drawable
.height
,
371 exaPixmapIsDirty(pPixmap
) ? 'd' : 'c'));
373 pExaPixmap
->use_gpu_copy
= TRUE
;
375 pPixmap
->devKind
= pExaPixmap
->fb_pitch
;
376 pPixmap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
380 exaMoveInPixmap_classic(PixmapPtr pPixmap
)
382 static ExaMigrationRec migrate
= {.as_dst
= FALSE
,.as_src
= TRUE
,
386 migrate
.pPix
= pPixmap
;
387 exaDoMoveInPixmap(&migrate
);
391 * Switches the current active location of the pixmap to system memory, copying
392 * updated data out if necessary.
395 exaDoMoveOutPixmap(ExaMigrationPtr migrate
)
397 PixmapPtr pPixmap
= migrate
->pPix
;
399 ExaPixmapPriv(pPixmap
);
401 if (!pExaPixmap
->area
|| exaPixmapIsPinned(pPixmap
))
404 exaCopyDirtyToSys(migrate
);
406 if (exaPixmapHasGpuCopy(pPixmap
)) {
408 DBG_MIGRATE(("<- %p (%p) (%dx%d) (%c)\n", pPixmap
,
409 (void *) (ExaGetPixmapPriv(pPixmap
)->area
?
410 ExaGetPixmapPriv(pPixmap
)->area
->offset
: 0),
411 pPixmap
->drawable
.width
,
412 pPixmap
->drawable
.height
,
413 exaPixmapIsDirty(pPixmap
) ? 'd' : 'c'));
415 pExaPixmap
->use_gpu_copy
= FALSE
;
417 pPixmap
->devKind
= pExaPixmap
->sys_pitch
;
418 pPixmap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
423 exaMoveOutPixmap_classic(PixmapPtr pPixmap
)
425 static ExaMigrationRec migrate
= {.as_dst
= FALSE
,.as_src
= TRUE
,
429 migrate
.pPix
= pPixmap
;
430 exaDoMoveOutPixmap(&migrate
);
434 * Copies out important pixmap data and removes references to framebuffer area.
435 * Called when the memory manager decides it's time to kick the pixmap out of
436 * framebuffer entirely.
439 exaPixmapSave(ScreenPtr pScreen
, ExaOffscreenArea
* area
)
441 PixmapPtr pPixmap
= area
->privData
;
443 ExaPixmapPriv(pPixmap
);
445 exaMoveOutPixmap(pPixmap
);
447 pExaPixmap
->fb_ptr
= NULL
;
448 pExaPixmap
->area
= NULL
;
450 /* Mark all FB bits as invalid, so all valid system bits get copied to FB
452 RegionEmpty(&pExaPixmap
->validFB
);
456 * For the "greedy" migration scheme, pushes the pixmap toward being located in
457 * framebuffer memory.
460 exaMigrateTowardFb(ExaMigrationPtr migrate
)
462 PixmapPtr pPixmap
= migrate
->pPix
;
464 ExaPixmapPriv(pPixmap
);
466 if (pExaPixmap
->score
== EXA_PIXMAP_SCORE_PINNED
) {
467 DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
472 DBG_MIGRATE(("UseScreen %p score %d\n",
473 (pointer
) pPixmap
, pExaPixmap
->score
));
475 if (pExaPixmap
->score
== EXA_PIXMAP_SCORE_INIT
) {
476 exaDoMoveInPixmap(migrate
);
477 pExaPixmap
->score
= 0;
480 if (pExaPixmap
->score
< EXA_PIXMAP_SCORE_MAX
)
483 if (pExaPixmap
->score
>= EXA_PIXMAP_SCORE_MOVE_IN
&&
484 !exaPixmapHasGpuCopy(pPixmap
)) {
485 exaDoMoveInPixmap(migrate
);
488 if (exaPixmapHasGpuCopy(pPixmap
)) {
489 exaCopyDirtyToFb(migrate
);
490 ExaOffscreenMarkUsed(pPixmap
);
493 exaCopyDirtyToSys(migrate
);
497 * For the "greedy" migration scheme, pushes the pixmap toward being located in
501 exaMigrateTowardSys(ExaMigrationPtr migrate
)
503 PixmapPtr pPixmap
= migrate
->pPix
;
505 ExaPixmapPriv(pPixmap
);
507 DBG_MIGRATE(("UseMem: %p score %d\n", (pointer
) pPixmap
,
510 if (pExaPixmap
->score
== EXA_PIXMAP_SCORE_PINNED
)
513 if (pExaPixmap
->score
== EXA_PIXMAP_SCORE_INIT
)
514 pExaPixmap
->score
= 0;
516 if (pExaPixmap
->score
> EXA_PIXMAP_SCORE_MIN
)
519 if (pExaPixmap
->score
<= EXA_PIXMAP_SCORE_MOVE_OUT
&& pExaPixmap
->area
)
520 exaDoMoveOutPixmap(migrate
);
522 if (exaPixmapHasGpuCopy(pPixmap
)) {
523 exaCopyDirtyToFb(migrate
);
524 ExaOffscreenMarkUsed(pPixmap
);
527 exaCopyDirtyToSys(migrate
);
531 * If the pixmap has both a framebuffer and system memory copy, this function
532 * asserts that both of them are the same.
535 exaAssertNotDirty(PixmapPtr pPixmap
)
537 ExaPixmapPriv(pPixmap
);
540 int dst_pitch
, src_pitch
, cpp
, y
, nbox
, save_pitch
;
542 Bool ret
= TRUE
, save_use_gpu_copy
;
544 if (exaPixmapIsPinned(pPixmap
) || pExaPixmap
->area
== NULL
)
547 RegionNull(&ValidReg
);
548 RegionIntersect(&ValidReg
, &pExaPixmap
->validFB
, &pExaPixmap
->validSys
);
549 nbox
= RegionNumRects(&ValidReg
);
554 pBox
= RegionRects(&ValidReg
);
556 dst_pitch
= pExaPixmap
->sys_pitch
;
557 src_pitch
= pExaPixmap
->fb_pitch
;
558 cpp
= pPixmap
->drawable
.bitsPerPixel
/ 8;
560 save_use_gpu_copy
= pExaPixmap
->use_gpu_copy
;
561 save_pitch
= pPixmap
->devKind
;
562 pExaPixmap
->use_gpu_copy
= TRUE
;
563 pPixmap
->devKind
= pExaPixmap
->fb_pitch
;
565 if (!ExaDoPrepareAccess(pPixmap
, EXA_PREPARE_SRC
))
571 pBox
->x1
= max(pBox
->x1
, 0);
572 pBox
->y1
= max(pBox
->y1
, 0);
573 pBox
->x2
= min(pBox
->x2
, pPixmap
->drawable
.width
);
574 pBox
->y2
= min(pBox
->y2
, pPixmap
->drawable
.height
);
576 if (pBox
->x1
>= pBox
->x2
|| pBox
->y1
>= pBox
->y2
)
579 rowbytes
= (pBox
->x2
- pBox
->x1
) * cpp
;
581 (CARD8
*) pPixmap
->devPrivate
.ptr
+ pBox
->y1
* src_pitch
+
583 dst
= pExaPixmap
->sys_ptr
+ pBox
->y1
* dst_pitch
+ pBox
->x1
* cpp
;
585 for (y
= pBox
->y1
; y
< pBox
->y2
;
586 y
++, src
+= src_pitch
, dst
+= dst_pitch
) {
587 if (memcmp(dst
, src
, rowbytes
) != 0) {
589 exaPixmapDirty(pPixmap
, pBox
->x1
, pBox
->y1
, pBox
->x2
, pBox
->y2
);
596 exaFinishAccess(&pPixmap
->drawable
, EXA_PREPARE_SRC
);
598 pExaPixmap
->use_gpu_copy
= save_use_gpu_copy
;
599 pPixmap
->devKind
= save_pitch
;
602 RegionUninit(&ValidReg
);
607 * Performs migration of the pixmaps according to the operation information
608 * provided in pixmaps and can_accel and the migration scheme chosen in the
612 exaDoMigration_classic(ExaMigrationPtr pixmaps
, int npixmaps
, Bool can_accel
)
614 ScreenPtr pScreen
= pixmaps
[0].pPix
->drawable
.pScreen
;
616 ExaScreenPriv(pScreen
);
619 /* If this debugging flag is set, check each pixmap for whether it is marked
620 * as clean, and if so, actually check if that's the case. This should help
621 * catch issues with failing to mark a drawable as dirty. While it will
622 * catch them late (after the operation happened), it at least explains what
623 * went wrong, and instrumenting the code to find what operation happened
624 * to the pixmap last shouldn't be hard.
626 if (pExaScr
->checkDirtyCorrectness
) {
627 for (i
= 0; i
< npixmaps
; i
++) {
628 if (!exaPixmapIsDirty(pixmaps
[i
].pPix
) &&
629 !exaAssertNotDirty(pixmaps
[i
].pPix
))
630 ErrorF("%s: Pixmap %d dirty but not marked as such!\n",
634 /* If anything is pinned in system memory, we won't be able to
637 for (i
= 0; i
< npixmaps
; i
++) {
638 if (exaPixmapIsPinned(pixmaps
[i
].pPix
) &&
639 !exaPixmapHasGpuCopy(pixmaps
[i
].pPix
)) {
640 EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps
[i
].pPix
,
641 pixmaps
[i
].pPix
->drawable
.width
,
642 pixmaps
[i
].pPix
->drawable
.height
));
648 if (pExaScr
->migration
== ExaMigrationSmart
) {
649 /* If we've got something as a destination that we shouldn't cause to
650 * become newly dirtied, take the unaccelerated route.
652 for (i
= 0; i
< npixmaps
; i
++) {
653 if (pixmaps
[i
].as_dst
&& !exaPixmapShouldBeInFB(pixmaps
[i
].pPix
) &&
654 !exaPixmapIsDirty(pixmaps
[i
].pPix
)) {
655 for (i
= 0; i
< npixmaps
; i
++) {
656 if (!exaPixmapIsDirty(pixmaps
[i
].pPix
))
657 exaDoMoveOutPixmap(pixmaps
+ i
);
663 /* If we aren't going to accelerate, then we migrate everybody toward
664 * system memory, and kick out if it's free.
667 for (i
= 0; i
< npixmaps
; i
++) {
668 exaMigrateTowardSys(pixmaps
+ i
);
669 if (!exaPixmapIsDirty(pixmaps
[i
].pPix
))
670 exaDoMoveOutPixmap(pixmaps
+ i
);
675 /* Finally, the acceleration path. Move them all in. */
676 for (i
= 0; i
< npixmaps
; i
++) {
677 exaMigrateTowardFb(pixmaps
+ i
);
678 exaDoMoveInPixmap(pixmaps
+ i
);
681 else if (pExaScr
->migration
== ExaMigrationGreedy
) {
682 /* If we can't accelerate, either because the driver can't or because one of
683 * the pixmaps is pinned in system memory, then we migrate everybody toward
686 * We also migrate toward system if all pixmaps involved are currently in
687 * system memory -- this can mitigate thrashing when there are significantly
688 * more pixmaps active than would fit in memory.
690 * If not, then we migrate toward FB so that hopefully acceleration can
694 for (i
= 0; i
< npixmaps
; i
++)
695 exaMigrateTowardSys(pixmaps
+ i
);
699 for (i
= 0; i
< npixmaps
; i
++) {
700 if (exaPixmapHasGpuCopy(pixmaps
[i
].pPix
)) {
701 /* Found one in FB, so move all to FB. */
702 for (j
= 0; j
< npixmaps
; j
++)
703 exaMigrateTowardFb(pixmaps
+ i
);
708 /* Nobody's in FB, so move all away from FB. */
709 for (i
= 0; i
< npixmaps
; i
++)
710 exaMigrateTowardSys(pixmaps
+ i
);
712 else if (pExaScr
->migration
== ExaMigrationAlways
) {
713 /* Always move the pixmaps out if we can't accelerate. If we can
714 * accelerate, try to move them all in. If that fails, then move them
718 for (i
= 0; i
< npixmaps
; i
++)
719 exaDoMoveOutPixmap(pixmaps
+ i
);
723 /* Now, try to move them all into FB */
724 for (i
= 0; i
< npixmaps
; i
++) {
725 exaDoMoveInPixmap(pixmaps
+ i
);
728 /* If we couldn't fit everything in, abort */
729 for (i
= 0; i
< npixmaps
; i
++) {
730 if (!exaPixmapHasGpuCopy(pixmaps
[i
].pPix
)) {
735 /* Yay, everything has a gpu copy, mark memory as used */
736 for (i
= 0; i
< npixmaps
; i
++) {
737 ExaOffscreenMarkUsed(pixmaps
[i
].pPix
);
743 exaPrepareAccessReg_classic(PixmapPtr pPixmap
, int index
, RegionPtr pReg
)
745 ExaMigrationRec pixmaps
[1];
747 if (index
== EXA_PREPARE_DEST
|| index
== EXA_PREPARE_AUX_DEST
) {
748 pixmaps
[0].as_dst
= TRUE
;
749 pixmaps
[0].as_src
= FALSE
;
752 pixmaps
[0].as_dst
= FALSE
;
753 pixmaps
[0].as_src
= TRUE
;
755 pixmaps
[0].pPix
= pPixmap
;
756 pixmaps
[0].pReg
= pReg
;
758 exaDoMigration(pixmaps
, 1, FALSE
);
760 (void) ExaDoPrepareAccess(pPixmap
, index
);