From c4af8ce69e1a7105b0178da8a085b73ab984e432 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Thu, 22 Oct 2009 11:49:19 -0400 Subject: [PATCH] st/xorg: lots of render fixes fixes all the blend modes, fixes flushing/finishing semantics, adds acceleration for the component alpha modes that we can support, fixes src in mask shader and general cleanups --- .../state_trackers/xorg/xorg_composite.c | 168 ++++++++++-------- src/gallium/state_trackers/xorg/xorg_exa.c | 19 +- .../state_trackers/xorg/xorg_exa_tgsi.c | 37 ++-- .../state_trackers/xorg/xorg_exa_tgsi.h | 3 +- 4 files changed, 114 insertions(+), 113 deletions(-) diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index 7379e3b7461..297b6c5f5d2 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -13,68 +13,43 @@ #define XFixedToDouble(f) (((double) (f)) / 65536.) struct xorg_composite_blend { - int op:8; + int op : 8; - unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */ - unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */ + unsigned alpha_dst : 4; + unsigned alpha_src : 4; - unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ - unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */ + unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ + unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ }; #define BLEND_OP_OVER 3 static const struct xorg_composite_blend xorg_blends[] = { { PictOpClear, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, - + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, { PictOpSrc, - PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO }, - + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, { PictOpDst, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO, - PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE }, - + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, { PictOpOver, - PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, { PictOpOverReverse, - PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, { PictOpIn, - PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, { PictOpInReverse, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE }, - + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, { PictOpOut, - PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, { PictOpOutReverse, - PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, { PictOpAtop, - PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, { PictOpAtopReverse, - PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA }, - + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, { PictOpXor, - PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_ONE }, - + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, { PictOpAdd, - PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE, - PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE }, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, }; @@ -95,38 +70,62 @@ pixel_to_float4(Pixel pixel, float *color) struct acceleration_info { int op : 16; - int with_mask : 1; - int component_alpha : 1; }; static const struct acceleration_info accelerated_ops[] = { - {PictOpClear, 1, 0}, - {PictOpSrc, 1, 0}, - {PictOpDst, 1, 0}, - {PictOpOver, 1, 0}, - {PictOpOverReverse, 1, 0}, - {PictOpIn, 1, 0}, - {PictOpInReverse, 1, 0}, - {PictOpOut, 1, 0}, - {PictOpOutReverse, 1, 0}, - {PictOpAtop, 1, 0}, - {PictOpAtopReverse, 1, 0}, - {PictOpXor, 1, 0}, - {PictOpAdd, 1, 0}, - {PictOpSaturate, 1, 0}, + {PictOpClear, }, + {PictOpSrc, }, + {PictOpDst, }, + {PictOpOver, }, + {PictOpOverReverse, }, + {PictOpIn, }, + {PictOpInReverse, }, + {PictOpOut, }, + {PictOpOutReverse, }, + {PictOpAtop, }, + {PictOpAtopReverse, }, + {PictOpXor, }, + {PictOpAdd, }, + {PictOpSaturate, }, }; static struct xorg_composite_blend -blend_for_op(int op) +blend_for_op(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) { const int num_blends = sizeof(xorg_blends)/sizeof(struct xorg_composite_blend); int i; + struct xorg_composite_blend blend = xorg_blends[BLEND_OP_OVER]; for (i = 0; i < num_blends; ++i) { if (xorg_blends[i].op == op) - return xorg_blends[i]; + blend = xorg_blends[i]; } - return xorg_blends[BLEND_OP_OVER]; + + /* If there's no dst alpha channel, adjust the blend op so that we'll treat + * it as always 1. + */ + if (pDstPicture && + PICT_FORMAT_A(pDstPicture->format) == 0 && blend.alpha_dst) { + if (blend.rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) + blend.rgb_src = PIPE_BLENDFACTOR_ONE; + else if (blend.rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) + blend.rgb_src = PIPE_BLENDFACTOR_ZERO; + } + + /* If the source alpha is being used, then we should only be in a case where + * the source blend factor is 0, and the source blend value is the mask + * channels multiplied by the source picture's alpha. + */ + if (pMaskPicture && pMaskPicture->componentAlpha && + PICT_FORMAT_RGB(pMaskPicture->format) && blend.alpha_src) { + if (blend.rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) { + blend.rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR; + } else if (blend.rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) { + blend.rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR; + } + } + return blend; } static INLINE int @@ -203,41 +202,50 @@ boolean xorg_composite_accelerated(int op, if (pSrcPicture->pSourcePict) { if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill) - XORG_FALLBACK("gradients not enabled (haven't been well tested)"); + XORG_FALLBACK("Gradients not enabled (haven't been well tested)"); } for (i = 0; i < accel_ops_count; ++i) { if (op == accelerated_ops[i].op) { + struct xorg_composite_blend blend = blend_for_op(op, + pSrcPicture, + pMaskPicture, + pDstPicture); /* Check for component alpha */ - if (pMaskPicture && - (pMaskPicture->componentAlpha || - (!accelerated_ops[i].with_mask))) - XORG_FALLBACK("component alpha unsupported (PictOpOver=%s(%d)", - (accelerated_ops[i].op == PictOpOver) ? "yes" : "no", - accelerated_ops[i].op); + if (pMaskPicture && pMaskPicture->componentAlpha && + PICT_FORMAT_RGB(pMaskPicture->format)) { + if (blend.alpha_src && + blend.rgb_src != PIPE_BLENDFACTOR_ZERO) { + XORG_FALLBACK("Component alpha not supported with source " + "alpha and source value blending. (op=%d)", + op); + } + } return TRUE; } } - XORG_FALLBACK("unsupported operation"); + XORG_FALLBACK("Unsupported composition operation = %d", op); } static void bind_blend_state(struct exa_context *exa, int op, - PicturePtr pSrcPicture, PicturePtr pMaskPicture) + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture) { struct xorg_composite_blend blend_opt; struct pipe_blend_state blend; - blend_opt = blend_for_op(op); + blend_opt = blend_for_op(op, pSrcPicture, pMaskPicture, pDstPicture); - memset(&blend, 0, sizeof(struct pipe_blend_state)); + memset(&blend, 0, sizeof(struct pipe_blend_state)); blend.blend_enable = 1; blend.colormask |= PIPE_MASK_RGBA; - blend.rgb_src_factor = blend_opt.rgb_src_factor; - blend.alpha_src_factor = blend_opt.alpha_src_factor; - blend.rgb_dst_factor = blend_opt.rgb_dst_factor; - blend.alpha_dst_factor = blend_opt.alpha_dst_factor; + blend.rgb_src_factor = blend_opt.rgb_src; + blend.alpha_src_factor = blend_opt.rgb_src; + blend.rgb_dst_factor = blend_opt.rgb_dst; + blend.alpha_dst_factor = blend_opt.rgb_dst; cso_set_blend(exa->renderer->cso, &blend); } @@ -273,6 +281,8 @@ bind_shaders(struct exa_context *exa, int op, if (pMaskPicture) { vs_traits |= VS_MASK; fs_traits |= FS_MASK; + if (pMaskPicture->componentAlpha) + fs_traits |= FS_COMPONENT_ALPHA; } shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); @@ -428,7 +438,7 @@ boolean xorg_composite_bind_state(struct exa_context *exa, { renderer_bind_framebuffer(exa->renderer, pDst); renderer_bind_viewport(exa->renderer, pDst); - bind_blend_state(exa, op, pSrcPicture, pMaskPicture); + bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture); renderer_bind_rasterizer(exa->renderer); bind_shaders(exa, op, pSrcPicture, pMaskPicture); bind_samplers(exa, op, pSrcPicture, pMaskPicture, @@ -491,7 +501,7 @@ boolean xorg_solid_bind_state(struct exa_context *exa, renderer_bind_framebuffer(exa->renderer, pixmap); renderer_bind_viewport(exa->renderer, pixmap); renderer_bind_rasterizer(exa->renderer); - bind_blend_state(exa, PictOpSrc, NULL, NULL); + bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL); setup_constant_buffers(exa, pixmap); shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index 39c4d26ebe8..b83d97bdb62 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -105,12 +105,21 @@ xorg_exa_common_done(struct exa_context *exa) static void ExaWaitMarker(ScreenPtr pScreen, int marker) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + struct exa_context *exa = ms->exa; + +#if 0 + xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL); +#else + xorg_exa_finish(exa); +#endif } static int ExaMarkSync(ScreenPtr pScreen) { - return 1; + return 1; } static Bool @@ -258,11 +267,6 @@ ExaDone(PixmapPtr pPixmap) if (!priv) return; -#if 1 - xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL); -#else - xorg_exa_finish(exa); -#endif xorg_exa_common_done(exa); } @@ -442,7 +446,8 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture, struct exa_pixmap_priv *priv; #if DEBUG_PRINT - debug_printf("ExaPrepareComposite\n"); + debug_printf("ExaPrepareComposite(%d, src=0x%p, mask=0x%p, dst=0x%p)\n", + op, pSrcPicture, pMaskPicture, pDstPicture); #endif if (!exa->pipe) XORG_FALLBACK("accle not enabled"); diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c index 8c9b674b4b6..041f4f96dc8 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c @@ -50,36 +50,20 @@ struct xorg_shaders { struct cso_hash *fs_hash; }; -static const char over_op[] = - "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n" - "MAD TEMP[3], TEMP[0], TEMP[3], TEMP[0]\n"; - - -static INLINE void -create_preamble(struct ureg_program *ureg) -{ -} - - static INLINE void src_in_mask(struct ureg_program *ureg, struct ureg_dst dst, struct ureg_src src, - struct ureg_src mask) + struct ureg_src mask, + boolean component_alpha) { -#if 0 - /* MUL dst, src, mask.a */ - ureg_MUL(ureg, dst, src, - ureg_scalar(mask, TGSI_SWIZZLE_W)); -#else - /* MOV dst, src */ - /* MUL dst.a, src.a, mask.a */ - ureg_MOV(ureg, dst, src); - ureg_MUL(ureg, - ureg_writemask(dst, TGSI_WRITEMASK_W), - ureg_scalar(src, TGSI_SWIZZLE_W), - ureg_scalar(mask, TGSI_SWIZZLE_W)); -#endif + if (component_alpha) { + ureg_MUL(ureg, dst, src, mask); + } + else { + ureg_MUL(ureg, dst, src, + ureg_scalar(mask, TGSI_SWIZZLE_W)); + } } static struct ureg_src @@ -305,6 +289,7 @@ create_fs(struct pipe_context *pipe, boolean is_solid = fs_traits & FS_SOLID_FILL; boolean is_lingrad = fs_traits & FS_LINGRAD_FILL; boolean is_radgrad = fs_traits & FS_RADGRAD_FILL; + boolean is_comp_alpha = fs_traits & FS_COMPONENT_ALPHA; ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); if (ureg == NULL) @@ -401,7 +386,7 @@ create_fs(struct pipe_context *pipe, ureg_TEX(ureg, mask, TGSI_TEXTURE_2D, mask_pos, mask_sampler); /* src IN mask */ - src_in_mask(ureg, out, ureg_src(src), ureg_src(mask)); + src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), is_comp_alpha); ureg_release_temporary(ureg, mask); } diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h index 33c272070b8..c290d44e8fc 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h @@ -23,7 +23,8 @@ enum xorg_fs_traits { FS_RADGRAD_FILL = 1 << 4, FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | - FS_RADGRAD_FILL) + FS_RADGRAD_FILL), + FS_COMPONENT_ALPHA = 1 << 5 }; struct xorg_shader { -- 2.30.2