From adf166b6c4f6781fd5e751622e9488e5f834bbc2 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 21 Jun 2011 21:31:59 +0200 Subject: [PATCH] st/xa: Solid fill (tested) and composite (yet untested) Signed-off-by: Thomas Hellstrom --- src/gallium/state_trackers/xa/Makefile | 5 +- src/gallium/state_trackers/xa/xa_composite.c | 495 +++++++++++++++++++ src/gallium/state_trackers/xa/xa_composite.h | 131 +++++ src/gallium/state_trackers/xa/xa_context.c | 127 ++++- src/gallium/state_trackers/xa/xa_context.h | 9 + src/gallium/state_trackers/xa/xa_priv.h | 55 ++- src/gallium/state_trackers/xa/xa_renderer.c | 156 ++++++ src/gallium/state_trackers/xa/xa_symbols | 14 +- src/gallium/state_trackers/xa/xa_tracker.h | 2 +- src/gallium/targets/xa-vmwgfx/Makefile | 3 +- 10 files changed, 974 insertions(+), 23 deletions(-) create mode 100644 src/gallium/state_trackers/xa/xa_composite.c create mode 100644 src/gallium/state_trackers/xa/xa_composite.h diff --git a/src/gallium/state_trackers/xa/Makefile b/src/gallium/state_trackers/xa/Makefile index 7dc47b59ccc..92edfd09340 100644 --- a/src/gallium/state_trackers/xa/Makefile +++ b/src/gallium/state_trackers/xa/Makefile @@ -4,7 +4,7 @@ include $(TOP)/configs/current ##### MACROS ##### XA_MAJOR = 0 -XA_MINOR = 2 +XA_MINOR = 3 XA_TINY = 0 XA_CFLAGS = -g -fPIC -Wall @@ -25,7 +25,8 @@ SOURCES = \ xa_context.c \ xa_renderer.c \ xa_tgsi.c \ - xa_yuv.c + xa_yuv.c \ + xa_composite.c OBJECTS = $(SOURCES:.c=.o) ##### RULES ##### diff --git a/src/gallium/state_trackers/xa/xa_composite.c b/src/gallium/state_trackers/xa/xa_composite.c new file mode 100644 index 00000000000..b30728423e8 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_composite.c @@ -0,0 +1,495 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#include "xa_composite.h" +#include "xa_context.h" +#include "xa_priv.h" +#include "cso_cache/cso_context.h" +#include "util/u_sampler.h" +#include "util/u_inlines.h" + + +/*XXX also in Xrender.h but the including it here breaks compilition */ +#define XFixedToDouble(f) (((double) (f)) / 65536.) + +struct xa_composite_blend { + enum xa_composite_op op : 8; + + unsigned alpha_dst : 4; + unsigned alpha_src : 4; + + unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ + unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ +}; + +#define XA_BLEND_OP_OVER 3 +static const struct xa_composite_blend xa_blends[] = { + { xa_op_clear, + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, + { xa_op_src, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, + { xa_op_dst, + 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, + { xa_op_over, + 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_over_reverse, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, + { xa_op_in, + 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { xa_op_in_reverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, + { xa_op_out, + 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, + { xa_op_out_reverse, + 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_atop, + 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_atop_reverse, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, + { xa_op_xor, + 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, + { xa_op_add, + 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, +}; + + +static boolean +blend_for_op(struct xa_composite_blend *blend, + enum xa_composite_op op, + struct xa_picture *src_pic, + struct xa_picture *mask_pic, + struct xa_picture *dst_pic) +{ + const int num_blends = + sizeof(xa_blends)/sizeof(struct xa_composite_blend); + int i; + boolean supported = FALSE; + + /* + * our default in case something goes wrong + */ + + *blend = xa_blends[XA_BLEND_OP_OVER]; + + for (i = 0; i < num_blends; ++i) { + if (xa_blends[i].op == op) { + *blend = xa_blends[i]; + supported = TRUE; + } + } + + + /* + * 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(xa_surface_format(dst_pic->srf)) == 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) + 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(xa_surface_format(mask_pic->srf)) && + 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; +} + + +static INLINE int +xa_repeat_to_gallium(int mode) +{ + switch(mode) { + case xa_wrap_clamp_to_border: + return PIPE_TEX_WRAP_CLAMP_TO_BORDER; + case xa_wrap_repeat: + return PIPE_TEX_WRAP_REPEAT; + case xa_wrap_mirror_repeat: + return PIPE_TEX_WRAP_MIRROR_REPEAT; + case xa_wrap_clamp_to_edge: + return PIPE_TEX_WRAP_CLAMP_TO_EDGE; + default: + break; + } + return PIPE_TEX_WRAP_REPEAT; +} + +static INLINE boolean +xa_filter_to_gallium(int xrender_filter, int *out_filter) +{ + + switch (xrender_filter) { + case xa_filter_nearest: + *out_filter = PIPE_TEX_FILTER_NEAREST; + break; + case xa_filter_linear: + *out_filter = PIPE_TEX_FILTER_LINEAR; + break; + default: + *out_filter = PIPE_TEX_FILTER_NEAREST; + return FALSE; + } + return TRUE; +} + +static int +xa_is_filter_accelerated(struct xa_picture *pic) +{ + int filter; + if (pic && !xa_filter_to_gallium(pic->filter, &filter)) + return 0; + return 1; +} + +int +xa_composite_is_accelerated(const struct xa_composite *comp) +{ + struct xa_composite_blend blend; + struct xa_picture *src_pic = comp->src; + + if (!xa_is_filter_accelerated(src_pic) || + !xa_is_filter_accelerated(comp->mask)) { + return 0; + } + + + if (src_pic->src_pict) { + if (src_pic->src_pict->type != xa_src_pict_solid_fill) + return 0; + } + + 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(xa_surface_format(mask->srf))) { + if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) { + return 0; + } + } + + return 1; + } + return 0; +} + +static void +bind_composite_blend_state(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct xa_composite_blend blend_opt; + struct pipe_blend_state blend; + + blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst); + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 1; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + blend.rt[0].rgb_src_factor = blend_opt.rgb_src; + blend.rt[0].alpha_src_factor = blend_opt.rgb_src; + blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; + blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; + + cso_set_blend(ctx->cso, &blend); +} + +static unsigned int +picture_format_fixups(struct xa_picture *src_pic, + struct xa_picture *dst_pic, + int mask) +{ + boolean set_alpha = FALSE; + boolean swizzle = FALSE; + unsigned ret = 0; + struct xa_surface *src = src_pic->srf; + enum xa_formats src_hw_format, src_pic_format; + enum xa_surface_type src_hw_type, src_pic_type; + + src_hw_format = xa_surface_format(src); + src_pic_format = src_pic->pict_format; + + if (src_hw_format == src_pic_format) { + if (src_pic->pict_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; + } + + src_hw_type = xa_format_type(src_hw_format); + src_pic_type = xa_format_type(src_pic_format); + + swizzle = ((src_hw_type == xa_type_argb && + src_pic_type == xa_type_abgr) || + ((src_hw_type == xa_type_abgr && + src_pic_type == xa_type_argb))); + + if (!swizzle && (src_hw_type != src_pic_type)) + return 0; + + set_alpha = (xa_format_type_is_color(src_hw_type) && + xa_format_a(src_hw_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; + + return ret; +} + +static void +bind_shaders(struct xa_context *ctx, const struct xa_composite *comp) +{ + unsigned vs_traits = 0, fs_traits = 0; + 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; + + if (src_pic) { + if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) + fs_traits |= FS_SRC_REPEAT_NONE; + + if (src_pic->src_pict) { + if (src_pic->src_pict->type == xa_src_pict_solid_fill) { + fs_traits |= FS_SOLID_FILL; + vs_traits |= VS_SOLID_FILL; + xa_pixel_to_float4(src_pic->src_pict->solid_fill.color, + ctx->solid_color); + ctx->has_solid_color = TRUE; + } + } else { + fs_traits |= FS_COMPOSITE; + vs_traits |= VS_COMPOSITE; + } + + fs_traits |= picture_format_fixups(src_pic, dst_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->component_alpha) { + struct xa_composite_blend blend; + blend_for_op(&blend, comp->op, src_pic, mask_pic, NULL); + if (blend.alpha_src) { + fs_traits |= FS_CA_SRCALPHA; + } else + fs_traits |= FS_CA_FULL; + } + + fs_traits |= picture_format_fixups(mask_pic, dst_pic, 1); + } + + 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); +} + +static void +bind_samplers(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state src_sampler, mask_sampler; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; + struct pipe_context *pipe = ctx->pipe; + struct xa_picture *src_pic = comp->src; + struct xa_picture *mask_pic = comp->mask; + + ctx->num_bound_samplers = 0; + + 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; + + (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; + } + } + + if (mask_pic) { + unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); + int filter; + + (void) xa_filter_to_gallium(mask_pic->filter, &filter); + + mask_sampler.wrap_s = mask_wrap; + mask_sampler.wrap_t = mask_wrap; + mask_sampler.min_img_filter = filter; + 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; + 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; + } + + cso_set_samplers(ctx->cso, ctx->num_bound_samplers, + (const struct pipe_sampler_state **)samplers); + cso_set_fragment_sampler_views(ctx->cso, ctx->num_bound_samplers, + ctx->bound_sampler_views); +} + +int +xa_composite_prepare(struct xa_context *ctx, + const struct xa_composite *comp) +{ + struct xa_surface *dst_srf = comp->dst->srf; + int ret; + + ret = xa_surface_psurf_create(ctx, dst_srf); + if (ret != XA_ERR_NONE) + return ret; + + renderer_bind_destination(ctx, dst_srf->srf, + dst_srf->srf->width, + dst_srf->srf->height); + + bind_composite_blend_state(ctx, comp); + bind_shaders(ctx, comp); + bind_samplers(ctx, comp); + + if (ctx->num_bound_samplers == 0 ) { /* solid fill */ + renderer_begin_solid(ctx); + } else { + renderer_begin_textures(ctx); + } + + xa_surface_psurf_destroy(dst_srf); + return XA_ERR_NONE; +} + +void xa_composite_rect(struct xa_context *ctx, + int srcX, int srcY, int maskX, int maskY, + 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); + } else { + const struct xa_composite *comp = ctx->comp; + int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; + const float *src_matrix = NULL; + const float *mask_matrix = NULL; + + if (comp->src->has_transform) + src_matrix = comp->src->transform; + if (comp->mask->has_transform) + mask_matrix = comp->mask->transform; + + renderer_texture(ctx, pos, width, height, + src_matrix, mask_matrix); + } +} + +void +xa_composite_done(struct xa_context *ctx) +{ + renderer_draw_flush(ctx); + ctx->pipe->flush(ctx->pipe, &ctx->last_fence); + + ctx->comp = NULL; + ctx->has_solid_color = FALSE; + ctx->num_bound_samplers = 0; +} + +static const struct xa_composite_allocation a = { + .xa_composite_size = sizeof(struct xa_composite), + .xa_picture_size = sizeof(struct xa_picture), + .xa_source_pict_size = sizeof(union xa_source_pict), +}; + +const struct xa_composite_allocation * +xa_composite_allocation(void) +{ + return &a; +} diff --git a/src/gallium/state_trackers/xa/xa_composite.h b/src/gallium/state_trackers/xa/xa_composite.h new file mode 100644 index 00000000000..63174a41fb1 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_composite.h @@ -0,0 +1,131 @@ +/********************************************************** + * Copyright 2009-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ********************************************************* + * Authors: + * Zack Rusin + * Thomas Hellstrom + */ + +#ifndef _XA_COMPOSITE_H_ +#define _XA_COMPOSITE_H_ + +#include "xa_tracker.h" +#include "xa_context.h" + +/* + * Supported composite ops. + */ +enum xa_composite_op { + xa_op_clear, + xa_op_src, + xa_op_dst, + xa_op_over, + xa_op_over_reverse, + xa_op_in, + xa_op_in_reverse, + xa_op_out, + xa_op_out_reverse, + xa_op_atop, + xa_op_atop_reverse, + xa_op_xor, + xa_op_add +}; + +/* + * Supported filters. + */ +enum xa_composite_filter { + xa_filter_nearest, + xa_filter_linear +}; + +/* + * Supported clamp methods. + */ +enum xa_composite_wrap { + xa_wrap_clamp_to_border, + xa_wrap_repeat, + xa_wrap_mirror_repeat, + xa_wrap_clamp_to_edge +}; + +/* + * Src picture types. + */ +enum xa_composite_src_pict_type { + xa_src_pict_solid_fill +}; + +struct xa_pict_solid_fill { + enum xa_composite_src_pict_type type; + unsigned int class; + uint32_t color; +}; + +union xa_source_pict { + unsigned int type; + struct xa_pict_solid_fill solid_fill; +}; + +struct xa_picture { + enum xa_formats pict_format; + struct xa_surface *srf; + struct xa_surface *alpha_map; + float transform[9]; + int has_transform; + int component_alpha; + enum xa_composite_wrap wrap; + enum xa_composite_filter filter; + union xa_source_pict *src_pict; +}; + +struct xa_composite { + struct xa_picture *src, *mask, *dst; + int op; +}; + +struct xa_composite_allocation { + unsigned int xa_composite_size; + unsigned int xa_picture_size; + unsigned int xa_source_pict_size; +}; + +/* + * Get allocation sizes for minor bump compatibility. + */ + +extern const struct xa_composite_allocation * +xa_composite_allocation(void); +extern int +xa_composite_is_accelerated(const struct xa_composite *comp); +extern int +xa_composite_prepare(struct xa_context *ctx, const struct xa_composite *comp); +extern void +xa_composite_rect(struct xa_context *ctx, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height); +extern void +xa_composite_done(struct xa_context *ctx); + +#endif diff --git a/src/gallium/state_trackers/xa/xa_context.c b/src/gallium/state_trackers/xa/xa_context.c index a6abd8c4107..3cc25ed2071 100644 --- a/src/gallium/state_trackers/xa/xa_context.c +++ b/src/gallium/state_trackers/xa/xa_context.c @@ -173,6 +173,35 @@ xa_surface_unmap(struct xa_surface *srf) } } +int +xa_surface_psurf_create(struct xa_context *ctx, struct xa_surface *dst) +{ + struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_surface srf_templ; + + if (dst->srf) + return -XA_ERR_INVAL; + + if (!screen->is_format_supported(screen, dst->tex->format, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET)) + return -XA_ERR_INVAL; + + u_surface_default_template(&srf_templ, dst->tex, + PIPE_BIND_RENDER_TARGET); + dst->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ); + if (!dst->srf) + return -XA_ERR_NORES; + + return XA_ERR_NONE; +} + +void +xa_surface_psurf_destroy(struct xa_surface *dst) +{ + pipe_surface_reference(&dst->srf, NULL); +} + int xa_copy_prepare(struct xa_context *ctx, struct xa_surface *dst, struct xa_surface *src) @@ -181,19 +210,9 @@ xa_copy_prepare(struct xa_context *ctx, return -XA_ERR_INVAL; if (src->tex->format != dst->tex->format) { - struct pipe_screen *screen = ctx->pipe->screen; - struct pipe_surface srf_templ; - - if (!screen->is_format_supported(screen, dst->tex->format, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET)) - return -XA_ERR_INVAL; - u_surface_default_template(&srf_templ, dst->tex, - PIPE_BIND_RENDER_TARGET); - dst->srf = ctx->pipe->create_surface(ctx->pipe, dst->tex, &srf_templ); - if (!dst->srf) - return -XA_ERR_NORES; - + int ret = xa_surface_psurf_create(ctx, dst); + if (ret != XA_ERR_NONE) + return ret; renderer_copy_prepare(ctx, dst->srf, src->tex); ctx->simple_copy = 0; } else @@ -228,11 +247,91 @@ xa_copy_done(struct xa_context *ctx) if (!ctx->simple_copy) { renderer_draw_flush(ctx); ctx->pipe->flush(ctx->pipe, &ctx->last_fence); - pipe_surface_reference(&ctx->dst->srf, NULL); + xa_surface_psurf_destroy(ctx->dst); } else ctx->pipe->flush(ctx->pipe, &ctx->last_fence); } +static void +bind_solid_blend_state(struct xa_context *ctx) +{ + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].blend_enable = 0; + blend.rt[0].colormask = PIPE_MASK_RGBA; + + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + + cso_set_blend(ctx->cso, &blend); +} + +int +xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, + uint32_t fg) +{ + unsigned vs_traits, fs_traits; + struct xa_shader shader; + 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; + + ctx->dst = dst; + width = dst->srf->width; + height = dst->srf->height; + +#if 0 + debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n", + (fg >> 24) & 0xff, (fg >> 16) & 0xff, + (fg >> 8) & 0xff, (fg >> 0) & 0xff, + exa->solid_color[0], exa->solid_color[1], + exa->solid_color[2], exa->solid_color[3]); +#endif + + vs_traits = VS_SOLID_FILL; + fs_traits = FS_SOLID_FILL; + + renderer_bind_destination(ctx, dst->srf, width, height); + bind_solid_blend_state(ctx); + cso_set_samplers(ctx->cso, 0, NULL); + cso_set_fragment_sampler_views(ctx->cso, 0, NULL); + + 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); + + renderer_begin_solid(ctx); + + xa_surface_psurf_destroy(dst); + return XA_ERR_NONE; +} + +void +xa_solid(struct xa_context *ctx, int x, int y, int width, int height) +{ + renderer_solid(ctx, x, y, x + width, y + height, ctx->solid_color); +} + +void +xa_solid_done(struct xa_context *ctx) +{ + renderer_draw_flush(ctx); + ctx->pipe->flush(ctx->pipe, &ctx->last_fence); + + ctx->comp = NULL; + ctx->has_solid_color = FALSE; + ctx->num_bound_samplers = 0; +} + struct xa_fence * xa_fence_get(struct xa_context *ctx) { diff --git a/src/gallium/state_trackers/xa/xa_context.h b/src/gallium/state_trackers/xa/xa_context.h index 753ba3d79b4..ea2b923a5a1 100644 --- a/src/gallium/state_trackers/xa/xa_context.h +++ b/src/gallium/state_trackers/xa/xa_context.h @@ -69,6 +69,15 @@ extern int xa_surface_dma(struct xa_context *ctx, int to_surface, struct xa_box *boxes, unsigned int num_boxes); +extern int +xa_solid_prepare(struct xa_context *ctx, struct xa_surface *dst, + uint32_t fg); +extern void +xa_solid(struct xa_context *ctx, int x, int y, int width, int height); + +extern void +xa_solid_done(struct xa_context *ctx); + extern struct xa_fence *xa_fence_get(struct xa_context *ctx); extern int xa_fence_wait(struct xa_fence *fence, uint64_t timeout); diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h index 22a49c138ce..94627e1e9d0 100644 --- a/src/gallium/state_trackers/xa/xa_priv.h +++ b/src/gallium/state_trackers/xa/xa_priv.h @@ -32,6 +32,7 @@ #include "xa_tracker.h" #include "xa_context.h" +#include "xa_composite.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" @@ -39,6 +40,7 @@ #define XA_VB_SIZE (100 * 4 * 3 * 4) #define XA_LAST_SURFACE_TYPE (xa_type_yuv_component + 1) +#define XA_MAX_SAMPLERS 3 struct xa_fence { struct pipe_fence_handle *pipe_fence; @@ -96,6 +98,13 @@ struct xa_context { struct xa_surface *src; struct xa_surface *dst; int simple_copy; + + int has_solid_color; + float solid_color[4]; + + unsigned int num_bound_samplers; + struct pipe_sampler_view *bound_sampler_views[XA_MAX_SAMPLERS]; + const struct xa_composite *comp; }; enum xa_vs_traits { @@ -136,13 +145,33 @@ struct xa_shader { void *vs; }; -static inline int +struct xa_shaders; + +/* + * Inline utilities + */ + +static INLINE int xa_min(int a, int b) { return ((a <= b) ? a : b); } -struct xa_shaders; +static INLINE void +xa_pixel_to_float4(uint32_t pixel, float *color) +{ + uint32_t r, g, b, a; + + a = (pixel >> 24) & 0xff; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel >> 0) & 0xff; + color[0] = ((float)r) / 255.; + color[1] = ((float)g) / 255.; + color[2] = ((float)b) / 255.; + color[3] = ((float)a) / 255.; +} + /* * xa_tgsi.c @@ -155,6 +184,15 @@ void xa_shaders_destroy(struct xa_shaders *shaders); struct xa_shader xa_shaders_get(struct xa_shaders *shaders, unsigned vs_traits, unsigned fs_traits); +/* + * xa_context.c + */ +extern int +xa_surface_psurf_create(struct xa_context *ctx, struct xa_surface *dst); + +extern void +xa_surface_psurf_destroy(struct xa_surface *dst); + /* * xa_renderer.c */ @@ -187,4 +225,17 @@ void renderer_copy(struct xa_context *r, int dx, 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); +void +renderer_begin_textures(struct xa_context *r); + +void +renderer_texture(struct xa_context *r, + int *pos, + int width, int height, + const float *src_matrix, + const float *mask_matrix); + #endif diff --git a/src/gallium/state_trackers/xa/xa_renderer.c b/src/gallium/state_trackers/xa/xa_renderer.c index b92df0da7d5..559b2699da6 100644 --- a/src/gallium/state_trackers/xa/xa_renderer.c +++ b/src/gallium/state_trackers/xa/xa_renderer.c @@ -202,6 +202,107 @@ add_vertex_2tex(struct xa_context *r, r->buffer_size += 12; } +static void +add_vertex_data1(struct xa_context *r, + float srcX, float srcY, float dstX, float dstY, + float width, float height, + struct pipe_resource *src, const float *src_matrix) +{ + float s0, t0, s1, t1, s2, t2, s3, t3; + float pt0[2], pt1[2], pt2[2], pt3[2]; + + pt0[0] = srcX; + pt0[1] = srcY; + pt1[0] = (srcX + width); + pt1[1] = srcY; + pt2[0] = (srcX + width); + pt2[1] = (srcY + height); + pt3[0] = srcX; + pt3[1] = (srcY + height); + + if (src_matrix) { + map_point((float *)src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]); + map_point((float *)src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]); + map_point((float *)src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]); + map_point((float *)src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]); + } + + s0 = pt0[0] / src->width0; + s1 = pt1[0] / src->width0; + s2 = pt2[0] / src->width0; + s3 = pt3[0] / src->width0; + t0 = pt0[1] / src->height0; + t1 = pt1[1] / src->height0; + t2 = pt2[1] / src->height0; + t3 = pt3[1] / src->height0; + + /* 1st vertex */ + add_vertex_1tex(r, dstX, dstY, s0, t0); + /* 2nd vertex */ + add_vertex_1tex(r, dstX + width, dstY, s1, t1); + /* 3rd vertex */ + add_vertex_1tex(r, dstX + width, dstY + height, s2, t2); + /* 4th vertex */ + add_vertex_1tex(r, dstX, dstY + height, s3, t3); +} + +static void +add_vertex_data2(struct xa_context *r, + float srcX, float srcY, float maskX, float maskY, + float dstX, float dstY, float width, float height, + struct pipe_resource *src, + struct pipe_resource *mask, + const float *src_matrix, const float *mask_matrix) +{ + float src_s0, src_t0, src_s1, src_t1; + float mask_s0, mask_t0, mask_s1, mask_t1; + float spt0[2], spt1[2]; + float mpt0[2], mpt1[2]; + + spt0[0] = srcX; + spt0[1] = srcY; + spt1[0] = srcX + width; + spt1[1] = srcY + height; + + mpt0[0] = maskX; + mpt0[1] = maskY; + mpt1[0] = maskX + width; + mpt1[1] = maskY + height; + + if (src_matrix) { + map_point((float *)src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]); + map_point((float *)src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]); + } + + if (mask_matrix) { + map_point((float *)mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]); + map_point((float *)mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]); + } + + src_s0 = spt0[0] / src->width0; + src_t0 = spt0[1] / src->height0; + src_s1 = spt1[0] / src->width0; + src_t1 = spt1[1] / src->height0; + + mask_s0 = mpt0[0] / mask->width0; + mask_t0 = mpt0[1] / mask->height0; + mask_s1 = mpt1[0] / mask->width0; + mask_t1 = mpt1[1] / mask->height0; + + /* 1st vertex */ + add_vertex_2tex(r, dstX, dstY, + src_s0, src_t0, mask_s0, mask_t0); + /* 2nd vertex */ + add_vertex_2tex(r, dstX + width, dstY, + src_s1, src_t0, mask_s1, mask_t0); + /* 3rd vertex */ + add_vertex_2tex(r, dstX + width, dstY + height, + src_s1, src_t1, mask_s1, mask_t1); + /* 4th vertex */ + add_vertex_2tex(r, dstX, dstY + height, + src_s0, src_t1, mask_s0, mask_t1); +} + static struct pipe_resource * setup_vertex_data_yuv(struct xa_context *r, float srcX, @@ -468,3 +569,58 @@ renderer_draw_flush(struct xa_context *r) { renderer_draw_conditional(r, 0); } + +void +renderer_begin_textures(struct xa_context *r) +{ + r->attrs_per_vertex = 1 + r->num_bound_samplers; + r->buffer_size = 0; +} + +void +renderer_texture(struct xa_context *r, + int *pos, + int width, int height, + const float *src_matrix, + const float *mask_matrix) +{ + struct pipe_sampler_view **sampler_view = r->bound_sampler_views; + +#if 0 + if (src_matrix) { + debug_printf("src_matrix = \n"); + debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]); + debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]); + debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]); + } + if (mask_matrix) { + debug_printf("mask_matrix = \n"); + debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]); + debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]); + debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]); + } +#endif + + 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); + break; + case 3: + renderer_draw_conditional(r, 4 * 12); + add_vertex_data2(r, + pos[0], pos[1], /* src */ + pos[2], pos[3], /* mask */ + pos[4], pos[5], /* dst */ + width, height, + sampler_view[0]->texture, sampler_view[1]->texture, + src_matrix, mask_matrix); + break; + default: + break; + } +} diff --git a/src/gallium/state_trackers/xa/xa_symbols b/src/gallium/state_trackers/xa/xa_symbols index 62ae333eeb5..7fa6c94cfe8 100644 --- a/src/gallium/state_trackers/xa/xa_symbols +++ b/src/gallium/state_trackers/xa/xa_symbols @@ -8,9 +8,6 @@ xa_surface_dma xa_surface_map xa_surface_unmap xa_surface_format -xa_copy_prepare -xa_copy -xa_copy_done xa_surface_handle xa_context_default xa_context_create @@ -18,4 +15,15 @@ xa_context_destroy xa_fence_get xa_fence_wait xa_fence_destroy +xa_copy_prepare +xa_copy +xa_copy_done +xa_solid_prepare +xa_solid +xa_solid_done +xa_composite_allocation +xa_composite_is_accelerated +xa_composite_prepare +xa_composite_rect +xa_composite_done xa_yuv_planar_blit diff --git a/src/gallium/state_trackers/xa/xa_tracker.h b/src/gallium/state_trackers/xa/xa_tracker.h index ed81070a403..8c9dd5e167d 100644 --- a/src/gallium/state_trackers/xa/xa_tracker.h +++ b/src/gallium/state_trackers/xa/xa_tracker.h @@ -37,7 +37,7 @@ #include #define XA_TRACKER_VERSION_MAJOR 0 -#define XA_TRACKER_VERSION_MINOR 2 +#define XA_TRACKER_VERSION_MINOR 3 #define XA_TRACKER_VERSION_PATCH 0 #define XA_FLAG_SHARED (1 << 0) diff --git a/src/gallium/targets/xa-vmwgfx/Makefile b/src/gallium/targets/xa-vmwgfx/Makefile index 7d46627db44..cfd32797202 100644 --- a/src/gallium/targets/xa-vmwgfx/Makefile +++ b/src/gallium/targets/xa-vmwgfx/Makefile @@ -4,7 +4,7 @@ include $(TOP)/configs/current ##### MACROS ##### XA_MAJOR = 0 -XA_MINOR = 2 +XA_MINOR = 3 XA_TINY = 0 XA_CFLAGS = -g -fPIC @@ -76,6 +76,7 @@ install: xatracker.pc $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig $(INSTALL) -m 644 $(TOP)/src/gallium/state_trackers/xa/xa_tracker.h $(DESTDIR)$(INSTALL_INC_DIR) $(INSTALL) -m 644 $(TOP)/src/gallium/state_trackers/xa/xa_context.h $(DESTDIR)$(INSTALL_INC_DIR) + $(INSTALL) -m 644 $(TOP)/src/gallium/state_trackers/xa/xa_composite.h $(DESTDIR)$(INSTALL_INC_DIR) $(MINSTALL) -m 755 $(TOP)/$(LIB_DIR)/gallium/$(XA_LIB_GLOB) $(DESTDIR)$(INSTALL_LIB_DIR) $(INSTALL) -m 644 xatracker.pc $(DESTDIR)$(INSTALL_LIB_DIR)/pkgconfig -- 2.30.2