st/xorg: Incase of format missmatch swizzle channels and set alpha

This path is only hit for icons in gnome so far
This commit is contained in:
Jakob Bornecrantz
2009-11-12 11:16:30 +01:00
parent d683acb101
commit 5438ee3ecf
4 changed files with 138 additions and 10 deletions
@@ -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);
+37 -2
View File
@@ -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));
@@ -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);
@@ -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 |