Ignore the coding style change commit during git blame
[xserver.git] / exa / exa_migration_classic.c
blob82578957863f353fada003051e090fe33c026307
1 /*
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
13 * Software.
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
21 * SOFTWARE.
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 * Michel Dänzer <michel@tungstengraphics.com>
29 #include <dix-config.h>
31 #include <string.h>
33 #include "exa_priv.h"
34 #include "exa.h"
36 #if DEBUG_MIGRATE
37 #define DBG_MIGRATE(a) ErrorF a
38 #else
39 #define DBG_MIGRATE(a)
40 #endif
42 /**
43 * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
44 * and exaCopyDirtyToFb both needed to do this loop.
46 static void
47 exaMemcpyBox(PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
48 CARD8 *dst, int dst_pitch)
50 int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
51 int bytes = (pbox->x2 - pbox->x1) * cpp;
53 src += pbox->y1 * src_pitch + pbox->x1 * cpp;
54 dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
56 for (i = pbox->y2 - pbox->y1; i; i--) {
57 memcpy(dst, src, bytes);
58 src += src_pitch;
59 dst += dst_pitch;
63 /**
64 * Returns TRUE if the pixmap is dirty (has been modified in its current
65 * location compared to the other), or lacks a private for tracking
66 * dirtiness.
68 static Bool
69 exaPixmapIsDirty(PixmapPtr pPix)
71 ExaPixmapPriv(pPix);
73 if (pExaPixmap == NULL)
74 EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
76 if (!pExaPixmap->pDamage)
77 return FALSE;
79 return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
80 !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
83 /**
84 * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
85 * to be considered "should be in framebuffer". That's just anything that has
86 * had more acceleration than fallbacks, or has no score yet.
88 * Only valid if using a migration scheme that tracks score.
90 static Bool
91 exaPixmapShouldBeInFB(PixmapPtr pPix)
93 ExaPixmapPriv(pPix);
95 if (exaPixmapIsPinned(pPix))
96 return TRUE;
98 return pExaPixmap->score >= 0;
102 * If the pixmap is currently dirty, this copies at least the dirty area from
103 * FB to system or vice versa. Both areas must be allocated.
105 static void
106 exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
107 Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
108 char *sys, int sys_pitch), int fallback_index,
109 void (*sync) (ScreenPtr pScreen))
111 PixmapPtr pPixmap = migrate->pPix;
113 ExaPixmapPriv(pPixmap);
114 RegionPtr damage = DamageRegion(pExaPixmap->pDamage);
115 RegionRec CopyReg;
116 Bool save_use_gpu_copy;
117 int save_pitch;
118 BoxPtr pBox;
119 int nbox;
120 Bool access_prepared = FALSE;
121 Bool need_sync = FALSE;
123 /* Damaged bits are valid in current copy but invalid in other one */
124 if (pExaPixmap->use_gpu_copy) {
125 RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
126 RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
128 else {
129 RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
130 RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
133 RegionEmpty(damage);
135 /* Copy bits valid in source but not in destination */
136 RegionNull(&CopyReg);
137 RegionSubtract(&CopyReg, pValidSrc, pValidDst);
139 if (migrate->as_dst) {
140 ExaScreenPriv(pPixmap->drawable.pScreen);
142 /* XXX: The pending damage region will be marked as damaged after the
143 * operation, so it should serve as an upper bound for the region that
144 * needs to be synchronized for the operation. Unfortunately, this
145 * causes corruption in some cases, e.g. when starting compiz. See
146 * https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
148 if (pExaScr->optimize_migration) {
149 RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
151 #if DEBUG_MIGRATE
152 if (RegionNil(pending_damage)) {
153 static Bool firsttime = TRUE;
155 if (firsttime) {
156 ErrorF("%s: Pending damage region empty!\n", __func__);
157 firsttime = FALSE;
160 #endif
162 /* Try to prevent destination valid region from growing too many
163 * rects by filling it up to the extents of the union of the
164 * destination valid region and the pending damage region.
166 if (RegionNumRects(pValidDst) > 10) {
167 BoxRec box;
168 BoxPtr pValidExt, pDamageExt;
169 RegionRec closure;
171 pValidExt = RegionExtents(pValidDst);
172 pDamageExt = RegionExtents(pending_damage);
174 box.x1 = min(pValidExt->x1, pDamageExt->x1);
175 box.y1 = min(pValidExt->y1, pDamageExt->y1);
176 box.x2 = max(pValidExt->x2, pDamageExt->x2);
177 box.y2 = max(pValidExt->y2, pDamageExt->y2);
179 RegionInit(&closure, &box, 0);
180 RegionIntersect(&CopyReg, &CopyReg, &closure);
182 else
183 RegionIntersect(&CopyReg, &CopyReg, pending_damage);
186 /* The caller may provide a region to be subtracted from the calculated
187 * dirty region. This is to avoid migration of bits that don't
188 * contribute to the result of the operation.
190 if (migrate->pReg)
191 RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
193 else {
194 /* The caller may restrict the region to be migrated for source pixmaps
195 * to what's relevant for the operation.
197 if (migrate->pReg)
198 RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
201 pBox = RegionRects(&CopyReg);
202 nbox = RegionNumRects(&CopyReg);
204 save_use_gpu_copy = pExaPixmap->use_gpu_copy;
205 save_pitch = pPixmap->devKind;
206 pExaPixmap->use_gpu_copy = TRUE;
207 pPixmap->devKind = pExaPixmap->fb_pitch;
209 while (nbox--) {
210 pBox->x1 = max(pBox->x1, 0);
211 pBox->y1 = max(pBox->y1, 0);
212 pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
213 pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
215 if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
216 continue;
218 if (!transfer || !transfer(pPixmap,
219 pBox->x1, pBox->y1,
220 pBox->x2 - pBox->x1,
221 pBox->y2 - pBox->y1,
222 (char *) (pExaPixmap->sys_ptr
223 + pBox->y1 * pExaPixmap->sys_pitch
225 pBox->x1 *
226 pPixmap->drawable.bitsPerPixel /
227 8), pExaPixmap->sys_pitch)) {
228 if (!access_prepared) {
229 ExaDoPrepareAccess(pPixmap, fallback_index);
230 access_prepared = TRUE;
232 if (fallback_index == EXA_PREPARE_DEST) {
233 exaMemcpyBox(pPixmap, pBox,
234 pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
235 pPixmap->devPrivate.ptr, pPixmap->devKind);
237 else {
238 exaMemcpyBox(pPixmap, pBox,
239 pPixmap->devPrivate.ptr, pPixmap->devKind,
240 pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
243 else
244 need_sync = TRUE;
246 pBox++;
249 pExaPixmap->use_gpu_copy = save_use_gpu_copy;
250 pPixmap->devKind = save_pitch;
252 /* Try to prevent source valid region from growing too many rects by
253 * removing parts of it which are also in the destination valid region.
254 * Removing anything beyond that would lead to data loss.
256 if (RegionNumRects(pValidSrc) > 20)
257 RegionSubtract(pValidSrc, pValidSrc, pValidDst);
259 /* The copied bits are now valid in destination */
260 RegionUnion(pValidDst, pValidDst, &CopyReg);
262 RegionUninit(&CopyReg);
264 if (access_prepared)
265 exaFinishAccess(&pPixmap->drawable, fallback_index);
266 else if (need_sync && sync)
267 sync(pPixmap->drawable.pScreen);
271 * If the pixmap is currently dirty, this copies at least the dirty area from
272 * the framebuffer memory copy to the system memory copy. Both areas must be
273 * allocated.
275 void
276 exaCopyDirtyToSys(ExaMigrationPtr migrate)
278 PixmapPtr pPixmap = migrate->pPix;
280 ExaScreenPriv(pPixmap->drawable.pScreen);
281 ExaPixmapPriv(pPixmap);
283 exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
284 pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
285 exaWaitSync);
289 * If the pixmap is currently dirty, this copies at least the dirty area from
290 * the system memory copy to the framebuffer memory copy. Both areas must be
291 * allocated.
293 void
294 exaCopyDirtyToFb(ExaMigrationPtr migrate)
296 PixmapPtr pPixmap = migrate->pPix;
298 ExaScreenPriv(pPixmap->drawable.pScreen);
299 ExaPixmapPriv(pPixmap);
301 exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
302 pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
306 * Allocates a framebuffer copy of the pixmap if necessary, and then copies
307 * any necessary pixmap data into the framebuffer copy and points the pixmap at
308 * it.
310 * Note that when first allocated, a pixmap will have FALSE dirty flag.
311 * This is intentional because pixmap data starts out undefined. So if we move
312 * it in due to the first operation against it being accelerated, it will have
313 * undefined framebuffer contents that we didn't have to upload. If we do
314 * moveouts (and moveins) after the first movein, then we will only have to copy
315 * back and forth if the pixmap was written to after the last synchronization of
316 * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away)
317 * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
318 * all the data, since it's almost surely all valid now.
320 static void
321 exaDoMoveInPixmap(ExaMigrationPtr migrate)
323 PixmapPtr pPixmap = migrate->pPix;
324 ScreenPtr pScreen = pPixmap->drawable.pScreen;
326 ExaScreenPriv(pScreen);
327 ExaPixmapPriv(pPixmap);
329 /* If we're VT-switched away, no touching card memory allowed. */
330 if (pExaScr->swappedOut)
331 return;
333 /* If we're not allowed to move, then fail. */
334 if (exaPixmapIsPinned(pPixmap))
335 return;
337 /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of
338 * fragility in EXA, and <8bpp is probably not used enough any more to care
339 * (at least, not in acceleratd paths).
341 if (pPixmap->drawable.bitsPerPixel < 8)
342 return;
344 if (pExaPixmap->accel_blocked)
345 return;
347 if (pExaPixmap->area == NULL) {
348 pExaPixmap->area =
349 exaOffscreenAlloc(pScreen, pExaPixmap->fb_size,
350 pExaScr->info->pixmapOffsetAlign, FALSE,
351 exaPixmapSave, (void *) pPixmap);
352 if (pExaPixmap->area == NULL)
353 return;
355 pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
356 pExaPixmap->area->offset;
359 exaCopyDirtyToFb(migrate);
361 if (exaPixmapHasGpuCopy(pPixmap))
362 return;
364 DBG_MIGRATE(("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
365 (ExaGetPixmapPriv(pPixmap)->area ?
366 ExaGetPixmapPriv(pPixmap)->area->offset : 0),
367 pPixmap->drawable.width,
368 pPixmap->drawable.height,
369 exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
371 pExaPixmap->use_gpu_copy = TRUE;
373 pPixmap->devKind = pExaPixmap->fb_pitch;
374 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
377 void
378 exaMoveInPixmap_classic(PixmapPtr pPixmap)
380 static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
381 .pReg = NULL
384 migrate.pPix = pPixmap;
385 exaDoMoveInPixmap(&migrate);
389 * Switches the current active location of the pixmap to system memory, copying
390 * updated data out if necessary.
392 static void
393 exaDoMoveOutPixmap(ExaMigrationPtr migrate)
395 PixmapPtr pPixmap = migrate->pPix;
397 ExaPixmapPriv(pPixmap);
399 if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
400 return;
402 exaCopyDirtyToSys(migrate);
404 if (exaPixmapHasGpuCopy(pPixmap)) {
406 DBG_MIGRATE(("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
407 (void *) (ExaGetPixmapPriv(pPixmap)->area ?
408 ExaGetPixmapPriv(pPixmap)->area->offset : 0),
409 pPixmap->drawable.width,
410 pPixmap->drawable.height,
411 exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
413 pExaPixmap->use_gpu_copy = FALSE;
415 pPixmap->devKind = pExaPixmap->sys_pitch;
416 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
420 void
421 exaMoveOutPixmap_classic(PixmapPtr pPixmap)
423 static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
424 .pReg = NULL
427 migrate.pPix = pPixmap;
428 exaDoMoveOutPixmap(&migrate);
432 * Copies out important pixmap data and removes references to framebuffer area.
433 * Called when the memory manager decides it's time to kick the pixmap out of
434 * framebuffer entirely.
436 void
437 exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area)
439 PixmapPtr pPixmap = area->privData;
441 ExaPixmapPriv(pPixmap);
443 exaMoveOutPixmap(pPixmap);
445 pExaPixmap->fb_ptr = NULL;
446 pExaPixmap->area = NULL;
448 /* Mark all FB bits as invalid, so all valid system bits get copied to FB
449 * next time */
450 RegionEmpty(&pExaPixmap->validFB);
454 * For the "greedy" migration scheme, pushes the pixmap toward being located in
455 * framebuffer memory.
457 static void
458 exaMigrateTowardFb(ExaMigrationPtr migrate)
460 PixmapPtr pPixmap = migrate->pPix;
462 ExaPixmapPriv(pPixmap);
464 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
465 DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
466 (void *) pPixmap));
467 return;
470 DBG_MIGRATE(("UseScreen %p score %d\n",
471 (void *) pPixmap, pExaPixmap->score));
473 if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
474 exaDoMoveInPixmap(migrate);
475 pExaPixmap->score = 0;
478 if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
479 pExaPixmap->score++;
481 if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
482 !exaPixmapHasGpuCopy(pPixmap)) {
483 exaDoMoveInPixmap(migrate);
486 if (exaPixmapHasGpuCopy(pPixmap)) {
487 exaCopyDirtyToFb(migrate);
488 ExaOffscreenMarkUsed(pPixmap);
490 else
491 exaCopyDirtyToSys(migrate);
495 * For the "greedy" migration scheme, pushes the pixmap toward being located in
496 * system memory.
498 static void
499 exaMigrateTowardSys(ExaMigrationPtr migrate)
501 PixmapPtr pPixmap = migrate->pPix;
503 ExaPixmapPriv(pPixmap);
505 DBG_MIGRATE(("UseMem: %p score %d\n", (void *) pPixmap,
506 pExaPixmap->score));
508 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
509 return;
511 if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
512 pExaPixmap->score = 0;
514 if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
515 pExaPixmap->score--;
517 if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
518 exaDoMoveOutPixmap(migrate);
520 if (exaPixmapHasGpuCopy(pPixmap)) {
521 exaCopyDirtyToFb(migrate);
522 ExaOffscreenMarkUsed(pPixmap);
524 else
525 exaCopyDirtyToSys(migrate);
529 * If the pixmap has both a framebuffer and system memory copy, this function
530 * asserts that both of them are the same.
532 static Bool
533 exaAssertNotDirty(PixmapPtr pPixmap)
535 ExaPixmapPriv(pPixmap);
536 CARD8 *dst, *src;
537 RegionRec ValidReg;
538 int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
539 BoxPtr pBox;
540 Bool ret = TRUE, save_use_gpu_copy;
542 if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
543 return ret;
545 RegionNull(&ValidReg);
546 RegionIntersect(&ValidReg, &pExaPixmap->validFB, &pExaPixmap->validSys);
547 nbox = RegionNumRects(&ValidReg);
549 if (!nbox)
550 goto out;
552 pBox = RegionRects(&ValidReg);
554 dst_pitch = pExaPixmap->sys_pitch;
555 src_pitch = pExaPixmap->fb_pitch;
556 cpp = pPixmap->drawable.bitsPerPixel / 8;
558 save_use_gpu_copy = pExaPixmap->use_gpu_copy;
559 save_pitch = pPixmap->devKind;
560 pExaPixmap->use_gpu_copy = TRUE;
561 pPixmap->devKind = pExaPixmap->fb_pitch;
563 if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
564 goto skip;
566 while (nbox--) {
567 int rowbytes;
569 pBox->x1 = max(pBox->x1, 0);
570 pBox->y1 = max(pBox->y1, 0);
571 pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
572 pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
574 if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
575 continue;
577 rowbytes = (pBox->x2 - pBox->x1) * cpp;
578 src =
579 (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch +
580 pBox->x1 * cpp;
581 dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
583 for (y = pBox->y1; y < pBox->y2;
584 y++, src += src_pitch, dst += dst_pitch) {
585 if (memcmp(dst, src, rowbytes) != 0) {
586 ret = FALSE;
587 exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
588 break;
593 skip:
594 exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
596 pExaPixmap->use_gpu_copy = save_use_gpu_copy;
597 pPixmap->devKind = save_pitch;
599 out:
600 RegionUninit(&ValidReg);
601 return ret;
605 * Performs migration of the pixmaps according to the operation information
606 * provided in pixmaps and can_accel and the migration scheme chosen in the
607 * config file.
609 void
610 exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
612 ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
614 ExaScreenPriv(pScreen);
615 int i, j;
617 /* If this debugging flag is set, check each pixmap for whether it is marked
618 * as clean, and if so, actually check if that's the case. This should help
619 * catch issues with failing to mark a drawable as dirty. While it will
620 * catch them late (after the operation happened), it at least explains what
621 * went wrong, and instrumenting the code to find what operation happened
622 * to the pixmap last shouldn't be hard.
624 if (pExaScr->checkDirtyCorrectness) {
625 for (i = 0; i < npixmaps; i++) {
626 if (!exaPixmapIsDirty(pixmaps[i].pPix) &&
627 !exaAssertNotDirty(pixmaps[i].pPix))
628 ErrorF("%s: Pixmap %d dirty but not marked as such!\n",
629 __func__, i);
632 /* If anything is pinned in system memory, we won't be able to
633 * accelerate.
635 for (i = 0; i < npixmaps; i++) {
636 if (exaPixmapIsPinned(pixmaps[i].pPix) &&
637 !exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
638 EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
639 pixmaps[i].pPix->drawable.width,
640 pixmaps[i].pPix->drawable.height));
641 can_accel = FALSE;
642 break;
646 if (pExaScr->migration == ExaMigrationSmart) {
647 /* If we've got something as a destination that we shouldn't cause to
648 * become newly dirtied, take the unaccelerated route.
650 for (i = 0; i < npixmaps; i++) {
651 if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB(pixmaps[i].pPix) &&
652 !exaPixmapIsDirty(pixmaps[i].pPix)) {
653 for (i = 0; i < npixmaps; i++) {
654 if (!exaPixmapIsDirty(pixmaps[i].pPix))
655 exaDoMoveOutPixmap(pixmaps + i);
657 return;
661 /* If we aren't going to accelerate, then we migrate everybody toward
662 * system memory, and kick out if it's free.
664 if (!can_accel) {
665 for (i = 0; i < npixmaps; i++) {
666 exaMigrateTowardSys(pixmaps + i);
667 if (!exaPixmapIsDirty(pixmaps[i].pPix))
668 exaDoMoveOutPixmap(pixmaps + i);
670 return;
673 /* Finally, the acceleration path. Move them all in. */
674 for (i = 0; i < npixmaps; i++) {
675 exaMigrateTowardFb(pixmaps + i);
676 exaDoMoveInPixmap(pixmaps + i);
679 else if (pExaScr->migration == ExaMigrationGreedy) {
680 /* If we can't accelerate, either because the driver can't or because one of
681 * the pixmaps is pinned in system memory, then we migrate everybody toward
682 * system memory.
684 * We also migrate toward system if all pixmaps involved are currently in
685 * system memory -- this can mitigate thrashing when there are significantly
686 * more pixmaps active than would fit in memory.
688 * If not, then we migrate toward FB so that hopefully acceleration can
689 * happen.
691 if (!can_accel) {
692 for (i = 0; i < npixmaps; i++)
693 exaMigrateTowardSys(pixmaps + i);
694 return;
697 for (i = 0; i < npixmaps; i++) {
698 if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
699 /* Found one in FB, so move all to FB. */
700 for (j = 0; j < npixmaps; j++)
701 exaMigrateTowardFb(pixmaps + i);
702 return;
706 /* Nobody's in FB, so move all away from FB. */
707 for (i = 0; i < npixmaps; i++)
708 exaMigrateTowardSys(pixmaps + i);
710 else if (pExaScr->migration == ExaMigrationAlways) {
711 /* Always move the pixmaps out if we can't accelerate. If we can
712 * accelerate, try to move them all in. If that fails, then move them
713 * back out.
715 if (!can_accel) {
716 for (i = 0; i < npixmaps; i++)
717 exaDoMoveOutPixmap(pixmaps + i);
718 return;
721 /* Now, try to move them all into FB */
722 for (i = 0; i < npixmaps; i++) {
723 exaDoMoveInPixmap(pixmaps + i);
726 /* If we couldn't fit everything in, abort */
727 for (i = 0; i < npixmaps; i++) {
728 if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
729 return;
733 /* Yay, everything has a gpu copy, mark memory as used */
734 for (i = 0; i < npixmaps; i++) {
735 ExaOffscreenMarkUsed(pixmaps[i].pPix);
740 void
741 exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
743 ExaMigrationRec pixmaps[1];
745 if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
746 pixmaps[0].as_dst = TRUE;
747 pixmaps[0].as_src = FALSE;
749 else {
750 pixmaps[0].as_dst = FALSE;
751 pixmaps[0].as_src = TRUE;
753 pixmaps[0].pPix = pPixmap;
754 pixmaps[0].pReg = pReg;
756 exaDoMigration(pixmaps, 1, FALSE);
758 (void) ExaDoPrepareAccess(pPixmap, index);