st/xa: Fix render to xa_format_a8, which is backed by a gallium L8 texture

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
This commit is contained in:
Thomas Hellstrom 2011-07-06 21:58:33 +02:00
parent 7a10976adb
commit 568d99cc6c
5 changed files with 86 additions and 37 deletions

View File

@ -79,6 +79,25 @@ static const struct xa_composite_blend xa_blends[] = {
};
/*
* The alpha value stored in a luminance texture is read by the
* hardware as color.
*/
static unsigned
xa_convert_blend_for_luminance(unsigned factor)
{
switch(factor) {
case PIPE_BLENDFACTOR_DST_ALPHA:
return PIPE_BLENDFACTOR_DST_COLOR;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
return PIPE_BLENDFACTOR_INV_DST_COLOR;
default:
break;
}
return factor;
}
static boolean
blend_for_op(struct xa_composite_blend *blend,
enum xa_composite_op op,
@ -104,15 +123,20 @@ blend_for_op(struct xa_composite_blend *blend,
}
}
if (!dst_pic->srf)
return supported;
if (dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM) {
blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src);
blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst);
}
/*
* If there's no dst alpha channel, adjust the blend op so that we'll treat
* it as always 1.
*/
if (dst_pic &&
xa_format_a(dst_pic->pict_format) == 0 &&
blend->alpha_dst) {
if (xa_format_a(dst_pic->pict_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)
@ -237,7 +261,6 @@ bind_composite_blend_state(struct xa_context *ctx,
static unsigned int
picture_format_fixups(struct xa_picture *src_pic,
struct xa_picture *dst_pic,
int mask)
{
boolean set_alpha = FALSE;
@ -253,22 +276,17 @@ picture_format_fixups(struct xa_picture *src_pic,
src_hw_format = xa_surface_format(src);
src_pic_format = src_pic->pict_format;
if (!src || src_hw_format == src_pic_format) {
if (src_pic_format == xa_format_a8) {
if (mask)
return FS_MASK_LUMINANCE;
else if (dst_pic->pict_format != xa_format_a8) {
set_alpha = (xa_format_type_is_color(src_pic_format) &&
xa_format_a(src_pic_format) == 0);
/*
* if both dst and src are luminance then
* we don't want to swizzle the alpha (X) of the
* source into W component of the dst because
* it will break our destination
*/
return FS_SRC_LUMINANCE;
}
}
return 0;
if (set_alpha)
ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA;
if (src_hw_format == src_pic_format) {
if (src->tex->format == PIPE_FORMAT_L8_UNORM)
return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE);
return ret;
}
src_hw_type = xa_format_type(src_hw_format);
@ -280,13 +298,8 @@ picture_format_fixups(struct xa_picture *src_pic,
src_pic_type == xa_type_argb)));
if (!swizzle && (src_hw_type != src_pic_type))
return 0;
return ret;
set_alpha = (xa_format_type_is_color(src_pic_format) &&
xa_format_a(src_pic_type) == 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;
@ -300,7 +313,6 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
struct xa_shader shader;
struct xa_picture *src_pic = comp->src;
struct xa_picture *mask_pic = comp->mask;
struct xa_picture *dst_pic = comp->dst;
ctx->has_solid_color = FALSE;
@ -321,7 +333,7 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
vs_traits |= VS_COMPOSITE;
}
fs_traits |= picture_format_fixups(src_pic, dst_pic, 0);
fs_traits |= picture_format_fixups(src_pic, 0);
}
if (mask_pic) {
@ -340,9 +352,12 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp)
fs_traits |= FS_CA_FULL;
}
fs_traits |= picture_format_fixups(mask_pic, dst_pic, 1);
fs_traits |= picture_format_fixups(mask_pic, 1);
}
if (ctx->dst->srf->format == PIPE_FORMAT_L8_UNORM)
fs_traits |= FS_DST_LUMINANCE;
shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits);
cso_set_vertex_shader_handle(ctx->cso, shader.vs);
cso_set_fragment_shader_handle(ctx->cso, shader.fs);
@ -433,6 +448,7 @@ xa_composite_prepare(struct xa_context *ctx,
if (ret != XA_ERR_NONE)
return ret;
ctx->dst = dst_srf;
renderer_bind_destination(ctx, dst_srf->srf,
dst_srf->srf->width,
dst_srf->srf->height);

View File

@ -278,13 +278,16 @@ xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst,
int width, height;
int ret;
xa_pixel_to_float4(fg, ctx->solid_color);
ctx->has_solid_color = 1;
ret = xa_surface_psurf_create(ctx, dst);
if (ret != XA_ERR_NONE)
return ret;
if (dst->srf->format == PIPE_FORMAT_L8_UNORM)
xa_pixel_to_float4_a8(fg, ctx->solid_color);
else
xa_pixel_to_float4(fg, ctx->solid_color);
ctx->has_solid_color = 1;
ctx->dst = dst;
width = dst->srf->width;
height = dst->srf->height;

View File

@ -135,6 +135,7 @@ enum xa_fs_traits {
FS_MASK_SET_ALPHA = 1 << 13,
FS_SRC_LUMINANCE = 1 << 14,
FS_MASK_LUMINANCE = 1 << 15,
FS_DST_LUMINANCE = 1 << 16,
FS_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | FS_RADGRAD_FILL),
FS_COMPONENT_ALPHA = (FS_CA_FULL | FS_CA_SRCALPHA)
@ -172,6 +173,17 @@ xa_pixel_to_float4(uint32_t pixel, float *color)
color[3] = ((float)a) / 255.;
}
static INLINE void
xa_pixel_to_float4_a8(uint32_t pixel, float *color)
{
uint32_t a;
a = (pixel >> 24) & 0xff;
color[0] = ((float)a) / 255.;
color[1] = ((float)a) / 255.;
color[2] = ((float)a) / 255.;
color[3] = ((float)a) / 255.;
}
/*
* xa_tgsi.c

View File

@ -418,6 +418,7 @@ renderer_copy_prepare(struct xa_context *r,
struct pipe_context *pipe = r->pipe;
struct pipe_screen *screen = pipe->screen;
struct xa_shader shader;
uint32_t fs_traits = FS_COMPOSITE;
assert(screen->is_format_supported(screen, dst_surface->format,
PIPE_TEXTURE_2D, 0,
@ -469,7 +470,12 @@ renderer_copy_prepare(struct xa_context *r,
}
/* shaders */
shader = xa_shaders_get(r->shaders, VS_COMPOSITE, FS_COMPOSITE);
if (src_texture->format == PIPE_FORMAT_L8_UNORM)
fs_traits |= FS_SRC_LUMINANCE;
if (dst_surface->format == PIPE_FORMAT_L8_UNORM)
fs_traits |= FS_DST_LUMINANCE;
shader = xa_shaders_get(r->shaders, VS_COMPOSITE, fs_traits);
cso_set_vertex_shader_handle(r->cso, shader.vs);
cso_set_fragment_shader_handle(r->cso, shader.fs);

View File

@ -85,6 +85,7 @@ print_fs_traits(int fs_traits)
"FS_MASK_SET_ALPHA", /* = 1 << 13, */
"FS_SRC_LUMINANCE", /* = 1 << 14, */
"FS_MASK_LUMINANCE", /* = 1 << 15, */
"FS_DST_LUMINANCE", /* = 1 << 15, */
};
int i, k;
@ -454,6 +455,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;
unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;
unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0;
#if 0
print_fs_traits(fs_traits);
@ -508,7 +510,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
#endif
if (is_composite) {
if (has_mask || src_luminance)
if (has_mask || src_luminance || dst_luminance)
src = ureg_DECL_temporary(ureg);
else
src = out;
@ -516,14 +518,14 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
src_repeat_none, src_swizzle, src_set_alpha);
} else if (is_fill) {
if (is_solid) {
if (has_mask || src_luminance)
if (has_mask || src_luminance || dst_luminance)
src = ureg_dst(src_input);
else
ureg_MOV(ureg, out, src_input);
} else if (is_lingrad || is_radgrad) {
struct ureg_src coords, const0124, matrow0, matrow1, matrow2;
if (has_mask || src_luminance)
if (has_mask || src_luminance || dst_luminance)
src = ureg_DECL_temporary(ureg);
else
src = out;
@ -550,7 +552,7 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));
ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),
ureg_scalar(imm0, TGSI_SWIZZLE_X));
if (!has_mask)
if (!has_mask && !dst_luminance)
ureg_MOV(ureg, out, ureg_src(src));
}
@ -559,11 +561,21 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits)
xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
mask_repeat_none, mask_swizzle, mask_set_alpha);
/* src IN mask */
src_in_mask(ureg, out, ureg_src(src), ureg_src(mask),
src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),
ureg_src(mask),
comp_alpha_mask, mask_luminance);
ureg_release_temporary(ureg, mask);
}
if (dst_luminance) {
/*
* Make sure the alpha channel goes into the output L8 surface.
*/
ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W));
}
ureg_END(ureg);
return ureg_create_shader_and_destroy(ureg, pipe);