/** * For the "greedy" migration scheme, pushes the pixmap toward being located in * system memory. */ static void exaMigrateTowardSys(ExaMigrationPtr migrate) { PixmapPtr pPixmap = migrate->pPix; ExaPixmapPriv(pPixmap); DBG_MIGRATE(("UseMem: %p score %d\n", (pointer) pPixmap, pExaPixmap->score)); if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) return; if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) pExaPixmap->score = 0; if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN) pExaPixmap->score--; if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area) exaDoMoveOutPixmap(migrate); if (exaPixmapHasGpuCopy(pPixmap)) { exaCopyDirtyToFb(migrate); ExaOffscreenMarkUsed(pPixmap); } else exaCopyDirtyToSys(migrate); }
/** * Allocates a framebuffer copy of the pixmap if necessary, and then copies * any necessary pixmap data into the framebuffer copy and points the pixmap at * it. * * Note that when first allocated, a pixmap will have FALSE dirty flag. * This is intentional because pixmap data starts out undefined. So if we move * it in due to the first operation against it being accelerated, it will have * undefined framebuffer contents that we didn't have to upload. If we do * moveouts (and moveins) after the first movein, then we will only have to copy * back and forth if the pixmap was written to after the last synchronization of * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away) * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move * all the data, since it's almost surely all valid now. */ static void exaDoMoveInPixmap(ExaMigrationPtr migrate) { PixmapPtr pPixmap = migrate->pPix; ScreenPtr pScreen = pPixmap->drawable.pScreen; ExaScreenPriv(pScreen); ExaPixmapPriv(pPixmap); /* If we're VT-switched away, no touching card memory allowed. */ if (pExaScr->swappedOut) return; /* If we're not allowed to move, then fail. */ if (exaPixmapIsPinned(pPixmap)) return; /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of * fragility in EXA, and <8bpp is probably not used enough any more to care * (at least, not in acceleratd paths). */ if (pPixmap->drawable.bitsPerPixel < 8) return; if (pExaPixmap->accel_blocked) return; if (pExaPixmap->area == NULL) { pExaPixmap->area = exaOffscreenAlloc(pScreen, pExaPixmap->fb_size, pExaScr->info->pixmapOffsetAlign, FALSE, exaPixmapSave, (pointer) pPixmap); if (pExaPixmap->area == NULL) return; pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase + pExaPixmap->area->offset; } exaCopyDirtyToFb(migrate); if (exaPixmapHasGpuCopy(pPixmap)) return; DBG_MIGRATE(("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap, (ExaGetPixmapPriv(pPixmap)->area ? ExaGetPixmapPriv(pPixmap)->area->offset : 0), pPixmap->drawable.width, pPixmap->drawable.height, exaPixmapIsDirty(pPixmap) ? 'd' : 'c')); pExaPixmap->use_gpu_copy = TRUE; pPixmap->devKind = pExaPixmap->fb_pitch; pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; }
void exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) { int i; /* If anything is pinned in system memory, we won't be able to * accelerate. */ for (i = 0; i < npixmaps; i++) { if (exaPixmapIsPinned(pixmaps[i].pPix) && !exaPixmapHasGpuCopy(pixmaps[i].pPix)) { can_accel = FALSE; break; } } /* We can do nothing. */ if (!can_accel) return; for (i = 0; i < npixmaps; i++) { PixmapPtr pPixmap = pixmaps[i].pPix; ExaPixmapPriv(pPixmap); if (!pExaPixmap->driverPriv) exaCreateDriverPixmap_mixed(pPixmap); if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) { ExaScreenPriv(pPixmap->drawable.pScreen); /* This pitch is needed for proper acceleration. For some reason * there are pixmaps without pDamage and a bad fb_pitch value. * So setting devKind when only exaPixmapHasGpuCopy() is true * causes corruption. Pixmaps without pDamage are not migrated * and should have a valid devKind at all times, so that's why this * isn't causing problems. Pixmaps have their gpu pitch set the * first time in the MPH call from exaCreateDriverPixmap_mixed(). */ pPixmap->devKind = pExaPixmap->fb_pitch; exaCopyDirtyToFb(pixmaps + i); if (pExaScr->deferred_mixed_pixmap == pPixmap && !pixmaps[i].as_dst && !pixmaps[i].pReg) pExaScr->deferred_mixed_pixmap = NULL; } pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); } }
/** * For the "greedy" migration scheme, pushes the pixmap toward being located in * framebuffer memory. */ static void exaMigrateTowardFb(ExaMigrationPtr migrate) { PixmapPtr pPixmap = migrate->pPix; ExaPixmapPriv(pPixmap); if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) { DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n", (pointer) pPixmap)); return; } DBG_MIGRATE(("UseScreen %p score %d\n", (pointer) pPixmap, pExaPixmap->score)); if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) { exaDoMoveInPixmap(migrate); pExaPixmap->score = 0; } if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX) pExaPixmap->score++; if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN && !exaPixmapHasGpuCopy(pPixmap)) { exaDoMoveInPixmap(migrate); } if (exaPixmapHasGpuCopy(pPixmap)) { exaCopyDirtyToFb(migrate); ExaOffscreenMarkUsed(pPixmap); } else exaCopyDirtyToSys(migrate); }