summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/xorg
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2009-10-22 11:49:19 -0400
committerZack Rusin <[email protected]>2009-10-22 11:53:10 -0400
commitc4af8ce69e1a7105b0178da8a085b73ab984e432 (patch)
tree873ff5b0d4306fe591483071736937b1a195153d /src/gallium/state_trackers/xorg
parent4e2bdd66352cf9a2e951bb21151edee25c8c0a8c (diff)
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
Diffstat (limited to 'src/gallium/state_trackers/xorg')
-rw-r--r--src/gallium/state_trackers/xorg/xorg_composite.c168
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa.c19
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.c37
-rw-r--r--src/gallium/state_trackers/xorg/xorg_exa_tgsi.h3
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 {