diff options
author | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-11-02 15:26:35 +0000 |
---|---|---|
committer | Matthieu Herrb <matthieu@cvs.openbsd.org> | 2008-11-02 15:26:35 +0000 |
commit | dbca69c8a4f3e2d1ccb4f89152213b2861b33af6 (patch) | |
tree | f8963ef73903a7b4374adc2354dffbaa905112ac /xserver/exa/exa_render.c | |
parent | 33b2029f322f3c238b7ba528083195ad8dde33e1 (diff) |
xserver 1.5.2. tested by ckuethe@, oga@, and others.
Diffstat (limited to 'xserver/exa/exa_render.c')
-rw-r--r-- | xserver/exa/exa_render.c | 667 |
1 files changed, 194 insertions, 473 deletions
diff --git a/xserver/exa/exa_render.c b/xserver/exa/exa_render.c index ad1c02b18..1d7b8974c 100644 --- a/xserver/exa/exa_render.c +++ b/xserver/exa/exa_render.c @@ -51,6 +51,9 @@ static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n) case PICT_a8r8g8b8: snprintf(format, 20, "ARGB8888"); break; + case PICT_x8r8g8b8: + snprintf(format, 20, "XRGB8888"); + break; case PICT_r5g6b5: snprintf(format, 20, "RGB565 "); break; @@ -111,7 +114,7 @@ exaPrintCompositeFallback(CARD8 op, } #endif /* DEBUG_TRACE_FALL */ -static Bool +Bool exaOpReadsDestination (CARD8 op) { /* FALSE (does not read destination) is the list of ops in the protocol @@ -247,10 +250,24 @@ exaTryDriverSolidFill(PicturePtr pSrc, int nbox; int dst_off_x, dst_off_y; PixmapPtr pSrcPix, pDstPix; + ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; CARD32 pixel; CARD16 red, green, blue, alpha; ExaMigrationRec pixmaps[1]; + pDstPix = exaGetDrawablePixmap (pDst->pDrawable); + pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); + + pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + pDstExaPix = ExaGetPixmapPriv(pDstPix); + + /* Check whether the accelerator can use these pixmaps. + */ + if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked) + { + return -1; + } + xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; @@ -261,16 +278,19 @@ exaTryDriverSolidFill(PicturePtr pSrc, width, height)) return 1; - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); + exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); + + REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); + pixel = exaGetPixmapFirstPixel (pSrcPix); pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); + pixmaps[0].pPix = pDstPix; + pixmaps[0].pReg = ®ion; exaDoMigration(pixmaps, 1, TRUE); - pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); - if (!pDstPix) { + if (!exaPixmapIsOffscreen(pDstPix)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 0; } @@ -300,9 +320,7 @@ exaTryDriverSolidFill(PicturePtr pSrc, while (nbox--) { - (*pExaScr->info->Solid) (pDstPix, - pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, - pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); + (*pExaScr->info->Solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, pbox->y2); pbox++; } @@ -333,24 +351,28 @@ exaTryDriverComposite(CARD8 op, int nbox; int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; + ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; struct _Pixmap scratch; ExaMigrationRec pixmaps[3]; pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); + pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + pDstPix = exaGetDrawablePixmap(pDst->pDrawable); - if (pMask) + pDstExaPix = ExaGetPixmapPriv(pDstPix); + + if (pMask) { pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); + pMaskExaPix = ExaGetPixmapPriv(pMaskPix); + } - /* Bail if we might exceed coord limits by rendering from/to these. We - * should really be making some scratch pixmaps with offsets and coords - * adjusted to deal with this, but it hasn't been done yet. + /* Check whether the accelerator can use these pixmaps. + * FIXME: If it cannot, use temporary pixmaps so that the drawing + * happens within limits. */ - if (pSrcPix->drawable.width > pExaScr->info->maxX || - pSrcPix->drawable.height > pExaScr->info->maxY || - pDstPix->drawable.width > pExaScr->info->maxX || - pDstPix->drawable.height > pExaScr->info->maxY || - (pMask && (pMaskPix->drawable.width > pExaScr->info->maxX || - pMaskPix->drawable.height > pExaScr->info->maxY))) + if (pSrcExaPix->accel_blocked || + pDstExaPix->accel_blocked || + (pMask && (pMaskExaPix->accel_blocked))) { return -1; } @@ -366,28 +388,34 @@ exaTryDriverComposite(CARD8 op, xSrc += pSrc->pDrawable->x; ySrc += pSrc->pDrawable->y; - if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - width, height)) - return 1; - if (pExaScr->info->CheckComposite && !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return -1; } + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + return 1; + + exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); + + REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); + pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = exaOpReadsDestination(op); - pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); + pixmaps[0].pPix = pDstPix; + pixmaps[0].pReg = pixmaps[0].as_src ? NULL : ®ion; pixmaps[1].as_dst = FALSE; pixmaps[1].as_src = TRUE; - pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable); + pixmaps[1].pPix = pSrcPix; + pixmaps[1].pReg = NULL; if (pMask) { pixmaps[2].as_dst = FALSE; pixmaps[2].as_src = TRUE; - pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable); + pixmaps[2].pPix = pMaskPix; + pixmaps[2].pReg = NULL; exaDoMigration(pixmaps, 3, TRUE); } else { exaDoMigration(pixmaps, 2, TRUE); @@ -397,9 +425,8 @@ exaTryDriverComposite(CARD8 op, if (pMask) pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y); - pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y); - if (!pDstPix) { + if (!exaPixmapIsOffscreen(pDstPix)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 0; } @@ -429,21 +456,21 @@ exaTryDriverComposite(CARD8 op, nbox = REGION_NUM_RECTS(®ion); pbox = REGION_RECTS(®ion); - xMask -= xDst; - yMask -= yDst; + xMask = xMask + mask_off_x - xDst - dst_off_x; + yMask = yMask + mask_off_y - yDst - dst_off_y; - xSrc -= xDst; - ySrc -= yDst; + xSrc = xSrc + src_off_x - xDst - dst_off_x; + ySrc = ySrc + src_off_y - yDst - dst_off_y; while (nbox--) { (*pExaScr->info->Composite) (pDstPix, - pbox->x1 + xSrc + src_off_x, - pbox->y1 + ySrc + src_off_y, - pbox->x1 + xMask + mask_off_x, - pbox->y1 + yMask + mask_off_y, - pbox->x1 + dst_off_x, - pbox->y1 + dst_off_y, + pbox->x1 + xSrc, + pbox->y1 + ySrc, + pbox->x1 + xMask, + pbox->y1 + yMask, + pbox->x1, + pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; @@ -519,9 +546,6 @@ exaTryMagicTwoPassCompositeHelper(CARD8 op, CARD16 height) { ExaScreenPriv (pDst->pDrawable->pScreen); - DrawablePtr pDstDraw = pDst->pDrawable; - PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDstDraw); - int xoff, yoff; assert(op == PictOpOver); @@ -540,12 +564,6 @@ exaTryMagicTwoPassCompositeHelper(CARD8 op, exaComposite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); - exaGetDrawableDeltas(pDstDraw, pDstPixmap, &xoff, &yoff); - xoff += pDstDraw->x; - yoff += pDstDraw->y; - exaPixmapDirty(pDstPixmap, xDst + xoff, yDst + yoff, xDst + xoff + width, - yDst + yoff + height); - /* Then, add in the source value times the destination alpha factors (1.0). */ exaComposite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, @@ -572,28 +590,7 @@ exaComposite(CARD8 op, int ret = -1; Bool saveSrcRepeat = pSrc->repeat; Bool saveMaskRepeat = pMask ? pMask->repeat : 0; - ExaMigrationRec pixmaps[3]; - int npixmaps = 1; - PixmapPtr pSrcPixmap = NULL; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = exaOpReadsDestination(op); - pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); - - if (pSrc->pDrawable) { - pSrcPixmap = exaGetDrawablePixmap (pSrc->pDrawable); - pixmaps[npixmaps].as_dst = FALSE; - pixmaps[npixmaps].as_src = TRUE; - pixmaps[npixmaps].pPix = pSrcPixmap; - npixmaps++; - } - - if (pMask && pMask->pDrawable) { - pixmaps[npixmaps].as_dst = FALSE; - pixmaps[npixmaps].as_src = TRUE; - pixmaps[npixmaps].pPix = exaGetDrawablePixmap (pMask->pDrawable); - npixmaps++; - } + RegionRec region; /* We currently don't support acceleration of gradients, or other pictures * with a NULL pDrawable. @@ -629,10 +626,10 @@ exaComposite(CARD8 op, if (ret == 1) goto done; } - else if (pSrcPixmap && !pSrc->repeat && !pSrc->transform) + else if (pSrc->pDrawable != NULL && + !pSrc->repeat && + !pSrc->transform) { - RegionRec region; - xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; @@ -651,11 +648,12 @@ exaComposite(CARD8 op, REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); goto done; } - else if (pSrcPixmap && !pSrc->transform && + else if (pSrc->pDrawable != NULL && + pSrc->pDrawable->type == DRAWABLE_PIXMAP && + !pSrc->transform && pSrc->repeatType == RepeatNormal) { - RegionRec region; - DDXPointRec srcOrg; + DDXPointRec patOrg; /* Let's see if the driver can do the repeat in one go */ if (pExaScr->info->PrepareComposite && !pSrc->alphaMap && @@ -679,11 +677,14 @@ exaComposite(CARD8 op, width, height)) goto done; - srcOrg.x = (xSrc - xDst) % pSrcPixmap->drawable.width; - srcOrg.y = (ySrc - yDst) % pSrcPixmap->drawable.height; + /* pattern origin is the point in the destination drawable + * corresponding to (0,0) in the source */ + patOrg.x = xDst - xSrc; + patOrg.y = yDst - ySrc; - ret = exaFillRegionTiled(pDst->pDrawable, ®ion, pSrcPixmap, - &srcOrg, FB_ALLONES, GXcopy); + ret = exaFillRegionTiled(pDst->pDrawable, ®ion, + (PixmapPtr)pSrc->pDrawable, + &patOrg, FB_ALLONES, GXcopy); REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); @@ -700,8 +701,6 @@ exaComposite(CARD8 op, pMask->repeat = 0; if (pExaScr->info->PrepareComposite && - (!pSrc->repeat || pSrc->repeatType == RepeatNormal) && - (!pMask || !pMask->repeat || pMask->repeatType == RepeatNormal) && !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) { Bool isSrcSolid; @@ -738,7 +737,6 @@ fallback: exaPrintCompositeFallback (op, pSrc, pMask, pDst); #endif - exaDoMigration(pixmaps, npixmaps, FALSE); ExaCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); @@ -754,7 +752,7 @@ done: * of PolyFillRect to initialize the pixmap after creating it, to prevent * the pixmap from being migrated. * - * See the comments about exaTrapezoids. + * See the comments about exaTrapezoids and exaTriangles. */ static PicturePtr exaCreateAlphaPicture (ScreenPtr pScreen, @@ -783,7 +781,7 @@ exaCreateAlphaPicture (ScreenPtr pScreen, } pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - pPictFormat->depth); + pPictFormat->depth, 0); if (!pPixmap) return 0; pGC = GetScratchGC (pPixmap->drawable.depth, pScreen); @@ -826,36 +824,70 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst, { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec bounds; + Bool direct = op == PictOpAdd && miIsSolidAlpha (pSrc); + + if (maskFormat || direct) { + miTrapezoidBounds (ntrap, traps, &bounds); + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + } /* * Check for solid alpha add */ - if (op == PictOpAdd && miIsSolidAlpha (pSrc)) + if (direct) { + DrawablePtr pDraw = pDst->pDrawable; + PixmapPtr pixmap = exaGetDrawablePixmap (pDraw); + ExaPixmapPriv (pixmap); + RegionRec migration; + RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); + int xoff, yoff; + + exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff); + + xoff += pDraw->x; + yoff += pDraw->y; + + bounds.x1 += xoff; + bounds.y1 += yoff; + bounds.x2 += xoff; + bounds.y2 += yoff; + + REGION_INIT(pScreen, &migration, &bounds, 1); + REGION_UNION(pScreen, pending_damage, pending_damage, &migration); + REGION_UNINIT(pScreen, &migration); + + exaPrepareAccess(pDraw, EXA_PREPARE_DEST); + for (; ntrap; ntrap--, traps++) (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0); + + exaFinishAccess(pDraw, EXA_PREPARE_DEST); } else if (maskFormat) { PicturePtr pPicture; - BoxRec bounds; INT16 xDst, yDst; INT16 xRel, yRel; xDst = traps[0].left.p1.x >> 16; yDst = traps[0].left.p1.y >> 16; - miTrapezoidBounds (ntrap, traps, &bounds); - if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return; pPicture = exaCreateAlphaPicture (pScreen, pDst, maskFormat, bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); if (!pPicture) return; + + exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); for (; ntrap; ntrap--, traps++) (*ps->RasterizeTrapezoid) (pPicture, traps, -bounds.x1, -bounds.y1); + exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + xRel = bounds.x1 + xSrc - xDst; yRel = bounds.y1 + ySrc - yDst; CompositePicture (op, pSrc, pPicture, pDst, @@ -875,411 +907,100 @@ exaTrapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst, } } -#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) - /** - * exaRasterizeTrapezoid is just a wrapper around the software implementation. + * exaTriangles is essentially a copy of miTriangles that uses + * exaCreateAlphaPicture instead of miCreateAlphaPicture. * - * The trapezoid specification is basically too hard to be done in hardware (at - * the very least, without programmability), so we just do the appropriate - * Prepare/FinishAccess for it before using fbtrap.c. - */ -void -exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, - int x_off, int y_off) -{ - DrawablePtr pDraw = pPicture->pDrawable; - ExaMigrationRec pixmaps[1]; - int xoff, yoff; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = exaGetDrawablePixmap (pDraw); - exaDoMigration(pixmaps, 1, FALSE); - - exaPrepareAccess(pDraw, EXA_PREPARE_DEST); - fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); - exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff); - exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff, - pDraw->x + xoff + pDraw->width, - pDraw->y + yoff + pDraw->height); - exaFinishAccess(pDraw, EXA_PREPARE_DEST); -} - -/** - * exaAddTriangles does migration and syncing before dumping down to the - * software implementation. + * The problem with miCreateAlphaPicture is that it calls PolyFillRect + * to initialize the contents after creating the pixmap, which + * causes the pixmap to be moved in for acceleration. The subsequent + * call to AddTriangles won't be accelerated however, which forces the pixmap + * to be moved out again. + * + * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect + * to initialize the contents. */ void -exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, - xTriangle *tris) +exaTriangles (CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle *tris) { - DrawablePtr pDraw = pPicture->pDrawable; - ExaMigrationRec pixmaps[1]; - int xoff, yoff; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = exaGetDrawablePixmap (pDraw); - exaDoMigration(pixmaps, 1, FALSE); - - exaPrepareAccess(pDraw, EXA_PREPARE_DEST); - fbAddTriangles(pPicture, x_off, y_off, ntri, tris); - exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff); - exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff, - pDraw->x + xoff + pDraw->width, - pDraw->y + yoff + pDraw->height); - exaFinishAccess(pDraw, EXA_PREPARE_DEST); -} - -/** - * Returns TRUE if the glyphs in the lists intersect. Only checks based on - * bounding box, which appears to be good enough to catch most cases at least. - */ -static Bool -exaGlyphsIntersect(int nlist, GlyphListPtr list, GlyphPtr *glyphs) -{ - int x1, x2, y1, y2; - int n; - GlyphPtr glyph; - int x, y; - BoxRec extents; - Bool first = TRUE; - - x = 0; - y = 0; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) { - glyph = *glyphs++; - - if (glyph->info.width == 0 || glyph->info.height == 0) { - x += glyph->info.xOff; - y += glyph->info.yOff; - continue; - } - - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - x2 = x1 + glyph->info.width; - if (x2 > MAXSHORT) - x2 = MAXSHORT; - y2 = y1 + glyph->info.height; - if (y2 > MAXSHORT) - y2 = MAXSHORT; - - if (first) { - extents.x1 = x1; - extents.y1 = y1; - extents.x2 = x2; - extents.y2 = y2; - first = FALSE; - } else { - if (x1 < extents.x2 && x2 > extents.x1 && - y1 < extents.y2 && y2 > extents.y1) - { - return TRUE; - } - - if (x1 < extents.x1) - extents.x1 = x1; - if (x2 > extents.x2) - extents.x2 = x2; - if (y1 < extents.y1) - extents.y1 = y1; - if (y2 > extents.y2) - extents.y2 = y2; - } - x += glyph->info.xOff; - y += glyph->info.yOff; - } - } + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec bounds; + Bool direct = op == PictOpAdd && miIsSolidAlpha (pSrc); - return FALSE; -} + if (maskFormat || direct) { + miTriangleBounds (ntri, tris, &bounds); -/* exaGlyphs is a slight variation on miGlyphs, to support acceleration. The - * issue is that miGlyphs' use of ModifyPixmapHeader makes it impossible to - * migrate these pixmaps. So, instead we create a pixmap at the beginning of - * the loop and upload each glyph into the pixmap before compositing. - */ -void -exaGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs) -{ - ExaScreenPriv (pDst->pDrawable->pScreen); - PixmapPtr pPixmap = NULL; - PicturePtr pPicture; - PixmapPtr pMaskPixmap = NULL; - PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDst->pDrawable); - PicturePtr pMask; - ScreenPtr pScreen = pDst->pDrawable->pScreen; - int width = 0, height = 0; - int x, y, x1, y1, xoff, yoff; - int xDst = list->xOff, yDst = list->yOff; - int n; - int error; - BoxRec extents; - CARD32 component_alpha; - - /* If we have a mask format but it's the same as all the glyphs and - * the glyphs don't intersect, we can avoid accumulating the glyphs in the - * temporary picture. - */ - if (maskFormat != NULL) { - Bool sameFormat = TRUE; - int i; - - for (i = 0; i < nlist; i++) { - if (maskFormat->format != list[i].format->format) { - sameFormat = FALSE; - break; - } - } - if (sameFormat) { - if (!exaGlyphsIntersect(nlist, list, glyphs)) { - maskFormat = NULL; - } - } + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; } - /* If the driver doesn't support accelerated composite, there's no point in - * going to this extra work. Assume that any driver that supports Composite - * will be able to support component alpha using the two-pass helper. + /* + * Check for solid alpha add */ - if (!pExaScr->info->PrepareComposite) + if (direct) { - miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); - return; - } + DrawablePtr pDraw = pDst->pDrawable; + PixmapPtr pixmap = exaGetDrawablePixmap (pDraw); + ExaPixmapPriv (pixmap); + RegionRec migration; + RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); + int xoff, yoff; - if (maskFormat) - { - GCPtr pGC; - xRectangle rect; - - miGlyphExtents (nlist, list, glyphs, &extents); + exaGetDrawableDeltas(pDraw, pixmap, &xoff, &yoff); - extents.x1 = max(extents.x1, 0); - extents.y1 = max(extents.y1, 0); - extents.x2 = min(extents.x2, pDst->pDrawable->width); - extents.y2 = min(extents.y2, pDst->pDrawable->height); + xoff += pDraw->x; + yoff += pDraw->y; - if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) - return; - width = extents.x2 - extents.x1; - height = extents.y2 - extents.y1; - pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - maskFormat->depth); - if (!pMaskPixmap) - return; - component_alpha = NeedsComponent(maskFormat->format); - pMask = CreatePicture (0, &pMaskPixmap->drawable, - maskFormat, CPComponentAlpha, &component_alpha, - serverClient, &error); - if (!pMask) - { - (*pScreen->DestroyPixmap) (pMaskPixmap); - return; - } - ValidatePicture(pMask); - pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); - ValidateGC (&pMaskPixmap->drawable, pGC); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); - exaPixmapDirty(pMaskPixmap, 0, 0, width, height); - FreeScratchGC (pGC); - x = -extents.x1; - y = -extents.y1; - } - else - { - pMask = pDst; - x = 0; - y = 0; - } + bounds.x1 += xoff; + bounds.y1 += yoff; + bounds.x2 += xoff; + bounds.y2 += yoff; - exaGetDrawableDeltas(pDst->pDrawable, pDstPixmap, &xoff, &yoff); + REGION_INIT(pScreen, &migration, &bounds, 1); + REGION_UNION(pScreen, pending_damage, pending_damage, &migration); + REGION_UNINIT(pScreen, &migration); - while (nlist--) + exaPrepareAccess(pDraw, EXA_PREPARE_DEST); + (*ps->AddTriangles) (pDst, 0, 0, ntri, tris); + exaFinishAccess(pDraw, EXA_PREPARE_DEST); + } + else if (maskFormat) { - GCPtr pGC = NULL; - int maxwidth = 0, maxheight = 0, i; - ExaMigrationRec pixmaps[1]; - PixmapPtr pScratchPixmap = NULL; - - x += list->xOff; - y += list->yOff; - n = list->len; - for (i = 0; i < n; i++) { - if (glyphs[i]->info.width > maxwidth) - maxwidth = glyphs[i]->info.width; - if (glyphs[i]->info.height > maxheight) - maxheight = glyphs[i]->info.height; - } - if (maxwidth == 0 || maxheight == 0) { - while (n--) - { - GlyphPtr glyph; - - glyph = *glyphs++; - x += glyph->info.xOff; - y += glyph->info.yOff; - } - list++; - continue; - } - - /* Create the (real) temporary pixmap to store the current glyph in */ - pPixmap = (*pScreen->CreatePixmap) (pScreen, maxwidth, maxheight, - list->format->depth); - if (!pPixmap) - return; + PicturePtr pPicture; + INT16 xDst, yDst; + INT16 xRel, yRel; + + xDst = tris[0].p1.x >> 16; + yDst = tris[0].p1.y >> 16; - /* Create a temporary picture to wrap the temporary pixmap, so it can be - * used as a source for Composite. - */ - component_alpha = NeedsComponent(list->format->format); - pPicture = CreatePicture (0, &pPixmap->drawable, list->format, - CPComponentAlpha, &component_alpha, - serverClient, &error); - if (!pPicture) { - (*pScreen->DestroyPixmap) (pPixmap); + pPicture = exaCreateAlphaPicture (pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) return; - } - ValidatePicture(pPicture); - - /* Give the temporary pixmap an initial kick towards the screen, so - * it'll stick there. - */ - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = pPixmap; - exaDoMigration (pixmaps, 1, pExaScr->info->PrepareComposite != NULL); - while (n--) - { - GlyphPtr glyph = *glyphs++; - pointer glyphdata = (pointer) (glyph + 1); - DrawablePtr pCmpDrw = (maskFormat ? pMask : pDst)->pDrawable; - - x1 = x - glyph->info.x; - y1 = y - glyph->info.y; - - if (x1 >= pCmpDrw->width || y1 >= pCmpDrw->height || - glyph->info.width == 0 || glyph->info.height == 0 || - (x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0) - goto nextglyph; - - (*pScreen->ModifyPixmapHeader) (pScratchPixmap, - glyph->info.width, - glyph->info.height, - 0, 0, -1, glyphdata); - - /* Copy the glyph data into the proper pixmap instead of a fake. - * First we try to use UploadToScreen, if we can, then we fall back - * to a plain exaCopyArea in case of failure. - */ - if (pExaScr->info->UploadToScreen && - exaPixmapIsOffscreen(pPixmap) && - (*pExaScr->info->UploadToScreen) (pPixmap, 0, 0, - glyph->info.width, - glyph->info.height, - glyphdata, - PixmapBytePad(glyph->info.width, - list->format->depth))) - { - exaMarkSync (pScreen); - } else { - /* Set up the scratch pixmap/GC for doing a CopyArea. */ - if (pScratchPixmap == NULL) { - /* Get a scratch pixmap to wrap the original glyph data */ - pScratchPixmap = GetScratchPixmapHeader (pScreen, - glyph->info.width, - glyph->info.height, - list->format->depth, - list->format->depth, - -1, glyphdata); - if (!pScratchPixmap) { - FreePicture(pPicture, 0); - (*pScreen->DestroyPixmap) (pPixmap); - return; - } + exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris); + exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - /* Get a scratch GC with which to copy the glyph data from - * scratch to temporary - */ - pGC = GetScratchGC (list->format->depth, pScreen); - ValidateGC (&pPixmap->drawable, pGC); - } else { - (*pScreen->ModifyPixmapHeader) (pScratchPixmap, - glyph->info.width, - glyph->info.height, - 0, 0, -1, glyphdata); - pScratchPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - } - - exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC, - 0, 0, glyph->info.width, glyph->info.height, 0, 0); - } - - exaPixmapDirty (pPixmap, 0, 0, - glyph->info.width, glyph->info.height); - - if (maskFormat) - { - exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0, - x1, y1, glyph->info.width, glyph->info.height); - exaPixmapDirty(pMaskPixmap, x1, y1, x1 + glyph->info.width, - y1 + glyph->info.height); - } - else - { - exaComposite (op, pSrc, pPicture, pDst, - xSrc + x1 - xDst, ySrc + y1 - yDst, - 0, 0, x1, y1, glyph->info.width, - glyph->info.height); - x1 += pDst->pDrawable->x + xoff; - y1 += pDst->pDrawable->y + yoff; - exaPixmapDirty(pDstPixmap, x1, y1, x1 + glyph->info.width, - y1 + glyph->info.height); - } -nextglyph: - x += glyph->info.xOff; - y += glyph->info.yOff; - } - list++; - if (pGC != NULL) - FreeScratchGC (pGC); - FreePicture ((pointer) pPicture, 0); - (*pScreen->DestroyPixmap) (pPixmap); - if (pScratchPixmap != NULL) - FreeScratchPixmapHeader (pScratchPixmap); + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture (op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture (pPicture, 0); } - if (maskFormat) + else { - x = extents.x1; - y = extents.y1; - exaComposite (op, pSrc, pMask, pDst, xSrc + x - xDst, ySrc + y - yDst, - 0, 0, x, y, width, height); - FreePicture ((pointer) pMask, (XID) 0); - (*pScreen->DestroyPixmap) (pMaskPixmap); + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8); + + for (; ntri; ntri--, tris++) + exaTriangles (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris); } } |