softpipe: Fix alpha blending for formats without alpha channel.

Don't use the dst alpha channel from the tile cache when it does not
exist in the true format.
This commit is contained in:
José Fonseca 2010-05-02 21:37:24 +01:00
parent 59253a79d8
commit 4885cd4ff7
1 changed files with 108 additions and 60 deletions

View File

@ -33,6 +33,7 @@
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_format.h"
#include "sp_context.h"
#include "sp_quad.h"
#include "sp_tile_cache.h"
@ -224,7 +225,8 @@ static void
blend_quad(struct quad_stage *qs,
float (*quadColor)[4],
float (*dest)[4],
unsigned cbuf)
unsigned cbuf,
boolean has_dst_alpha)
{
static const float zero[4] = { 0, 0, 0, 0 };
static const float one[4] = { 1, 1, 1, 1 };
@ -259,24 +261,34 @@ blend_quad(struct quad_stage *qs,
VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
{
const float *alpha = dest[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
if (has_dst_alpha) {
const float *alpha = dest[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
else {
VEC4_COPY(source[0], quadColor[0]); /* R */
VEC4_COPY(source[1], quadColor[1]); /* G */
VEC4_COPY(source[2], quadColor[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
{
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(source[0], quadColor[0], temp); /* R */
VEC4_MUL(source[1], quadColor[1], temp); /* G */
VEC4_MUL(source[2], quadColor[2], temp); /* B */
}
break;
if (has_dst_alpha) {
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(source[0], quadColor[0], temp); /* R */
VEC4_MUL(source[1], quadColor[1], temp); /* G */
VEC4_MUL(source[2], quadColor[2], temp); /* B */
}
else {
VEC4_COPY(source[0], zero); /* R */
VEC4_COPY(source[1], zero); /* G */
VEC4_COPY(source[2], zero); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
float comp[4];
@ -329,14 +341,19 @@ blend_quad(struct quad_stage *qs,
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
if (has_dst_alpha) {
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
else {
VEC4_COPY(source[0], zero); /* R */
VEC4_COPY(source[1], zero); /* G */
VEC4_COPY(source[2], zero); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
float inv_comp[4];
@ -399,7 +416,10 @@ blend_quad(struct quad_stage *qs,
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
if (has_dst_alpha)
VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
else
VEC4_COPY(source[3], quadColor[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
/* multiply alpha by 1.0 */
@ -429,12 +449,15 @@ blend_quad(struct quad_stage *qs,
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
if (has_dst_alpha) {
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
else {
VEC4_COPY(source[3], zero); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
@ -468,9 +491,14 @@ blend_quad(struct quad_stage *qs,
VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
if (has_dst_alpha) {
VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
}
else {
/* dest = dest * 1 NO-OP, leave dest as-is */
}
break;
case PIPE_BLENDFACTOR_DST_COLOR:
VEC4_MUL(dest[0], dest[0], dest[0]); /* R */
@ -478,15 +506,20 @@ blend_quad(struct quad_stage *qs,
VEC4_MUL(dest[2], dest[2], dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
{
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(dest[0], quadColor[0], temp); /* R */
VEC4_MUL(dest[1], quadColor[1], temp); /* G */
VEC4_MUL(dest[2], quadColor[2], temp); /* B */
}
if (has_dst_alpha) {
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(dest[0], quadColor[0], temp); /* R */
VEC4_MUL(dest[1], quadColor[1], temp); /* G */
VEC4_MUL(dest[2], quadColor[2], temp); /* B */
}
else {
VEC4_COPY(dest[0], zero); /* R */
VEC4_COPY(dest[1], zero); /* G */
VEC4_COPY(dest[2], zero); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
@ -539,13 +572,18 @@ blend_quad(struct quad_stage *qs,
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[3]); /* A */
VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
}
if (has_dst_alpha) {
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[3]); /* A */
VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
}
else {
VEC4_COPY(dest[0], zero); /* R */
VEC4_COPY(dest[1], zero); /* G */
VEC4_COPY(dest[2], zero); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
@ -605,7 +643,12 @@ blend_quad(struct quad_stage *qs,
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
if (has_dst_alpha) {
VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
}
else {
/* dest = dest * 1 NO-OP, leave dest as-is */
}
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
/* dest = dest * 1 NO-OP, leave dest as-is */
@ -634,12 +677,15 @@ blend_quad(struct quad_stage *qs,
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[3]); /* A */
VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
}
break;
if (has_dst_alpha) {
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[3]); /* A */
VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
}
else {
VEC4_COPY(dest[3], zero); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
@ -751,6 +797,8 @@ blend_fallback(struct quad_stage *qs,
= sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
quads[0]->input.x0,
quads[0]->input.y0);
boolean has_dst_alpha
= util_format_has_alpha(softpipe->framebuffer.cbufs[cbuf]->format);
uint q, i, j;
for (q = 0; q < nr; q++) {
@ -774,7 +822,7 @@ blend_fallback(struct quad_stage *qs,
logicop_quad( qs, quadColor, dest );
}
else if (blend->rt[blend_buf].blend_enable) {
blend_quad( qs, quadColor, dest, cbuf );
blend_quad( qs, quadColor, dest, cbuf, has_dst_alpha );
}
if (blend->rt[blend_buf].colormask != 0xf)