17ec681f3Smrg/********************************************************** 27ec681f3Smrg * Copyright 2009-2011 VMware, Inc. All rights reserved. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person 57ec681f3Smrg * obtaining a copy of this software and associated documentation 67ec681f3Smrg * files (the "Software"), to deal in the Software without 77ec681f3Smrg * restriction, including without limitation the rights to use, copy, 87ec681f3Smrg * modify, merge, publish, distribute, sublicense, and/or sell copies 97ec681f3Smrg * of the Software, and to permit persons to whom the Software is 107ec681f3Smrg * furnished to do so, subject to the following conditions: 117ec681f3Smrg * 127ec681f3Smrg * The above copyright notice and this permission notice shall be 137ec681f3Smrg * included in all copies or substantial portions of the Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 167ec681f3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 177ec681f3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 187ec681f3Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 197ec681f3Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 207ec681f3Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 217ec681f3Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 227ec681f3Smrg * SOFTWARE. 237ec681f3Smrg * 247ec681f3Smrg ********************************************************* 257ec681f3Smrg * Authors: 267ec681f3Smrg * Zack Rusin <zackr-at-vmware-dot-com> 277ec681f3Smrg * Thomas Hellstrom <thellstrom-at-vmware-dot-com> 287ec681f3Smrg */ 297ec681f3Smrg 307ec681f3Smrg#include "xa_composite.h" 317ec681f3Smrg#include "xa_context.h" 327ec681f3Smrg#include "xa_priv.h" 337ec681f3Smrg#include "cso_cache/cso_context.h" 347ec681f3Smrg#include "util/u_sampler.h" 357ec681f3Smrg#include "util/u_inlines.h" 367ec681f3Smrg 377ec681f3Smrg 387ec681f3Smrg/*XXX also in Xrender.h but the including it here breaks compilition */ 397ec681f3Smrg#define XFixedToDouble(f) (((double) (f)) / 65536.) 407ec681f3Smrg 417ec681f3Smrgstruct xa_composite_blend { 427ec681f3Smrg unsigned op : 8; 437ec681f3Smrg 447ec681f3Smrg unsigned alpha_dst : 4; 457ec681f3Smrg unsigned alpha_src : 4; 467ec681f3Smrg 477ec681f3Smrg unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ 487ec681f3Smrg unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ 497ec681f3Smrg}; 507ec681f3Smrg 517ec681f3Smrg#define XA_BLEND_OP_OVER 3 527ec681f3Smrgstatic const struct xa_composite_blend xa_blends[] = { 537ec681f3Smrg { xa_op_clear, 547ec681f3Smrg 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, 557ec681f3Smrg { xa_op_src, 567ec681f3Smrg 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, 577ec681f3Smrg { xa_op_dst, 587ec681f3Smrg 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, 597ec681f3Smrg { xa_op_over, 607ec681f3Smrg 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 617ec681f3Smrg { xa_op_over_reverse, 627ec681f3Smrg 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, 637ec681f3Smrg { xa_op_in, 647ec681f3Smrg 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, 657ec681f3Smrg { xa_op_in_reverse, 667ec681f3Smrg 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, 677ec681f3Smrg { xa_op_out, 687ec681f3Smrg 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, 697ec681f3Smrg { xa_op_out_reverse, 707ec681f3Smrg 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 717ec681f3Smrg { xa_op_atop, 727ec681f3Smrg 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 737ec681f3Smrg { xa_op_atop_reverse, 747ec681f3Smrg 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, 757ec681f3Smrg { xa_op_xor, 767ec681f3Smrg 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 777ec681f3Smrg { xa_op_add, 787ec681f3Smrg 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, 797ec681f3Smrg}; 807ec681f3Smrg 817ec681f3Smrg/* 827ec681f3Smrg * The alpha value stored in a L8 texture is read by the 837ec681f3Smrg * hardware as color, and R8 is read as red. The source alpha value 847ec681f3Smrg * at the end of the fragment shader is stored in all color channels, 857ec681f3Smrg * so the correct approach is to blend using DST_COLOR instead of 867ec681f3Smrg * DST_ALPHA and then output any color channel (L8) or the red channel (R8). 877ec681f3Smrg */ 887ec681f3Smrgstatic unsigned 897ec681f3Smrgxa_convert_blend_for_luminance(unsigned factor) 907ec681f3Smrg{ 917ec681f3Smrg switch(factor) { 927ec681f3Smrg case PIPE_BLENDFACTOR_DST_ALPHA: 937ec681f3Smrg return PIPE_BLENDFACTOR_DST_COLOR; 947ec681f3Smrg case PIPE_BLENDFACTOR_INV_DST_ALPHA: 957ec681f3Smrg return PIPE_BLENDFACTOR_INV_DST_COLOR; 967ec681f3Smrg default: 977ec681f3Smrg break; 987ec681f3Smrg } 997ec681f3Smrg return factor; 1007ec681f3Smrg} 1017ec681f3Smrg 1027ec681f3Smrgstatic boolean 1037ec681f3Smrgblend_for_op(struct xa_composite_blend *blend, 1047ec681f3Smrg enum xa_composite_op op, 1057ec681f3Smrg struct xa_picture *src_pic, 1067ec681f3Smrg struct xa_picture *mask_pic, 1077ec681f3Smrg struct xa_picture *dst_pic) 1087ec681f3Smrg{ 1097ec681f3Smrg const int num_blends = 1107ec681f3Smrg sizeof(xa_blends)/sizeof(struct xa_composite_blend); 1117ec681f3Smrg int i; 1127ec681f3Smrg boolean supported = FALSE; 1137ec681f3Smrg 1147ec681f3Smrg /* 1157ec681f3Smrg * our default in case something goes wrong 1167ec681f3Smrg */ 1177ec681f3Smrg *blend = xa_blends[XA_BLEND_OP_OVER]; 1187ec681f3Smrg 1197ec681f3Smrg for (i = 0; i < num_blends; ++i) { 1207ec681f3Smrg if (xa_blends[i].op == op) { 1217ec681f3Smrg *blend = xa_blends[i]; 1227ec681f3Smrg supported = TRUE; 1237ec681f3Smrg break; 1247ec681f3Smrg } 1257ec681f3Smrg } 1267ec681f3Smrg 1277ec681f3Smrg /* 1287ec681f3Smrg * No component alpha yet. 1297ec681f3Smrg */ 1307ec681f3Smrg if (mask_pic && mask_pic->component_alpha && blend->alpha_src) 1317ec681f3Smrg return FALSE; 1327ec681f3Smrg 1337ec681f3Smrg if (!dst_pic->srf) 1347ec681f3Smrg return supported; 1357ec681f3Smrg 1367ec681f3Smrg if ((dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM || 1377ec681f3Smrg dst_pic->srf->tex->format == PIPE_FORMAT_R8_UNORM)) { 1387ec681f3Smrg blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src); 1397ec681f3Smrg blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst); 1407ec681f3Smrg } 1417ec681f3Smrg 1427ec681f3Smrg /* 1437ec681f3Smrg * If there's no dst alpha channel, adjust the blend op so that we'll treat 1447ec681f3Smrg * it as always 1. 1457ec681f3Smrg */ 1467ec681f3Smrg 1477ec681f3Smrg if (xa_format_a(dst_pic->pict_format) == 0 && blend->alpha_dst) { 1487ec681f3Smrg if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) 1497ec681f3Smrg blend->rgb_src = PIPE_BLENDFACTOR_ONE; 1507ec681f3Smrg else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) 1517ec681f3Smrg blend->rgb_src = PIPE_BLENDFACTOR_ZERO; 1527ec681f3Smrg } 1537ec681f3Smrg 1547ec681f3Smrg return supported; 1557ec681f3Smrg} 1567ec681f3Smrg 1577ec681f3Smrg 1587ec681f3Smrgstatic inline int 1597ec681f3Smrgxa_repeat_to_gallium(int mode) 1607ec681f3Smrg{ 1617ec681f3Smrg switch(mode) { 1627ec681f3Smrg case xa_wrap_clamp_to_border: 1637ec681f3Smrg return PIPE_TEX_WRAP_CLAMP_TO_BORDER; 1647ec681f3Smrg case xa_wrap_repeat: 1657ec681f3Smrg return PIPE_TEX_WRAP_REPEAT; 1667ec681f3Smrg case xa_wrap_mirror_repeat: 1677ec681f3Smrg return PIPE_TEX_WRAP_MIRROR_REPEAT; 1687ec681f3Smrg case xa_wrap_clamp_to_edge: 1697ec681f3Smrg return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 1707ec681f3Smrg default: 1717ec681f3Smrg break; 1727ec681f3Smrg } 1737ec681f3Smrg return PIPE_TEX_WRAP_REPEAT; 1747ec681f3Smrg} 1757ec681f3Smrg 1767ec681f3Smrgstatic inline boolean 1777ec681f3Smrgxa_filter_to_gallium(int xrender_filter, int *out_filter) 1787ec681f3Smrg{ 1797ec681f3Smrg 1807ec681f3Smrg switch (xrender_filter) { 1817ec681f3Smrg case xa_filter_nearest: 1827ec681f3Smrg *out_filter = PIPE_TEX_FILTER_NEAREST; 1837ec681f3Smrg break; 1847ec681f3Smrg case xa_filter_linear: 1857ec681f3Smrg *out_filter = PIPE_TEX_FILTER_LINEAR; 1867ec681f3Smrg break; 1877ec681f3Smrg default: 1887ec681f3Smrg *out_filter = PIPE_TEX_FILTER_NEAREST; 1897ec681f3Smrg return FALSE; 1907ec681f3Smrg } 1917ec681f3Smrg return TRUE; 1927ec681f3Smrg} 1937ec681f3Smrg 1947ec681f3Smrgstatic int 1957ec681f3Smrgxa_is_filter_accelerated(struct xa_picture *pic) 1967ec681f3Smrg{ 1977ec681f3Smrg int filter; 1987ec681f3Smrg if (pic && !xa_filter_to_gallium(pic->filter, &filter)) 1997ec681f3Smrg return 0; 2007ec681f3Smrg return 1; 2017ec681f3Smrg} 2027ec681f3Smrg 2037ec681f3Smrg/** 2047ec681f3Smrg * xa_src_pict_is_accelerated - Check whether we support acceleration 2057ec681f3Smrg * of the given src_pict type 2067ec681f3Smrg * 2077ec681f3Smrg * \param src_pic[in]: Pointer to a union xa_source_pict to check. 2087ec681f3Smrg * 2097ec681f3Smrg * \returns TRUE if accelerated, FALSE otherwise. 2107ec681f3Smrg */ 2117ec681f3Smrgstatic boolean 2127ec681f3Smrgxa_src_pict_is_accelerated(const union xa_source_pict *src_pic) 2137ec681f3Smrg{ 2147ec681f3Smrg if (!src_pic) 2157ec681f3Smrg return TRUE; 2167ec681f3Smrg 2177ec681f3Smrg if (src_pic->type == xa_src_pict_solid_fill || 2187ec681f3Smrg src_pic->type == xa_src_pict_float_solid_fill) 2197ec681f3Smrg return TRUE; 2207ec681f3Smrg 2217ec681f3Smrg return FALSE; 2227ec681f3Smrg} 2237ec681f3Smrg 2247ec681f3SmrgXA_EXPORT int 2257ec681f3Smrgxa_composite_check_accelerated(const struct xa_composite *comp) 2267ec681f3Smrg{ 2277ec681f3Smrg struct xa_picture *src_pic = comp->src; 2287ec681f3Smrg struct xa_picture *mask_pic = comp->mask; 2297ec681f3Smrg struct xa_composite_blend blend; 2307ec681f3Smrg 2317ec681f3Smrg if (!xa_is_filter_accelerated(src_pic) || 2327ec681f3Smrg !xa_is_filter_accelerated(comp->mask)) { 2337ec681f3Smrg return -XA_ERR_INVAL; 2347ec681f3Smrg } 2357ec681f3Smrg 2367ec681f3Smrg if (!xa_src_pict_is_accelerated(src_pic->src_pict) || 2377ec681f3Smrg (mask_pic && !xa_src_pict_is_accelerated(mask_pic->src_pict))) 2387ec681f3Smrg return -XA_ERR_INVAL; 2397ec681f3Smrg 2407ec681f3Smrg if (!blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) 2417ec681f3Smrg return -XA_ERR_INVAL; 2427ec681f3Smrg 2437ec681f3Smrg /* 2447ec681f3Smrg * No component alpha yet. 2457ec681f3Smrg */ 2467ec681f3Smrg if (mask_pic && mask_pic->component_alpha && blend.alpha_src) 2477ec681f3Smrg return -XA_ERR_INVAL; 2487ec681f3Smrg 2497ec681f3Smrg return XA_ERR_NONE; 2507ec681f3Smrg} 2517ec681f3Smrg 2527ec681f3Smrgstatic int 2537ec681f3Smrgbind_composite_blend_state(struct xa_context *ctx, 2547ec681f3Smrg const struct xa_composite *comp) 2557ec681f3Smrg{ 2567ec681f3Smrg struct xa_composite_blend blend_opt; 2577ec681f3Smrg struct pipe_blend_state blend; 2587ec681f3Smrg 2597ec681f3Smrg if (!blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst)) 2607ec681f3Smrg return -XA_ERR_INVAL; 2617ec681f3Smrg 2627ec681f3Smrg memset(&blend, 0, sizeof(struct pipe_blend_state)); 2637ec681f3Smrg blend.rt[0].blend_enable = 1; 2647ec681f3Smrg blend.rt[0].colormask = PIPE_MASK_RGBA; 2657ec681f3Smrg 2667ec681f3Smrg blend.rt[0].rgb_src_factor = blend_opt.rgb_src; 2677ec681f3Smrg blend.rt[0].alpha_src_factor = blend_opt.rgb_src; 2687ec681f3Smrg blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; 2697ec681f3Smrg blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; 2707ec681f3Smrg 2717ec681f3Smrg cso_set_blend(ctx->cso, &blend); 2727ec681f3Smrg return XA_ERR_NONE; 2737ec681f3Smrg} 2747ec681f3Smrg 2757ec681f3Smrgstatic unsigned int 2767ec681f3Smrgpicture_format_fixups(struct xa_picture *src_pic, 2777ec681f3Smrg int mask) 2787ec681f3Smrg{ 2797ec681f3Smrg boolean set_alpha = FALSE; 2807ec681f3Smrg boolean swizzle = FALSE; 2817ec681f3Smrg unsigned ret = 0; 2827ec681f3Smrg struct xa_surface *src = src_pic->srf; 2837ec681f3Smrg enum xa_formats src_hw_format, src_pic_format; 2847ec681f3Smrg enum xa_surface_type src_hw_type, src_pic_type; 2857ec681f3Smrg 2867ec681f3Smrg if (!src) 2877ec681f3Smrg return 0; 2887ec681f3Smrg 2897ec681f3Smrg src_hw_format = xa_surface_format(src); 2907ec681f3Smrg src_pic_format = src_pic->pict_format; 2917ec681f3Smrg 2927ec681f3Smrg set_alpha = (xa_format_type_is_color(src_hw_format) && 2937ec681f3Smrg xa_format_a(src_pic_format) == 0); 2947ec681f3Smrg 2957ec681f3Smrg if (set_alpha) 2967ec681f3Smrg ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; 2977ec681f3Smrg 2987ec681f3Smrg if (src_hw_format == src_pic_format) { 2997ec681f3Smrg if (src->tex->format == PIPE_FORMAT_L8_UNORM || 3007ec681f3Smrg src->tex->format == PIPE_FORMAT_R8_UNORM) 3017ec681f3Smrg return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE); 3027ec681f3Smrg 3037ec681f3Smrg return ret; 3047ec681f3Smrg } 3057ec681f3Smrg 3067ec681f3Smrg src_hw_type = xa_format_type(src_hw_format); 3077ec681f3Smrg src_pic_type = xa_format_type(src_pic_format); 3087ec681f3Smrg 3097ec681f3Smrg swizzle = ((src_hw_type == xa_type_argb && 3107ec681f3Smrg src_pic_type == xa_type_abgr) || 3117ec681f3Smrg ((src_hw_type == xa_type_abgr && 3127ec681f3Smrg src_pic_type == xa_type_argb))); 3137ec681f3Smrg 3147ec681f3Smrg if (!swizzle && (src_hw_type != src_pic_type)) 3157ec681f3Smrg return ret; 3167ec681f3Smrg 3177ec681f3Smrg if (swizzle) 3187ec681f3Smrg ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; 3197ec681f3Smrg 3207ec681f3Smrg return ret; 3217ec681f3Smrg} 3227ec681f3Smrg 3237ec681f3Smrgstatic void 3247ec681f3Smrgxa_src_in_mask(float src[4], const float mask[4]) 3257ec681f3Smrg{ 3267ec681f3Smrg src[0] *= mask[3]; 3277ec681f3Smrg src[1] *= mask[3]; 3287ec681f3Smrg src[2] *= mask[3]; 3297ec681f3Smrg src[3] *= mask[3]; 3307ec681f3Smrg} 3317ec681f3Smrg 3327ec681f3Smrg/** 3337ec681f3Smrg * xa_handle_src_pict - Set up xa_context state and fragment shader 3347ec681f3Smrg * input based on scr_pict type 3357ec681f3Smrg * 3367ec681f3Smrg * \param ctx[in, out]: Pointer to the xa context. 3377ec681f3Smrg * \param src_pict[in]: Pointer to the union xa_source_pict to consider. 3387ec681f3Smrg * \param is_mask[in]: Whether we're considering a mask picture. 3397ec681f3Smrg * 3407ec681f3Smrg * \returns TRUE if succesful, FALSE otherwise. 3417ec681f3Smrg * 3427ec681f3Smrg * This function computes some xa_context state used to determine whether 3437ec681f3Smrg * to upload the solid color and also the solid color itself used as an input 3447ec681f3Smrg * to the fragment shader. 3457ec681f3Smrg */ 3467ec681f3Smrgstatic boolean 3477ec681f3Smrgxa_handle_src_pict(struct xa_context *ctx, 3487ec681f3Smrg const union xa_source_pict *src_pict, 3497ec681f3Smrg boolean is_mask) 3507ec681f3Smrg{ 3517ec681f3Smrg float solid_color[4]; 3527ec681f3Smrg 3537ec681f3Smrg switch(src_pict->type) { 3547ec681f3Smrg case xa_src_pict_solid_fill: 3557ec681f3Smrg xa_pixel_to_float4(src_pict->solid_fill.color, solid_color); 3567ec681f3Smrg break; 3577ec681f3Smrg case xa_src_pict_float_solid_fill: 3587ec681f3Smrg memcpy(solid_color, src_pict->float_solid_fill.color, 3597ec681f3Smrg sizeof(solid_color)); 3607ec681f3Smrg break; 3617ec681f3Smrg default: 3627ec681f3Smrg return FALSE; 3637ec681f3Smrg } 3647ec681f3Smrg 3657ec681f3Smrg if (is_mask && ctx->has_solid_src) 3667ec681f3Smrg xa_src_in_mask(ctx->solid_color, solid_color); 3677ec681f3Smrg else 3687ec681f3Smrg memcpy(ctx->solid_color, solid_color, sizeof(solid_color)); 3697ec681f3Smrg 3707ec681f3Smrg if (is_mask) 3717ec681f3Smrg ctx->has_solid_mask = TRUE; 3727ec681f3Smrg else 3737ec681f3Smrg ctx->has_solid_src = TRUE; 3747ec681f3Smrg 3757ec681f3Smrg return TRUE; 3767ec681f3Smrg} 3777ec681f3Smrg 3787ec681f3Smrgstatic int 3797ec681f3Smrgbind_shaders(struct xa_context *ctx, const struct xa_composite *comp) 3807ec681f3Smrg{ 3817ec681f3Smrg unsigned vs_traits = 0, fs_traits = 0; 3827ec681f3Smrg struct xa_shader shader; 3837ec681f3Smrg struct xa_picture *src_pic = comp->src; 3847ec681f3Smrg struct xa_picture *mask_pic = comp->mask; 3857ec681f3Smrg struct xa_picture *dst_pic = comp->dst; 3867ec681f3Smrg 3877ec681f3Smrg ctx->has_solid_src = FALSE; 3887ec681f3Smrg ctx->has_solid_mask = FALSE; 3897ec681f3Smrg 3907ec681f3Smrg if (dst_pic && xa_format_type(dst_pic->pict_format) != 3917ec681f3Smrg xa_format_type(xa_surface_format(dst_pic->srf))) 3927ec681f3Smrg return -XA_ERR_INVAL; 3937ec681f3Smrg 3947ec681f3Smrg if (src_pic) { 3957ec681f3Smrg if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) 3967ec681f3Smrg fs_traits |= FS_SRC_REPEAT_NONE; 3977ec681f3Smrg 3987ec681f3Smrg fs_traits |= FS_COMPOSITE; 3997ec681f3Smrg vs_traits |= VS_COMPOSITE; 4007ec681f3Smrg 4017ec681f3Smrg if (src_pic->src_pict) { 4027ec681f3Smrg if (!xa_handle_src_pict(ctx, src_pic->src_pict, false)) 4037ec681f3Smrg return -XA_ERR_INVAL; 4047ec681f3Smrg fs_traits |= FS_SRC_SRC; 4057ec681f3Smrg vs_traits |= VS_SRC_SRC; 4067ec681f3Smrg } else 4077ec681f3Smrg fs_traits |= picture_format_fixups(src_pic, 0); 4087ec681f3Smrg } 4097ec681f3Smrg 4107ec681f3Smrg if (mask_pic) { 4117ec681f3Smrg vs_traits |= VS_MASK; 4127ec681f3Smrg fs_traits |= FS_MASK; 4137ec681f3Smrg if (mask_pic->component_alpha) 4147ec681f3Smrg fs_traits |= FS_CA; 4157ec681f3Smrg if (mask_pic->src_pict) { 4167ec681f3Smrg if (!xa_handle_src_pict(ctx, mask_pic->src_pict, true)) 4177ec681f3Smrg return -XA_ERR_INVAL; 4187ec681f3Smrg 4197ec681f3Smrg if (ctx->has_solid_src) { 4207ec681f3Smrg vs_traits &= ~VS_MASK; 4217ec681f3Smrg fs_traits &= ~FS_MASK; 4227ec681f3Smrg } else { 4237ec681f3Smrg vs_traits |= VS_MASK_SRC; 4247ec681f3Smrg fs_traits |= FS_MASK_SRC; 4257ec681f3Smrg } 4267ec681f3Smrg } else { 4277ec681f3Smrg if (mask_pic->wrap == xa_wrap_clamp_to_border && 4287ec681f3Smrg mask_pic->has_transform) 4297ec681f3Smrg fs_traits |= FS_MASK_REPEAT_NONE; 4307ec681f3Smrg 4317ec681f3Smrg fs_traits |= picture_format_fixups(mask_pic, 1); 4327ec681f3Smrg } 4337ec681f3Smrg } 4347ec681f3Smrg 4357ec681f3Smrg if (ctx->srf->format == PIPE_FORMAT_L8_UNORM || 4367ec681f3Smrg ctx->srf->format == PIPE_FORMAT_R8_UNORM) 4377ec681f3Smrg fs_traits |= FS_DST_LUMINANCE; 4387ec681f3Smrg 4397ec681f3Smrg shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); 4407ec681f3Smrg cso_set_vertex_shader_handle(ctx->cso, shader.vs); 4417ec681f3Smrg cso_set_fragment_shader_handle(ctx->cso, shader.fs); 4427ec681f3Smrg return XA_ERR_NONE; 4437ec681f3Smrg} 4447ec681f3Smrg 4457ec681f3Smrgstatic void 4467ec681f3Smrgbind_samplers(struct xa_context *ctx, 4477ec681f3Smrg const struct xa_composite *comp) 4487ec681f3Smrg{ 4497ec681f3Smrg struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 4507ec681f3Smrg struct pipe_sampler_state src_sampler, mask_sampler; 4517ec681f3Smrg struct pipe_sampler_view view_templ; 4527ec681f3Smrg struct pipe_sampler_view *src_view; 4537ec681f3Smrg struct pipe_context *pipe = ctx->pipe; 4547ec681f3Smrg struct xa_picture *src_pic = comp->src; 4557ec681f3Smrg struct xa_picture *mask_pic = comp->mask; 4567ec681f3Smrg int num_samplers = 0; 4577ec681f3Smrg 4587ec681f3Smrg xa_ctx_sampler_views_destroy(ctx); 4597ec681f3Smrg memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); 4607ec681f3Smrg memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); 4617ec681f3Smrg 4627ec681f3Smrg if (src_pic && !ctx->has_solid_src) { 4637ec681f3Smrg unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); 4647ec681f3Smrg int filter; 4657ec681f3Smrg 4667ec681f3Smrg (void) xa_filter_to_gallium(src_pic->filter, &filter); 4677ec681f3Smrg 4687ec681f3Smrg src_sampler.wrap_s = src_wrap; 4697ec681f3Smrg src_sampler.wrap_t = src_wrap; 4707ec681f3Smrg src_sampler.min_img_filter = filter; 4717ec681f3Smrg src_sampler.mag_img_filter = filter; 4727ec681f3Smrg src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 4737ec681f3Smrg src_sampler.normalized_coords = 1; 4747ec681f3Smrg samplers[0] = &src_sampler; 4757ec681f3Smrg u_sampler_view_default_template(&view_templ, 4767ec681f3Smrg src_pic->srf->tex,+ src_pic->srf->tex->format); 4777ec681f3Smrg src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, 4787ec681f3Smrg &view_templ); 4797ec681f3Smrg ctx->bound_sampler_views[0] = src_view; 4807ec681f3Smrg num_samplers++; 4817ec681f3Smrg } 4827ec681f3Smrg 4837ec681f3Smrg if (mask_pic && !ctx->has_solid_mask) { 4847ec681f3Smrg unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); 4857ec681f3Smrg int filter; 4867ec681f3Smrg 4877ec681f3Smrg (void) xa_filter_to_gallium(mask_pic->filter, &filter); 4887ec681f3Smrg 4897ec681f3Smrg mask_sampler.wrap_s = mask_wrap; 4907ec681f3Smrg mask_sampler.wrap_t = mask_wrap; 4917ec681f3Smrg mask_sampler.min_img_filter = filter; 4927ec681f3Smrg mask_sampler.mag_img_filter = filter; 4937ec681f3Smrg src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 4947ec681f3Smrg mask_sampler.normalized_coords = 1; 4957ec681f3Smrg samplers[num_samplers] = &mask_sampler; 4967ec681f3Smrg u_sampler_view_default_template(&view_templ, 4977ec681f3Smrg mask_pic->srf->tex, 4987ec681f3Smrg mask_pic->srf->tex->format); 4997ec681f3Smrg src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, 5007ec681f3Smrg &view_templ); 5017ec681f3Smrg ctx->bound_sampler_views[num_samplers] = src_view; 5027ec681f3Smrg num_samplers++; 5037ec681f3Smrg } 5047ec681f3Smrg 5057ec681f3Smrg cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, 5067ec681f3Smrg (const struct pipe_sampler_state **)samplers); 5077ec681f3Smrg pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_samplers, 0, 5087ec681f3Smrg false, ctx->bound_sampler_views); 5097ec681f3Smrg ctx->num_bound_samplers = num_samplers; 5107ec681f3Smrg} 5117ec681f3Smrg 5127ec681f3SmrgXA_EXPORT int 5137ec681f3Smrgxa_composite_prepare(struct xa_context *ctx, 5147ec681f3Smrg const struct xa_composite *comp) 5157ec681f3Smrg{ 5167ec681f3Smrg struct xa_surface *dst_srf = comp->dst->srf; 5177ec681f3Smrg int ret; 5187ec681f3Smrg 5197ec681f3Smrg ret = xa_ctx_srf_create(ctx, dst_srf); 5207ec681f3Smrg if (ret != XA_ERR_NONE) 5217ec681f3Smrg return ret; 5227ec681f3Smrg 5237ec681f3Smrg ctx->dst = dst_srf; 5247ec681f3Smrg renderer_bind_destination(ctx, ctx->srf); 5257ec681f3Smrg 5267ec681f3Smrg ret = bind_composite_blend_state(ctx, comp); 5277ec681f3Smrg if (ret != XA_ERR_NONE) 5287ec681f3Smrg return ret; 5297ec681f3Smrg ret = bind_shaders(ctx, comp); 5307ec681f3Smrg if (ret != XA_ERR_NONE) 5317ec681f3Smrg return ret; 5327ec681f3Smrg bind_samplers(ctx, comp); 5337ec681f3Smrg 5347ec681f3Smrg if (ctx->num_bound_samplers == 0 ) { /* solid fill */ 5357ec681f3Smrg renderer_begin_solid(ctx); 5367ec681f3Smrg } else { 5377ec681f3Smrg renderer_begin_textures(ctx); 5387ec681f3Smrg ctx->comp = comp; 5397ec681f3Smrg } 5407ec681f3Smrg 5417ec681f3Smrg xa_ctx_srf_destroy(ctx); 5427ec681f3Smrg return XA_ERR_NONE; 5437ec681f3Smrg} 5447ec681f3Smrg 5457ec681f3SmrgXA_EXPORT void 5467ec681f3Smrgxa_composite_rect(struct xa_context *ctx, 5477ec681f3Smrg int srcX, int srcY, int maskX, int maskY, 5487ec681f3Smrg int dstX, int dstY, int width, int height) 5497ec681f3Smrg{ 5507ec681f3Smrg if (ctx->num_bound_samplers == 0 ) { /* solid fill */ 5517ec681f3Smrg xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); 5527ec681f3Smrg renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height); 5537ec681f3Smrg } else { 5547ec681f3Smrg const struct xa_composite *comp = ctx->comp; 5557ec681f3Smrg int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; 5567ec681f3Smrg const float *src_matrix = NULL; 5577ec681f3Smrg const float *mask_matrix = NULL; 5587ec681f3Smrg 5597ec681f3Smrg xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); 5607ec681f3Smrg 5617ec681f3Smrg if (comp->src->has_transform) 5627ec681f3Smrg src_matrix = comp->src->transform; 5637ec681f3Smrg if (comp->mask && comp->mask->has_transform) 5647ec681f3Smrg mask_matrix = comp->mask->transform; 5657ec681f3Smrg 5667ec681f3Smrg renderer_texture(ctx, pos, width, height, 5677ec681f3Smrg src_matrix, mask_matrix); 5687ec681f3Smrg } 5697ec681f3Smrg} 5707ec681f3Smrg 5717ec681f3SmrgXA_EXPORT void 5727ec681f3Smrgxa_composite_done(struct xa_context *ctx) 5737ec681f3Smrg{ 5747ec681f3Smrg renderer_draw_flush(ctx); 5757ec681f3Smrg 5767ec681f3Smrg ctx->comp = NULL; 5777ec681f3Smrg ctx->has_solid_src = FALSE; 5787ec681f3Smrg ctx->has_solid_mask = FALSE; 5797ec681f3Smrg xa_ctx_sampler_views_destroy(ctx); 5807ec681f3Smrg} 5817ec681f3Smrg 5827ec681f3Smrgstatic const struct xa_composite_allocation a = { 5837ec681f3Smrg .xa_composite_size = sizeof(struct xa_composite), 5847ec681f3Smrg .xa_picture_size = sizeof(struct xa_picture), 5857ec681f3Smrg .xa_source_pict_size = sizeof(union xa_source_pict), 5867ec681f3Smrg}; 5877ec681f3Smrg 5887ec681f3SmrgXA_EXPORT const struct xa_composite_allocation * 5897ec681f3Smrgxa_composite_allocation(void) 5907ec681f3Smrg{ 5917ec681f3Smrg return &a; 5927ec681f3Smrg} 593