From d86ad38205e42670bfc127a8942dffa1d98b16ea Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 7 Nov 2018 11:14:04 +0100 Subject: [PATCH] st/xa: Render update. Better support for solid pictures Remove unused and obsolete code for gradients and component-alpha Support solid source- and mask pictures using a variable number of samplers in the composite pipeline rather than the fixed number we used before. Tested using rendercheck for XA. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul --- src/gallium/state_trackers/xa/xa_composite.c | 203 +++++------ src/gallium/state_trackers/xa/xa_context.c | 10 +- src/gallium/state_trackers/xa/xa_priv.h | 44 +-- src/gallium/state_trackers/xa/xa_renderer.c | 46 ++- src/gallium/state_trackers/xa/xa_tgsi.c | 350 +++++-------------- 5 files changed, 219 insertions(+), 434 deletions(-) diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c index bcb27ea1825..8de51b34d96 100644 --- a/src/gallium/state_trackers/xa/xa_composite.c +++ b/src/gallium/state_trackers/xa/xa_composite.c @@ -112,7 +112,7 @@ blend_for_op(struct xa_composite_blend *blend, boolean supported = FALSE; /* - * Temporarily disable component alpha since it appears buggy. + * No component alpha yet. */ if (mask_pic && mask_pic->component_alpha) return FALSE; @@ -126,6 +126,7 @@ blend_for_op(struct xa_composite_blend *blend, if (xa_blends[i].op == op) { *blend = xa_blends[i]; supported = TRUE; + break; } } @@ -150,21 +151,6 @@ blend_for_op(struct xa_composite_blend *blend, 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 (mask_pic && mask_pic->component_alpha && - xa_format_rgb(mask_pic->pict_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 supported; } @@ -219,38 +205,26 @@ xa_composite_check_accelerated(const struct xa_composite *comp) { struct xa_composite_blend blend; struct xa_picture *src_pic = comp->src; + struct xa_picture *mask_pic = comp->mask; + + /* + * No component alpha yet. + */ + if (mask_pic && mask_pic->component_alpha) + return -XA_ERR_INVAL; if (!xa_is_filter_accelerated(src_pic) || !xa_is_filter_accelerated(comp->mask)) { return -XA_ERR_INVAL; } + if (src_pic->src_pict &&src_pic->src_pict->type != xa_src_pict_solid_fill) + return -XA_ERR_INVAL; - if (src_pic->src_pict) { - if (src_pic->src_pict->type != xa_src_pict_solid_fill) - return -XA_ERR_INVAL; + if (!blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) + return -XA_ERR_INVAL; - /* - * Currently we don't support solid fill with a mask. - * We can easily do that, but that would require shader, - * sampler view setup and vertex setup modification. - */ - if (comp->mask) - return -XA_ERR_INVAL; - } - - if (blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) { - struct xa_picture *mask = comp->mask; - if (mask && mask->component_alpha && - xa_format_rgb(mask->pict_format)) { - if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) { - return -XA_ERR_INVAL; - } - } - - return XA_ERR_NONE; - } - return -XA_ERR_INVAL; + return XA_ERR_NONE; } static int @@ -293,7 +267,7 @@ picture_format_fixups(struct xa_picture *src_pic, src_hw_format = xa_surface_format(src); src_pic_format = src_pic->pict_format; - set_alpha = (xa_format_type_is_color(src_pic_format) && + set_alpha = (xa_format_type_is_color(src_hw_format) && xa_format_a(src_pic_format) == 0); if (set_alpha) @@ -324,6 +298,15 @@ picture_format_fixups(struct xa_picture *src_pic, return ret; } +static void +xa_src_in_mask(float src[4], const float mask[4]) +{ + src[0] *= mask[3]; + src[1] *= mask[3]; + src[2] *= mask[3]; + src[3] *= mask[3]; +} + static int bind_shaders(struct xa_context *ctx, const struct xa_composite *comp) { @@ -332,47 +315,56 @@ bind_shaders(struct xa_context *ctx, const struct xa_composite *comp) struct xa_picture *src_pic = comp->src; struct xa_picture *mask_pic = comp->mask; - ctx->has_solid_color = FALSE; + ctx->has_solid_src = FALSE; + ctx->has_solid_mask = FALSE; if (src_pic) { if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) fs_traits |= FS_SRC_REPEAT_NONE; + fs_traits |= FS_COMPOSITE; + vs_traits |= VS_COMPOSITE; + if (src_pic->src_pict) { if (src_pic->src_pict->type == xa_src_pict_solid_fill) { - fs_traits |= FS_SOLID_FILL | FS_FILL; - vs_traits |= VS_SOLID_FILL; + fs_traits |= FS_SRC_SRC; + vs_traits |= VS_SRC_SRC; xa_pixel_to_float4(src_pic->src_pict->solid_fill.color, ctx->solid_color); - ctx->has_solid_color = TRUE; + ctx->has_solid_src = TRUE; } - } else { - fs_traits |= FS_COMPOSITE; - vs_traits |= VS_COMPOSITE; - } - - fs_traits |= picture_format_fixups(src_pic, 0); + } else + fs_traits |= picture_format_fixups(src_pic, 0); } if (mask_pic) { vs_traits |= VS_MASK; fs_traits |= FS_MASK; - if (mask_pic->wrap == xa_wrap_clamp_to_border && - mask_pic->has_transform) - fs_traits |= FS_MASK_REPEAT_NONE; + if (mask_pic->src_pict) { + if (mask_pic->src_pict->type == xa_src_pict_solid_fill) { + if (ctx->has_solid_src) { + float solid_mask[4]; - if (mask_pic->component_alpha) { - struct xa_composite_blend blend; - if (!blend_for_op(&blend, comp->op, src_pic, mask_pic, NULL)) - return -XA_ERR_INVAL; + xa_pixel_to_float4(mask_pic->src_pict->solid_fill.color, + solid_mask); + xa_src_in_mask(ctx->solid_color, solid_mask); + vs_traits &= ~(VS_MASK); + fs_traits &= ~(FS_MASK); + } else { + xa_pixel_to_float4(mask_pic->src_pict->solid_fill.color, + ctx->solid_color); + vs_traits |= VS_MASK_SRC; + fs_traits |= FS_MASK_SRC; + } + ctx->has_solid_mask = TRUE; + } + } else { + if (mask_pic->wrap == xa_wrap_clamp_to_border && + mask_pic->has_transform) + fs_traits |= FS_MASK_REPEAT_NONE; - if (blend.alpha_src) { - fs_traits |= FS_CA_SRCALPHA; - } else - fs_traits |= FS_CA_FULL; - } - - fs_traits |= picture_format_fixups(mask_pic, 1); + fs_traits |= picture_format_fixups(mask_pic, 1); + } } if (ctx->srf->format == PIPE_FORMAT_L8_UNORM || @@ -396,42 +388,35 @@ bind_samplers(struct xa_context *ctx, struct pipe_context *pipe = ctx->pipe; struct xa_picture *src_pic = comp->src; struct xa_picture *mask_pic = comp->mask; + int num_samplers = 0; - ctx->num_bound_samplers = 0; - + xa_ctx_sampler_views_destroy(ctx); memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); - if (src_pic) { - if (ctx->has_solid_color) { - samplers[0] = NULL; - pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); - } else { - unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); - int filter; + if (src_pic && !ctx->has_solid_src) { + unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); + int filter; - (void) xa_filter_to_gallium(src_pic->filter, &filter); + (void) xa_filter_to_gallium(src_pic->filter, &filter); - src_sampler.wrap_s = src_wrap; - src_sampler.wrap_t = src_wrap; - src_sampler.min_img_filter = filter; - src_sampler.mag_img_filter = filter; - src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; - src_sampler.normalized_coords = 1; - samplers[0] = &src_sampler; - ctx->num_bound_samplers = 1; - u_sampler_view_default_template(&view_templ, - src_pic->srf->tex, - src_pic->srf->tex->format); - src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, - &view_templ); - pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); - ctx->bound_sampler_views[0] = src_view; - } + src_sampler.wrap_s = src_wrap; + src_sampler.wrap_t = src_wrap; + src_sampler.min_img_filter = filter; + src_sampler.mag_img_filter = filter; + src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + src_sampler.normalized_coords = 1; + samplers[0] = &src_sampler; + u_sampler_view_default_template(&view_templ, + src_pic->srf->tex,+ src_pic->srf->tex->format); + src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, + &view_templ); + ctx->bound_sampler_views[0] = src_view; + num_samplers++; } - if (mask_pic) { - unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); + if (mask_pic && !ctx->has_solid_mask) { + unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); int filter; (void) xa_filter_to_gallium(mask_pic->filter, &filter); @@ -442,31 +427,21 @@ bind_samplers(struct xa_context *ctx, mask_sampler.mag_img_filter = filter; src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; mask_sampler.normalized_coords = 1; - samplers[1] = &mask_sampler; - ctx->num_bound_samplers = 2; + samplers[num_samplers] = &mask_sampler; u_sampler_view_default_template(&view_templ, mask_pic->srf->tex, mask_pic->srf->tex->format); src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, &view_templ); - pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL); - ctx->bound_sampler_views[1] = src_view; - - - /* - * If src is a solid color, we have no src view, so set up a - * dummy one that will not be used anyway. - */ - if (ctx->bound_sampler_views[0] == NULL) - pipe_sampler_view_reference(&ctx->bound_sampler_views[0], - src_view); - + ctx->bound_sampler_views[num_samplers] = src_view; + num_samplers++; } - cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, ctx->num_bound_samplers, + cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, ctx->num_bound_samplers, + cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, ctx->bound_sampler_views); + ctx->num_bound_samplers = num_samplers; } XA_EXPORT int @@ -476,9 +451,6 @@ xa_composite_prepare(struct xa_context *ctx, struct xa_surface *dst_srf = comp->dst->srf; int ret; - if (comp->mask && !comp->mask->srf) - return -XA_ERR_INVAL; - ret = xa_ctx_srf_create(ctx, dst_srf); if (ret != XA_ERR_NONE) return ret; @@ -511,8 +483,8 @@ xa_composite_rect(struct xa_context *ctx, int dstX, int dstY, int width, int height) { if (ctx->num_bound_samplers == 0 ) { /* solid fill */ - renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height, - ctx->solid_color); + xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); + renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height); } else { const struct xa_composite *comp = ctx->comp; int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; @@ -537,7 +509,8 @@ xa_composite_done(struct xa_context *ctx) renderer_draw_flush(ctx); ctx->comp = NULL; - ctx->has_solid_color = FALSE; + ctx->has_solid_src = FALSE; + ctx->has_solid_mask = FALSE; xa_ctx_sampler_views_destroy(ctx); } diff --git a/src/gallium/state_trackers/xa/xa_context.c b/src/gallium/state_trackers/xa/xa_context.c index ba220877c84..94f7185272a 100644 --- a/src/gallium/state_trackers/xa/xa_context.c +++ b/src/gallium/state_trackers/xa/xa_context.c @@ -308,7 +308,7 @@ xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, xa_pixel_to_float4_a8(fg, ctx->solid_color); else xa_pixel_to_float4(fg, ctx->solid_color); - ctx->has_solid_color = 1; + ctx->has_solid_src = 1; ctx->dst = dst; @@ -320,8 +320,8 @@ xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, exa->solid_color[2], exa->solid_color[3]); #endif - vs_traits = VS_SOLID_FILL; - fs_traits = FS_SOLID_FILL; + vs_traits = VS_SRC_SRC | VS_COMPOSITE; + fs_traits = FS_SRC_SRC | VS_COMPOSITE; renderer_bind_destination(ctx, ctx->srf); bind_solid_blend_state(ctx); @@ -342,7 +342,7 @@ XA_EXPORT void xa_solid(struct xa_context *ctx, int x, int y, int width, int height) { xa_scissor_update(ctx, x, y, x + width, y + height); - renderer_solid(ctx, x, y, x + width, y + height, ctx->solid_color); + renderer_solid(ctx, x, y, x + width, y + height); } XA_EXPORT void @@ -350,7 +350,7 @@ xa_solid_done(struct xa_context *ctx) { renderer_draw_flush(ctx); ctx->comp = NULL; - ctx->has_solid_color = FALSE; + ctx->has_solid_src = FALSE; ctx->num_bound_samplers = 0; } diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h index c513b8d9629..09a858ff972 100644 --- a/src/gallium/state_trackers/xa/xa_priv.h +++ b/src/gallium/state_trackers/xa/xa_priv.h @@ -113,7 +113,8 @@ struct xa_context { int simple_copy; - int has_solid_color; + int has_solid_src; + int has_solid_mask; float solid_color[4]; unsigned int num_bound_samplers; @@ -145,35 +146,26 @@ xa_scissor_update(struct xa_context *ctx, unsigned minx, unsigned miny, enum xa_vs_traits { VS_COMPOSITE = 1 << 0, VS_MASK = 1 << 1, - VS_SOLID_FILL = 1 << 2, - VS_LINGRAD_FILL = 1 << 3, - VS_RADGRAD_FILL = 1 << 4, - VS_YUV = 1 << 5, - - VS_FILL = (VS_SOLID_FILL | VS_LINGRAD_FILL | VS_RADGRAD_FILL) + VS_SRC_SRC = 1 << 2, + VS_MASK_SRC = 1 << 3, + VS_YUV = 1 << 4, }; enum xa_fs_traits { FS_COMPOSITE = 1 << 0, FS_MASK = 1 << 1, - FS_SOLID_FILL = 1 << 2, - FS_LINGRAD_FILL = 1 << 3, - FS_RADGRAD_FILL = 1 << 4, - FS_CA_FULL = 1 << 5, /* src.rgba * mask.rgba */ - FS_CA_SRCALPHA = 1 << 6, /* src.aaaa * mask.rgba */ - FS_YUV = 1 << 7, - FS_SRC_REPEAT_NONE = 1 << 8, - FS_MASK_REPEAT_NONE = 1 << 9, - FS_SRC_SWIZZLE_RGB = 1 << 10, - FS_MASK_SWIZZLE_RGB = 1 << 11, - FS_SRC_SET_ALPHA = 1 << 12, - 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) + FS_SRC_SRC = 1 << 2, + FS_MASK_SRC = 1 << 3, + FS_YUV = 1 << 4, + FS_SRC_REPEAT_NONE = 1 << 5, + FS_MASK_REPEAT_NONE = 1 << 6, + FS_SRC_SWIZZLE_RGB = 1 << 7, + FS_MASK_SWIZZLE_RGB = 1 << 8, + FS_SRC_SET_ALPHA = 1 << 9, + FS_MASK_SET_ALPHA = 1 << 10, + FS_SRC_LUMINANCE = 1 << 11, + FS_MASK_LUMINANCE = 1 << 12, + FS_DST_LUMINANCE = 1 << 13, }; struct xa_shader { @@ -282,7 +274,7 @@ void renderer_draw_flush(struct xa_context *r); void renderer_begin_solid(struct xa_context *r); void renderer_solid(struct xa_context *r, - int x0, int y0, int x1, int y1, float *color); + int x0, int y0, int x1, int y1); void renderer_begin_textures(struct xa_context *r); diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c index d87a14e8088..0cb75a8c968 100644 --- a/src/gallium/state_trackers/xa/xa_renderer.c +++ b/src/gallium/state_trackers/xa/xa_renderer.c @@ -137,7 +137,7 @@ renderer_init_state(struct xa_context *r) } static inline void -add_vertex_color(struct xa_context *r, float x, float y, float color[4]) +add_vertex_none(struct xa_context *r, float x, float y) { float *vertex = r->buffer + r->buffer_size; @@ -146,12 +146,7 @@ add_vertex_color(struct xa_context *r, float x, float y, float color[4]) vertex[2] = 0.f; /*z */ vertex[3] = 1.f; /*w */ - vertex[4] = color[0]; /*r */ - vertex[5] = color[1]; /*g */ - vertex[6] = color[2]; /*b */ - vertex[7] = color[3]; /*a */ - - r->buffer_size += 8; + r->buffer_size += 4; } static inline void @@ -554,27 +549,29 @@ void renderer_begin_solid(struct xa_context *r) { r->buffer_size = 0; - r->attrs_per_vertex = 2; + r->attrs_per_vertex = 1; + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color, + 4 * sizeof(float)); } void renderer_solid(struct xa_context *r, - int x0, int y0, int x1, int y1, float *color) + int x0, int y0, int x1, int y1) { /* * debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n", * x0, y0, x1, y1, color[0], color[1], color[2], color[3]); */ - renderer_draw_conditional(r, 4 * 8); + renderer_draw_conditional(r, 4 * 4); /* 1st vertex */ - add_vertex_color(r, x0, y0, color); + add_vertex_none(r, x0, y0); /* 2nd vertex */ - add_vertex_color(r, x1, y0, color); + add_vertex_none(r, x1, y0); /* 3rd vertex */ - add_vertex_color(r, x1, y1, color); + add_vertex_none(r, x1, y1); /* 4th vertex */ - add_vertex_color(r, x0, y1, color); + add_vertex_none(r, x0, y1); } void @@ -588,6 +585,9 @@ renderer_begin_textures(struct xa_context *r) { r->attrs_per_vertex = 1 + r->num_bound_samplers; r->buffer_size = 0; + if (r->has_solid_src || r->has_solid_mask) + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, r->solid_color, + 4 * sizeof(float)); } void @@ -617,11 +617,19 @@ renderer_texture(struct xa_context *r, switch(r->attrs_per_vertex) { case 2: renderer_draw_conditional(r, 4 * 8); - add_vertex_data1(r, - pos[0], pos[1], /* src */ - pos[4], pos[5], /* dst */ - width, height, - sampler_view[0]->texture, src_matrix); + if (!r->has_solid_src) { + add_vertex_data1(r, + pos[0], pos[1], /* src */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, src_matrix); + } else { + add_vertex_data1(r, + pos[2], pos[3], /* mask */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, mask_matrix); + } break; case 3: renderer_draw_conditional(r, 4 * 12); diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c index 344a576d975..5f2608aee55 100644 --- a/src/gallium/state_trackers/xa/xa_tgsi.c +++ b/src/gallium/state_trackers/xa/xa_tgsi.c @@ -48,19 +48,18 @@ * CONST[1] = (-1, -1, 0, 0) * * OUT[0] = vertex pos - * OUT[1] = src tex coord | solid fill color + * OUT[1] = src tex coord * OUT[2] = mask tex coord * OUT[3] = dst tex coord */ -/* Fragment shader: - * SAMP[0] = src - * SAMP[1] = mask - * SAMP[2] = dst - * IN[0] = pos src | solid fill color - * IN[1] = pos mask - * IN[2] = pos dst - * CONST[0] = (0, 0, 0, 1) +/* Fragment shader. Samplers are allocated when needed. + * SAMP[0] = sampler for first texture (src or mask if src is solid) + * SAMP[1] = sampler for second texture (mask or none) + * IN[0] = first texture coordinates if present + * IN[1] = second texture coordinates if present + * CONST[0] = Solid color (src if src solid or mask if mask solid + * or src in mask if both solid). * * OUT[0] = color */ @@ -71,21 +70,18 @@ print_fs_traits(int fs_traits) const char *strings[] = { "FS_COMPOSITE", /* = 1 << 0, */ "FS_MASK", /* = 1 << 1, */ - "FS_SOLID_FILL", /* = 1 << 2, */ - "FS_LINGRAD_FILL", /* = 1 << 3, */ - "FS_RADGRAD_FILL", /* = 1 << 4, */ - "FS_CA_FULL", /* = 1 << 5, *//* src.rgba * mask.rgba */ - "FS_CA_SRCALPHA", /* = 1 << 6, *//* src.aaaa * mask.rgba */ - "FS_YUV", /* = 1 << 7, */ - "FS_SRC_REPEAT_NONE", /* = 1 << 8, */ - "FS_MASK_REPEAT_NONE", /* = 1 << 9, */ - "FS_SRC_SWIZZLE_RGB", /* = 1 << 10, */ - "FS_MASK_SWIZZLE_RGB", /* = 1 << 11, */ - "FS_SRC_SET_ALPHA", /* = 1 << 12, */ - "FS_MASK_SET_ALPHA", /* = 1 << 13, */ - "FS_SRC_LUMINANCE", /* = 1 << 14, */ - "FS_MASK_LUMINANCE", /* = 1 << 15, */ - "FS_DST_LUMINANCE", /* = 1 << 15, */ + "FS_SRC_SRC", /* = 1 << 2, */ + "FS_MASK_SRC", /* = 1 << 3, */ + "FS_YUV", /* = 1 << 4, */ + "FS_SRC_REPEAT_NONE", /* = 1 << 5, */ + "FS_MASK_REPEAT_NONE", /* = 1 << 6, */ + "FS_SRC_SWIZZLE_RGB", /* = 1 << 7, */ + "FS_MASK_SWIZZLE_RGB", /* = 1 << 8, */ + "FS_SRC_SET_ALPHA", /* = 1 << 9, */ + "FS_MASK_SET_ALPHA", /* = 1 << 10, */ + "FS_SRC_LUMINANCE", /* = 1 << 11, */ + "FS_MASK_LUMINANCE", /* = 1 << 12, */ + "FS_DST_LUMINANCE", /* = 1 << 13, */ }; int i, k; @@ -111,18 +107,12 @@ src_in_mask(struct ureg_program *ureg, struct ureg_dst dst, struct ureg_src src, struct ureg_src mask, - unsigned component_alpha, unsigned mask_luminance) + unsigned mask_luminance) { - if (component_alpha == FS_CA_FULL) { - ureg_MUL(ureg, dst, src, mask); - } else if (component_alpha == FS_CA_SRCALPHA) { - ureg_MUL(ureg, dst, ureg_scalar(src, TGSI_SWIZZLE_W), mask); - } else { - if (mask_luminance) - ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X)); - else - ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W)); - } + if (mask_luminance) + ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X)); + else + ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W)); } static struct ureg_src @@ -139,125 +129,6 @@ vs_normalize_coords(struct ureg_program *ureg, return ret; } -static void -linear_gradient(struct ureg_program *ureg, - struct ureg_dst out, - struct ureg_src pos, - struct ureg_src sampler, - struct ureg_src coords, - struct ureg_src const0124, - struct ureg_src matrow0, - struct ureg_src matrow1, struct ureg_src matrow2) -{ - struct ureg_dst temp0 = ureg_DECL_temporary(ureg); - struct ureg_dst temp1 = ureg_DECL_temporary(ureg); - struct ureg_dst temp2 = ureg_DECL_temporary(ureg); - struct ureg_dst temp3 = ureg_DECL_temporary(ureg); - struct ureg_dst temp4 = ureg_DECL_temporary(ureg); - struct ureg_dst temp5 = ureg_DECL_temporary(ureg); - - ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); - ureg_MOV(ureg, - ureg_writemask(temp0, TGSI_WRITEMASK_Z), - ureg_scalar(const0124, TGSI_SWIZZLE_Y)); - - ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); - ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); - ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); - ureg_RCP(ureg, temp3, ureg_src(temp3)); - ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); - ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); - - ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X), ureg_src(temp1)); - ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y), ureg_src(temp2)); - - ureg_MUL(ureg, temp0, - ureg_scalar(coords, TGSI_SWIZZLE_Y), - ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y)); - ureg_MAD(ureg, temp1, - ureg_scalar(coords, TGSI_SWIZZLE_X), - ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X), ureg_src(temp0)); - - ureg_MUL(ureg, temp2, ureg_src(temp1), ureg_scalar(coords, TGSI_SWIZZLE_Z)); - - ureg_TEX(ureg, out, TGSI_TEXTURE_1D, ureg_src(temp2), sampler); - - ureg_release_temporary(ureg, temp0); - ureg_release_temporary(ureg, temp1); - ureg_release_temporary(ureg, temp2); - ureg_release_temporary(ureg, temp3); - ureg_release_temporary(ureg, temp4); - ureg_release_temporary(ureg, temp5); -} - -static void -radial_gradient(struct ureg_program *ureg, - struct ureg_dst out, - struct ureg_src pos, - struct ureg_src sampler, - struct ureg_src coords, - struct ureg_src const0124, - struct ureg_src matrow0, - struct ureg_src matrow1, struct ureg_src matrow2) -{ - struct ureg_dst temp0 = ureg_DECL_temporary(ureg); - struct ureg_dst temp1 = ureg_DECL_temporary(ureg); - struct ureg_dst temp2 = ureg_DECL_temporary(ureg); - struct ureg_dst temp3 = ureg_DECL_temporary(ureg); - struct ureg_dst temp4 = ureg_DECL_temporary(ureg); - struct ureg_dst temp5 = ureg_DECL_temporary(ureg); - - ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); - ureg_MOV(ureg, - ureg_writemask(temp0, TGSI_WRITEMASK_Z), - ureg_scalar(const0124, TGSI_SWIZZLE_Y)); - - ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); - ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); - ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); - ureg_RCP(ureg, temp3, ureg_src(temp3)); - ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); - ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); - - ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X), ureg_src(temp1)); - ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y), ureg_src(temp2)); - - ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y), - ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); - ureg_MAD(ureg, temp1, - ureg_scalar(coords, TGSI_SWIZZLE_X), - ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), ureg_src(temp0)); - ureg_ADD(ureg, temp1, ureg_src(temp1), ureg_src(temp1)); - ureg_MUL(ureg, temp3, - ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y), - ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); - ureg_MAD(ureg, temp4, - ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), - ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), ureg_src(temp3)); - ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4))); - ureg_MUL(ureg, temp2, ureg_scalar(coords, TGSI_SWIZZLE_Z), ureg_src(temp4)); - ureg_MUL(ureg, temp0, - ureg_scalar(const0124, TGSI_SWIZZLE_W), ureg_src(temp2)); - ureg_MUL(ureg, temp3, ureg_src(temp1), ureg_src(temp1)); - ureg_ADD(ureg, temp2, ureg_src(temp3), ureg_negate(ureg_src(temp0))); - ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2))); - ureg_RCP(ureg, temp2, ureg_src(temp2)); - ureg_ADD(ureg, temp1, ureg_src(temp2), ureg_negate(ureg_src(temp1))); - ureg_ADD(ureg, temp0, - ureg_scalar(coords, TGSI_SWIZZLE_Z), - ureg_scalar(coords, TGSI_SWIZZLE_Z)); - ureg_RCP(ureg, temp0, ureg_src(temp0)); - ureg_MUL(ureg, temp2, ureg_src(temp1), ureg_src(temp0)); - ureg_TEX(ureg, out, TGSI_TEXTURE_1D, ureg_src(temp2), sampler); - - ureg_release_temporary(ureg, temp0); - ureg_release_temporary(ureg, temp1); - ureg_release_temporary(ureg, temp2); - ureg_release_temporary(ureg, temp3); - ureg_release_temporary(ureg, temp4); - ureg_release_temporary(ureg, temp5); -} - static void * create_vs(struct pipe_context *pipe, unsigned vs_traits) { @@ -265,10 +136,11 @@ create_vs(struct pipe_context *pipe, unsigned vs_traits) struct ureg_src src; struct ureg_dst dst; struct ureg_src const0, const1; - boolean is_fill = (vs_traits & VS_FILL) != 0; boolean is_composite = (vs_traits & VS_COMPOSITE) != 0; boolean has_mask = (vs_traits & VS_MASK) != 0; boolean is_yuv = (vs_traits & VS_YUV) != 0; + boolean is_src_src = (vs_traits & VS_SRC_SRC) != 0; + boolean is_mask_src = (vs_traits & VS_MASK_SRC) != 0; unsigned input_slot = 0; ureg = ureg_create(PIPE_SHADER_VERTEX); @@ -279,8 +151,6 @@ create_vs(struct pipe_context *pipe, unsigned vs_traits) const1 = ureg_DECL_constant(ureg, 1); /* it has to be either a fill or a composite op */ - debug_assert((is_fill ^ is_composite) ^ is_yuv); - src = ureg_DECL_vs_input(ureg, input_slot++); dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); src = vs_normalize_coords(ureg, src, const0, const1); @@ -293,21 +163,17 @@ create_vs(struct pipe_context *pipe, unsigned vs_traits) } if (is_composite) { - src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); - ureg_MOV(ureg, dst, src); - } + if (!is_src_src || (has_mask && !is_mask_src)) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); + ureg_MOV(ureg, dst, src); + } - if (is_fill) { - src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); - ureg_MOV(ureg, dst, src); - } - - if (has_mask) { - src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); - ureg_MOV(ureg, dst, src); + if (!is_src_src && (has_mask && !is_mask_src)) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); + ureg_MOV(ureg, dst, src); + } } ureg_END(ureg); @@ -383,7 +249,7 @@ xrender_tex(struct ureg_program *ureg, struct ureg_dst dst, struct ureg_src coords, struct ureg_src sampler, - struct ureg_src imm0, + const struct ureg_src *imm0, boolean repeat_none, boolean swizzle, boolean set_alpha) { if (repeat_none) { @@ -394,11 +260,11 @@ xrender_tex(struct ureg_program *ureg, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, - TGSI_SWIZZLE_Y), ureg_scalar(imm0, + TGSI_SWIZZLE_Y), ureg_scalar(*imm0, TGSI_SWIZZLE_X)); ureg_SLT(ureg, tmp0, ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, - TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(imm0, + TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(*imm0, TGSI_SWIZZLE_W)); ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), @@ -412,7 +278,7 @@ xrender_tex(struct ureg_program *ureg, if (set_alpha) ureg_MOV(ureg, ureg_writemask(tmp1, TGSI_WRITEMASK_W), - ureg_scalar(imm0, TGSI_SWIZZLE_W)); + ureg_scalar(*imm0, TGSI_SWIZZLE_W)); ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); ureg_release_temporary(ureg, tmp0); ureg_release_temporary(ureg, tmp1); @@ -432,7 +298,32 @@ xrender_tex(struct ureg_program *ureg, if (set_alpha) ureg_MOV(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W), - ureg_scalar(imm0, TGSI_SWIZZLE_W)); + ureg_scalar(*imm0, TGSI_SWIZZLE_W)); + } +} + +static void +read_input(struct ureg_program *ureg, + struct ureg_dst dst, + const struct ureg_src *imm0, + boolean repeat_none, boolean swizzle, boolean set_alpha, + boolean is_src, unsigned *cur_constant, unsigned *cur_sampler) +{ + struct ureg_src input, sampler; + + if (is_src) { + input = ureg_DECL_constant(ureg, (*cur_constant)++); + ureg_MOV(ureg, dst, input); + } else { + sampler = ureg_DECL_sampler(ureg, *cur_sampler); + ureg_DECL_sampler_view(ureg, *cur_sampler, TGSI_TEXTURE_2D, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); + input = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, (*cur_sampler)++, + TGSI_INTERPOLATE_PERSPECTIVE); + xrender_tex(ureg, dst, input, sampler, imm0, + repeat_none, swizzle, set_alpha); } } @@ -440,18 +331,10 @@ static void * create_fs(struct pipe_context *pipe, unsigned fs_traits) { struct ureg_program *ureg; - struct ureg_src /*dst_sampler, */ src_sampler, mask_sampler; - struct ureg_src /*dst_pos, */ src_input, mask_pos; struct ureg_dst src, mask; struct ureg_dst out; struct ureg_src imm0 = { 0 }; unsigned has_mask = (fs_traits & FS_MASK) != 0; - unsigned is_fill = (fs_traits & FS_FILL) != 0; - unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0; - unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0; - unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0; - unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0; - unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA; unsigned is_yuv = (fs_traits & FS_YUV) != 0; unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; @@ -462,6 +345,10 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits) 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; + unsigned is_src_src = (fs_traits & FS_SRC_SRC) != 0; + unsigned is_mask_src = (fs_traits & FS_MASK_SRC) != 0; + unsigned cur_sampler = 0; + unsigned cur_constant = 0; #if 0 print_fs_traits(fs_traits); @@ -473,9 +360,8 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits) if (ureg == NULL) return 0; - /* it has to be either a fill, a composite op or a yuv conversion */ - debug_assert((is_fill ^ is_composite) ^ is_yuv); - (void)is_yuv; + if (is_yuv) + return create_yuv_shader(pipe, ureg); out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); @@ -483,86 +369,13 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits) src_set_alpha || mask_set_alpha || src_luminance) { imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); } - if (is_composite) { - src_sampler = ureg_DECL_sampler(ureg, 0); - ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); - src_input = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_GENERIC, 0, - TGSI_INTERPOLATE_PERSPECTIVE); - } else if (is_fill) { - if (is_solid) - src_input = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_COLOR, 0, - TGSI_INTERPOLATE_PERSPECTIVE); - else - src_input = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_POSITION, 0, - TGSI_INTERPOLATE_PERSPECTIVE); - } else { - debug_assert(is_yuv); - return create_yuv_shader(pipe, ureg); - } - if (has_mask) { - mask_sampler = ureg_DECL_sampler(ureg, 1); - ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); - mask_pos = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_GENERIC, 1, - TGSI_INTERPOLATE_PERSPECTIVE); - } -#if 0 /* unused right now */ - dst_sampler = ureg_DECL_sampler(ureg, 2); - ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); - dst_pos = ureg_DECL_fs_input(ureg, - TGSI_SEMANTIC_POSITION, 2, - TGSI_INTERPOLATE_PERSPECTIVE); -#endif + src = (has_mask || src_luminance || dst_luminance) ? + ureg_DECL_temporary(ureg) : out; - if (is_composite) { - if (has_mask || src_luminance || dst_luminance) - src = ureg_DECL_temporary(ureg); - else - src = out; - xrender_tex(ureg, src, src_input, src_sampler, imm0, - src_repeat_none, src_swizzle, src_set_alpha); - } else if (is_fill) { - if (is_solid) { - 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; + read_input(ureg, src, &imm0, src_repeat_none, src_swizzle, + src_set_alpha, is_src_src, &cur_constant, &cur_sampler); - if (has_mask || src_luminance || dst_luminance) - src = ureg_DECL_temporary(ureg); - else - src = out; - - coords = ureg_DECL_constant(ureg, 0); - const0124 = ureg_DECL_constant(ureg, 1); - matrow0 = ureg_DECL_constant(ureg, 2); - matrow1 = ureg_DECL_constant(ureg, 3); - matrow2 = ureg_DECL_constant(ureg, 4); - - if (is_lingrad) { - linear_gradient(ureg, src, - src_input, src_sampler, - coords, const0124, matrow0, matrow1, matrow2); - } else if (is_radgrad) { - radial_gradient(ureg, src, - src_input, src_sampler, - coords, const0124, matrow0, matrow1, matrow2); - } - } else - debug_assert(!"Unknown fill type!"); - } if (src_luminance) { ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X)); ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ), @@ -573,13 +386,12 @@ create_fs(struct pipe_context *pipe, unsigned fs_traits) if (has_mask) { mask = ureg_DECL_temporary(ureg); - xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0, - mask_repeat_none, mask_swizzle, mask_set_alpha); - /* src IN mask */ + read_input(ureg, mask, &imm0, mask_repeat_none, + mask_swizzle, mask_set_alpha, is_mask_src, &cur_constant, + &cur_sampler); src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src), - ureg_src(mask), - comp_alpha_mask, mask_luminance); + ureg_src(mask), mask_luminance); ureg_release_temporary(ureg, mask); }