diff options
author | Thomas Hellstrom <[email protected]> | 2011-07-04 10:21:35 +0200 |
---|---|---|
committer | Thomas Hellstrom <[email protected]> | 2011-07-04 10:21:35 +0200 |
commit | 424b1210d951c206e7c2fb8f2778acbd384eb247 (patch) | |
tree | 964884074e08de8072ef535ff5f2ee5f2c416b61 /src/gallium/state_trackers | |
parent | a221807dc5d69598afd1d0e0a4e715fb82a9f30d (diff) | |
parent | f81ac1840a25ad39a9d7e46e4951e5eb45a05971 (diff) |
Merge branch 'xa_branch'
Conflicts:
configure.ac
Signed-off-by: Thomas Hellstrom <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r-- | src/gallium/state_trackers/xa/Makefile | 67 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/README | 72 | ||||
-rwxr-xr-x | src/gallium/state_trackers/xa/xa-indent | 3 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_composite.c | 499 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_composite.h | 140 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_context.c | 386 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_context.h | 86 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_priv.h | 241 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_renderer.c | 626 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_symbols | 30 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_tgsi.c | 651 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_tracker.c | 448 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_tracker.h | 178 | ||||
-rw-r--r-- | src/gallium/state_trackers/xa/xa_yuv.c | 179 |
14 files changed, 3606 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/xa/Makefile b/src/gallium/state_trackers/xa/Makefile new file mode 100644 index 00000000000..d95f9382630 --- /dev/null +++ b/src/gallium/state_trackers/xa/Makefile @@ -0,0 +1,67 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +##### MACROS ##### + +XA_MAJOR = 0 +XA_MINOR = 4 +XA_TINY = 0 +XA_CFLAGS = -g -fPIC -Wall + +XA_INCLUDES= -I$(TOP)/src/gallium/ \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/winsys \ + -I$(TOP)/src/gallium/drivers + +XA_LIB = xatracker +XA_LIB_NAME = lib$(XA_LIB).o +XA_LIB_DEPS = + +COMMON_GALLIUM_SOURCES= + +SOURCES = \ + xa_tracker.c \ + xa_context.c \ + xa_renderer.c \ + xa_tgsi.c \ + xa_yuv.c \ + xa_composite.c +OBJECTS = $(SOURCES:.c=.o) + +##### RULES ##### + +.c.o: + $(CC) -c $(XA_CFLAGS) $(XA_INCLUDES) $< + + +##### TARGETS ##### + +default: $(XA_LIB_NAME) + + +# Make the library +$(XA_LIB_NAME): depend $(OBJECTS) + $(CC) -r -nostdlib -o $(XA_LIB_NAME) $(OBJECTS) + +install: FORCE + +clean: + -rm -f *.o *~ + -rm -f *.lo + -rm -f *.la + -rm -f *.pc + -rm -rf .libs + -rm -f depend depend.bak + + +depend: $(SOURCES) + @ echo "running $(MKDEP)" + @ rm -f depend + @ touch depend + @ $(MKDEP) $(MKDEP_OPTIONS) -I$(TOP)/include $(XA_INCLUDES) $(SOURCES) \ + > /dev/null + +-include depend + +FORCE: diff --git a/src/gallium/state_trackers/xa/README b/src/gallium/state_trackers/xa/README new file mode 100644 index 00000000000..1f08861588c --- /dev/null +++ b/src/gallium/state_trackers/xa/README @@ -0,0 +1,72 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +The XA state tracker is intended as a versioned interface to gallium for +xorg driver writers. Initially it's mostly based on Zack Rusin's +composite / video work for the Xorg state tracker. + +The motivation behind this state tracker is that the Xorg state tracker has +a number of interfaces to work with: + +1) The Xorg sdk (versioned) +2) Gallium3D (not versioned) +3) KMS modesetting (versioned) +4) Driver-private (hopefully versioned) + +Since Gallium3D is not versioned, the Xorg state tracker needs to be compiled +with Gallium, but it's really beneficial to be able to compile xorg drivers +standalone. + +Therefore the xa state tracker is intended to supply the following +functionality: + +1) Versioning. +2) Surface functionality (creation and copying for a basic dri2 implementation) +3) YUV blits for textured Xv. +4) Solid fills without ROP functionality. +5) Copies with format conversion and - reinterpretation but without ROP +6) Xrender- type compositing for general acceleration. + + +The first user will be the vmwgfx xorg driver. When there are more users, +we need to be able to load the appropriate gallium pipe driver, and we +should investigate sharing the loadig mechanism with the EGL state tracker. + +IMPORTANT: +Version compatibilities: +While this library remains OUTSIDE any mesa release branch, +and the major version number is still 0. Any minor bump should be viewed as +an incompatibility event, and any user of this library should test for that +and refuse to use the library if minor versions differ. +As soon as the library enters a mesa release branch, if not earlier, major +will be bumped to 1, and normal incompatibility rules (major bump) +will be followed. +It is allowed to add function interfaces while only bumping minor. Any +user that uses these function interfaces must therefore use lazy symbol +lookups and test minor for compatibility before using such a function. diff --git a/src/gallium/state_trackers/xa/xa-indent b/src/gallium/state_trackers/xa/xa-indent new file mode 100755 index 00000000000..1972e53226f --- /dev/null +++ b/src/gallium/state_trackers/xa/xa-indent @@ -0,0 +1,3 @@ +# +indent --linux-style -i4 -ip4 -bad -bap -psl $* + 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..5389af6f363 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_composite.c @@ -0,0 +1,499 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#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(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) + 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; +} + + +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_check_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 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)) { + 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; +} + +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; + + if (!src) + return 0; + + 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; + } + + 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_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; + + 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); + ctx->comp = comp; + } + + 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 && 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..d16ef89ebd8 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_composite.h @@ -0,0 +1,140 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#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; + int no_solid; +}; + +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); + +/* + * This function checks most things except the format of the hardware + * surfaces, since they are generally not available at the time this + * function is called. Returns usual XA error codes. + */ +extern int +xa_composite_check_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 new file mode 100644 index 00000000000..3cc25ed2071 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_context.c @@ -0,0 +1,386 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ +#include "xa_context.h" +#include "xa_priv.h" +#include "cso_cache/cso_context.h" +#include "util/u_inlines.h" +#include "util/u_rect.h" +#include "util/u_surface.h" +#include "pipe/p_context.h" + + +struct xa_context * +xa_context_default(struct xa_tracker *xa) +{ + return xa->default_ctx; +} + +struct xa_context * +xa_context_create(struct xa_tracker *xa) +{ + struct xa_context *ctx = calloc(1, sizeof(*ctx)); + + ctx->xa = xa; + ctx->pipe = xa->screen->context_create(xa->screen, NULL); + ctx->cso = cso_create_context(ctx->pipe); + ctx->shaders = xa_shaders_create(ctx); + renderer_init_state(ctx); + + return ctx; +} + +void +xa_context_destroy(struct xa_context *r) +{ + struct pipe_resource **vsbuf = &r->vs_const_buffer; + struct pipe_resource **fsbuf = &r->fs_const_buffer; + + if (*vsbuf) + pipe_resource_reference(vsbuf, NULL); + + if (*fsbuf) + pipe_resource_reference(fsbuf, NULL); + + if (r->shaders) { + xa_shaders_destroy(r->shaders); + r->shaders = NULL; + } + + if (r->cso) { + cso_release_all(r->cso); + cso_destroy_context(r->cso); + r->cso = NULL; + } +} + +int +xa_surface_dma(struct xa_context *ctx, + struct xa_surface *srf, + void *data, + unsigned int pitch, + int to_surface, struct xa_box *boxes, unsigned int num_boxes) +{ + struct pipe_transfer *transfer; + void *map; + int w, h, i; + enum pipe_transfer_usage transfer_direction; + struct pipe_context *pipe = ctx->pipe; + + transfer_direction = (to_surface ? PIPE_TRANSFER_WRITE : + PIPE_TRANSFER_READ); + + for (i = 0; i < num_boxes; ++i, ++boxes) { + w = boxes->x2 - boxes->x1; + h = boxes->y2 - boxes->y1; + + transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, + transfer_direction, boxes->x1, boxes->y1, + w, h); + if (!transfer) + return -XA_ERR_NORES; + + map = pipe_transfer_map(ctx->pipe, transfer); + if (!map) + goto out_no_map; + + if (to_surface) { + util_copy_rect(map, srf->tex->format, transfer->stride, + 0, 0, w, h, data, pitch, boxes->x1, boxes->y1); + } else { + util_copy_rect(data, srf->tex->format, pitch, + boxes->x1, boxes->y1, w, h, map, transfer->stride, 0, + 0); + } + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); + if (to_surface) + pipe->flush(pipe, &ctx->last_fence); + } + return XA_ERR_NONE; + out_no_map: + pipe->transfer_destroy(pipe, transfer); + return -XA_ERR_NORES; +} + +void * +xa_surface_map(struct xa_context *ctx, + struct xa_surface *srf, unsigned int usage) +{ + void *map; + unsigned int transfer_direction = 0; + struct pipe_context *pipe = ctx->pipe; + + if (srf->transfer) + return NULL; + + if (usage & XA_MAP_READ) + transfer_direction = PIPE_TRANSFER_READ; + if (usage & XA_MAP_WRITE) + transfer_direction = PIPE_TRANSFER_WRITE; + + if (!transfer_direction) + return NULL; + + srf->transfer = pipe_get_transfer(pipe, srf->tex, 0, 0, + transfer_direction, 0, 0, + srf->tex->width0, srf->tex->height0); + if (!srf->transfer) + return NULL; + + map = pipe_transfer_map(pipe, srf->transfer); + if (!map) + pipe->transfer_destroy(pipe, srf->transfer); + + srf->mapping_pipe = pipe; + return map; +} + +void +xa_surface_unmap(struct xa_surface *srf) +{ + if (srf->transfer) { + struct pipe_context *pipe = srf->mapping_pipe; + + pipe->transfer_unmap(pipe, srf->transfer); + pipe->transfer_destroy(pipe, srf->transfer); + srf->transfer = NULL; + } +} + +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) +{ + if (src == dst || dst->srf != NULL) + return -XA_ERR_INVAL; + + if (src->tex->format != dst->tex->format) { + 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 + ctx->simple_copy = 1; + + ctx->src = src; + ctx->dst = dst; + + return 0; +} + +void +xa_copy(struct xa_context *ctx, + int dx, int dy, int sx, int sy, int width, int height) +{ + struct pipe_box src_box; + + if (ctx->simple_copy) { + u_box_2d(sx, sy, width, height, &src_box); + ctx->pipe->resource_copy_region(ctx->pipe, + ctx->dst->tex, 0, dx, dy, 0, + ctx->src->tex, + 0, &src_box); + } else + renderer_copy(ctx, dx, dy, sx, sy, width, height, + (float) width, (float) height); +} + +void +xa_copy_done(struct xa_context *ctx) +{ + if (!ctx->simple_copy) { + renderer_draw_flush(ctx); + ctx->pipe->flush(ctx->pipe, &ctx->last_fence); + 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) +{ + struct xa_fence *fence = malloc(sizeof(*fence)); + struct pipe_screen *screen = ctx->xa->screen; + + if (!fence) + return NULL; + + fence->xa = ctx->xa; + + if (ctx->last_fence == NULL) + fence->pipe_fence = NULL; + else + screen->fence_reference(screen, &fence->pipe_fence, ctx->last_fence); + + return fence; +} + +int +xa_fence_wait(struct xa_fence *fence, uint64_t timeout) +{ + if (!fence) + return XA_ERR_NONE; + + if (fence->pipe_fence) { + struct pipe_screen *screen = fence->xa->screen; + boolean timed_out; + + timed_out = !screen->fence_finish(screen, fence->pipe_fence, timeout); + if (timed_out) + return -XA_ERR_BUSY; + + screen->fence_reference(screen, &fence->pipe_fence, NULL); + } + return XA_ERR_NONE; +} + +void +xa_fence_destroy(struct xa_fence *fence) +{ + if (!fence) + return; + + if (fence->pipe_fence) { + struct pipe_screen *screen = fence->xa->screen; + + screen->fence_reference(screen, &fence->pipe_fence, NULL); + } + + free(fence); +} diff --git a/src/gallium/state_trackers/xa/xa_context.h b/src/gallium/state_trackers/xa/xa_context.h new file mode 100644 index 00000000000..ea2b923a5a1 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_context.h @@ -0,0 +1,86 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#ifndef _XA_CONTEXT_H_ +#define _XA_CONTEXT_H_ +#include "xa_tracker.h" +#include <stdint.h> + +struct xa_context; + +extern struct xa_context *xa_context_default(struct xa_tracker *xa); + +extern struct xa_context *xa_context_create(struct xa_tracker *xa); + +extern void xa_context_destroy(struct xa_context *r); + +extern int xa_yuv_planar_blit(struct xa_context *r, + int src_x, + int src_y, + int src_w, + int src_h, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + struct xa_box *box, + unsigned int num_boxes, + const float conversion_matrix[], + struct xa_surface *dst, struct xa_surface *yuv[]); + +extern int xa_copy_prepare(struct xa_context *ctx, + struct xa_surface *dst, struct xa_surface *src); + +extern void xa_copy(struct xa_context *ctx, + int dx, int dy, int sx, int sy, int width, int height); + +extern void xa_copy_done(struct xa_context *ctx); + +extern int xa_surface_dma(struct xa_context *ctx, + struct xa_surface *srf, + void *data, + unsigned int byte_pitch, + 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); + +extern void xa_fence_destroy(struct xa_fence *fence); +#endif diff --git a/src/gallium/state_trackers/xa/xa_priv.h b/src/gallium/state_trackers/xa/xa_priv.h new file mode 100644 index 00000000000..94627e1e9d0 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_priv.h @@ -0,0 +1,241 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#ifndef _XA_PRIV_H_ +#define _XA_PRIV_H_ + +#include "xa_tracker.h" +#include "xa_context.h" +#include "xa_composite.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +#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; + struct xa_tracker *xa; +}; + +struct xa_format_descriptor { + enum pipe_format format; + enum xa_formats xa_format; +}; + +struct xa_surface { + struct pipe_resource template; + struct xa_tracker *xa; + struct pipe_resource *tex; + struct pipe_surface *srf; + struct pipe_sampler_view *view; + unsigned int flags; + struct xa_format_descriptor fdesc; + struct pipe_transfer *transfer; + struct pipe_context *mapping_pipe; +}; + +struct xa_tracker { + enum xa_formats *supported_formats; + unsigned int format_map[XA_LAST_SURFACE_TYPE][2]; + int d_depth_bits_last; + int ds_depth_bits_last; + struct pipe_screen *screen; + struct xa_context *default_ctx; +}; + +struct xa_context { + struct xa_tracker *xa; + struct pipe_context *pipe; + + struct cso_context *cso; + struct xa_shaders *shaders; + + struct pipe_resource *vs_const_buffer; + struct pipe_resource *fs_const_buffer; + + float buffer[XA_VB_SIZE]; + unsigned int buffer_size; + struct pipe_vertex_element velems[3]; + + /* number of attributes per vertex for the current + * draw operation */ + unsigned int attrs_per_vertex; + + unsigned int fb_width; + unsigned int fb_height; + + struct pipe_fence_handle *last_fence; + 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 { + 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) +}; + +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_FILL = (FS_SOLID_FILL | FS_LINGRAD_FILL | FS_RADGRAD_FILL), + FS_COMPONENT_ALPHA = (FS_CA_FULL | FS_CA_SRCALPHA) +}; + +struct xa_shader { + void *fs; + void *vs; +}; + +struct xa_shaders; + +/* + * Inline utilities + */ + +static INLINE int +xa_min(int a, int b) +{ + return ((a <= b) ? a : b); +} + +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 + */ + +extern struct xa_shaders *xa_shaders_create(struct xa_context *); + +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 + */ +void renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, + int param_bytes); + +void renderer_draw_yuv(struct xa_context *r, + float src_x, + float src_y, + float src_w, + float src_h, + int dst_x, + int dst_y, int dst_w, int dst_h, + struct xa_surface *srf[]); + +void renderer_bind_destination(struct xa_context *r, + struct pipe_surface *surface, int width, + int height); + +void renderer_init_state(struct xa_context *r); +void renderer_copy_prepare(struct xa_context *r, + struct pipe_surface *dst_surface, + struct pipe_resource *src_texture); +void renderer_copy(struct xa_context *r, int dx, + int dy, + int sx, + int sy, + int width, int height, float src_width, float src_height); + +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 new file mode 100644 index 00000000000..559b2699da6 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_renderer.c @@ -0,0 +1,626 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + */ + +#include "xa_context.h" +#include "xa_priv.h" +#include <math.h> +#include "cso_cache/cso_context.h" +#include "util/u_inlines.h" +#include "util/u_sampler.h" +#include "util/u_draw_quad.h" + +#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y))) +#define floatIsZero(x) (floatsEqual((x) + 1, 1)) + +#define NUM_COMPONENTS 4 + +void + + +renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, int param_bytes); + +static INLINE boolean +is_affine(float *matrix) +{ + return floatIsZero(matrix[2]) && floatIsZero(matrix[5]) + && floatsEqual(matrix[8], 1); +} + +static INLINE void +map_point(float *mat, float x, float y, float *out_x, float *out_y) +{ + if (!mat) { + *out_x = x; + *out_y = y; + return; + } + + *out_x = mat[0] * x + mat[3] * y + mat[6]; + *out_y = mat[1] * x + mat[4] * y + mat[7]; + if (!is_affine(mat)) { + float w = 1 / (mat[2] * x + mat[5] * y + mat[8]); + + *out_x *= w; + *out_y *= w; + } +} + +static INLINE struct pipe_resource * +renderer_buffer_create(struct xa_context *r) +{ + struct pipe_resource *buf = pipe_user_buffer_create(r->pipe->screen, + r->buffer, + sizeof(float) * + r->buffer_size, + PIPE_BIND_VERTEX_BUFFER); + + r->buffer_size = 0; + + return buf; +} + +static INLINE void +renderer_draw(struct xa_context *r) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_resource *buf = 0; + int num_verts = r->buffer_size / (r->attrs_per_vertex * NUM_COMPONENTS); + + if (!r->buffer_size) + return; + + buf = renderer_buffer_create(r); + + if (buf) { + cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems); + + util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, num_verts, /* verts */ + r->attrs_per_vertex); /* attribs/vert */ + + pipe_resource_reference(&buf, NULL); + } +} + +static INLINE void +renderer_draw_conditional(struct xa_context *r, int next_batch) +{ + if (r->buffer_size + next_batch >= XA_VB_SIZE || + (next_batch == 0 && r->buffer_size)) { + renderer_draw(r); + } +} + +void +renderer_init_state(struct xa_context *r) +{ + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_rasterizer_state raster; + unsigned i; + + /* set common initial clip state */ + memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); + cso_set_depth_stencil_alpha(r->cso, &dsa); + + /* XXX: move to renderer_init_state? */ + memset(&raster, 0, sizeof(struct pipe_rasterizer_state)); + raster.gl_rasterization_rules = 1; + cso_set_rasterizer(r->cso, &raster); + + /* vertex elements state */ + memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3); + for (i = 0; i < 3; i++) { + r->velems[i].src_offset = i * 4 * sizeof(float); + r->velems[i].instance_divisor = 0; + r->velems[i].vertex_buffer_index = 0; + r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } +} + +static INLINE void +add_vertex_color(struct xa_context *r, float x, float y, float color[4]) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + 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; +} + +static INLINE void +add_vertex_1tex(struct xa_context *r, float x, float y, float s, float t) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + vertex[4] = s; /*s */ + vertex[5] = t; /*t */ + vertex[6] = 0.f; /*r */ + vertex[7] = 1.f; /*q */ + + r->buffer_size += 8; +} + +static INLINE void +add_vertex_2tex(struct xa_context *r, + float x, float y, float s0, float t0, float s1, float t1) +{ + float *vertex = r->buffer + r->buffer_size; + + vertex[0] = x; + vertex[1] = y; + vertex[2] = 0.f; /*z */ + vertex[3] = 1.f; /*w */ + + vertex[4] = s0; /*s */ + vertex[5] = t0; /*t */ + vertex[6] = 0.f; /*r */ + vertex[7] = 1.f; /*q */ + + vertex[8] = s1; /*s */ + vertex[9] = t1; /*t */ + vertex[10] = 0.f; /*r */ + vertex[11] = 1.f; /*q */ + + 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, + float srcY, + float srcW, + float srcH, + float dstX, + float dstY, + float dstW, float dstH, struct xa_surface *srf[]) +{ + float s0, t0, s1, t1; + float spt0[2], spt1[2]; + struct pipe_resource *tex; + + spt0[0] = srcX; + spt0[1] = srcY; + spt1[0] = srcX + srcW; + spt1[1] = srcY + srcH; + + tex = srf[0]->tex; + s0 = spt0[0] / tex->width0; + t0 = spt0[1] / tex->height0; + s1 = spt1[0] / tex->width0; + t1 = spt1[1] / tex->height0; + + /* 1st vertex */ + add_vertex_1tex(r, dstX, dstY, s0, t0); + /* 2nd vertex */ + add_vertex_1tex(r, dstX + dstW, dstY, s1, t0); + /* 3rd vertex */ + add_vertex_1tex(r, dstX + dstW, dstY + dstH, s1, t1); + /* 4th vertex */ + add_vertex_1tex(r, dstX, dstY + dstH, s0, t1); + + return renderer_buffer_create(r); +} + +/* Set up framebuffer, viewport and vertex shader constant buffer + * state for a particular destinaton surface. In all our rendering, + * these concepts are linked. + */ +void +renderer_bind_destination(struct xa_context *r, + struct pipe_surface *surface, int width, int height) +{ + + struct pipe_framebuffer_state fb; + struct pipe_viewport_state viewport; + + /* Framebuffer uses actual surface width/height + */ + memset(&fb, 0, sizeof fb); + fb.width = surface->width; + fb.height = surface->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = surface; + fb.zsbuf = 0; + + /* Viewport just touches the bit we're interested in: + */ + viewport.scale[0] = width / 2.f; + viewport.scale[1] = height / 2.f; + viewport.scale[2] = 1.0; + viewport.scale[3] = 1.0; + viewport.translate[0] = width / 2.f; + viewport.translate[1] = height / 2.f; + viewport.translate[2] = 0.0; + viewport.translate[3] = 0.0; + + /* Constant buffer set up to match viewport dimensions: + */ + if (r->fb_width != width || r->fb_height != height) { + float vs_consts[8] = { + 2.f / width, 2.f / height, 1, 1, + -1, -1, 0, 0 + }; + + r->fb_width = width; + r->fb_height = height; + + renderer_set_constants(r, PIPE_SHADER_VERTEX, + vs_consts, sizeof vs_consts); + } + + cso_set_framebuffer(r->cso, &fb); + cso_set_viewport(r->cso, &viewport); +} + +void +renderer_set_constants(struct xa_context *r, + int shader_type, const float *params, int param_bytes) +{ + struct pipe_resource **cbuf = + (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer : + &r->fs_const_buffer; + + pipe_resource_reference(cbuf, NULL); + *cbuf = pipe_buffer_create(r->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC, + param_bytes); + + if (*cbuf) { + pipe_buffer_write(r->pipe, *cbuf, 0, param_bytes, params); + } + r->pipe->set_constant_buffer(r->pipe, shader_type, 0, *cbuf); +} + +void +renderer_copy_prepare(struct xa_context *r, + struct pipe_surface *dst_surface, + struct pipe_resource *src_texture) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_screen *screen = pipe->screen; + struct xa_shader shader; + + assert(screen->is_format_supported(screen, dst_surface->format, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET)); + (void)screen; + + /* set misc state we care about */ + { + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(blend)); + 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; + blend.rt[0].colormask = PIPE_MASK_RGBA; + cso_set_blend(r->cso, &blend); + } + + /* sampler */ + { + struct pipe_sampler_state sampler; + + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.normalized_coords = 1; + cso_single_sampler(r->cso, 0, &sampler); + cso_single_sampler_done(r->cso); + } + + renderer_bind_destination(r, dst_surface, + dst_surface->width, dst_surface->height); + + /* texture/sampler view */ + { + struct pipe_sampler_view templ; + struct pipe_sampler_view *src_view; + + u_sampler_view_default_template(&templ, + src_texture, src_texture->format); + src_view = pipe->create_sampler_view(pipe, src_texture, &templ); + cso_set_fragment_sampler_views(r->cso, 1, &src_view); + pipe_sampler_view_reference(&src_view, NULL); + } + + /* shaders */ + shader = xa_shaders_get(r->shaders, VS_COMPOSITE, FS_COMPOSITE); + cso_set_vertex_shader_handle(r->cso, shader.vs); + cso_set_fragment_shader_handle(r->cso, shader.fs); + + r->buffer_size = 0; + r->attrs_per_vertex = 2; +} + +void +renderer_copy(struct xa_context *r, + int dx, + int dy, + int sx, + int sy, + int width, int height, float src_width, float src_height) +{ + float s0, t0, s1, t1; + float x0, y0, x1, y1; + + /* XXX: could put the texcoord scaling calculation into the vertex + * shader. + */ + s0 = sx / src_width; + s1 = (sx + width) / src_width; + t0 = sy / src_height; + t1 = (sy + height) / src_height; + + x0 = dx; + x1 = dx + width; + y0 = dy; + y1 = dy + height; + + /* draw quad */ + renderer_draw_conditional(r, 4 * 8); + add_vertex_1tex(r, x0, y0, s0, t0); + add_vertex_1tex(r, x1, y0, s1, t0); + add_vertex_1tex(r, x1, y1, s1, t1); + add_vertex_1tex(r, x0, y1, s0, t1); +} + +void +renderer_draw_yuv(struct xa_context *r, + float src_x, + float src_y, + float src_w, + float src_h, + int dst_x, + int dst_y, int dst_w, int dst_h, struct xa_surface *srf[]) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_resource *buf = 0; + + buf = setup_vertex_data_yuv(r, + src_x, src_y, src_w, src_h, dst_x, dst_y, dst_w, + dst_h, srf); + + if (buf) { + const int num_attribs = 2; /*pos + tex coord */ + + cso_set_vertex_elements(r->cso, num_attribs, r->velems); + + util_draw_vertex_buffer(pipe, r->cso, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ + num_attribs); /* attribs/vert */ + + pipe_resource_reference(&buf, NULL); + } +} + +void +renderer_begin_solid(struct xa_context *r) +{ + r->buffer_size = 0; + r->attrs_per_vertex = 2; +} + +void +renderer_solid(struct xa_context *r, + int x0, int y0, int x1, int y1, float *color) +{ + /* + * 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); + + /* 1st vertex */ + add_vertex_color(r, x0, y0, color); + /* 2nd vertex */ + add_vertex_color(r, x1, y0, color); + /* 3rd vertex */ + add_vertex_color(r, x1, y1, color); + /* 4th vertex */ + add_vertex_color(r, x0, y1, color); +} + +void +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 new file mode 100644 index 00000000000..6da701f9702 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_symbols @@ -0,0 +1,30 @@ +xa_tracker_version +xa_tracker_create +xa_tracker_destroy +xa_surface_create +xa_surface_destroy +xa_surface_redefine +xa_surface_dma +xa_surface_map +xa_surface_unmap +xa_surface_format +xa_surface_handle +xa_format_check_supported +xa_context_default +xa_context_create +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_check_accelerated +xa_composite_prepare +xa_composite_rect +xa_composite_done +xa_yuv_planar_blit diff --git a/src/gallium/state_trackers/xa/xa_tgsi.c b/src/gallium/state_trackers/xa/xa_tgsi.c new file mode 100644 index 00000000000..fb6ffefd636 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_tgsi.c @@ -0,0 +1,651 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + */ +#include "xa_priv.h" + +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" + +#include "util/u_memory.h" + +#include "tgsi/tgsi_ureg.h" + +#include "cso_cache/cso_context.h" +#include "cso_cache/cso_hash.h" + +/* Vertex shader: + * IN[0] = vertex pos + * IN[1] = src tex coord | solid fill color + * IN[2] = mask tex coord + * IN[3] = dst tex coord + * CONST[0] = (2/dst_width, 2/dst_height, 1, 1) + * CONST[1] = (-1, -1, 0, 0) + * + * OUT[0] = vertex pos + * OUT[1] = src tex coord | solid fill color + * 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) + * + * OUT[0] = color + */ + +static void +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, */ + }; + int i, k; + + debug_printf("%s: ", __func__); + + for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) { + if (fs_traits & k) + debug_printf("%s, ", strings[i]); + } + + debug_printf("\n"); +} + +struct xa_shaders { + struct xa_context *r; + + struct cso_hash *vs_hash; + struct cso_hash *fs_hash; +}; + +static INLINE void +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) +{ + 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)); + } +} + +static struct ureg_src +vs_normalize_coords(struct ureg_program *ureg, + struct ureg_src coords, + struct ureg_src const0, struct ureg_src const1) +{ + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + struct ureg_src ret; + + ureg_MAD(ureg, tmp, coords, const0, const1); + ret = ureg_src(tmp); + ureg_release_temporary(ureg, tmp); + 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_SUB(ureg, temp2, ureg_src(temp3), ureg_src(temp0)); + ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2))); + ureg_RCP(ureg, temp2, ureg_src(temp2)); + ureg_SUB(ureg, temp1, ureg_src(temp2), 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) +{ + struct ureg_program *ureg; + 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; + unsigned input_slot = 0; + + ureg = ureg_create(TGSI_PROCESSOR_VERTEX); + if (ureg == NULL) + return 0; + + const0 = ureg_DECL_constant(ureg, 0); + 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); + ureg_MOV(ureg, dst, src); + + if (is_yuv) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); + ureg_MOV(ureg, dst, src); + } + + 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_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); + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +static void * +create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg) +{ + struct ureg_src y_sampler, u_sampler, v_sampler; + struct ureg_src pos; + struct ureg_src matrow0, matrow1, matrow2; + struct ureg_dst y, u, v, rgb; + struct ureg_dst out = ureg_DECL_output(ureg, + TGSI_SEMANTIC_COLOR, + 0); + + pos = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_PERSPECTIVE); + + rgb = ureg_DECL_temporary(ureg); + y = ureg_DECL_temporary(ureg); + u = ureg_DECL_temporary(ureg); + v = ureg_DECL_temporary(ureg); + + y_sampler = ureg_DECL_sampler(ureg, 0); + u_sampler = ureg_DECL_sampler(ureg, 1); + v_sampler = ureg_DECL_sampler(ureg, 2); + + matrow0 = ureg_DECL_constant(ureg, 0); + matrow1 = ureg_DECL_constant(ureg, 1); + matrow2 = ureg_DECL_constant(ureg, 2); + + ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler); + ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler); + ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler); + + ureg_SUB(ureg, u, ureg_src(u), ureg_scalar(matrow0, TGSI_SWIZZLE_W)); + ureg_SUB(ureg, v, ureg_src(v), ureg_scalar(matrow0, TGSI_SWIZZLE_W)); + + ureg_MUL(ureg, rgb, ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb)); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb)); + + /* rgb.a = 1; */ + ureg_MOV(ureg, ureg_writemask(rgb, TGSI_WRITEMASK_W), + ureg_scalar(matrow0, TGSI_SWIZZLE_X)); + + ureg_MOV(ureg, out, ureg_src(rgb)); + + ureg_release_temporary(ureg, rgb); + ureg_release_temporary(ureg, y); + ureg_release_temporary(ureg, u); + ureg_release_temporary(ureg, v); + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +static INLINE void +xrender_tex(struct ureg_program *ureg, + struct ureg_dst dst, + struct ureg_src coords, + struct ureg_src sampler, + struct ureg_src imm0, + boolean repeat_none, boolean swizzle, boolean set_alpha) +{ + if (repeat_none) { + struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); + struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); + + ureg_SGT(ureg, tmp1, ureg_swizzle(coords, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + 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_W)); + ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); + ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); + ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); + if (swizzle) + ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(tmp1, TGSI_WRITEMASK_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); + } else { + if (swizzle) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + + ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); + ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + ureg_release_temporary(ureg, tmp); + } else { + ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); + } + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); + } +} + +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; + unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; + unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; + unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; + 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; + +#if 0 + print_fs_traits(fs_traits); +#else + (void)print_fs_traits; +#endif + + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + 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; + + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + + if (src_repeat_none || mask_repeat_none || + 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); + 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); + 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); + dst_pos = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_POSITION, 2, + TGSI_INTERPOLATE_PERSPECTIVE); +#endif + + if (is_composite) { + if (has_mask || src_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) + 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) + 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), + ureg_scalar(imm0, TGSI_SWIZZLE_X)); + if (!has_mask) + ureg_MOV(ureg, out, ureg_src(src)); + } + + 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 */ + src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), + comp_alpha_mask, mask_luminance); + ureg_release_temporary(ureg, mask); + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + +struct xa_shaders * +xa_shaders_create(struct xa_context *r) +{ + struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders); + + sc->r = r; + sc->vs_hash = cso_hash_create(); + sc->fs_hash = cso_hash_create(); + + return sc; +} + +static void +cache_destroy(struct cso_context *cso, + struct cso_hash *hash, unsigned processor) +{ + struct cso_hash_iter iter = cso_hash_first_node(hash); + + while (!cso_hash_iter_is_null(iter)) { + void *shader = (void *)cso_hash_iter_data(iter); + + if (processor == PIPE_SHADER_FRAGMENT) { + cso_delete_fragment_shader(cso, shader); + } else if (processor == PIPE_SHADER_VERTEX) { + cso_delete_vertex_shader(cso, shader); + } + iter = cso_hash_erase(hash, iter); + } + cso_hash_delete(hash); +} + +void +xa_shaders_destroy(struct xa_shaders *sc) +{ + cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX); + cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT); + + FREE(sc); +} + +static INLINE void * +shader_from_cache(struct pipe_context *pipe, + unsigned type, struct cso_hash *hash, unsigned key) +{ + void *shader = 0; + + struct cso_hash_iter iter = cso_hash_find(hash, key); + + if (cso_hash_iter_is_null(iter)) { + if (type == PIPE_SHADER_VERTEX) + shader = create_vs(pipe, key); + else + shader = create_fs(pipe, key); + cso_hash_insert(hash, key, shader); + } else + shader = (void *)cso_hash_iter_data(iter); + + return shader; +} + +struct xa_shader +xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits) +{ + struct xa_shader shader = { NULL, NULL }; + void *vs, *fs; + + vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, + sc->vs_hash, vs_traits); + fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, + sc->fs_hash, fs_traits); + + debug_assert(vs && fs); + if (!vs || !fs) + return shader; + + shader.vs = vs; + shader.fs = fs; + + return shader; +} diff --git a/src/gallium/state_trackers/xa/xa_tracker.c b/src/gallium/state_trackers/xa/xa_tracker.c new file mode 100644 index 00000000000..50922d38378 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_tracker.c @@ -0,0 +1,448 @@ +/********************************************************** + * 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: + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#include "xa_tracker.h" +#include "xa_priv.h" +#include "pipe/p_state.h" +#include "pipe/p_format.h" +#include "state_tracker/drm_driver.h" +#include "util/u_inlines.h" + +/* + * format_map [xa_surface_type][first..last in list]. + * Needs to be updated when enum xa_formats is updated. + */ + +static const enum xa_formats preferred_a[] = { xa_format_a8 }; + +static const enum xa_formats preferred_argb[] = + { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5, + xa_format_x1r5g5b5 +}; +static const enum xa_formats preferred_z[] = + { xa_format_z32, xa_format_z24, xa_format_z16 }; +static const enum xa_formats preferred_sz[] = + { xa_format_x8z24, xa_format_s8z24 }; +static const enum xa_formats preferred_zs[] = + { xa_format_z24x8, xa_format_z24s8 }; +static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 }; + +static const enum xa_formats *preferred[] = + { NULL, preferred_a, preferred_argb, NULL, NULL, + preferred_z, preferred_zs, preferred_sz, preferred_yuv +}; + +static const unsigned int num_preferred[] = { 0, + sizeof(preferred_a) / sizeof(enum xa_formats), + sizeof(preferred_argb) / sizeof(enum xa_formats), + 0, + 0, + sizeof(preferred_z) / sizeof(enum xa_formats), + sizeof(preferred_zs) / sizeof(enum xa_formats), + sizeof(preferred_sz) / sizeof(enum xa_formats), + sizeof(preferred_yuv) / sizeof(enum xa_formats) +}; + +static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_SAMPLER_VIEW, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_DEPTH_STENCIL, + PIPE_BIND_SAMPLER_VIEW +}; + +static struct xa_format_descriptor +xa_get_pipe_format(enum xa_formats xa_format) +{ + struct xa_format_descriptor fdesc; + + fdesc.xa_format = xa_format; + + switch (xa_format) { + case xa_format_a8r8g8b8: + fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case xa_format_x8r8g8b8: + fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case xa_format_r5g6b5: + fdesc.format = PIPE_FORMAT_B5G6R5_UNORM; + break; + case xa_format_x1r5g5b5: + fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM; + break; + case xa_format_a8: + fdesc.format = PIPE_FORMAT_L8_UNORM; + break; + case xa_format_z24: + fdesc.format = PIPE_FORMAT_Z24X8_UNORM; + break; + case xa_format_z16: + fdesc.format = PIPE_FORMAT_Z16_UNORM; + break; + case xa_format_z32: + fdesc.format = PIPE_FORMAT_Z32_UNORM; + break; + case xa_format_x8z24: + fdesc.format = PIPE_FORMAT_Z24X8_UNORM; + break; + case xa_format_z24x8: + fdesc.format = PIPE_FORMAT_X8Z24_UNORM; + break; + case xa_format_s8z24: + fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_USCALED; + break; + case xa_format_z24s8: + fdesc.format = PIPE_FORMAT_S8_USCALED_Z24_UNORM; + break; + case xa_format_yuv8: + fdesc.format = PIPE_FORMAT_L8_UNORM; + break; + default: + fdesc.xa_format = xa_format_unknown; + break; + } + return fdesc; +} + +struct xa_tracker * +xa_tracker_create(int drm_fd) +{ + struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker)); + enum xa_surface_type stype; + unsigned int num_formats; + + if (!xa) + return NULL; + + xa->screen = driver_descriptor.create_screen(drm_fd); + if (!xa->screen) + goto out_no_screen; + + xa->default_ctx = xa_context_create(xa); + if (!xa->default_ctx) + goto out_no_pipe; + + num_formats = 0; + for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) + num_formats += num_preferred[stype]; + + num_formats += 1; + xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats)); + if (!xa->supported_formats) + goto out_sf_alloc_fail; + + xa->supported_formats[0] = xa_format_unknown; + num_formats = 1; + memset(xa->format_map, 0, sizeof(xa->format_map)); + + for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) { + unsigned int bind = stype_bind[stype]; + enum xa_formats xa_format; + int i; + + for (i = 0; i < num_preferred[stype]; ++i) { + xa_format = preferred[stype][i]; + + struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format); + + if (xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, bind)) { + if (xa->format_map[stype][0] == 0) + xa->format_map[stype][0] = num_formats; + xa->format_map[stype][1] = num_formats; + xa->supported_formats[num_formats++] = xa_format; + } + } + } + return xa; + + out_sf_alloc_fail: + xa_context_destroy(xa->default_ctx); + out_no_pipe: + xa->screen->destroy(xa->screen); + out_no_screen: + free(xa); + return NULL; +} + +void +xa_tracker_destroy(struct xa_tracker *xa) +{ + free(xa->supported_formats); + xa_context_destroy(xa->default_ctx); + xa->screen->destroy(xa->screen); + free(xa); +} + +static int +xa_flags_compat(unsigned int old_flags, unsigned int new_flags) +{ + unsigned int flag_diff = (old_flags ^ new_flags); + + if (flag_diff == 0) + return 1; + + if (flag_diff & XA_FLAG_SHARED) + return 0; + /* + * Don't recreate if we're dropping the render target flag. + */ + if (flag_diff & XA_FLAG_RENDER_TARGET) + return ((new_flags & XA_FLAG_RENDER_TARGET) == 0); + + /* + * Always recreate for unknown / unimplemented flags. + */ + return 0; +} + +static struct xa_format_descriptor +xa_get_format_stype_depth(struct xa_tracker *xa, + enum xa_surface_type stype, unsigned int depth) +{ + unsigned int i; + struct xa_format_descriptor fdesc; + int found = 0; + + for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) { + fdesc = xa_get_pipe_format(xa->supported_formats[i]); + if (fdesc.xa_format != xa_format_unknown && + xa_format_depth(fdesc.xa_format) == depth) { + found = 1; + break; + } + } + + if (!found) + fdesc.xa_format = xa_format_unknown; + + return fdesc; +} + +int +xa_format_check_supported(struct xa_tracker *xa, + enum xa_formats xa_format, unsigned int flags) +{ + struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format); + unsigned int bind; + + if (fdesc.xa_format == xa_format_unknown) + return -XA_ERR_INVAL; + + bind = stype_bind[xa_format_type(fdesc.xa_format)]; + if (flags & XA_FLAG_SHARED) + bind |= PIPE_BIND_SHARED; + if (flags & XA_FLAG_RENDER_TARGET) + bind |= PIPE_BIND_RENDER_TARGET; + + if (!xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, bind)) + return -XA_ERR_INVAL; + + return XA_ERR_NONE; +} + +struct xa_surface * +xa_surface_create(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, unsigned int flags) +{ + struct pipe_resource *template; + struct xa_surface *srf; + struct xa_format_descriptor fdesc; + + if (xa_format == xa_format_unknown) + fdesc = xa_get_format_stype_depth(xa, stype, depth); + else + fdesc = xa_get_pipe_format(xa_format); + + if (fdesc.xa_format == xa_format_unknown) + return NULL; + + srf = calloc(1, sizeof(*srf)); + if (!srf) + return NULL; + + template = &srf->template; + template->format = fdesc.format; + template->target = PIPE_TEXTURE_2D; + template->width0 = width; + template->height0 = height; + template->depth0 = 1; + template->array_size = 1; + template->last_level = 0; + template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; + + if (flags & XA_FLAG_SHARED) + template->bind |= PIPE_BIND_SHARED; + if (flags & XA_FLAG_RENDER_TARGET) + template->bind |= PIPE_BIND_RENDER_TARGET; + + srf->tex = xa->screen->resource_create(xa->screen, template); + if (!srf->tex) + goto out_no_tex; + + srf->srf = NULL; + srf->xa = xa; + srf->flags = flags; + srf->fdesc = fdesc; + + return srf; + out_no_tex: + free(srf); + return NULL; +} + +int +xa_surface_redefine(struct xa_surface *srf, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats xa_format, + unsigned int new_flags, + int copy_contents) +{ + struct pipe_resource *template = &srf->template; + struct pipe_resource *texture; + struct pipe_box src_box; + struct xa_tracker *xa = srf->xa; + int save_width; + int save_height; + struct xa_format_descriptor fdesc; + + if (xa_format == xa_format_unknown) + fdesc = xa_get_format_stype_depth(xa, stype, depth); + else + fdesc = xa_get_pipe_format(xa_format); + + if (width == template->width0 && height == template->height0 && + template->format == fdesc.format && + xa_flags_compat(srf->flags, new_flags)) + return XA_ERR_NONE; + + template->bind = stype_bind[xa_format_type(fdesc.xa_format)]; + if (new_flags & XA_FLAG_SHARED) + template->bind |= PIPE_BIND_SHARED; + if (new_flags & XA_FLAG_RENDER_TARGET) + template->bind |= PIPE_BIND_RENDER_TARGET; + + if (copy_contents) { + if (!xa_format_type_is_color(fdesc.xa_format) || + xa_format_type(fdesc.xa_format) == xa_type_a) + return -XA_ERR_INVAL; + + if (!xa->screen->is_format_supported(xa->screen, fdesc.format, + PIPE_TEXTURE_2D, 0, + template->bind | + PIPE_BIND_RENDER_TARGET)) + return -XA_ERR_INVAL; + } + + save_width = template->width0; + save_height = template->height0; + + template->width0 = width; + template->height0 = height; + + texture = xa->screen->resource_create(xa->screen, template); + if (!texture) { + template->width0 = save_width; + template->height0 = save_height; + return -XA_ERR_NORES; + } + + pipe_surface_reference(&srf->srf, NULL); + + if (copy_contents) { + struct pipe_context *pipe = xa->default_ctx->pipe; + + u_box_origin_2d(xa_min(save_width, template->width0), + xa_min(save_height, template->height0), &src_box); + pipe->resource_copy_region(pipe, texture, + 0, 0, 0, 0, srf->tex, 0, &src_box); + pipe->flush(pipe, &xa->default_ctx->last_fence); + } + + pipe_resource_reference(&srf->tex, texture); + pipe_resource_reference(&texture, NULL); + srf->fdesc = fdesc; + srf->flags = new_flags; + + return XA_ERR_NONE; +} + +void +xa_surface_destroy(struct xa_surface *srf) +{ + pipe_surface_reference(&srf->srf, NULL); + pipe_resource_reference(&srf->tex, NULL); + free(srf); +} + +extern void +xa_tracker_version(int *major, int *minor, int *patch) +{ + *major = XA_TRACKER_VERSION_MAJOR; + *minor = XA_TRACKER_VERSION_MINOR; + *patch = XA_TRACKER_VERSION_PATCH; +} + +extern int +xa_surface_handle(struct xa_surface *srf, + uint32_t * handle, unsigned int *stride) +{ + struct winsys_handle whandle; + + struct pipe_screen *screen = srf->xa->screen; + boolean res; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + res = screen->resource_get_handle(screen, srf->tex, &whandle); + if (!res) + return -XA_ERR_INVAL; + + *handle = whandle.handle; + *stride = whandle.stride; + + return XA_ERR_NONE; +} + +enum xa_formats +xa_surface_format(const struct xa_surface *srf) +{ + return srf->fdesc.xa_format; +} diff --git a/src/gallium/state_trackers/xa/xa_tracker.h b/src/gallium/state_trackers/xa/xa_tracker.h new file mode 100644 index 00000000000..62f8a210fb6 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_tracker.h @@ -0,0 +1,178 @@ +/********************************************************** + * 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. + * + * The format encoding idea is partially borrowed from libpixman, but it is not + * considered a "substantial part of the software", so the pixman copyright + * is left out for simplicity, and acknowledgment is instead given in this way. + * + ********************************************************* + * Authors: + * Zack Rusin <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#ifndef _XA_TRACKER_H_ +#define _XA_TRACKER_H_ + +#include <stdint.h> + +#define XA_TRACKER_VERSION_MAJOR 0 +#define XA_TRACKER_VERSION_MINOR 4 +#define XA_TRACKER_VERSION_PATCH 0 + +#define XA_FLAG_SHARED (1 << 0) +#define XA_FLAG_RENDER_TARGET (1 << 1) + +#define XA_MAP_READ (1 << 0) +#define XA_MAP_WRITE (1 << 1) + +#define XA_ERR_NONE 0 +#define XA_ERR_NORES 1 +#define XA_ERR_INVAL 2 +#define XA_ERR_BUSY 3 + +enum xa_surface_type { + xa_type_other, + xa_type_a, + xa_type_argb, + xa_type_abgr, + xa_type_bgra, + xa_type_z, + xa_type_zs, + xa_type_sz, + xa_type_yuv_component +}; + +/* + * Note that these formats should not be assumed to be binary compatible with + * pixman formats, but with the below macros and a format type map, + * conversion should be simple. Macros for now. We might replace with + * inline functions. + */ + +#define xa_format(bpp,type,a,r,g,b) (((bpp) << 24) | \ + ((type) << 16) | \ + ((a) << 12) | \ + ((r) << 8) | \ + ((g) << 4) | \ + ((b))) +/* + * Non-RGBA one- and two component formats. + */ + +#define xa_format_c(bpp,type,c1,c2) (((bpp) << 24) | \ + ((type) << 16) | \ + ((c1) << 8) | \ + ((c2))) +#define xa_format_bpp(f) (((f) >> 24) ) +#define xa_format_type(f) (((f) >> 16) & 0xff) +#define xa_format_a(f) (((f) >> 12) & 0x0f) +#define xa_format_r(f) (((f) >> 8) & 0x0f) +#define xa_format_g(f) (((f) >> 4) & 0x0f) +#define xa_format_b(f) (((f) ) & 0x0f) +#define xa_format_rgb(f) (((f) ) & 0xfff) +#define xa_format_c1(f) (((f) >> 8 ) & 0xff) +#define xa_format_c2(f) (((f) ) & 0xff) +#define xa_format_argb_depth(f) (xa_format_a(f) + \ + xa_format_r(f) + \ + xa_format_g(f) + \ + xa_format_b(f)) +#define xa_format_c_depth(f) (xa_format_c1(f) + \ + xa_format_c2(f)) + +static inline int +xa_format_type_is_color(uint32_t xa_format) +{ + return (xa_format_type(xa_format) < xa_type_z); +} + +static inline unsigned int +xa_format_depth(uint32_t xa_format) +{ + return ((xa_format_type_is_color(xa_format)) ? + xa_format_argb_depth(xa_format) : xa_format_c_depth(xa_format)); +} + +enum xa_formats { + xa_format_unknown = 0, + xa_format_a8 = xa_format(8, xa_type_a, 8, 0, 0, 0), + + xa_format_a8r8g8b8 = xa_format(32, xa_type_argb, 8, 8, 8, 8), + xa_format_x8r8g8b8 = xa_format(32, xa_type_argb, 0, 8, 8, 8), + xa_format_r5g6b5 = xa_format(16, xa_type_argb, 0, 5, 6, 5), + xa_format_x1r5g5b5 = xa_format(16, xa_type_argb, 0, 5, 5, 5), + + xa_format_z16 = xa_format_c(16, xa_type_z, 16, 0), + xa_format_z32 = xa_format_c(32, xa_type_z, 32, 0), + xa_format_z24 = xa_format_c(32, xa_type_z, 24, 0), + + xa_format_x8z24 = xa_format_c(32, xa_type_sz, 24, 0), + xa_format_s8z24 = xa_format_c(32, xa_type_sz, 24, 8), + xa_format_z24x8 = xa_format_c(32, xa_type_zs, 24, 0), + xa_format_z24s8 = xa_format_c(32, xa_type_zs, 24, 8), + + xa_format_yuv8 = xa_format_c(8, xa_type_yuv_component, 8, 0) +}; + +struct xa_tracker; +struct xa_surface; + +struct xa_box { + uint16_t x1, y1, x2, y2; +}; + +extern void xa_tracker_version(int *major, int *minor, int *patch); + +extern struct xa_tracker *xa_tracker_create(int drm_fd); + +extern void xa_tracker_destroy(struct xa_tracker *xa); + +extern int xa_format_check_supported(struct xa_tracker *xa, + enum xa_formats xa_format, + unsigned int flags); + +extern struct xa_surface *xa_surface_create(struct xa_tracker *xa, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats pform, + unsigned int flags); + +enum xa_formats xa_surface_format(const struct xa_surface *srf); + +extern void xa_surface_destroy(struct xa_surface *srf); + +extern int xa_surface_redefine(struct xa_surface *srf, + int width, + int height, + int depth, + enum xa_surface_type stype, + enum xa_formats rgb_format, + unsigned int new_flags, + int copy_contents); + +extern int xa_surface_handle(struct xa_surface *srf, + uint32_t * handle, unsigned int *byte_stride); + +#endif diff --git a/src/gallium/state_trackers/xa/xa_yuv.c b/src/gallium/state_trackers/xa/xa_yuv.c new file mode 100644 index 00000000000..66cbc5393b5 --- /dev/null +++ b/src/gallium/state_trackers/xa/xa_yuv.c @@ -0,0 +1,179 @@ +/********************************************************** + * 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 <zackr-at-vmware-dot-com> + * Thomas Hellstrom <thellstrom-at-vmware-dot-com> + */ + +#include "xa_context.h" +#include "xa_priv.h" +#include "util/u_inlines.h" +#include "util/u_sampler.h" +#include "util/u_surface.h" +#include "cso_cache/cso_context.h" + +static void +xa_yuv_bind_blend_state(struct xa_context *r) +{ + 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; + + /* porter&duff src */ + 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(r->cso, &blend); +} + +static void +xa_yuv_bind_shaders(struct xa_context *r) +{ + unsigned vs_traits = 0, fs_traits = 0; + struct xa_shader shader; + + vs_traits |= VS_YUV; + fs_traits |= FS_YUV; + + shader = xa_shaders_get(r->shaders, vs_traits, fs_traits); + cso_set_vertex_shader_handle(r->cso, shader.vs); + cso_set_fragment_shader_handle(r->cso, shader.fs); +} + +static void +xa_yuv_bind_samplers(struct xa_context *r, struct xa_surface *yuv[]) +{ + struct pipe_sampler_state *samplers[3]; + struct pipe_sampler_state sampler; + struct pipe_sampler_view *views[3]; + struct pipe_sampler_view view_templ; + unsigned int i; + + memset(&sampler, 0, sizeof(struct pipe_sampler_state)); + + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP; + sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + sampler.normalized_coords = 1; + + for (i = 0; i < 3; ++i) { + samplers[i] = &sampler; + if (!yuv[i]->view) { + u_sampler_view_default_template(&view_templ, + yuv[i]->tex, yuv[i]->tex->format); + + yuv[i]->view = r->pipe->create_sampler_view(r->pipe, + yuv[i]->tex, + &view_templ); + } + views[i] = yuv[i]->view; + } + + cso_set_samplers(r->cso, 3, (const struct pipe_sampler_state **)samplers); + cso_set_fragment_sampler_views(r->cso, 3, views); +} + +static void +xa_yuv_fs_constants(struct xa_context *r, const float conversion_matrix[]) +{ + const int param_bytes = 12 * sizeof(float); + + renderer_set_constants(r, PIPE_SHADER_FRAGMENT, + conversion_matrix, param_bytes); +} + +static void +xa_yuv_destroy_sampler_views(struct xa_surface *yuv[]) +{ + unsigned int i; + + for (i = 0; i < 3; ++i) { + pipe_sampler_view_reference(&yuv[i]->view, NULL); + } +} + +extern int +xa_yuv_planar_blit(struct xa_context *r, + int src_x, + int src_y, + int src_w, + int src_h, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + struct xa_box *box, + unsigned int num_boxes, + const float conversion_matrix[], + struct xa_surface *dst, struct xa_surface *yuv[]) +{ + float scale_x; + float scale_y; + struct pipe_surface srf_templ; + + if (dst_w == 0 || dst_h == 0) + return XA_ERR_NONE; + + memset(&srf_templ, 0, sizeof(srf_templ)); + u_surface_default_template(&srf_templ, dst->tex, PIPE_BIND_RENDER_TARGET); + dst->srf = r->pipe->create_surface(r->pipe, dst->tex, &srf_templ); + if (!dst->srf) + return -XA_ERR_NORES; + + renderer_bind_destination(r, dst->srf, dst->srf->width, dst->srf->height); + xa_yuv_bind_blend_state(r); + xa_yuv_bind_shaders(r); + xa_yuv_bind_samplers(r, yuv); + xa_yuv_fs_constants(r, conversion_matrix); + + scale_x = (float)src_w / (float)dst_w; + scale_y = (float)src_h / (float)dst_h; + + while (num_boxes--) { + int x = box->x1; + int y = box->y1; + int w = box->x2 - box->x1; + int h = box->y2 - box->y1; + + renderer_draw_yuv(r, + (float)src_x + scale_x * (x - dst_x), + (float)src_y + scale_y * (y - dst_y), + scale_x * w, scale_y * h, x, y, w, h, yuv); + box++; + } + + r->pipe->flush(r->pipe, &r->last_fence); + + xa_yuv_destroy_sampler_views(yuv); + pipe_surface_reference(&dst->srf, NULL); + + return XA_ERR_NONE; +} |