Example #1
0
/**
 * exaCreatePixmap() creates a new pixmap.
 *
 * If width and height are 0, this won't be a full-fledged pixmap and it will
 * get ModifyPixmapHeader() called on it later.  So, we mark it as pinned, because
 * ModifyPixmapHeader() would break migration.  These types of pixmaps are used
 * for scratch pixmaps, or to represent the visible screen.
 */
static PixmapPtr
exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
{
    PixmapPtr		pPixmap;
    ExaPixmapPrivPtr	pExaPixmap;
    int			bpp;
    ExaScreenPriv(pScreen);

    if (w > 32767 || h > 32767)
	return NullPixmap;

    pPixmap = fbCreatePixmap (pScreen, w, h, depth);
    if (!pPixmap)
	return NULL;
    pExaPixmap = ExaGetPixmapPriv(pPixmap);

    bpp = pPixmap->drawable.bitsPerPixel;

    /* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */
    if (!w || !h)
	pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
    else
	pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;

    pExaPixmap->area = NULL;

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

    pExaPixmap->fb_ptr = NULL;
    if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
	pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8;
    else
	pExaPixmap->fb_pitch = w * bpp / 8;
    pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
				     pExaScr->info->pixmapPitchAlign);
    pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;

    if (pExaPixmap->fb_pitch > 131071) {
	fbDestroyPixmap(pPixmap);
	return NULL;
    }

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

    if (pExaPixmap->pDamage == NULL) {
	fbDestroyPixmap (pPixmap);
	return NULL;
    }

    DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
    DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);

    /* None of the pixmap bits are valid initially */
    REGION_NULL(pScreen, &pExaPixmap->validReg);

    return pPixmap;
}
Bool
saa_add_damage(PixmapPtr pixmap)
{
    ScreenPtr pScreen = pixmap->drawable.pScreen;
    struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);

    if (spix->damage)
	return TRUE;

    spix->damage = DamageCreate(saa_report_damage, NULL,
				DamageReportRawRegion, TRUE, pScreen, pixmap);
    if (!spix->damage)
	return FALSE;

    DamageRegister(&pixmap->drawable, spix->damage);
    DamageSetReportAfterOp(spix->damage, TRUE);

    return TRUE;
}
Example #3
0
/**
 * exaCreatePixmap() creates a new pixmap.
 *
 * If width and height are 0, this won't be a full-fledged pixmap and it will
 * get ModifyPixmapHeader() called on it later.  So, we mark it as pinned, because
 * ModifyPixmapHeader() would break migration.  These types of pixmaps are used
 * for scratch pixmaps, or to represent the visible screen.
 */
PixmapPtr
exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
                        unsigned usage_hint)
{
    PixmapPtr pPixmap;
    ExaPixmapPrivPtr pExaPixmap;
    BoxRec box;
    int bpp;

    ExaScreenPriv(pScreen);

    if (w > 32767 || h > 32767)
        return NullPixmap;

    swap(pExaScr, pScreen, CreatePixmap);
    pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint);
    swap(pExaScr, pScreen, CreatePixmap);

    if (!pPixmap)
        return NULL;

    pExaPixmap = ExaGetPixmapPriv(pPixmap);
    pExaPixmap->driverPriv = NULL;

    bpp = pPixmap->drawable.bitsPerPixel;

    pExaPixmap->driverPriv = NULL;
    /* Scratch pixmaps may have w/h equal to zero, and may not be
     * migrated.
     */
    if (!w || !h)
        pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
    else
        pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;

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

    pPixmap->devPrivate.ptr = NULL;
    pExaPixmap->use_gpu_copy = FALSE;

    pExaPixmap->fb_ptr = NULL;
    exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
    pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;

    if (pExaPixmap->fb_pitch > 131071) {
        swap(pExaScr, pScreen, DestroyPixmap);
        pScreen->DestroyPixmap(pPixmap);
        swap(pExaScr, pScreen, DestroyPixmap);
        return NULL;
    }

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

    if (pExaPixmap->pDamage == NULL) {
        swap(pExaScr, pScreen, DestroyPixmap);
        pScreen->DestroyPixmap(pPixmap);
        swap(pExaScr, pScreen, DestroyPixmap);
        return NULL;
    }

    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);

    pExaPixmap->area = NULL;

    /* We set the initial pixmap as completely valid for a simple reason.
     * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
     * could form single pixel rects as part of a region. Setting the complete region
     * as valid is a natural defragmentation of the region.
     */
    box.x1 = 0;
    box.y1 = 0;
    box.x2 = w;
    box.y2 = h;
    RegionInit(&pExaPixmap->validSys, &box, 0);
    RegionInit(&pExaPixmap->validFB, &box, 0);

    exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);

    /* During a fallback we must prepare access. */
    if (pExaScr->fallback_counter)
        exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);

    return pPixmap;
}
Example #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;
    }
}
Example #5
0
static int
ProcDamageCreate (ClientPtr client)
{
    DrawablePtr		pDrawable;
    DamageExtPtr	pDamageExt;
    DamageReportLevel	level;
    RegionPtr		pRegion;
    int			rc;
    
    REQUEST(xDamageCreateReq);

    REQUEST_SIZE_MATCH(xDamageCreateReq);
    LEGAL_NEW_RESOURCE(stuff->damage, client);
    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
			   DixGetAttrAccess|DixReadAccess);
    if (rc != Success)
	return rc;

    switch (stuff->level) {
    case XDamageReportRawRectangles:
	level = DamageReportRawRegion;
	break;
    case XDamageReportDeltaRectangles:
	level = DamageReportDeltaRegion;
	break;
    case XDamageReportBoundingBox:
	level = DamageReportBoundingBox;
	break;
    case XDamageReportNonEmpty:
	level = DamageReportNonEmpty;
	break;
    default:
	client->errorValue = stuff->level;
	return BadValue;
    }
    
    pDamageExt = malloc(sizeof (DamageExtRec));
    if (!pDamageExt)
	return BadAlloc;
    pDamageExt->id = stuff->damage;
    pDamageExt->drawable = stuff->drawable;
    pDamageExt->pDrawable = pDrawable;
    pDamageExt->level = level;
    pDamageExt->pClient = client;
    pDamageExt->pDamage = DamageCreate (DamageExtReport,
					DamageExtDestroy,
					level,
					FALSE,
					pDrawable->pScreen,
					pDamageExt);
    if (!pDamageExt->pDamage)
    {
	free(pDamageExt);
	return BadAlloc;
    }
    if (!AddResource (stuff->damage, DamageExtType, (pointer) pDamageExt))
	return BadAlloc;

    DamageSetReportAfterOp (pDamageExt->pDamage, TRUE);
    DamageRegister (pDamageExt->pDrawable, pDamageExt->pDamage);

    if (pDrawable->type == DRAWABLE_WINDOW)
    {
	pRegion = &((WindowPtr) pDrawable)->borderClip;
	DamageDamageRegion(pDrawable, pRegion);
    }

    return Success;
}