From 5438ee3ecfe5c25102d196fd6d7258201e27e6ca Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 12 Nov 2009 11:16:30 +0100 Subject: st/xorg: Incase of format missmatch swizzle channels and set alpha This path is only hit for icons in gnome so far --- src/gallium/state_trackers/xorg/xorg_composite.c | 57 +++++++++++++++++++++++- src/gallium/state_trackers/xorg/xorg_exa.c | 39 +++++++++++++++- src/gallium/state_trackers/xorg/xorg_exa_tgsi.c | 48 +++++++++++++++++--- src/gallium/state_trackers/xorg/xorg_exa_tgsi.h | 4 ++ 4 files changed, 138 insertions(+), 10 deletions(-) diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index 02dc949c93e..1ff19a2a5c0 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -228,10 +228,59 @@ bind_blend_state(struct exa_context *exa, int op, cso_set_blend(exa->renderer->cso, &blend); } +static unsigned +picture_format_fixups(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture, boolean mask) +{ + boolean set_alpha = FALSE; + boolean swizzle = FALSE; + unsigned ret = 0; + + if (pSrc->picture_format == pSrcPicture->format) + return 0; + + if (pSrc->picture_format != PICT_a8r8g8b8) { + assert(!"can not handle formats"); + return 0; + } + + /* pSrc->picture_format == PICT_a8r8g8b8 */ + switch (pSrcPicture->format) { + case PICT_x8b8g8r8: + case PICT_b8g8r8: + set_alpha = TRUE; /* fall trough */ + case PICT_a8b8g8r8: + swizzle = TRUE; + break; + case PICT_x8r8g8b8: + case PICT_r8g8b8: + set_alpha = TRUE; /* fall through */ + case PICT_a8r8g8b8: + break; +#ifdef PICT_TYPE_BGRA + case PICT_b8g8r8a8: + case PICT_b8g8r8x8: + case PICT_a2r10g10b10: + case PICT_x2r10g10b10: + case PICT_a2b10g10r10: + case PICT_x2b10g10r10: +#endif + default: + assert(!"can not handle formats"); + return 0; + } + + if (set_alpha) + ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; + if (swizzle) + ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; + + return ret; +} static void bind_shaders(struct exa_context *exa, int op, - PicturePtr pSrcPicture, PicturePtr pMaskPicture) + PicturePtr pSrcPicture, PicturePtr pMaskPicture, + struct exa_pixmap_priv *pSrc, struct exa_pixmap_priv *pMask) { unsigned vs_traits = 0, fs_traits = 0; struct xorg_shader shader; @@ -257,6 +306,8 @@ bind_shaders(struct exa_context *exa, int op, fs_traits |= FS_COMPOSITE; vs_traits |= VS_COMPOSITE; } + + fs_traits |= picture_format_fixups(pSrc, pSrcPicture, FALSE); } if (pMaskPicture) { @@ -273,6 +324,8 @@ bind_shaders(struct exa_context *exa, int op, } else fs_traits |= FS_CA_FULL; } + + fs_traits |= picture_format_fixups(pMask, pMaskPicture, TRUE); } shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); @@ -438,7 +491,7 @@ boolean xorg_composite_bind_state(struct exa_context *exa, renderer_bind_viewport(exa->renderer, pDst); bind_blend_state(exa, op, pSrcPicture, pMaskPicture, pDstPicture); renderer_bind_rasterizer(exa->renderer); - bind_shaders(exa, op, pSrcPicture, pMaskPicture); + bind_shaders(exa, op, pSrcPicture, pMaskPicture, pSrc, pMask); bind_samplers(exa, op, pSrcPicture, pMaskPicture, pDstPicture, pSrc, pMask, pDst); setup_constant_buffers(exa, pDst); diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index 735cabfedfc..25c9fce2547 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -467,6 +467,41 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, width, height); } +static Bool +picture_check_formats(struct exa_pixmap_priv *pSrc, PicturePtr pSrcPicture) +{ + if (pSrc->picture_format == pSrcPicture->format) + return TRUE; + + if (pSrc->picture_format != PICT_a8r8g8b8) + return FALSE; + + /* pSrc->picture_format == PICT_a8r8g8b8 */ + switch (pSrcPicture->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + /* just treat these two as x8... */ + case PICT_r8g8b8: + case PICT_b8g8r8: + return TRUE; +#ifdef PICT_TYPE_BGRA + case PICT_b8g8r8a8: + case PICT_b8g8r8x8: + return FALSE; /* does not support swizzleing the alpha channel yet */ + case PICT_a2r10g10b10: + case PICT_x2r10g10b10: + case PICT_a2b10g10r10: + case PICT_x2b10g10r10: + return FALSE; +#endif + default: + return FALSE; + } + return FALSE; +} + static Bool ExaPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, @@ -512,7 +547,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture, PIPE_TEXTURE_USAGE_SAMPLER, 0)) XORG_FALLBACK("pSrc format: %s", pf_name(priv->tex->format)); - if (priv->picture_format != pSrcPicture->format) + if (!picture_check_formats(priv, pSrcPicture)) XORG_FALLBACK("pSrc pic_format: %s != %s", render_format_name(priv->picture_format), render_format_name(pSrcPicture->format)); @@ -528,7 +563,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture, PIPE_TEXTURE_USAGE_SAMPLER, 0)) XORG_FALLBACK("pMask format: %s", pf_name(priv->tex->format)); - if (priv->picture_format != pMaskPicture->format) + if (!picture_check_formats(priv, pMaskPicture)) XORG_FALLBACK("pMask pic_format: %s != %s", render_format_name(priv->picture_format), render_format_name(pMaskPicture->format)); diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c index f8557755ef2..cbb9ec137ea 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c @@ -359,12 +359,18 @@ xrender_tex(struct ureg_program *ureg, struct ureg_dst dst, struct ureg_src coords, struct ureg_src sampler, - boolean repeat_none) + boolean repeat_none, + boolean swizzle, + boolean set_alpha) { + struct ureg_src imm0 = { 0 }; + + if (repeat_none || set_alpha) + imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); + if (repeat_none) { struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); - struct ureg_src imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); ureg_SGT(ureg, tmp1, ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, @@ -381,11 +387,37 @@ xrender_tex(struct ureg_program *ureg, ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); + if (swizzle) + ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(tmp1, TGSI_WRITEMASK_W), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); ureg_release_temporary(ureg, tmp0); ureg_release_temporary(ureg, tmp1); - } else - ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); + } else { + if (swizzle) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); + ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + ureg_release_temporary(ureg, tmp); + } else { + ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); + } + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); + } } static void * @@ -407,6 +439,10 @@ create_fs(struct pipe_context *pipe, unsigned is_yuv = (fs_traits & FS_YUV) != 0; unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; + unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; + unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; + unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; + unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0; ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); if (ureg == NULL) @@ -463,7 +499,7 @@ create_fs(struct pipe_context *pipe, else src = out; xrender_tex(ureg, src, src_input, src_sampler, - src_repeat_none); + src_repeat_none, src_swizzle, src_set_alpha); } else if (is_fill) { if (is_solid) { if (has_mask) @@ -503,7 +539,7 @@ create_fs(struct pipe_context *pipe, if (has_mask) { mask = ureg_DECL_temporary(ureg); xrender_tex(ureg, mask, mask_pos, mask_sampler, - mask_repeat_none); + mask_repeat_none, mask_swizzle, mask_set_alpha); /* src IN mask */ src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), 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 c038dc2231f..062de947e62 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.h @@ -28,6 +28,10 @@ enum xorg_fs_traits { FS_YUV = 1 << 7, FS_SRC_REPEAT_NONE = 1 << 8, FS_MASK_REPEAT_NONE = 1 << 9, + FS_SRC_SWIZZLE_RGB = 1 << 10, + FS_MASK_SWIZZLE_RGB = 1 << 11, + FS_SRC_SET_ALPHA = 1 << 12, + FS_MASK_SET_ALPHA = 1 << 13, FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | -- cgit v1.2.3