[Mesa-dev] [PATCH 4/4] svga: adjust blending terms according to pipe_surface::alpha_one
Brian Paul
brianp at vmware.com
Fri Jun 24 02:07:54 UTC 2016
This is needed when we're using an RGBA surface but it should act as if
it were RGB (A=1).
---
src/gallium/drivers/svga/svga_context.h | 3 +-
src/gallium/drivers/svga/svga_pipe_blend.c | 90 ++++++++++++++++++++++--------
src/gallium/drivers/svga/svga_state_rss.c | 9 ++-
3 files changed, 76 insertions(+), 26 deletions(-)
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index 391a93a..1a80db9 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -116,7 +116,7 @@ struct svga_blend_state {
uint8_t blendeq_alpha;
} rt[PIPE_MAX_COLOR_BUFS];
- SVGA3dBlendStateId id; /**< vgpu10 */
+ SVGA3dBlendStateId id[2]; /**< vgpu10 */
};
struct svga_depth_stencil_state {
@@ -634,6 +634,7 @@ void svga_init_stream_output_functions( struct svga_context *svga );
enum pipe_error
svga_bind_blend_state_object(struct svga_context *svga,
struct svga_blend_state *bs,
+ boolean have_dst_alpha,
const float blend_factor[4],
unsigned sample_mask);
diff --git a/src/gallium/drivers/svga/svga_pipe_blend.c b/src/gallium/drivers/svga/svga_pipe_blend.c
index e10bc56..bae2d8a 100644
--- a/src/gallium/drivers/svga/svga_pipe_blend.c
+++ b/src/gallium/drivers/svga/svga_pipe_blend.c
@@ -89,13 +89,53 @@ svga_translate_blend_func(unsigned mode)
/**
+ * If the destination color buffer does not have an alpha channel, reading
+ * from it should return 1.0. But if the user requested an RGB surface and
+ * we actually allocated an RGBA surface, there actually is an alpha channel.
+ * But we have to act as if the alpha channel wasn't there. This function
+ * adjusts the blending mode to use 0 or 1 instead of DESTALPHA or
+ * INVDESTALPHA.
+ */
+static unsigned
+adjust_color(unsigned mode, boolean have_dst_alpha)
+{
+ if (!have_dst_alpha) {
+ if (mode == SVGA3D_BLENDOP_DESTALPHA)
+ return SVGA3D_BLENDOP_ONE;
+ if (mode == SVGA3D_BLENDOP_INVDESTALPHA)
+ return SVGA3D_BLENDOP_ZERO;
+ }
+ return mode;
+}
+
+
+/**
+ * As above, but for the blend equation's alpha terms.
+ */
+static unsigned
+adjust_alpha(unsigned mode, boolean have_dst_alpha)
+{
+ if (!have_dst_alpha) {
+ if (mode == SVGA3D_BLENDOP_DESTALPHA ||
+ mode == SVGA3D_BLENDOP_DESTCOLOR)
+ return SVGA3D_BLENDOP_ONE;
+ if (mode == SVGA3D_BLENDOP_INVDESTALPHA ||
+ mode == SVGA3D_BLENDOP_INVDESTCOLOR)
+ return SVGA3D_BLENDOP_ZERO;
+ }
+ return mode;
+}
+
+
+/**
* Define a vgpu10 blend state object for the given svga blend state using
* the given ID number.
*/
static enum pipe_error
define_blend_state_object(struct svga_context *svga,
struct svga_blend_state *bs,
- unsigned id)
+ unsigned id,
+ boolean have_dst_alpha)
{
SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
int i;
@@ -104,11 +144,13 @@ define_blend_state_object(struct svga_context *svga,
for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) {
perRT[i].blendEnable = bs->rt[i].blend_enable;
- perRT[i].srcBlend = bs->rt[i].srcblend;
- perRT[i].destBlend = bs->rt[i].dstblend;
+ perRT[i].srcBlend = adjust_color(bs->rt[i].srcblend, have_dst_alpha);
+ perRT[i].destBlend = adjust_color(bs->rt[i].dstblend, have_dst_alpha);
perRT[i].blendOp = bs->rt[i].blendeq;
- perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha;
- perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;
+ perRT[i].srcBlendAlpha =
+ adjust_alpha(bs->rt[i].srcblend_alpha, have_dst_alpha);
+ perRT[i].destBlendAlpha =
+ adjust_alpha(bs->rt[i].dstblend_alpha, have_dst_alpha);
perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;
perRT[i].renderTargetWriteMask = bs->rt[i].writemask;
perRT[i].logicOpEnable = 0;
@@ -131,6 +173,7 @@ define_blend_state_object(struct svga_context *svga,
enum pipe_error
svga_bind_blend_state_object(struct svga_context *svga,
struct svga_blend_state *bs,
+ boolean have_dst_alpha,
const float blend_factor[4],
unsigned sample_mask)
{
@@ -139,15 +182,15 @@ svga_bind_blend_state_object(struct svga_context *svga,
assert(svga_have_vgpu10(svga));
- if (bs->id != SVGA3D_INVALID_ID) {
- obj_id = bs->id;
+ if (bs->id[have_dst_alpha] != SVGA3D_INVALID_ID) {
+ obj_id = bs->id[have_dst_alpha];
}
else {
/* create blend state object */
obj_id = util_bitmask_add(svga->blend_object_id_bm);
- bs->id = obj_id;
+ bs->id[have_dst_alpha] = obj_id;
- ret = define_blend_state_object(svga, bs, obj_id);
+ ret = define_blend_state_object(svga, bs, obj_id, have_dst_alpha);
if (ret != PIPE_OK) {
util_bitmask_clear(svga->blend_object_id_bm, obj_id);
return ret;
@@ -356,7 +399,7 @@ svga_create_blend_state(struct pipe_context *pipe,
blend->alpha_to_coverage = templ->alpha_to_coverage;
/* blend state objects will be created on demand */
- blend->id = SVGA3D_INVALID_ID;
+ blend->id[0] = blend->id[1] = SVGA3D_INVALID_ID;
svga->hud.num_blend_objects++;
@@ -378,22 +421,25 @@ static void svga_delete_blend_state(struct pipe_context *pipe,
{
struct svga_context *svga = svga_context(pipe);
struct svga_blend_state *bs = (struct svga_blend_state *) blend;
+ int i;
- if (bs->id != SVGA3D_INVALID_ID) {
- enum pipe_error ret;
+ for (i = 0; i < 2; i++) {
+ if (bs->id[i] != SVGA3D_INVALID_ID) {
+ enum pipe_error ret;
- ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
- if (ret != PIPE_OK) {
- svga_context_flush(svga, NULL);
- ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
- assert(ret == PIPE_OK);
- }
+ ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id[i]);
+ if (ret != PIPE_OK) {
+ svga_context_flush(svga, NULL);
+ ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id[i]);
+ assert(ret == PIPE_OK);
+ }
- if (bs->id == svga->state.hw_draw.blend_id)
- svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
+ if (bs->id[i] == svga->state.hw_draw.blend_id)
+ svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
- util_bitmask_clear(svga->blend_object_id_bm, bs->id);
- bs->id = SVGA3D_INVALID_ID;
+ util_bitmask_clear(svga->blend_object_id_bm, bs->id[i]);
+ bs->id[i] = SVGA3D_INVALID_ID;
+ }
}
FREE(blend);
diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c
index 1540899..335b82b 100644
--- a/src/gallium/drivers/svga/svga_state_rss.c
+++ b/src/gallium/drivers/svga/svga_state_rss.c
@@ -346,6 +346,9 @@ emit_rss_vgpu10(struct svga_context *svga, unsigned dirty)
if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR | SVGA_NEW_FRAME_BUFFER)) {
struct svga_blend_state *curr;
float blend_factor[4];
+ boolean have_dst_alpha =
+ svga->curr.framebuffer.cbufs[0] != NULL &&
+ !svga->curr.framebuffer.cbufs[0]->alpha_one;
if (svga_has_any_integer_cbufs(svga)) {
/* Blending is not supported in integer-valued render targets. */
@@ -374,19 +377,19 @@ emit_rss_vgpu10(struct svga_context *svga, unsigned dirty)
}
/* Set/bind the blend state object */
- if (svga->state.hw_draw.blend_id != curr->id ||
+ if (svga->state.hw_draw.blend_id != curr->id[have_dst_alpha] ||
svga->state.hw_draw.blend_factor[0] != blend_factor[0] ||
svga->state.hw_draw.blend_factor[1] != blend_factor[1] ||
svga->state.hw_draw.blend_factor[2] != blend_factor[2] ||
svga->state.hw_draw.blend_factor[3] != blend_factor[3] ||
svga->state.hw_draw.blend_sample_mask != svga->curr.sample_mask) {
- ret = svga_bind_blend_state_object(svga, curr,
+ ret = svga_bind_blend_state_object(svga, curr, have_dst_alpha,
blend_factor,
svga->curr.sample_mask);
if (ret != PIPE_OK)
return ret;
- svga->state.hw_draw.blend_id = curr->id;
+ svga->state.hw_draw.blend_id = curr->id[have_dst_alpha];
svga->state.hw_draw.blend_factor[0] = blend_factor[0];
svga->state.hw_draw.blend_factor[1] = blend_factor[1];
svga->state.hw_draw.blend_factor[2] = blend_factor[2];
--
1.9.1
More information about the mesa-dev
mailing list