Esempio n. 1
0
/**
 * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
 *
 * This is probably the only case we actually care about.  The rest fall through
 * to migration and fbGetImage, which hopefully will result in migration pushing
 * the pixmap out of framebuffer.
 */
void
exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
            unsigned int format, unsigned long planeMask, char *d)
{
    ExaScreenPriv(pDrawable->pScreen);
    PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);

    ExaPixmapPriv(pPix);
    int xoff, yoff;
    Bool ok;

    if (pExaScr->fallback_counter || pExaScr->swappedOut)
        goto fallback;

    /* If there's a system copy, we want to save the result there */
    if (pExaPixmap->pDamage)
        goto fallback;

    pPix = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff);

    if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL)
        goto fallback;

    /* Only cover the ZPixmap, solid copy case. */
    if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
        goto fallback;

    /* Only try to handle the 8bpp and up cases, since we don't want to think
     * about <8bpp.
     */
    if (pDrawable->bitsPerPixel < 8)
        goto fallback;

    ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
                                           pDrawable->y + y + yoff, w, h, d,
                                           PixmapBytePad(w, pDrawable->depth));
    if (ok) {
        exaWaitSync(pDrawable->pScreen);
        return;
    }

 fallback:
    ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
}
Esempio n. 2
0
static void
exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
             DDXPointPtr ppt, int *pwidth, int fSorted)
{
    ScreenPtr pScreen = pDrawable->pScreen;

    ExaScreenPriv(pScreen);
    RegionPtr pClip = fbGetCompositeClip(pGC);
    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);

    ExaPixmapPriv(pPixmap);
    BoxPtr pextent, pbox;
    int nbox;
    int extentX1, extentX2, extentY1, extentY2;
    int fullX1, fullX2, fullY1;
    int partX1, partX2;
    int off_x, off_y;

    if (pExaScr->fallback_counter ||
        pExaScr->swappedOut ||
        pGC->fillStyle != FillSolid || pExaPixmap->accel_blocked) {
        ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted);
        return;
    }

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

        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = NULL;

        exaDoMigration(pixmaps, 1, TRUE);
    }

    if (!(pPixmap = exaGetOffscreenPixmap(pDrawable, &off_x, &off_y)) ||
        !(*pExaScr->info->PrepareSolid) (pPixmap,
                                         pGC->alu,
                                         pGC->planemask, pGC->fgPixel)) {
        ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted);
        return;
    }

    pextent = RegionExtents(pClip);
    extentX1 = pextent->x1;
    extentY1 = pextent->y1;
    extentX2 = pextent->x2;
    extentY2 = pextent->y2;
    while (n--) {
        fullX1 = ppt->x;
        fullY1 = ppt->y;
        fullX2 = fullX1 + (int) *pwidth;
        ppt++;
        pwidth++;

        if (fullY1 < extentY1 || extentY2 <= fullY1)
            continue;

        if (fullX1 < extentX1)
            fullX1 = extentX1;

        if (fullX2 > extentX2)
            fullX2 = extentX2;

        if (fullX1 >= fullX2)
            continue;

        nbox = RegionNumRects(pClip);
        if (nbox == 1) {
            (*pExaScr->info->Solid) (pPixmap,
                                     fullX1 + off_x, fullY1 + off_y,
                                     fullX2 + off_x, fullY1 + 1 + off_y);
        }
        else {
            pbox = RegionRects(pClip);
            while (nbox--) {
                if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) {
                    partX1 = pbox->x1;
                    if (partX1 < fullX1)
                        partX1 = fullX1;
                    partX2 = pbox->x2;
                    if (partX2 > fullX2)
                        partX2 = fullX2;
                    if (partX2 > partX1) {
                        (*pExaScr->info->Solid) (pPixmap,
                                                 partX1 + off_x, fullY1 + off_y,
                                                 partX2 + off_x,
                                                 fullY1 + 1 + off_y);
                    }
                }
                pbox++;
            }
        }
    }
    (*pExaScr->info->DoneSolid) (pPixmap);
    exaMarkSync(pScreen);
}
Esempio n. 3
0
static Bool inline
exaCopyNtoNTwoDir(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
                  GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
{
    ExaScreenPriv(pDstDrawable->pScreen);
    PixmapPtr pSrcPixmap, pDstPixmap;
    int src_off_x, src_off_y, dst_off_x, dst_off_y;
    int dirsetup;

    /* Need to get both pixmaps to call the driver routines */
    pSrcPixmap = exaGetOffscreenPixmap(pSrcDrawable, &src_off_x, &src_off_y);
    pDstPixmap = exaGetOffscreenPixmap(pDstDrawable, &dst_off_x, &dst_off_y);
    if (!pSrcPixmap || !pDstPixmap)
        return FALSE;

    /*
     * Now the case of a chip that only supports xdir = ydir = 1 or
     * xdir = ydir = -1, but we have xdir != ydir.
     */
    dirsetup = 0;               /* No direction set up yet. */
    for (; nbox; pbox++, nbox--) {
        if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
            /* Do a xdir = ydir = -1 blit instead. */
            if (dirsetup != -1) {
                if (dirsetup != 0)
                    pExaScr->info->DoneCopy(pDstPixmap);
                dirsetup = -1;
                if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap,
                                                    pDstPixmap,
                                                    -1, -1,
                                                    pGC ? pGC->alu : GXcopy,
                                                    pGC ? pGC->planemask :
                                                    FB_ALLONES))
                    return FALSE;
            }
            (*pExaScr->info->Copy) (pDstPixmap,
                                    src_off_x + pbox->x1 + dx,
                                    src_off_y + pbox->y1 + dy,
                                    dst_off_x + pbox->x1,
                                    dst_off_y + pbox->y1,
                                    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
        }
        else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
            /* Do a xdir = ydir = 1 blit instead. */
            if (dirsetup != 1) {
                if (dirsetup != 0)
                    pExaScr->info->DoneCopy(pDstPixmap);
                dirsetup = 1;
                if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap,
                                                    pDstPixmap,
                                                    1, 1,
                                                    pGC ? pGC->alu : GXcopy,
                                                    pGC ? pGC->planemask :
                                                    FB_ALLONES))
                    return FALSE;
            }
            (*pExaScr->info->Copy) (pDstPixmap,
                                    src_off_x + pbox->x1 + dx,
                                    src_off_y + pbox->y1 + dy,
                                    dst_off_x + pbox->x1,
                                    dst_off_y + pbox->y1,
                                    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
        }
        else if (dx >= 0) {
            /*
             * xdir = 1, ydir = -1.
             * Perform line-by-line xdir = ydir = 1 blits, going up.
             */
            int i;

            if (dirsetup != 1) {
                if (dirsetup != 0)
                    pExaScr->info->DoneCopy(pDstPixmap);
                dirsetup = 1;
                if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap,
                                                    pDstPixmap,
                                                    1, 1,
                                                    pGC ? pGC->alu : GXcopy,
                                                    pGC ? pGC->planemask :
                                                    FB_ALLONES))
                    return FALSE;
            }
            for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
                (*pExaScr->info->Copy) (pDstPixmap,
                                        src_off_x + pbox->x1 + dx,
                                        src_off_y + pbox->y1 + dy + i,
                                        dst_off_x + pbox->x1,
                                        dst_off_y + pbox->y1 + i,
                                        pbox->x2 - pbox->x1, 1);
        }
        else {
            /*
             * xdir = -1, ydir = 1.
             * Perform line-by-line xdir = ydir = -1 blits, going down.
             */
            int i;

            if (dirsetup != -1) {
                if (dirsetup != 0)
                    pExaScr->info->DoneCopy(pDstPixmap);
                dirsetup = -1;
                if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap,
                                                    pDstPixmap,
                                                    -1, -1,
                                                    pGC ? pGC->alu : GXcopy,
                                                    pGC ? pGC->planemask :
                                                    FB_ALLONES))
                    return FALSE;
            }
            for (i = 0; i < pbox->y2 - pbox->y1; i++)
                (*pExaScr->info->Copy) (pDstPixmap,
                                        src_off_x + pbox->x1 + dx,
                                        src_off_y + pbox->y1 + dy + i,
                                        dst_off_x + pbox->x1,
                                        dst_off_y + pbox->y1 + i,
                                        pbox->x2 - pbox->x1, 1);
        }
    }
    if (dirsetup != 0)
        pExaScr->info->DoneCopy(pDstPixmap);
    exaMarkSync(pDstDrawable->pScreen);
    return TRUE;
}
Esempio n. 4
0
static Bool
exaDoPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
              int w, int h, int format, char *bits, int src_stride)
{
    ExaScreenPriv(pDrawable->pScreen);
    PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);

    ExaPixmapPriv(pPix);
    RegionPtr pClip;
    BoxPtr pbox;
    int nbox;
    int xoff, yoff;
    int bpp = pDrawable->bitsPerPixel;
    Bool ret = TRUE;

    if (pExaScr->fallback_counter || pExaPixmap->accel_blocked ||
        !pExaScr->info->UploadToScreen)
        return FALSE;

    /* If there's a system copy, we want to save the result there */
    if (pExaPixmap->pDamage)
        return FALSE;

    /* Don't bother with under 8bpp, XYPixmaps. */
    if (format != ZPixmap || bpp < 8)
        return FALSE;

    /* Only accelerate copies: no rop or planemask. */
    if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
        return FALSE;

    if (pExaScr->swappedOut)
        return FALSE;

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

        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pPix;
        pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);

        exaDoMigration(pixmaps, 1, TRUE);
    }

    pPix = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff);

    if (!pPix)
        return FALSE;

    x += pDrawable->x;
    y += pDrawable->y;

    pClip = fbGetCompositeClip(pGC);
    for (nbox = RegionNumRects(pClip),
         pbox = RegionRects(pClip); nbox--; pbox++) {
        int x1 = x;
        int y1 = y;
        int x2 = x + w;
        int y2 = y + h;
        char *src;
        Bool ok;

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

        src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
        ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
                                           x2 - x1, y2 - y1, src, src_stride);
        /* We have to fall back completely, and ignore what has already been completed.
         * Messing with the fb layer directly like we used to is completely unacceptable.
         */
        if (!ok) {
            ret = FALSE;
            break;
        }
    }

    if (ret)
        exaMarkSync(pDrawable->pScreen);

    return ret;
}
Esempio n. 5
0
/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
 * Based on fbFillRegionTiled(), fbTile().
 */
Bool
exaFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
                   DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu,
                   Bool hasClientClip)
{
    ExaScreenPriv(pDrawable->pScreen);
    PixmapPtr pPixmap;
    ExaPixmapPrivPtr pExaPixmap;
    ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
    int xoff, yoff;
    int tileWidth, tileHeight;
    int nbox = RegionNumRects(pRegion);
    BoxPtr pBox = RegionRects(pRegion);
    Bool ret = FALSE;
    int i;

    tileWidth = pTile->drawable.width;
    tileHeight = pTile->drawable.height;

    /* If we're filling with a solid color, grab it out and go to
     * FillRegionSolid, saving numerous copies.
     */
    if (tileWidth == 1 && tileHeight == 1)
        return exaFillRegionSolid(pDrawable, pRegion,
                                  exaGetPixmapFirstPixel(pTile), planemask,
                                  alu, hasClientClip);

    pPixmap = exaGetDrawablePixmap(pDrawable);
    pExaPixmap = ExaGetPixmapPriv(pPixmap);

    if (pExaScr->fallback_counter || pExaPixmap->accel_blocked ||
        pTileExaPixmap->accel_blocked)
        return FALSE;

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

        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
                                                alu,
                                                hasClientClip) ? NULL : pRegion;
        pixmaps[1].as_dst = FALSE;
        pixmaps[1].as_src = TRUE;
        pixmaps[1].pPix = pTile;
        pixmaps[1].pReg = NULL;

        exaDoMigration(pixmaps, 2, TRUE);
    }

    pPixmap = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff);

    if (!pPixmap || !exaPixmapHasGpuCopy(pTile))
        return FALSE;

    if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) {
        if (xoff || yoff)
            RegionTranslate(pRegion, xoff, yoff);

        for (i = 0; i < nbox; i++) {
            int height = pBox[i].y2 - pBox[i].y1;
            int dstY = pBox[i].y1;
            int tileY;

            if (alu == GXcopy)
                height = min(height, tileHeight);

            modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);

            while (height > 0) {
                int width = pBox[i].x2 - pBox[i].x1;
                int dstX = pBox[i].x1;
                int tileX;
                int h = tileHeight - tileY;

                if (alu == GXcopy)
                    width = min(width, tileWidth);

                if (h > height)
                    h = height;
                height -= h;

                modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth,
                        tileX);

                while (width > 0) {
                    int w = tileWidth - tileX;

                    if (w > width)
                        w = width;
                    width -= w;

                    (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY,
                                            w, h);
                    dstX += w;
                    tileX = 0;
                }
                dstY += h;
                tileY = 0;
            }
        }
        (*pExaScr->info->DoneCopy) (pPixmap);

        /* With GXcopy, we only need to do the basic algorithm up to the tile
         * size; then, we can just keep doubling the destination in each
         * direction until it fills the box. This way, the number of copy
         * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where
         * rx/ry is the ratio between box and tile width/height. This can make
         * a big difference if each driver copy incurs a significant constant
         * overhead.
         */
        if (alu != GXcopy)
            ret = TRUE;
        else {
            Bool more_copy = FALSE;

            for (i = 0; i < nbox; i++) {
                int dstX = pBox[i].x1 + tileWidth;
                int dstY = pBox[i].y1 + tileHeight;

                if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) {
                    more_copy = TRUE;
                    break;
                }
            }

            if (more_copy == FALSE)
                ret = TRUE;

            if (more_copy && (*pExaScr->info->PrepareCopy) (pPixmap, pPixmap,
                                                            1, 1, alu,
                                                            planemask)) {
                for (i = 0; i < nbox; i++) {
                    int dstX = pBox[i].x1 + tileWidth;
                    int dstY = pBox[i].y1 + tileHeight;
                    int width = min(pBox[i].x2 - dstX, tileWidth);
                    int height = min(pBox[i].y2 - pBox[i].y1, tileHeight);

                    while (dstX < pBox[i].x2) {
                        (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
                                                dstX, pBox[i].y1, width,
                                                height);
                        dstX += width;
                        width = min(pBox[i].x2 - dstX, width * 2);
                    }

                    width = pBox[i].x2 - pBox[i].x1;
                    height = min(pBox[i].y2 - dstY, tileHeight);

                    while (dstY < pBox[i].y2) {
                        (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
                                                pBox[i].x1, dstY, width,
                                                height);
                        dstY += height;
                        height = min(pBox[i].y2 - dstY, height * 2);
                    }
                }

                (*pExaScr->info->DoneCopy) (pPixmap);

                ret = TRUE;
            }
        }

        exaMarkSync(pDrawable->pScreen);

        if (xoff || yoff)
            RegionTranslate(pRegion, -xoff, -yoff);
    }

    return ret;
}
Esempio n. 6
0
/**
 * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
 *
 * This is probably the only case we actually care about.  The rest fall through
 * to migration and fbGetImage, which hopefully will result in migration pushing
 * the pixmap out of framebuffer.
 */
void
exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
	     unsigned int format, unsigned long planeMask, char *d)
{
    ExaScreenPriv (pDrawable->pScreen);
    PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
    int xoff, yoff;
    Bool ok;

    if (pExaScr->fallback_counter || pExaScr->swappedOut)
	goto fallback;

    exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff);

    if (pExaScr->do_migration) {
	BoxRec Box;
	RegionRec Reg;
	ExaMigrationRec pixmaps[1];

	Box.x1 = pDrawable->y + x + xoff;
	Box.y1 = pDrawable->y + y + yoff;
	Box.x2 = Box.x1 + w;
	Box.y2 = Box.y1 + h;

	REGION_INIT(pScreen, &Reg, &Box, 1);

	pixmaps[0].as_dst = FALSE;
	pixmaps[0].as_src = TRUE;
	pixmaps[0].pPix = pPix;
	pixmaps[0].pReg = &Reg;

	exaDoMigration(pixmaps, 1, FALSE);

	REGION_UNINIT(pScreen, &Reg);
    }

    pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);

    if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL)
	goto fallback;

    /* Only cover the ZPixmap, solid copy case. */
    if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
	goto fallback;

    /* Only try to handle the 8bpp and up cases, since we don't want to think
     * about <8bpp.
     */
    if (pDrawable->bitsPerPixel < 8)
	goto fallback;

    ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
					   pDrawable->y + y + yoff, w, h, d,
					   PixmapBytePad(w, pDrawable->depth));
    if (ok) {
	exaWaitSync(pDrawable->pScreen);
	return;
    }

fallback:
    ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
}