diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-20 10:26:59 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-24 18:31:15 +0100 |
commit | 91f560034fc2695680d1208a78fc56d814b0da79 (patch) | |
tree | 8dd35a2ec95db86643152b37d4b3c68c8ca6f34f /uxa | |
parent | e3ece83f577d3664962edeec6ab5bdc41c5d77cf (diff) |
uxa: Composite glyphs directly onto dst when possible.
Without using a mask and compositing directly onto the destination,
takes us from 580 kglyphs/s to 850 kglyphs/s on i945 [x11perf -aa10text].
However, the extra intersection check almost entirely cancels out the
speed up and we discover that the glyphs in x11perf are always
overlapping. Nothing is ever easy.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'uxa')
-rw-r--r-- | uxa/uxa-glyphs.c | 348 | ||||
-rw-r--r-- | uxa/uxa-priv.h | 14 | ||||
-rw-r--r-- | uxa/uxa-render.c | 120 |
3 files changed, 324 insertions, 158 deletions
diff --git a/uxa/uxa-glyphs.c b/uxa/uxa-glyphs.c index f8bb7f54..921297a5 100644 --- a/uxa/uxa-glyphs.c +++ b/uxa/uxa-glyphs.c @@ -205,6 +205,8 @@ static Bool uxa_realize_glyph_caches(ScreenPtr pScreen, unsigned int format) if (!pPicture) return FALSE; + ValidatePicture(pPicture); + /* And store the picture in all the caches for the format */ for (i = 0; i < UXA_NUM_GLYPH_CACHES; i++) { @@ -573,41 +575,294 @@ uxa_buffer_glyph(ScreenPtr pScreen, return UXA_GLYPH_SUCCESS; } -static void uxa_glyphs_to_mask(PicturePtr pMask, uxa_glyph_buffer_t * buffer) +static PicturePtr +uxa_glyphs_acquire_source(ScreenPtr screen, + PicturePtr src, + INT16 x, INT16 y, + const uxa_glyph_buffer_t * buffer, + INT16 * out_x, INT16 * out_y) +{ + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + int x1, y1, x2, y2; + int width, height; + int i; + + if (uxa_screen->info->check_composite_texture && + uxa_screen->info->check_composite_texture(screen, src)) { + if (src->pDrawable) { + *out_x = x + src->pDrawable->x; + *out_y = y + src->pDrawable->y; + } else { + *out_x = x; + *out_y = y; + } + return src; + } + + for (i = 0; i < buffer->count; i++) { + const uxa_composite_rect_t *r = &buffer->rects[i]; + + if (r->xDst < x1) + x1 = r->xDst; + if (r->xDst + r->width > x2) + x2 = r->xDst + r->width; + + if (r->yDst < y1) + y1 = r->yDst; + if (r->yDst + r->height > y2) + y2 = r->yDst + r->height; + } + + width = x2 - x1; + height = y2 - y1; + + if (src->pDrawable) { + PicturePtr dst; + + dst = uxa_acquire_drawable(screen, src, + x, y, + width, height, + out_x, out_y); + if (uxa_screen->info->check_composite_texture && + !uxa_screen->info->check_composite_texture(screen, dst)) { + if (dst != src) + FreePicture(dst, 0); + return 0; + } + + return dst; + } + + *out_x = 0; + *out_y = 0; + return uxa_acquire_pattern(screen, src, + PICT_a8r8g8b8, x, y, width, height); +} + +static int +uxa_glyphs_try_driver_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + const uxa_glyph_buffer_t * buffer, + INT16 xSrc, INT16 ySrc, + INT16 xDst, INT16 yDst) { - uxa_composite_rects(PictOpAdd, buffer->source, pMask, - buffer->count, buffer->rects); + ScreenPtr screen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(screen); + PicturePtr localSrc; + int src_off_x = 0, src_off_y = 0, mask_off_x, mask_off_y, dst_off_x, dst_off_y; + PixmapPtr pSrcPix = NULL, pMaskPix, pDstPix; + const uxa_composite_rect_t *rects; + int nrect; + + if (uxa_screen->info->check_composite && + !(*uxa_screen->info->check_composite) (op, pSrc, buffer->source, pDst)) { + return -1; + } - buffer->count = 0; - buffer->source = NULL; + pDstPix = + uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + + pMaskPix = + uxa_get_offscreen_pixmap(buffer->source->pDrawable, &mask_off_x, &mask_off_y); + if(!pMaskPix) + return -1; + + localSrc = uxa_glyphs_acquire_source(screen, pSrc, + xSrc, ySrc, + buffer, + &xSrc, &ySrc); + if (!localSrc) + return 0; + + if (localSrc->pDrawable) { + pSrcPix = + uxa_get_offscreen_pixmap(localSrc->pDrawable, &src_off_x, &src_off_y); + if (!pSrcPix) { + if (localSrc != pSrc) + FreePicture(localSrc, 0); + return 0; + } + + xSrc += localSrc->pDrawable->x; + ySrc += localSrc->pDrawable->y; + } + + if (!(*uxa_screen->info->prepare_composite) + (op, localSrc, buffer->source, pDst, pSrcPix, pMaskPix, pDstPix)) { + if (localSrc != pSrc) + FreePicture(localSrc, 0); + return -1; + } + + nrect = buffer->count; + rects = buffer->rects; + do { + INT16 _xDst = rects->xDst + pDst->pDrawable->x; + INT16 _yDst = rects->yDst + pDst->pDrawable->y; + INT16 _xMask = rects->xSrc + buffer->source->pDrawable->x; + INT16 _yMask = rects->ySrc + buffer->source->pDrawable->y; + INT16 _xSrc = xSrc, _ySrc = ySrc; + + RegionRec region; + BoxPtr pbox; + int nbox; + + if (!miComputeCompositeRegion(®ion, + localSrc, buffer->source, pDst, + _xSrc, _ySrc, + _xMask, _yMask, + _xDst, _yDst, + rects->width, rects->height)) + goto next_rect; + + _xSrc += src_off_x - _xDst; + _ySrc += src_off_y - _yDst; + _xMask += mask_off_x - _xDst; + _yMask += mask_off_y - _yDst; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + while (nbox--) { + (*uxa_screen->info->composite) (pDstPix, + pbox->x1 + _xSrc, + pbox->y1 + _ySrc, + pbox->x1 + _xMask, + pbox->y1 + _yMask, + pbox->x1 + dst_off_x, + pbox->y1 + dst_off_y, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } + +next_rect: + REGION_UNINIT(screen, ®ion); + + rects++; + } while (--nrect); + (*uxa_screen->info->done_composite) (pDstPix); + + if (localSrc != pSrc) + FreePicture(localSrc, 0); + + return 1; } static void uxa_glyphs_to_dst(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - uxa_glyph_buffer_t * buffer, - INT16 xSrc, INT16 ySrc, INT16 xDst, INT16 yDst) + const uxa_glyph_buffer_t * buffer, + INT16 xSrc, INT16 ySrc, + INT16 xDst, INT16 yDst) { - int i; + if (uxa_glyphs_try_driver_composite(op, pSrc, pDst, buffer, + xSrc, ySrc, + xDst, yDst) != 1) { + int i; - for (i = 0; i < buffer->count; i++) { - uxa_composite_rect_t *rect = &buffer->rects[i]; + for (i = 0; i < buffer->count; i++) { + const uxa_composite_rect_t *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); + 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); + } } +} + +static int +uxa_glyphs_try_driver_add_to_mask(PicturePtr pDst, + const uxa_glyph_buffer_t *buffer) +{ + uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); + int src_off_x, src_off_y, dst_off_x, dst_off_y; + PixmapPtr pSrcPix, pDstPix; + const uxa_composite_rect_t *rects; + int nrect; + + if (uxa_screen->info->check_composite && + !(*uxa_screen->info->check_composite) (PictOpAdd, buffer->source, NULL, pDst)) { + return -1; + } + + pDstPix = + uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + + pSrcPix = + uxa_get_offscreen_pixmap(buffer->source->pDrawable, &src_off_x, &src_off_y); + if(!pSrcPix) + return -1; + + if (!(*uxa_screen->info->prepare_composite) + (PictOpAdd, buffer->source, NULL, pDst, pSrcPix, NULL, pDstPix)) + return -1; + + rects = buffer->rects; + nrect = buffer->count; + do { + INT16 xDst = rects->xDst + pDst->pDrawable->x; + INT16 yDst = rects->yDst + pDst->pDrawable->y; + INT16 xSrc = rects->xSrc + buffer->source->pDrawable->x; + INT16 ySrc = rects->ySrc + buffer->source->pDrawable->y; + + RegionRec region; + BoxPtr pbox; + int nbox; + + if (!miComputeCompositeRegion(®ion, buffer->source, NULL, pDst, + xSrc, ySrc, 0, 0, xDst, yDst, + rects->width, rects->height)) + goto next_rect; + + xSrc += src_off_x - xDst; + ySrc += src_off_y - yDst; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + + while (nbox--) { + (*uxa_screen->info->composite) (pDstPix, + pbox->x1 + xSrc, + pbox->y1 + ySrc, + 0, 0, + pbox->x1 + dst_off_x, + pbox->y1 + dst_off_y, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } + +next_rect: + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + + rects++; + } while (--nrect); + (*uxa_screen->info->done_composite) (pDstPix); + + return 1; +} + +static void uxa_glyphs_to_mask(PicturePtr pDst, const uxa_glyph_buffer_t *buffer) +{ + if (uxa_glyphs_try_driver_add_to_mask(pDst, buffer) != 1) { + int i; + + for (i = 0; i < buffer->count; i++) { + const uxa_composite_rect_t *r = &buffer->rects[i]; - buffer->count = 0; - buffer->source = NULL; + uxa_check_composite(PictOpAdd, buffer->source, NULL, pDst, + r->xSrc, r->ySrc, + 0, 0, + r->xDst, r->yDst, + r->width, r->height); + } + } } /* Cut and paste from render/glyph.c - probably should export it instead */ @@ -857,9 +1112,10 @@ uxa_glyphs(CARD8 op, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { + ScreenPtr pScreen = pDst->pDrawable->pScreen; + uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); PixmapPtr pMaskPixmap = 0; PicturePtr pMask; - ScreenPtr pScreen = pDst->pDrawable->pScreen; int width = 0, height = 0; int x, y; int xDst = list->xOff, yDst = list->yOff; @@ -870,32 +1126,38 @@ uxa_glyphs(CARD8 op, CARD32 component_alpha; uxa_glyph_buffer_t buffer; - if (!uxa_drawable_is_offscreen(pDst->pDrawable)) { + if (!uxa_screen->info->prepare_composite || + uxa_screen->swappedOut || + !uxa_drawable_is_offscreen(pDst->pDrawable) || + pDst->alphaMap || pSrc->alphaMap) { uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); return; } - /* 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. - */ + ValidatePicture(pSrc); + ValidatePicture(pDst); + if (!maskFormat) { - Bool sameFormat = TRUE; - int i; + /* If we don't have a mask format but all the glyphs have the same format, + * require ComponentAlpha and don't intersect, use the glyph format as mask + * format for the full benefits of the glyph cache. + */ + if (NeedsComponent(list[0].format->format)) { + Bool sameFormat = TRUE; + int i; - maskFormat = list[0].format; + maskFormat = list[0].format; - for (i = 0; i < nlist; i++) { - if (maskFormat->format != list[i].format->format) { - sameFormat = FALSE; - break; + for (i = 0; i < nlist; i++) { + if (maskFormat->format != list[i].format->format) { + sameFormat = FALSE; + break; + } } - } - if (!sameFormat || (maskFormat->depth != 1 && - uxa_glyphs_intersect(nlist, list, - glyphs))) { - maskFormat = NULL; + if (!sameFormat || + uxa_glyphs_intersect(nlist, list, glyphs)) + maskFormat = NULL; } } @@ -942,11 +1204,14 @@ uxa_glyphs(CARD8 op, FreeScratchGC(pGC); x = -extents.x1; y = -extents.y1; + + ValidatePicture(pMask); } else { pMask = pDst; x = 0; y = 0; } + buffer.count = 0; buffer.source = NULL; while (nlist--) { @@ -966,6 +1231,9 @@ uxa_glyphs(CARD8 op, &buffer, xSrc, ySrc, xDst, yDst); + buffer.count = 0; + buffer.source = NULL; + uxa_buffer_glyph(pScreen, &buffer, glyph, x, y); } diff --git a/uxa/uxa-priv.h b/uxa/uxa-priv.h index 8ff2c9c6..bace6798 100644 --- a/uxa/uxa-priv.h +++ b/uxa/uxa-priv.h @@ -437,6 +437,20 @@ uxa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PicturePtr uxa_acquire_solid(ScreenPtr screen, SourcePict *source); +PicturePtr +uxa_acquire_drawable(ScreenPtr pScreen, + PicturePtr pSrc, + INT16 x, INT16 y, + CARD16 width, CARD16 height, + INT16 * out_x, INT16 * out_y); + +PicturePtr +uxa_acquire_pattern(ScreenPtr pScreen, + PicturePtr pSrc, + pixman_format_code_t format, + INT16 x, INT16 y, + CARD16 width, CARD16 height); + Bool uxa_get_rgba_from_pixel(CARD32 pixel, CARD16 * red, diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c index 139d42e8..c866b854 100644 --- a/uxa/uxa-render.c +++ b/uxa/uxa-render.c @@ -664,7 +664,7 @@ DONE: return picture; } -static PicturePtr +PicturePtr uxa_acquire_pattern(ScreenPtr pScreen, PicturePtr pSrc, pixman_format_code_t format, @@ -757,7 +757,7 @@ uxa_render_picture(ScreenPtr screen, return picture; } -static PicturePtr +PicturePtr uxa_acquire_drawable(ScreenPtr pScreen, PicturePtr pSrc, INT16 x, INT16 y, @@ -1044,122 +1044,6 @@ fallback: } static int -uxa_try_driver_composite_rects(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - int nrect, uxa_composite_rect_t * rects) -{ - uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen); - int src_off_x, src_off_y, dst_off_x, dst_off_y; - PixmapPtr pSrcPix, pDstPix; - - if (!uxa_screen->info->prepare_composite || uxa_screen->swappedOut) - return -1; - - if (uxa_screen->info->check_composite && - !(*uxa_screen->info->check_composite) (op, pSrc, NULL, pDst)) { - return -1; - } - - pDstPix = - uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); - if (!pDstPix) - return 0; - - pSrcPix = - uxa_get_offscreen_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y); - if (!pSrcPix) - return 0; - - if (!(*uxa_screen->info->prepare_composite) - (op, pSrc, NULL, pDst, pSrcPix, NULL, pDstPix)) - return -1; - - while (nrect--) { - INT16 xDst = rects->xDst + pDst->pDrawable->x; - INT16 yDst = rects->yDst + pDst->pDrawable->y; - INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; - INT16 ySrc = rects->ySrc + pSrc->pDrawable->y; - - RegionRec region; - BoxPtr pbox; - int nbox; - - if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst, - xSrc, ySrc, 0, 0, xDst, yDst, - rects->width, rects->height)) - goto next_rect; - - xSrc = xSrc + src_off_x - xDst; - ySrc = ySrc + src_off_y - yDst; - - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - - while (nbox--) { - (*uxa_screen->info->composite) (pDstPix, - pbox->x1 + xSrc, - pbox->y1 + ySrc, - 0, 0, - pbox->x1 + dst_off_x, - pbox->y1 + dst_off_y, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - pbox++; - } - -next_rect: - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); - - rects++; - } - (*uxa_screen->info->done_composite) (pDstPix); - - return 1; -} - -/** - * Copy a number of rectangles from source to destination in a single - * operation. This is specialized for building a glyph mask: we don'y - * have a mask argument because we don't need it for that, and we - * don't have he special-case fallbacks found in uxa_composite() - if the - * driver can support it, we use the driver functionality, otherwise we - * fallback straight to software. - */ -void -uxa_composite_rects(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, int nrect, uxa_composite_rect_t * rects) -{ - int n; - uxa_composite_rect_t *r; - - /************************************************************/ - - ValidatePicture(pSrc); - ValidatePicture(pDst); - - if (uxa_try_driver_composite_rects(op, pSrc, pDst, nrect, rects) != 1) { - uxa_print_composite_fallback("uxa_composite_rects", - op, pSrc, NULL, pDst); - - n = nrect; - r = rects; - while (n--) { - uxa_check_composite(op, pSrc, NULL, pDst, - r->xSrc, r->ySrc, - 0, 0, - r->xDst, r->yDst, - r->width, r->height); - r++; - } - } - - /************************************************************/ - -} - -static int uxa_try_driver_composite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, |