[Intel-gfx] [PATCH] Avoid fallbacks for gradient patterns
Eric Anholt
eric at anholt.net
Fri Sep 4 21:35:29 CEST 2009
On Fri, 2009-09-04 at 20:26 +0100, Chris Wilson wrote:
> While not yet fully accelerating gradient patterns, by using pixman to
> compute the gradient image and copying that to a pixmap to use as the
> source, we avoid incurring the GPU stall suffered currently from
> reading back the destination surface.
The destination Picture (the one passed in to our uxa hooks) is supposed
to always have a pDrawable, and if it doesn't, that should have been
caught at a higher level.
>
> Speedups on i915:
> firefox-talos-svg: 710378.14 -> 549262.96: 1.29x speedup
>
> No slowdowns.
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
> src/i830_render.c | 14 ++-
> src/i915_render.c | 12 ++-
> src/i965_render.c | 14 ++-
> uxa/uxa-render.c | 261 ++++++++++++++++++++++++++++++++++++++++-------------
> 4 files changed, 223 insertions(+), 78 deletions(-)
>
> diff --git a/src/i830_render.c b/src/i830_render.c
> index e4c4623..8418bd7 100644
> --- a/src/i830_render.c
> +++ b/src/i830_render.c
> @@ -220,11 +220,15 @@ static Bool i830_get_blend_cntl(ScrnInfoPtr pScrn, int op, PicturePtr pMask,
>
> static Bool i830_check_composite_texture(PicturePtr pPict, int unit)
> {
> - ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
> - int w = pPict->pDrawable->width;
> - int h = pPict->pDrawable->height;
> - int i;
> + ScrnInfoPtr pScrn;
> + int w, h, i;
>
> + if (!pPict->pDrawable)
> + return TRUE;
> +
> + pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
> + w = pPict->pDrawable->width;
> + h = pPict->pDrawable->height;
> if ((w > 2048) || (h > 2048))
> I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
>
> @@ -393,7 +397,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
> PicturePtr pMaskPicture, PicturePtr pDstPicture,
> PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
> {
> - ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
> + ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
> I830Ptr pI830 = I830PTR(pScrn);
> Bool is_affine_src, is_affine_mask;
> Bool is_nearest = FALSE;
> diff --git a/src/i915_render.c b/src/i915_render.c
> index c81366a..bb755c5 100644
> --- a/src/i915_render.c
> +++ b/src/i915_render.c
> @@ -169,11 +169,15 @@ static Bool i915_get_dest_format(PicturePtr pDstPicture, uint32_t *dst_format)
>
> static Bool i915_check_composite_texture(PicturePtr pPict, int unit)
> {
> - ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
> - int w = pPict->pDrawable->width;
> - int h = pPict->pDrawable->height;
> - int i;
> + ScrnInfoPtr pScrn;
> + int w, h, i;
> +
> + if (!pPict->pDrawable)
> + return TRUE;
>
> + pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
> + w = pPict->pDrawable->width;
> + h = pPict->pDrawable->height;
> if ((w > 2048) || (h > 2048))
> I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
>
> diff --git a/src/i965_render.c b/src/i965_render.c
> index 1a8075b..1d88af8 100644
> --- a/src/i965_render.c
> +++ b/src/i965_render.c
> @@ -183,11 +183,15 @@ static Bool i965_get_dest_format(PicturePtr pDstPicture, uint32_t *dst_format)
>
> static Bool i965_check_composite_texture(PicturePtr pPict, int unit)
> {
> - ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
> - int w = pPict->pDrawable->width;
> - int h = pPict->pDrawable->height;
> - int i;
> + ScrnInfoPtr pScrn;
> + int w, h, i;
> +
> + if (!pPict->pDrawable)
> + return TRUE;
>
> + pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
> + w = pPict->pDrawable->width;
> + h = pPict->pDrawable->height;
> if ((w > 8192) || (h > 8192))
> I830FALLBACK("Picture w/h too large (%dx%d)\n", w, h);
>
> @@ -1438,7 +1442,7 @@ i965_prepare_composite(int op, PicturePtr pSrcPicture,
> PicturePtr pMaskPicture, PicturePtr pDstPicture,
> PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
> {
> - ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
> + ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum];
> I830Ptr pI830 = I830PTR(pScrn);
> struct gen4_render_state *render_state= pI830->gen4_render_state;
> gen4_composite_op *composite_op = &render_state->composite_op;
> diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
> index 13128ed..fde10b7 100644
> --- a/uxa/uxa-render.c
> +++ b/uxa/uxa-render.c
> @@ -314,6 +314,131 @@ uxa_try_driver_solid_fill(PicturePtr pSrc,
> return 1;
> }
>
> +static PicturePtr
> +uxa_picture_from_pixman_image (ScreenPtr pScreen,
> + pixman_image_t *image,
> + pixman_format_code_t format)
> +{
> + PicturePtr pPicture;
> + PixmapPtr pPixmap;
> + GCPtr pGC;
> + int width, height, depth;
> + int error;
> +
> + width = pixman_image_get_width (image);
> + height = pixman_image_get_height (image);
> + depth = pixman_image_get_depth (image);
> +
> + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth,
> + UXA_CREATE_PIXMAP_FOR_MAP);
> + if (!pPixmap)
> + return 0;
> +
> + pPicture = CreatePicture (0, &pPixmap->drawable,
> + PictureMatchFormat (pScreen, depth, format),
> + 0, 0, serverClient, &error);
> + (*pScreen->DestroyPixmap) (pPixmap);
> +
> +
> + pPixmap = GetScratchPixmapHeader(pScreen, width, height, depth,
> + BitsPerPixel (depth),
> + pixman_image_get_stride (image),
> + pixman_image_get_data (image));
> + if (!pPixmap)
> + {
> + FreePicture (pPicture, 0);
> + return 0;
> + }
> +
> + pGC = GetScratchGC (depth, pScreen);
> + if (!pGC)
> + {
> + FreeScratchPixmapHeader (pPixmap);
> + FreePicture (pPicture, 0);
> + return 0;
> + }
> + ValidateGC (pPicture->pDrawable, pGC);
> +
> + (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable,
> + pGC, 0, 0, width, height, 0, 0);
> +
> + FreeScratchGC (pGC);
> + FreeScratchPixmapHeader (pPixmap);
> +
> + return pPicture;
> +}
> +
> +static PicturePtr
> +uxa_get_pattern (ScreenPtr pScreen,
> + PicturePtr pPict,
> + pixman_format_code_t format,
> + INT16 x, INT16 y,
> + CARD16 width, CARD16 height)
> +{
> + pixman_image_t *source, *image;
> +
> + source = image_from_pict (pPict, 0, 0);
> + if (!source)
> + return 0;
> +
> + image = pixman_image_create_bits (format, width, height, NULL, 0);
> + if (!image) {
> + pixman_image_unref (source);
> + return 0;
> + }
> +
> + pixman_image_composite (PIXMAN_OP_SRC,
> + source, NULL, image,
> + x, y,
> + 0, 0,
> + 0, 0,
> + width, height);
> + pixman_image_unref (source);
> +
> + pPict = uxa_picture_from_pixman_image (pScreen, image, format);
> + pixman_image_unref (image);
> +
> + return pPict;
> +}
> +
> +static PicturePtr
> +uxa_get_source (ScreenPtr pScreen,
> + PicturePtr pPict,
> + INT16 x, INT16 y,
> + CARD16 width, CARD16 height,
> + INT16 *out_x, INT16 *out_y)
> +{
> + if (pPict->pDrawable) {
> + *out_x = x + pPict->pDrawable->x;
> + *out_y = y + pPict->pDrawable->y;
> + return pPict;
> + }
> +
> + *out_x = 0;
> + *out_y = 0;
> + return uxa_get_pattern (pScreen, pPict,
> + PICT_a8r8g8b8, x, y, width, height);
> +}
> +
> +static PicturePtr
> +uxa_get_mask (ScreenPtr pScreen,
> + PicturePtr pPict,
> + INT16 x, INT16 y,
> + INT16 width, INT16 height,
> + INT16 *out_x, INT16 *out_y)
> +{
> + if (pPict->pDrawable) {
> + *out_x = x + pPict->pDrawable->x;
> + *out_y = y + pPict->pDrawable->y;
> + return pPict;
> + }
> +
> + *out_x = 0;
> + *out_y = 0;
> + return uxa_get_pattern (pScreen, pPict,
> + PICT_a8, x, y, width, height);
> +}
> +
> static int
> uxa_try_driver_composite_rects(CARD8 op,
> PicturePtr pSrc,
> @@ -333,7 +458,7 @@ uxa_try_driver_composite_rects(CARD8 op,
> {
> return -1;
> }
> -
> +
> pDstPix = uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
> if (!pDstPix)
> return 0;
> @@ -453,48 +578,84 @@ uxa_try_driver_composite(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;
> + PicturePtr localSrc, localMask = NULL;
>
> xDst += pDst->pDrawable->x;
> yDst += pDst->pDrawable->y;
>
> + localSrc = uxa_get_source (pDst->pDrawable->pScreen,
> + pSrc, xSrc, ySrc, width, height,
> + &xSrc, &ySrc);
> + if (! localSrc)
> + return 0;
> +
> if (pMask) {
> - xMask += pMask->pDrawable->x;
> - yMask += pMask->pDrawable->y;
> - }
> + localMask = uxa_get_mask (pDst->pDrawable->pScreen,
> + pMask, xMask, yMask, width, height,
> + &xMask, &yMask);
> + if (! localMask) {
> + if (localSrc != pSrc)
> + FreePicture (localSrc, 0);
>
> - xSrc += pSrc->pDrawable->x;
> - ySrc += pSrc->pDrawable->y;
> + return 0;
> + }
> + }
>
> if (uxa_screen->info->check_composite &&
> - !(*uxa_screen->info->check_composite) (op, pSrc, pMask, pDst))
> + !(*uxa_screen->info->check_composite) (op, localSrc, localMask, pDst))
> {
> + if (localSrc != pSrc)
> + FreePicture (localSrc, 0);
> + if (localMask && localMask != pMask)
> + FreePicture (localMask, 0);
> +
> return -1;
> }
>
> - if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
> + if (!miComputeCompositeRegion (®ion, localSrc, localMask, pDst,
> xSrc, ySrc, xMask, yMask, xDst, yDst,
> width, height))
> + {
> + if (localSrc != pSrc)
> + FreePicture (localSrc, 0);
> + if (localMask && localMask != pMask)
> + FreePicture (localMask, 0);
> +
> return 1;
> + }
>
> pDstPix = uxa_get_offscreen_pixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
>
> - pSrcPix = uxa_get_offscreen_pixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
> + pSrcPix = uxa_get_offscreen_pixmap (localSrc->pDrawable,
> + &src_off_x, &src_off_y);
>
> - if (pMask)
> - pMaskPix = uxa_get_offscreen_pixmap (pMask->pDrawable, &mask_off_x,
> - &mask_off_y);
> + if (localMask)
> + pMaskPix = uxa_get_offscreen_pixmap (localMask->pDrawable,
> + &mask_off_x, &mask_off_y);
>
> - if (!pDstPix || !pSrcPix || (pMask && !pMaskPix)) {
> + if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) {
> REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
> +
> + if (localSrc != pSrc)
> + FreePicture (localSrc, 0);
> + if (localMask && localMask != pMask)
> + FreePicture (localMask, 0);
> +
> return 0;
> }
>
> REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y);
>
> - if (!(*uxa_screen->info->prepare_composite) (op, pSrc, pMask, pDst, pSrcPix,
> - pMaskPix, pDstPix))
> + if (!(*uxa_screen->info->prepare_composite) (op, localSrc, localMask, pDst,
> + pSrcPix, pMaskPix, pDstPix))
> {
> REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
> +
> + if (localSrc != pSrc)
> + FreePicture (localSrc, 0);
> + if (localMask && localMask != pMask)
> + FreePicture (localMask, 0);
> +
> return -1;
> }
>
> @@ -523,6 +684,12 @@ uxa_try_driver_composite(CARD8 op,
> (*uxa_screen->info->done_composite) (pDstPix);
>
> REGION_UNINIT(pDst->pDrawable->pScreen, ®ion);
> +
> + if (localSrc != pSrc)
> + FreePicture (localSrc, 0);
> + if (localMask && localMask != pMask)
> + FreePicture (localMask, 0);
> +
> return 1;
> }
>
> @@ -636,14 +803,11 @@ uxa_composite(CARD8 op,
> Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
> RegionRec region;
>
> - /* We currently don't support acceleration of gradients, or other pictures
> - * with a NULL pDrawable.
> - */
> - if (uxa_screen->swappedOut ||
> - pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL))
> - {
> + if (uxa_screen->swappedOut)
> goto fallback;
> - }
> +
> + if (pSrc->pDrawable == NULL || (pMask && pMask->pDrawable == NULL))
> + goto composite;
>
> /* Remove repeat in source if useless */
> if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
> @@ -744,6 +908,7 @@ uxa_composite(CARD8 op,
> (yMask + height) <= pMask->pDrawable->height)
> pMask->repeat = 0;
>
> +composite:
> if (uxa_screen->info->prepare_composite &&
> !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap)
> {
> @@ -757,7 +922,8 @@ uxa_composite(CARD8 op,
> /* For generic masks and solid src pictures, mach64 can do Over in two
> * passes, similar to the component-alpha case.
> */
> - isSrcSolid = pSrc->pDrawable->width == 1 &&
> + isSrcSolid = pSrc->pDrawable &&
> + pSrc->pDrawable->width == 1 &&
> pSrc->pDrawable->height == 1 &&
> pSrc->repeat;
>
> @@ -888,62 +1054,29 @@ uxa_trapezoids (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
> PicturePtr pPicture;
> INT16 xDst, yDst;
> INT16 xRel, yRel;
> - int width, height, stride;
> - PixmapPtr pPixmap;
> - GCPtr pGC;
> + int width, height;
> pixman_image_t *image;
> + pixman_format_code_t format;
>
> xDst = traps[0].left.p1.x >> 16;
> yDst = traps[0].left.p1.y >> 16;
>
> width = bounds.x2 - bounds.x1;
> height = bounds.y2 - bounds.y1;
> - stride = (width * BitsPerPixel (maskFormat->depth) + 7) / 8;
>
> - pPicture = uxa_create_alpha_picture (pScreen, pDst, maskFormat,
> - width, height);
> - if (!pPicture)
> + format = maskFormat->format | (BitsPerPixel (maskFormat->depth) << 24);
> + image = pixman_image_create_bits (format, width, height, NULL, 0);
> + if (!image)
> return;
>
> - image = pixman_image_create_bits (pPicture->format,
> - width, height,
> - NULL, stride);
> - if (!image) {
> - FreePicture (pPicture, 0);
> - return;
> - }
> -
> for (; ntrap; ntrap--, traps++)
> pixman_rasterize_trapezoid (image, (pixman_trapezoid_t *) traps,
> -bounds.x1, -bounds.y1);
>
> - pPixmap = GetScratchPixmapHeader(pScreen, width, height,
> - maskFormat->depth,
> - BitsPerPixel (maskFormat->depth),
> - PixmapBytePad (width, maskFormat->depth),
> - pixman_image_get_data (image));
> - if (!pPixmap) {
> - FreePicture (pPicture, 0);
> - pixman_image_unref (image);
> - return;
> - }
> -
> - pGC = GetScratchGC (pPicture->pDrawable->depth, pScreen);
> - if (!pGC)
> - {
> - FreeScratchPixmapHeader (pPixmap);
> - pixman_image_unref (image);
> - FreePicture (pPicture, 0);
> - return;
> - }
> - ValidateGC (pPicture->pDrawable, pGC);
> -
> - (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable,
> - pGC, 0, 0, width, height, 0, 0);
> -
> - FreeScratchGC (pGC);
> - FreeScratchPixmapHeader (pPixmap);
> + pPicture = uxa_picture_from_pixman_image (pScreen, image, format);
> pixman_image_unref (image);
> + if (!pPicture)
> + return;
>
> xRel = bounds.x1 + xSrc - xDst;
> yRel = bounds.y1 + ySrc - yDst;
--
Eric Anholt
eric at anholt.net eric.anholt at intel.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20090904/db08afc1/attachment.sig>
More information about the Intel-gfx
mailing list