1/*
2 * Copyright © 2006 Intel Corporation
3 *
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:
10 *
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.
14 *
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.
22 *
23 * Authors:
24 *    Eric Anholt <eric@anholt.net>
25 *    Michel Dänzer <michel@tungstengraphics.com>
26 *
27 */
28
29#ifdef HAVE_DIX_CONFIG_H
30#include <dix-config.h>
31#endif
32
33#include <string.h>
34
35#include "exa_priv.h"
36#include "exa.h"
37
38#if DEBUG_MIGRATE
39#define DBG_MIGRATE(a) ErrorF a
40#else
41#define DBG_MIGRATE(a)
42#endif
43
44/**
45 * The fallback path for UTS/DFS failing is to just memcpy.  exaCopyDirtyToSys
46 * and exaCopyDirtyToFb both needed to do this loop.
47 */
48static void
49exaMemcpyBox(PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
50             CARD8 *dst, int dst_pitch)
51{
52    int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
53    int bytes = (pbox->x2 - pbox->x1) * cpp;
54
55    src += pbox->y1 * src_pitch + pbox->x1 * cpp;
56    dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
57
58    for (i = pbox->y2 - pbox->y1; i; i--) {
59        memcpy(dst, src, bytes);
60        src += src_pitch;
61        dst += dst_pitch;
62    }
63}
64
65/**
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
68 * dirtiness.
69 */
70static Bool
71exaPixmapIsDirty(PixmapPtr pPix)
72{
73    ExaPixmapPriv(pPix);
74
75    if (pExaPixmap == NULL)
76        EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
77
78    if (!pExaPixmap->pDamage)
79        return FALSE;
80
81    return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
82        !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
83}
84
85/**
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.
89 *
90 * Only valid if using a migration scheme that tracks score.
91 */
92static Bool
93exaPixmapShouldBeInFB(PixmapPtr pPix)
94{
95    ExaPixmapPriv(pPix);
96
97    if (exaPixmapIsPinned(pPix))
98        return TRUE;
99
100    return pExaPixmap->score >= 0;
101}
102
103/**
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.
106 */
107static void
108exaCopyDirty(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))
112{
113    PixmapPtr pPixmap = migrate->pPix;
114
115    ExaPixmapPriv(pPixmap);
116    RegionPtr damage = DamageRegion(pExaPixmap->pDamage);
117    RegionRec CopyReg;
118    Bool save_use_gpu_copy;
119    int save_pitch;
120    BoxPtr pBox;
121    int nbox;
122    Bool access_prepared = FALSE;
123    Bool need_sync = FALSE;
124
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);
129    }
130    else {
131        RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
132        RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
133    }
134
135    RegionEmpty(damage);
136
137    /* Copy bits valid in source but not in destination */
138    RegionNull(&CopyReg);
139    RegionSubtract(&CopyReg, pValidSrc, pValidDst);
140
141    if (migrate->as_dst) {
142        ExaScreenPriv(pPixmap->drawable.pScreen);
143
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 .
149         */
150        if (pExaScr->optimize_migration) {
151            RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
152
153#if DEBUG_MIGRATE
154            if (RegionNil(pending_damage)) {
155                static Bool firsttime = TRUE;
156
157                if (firsttime) {
158                    ErrorF("%s: Pending damage region empty!\n", __func__);
159                    firsttime = FALSE;
160                }
161            }
162#endif
163
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.
167             */
168            if (RegionNumRects(pValidDst) > 10) {
169                BoxRec box;
170                BoxPtr pValidExt, pDamageExt;
171                RegionRec closure;
172
173                pValidExt = RegionExtents(pValidDst);
174                pDamageExt = RegionExtents(pending_damage);
175
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);
180
181                RegionInit(&closure, &box, 0);
182                RegionIntersect(&CopyReg, &CopyReg, &closure);
183            }
184            else
185                RegionIntersect(&CopyReg, &CopyReg, pending_damage);
186        }
187
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.
191         */
192        if (migrate->pReg)
193            RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
194    }
195    else {
196        /* The caller may restrict the region to be migrated for source pixmaps
197         * to what's relevant for the operation.
198         */
199        if (migrate->pReg)
200            RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
201    }
202
203    pBox = RegionRects(&CopyReg);
204    nbox = RegionNumRects(&CopyReg);
205
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;
210
211    while (nbox--) {
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);
216
217        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
218            continue;
219
220        if (!transfer || !transfer(pPixmap,
221                                   pBox->x1, pBox->y1,
222                                   pBox->x2 - pBox->x1,
223                                   pBox->y2 - pBox->y1,
224                                   (char *) (pExaPixmap->sys_ptr
225                                             + pBox->y1 * pExaPixmap->sys_pitch
226                                             +
227                                             pBox->x1 *
228                                             pPixmap->drawable.bitsPerPixel /
229                                             8), pExaPixmap->sys_pitch)) {
230            if (!access_prepared) {
231                ExaDoPrepareAccess(pPixmap, fallback_index);
232                access_prepared = TRUE;
233            }
234            if (fallback_index == EXA_PREPARE_DEST) {
235                exaMemcpyBox(pPixmap, pBox,
236                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
237                             pPixmap->devPrivate.ptr, pPixmap->devKind);
238            }
239            else {
240                exaMemcpyBox(pPixmap, pBox,
241                             pPixmap->devPrivate.ptr, pPixmap->devKind,
242                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
243            }
244        }
245        else
246            need_sync = TRUE;
247
248        pBox++;
249    }
250
251    pExaPixmap->use_gpu_copy = save_use_gpu_copy;
252    pPixmap->devKind = save_pitch;
253
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.
257     */
258    if (RegionNumRects(pValidSrc) > 20)
259        RegionSubtract(pValidSrc, pValidSrc, pValidDst);
260
261    /* The copied bits are now valid in destination */
262    RegionUnion(pValidDst, pValidDst, &CopyReg);
263
264    RegionUninit(&CopyReg);
265
266    if (access_prepared)
267        exaFinishAccess(&pPixmap->drawable, fallback_index);
268    else if (need_sync && sync)
269        sync(pPixmap->drawable.pScreen);
270}
271
272/**
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
275 * allocated.
276 */
277void
278exaCopyDirtyToSys(ExaMigrationPtr migrate)
279{
280    PixmapPtr pPixmap = migrate->pPix;
281
282    ExaScreenPriv(pPixmap->drawable.pScreen);
283    ExaPixmapPriv(pPixmap);
284
285    exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
286                 pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
287                 exaWaitSync);
288}
289
290/**
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
293 * allocated.
294 */
295void
296exaCopyDirtyToFb(ExaMigrationPtr migrate)
297{
298    PixmapPtr pPixmap = migrate->pPix;
299
300    ExaScreenPriv(pPixmap->drawable.pScreen);
301    ExaPixmapPriv(pPixmap);
302
303    exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
304                 pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
305}
306
307/**
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
310 * it.
311 *
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.
321 */
322static void
323exaDoMoveInPixmap(ExaMigrationPtr migrate)
324{
325    PixmapPtr pPixmap = migrate->pPix;
326    ScreenPtr pScreen = pPixmap->drawable.pScreen;
327
328    ExaScreenPriv(pScreen);
329    ExaPixmapPriv(pPixmap);
330
331    /* If we're VT-switched away, no touching card memory allowed. */
332    if (pExaScr->swappedOut)
333        return;
334
335    /* If we're not allowed to move, then fail. */
336    if (exaPixmapIsPinned(pPixmap))
337        return;
338
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).
342     */
343    if (pPixmap->drawable.bitsPerPixel < 8)
344        return;
345
346    if (pExaPixmap->accel_blocked)
347        return;
348
349    if (pExaPixmap->area == NULL) {
350        pExaPixmap->area =
351            exaOffscreenAlloc(pScreen, pExaPixmap->fb_size,
352                              pExaScr->info->pixmapOffsetAlign, FALSE,
353                              exaPixmapSave, (void *) pPixmap);
354        if (pExaPixmap->area == NULL)
355            return;
356
357        pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
358            pExaPixmap->area->offset;
359    }
360
361    exaCopyDirtyToFb(migrate);
362
363    if (exaPixmapHasGpuCopy(pPixmap))
364        return;
365
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'));
372
373    pExaPixmap->use_gpu_copy = TRUE;
374
375    pPixmap->devKind = pExaPixmap->fb_pitch;
376    pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
377}
378
379void
380exaMoveInPixmap_classic(PixmapPtr pPixmap)
381{
382    static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
383        .pReg = NULL
384    };
385
386    migrate.pPix = pPixmap;
387    exaDoMoveInPixmap(&migrate);
388}
389
390/**
391 * Switches the current active location of the pixmap to system memory, copying
392 * updated data out if necessary.
393 */
394static void
395exaDoMoveOutPixmap(ExaMigrationPtr migrate)
396{
397    PixmapPtr pPixmap = migrate->pPix;
398
399    ExaPixmapPriv(pPixmap);
400
401    if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
402        return;
403
404    exaCopyDirtyToSys(migrate);
405
406    if (exaPixmapHasGpuCopy(pPixmap)) {
407
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'));
414
415        pExaPixmap->use_gpu_copy = FALSE;
416
417        pPixmap->devKind = pExaPixmap->sys_pitch;
418        pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
419    }
420}
421
422void
423exaMoveOutPixmap_classic(PixmapPtr pPixmap)
424{
425    static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
426        .pReg = NULL
427    };
428
429    migrate.pPix = pPixmap;
430    exaDoMoveOutPixmap(&migrate);
431}
432
433/**
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.
437 */
438void
439exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area)
440{
441    PixmapPtr pPixmap = area->privData;
442
443    ExaPixmapPriv(pPixmap);
444
445    exaMoveOutPixmap(pPixmap);
446
447    pExaPixmap->fb_ptr = NULL;
448    pExaPixmap->area = NULL;
449
450    /* Mark all FB bits as invalid, so all valid system bits get copied to FB
451     * next time */
452    RegionEmpty(&pExaPixmap->validFB);
453}
454
455/**
456 * For the "greedy" migration scheme, pushes the pixmap toward being located in
457 * framebuffer memory.
458 */
459static void
460exaMigrateTowardFb(ExaMigrationPtr migrate)
461{
462    PixmapPtr pPixmap = migrate->pPix;
463
464    ExaPixmapPriv(pPixmap);
465
466    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
467        DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
468                     (void *) pPixmap));
469        return;
470    }
471
472    DBG_MIGRATE(("UseScreen %p score %d\n",
473                 (void *) pPixmap, pExaPixmap->score));
474
475    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
476        exaDoMoveInPixmap(migrate);
477        pExaPixmap->score = 0;
478    }
479
480    if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
481        pExaPixmap->score++;
482
483    if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
484        !exaPixmapHasGpuCopy(pPixmap)) {
485        exaDoMoveInPixmap(migrate);
486    }
487
488    if (exaPixmapHasGpuCopy(pPixmap)) {
489        exaCopyDirtyToFb(migrate);
490        ExaOffscreenMarkUsed(pPixmap);
491    }
492    else
493        exaCopyDirtyToSys(migrate);
494}
495
496/**
497 * For the "greedy" migration scheme, pushes the pixmap toward being located in
498 * system memory.
499 */
500static void
501exaMigrateTowardSys(ExaMigrationPtr migrate)
502{
503    PixmapPtr pPixmap = migrate->pPix;
504
505    ExaPixmapPriv(pPixmap);
506
507    DBG_MIGRATE(("UseMem: %p score %d\n", (void *) pPixmap,
508                 pExaPixmap->score));
509
510    if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
511        return;
512
513    if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
514        pExaPixmap->score = 0;
515
516    if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
517        pExaPixmap->score--;
518
519    if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
520        exaDoMoveOutPixmap(migrate);
521
522    if (exaPixmapHasGpuCopy(pPixmap)) {
523        exaCopyDirtyToFb(migrate);
524        ExaOffscreenMarkUsed(pPixmap);
525    }
526    else
527        exaCopyDirtyToSys(migrate);
528}
529
530/**
531 * If the pixmap has both a framebuffer and system memory copy, this function
532 * asserts that both of them are the same.
533 */
534static Bool
535exaAssertNotDirty(PixmapPtr pPixmap)
536{
537    ExaPixmapPriv(pPixmap);
538    CARD8 *dst, *src;
539    RegionRec ValidReg;
540    int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
541    BoxPtr pBox;
542    Bool ret = TRUE, save_use_gpu_copy;
543
544    if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
545        return ret;
546
547    RegionNull(&ValidReg);
548    RegionIntersect(&ValidReg, &pExaPixmap->validFB, &pExaPixmap->validSys);
549    nbox = RegionNumRects(&ValidReg);
550
551    if (!nbox)
552        goto out;
553
554    pBox = RegionRects(&ValidReg);
555
556    dst_pitch = pExaPixmap->sys_pitch;
557    src_pitch = pExaPixmap->fb_pitch;
558    cpp = pPixmap->drawable.bitsPerPixel / 8;
559
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;
564
565    if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
566        goto skip;
567
568    while (nbox--) {
569        int rowbytes;
570
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);
575
576        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
577            continue;
578
579        rowbytes = (pBox->x2 - pBox->x1) * cpp;
580        src =
581            (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch +
582            pBox->x1 * cpp;
583        dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
584
585        for (y = pBox->y1; y < pBox->y2;
586             y++, src += src_pitch, dst += dst_pitch) {
587            if (memcmp(dst, src, rowbytes) != 0) {
588                ret = FALSE;
589                exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
590                break;
591            }
592        }
593    }
594
595 skip:
596    exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
597
598    pExaPixmap->use_gpu_copy = save_use_gpu_copy;
599    pPixmap->devKind = save_pitch;
600
601 out:
602    RegionUninit(&ValidReg);
603    return ret;
604}
605
606/**
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
609 * config file.
610 */
611void
612exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
613{
614    ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
615
616    ExaScreenPriv(pScreen);
617    int i, j;
618
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.
625     */
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",
631                       __func__, i);
632        }
633    }
634    /* If anything is pinned in system memory, we won't be able to
635     * accelerate.
636     */
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));
643            can_accel = FALSE;
644            break;
645        }
646    }
647
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.
651         */
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);
658                }
659                return;
660            }
661        }
662
663        /* If we aren't going to accelerate, then we migrate everybody toward
664         * system memory, and kick out if it's free.
665         */
666        if (!can_accel) {
667            for (i = 0; i < npixmaps; i++) {
668                exaMigrateTowardSys(pixmaps + i);
669                if (!exaPixmapIsDirty(pixmaps[i].pPix))
670                    exaDoMoveOutPixmap(pixmaps + i);
671            }
672            return;
673        }
674
675        /* Finally, the acceleration path.  Move them all in. */
676        for (i = 0; i < npixmaps; i++) {
677            exaMigrateTowardFb(pixmaps + i);
678            exaDoMoveInPixmap(pixmaps + i);
679        }
680    }
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
684         * system memory.
685         *
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.
689         *
690         * If not, then we migrate toward FB so that hopefully acceleration can
691         * happen.
692         */
693        if (!can_accel) {
694            for (i = 0; i < npixmaps; i++)
695                exaMigrateTowardSys(pixmaps + i);
696            return;
697        }
698
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);
704                return;
705            }
706        }
707
708        /* Nobody's in FB, so move all away from FB. */
709        for (i = 0; i < npixmaps; i++)
710            exaMigrateTowardSys(pixmaps + i);
711    }
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
715         * back out.
716         */
717        if (!can_accel) {
718            for (i = 0; i < npixmaps; i++)
719                exaDoMoveOutPixmap(pixmaps + i);
720            return;
721        }
722
723        /* Now, try to move them all into FB */
724        for (i = 0; i < npixmaps; i++) {
725            exaDoMoveInPixmap(pixmaps + i);
726        }
727
728        /* If we couldn't fit everything in, abort */
729        for (i = 0; i < npixmaps; i++) {
730            if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
731                return;
732            }
733        }
734
735        /* Yay, everything has a gpu copy, mark memory as used */
736        for (i = 0; i < npixmaps; i++) {
737            ExaOffscreenMarkUsed(pixmaps[i].pPix);
738        }
739    }
740}
741
742void
743exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
744{
745    ExaMigrationRec pixmaps[1];
746
747    if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
748        pixmaps[0].as_dst = TRUE;
749        pixmaps[0].as_src = FALSE;
750    }
751    else {
752        pixmaps[0].as_dst = FALSE;
753        pixmaps[0].as_src = TRUE;
754    }
755    pixmaps[0].pPix = pPixmap;
756    pixmaps[0].pReg = pReg;
757
758    exaDoMigration(pixmaps, 1, FALSE);
759
760    (void) ExaDoPrepareAccess(pPixmap, index);
761}
762