summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.c57
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c39
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.c48
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.h4
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
@@ -468,6 +468,41 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
}
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,
PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
@@ -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 |