diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2012-04-13 09:35:38 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2012-04-16 15:54:26 +0200 |
commit | d88b9700137ee407c483f263bb55c77cd6f92fef (patch) | |
tree | 04202d50791f6cd06d3582a9cb97194934a4420f /src/r600_exa.c | |
parent | 66b586b9b9cdaf70f0fcd547b5a04f044d848d44 (diff) |
EXA: Support acceleration of solid pictures on R3xx-R7xx.
Allocate 1x1 scratch pixmaps to hold the solid picture colours.
This works around https://bugs.freedesktop.org/show_bug.cgi?id=47266 and might
improve performance in other cases as well.
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Diffstat (limited to 'src/r600_exa.c')
-rw-r--r-- | src/r600_exa.c | 160 |
1 files changed, 90 insertions, 70 deletions
diff --git a/src/r600_exa.c b/src/r600_exa.c index e1eb62f1..c3ae5536 100644 --- a/src/r600_exa.c +++ b/src/r600_exa.c @@ -901,17 +901,8 @@ static Bool R600CheckCompositeTexture(PicturePtr pPict, int op, int unit) { - int w = pPict->pDrawable->width; - int h = pPict->pDrawable->height; unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone; unsigned int i; - int max_tex_w, max_tex_h; - - max_tex_w = 8192; - max_tex_h = 8192; - - if ((w > max_tex_w) || (h > max_tex_h)) - RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); for (i = 0; i < sizeof(R600TexFormats) / sizeof(R600TexFormats[0]); i++) { if (R600TexFormats[i].fmt == pPict->format) @@ -951,9 +942,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix, ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_accel_state *accel_state = info->accel_state; - int w = pPict->pDrawable->width; - int h = pPict->pDrawable->height; - unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone; + unsigned int repeatType; unsigned int i; tex_resource_t tex_res; tex_sampler_t tex_samp; @@ -969,9 +958,16 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix, } /* Texture */ + if (pPict->pDrawable) { + tex_res.w = pPict->pDrawable->width; + tex_res.h = pPict->pDrawable->height; + repeatType = pPict->repeat ? pPict->repeatType : RepeatNone; + } else { + tex_res.w = 1; + tex_res.h = 1; + repeatType = RepeatNormal; + } tex_res.id = unit; - tex_res.w = w; - tex_res.h = h; tex_res.pitch = accel_state->src_obj[unit].pitch; tex_res.depth = 0; tex_res.dim = SQ_TEX_DIM_2D; @@ -1170,24 +1166,24 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix, vs_alu_consts[0] = xFixedToFloat(pPict->transform->matrix[0][0]); vs_alu_consts[1] = xFixedToFloat(pPict->transform->matrix[0][1]); vs_alu_consts[2] = xFixedToFloat(pPict->transform->matrix[0][2]); - vs_alu_consts[3] = 1.0 / w; + vs_alu_consts[3] = 1.0 / tex_res.w; vs_alu_consts[4] = xFixedToFloat(pPict->transform->matrix[1][0]); vs_alu_consts[5] = xFixedToFloat(pPict->transform->matrix[1][1]); vs_alu_consts[6] = xFixedToFloat(pPict->transform->matrix[1][2]); - vs_alu_consts[7] = 1.0 / h; + vs_alu_consts[7] = 1.0 / tex_res.h; } else { accel_state->is_transform[unit] = FALSE; vs_alu_consts[0] = 1.0; vs_alu_consts[1] = 0.0; vs_alu_consts[2] = 0.0; - vs_alu_consts[3] = 1.0 / w; + vs_alu_consts[3] = 1.0 / tex_res.w; vs_alu_consts[4] = 0.0; vs_alu_consts[5] = 1.0; vs_alu_consts[6] = 0.0; - vs_alu_consts[7] = 1.0 / h; + vs_alu_consts[7] = 1.0 / tex_res.h; } /* VS alu constants */ @@ -1202,33 +1198,30 @@ static Bool R600CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP { uint32_t tmp1; PixmapPtr pSrcPixmap, pDstPixmap; - int max_tex_w, max_tex_h, max_dst_w, max_dst_h; /* Check for unsupported compositing operations. */ if (op >= (int) (sizeof(R600BlendOp) / sizeof(R600BlendOp[0]))) RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op)); - if (!pSrcPicture->pDrawable) - RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n")); - - pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable); + if (pSrcPicture->pDrawable) { + pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable); - max_tex_w = 8192; - max_tex_h = 8192; - max_dst_w = 8192; - max_dst_h = 8192; + if (pSrcPixmap->drawable.width >= 8192 || + pSrcPixmap->drawable.height >= 8192) { + RADEON_FALLBACK(("Source w/h too large (%d,%d).\n", + pSrcPixmap->drawable.width, + pSrcPixmap->drawable.height)); + } - if (pSrcPixmap->drawable.width >= max_tex_w || - pSrcPixmap->drawable.height >= max_tex_h) { - RADEON_FALLBACK(("Source w/h too large (%d,%d).\n", - pSrcPixmap->drawable.width, - pSrcPixmap->drawable.height)); - } + if (!R600CheckCompositeTexture(pSrcPicture, pDstPicture, op, 0)) + return FALSE; + } else if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill) + RADEON_FALLBACK(("Gradient pictures not supported yet\n")); pDstPixmap = RADEONGetDrawablePixmap(pDstPicture->pDrawable); - if (pDstPixmap->drawable.width >= max_dst_w || - pDstPixmap->drawable.height >= max_dst_h) { + if (pDstPixmap->drawable.width >= 8192 || + pDstPixmap->drawable.height >= 8192) { RADEON_FALLBACK(("Dest w/h too large (%d,%d).\n", pDstPixmap->drawable.width, pDstPixmap->drawable.height)); @@ -1237,38 +1230,35 @@ static Bool R600CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP if (pMaskPicture) { PixmapPtr pMaskPixmap; - if (!pMaskPicture->pDrawable) - RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n")); + if (pMaskPicture->pDrawable) { + pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable); - pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable); - - if (pMaskPixmap->drawable.width >= max_tex_w || - pMaskPixmap->drawable.height >= max_tex_h) { - RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n", - pMaskPixmap->drawable.width, - pMaskPixmap->drawable.height)); - } + if (pMaskPixmap->drawable.width >= 8192 || + pMaskPixmap->drawable.height >= 8192) { + RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n", + pMaskPixmap->drawable.width, + pMaskPixmap->drawable.height)); + } - if (pMaskPicture->componentAlpha) { - /* Check if it's component alpha that relies on a source alpha and - * on the source value. We can only get one of those into the - * single source value that we get to blend with. - */ - if (R600BlendOp[op].src_alpha && - (R600BlendOp[op].blend_cntl & COLOR_SRCBLEND_mask) != - (BLEND_ZERO << COLOR_SRCBLEND_shift)) { - RADEON_FALLBACK(("Component alpha not supported with source " - "alpha and source value blending.\n")); + if (pMaskPicture->componentAlpha) { + /* Check if it's component alpha that relies on a source alpha and + * on the source value. We can only get one of those into the + * single source value that we get to blend with. + */ + if (R600BlendOp[op].src_alpha && + (R600BlendOp[op].blend_cntl & COLOR_SRCBLEND_mask) != + (BLEND_ZERO << COLOR_SRCBLEND_shift)) { + RADEON_FALLBACK(("Component alpha not supported with source " + "alpha and source value blending.\n")); + } } - } - if (!R600CheckCompositeTexture(pMaskPicture, pDstPicture, op, 1)) - return FALSE; + if (!R600CheckCompositeTexture(pMaskPicture, pDstPicture, op, 1)) + return FALSE; + } else if (pMaskPicture->pSourcePict->type != SourcePictTypeSolidFill) + RADEON_FALLBACK(("Gradient pictures not supported yet\n")); } - if (!R600CheckCompositeTexture(pSrcPicture, pDstPicture, op, 0)) - return FALSE; - if (!R600GetDestFormat(pDstPicture, &tmp1)) return FALSE; @@ -1280,7 +1270,8 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) { - ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; + ScreenPtr pScreen = pDst->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_accel_state *accel_state = info->accel_state; uint32_t dst_format; @@ -1288,15 +1279,21 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, shader_config_t vs_conf, ps_conf; struct r600_accel_object src_obj, mask_obj, dst_obj; - if (pDst->drawable.bitsPerPixel < 8 || pSrc->drawable.bitsPerPixel < 8) + if (pDst->drawable.bitsPerPixel < 8 || (pSrc && pSrc->drawable.bitsPerPixel < 8)) return FALSE; + if (!pSrc) { + pSrc = RADEONSolidPixmap(pScreen, pSrcPicture->pSourcePict->solidFill.color); + if (!pSrc) + RADEON_FALLBACK("Failed to create solid scratch pixmap\n"); + } + #if defined(XF86DRM_MODE) if (info->cs) { src_obj.offset = 0; dst_obj.offset = 0; - src_obj.bo = radeon_get_pixmap_bo(pSrc); dst_obj.bo = radeon_get_pixmap_bo(pDst); + src_obj.bo = radeon_get_pixmap_bo(pSrc); dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst); src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc); dst_obj.surface = radeon_get_pixmap_surface(pDst); @@ -1322,7 +1319,16 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, dst_obj.bpp = pDst->drawable.bitsPerPixel; dst_obj.domain = RADEON_GEM_DOMAIN_VRAM; - if (pMask) { + if (pMaskPicture) { + if (!pMask) { + pMask = RADEONSolidPixmap(pScreen, pMaskPicture->pSourcePict->solidFill.color); + if (!pMask) { + if (!pSrcPicture->pDrawable) + pScreen->DestroyPixmap(pSrc); + RADEON_FALLBACK("Failed to create solid scratch pixmap\n"); + } + } + #if defined(XF86DRM_MODE) if (info->cs) { mask_obj.offset = 0; @@ -1509,11 +1515,9 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, return TRUE; } -static void R600DoneComposite(PixmapPtr pDst) +static void R600FinishComposite(ScrnInfoPtr pScrn, PixmapPtr pDst, + struct radeon_accel_state *accel_state) { - ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_accel_state *accel_state = info->accel_state; int vtx_size; if (accel_state->vsync) @@ -1527,6 +1531,22 @@ static void R600DoneComposite(PixmapPtr pDst) r600_finish_op(pScrn, vtx_size); } +static void R600DoneComposite(PixmapPtr pDst) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + + R600FinishComposite(pScrn, pDst, accel_state); + + if (!accel_state->src_pic->pDrawable) + pScreen->DestroyPixmap(accel_state->src_pix); + + if (accel_state->msk_pic && !accel_state->msk_pic->pDrawable) + pScreen->DestroyPixmap(accel_state->msk_pix); +} + static void R600Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, @@ -1543,7 +1563,7 @@ static void R600Composite(PixmapPtr pDst, #ifdef XF86DRM_MODE if (info->cs && CS_FULL(info->cs)) { - R600DoneComposite(info->accel_state->dst_pix); + R600FinishComposite(pScrn, pDst, info->accel_state); radeon_cs_flush_indirect(pScrn); R600PrepareComposite(info->accel_state->composite_op, info->accel_state->src_pic, |