From 568d99cc6c8eea75ce50fe29e1ea8a94fe7ff7a7 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 6 Jul 2011 21:58:33 +0200 Subject: [PATCH] st/xa: Fix render to xa_format_a8, which is backed by a gallium L8 texture Signed-off-by: Thomas Hellstrom --- src/gallium/state_trackers/xa/xa_composite.c | 74 ++++++++++++-------- src/gallium/state_trackers/xa/xa_context.c | 9 ++- src/gallium/state_trackers/xa/xa_priv.h | 12 ++++ src/gallium/state_trackers/xa/xa_renderer.c | 8 ++- src/gallium/state_trackers/xa/xa_tgsi.c | 22 ++++-- 5 files changed, 87 insertions(+), 38 deletions(-) diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c index 5389af6f363..cc294846e10 100644 --- a/src/gallium/state_trackers/xa/xa_composite.c +++ b/src/gallium/state_trackers/xa/xa_composite.c @@ -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) { - - /* - * 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; + set_alpha = (xa_format_type_is_color(src_pic_format) && + xa_format_a(src_pic_format) == 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; - - set_alpha = (xa_format_type_is_color(src_pic_format) && - xa_format_a(src_pic_type) == 0); + return ret; - 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); diff --git a/src/gallium/state_trackers/xa/xa_context.c b/src/gallium/state_trackers/xa/xa_context.c index 3cc25ed2071..118a390a14a 100644 --- a/src/gallium/state_trackers/xa/xa_context.c +++ b/src/gallium/state_trackers/xa/xa_context.c @@ -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; diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h index 94627e1e9d0..e8f67a12276 100644 --- a/src/gallium/state_trackers/xa/xa_priv.h +++ b/src/gallium/state_trackers/xa/xa_priv.h @@ -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 diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c index 559b2699da6..ef762f0ab49 100644 --- a/src/gallium/state_trackers/xa/xa_renderer.c +++ b/src/gallium/state_trackers/xa/xa_renderer.c @@ -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); diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c index fb6ffefd636..ed1690ed369 100644 --- a/src/gallium/state_trackers/xa/xa_tgsi.c +++ b/src/gallium/state_trackers/xa/xa_tgsi.c @@ -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); -- 2.30.2