コード例 #1
0
ファイル: exa.c プロジェクト: miettal/armadillo420_standard
/**
 * exaValidateGC() sets the ops to EXA's implementations, which may be
 * accelerated or may sync the card and fall back to fb.
 */
static void
exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
    /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
     * Preempt fbValidateGC by doing its work and masking the change out, so
     * that we can do the Prepare/FinishAccess.
     */
#ifdef FB_24_32BIT
    if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) {
	(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
	fbGetRotatedPixmap(pGC) = 0;
    }
	
    if (pGC->fillStyle == FillTiled) {
	PixmapPtr	pOldTile, pNewTile;

	pOldTile = pGC->tile.pixmap;
	if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
	{
	    pNewTile = fbGetRotatedPixmap(pGC);
	    if (!pNewTile ||
		pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
	    {
		if (pNewTile)
		    (*pGC->pScreen->DestroyPixmap) (pNewTile);
		/* fb24_32ReformatTile will do direct access of a newly-
		 * allocated pixmap.  This isn't a problem yet, since we don't
		 * put pixmaps in FB until at least one accelerated EXA op.
		 */
		exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
		pNewTile = fb24_32ReformatTile (pOldTile,
						pDrawable->bitsPerPixel);
		exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height);
		exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC);
	    }
	    if (pNewTile)
	    {
		fbGetRotatedPixmap(pGC) = pOldTile;
		pGC->tile.pixmap = pNewTile;
		changes |= GCTile;
	    }
	}
    }
#endif
    if (changes & GCTile) {
	if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width *
					     pDrawable->bitsPerPixel))
	{
	    /* XXX This fixes corruption with tiled pixmaps, but may just be a
	     * workaround for broken drivers
	     */
	    exaMoveOutPixmap(pGC->tile.pixmap);
	    fbPadPixmap (pGC->tile.pixmap);
	    exaPixmapDirty(pGC->tile.pixmap, 0, 0,
			   pGC->tile.pixmap->drawable.width,
			   pGC->tile.pixmap->drawable.height);
	}
	/* Mask out the GCTile change notification, now that we've done FB's
	 * job for it.
	 */
	changes &= ~GCTile;
    }

    fbValidateGC (pGC, changes, pDrawable);

    pGC->ops = (GCOps *) &exaOps;
}
コード例 #2
0
/**
 * If the pixmap has both a framebuffer and system memory copy, this function
 * asserts that both of them are the same.
 */
static Bool
exaAssertNotDirty(PixmapPtr pPixmap)
{
    ExaPixmapPriv(pPixmap);
    CARD8 *dst, *src;
    RegionRec ValidReg;
    int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
    BoxPtr pBox;
    Bool ret = TRUE, save_use_gpu_copy;

    if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
        return ret;

    RegionNull(&ValidReg);
    RegionIntersect(&ValidReg, &pExaPixmap->validFB, &pExaPixmap->validSys);
    nbox = RegionNumRects(&ValidReg);

    if (!nbox)
        goto out;

    pBox = RegionRects(&ValidReg);

    dst_pitch = pExaPixmap->sys_pitch;
    src_pitch = pExaPixmap->fb_pitch;
    cpp = pPixmap->drawable.bitsPerPixel / 8;

    save_use_gpu_copy = pExaPixmap->use_gpu_copy;
    save_pitch = pPixmap->devKind;
    pExaPixmap->use_gpu_copy = TRUE;
    pPixmap->devKind = pExaPixmap->fb_pitch;

    if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
        goto skip;

    while (nbox--) {
        int rowbytes;

        pBox->x1 = max(pBox->x1, 0);
        pBox->y1 = max(pBox->y1, 0);
        pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
        pBox->y2 = min(pBox->y2, pPixmap->drawable.height);

        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
            continue;

        rowbytes = (pBox->x2 - pBox->x1) * cpp;
        src =
            (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch +
            pBox->x1 * cpp;
        dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;

        for (y = pBox->y1; y < pBox->y2;
                y++, src += src_pitch, dst += dst_pitch) {
            if (memcmp(dst, src, rowbytes) != 0) {
                ret = FALSE;
                exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
                break;
            }
        }
    }

skip:
    exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);

    pExaPixmap->use_gpu_copy = save_use_gpu_copy;
    pPixmap->devKind = save_pitch;

out:
    RegionUninit(&ValidReg);
    return ret;
}
コード例 #3
0
ファイル: exa_glyphs.c プロジェクト: Agnesa/xserver
/* The most efficient thing to way to upload the glyph to the screen
 * is to use the UploadToScreen() driver hook; this allows us to
 * pipeline glyph uploads and to avoid creating gpu backed pixmaps for
 * glyphs that we'll never use again.
 *
 * If we can't do it with UploadToScreen (because the glyph has a gpu copy,
 * etc), we fall back to CompositePicture.
 *
 * We need to damage the cache pixmap manually in either case because the damage
 * layer unwrapped the picture screen before calling exaGlyphs.
 */
static void
exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
                         ExaGlyphCachePtr cache, int x, int y, GlyphPtr pGlyph)
{
    ExaScreenPriv(pScreen);
    PicturePtr pGlyphPicture = GetGlyphPicture(pGlyph, pScreen);
    PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable;

    ExaPixmapPriv(pGlyphPixmap);
    PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable;

    if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut ||
        pExaPixmap->accel_blocked)
        goto composite;

    /* If the glyph pixmap is already uploaded, no point in doing
     * things this way */
    if (exaPixmapHasGpuCopy(pGlyphPixmap))
        goto composite;

    /* UploadToScreen only works if bpp match */
    if (pGlyphPixmap->drawable.bitsPerPixel !=
        pCachePixmap->drawable.bitsPerPixel)
        goto composite;

    if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[1];

        /* cache pixmap must have a gpu copy. */
        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pCachePixmap;
        pixmaps[0].pReg = NULL;
        exaDoMigration(pixmaps, 1, TRUE);
    }

    if (!exaPixmapHasGpuCopy(pCachePixmap))
        goto composite;

    /* x,y are in pixmap coordinates, no need for cache{X,Y}off */
    if (pExaScr->info->UploadToScreen(pCachePixmap,
                                      x,
                                      y,
                                      pGlyph->info.width,
                                      pGlyph->info.height,
                                      (char *) pExaPixmap->sys_ptr,
                                      pExaPixmap->sys_pitch))
        goto damage;

 composite:
    CompositePicture(PictOpSrc,
                     pGlyphPicture,
                     None,
                     cache->picture,
                     0, 0, 0, 0, x, y, pGlyph->info.width, pGlyph->info.height);

 damage:
    /* The cache pixmap isn't a window, so no need to offset coordinates. */
    exaPixmapDirty(pCachePixmap,
                   x, y, x + cache->glyphWidth, y + cache->glyphHeight);
}
コード例 #4
0
/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
 * use the DownloadFromScreen hook to retrieve contents to a copy in system
 * memory, perform software rendering on that and move back the results with the
 * UploadToScreen hook (see exaDamageReport_mixed).
 */
void
exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
{
    ExaPixmapPriv(pPixmap);
    Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
    Bool success;

    success = ExaDoPrepareAccess(pPixmap, index);

    if (success && has_gpu_copy && pExaPixmap->pDamage) {
        /* You cannot do accelerated operations while a buffer is mapped. */
        exaFinishAccess(&pPixmap->drawable, index);
        /* Update the gpu view of both deferred destination pixmaps and of
         * source pixmaps that were migrated with a bounding region.
         */
        exaMoveInPixmap_mixed(pPixmap);
        success = ExaDoPrepareAccess(pPixmap, index);

        if (success) {
            /* We have a gpu pixmap that can be accessed, we don't need the cpu
             * copy anymore. Drivers that prefer DFS, should fail prepare
             * access.
             */
            DamageDestroy(pExaPixmap->pDamage);
            pExaPixmap->pDamage = NULL;

            free(pExaPixmap->sys_ptr);
            pExaPixmap->sys_ptr = NULL;

            return;
        }
    }

    if (!success) {
        ExaMigrationRec pixmaps[1];

        /* Do we need to allocate our system buffer? */
        if (!pExaPixmap->sys_ptr) {
            pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
                                         pPixmap->drawable.height);
            if (!pExaPixmap->sys_ptr)
                FatalError("EXA: malloc failed for size %d bytes\n",
                           pExaPixmap->sys_pitch * pPixmap->drawable.height);
        }

        if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
            pixmaps[0].as_dst = TRUE;
            pixmaps[0].as_src = FALSE;
        }
        else {
            pixmaps[0].as_dst = FALSE;
            pixmaps[0].as_src = TRUE;
        }
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = pReg;

        if (!pExaPixmap->pDamage &&
            (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
            Bool as_dst = pixmaps[0].as_dst;

            /* Set up damage tracking */
            pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
                                               DamageReportNonEmpty, TRUE,
                                               pPixmap->drawable.pScreen,
                                               pPixmap);

            if (pExaPixmap->pDamage) {
                DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
                /* This ensures that pending damage reflects the current
                 * operation. This is used by exa to optimize migration.
                 */
                DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
            }

            if (has_gpu_copy) {
                exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
                               pPixmap->drawable.height);

                /* We don't know which region of the destination will be damaged,
                 * have to assume all of it
                 */
                if (as_dst) {
                    pixmaps[0].as_dst = FALSE;
                    pixmaps[0].as_src = TRUE;
                    pixmaps[0].pReg = NULL;
                }
                exaCopyDirtyToSys(pixmaps);
            }

            if (as_dst)
                exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
                               pPixmap->drawable.height);
        }
        else if (has_gpu_copy)
            exaCopyDirtyToSys(pixmaps);

        pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
        pPixmap->devKind = pExaPixmap->sys_pitch;
        pExaPixmap->use_gpu_copy = FALSE;
    }
}