diff options
Diffstat (limited to 'xorg-server/exa/exa_glyphs.c')
-rw-r--r-- | xorg-server/exa/exa_glyphs.c | 319 |
1 files changed, 141 insertions, 178 deletions
diff --git a/xorg-server/exa/exa_glyphs.c b/xorg-server/exa/exa_glyphs.c index 93b8b36ae..d621ccf76 100644 --- a/xorg-server/exa/exa_glyphs.c +++ b/xorg-server/exa/exa_glyphs.c @@ -68,7 +68,7 @@ #define GLYPH_BUFFER_SIZE 256 typedef struct { - PicturePtr source; + PicturePtr mask; ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE]; int count; } ExaGlyphBuffer, *ExaGlyphBufferPtr; @@ -144,7 +144,7 @@ exaUnrealizeGlyphCaches(ScreenPtr pScreen, /* All caches for a single format share a single pixmap for glyph storage, * allowing mixing glyphs of different sizes without paying a penalty - * for switching between source pixmaps. (Note that for a size of font + * for switching between mask pixmaps. (Note that for a size of font * right at the border between two sizes, we might be switching for almost * every glyph.) * @@ -187,7 +187,6 @@ exaRealizeGlyphCaches(ScreenPtr pScreen, } /* Now allocate the pixmap and picture */ - pPixmap = (*pScreen->CreatePixmap) (pScreen, CACHE_PICTURE_WIDTH, height, depth, 0); @@ -205,7 +204,6 @@ exaRealizeGlyphCaches(ScreenPtr pScreen, return FALSE; /* And store the picture in all the caches for the format */ - for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; int j; @@ -374,7 +372,6 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen, PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable; ExaPixmapPriv(pGlyphPixmap); PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable; - ExaMigrationRec pixmaps[1]; if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked) goto composite; @@ -388,12 +385,16 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen, if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel) goto composite; - /* cache pixmap must be offscreen. */ - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pCachePixmap; - pixmaps[0].pReg = NULL; - exaDoMigration (pixmaps, 1, TRUE); + if (pExaScr->do_migration) { + ExaMigrationRec pixmaps[1]; + + /* cache pixmap must be offscreen. */ + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = pCachePixmap; + pixmaps[0].pReg = NULL; + exaDoMigration (pixmaps, 1, TRUE); + } if (!exaPixmapIsOffscreen(pCachePixmap)) goto composite; @@ -434,13 +435,19 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, ExaGlyphCachePtr cache, ExaGlyphBufferPtr buffer, GlyphPtr pGlyph, - int xGlyph, - int yGlyph) + PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst) { ExaCompositeRectPtr rect; int pos; - if (buffer->source && buffer->source != cache->picture) + if (buffer->mask && buffer->mask != cache->picture) return ExaGlyphNeedFlush; if (!cache->picture) { @@ -469,18 +476,19 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, * already in the output buffer were at this position in * the cache */ - pos = cache->evictionPosition; DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos)); if (buffer->count) { int x, y; int i; - + x = CACHE_X(pos); y = CACHE_Y(pos); for (i = 0; i < buffer->count; i++) { - if (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y) { + if (pSrc ? + (buffer->rects[i].xMask == x && buffer->rects[i].yMask == y) : + (buffer->rects[i].xSrc == x && buffer->rects[i].ySrc == y)) { DBG_GLYPH_CACHE((" must flush buffer\n")); return ExaGlyphNeedFlush; } @@ -498,13 +506,28 @@ exaGlyphCacheBufferGlyph(ScreenPtr pScreen, exaGlyphCacheUploadGlyph(pScreen, cache, pos, pGlyph); } - buffer->source = cache->picture; + buffer->mask = cache->picture; rect = &buffer->rects[buffer->count]; - rect->xSrc = CACHE_X(pos); - rect->ySrc = CACHE_Y(pos); - rect->xDst = xGlyph - pGlyph->info.x; - rect->yDst = yGlyph - pGlyph->info.y; + + if (pSrc) + { + rect->xSrc = xSrc; + rect->ySrc = ySrc; + rect->xMask = CACHE_X(pos); + rect->yMask = CACHE_Y(pos); + } + else + { + rect->xSrc = CACHE_X(pos); + rect->ySrc = CACHE_Y(pos); + rect->xMask = 0; + rect->yMask = 0; + } + + rect->pDst = pDst; + rect->xDst = xDst; + rect->yDst = yDst; rect->width = pGlyph->info.width; rect->height = pGlyph->info.height; @@ -520,15 +543,21 @@ static ExaGlyphCacheResult exaBufferGlyph(ScreenPtr pScreen, ExaGlyphBufferPtr buffer, GlyphPtr pGlyph, - int xGlyph, - int yGlyph) + PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst) { ExaScreenPriv(pScreen); unsigned int format = (GlyphPicture(pGlyph)[pScreen->myNum])->format; int width = pGlyph->info.width; int height = pGlyph->info.height; ExaCompositeRectPtr rect; - PicturePtr source; + PicturePtr mask; int i; if (buffer->count == GLYPH_BUFFER_SIZE) @@ -543,9 +572,15 @@ exaBufferGlyph(ScreenPtr pScreen, if (format == cache->format && width <= cache->glyphWidth && height <= cache->glyphHeight) { - ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, &pExaScr->glyphCaches[i], + ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, + &pExaScr->glyphCaches[i], buffer, - pGlyph, xGlyph, yGlyph); + pGlyph, + pSrc, + pDst, + xSrc, ySrc, + xMask, yMask, + xDst, yDst); switch (result) { case ExaGlyphFail: break; @@ -558,19 +593,21 @@ exaBufferGlyph(ScreenPtr pScreen, /* Couldn't find the glyph in the cache, use the glyph picture directly */ - source = GlyphPicture(pGlyph)[pScreen->myNum]; - if (buffer->source && buffer->source != source) + mask = GlyphPicture(pGlyph)[pScreen->myNum]; + if (buffer->mask && buffer->mask != mask) return ExaGlyphNeedFlush; - buffer->source = source; - + buffer->mask = mask; + rect = &buffer->rects[buffer->count]; - rect->xSrc = 0; - rect->ySrc = 0; - rect->xDst = xGlyph - pGlyph->info.x; - rect->yDst = yGlyph - pGlyph->info.y; - rect->width = pGlyph->info.width; - rect->height = pGlyph->info.height; + rect->xSrc = xSrc; + rect->ySrc = ySrc; + rect->xMask = xMask; + rect->yMask = yMask; + rect->xDst = xDst; + rect->yDst = yDst; + rect->width = width; + rect->height = height; buffer->count++; @@ -581,44 +618,23 @@ static void exaGlyphsToMask(PicturePtr pMask, ExaGlyphBufferPtr buffer) { - exaCompositeRects(PictOpAdd, buffer->source, pMask, + exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask, buffer->count, buffer->rects); buffer->count = 0; - buffer->source = NULL; + buffer->mask = NULL; } static void -exaGlyphsToDst(CARD8 op, - PicturePtr pSrc, +exaGlyphsToDst(PicturePtr pSrc, PicturePtr pDst, - ExaGlyphBufferPtr buffer, - INT16 xSrc, - INT16 ySrc, - INT16 xDst, - INT16 yDst) + ExaGlyphBufferPtr buffer) { - int i; - - for (i = 0; i < buffer->count; i++) { - ExaCompositeRectPtr rect = &buffer->rects[i]; - - CompositePicture (op, - pSrc, - buffer->source, - pDst, - xSrc + rect->xDst - xDst, - ySrc + rect->yDst - yDst, - rect->xSrc, - rect->ySrc, - rect->xDst, - rect->yDst, - rect->width, - rect->height); - } + exaCompositeRects(PictOpOver, pSrc, buffer->mask, pDst, buffer->count, + buffer->rects); buffer->count = 0; - buffer->source = NULL; + buffer->mask = NULL; } /* Cut and paste from render/glyph.c - probably should export it instead */ @@ -674,79 +690,6 @@ GlyphExtents (int nlist, } } -/** - * 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; - } - } - - return FALSE; -} - void exaGlyphs (CARD8 op, PicturePtr pSrc, @@ -760,11 +703,11 @@ exaGlyphs (CARD8 op, { PicturePtr pPicture; PixmapPtr pMaskPixmap = 0; - PicturePtr pMask; + PicturePtr pMask = NULL; ScreenPtr pScreen = pDst->pDrawable->pScreen; int width = 0, height = 0; int x, y; - int xDst = list->xOff, yDst = list->yOff; + int first_xOff = list->xOff, first_yOff = list->yOff; int n; GlyphPtr glyph; int error; @@ -772,31 +715,9 @@ exaGlyphs (CARD8 op, CARD32 component_alpha; ExaGlyphBuffer buffer; - /* If we don't have a mask format but all the glyphs have the same format - * and don't intersect, use the glyph format as mask format for the full - * benefits of the glyph cache. - */ - if (!maskFormat) { - Bool sameFormat = TRUE; - int i; - - maskFormat = list[0].format; - - for (i = 0; i < nlist; i++) { - if (maskFormat->format != list[i].format->format) { - sameFormat = FALSE; - break; - } - } - - if (!sameFormat || (maskFormat->depth != 1 && - exaGlyphsIntersect(nlist, list, glyphs))) { - maskFormat = NULL; - } - } - if (maskFormat) { + ExaScreenPriv(pScreen); GCPtr pGC; xRectangle rect; @@ -823,10 +744,38 @@ exaGlyphs (CARD8 op, pMask = CreatePicture (0, &pMaskPixmap->drawable, maskFormat, CPComponentAlpha, &component_alpha, serverClient, &error); - if (!pMask) + if (!pMask || + (!component_alpha && pExaScr->info->CheckComposite && + !(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, NULL, pMask))) { + PictFormatPtr argbFormat; + (*pScreen->DestroyPixmap) (pMaskPixmap); - return; + + if (!pMask) + return; + + /* The driver can't seem to composite to a8, let's try argb (but + * without component-alpha) */ + FreePicture ((pointer) pMask, (XID) 0); + + argbFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + + if (argbFormat) + maskFormat = argbFormat; + + pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + maskFormat->depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pMaskPixmap) + return; + + pMask = CreatePicture (0, &pMaskPixmap->drawable, maskFormat, 0, 0, + serverClient, &error); + if (!pMask) { + (*pScreen->DestroyPixmap) (pMaskPixmap); + return; + } } pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen); ValidateGC (&pMaskPixmap->drawable, pGC); @@ -841,12 +790,11 @@ exaGlyphs (CARD8 op, } else { - pMask = pDst; x = 0; y = 0; } buffer.count = 0; - buffer.source = NULL; + buffer.mask = NULL; while (nlist--) { x += list->xOff; @@ -857,16 +805,32 @@ exaGlyphs (CARD8 op, glyph = *glyphs++; pPicture = GlyphPicture (glyph)[pScreen->myNum]; - if (glyph->info.width > 0 && glyph->info.height > 0 && - exaBufferGlyph(pScreen, &buffer, glyph, x, y) == ExaGlyphNeedFlush) + if (glyph->info.width > 0 && glyph->info.height > 0) { + /* pGlyph->info.{x,y} compensate for empty space in the glyph. */ if (maskFormat) - exaGlyphsToMask(pMask, &buffer); + { + if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, + 0, 0, 0, 0, x - glyph->info.x, y - glyph->info.y) == ExaGlyphNeedFlush) + { + exaGlyphsToMask(pMask, &buffer); + exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, + 0, 0, 0, 0, x - glyph->info.x, y - glyph->info.y); + } + } else - exaGlyphsToDst(op, pSrc, pDst, &buffer, - xSrc, ySrc, xDst, yDst); - - exaBufferGlyph(pScreen, &buffer, glyph, x, y); + { + if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, + xSrc + (x - glyph->info.x) - first_xOff, ySrc + (y - glyph->info.y) - first_yOff, + 0, 0, x - glyph->info.x, y - glyph->info.y) + == ExaGlyphNeedFlush) + { + exaGlyphsToDst(pSrc, pDst, &buffer); + exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, + xSrc + (x - glyph->info.x) - first_xOff, ySrc + (y - glyph->info.y) - first_yOff, + 0, 0, x - glyph->info.x, y - glyph->info.y); + } + } } x += glyph->info.xOff; @@ -879,8 +843,7 @@ exaGlyphs (CARD8 op, if (maskFormat) exaGlyphsToMask(pMask, &buffer); else - exaGlyphsToDst(op, pSrc, pDst, &buffer, - xSrc, ySrc, xDst, yDst); + exaGlyphsToDst(pSrc, pDst, &buffer); } if (maskFormat) @@ -891,8 +854,8 @@ exaGlyphs (CARD8 op, pSrc, pMask, pDst, - xSrc + x - xDst, - ySrc + y - yDst, + xSrc + x - first_xOff, + ySrc + y - first_yOff, 0, 0, x, y, width, height); |