xa_composite.c revision adf166b6c4f6781fd5e751622e9488e5f834bbc2
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/********************************************************** 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Copyright 2009-2011 VMware, Inc. All rights reserved. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Permission is hereby granted, free of charge, to any person 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * obtaining a copy of this software and associated documentation 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * files (the "Software"), to deal in the Software without 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * restriction, including without limitation the rights to use, copy, 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * modify, merge, publish, distribute, sublicense, and/or sell copies 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * of the Software, and to permit persons to whom the Software is 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * furnished to do so, subject to the following conditions: 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * The above copyright notice and this permission notice shall be 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * included in all copies or substantial portions of the Software. 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * SOFTWARE. 23654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com * 24654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com ********************************************************* 25654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com * Authors: 26654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com * Zack Rusin <zackr-at-vmware-dot-com> 27654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com * Thomas Hellstrom <thellstrom-at-vmware-dot-com> 28654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com */ 29654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 30654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#include "xa_composite.h" 31654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#include "xa_context.h" 32654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#include "xa_priv.h" 33654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#include "cso_cache/cso_context.h" 34654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#include "util/u_sampler.h" 35654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#include "util/u_inlines.h" 36654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 37654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 38654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com/*XXX also in Xrender.h but the including it here breaks compilition */ 39654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#define XFixedToDouble(f) (((double) (f)) / 65536.) 40654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 41654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.comstruct xa_composite_blend { 42654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com enum xa_composite_op op : 8; 43fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 44e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com unsigned alpha_dst : 4; 45e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com unsigned alpha_src : 4; 46e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 47e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ 48e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ 49fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com}; 50654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 51654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com#define XA_BLEND_OP_OVER 3 52e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.comstatic const struct xa_composite_blend xa_blends[] = { 53e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com { xa_op_clear, 54e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, 55e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com { xa_op_src, 56fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, 57e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com { xa_op_dst, 58654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, 59fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { xa_op_over, 60e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 61e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com { xa_op_over_reverse, 62654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, 63654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com { xa_op_in, 64e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, 65e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com { xa_op_in_reverse, 66e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, 67fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com { xa_op_out, 68e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, 69ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com { xa_op_out_reverse, 70e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 71ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com { xa_op_atop, 72fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 73ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com { xa_op_atop_reverse, 74ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, 75ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com { xa_op_xor, 76fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 77e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com { xa_op_add, 78fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, 79ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com}; 80e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 81ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic boolean 83654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.comblend_for_op(struct xa_composite_blend *blend, 84654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com enum xa_composite_op op, 85654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com struct xa_picture *src_pic, 86654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com struct xa_picture *mask_pic, 87654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com struct xa_picture *dst_pic) 88654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com{ 89e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com const int num_blends = 90654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com sizeof(xa_blends)/sizeof(struct xa_composite_blend); 91fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int i; 92ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com boolean supported = FALSE; 93e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 94e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com /* 95ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * our default in case something goes wrong 96ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com */ 97ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com 98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com *blend = xa_blends[XA_BLEND_OP_OVER]; 99e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 100fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com for (i = 0; i < num_blends; ++i) { 101e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com if (xa_blends[i].op == op) { 102e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com *blend = xa_blends[i]; 103e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com supported = TRUE; 104e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com } 105fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 107fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 108e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com /* 109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * If there's no dst alpha channel, adjust the blend op so that we'll treat 110e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com * it as always 1. 111e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com */ 112e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 113fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (dst_pic && 114e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com xa_format_a(xa_surface_format(dst_pic->srf)) == 0 && 115fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com blend->alpha_dst) { 116fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) 117e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com blend->rgb_src = PIPE_BLENDFACTOR_ONE; 118e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) 119e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com blend->rgb_src = PIPE_BLENDFACTOR_ZERO; 120e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com } 121fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /* 123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * If the source alpha is being used, then we should only be in a case where 124e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com * the source blend factor is 0, and the source blend value is the mask 125fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * channels multiplied by the source picture's alpha. 126e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com */ 127fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com if (mask_pic && mask_pic->component_alpha && 128e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com xa_format_rgb(xa_surface_format(mask_pic->srf)) && 129e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com blend->alpha_src) { 130654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com if (blend->rgb_dst == PIPE_BLENDFACTOR_SRC_ALPHA) { 131fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com blend->rgb_dst = PIPE_BLENDFACTOR_SRC_COLOR; 132a10742c69ce47d346e3cf23e7be909c9f29b401ecaryclark } else if (blend->rgb_dst == PIPE_BLENDFACTOR_INV_SRC_ALPHA) { 133fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com blend->rgb_dst = PIPE_BLENDFACTOR_INV_SRC_COLOR; 134fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 135654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com } 136fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 137654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com return supported; 138654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com} 139e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 140654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com 141654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.comstatic INLINE int 142fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comxa_repeat_to_gallium(int mode) 143fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com{ 144e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com switch(mode) { 145e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com case xa_wrap_clamp_to_border: 146e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com return PIPE_TEX_WRAP_CLAMP_TO_BORDER; 147e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com case xa_wrap_repeat: 148ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com return PIPE_TEX_WRAP_REPEAT; 149e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com case xa_wrap_mirror_repeat: 150fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return PIPE_TEX_WRAP_MIRROR_REPEAT; 151e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com case xa_wrap_clamp_to_edge: 152e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 153ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com default: 154ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com break; 155ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com } 156fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return PIPE_TEX_WRAP_REPEAT; 157e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com} 158e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com 159e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.comstatic INLINE boolean 160ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.comxa_filter_to_gallium(int xrender_filter, int *out_filter) 161e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com{ 162fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 163fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com switch (xrender_filter) { 164fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com case xa_filter_nearest: 165e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com *out_filter = PIPE_TEX_FILTER_NEAREST; 166e55f533f4c80818d542c2beac14a37600c3718f8yangsu@google.com break; 167ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com case xa_filter_linear: 168ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com *out_filter = PIPE_TEX_FILTER_LINEAR; 169ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com break; 170ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com default: 171ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com *out_filter = PIPE_TEX_FILTER_NEAREST; 172fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return FALSE; 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 174654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com return TRUE; 175654d72f94c855ceae34db0ee82d92844835c0d29yangsu@google.com} 176fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comxa_is_filter_accelerated(struct xa_picture *pic) 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int filter; 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (pic && !xa_filter_to_gallium(pic->filter, &filter)) 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 183 return 1; 184} 185 186int 187xa_composite_is_accelerated(const struct xa_composite *comp) 188{ 189 struct xa_composite_blend blend; 190 struct xa_picture *src_pic = comp->src; 191 192 if (!xa_is_filter_accelerated(src_pic) || 193 !xa_is_filter_accelerated(comp->mask)) { 194 return 0; 195 } 196 197 198 if (src_pic->src_pict) { 199 if (src_pic->src_pict->type != xa_src_pict_solid_fill) 200 return 0; 201 } 202 203 if (blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) { 204 struct xa_picture *mask = comp->mask; 205 if (mask && mask->component_alpha && 206 xa_format_rgb(xa_surface_format(mask->srf))) { 207 if (blend.alpha_src && blend.rgb_src != PIPE_BLENDFACTOR_ZERO) { 208 return 0; 209 } 210 } 211 212 return 1; 213 } 214 return 0; 215} 216 217static void 218bind_composite_blend_state(struct xa_context *ctx, 219 const struct xa_composite *comp) 220{ 221 struct xa_composite_blend blend_opt; 222 struct pipe_blend_state blend; 223 224 blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst); 225 226 memset(&blend, 0, sizeof(struct pipe_blend_state)); 227 blend.rt[0].blend_enable = 1; 228 blend.rt[0].colormask = PIPE_MASK_RGBA; 229 230 blend.rt[0].rgb_src_factor = blend_opt.rgb_src; 231 blend.rt[0].alpha_src_factor = blend_opt.rgb_src; 232 blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; 233 blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; 234 235 cso_set_blend(ctx->cso, &blend); 236} 237 238static unsigned int 239picture_format_fixups(struct xa_picture *src_pic, 240 struct xa_picture *dst_pic, 241 int mask) 242{ 243 boolean set_alpha = FALSE; 244 boolean swizzle = FALSE; 245 unsigned ret = 0; 246 struct xa_surface *src = src_pic->srf; 247 enum xa_formats src_hw_format, src_pic_format; 248 enum xa_surface_type src_hw_type, src_pic_type; 249 250 src_hw_format = xa_surface_format(src); 251 src_pic_format = src_pic->pict_format; 252 253 if (src_hw_format == src_pic_format) { 254 if (src_pic->pict_format == xa_format_a8) { 255 if (mask) 256 return FS_MASK_LUMINANCE; 257 else if (dst_pic->pict_format != xa_format_a8) { 258 259 /* 260 * if both dst and src are luminance then 261 * we don't want to swizzle the alpha (X) of the 262 * source into W component of the dst because 263 * it will break our destination 264 */ 265 return FS_SRC_LUMINANCE; 266 } 267 } 268 return 0; 269 } 270 271 src_hw_type = xa_format_type(src_hw_format); 272 src_pic_type = xa_format_type(src_pic_format); 273 274 swizzle = ((src_hw_type == xa_type_argb && 275 src_pic_type == xa_type_abgr) || 276 ((src_hw_type == xa_type_abgr && 277 src_pic_type == xa_type_argb))); 278 279 if (!swizzle && (src_hw_type != src_pic_type)) 280 return 0; 281 282 set_alpha = (xa_format_type_is_color(src_hw_type) && 283 xa_format_a(src_hw_type) == 0); 284 285 if (set_alpha) 286 ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; 287 if (swizzle) 288 ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; 289 290 return ret; 291} 292 293static void 294bind_shaders(struct xa_context *ctx, const struct xa_composite *comp) 295{ 296 unsigned vs_traits = 0, fs_traits = 0; 297 struct xa_shader shader; 298 struct xa_picture *src_pic = comp->src; 299 struct xa_picture *mask_pic = comp->mask; 300 struct xa_picture *dst_pic = comp->dst; 301 302 ctx->has_solid_color = FALSE; 303 304 if (src_pic) { 305 if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) 306 fs_traits |= FS_SRC_REPEAT_NONE; 307 308 if (src_pic->src_pict) { 309 if (src_pic->src_pict->type == xa_src_pict_solid_fill) { 310 fs_traits |= FS_SOLID_FILL; 311 vs_traits |= VS_SOLID_FILL; 312 xa_pixel_to_float4(src_pic->src_pict->solid_fill.color, 313 ctx->solid_color); 314 ctx->has_solid_color = TRUE; 315 } 316 } else { 317 fs_traits |= FS_COMPOSITE; 318 vs_traits |= VS_COMPOSITE; 319 } 320 321 fs_traits |= picture_format_fixups(src_pic, dst_pic, 0); 322 } 323 324 if (mask_pic) { 325 vs_traits |= VS_MASK; 326 fs_traits |= FS_MASK; 327 if (mask_pic->wrap == xa_wrap_clamp_to_border && 328 mask_pic->has_transform) 329 fs_traits |= FS_MASK_REPEAT_NONE; 330 331 if (mask_pic->component_alpha) { 332 struct xa_composite_blend blend; 333 blend_for_op(&blend, comp->op, src_pic, mask_pic, NULL); 334 if (blend.alpha_src) { 335 fs_traits |= FS_CA_SRCALPHA; 336 } else 337 fs_traits |= FS_CA_FULL; 338 } 339 340 fs_traits |= picture_format_fixups(mask_pic, dst_pic, 1); 341 } 342 343 shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); 344 cso_set_vertex_shader_handle(ctx->cso, shader.vs); 345 cso_set_fragment_shader_handle(ctx->cso, shader.fs); 346} 347 348static void 349bind_samplers(struct xa_context *ctx, 350 const struct xa_composite *comp) 351{ 352 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 353 struct pipe_sampler_state src_sampler, mask_sampler; 354 struct pipe_sampler_view view_templ; 355 struct pipe_sampler_view *src_view; 356 struct pipe_context *pipe = ctx->pipe; 357 struct xa_picture *src_pic = comp->src; 358 struct xa_picture *mask_pic = comp->mask; 359 360 ctx->num_bound_samplers = 0; 361 362 memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); 363 memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); 364 365 if (src_pic) { 366 if (ctx->has_solid_color) { 367 samplers[0] = NULL; 368 pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); 369 } else { 370 unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); 371 int filter; 372 373 (void) xa_filter_to_gallium(src_pic->filter, &filter); 374 375 src_sampler.wrap_s = src_wrap; 376 src_sampler.wrap_t = src_wrap; 377 src_sampler.min_img_filter = filter; 378 src_sampler.mag_img_filter = filter; 379 src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 380 src_sampler.normalized_coords = 1; 381 samplers[0] = &src_sampler; 382 ctx->num_bound_samplers = 1; 383 u_sampler_view_default_template(&view_templ, 384 src_pic->srf->tex, 385 src_pic->srf->tex->format); 386 src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, 387 &view_templ); 388 pipe_sampler_view_reference(&ctx->bound_sampler_views[0], NULL); 389 ctx->bound_sampler_views[0] = src_view; 390 } 391 } 392 393 if (mask_pic) { 394 unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); 395 int filter; 396 397 (void) xa_filter_to_gallium(mask_pic->filter, &filter); 398 399 mask_sampler.wrap_s = mask_wrap; 400 mask_sampler.wrap_t = mask_wrap; 401 mask_sampler.min_img_filter = filter; 402 mask_sampler.mag_img_filter = filter; 403 src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 404 mask_sampler.normalized_coords = 1; 405 samplers[1] = &mask_sampler; 406 ctx->num_bound_samplers = 2; 407 u_sampler_view_default_template(&view_templ, 408 mask_pic->srf->tex, 409 mask_pic->srf->tex->format); 410 src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, 411 &view_templ); 412 pipe_sampler_view_reference(&ctx->bound_sampler_views[1], NULL); 413 ctx->bound_sampler_views[1] = src_view; 414 } 415 416 cso_set_samplers(ctx->cso, ctx->num_bound_samplers, 417 (const struct pipe_sampler_state **)samplers); 418 cso_set_fragment_sampler_views(ctx->cso, ctx->num_bound_samplers, 419 ctx->bound_sampler_views); 420} 421 422int 423xa_composite_prepare(struct xa_context *ctx, 424 const struct xa_composite *comp) 425{ 426 struct xa_surface *dst_srf = comp->dst->srf; 427 int ret; 428 429 ret = xa_surface_psurf_create(ctx, dst_srf); 430 if (ret != XA_ERR_NONE) 431 return ret; 432 433 renderer_bind_destination(ctx, dst_srf->srf, 434 dst_srf->srf->width, 435 dst_srf->srf->height); 436 437 bind_composite_blend_state(ctx, comp); 438 bind_shaders(ctx, comp); 439 bind_samplers(ctx, comp); 440 441 if (ctx->num_bound_samplers == 0 ) { /* solid fill */ 442 renderer_begin_solid(ctx); 443 } else { 444 renderer_begin_textures(ctx); 445 } 446 447 xa_surface_psurf_destroy(dst_srf); 448 return XA_ERR_NONE; 449} 450 451void xa_composite_rect(struct xa_context *ctx, 452 int srcX, int srcY, int maskX, int maskY, 453 int dstX, int dstY, int width, int height) 454{ 455 if (ctx->num_bound_samplers == 0 ) { /* solid fill */ 456 renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height, 457 ctx->solid_color); 458 } else { 459 const struct xa_composite *comp = ctx->comp; 460 int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; 461 const float *src_matrix = NULL; 462 const float *mask_matrix = NULL; 463 464 if (comp->src->has_transform) 465 src_matrix = comp->src->transform; 466 if (comp->mask->has_transform) 467 mask_matrix = comp->mask->transform; 468 469 renderer_texture(ctx, pos, width, height, 470 src_matrix, mask_matrix); 471 } 472} 473 474void 475xa_composite_done(struct xa_context *ctx) 476{ 477 renderer_draw_flush(ctx); 478 ctx->pipe->flush(ctx->pipe, &ctx->last_fence); 479 480 ctx->comp = NULL; 481 ctx->has_solid_color = FALSE; 482 ctx->num_bound_samplers = 0; 483} 484 485static const struct xa_composite_allocation a = { 486 .xa_composite_size = sizeof(struct xa_composite), 487 .xa_picture_size = sizeof(struct xa_picture), 488 .xa_source_pict_size = sizeof(union xa_source_pict), 489}; 490 491const struct xa_composite_allocation * 492xa_composite_allocation(void) 493{ 494 return &a; 495} 496