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;
fs_traits |= FS_COMPOSITE;
vs_traits |= VS_COMPOSITE;
}
+
+ fs_traits |= picture_format_fixups(pSrc, pSrcPicture, FALSE);
}
if (pMaskPicture) {
} 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);
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);
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,
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));
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));
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,
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 *
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)
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)
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);
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 |