1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2009-2011 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci ********************************************************* 25bf215546Sopenharmony_ci * Authors: 26bf215546Sopenharmony_ci * Zack Rusin <zackr-at-vmware-dot-com> 27bf215546Sopenharmony_ci * Thomas Hellstrom <thellstrom-at-vmware-dot-com> 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "xa_composite.h" 31bf215546Sopenharmony_ci#include "xa_context.h" 32bf215546Sopenharmony_ci#include "xa_priv.h" 33bf215546Sopenharmony_ci#include "cso_cache/cso_context.h" 34bf215546Sopenharmony_ci#include "util/u_sampler.h" 35bf215546Sopenharmony_ci#include "util/u_inlines.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci/*XXX also in Xrender.h but the including it here breaks compilition */ 39bf215546Sopenharmony_ci#define XFixedToDouble(f) (((double) (f)) / 65536.) 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistruct xa_composite_blend { 42bf215546Sopenharmony_ci unsigned op : 8; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci unsigned alpha_dst : 4; 45bf215546Sopenharmony_ci unsigned alpha_src : 4; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci unsigned rgb_src : 8; /**< PIPE_BLENDFACTOR_x */ 48bf215546Sopenharmony_ci unsigned rgb_dst : 8; /**< PIPE_BLENDFACTOR_x */ 49bf215546Sopenharmony_ci}; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci#define XA_BLEND_OP_OVER 3 52bf215546Sopenharmony_cistatic const struct xa_composite_blend xa_blends[] = { 53bf215546Sopenharmony_ci { xa_op_clear, 54bf215546Sopenharmony_ci 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO}, 55bf215546Sopenharmony_ci { xa_op_src, 56bf215546Sopenharmony_ci 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO}, 57bf215546Sopenharmony_ci { xa_op_dst, 58bf215546Sopenharmony_ci 0, 0, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ONE}, 59bf215546Sopenharmony_ci { xa_op_over, 60bf215546Sopenharmony_ci 0, 1, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 61bf215546Sopenharmony_ci { xa_op_over_reverse, 62bf215546Sopenharmony_ci 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ONE}, 63bf215546Sopenharmony_ci { xa_op_in, 64bf215546Sopenharmony_ci 1, 0, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, 65bf215546Sopenharmony_ci { xa_op_in_reverse, 66bf215546Sopenharmony_ci 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_SRC_ALPHA}, 67bf215546Sopenharmony_ci { xa_op_out, 68bf215546Sopenharmony_ci 1, 0, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_ZERO}, 69bf215546Sopenharmony_ci { xa_op_out_reverse, 70bf215546Sopenharmony_ci 0, 1, PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 71bf215546Sopenharmony_ci { xa_op_atop, 72bf215546Sopenharmony_ci 1, 1, PIPE_BLENDFACTOR_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 73bf215546Sopenharmony_ci { xa_op_atop_reverse, 74bf215546Sopenharmony_ci 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_SRC_ALPHA}, 75bf215546Sopenharmony_ci { xa_op_xor, 76bf215546Sopenharmony_ci 1, 1, PIPE_BLENDFACTOR_INV_DST_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA}, 77bf215546Sopenharmony_ci { xa_op_add, 78bf215546Sopenharmony_ci 0, 0, PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE}, 79bf215546Sopenharmony_ci}; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci/* 82bf215546Sopenharmony_ci * The alpha value stored in a L8 texture is read by the 83bf215546Sopenharmony_ci * hardware as color, and R8 is read as red. The source alpha value 84bf215546Sopenharmony_ci * at the end of the fragment shader is stored in all color channels, 85bf215546Sopenharmony_ci * so the correct approach is to blend using DST_COLOR instead of 86bf215546Sopenharmony_ci * DST_ALPHA and then output any color channel (L8) or the red channel (R8). 87bf215546Sopenharmony_ci */ 88bf215546Sopenharmony_cistatic unsigned 89bf215546Sopenharmony_cixa_convert_blend_for_luminance(unsigned factor) 90bf215546Sopenharmony_ci{ 91bf215546Sopenharmony_ci switch(factor) { 92bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_DST_ALPHA: 93bf215546Sopenharmony_ci return PIPE_BLENDFACTOR_DST_COLOR; 94bf215546Sopenharmony_ci case PIPE_BLENDFACTOR_INV_DST_ALPHA: 95bf215546Sopenharmony_ci return PIPE_BLENDFACTOR_INV_DST_COLOR; 96bf215546Sopenharmony_ci default: 97bf215546Sopenharmony_ci break; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci return factor; 100bf215546Sopenharmony_ci} 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cistatic boolean 103bf215546Sopenharmony_ciblend_for_op(struct xa_composite_blend *blend, 104bf215546Sopenharmony_ci enum xa_composite_op op, 105bf215546Sopenharmony_ci struct xa_picture *src_pic, 106bf215546Sopenharmony_ci struct xa_picture *mask_pic, 107bf215546Sopenharmony_ci struct xa_picture *dst_pic) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci const int num_blends = 110bf215546Sopenharmony_ci sizeof(xa_blends)/sizeof(struct xa_composite_blend); 111bf215546Sopenharmony_ci int i; 112bf215546Sopenharmony_ci boolean supported = FALSE; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci /* 115bf215546Sopenharmony_ci * our default in case something goes wrong 116bf215546Sopenharmony_ci */ 117bf215546Sopenharmony_ci *blend = xa_blends[XA_BLEND_OP_OVER]; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci for (i = 0; i < num_blends; ++i) { 120bf215546Sopenharmony_ci if (xa_blends[i].op == op) { 121bf215546Sopenharmony_ci *blend = xa_blends[i]; 122bf215546Sopenharmony_ci supported = TRUE; 123bf215546Sopenharmony_ci break; 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci /* 128bf215546Sopenharmony_ci * No component alpha yet. 129bf215546Sopenharmony_ci */ 130bf215546Sopenharmony_ci if (mask_pic && mask_pic->component_alpha && blend->alpha_src) 131bf215546Sopenharmony_ci return FALSE; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci if (!dst_pic->srf) 134bf215546Sopenharmony_ci return supported; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci if ((dst_pic->srf->tex->format == PIPE_FORMAT_L8_UNORM || 137bf215546Sopenharmony_ci dst_pic->srf->tex->format == PIPE_FORMAT_R8_UNORM)) { 138bf215546Sopenharmony_ci blend->rgb_src = xa_convert_blend_for_luminance(blend->rgb_src); 139bf215546Sopenharmony_ci blend->rgb_dst = xa_convert_blend_for_luminance(blend->rgb_dst); 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci /* 143bf215546Sopenharmony_ci * If there's no dst alpha channel, adjust the blend op so that we'll treat 144bf215546Sopenharmony_ci * it as always 1. 145bf215546Sopenharmony_ci */ 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci if (xa_format_a(dst_pic->pict_format) == 0 && blend->alpha_dst) { 148bf215546Sopenharmony_ci if (blend->rgb_src == PIPE_BLENDFACTOR_DST_ALPHA) 149bf215546Sopenharmony_ci blend->rgb_src = PIPE_BLENDFACTOR_ONE; 150bf215546Sopenharmony_ci else if (blend->rgb_src == PIPE_BLENDFACTOR_INV_DST_ALPHA) 151bf215546Sopenharmony_ci blend->rgb_src = PIPE_BLENDFACTOR_ZERO; 152bf215546Sopenharmony_ci } 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci return supported; 155bf215546Sopenharmony_ci} 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_cistatic inline int 159bf215546Sopenharmony_cixa_repeat_to_gallium(int mode) 160bf215546Sopenharmony_ci{ 161bf215546Sopenharmony_ci switch(mode) { 162bf215546Sopenharmony_ci case xa_wrap_clamp_to_border: 163bf215546Sopenharmony_ci return PIPE_TEX_WRAP_CLAMP_TO_BORDER; 164bf215546Sopenharmony_ci case xa_wrap_repeat: 165bf215546Sopenharmony_ci return PIPE_TEX_WRAP_REPEAT; 166bf215546Sopenharmony_ci case xa_wrap_mirror_repeat: 167bf215546Sopenharmony_ci return PIPE_TEX_WRAP_MIRROR_REPEAT; 168bf215546Sopenharmony_ci case xa_wrap_clamp_to_edge: 169bf215546Sopenharmony_ci return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 170bf215546Sopenharmony_ci default: 171bf215546Sopenharmony_ci break; 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci return PIPE_TEX_WRAP_REPEAT; 174bf215546Sopenharmony_ci} 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_cistatic inline boolean 177bf215546Sopenharmony_cixa_filter_to_gallium(int xrender_filter, int *out_filter) 178bf215546Sopenharmony_ci{ 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci switch (xrender_filter) { 181bf215546Sopenharmony_ci case xa_filter_nearest: 182bf215546Sopenharmony_ci *out_filter = PIPE_TEX_FILTER_NEAREST; 183bf215546Sopenharmony_ci break; 184bf215546Sopenharmony_ci case xa_filter_linear: 185bf215546Sopenharmony_ci *out_filter = PIPE_TEX_FILTER_LINEAR; 186bf215546Sopenharmony_ci break; 187bf215546Sopenharmony_ci default: 188bf215546Sopenharmony_ci *out_filter = PIPE_TEX_FILTER_NEAREST; 189bf215546Sopenharmony_ci return FALSE; 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci return TRUE; 192bf215546Sopenharmony_ci} 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_cistatic int 195bf215546Sopenharmony_cixa_is_filter_accelerated(struct xa_picture *pic) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci int filter; 198bf215546Sopenharmony_ci if (pic && !xa_filter_to_gallium(pic->filter, &filter)) 199bf215546Sopenharmony_ci return 0; 200bf215546Sopenharmony_ci return 1; 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci/** 204bf215546Sopenharmony_ci * xa_src_pict_is_accelerated - Check whether we support acceleration 205bf215546Sopenharmony_ci * of the given src_pict type 206bf215546Sopenharmony_ci * 207bf215546Sopenharmony_ci * \param src_pic[in]: Pointer to a union xa_source_pict to check. 208bf215546Sopenharmony_ci * 209bf215546Sopenharmony_ci * \returns TRUE if accelerated, FALSE otherwise. 210bf215546Sopenharmony_ci */ 211bf215546Sopenharmony_cistatic boolean 212bf215546Sopenharmony_cixa_src_pict_is_accelerated(const union xa_source_pict *src_pic) 213bf215546Sopenharmony_ci{ 214bf215546Sopenharmony_ci if (!src_pic) 215bf215546Sopenharmony_ci return TRUE; 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci if (src_pic->type == xa_src_pict_solid_fill || 218bf215546Sopenharmony_ci src_pic->type == xa_src_pict_float_solid_fill) 219bf215546Sopenharmony_ci return TRUE; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci return FALSE; 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ciXA_EXPORT int 225bf215546Sopenharmony_cixa_composite_check_accelerated(const struct xa_composite *comp) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci struct xa_picture *src_pic = comp->src; 228bf215546Sopenharmony_ci struct xa_picture *mask_pic = comp->mask; 229bf215546Sopenharmony_ci struct xa_composite_blend blend; 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (!xa_is_filter_accelerated(src_pic) || 232bf215546Sopenharmony_ci !xa_is_filter_accelerated(comp->mask)) { 233bf215546Sopenharmony_ci return -XA_ERR_INVAL; 234bf215546Sopenharmony_ci } 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci if (!xa_src_pict_is_accelerated(src_pic->src_pict) || 237bf215546Sopenharmony_ci (mask_pic && !xa_src_pict_is_accelerated(mask_pic->src_pict))) 238bf215546Sopenharmony_ci return -XA_ERR_INVAL; 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci if (!blend_for_op(&blend, comp->op, comp->src, comp->mask, comp->dst)) 241bf215546Sopenharmony_ci return -XA_ERR_INVAL; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci /* 244bf215546Sopenharmony_ci * No component alpha yet. 245bf215546Sopenharmony_ci */ 246bf215546Sopenharmony_ci if (mask_pic && mask_pic->component_alpha && blend.alpha_src) 247bf215546Sopenharmony_ci return -XA_ERR_INVAL; 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci return XA_ERR_NONE; 250bf215546Sopenharmony_ci} 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_cistatic int 253bf215546Sopenharmony_cibind_composite_blend_state(struct xa_context *ctx, 254bf215546Sopenharmony_ci const struct xa_composite *comp) 255bf215546Sopenharmony_ci{ 256bf215546Sopenharmony_ci struct xa_composite_blend blend_opt; 257bf215546Sopenharmony_ci struct pipe_blend_state blend; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci if (!blend_for_op(&blend_opt, comp->op, comp->src, comp->mask, comp->dst)) 260bf215546Sopenharmony_ci return -XA_ERR_INVAL; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci memset(&blend, 0, sizeof(struct pipe_blend_state)); 263bf215546Sopenharmony_ci blend.rt[0].blend_enable = 1; 264bf215546Sopenharmony_ci blend.rt[0].colormask = PIPE_MASK_RGBA; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci blend.rt[0].rgb_src_factor = blend_opt.rgb_src; 267bf215546Sopenharmony_ci blend.rt[0].alpha_src_factor = blend_opt.rgb_src; 268bf215546Sopenharmony_ci blend.rt[0].rgb_dst_factor = blend_opt.rgb_dst; 269bf215546Sopenharmony_ci blend.rt[0].alpha_dst_factor = blend_opt.rgb_dst; 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci cso_set_blend(ctx->cso, &blend); 272bf215546Sopenharmony_ci return XA_ERR_NONE; 273bf215546Sopenharmony_ci} 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_cistatic unsigned int 276bf215546Sopenharmony_cipicture_format_fixups(struct xa_picture *src_pic, 277bf215546Sopenharmony_ci int mask) 278bf215546Sopenharmony_ci{ 279bf215546Sopenharmony_ci boolean set_alpha = FALSE; 280bf215546Sopenharmony_ci boolean swizzle = FALSE; 281bf215546Sopenharmony_ci unsigned ret = 0; 282bf215546Sopenharmony_ci struct xa_surface *src = src_pic->srf; 283bf215546Sopenharmony_ci enum xa_formats src_hw_format, src_pic_format; 284bf215546Sopenharmony_ci enum xa_surface_type src_hw_type, src_pic_type; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci if (!src) 287bf215546Sopenharmony_ci return 0; 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci src_hw_format = xa_surface_format(src); 290bf215546Sopenharmony_ci src_pic_format = src_pic->pict_format; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci set_alpha = (xa_format_type_is_color(src_hw_format) && 293bf215546Sopenharmony_ci xa_format_a(src_pic_format) == 0); 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci if (set_alpha) 296bf215546Sopenharmony_ci ret |= mask ? FS_MASK_SET_ALPHA : FS_SRC_SET_ALPHA; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci if (src_hw_format == src_pic_format) { 299bf215546Sopenharmony_ci if (src->tex->format == PIPE_FORMAT_L8_UNORM || 300bf215546Sopenharmony_ci src->tex->format == PIPE_FORMAT_R8_UNORM) 301bf215546Sopenharmony_ci return ((mask) ? FS_MASK_LUMINANCE : FS_SRC_LUMINANCE); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci return ret; 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci src_hw_type = xa_format_type(src_hw_format); 307bf215546Sopenharmony_ci src_pic_type = xa_format_type(src_pic_format); 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci swizzle = ((src_hw_type == xa_type_argb && 310bf215546Sopenharmony_ci src_pic_type == xa_type_abgr) || 311bf215546Sopenharmony_ci ((src_hw_type == xa_type_abgr && 312bf215546Sopenharmony_ci src_pic_type == xa_type_argb))); 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci if (!swizzle && (src_hw_type != src_pic_type)) 315bf215546Sopenharmony_ci return ret; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci if (swizzle) 318bf215546Sopenharmony_ci ret |= mask ? FS_MASK_SWIZZLE_RGB : FS_SRC_SWIZZLE_RGB; 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci return ret; 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_cistatic void 324bf215546Sopenharmony_cixa_src_in_mask(float src[4], const float mask[4]) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci src[0] *= mask[3]; 327bf215546Sopenharmony_ci src[1] *= mask[3]; 328bf215546Sopenharmony_ci src[2] *= mask[3]; 329bf215546Sopenharmony_ci src[3] *= mask[3]; 330bf215546Sopenharmony_ci} 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci/** 333bf215546Sopenharmony_ci * xa_handle_src_pict - Set up xa_context state and fragment shader 334bf215546Sopenharmony_ci * input based on scr_pict type 335bf215546Sopenharmony_ci * 336bf215546Sopenharmony_ci * \param ctx[in, out]: Pointer to the xa context. 337bf215546Sopenharmony_ci * \param src_pict[in]: Pointer to the union xa_source_pict to consider. 338bf215546Sopenharmony_ci * \param is_mask[in]: Whether we're considering a mask picture. 339bf215546Sopenharmony_ci * 340bf215546Sopenharmony_ci * \returns TRUE if succesful, FALSE otherwise. 341bf215546Sopenharmony_ci * 342bf215546Sopenharmony_ci * This function computes some xa_context state used to determine whether 343bf215546Sopenharmony_ci * to upload the solid color and also the solid color itself used as an input 344bf215546Sopenharmony_ci * to the fragment shader. 345bf215546Sopenharmony_ci */ 346bf215546Sopenharmony_cistatic boolean 347bf215546Sopenharmony_cixa_handle_src_pict(struct xa_context *ctx, 348bf215546Sopenharmony_ci const union xa_source_pict *src_pict, 349bf215546Sopenharmony_ci boolean is_mask) 350bf215546Sopenharmony_ci{ 351bf215546Sopenharmony_ci float solid_color[4]; 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci switch(src_pict->type) { 354bf215546Sopenharmony_ci case xa_src_pict_solid_fill: 355bf215546Sopenharmony_ci xa_pixel_to_float4(src_pict->solid_fill.color, solid_color); 356bf215546Sopenharmony_ci break; 357bf215546Sopenharmony_ci case xa_src_pict_float_solid_fill: 358bf215546Sopenharmony_ci memcpy(solid_color, src_pict->float_solid_fill.color, 359bf215546Sopenharmony_ci sizeof(solid_color)); 360bf215546Sopenharmony_ci break; 361bf215546Sopenharmony_ci default: 362bf215546Sopenharmony_ci return FALSE; 363bf215546Sopenharmony_ci } 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci if (is_mask && ctx->has_solid_src) 366bf215546Sopenharmony_ci xa_src_in_mask(ctx->solid_color, solid_color); 367bf215546Sopenharmony_ci else 368bf215546Sopenharmony_ci memcpy(ctx->solid_color, solid_color, sizeof(solid_color)); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci if (is_mask) 371bf215546Sopenharmony_ci ctx->has_solid_mask = TRUE; 372bf215546Sopenharmony_ci else 373bf215546Sopenharmony_ci ctx->has_solid_src = TRUE; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci return TRUE; 376bf215546Sopenharmony_ci} 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_cistatic int 379bf215546Sopenharmony_cibind_shaders(struct xa_context *ctx, const struct xa_composite *comp) 380bf215546Sopenharmony_ci{ 381bf215546Sopenharmony_ci unsigned vs_traits = 0, fs_traits = 0; 382bf215546Sopenharmony_ci struct xa_shader shader; 383bf215546Sopenharmony_ci struct xa_picture *src_pic = comp->src; 384bf215546Sopenharmony_ci struct xa_picture *mask_pic = comp->mask; 385bf215546Sopenharmony_ci struct xa_picture *dst_pic = comp->dst; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci ctx->has_solid_src = FALSE; 388bf215546Sopenharmony_ci ctx->has_solid_mask = FALSE; 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci if (dst_pic && xa_format_type(dst_pic->pict_format) != 391bf215546Sopenharmony_ci xa_format_type(xa_surface_format(dst_pic->srf))) 392bf215546Sopenharmony_ci return -XA_ERR_INVAL; 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci if (src_pic) { 395bf215546Sopenharmony_ci if (src_pic->wrap == xa_wrap_clamp_to_border && src_pic->has_transform) 396bf215546Sopenharmony_ci fs_traits |= FS_SRC_REPEAT_NONE; 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci fs_traits |= FS_COMPOSITE; 399bf215546Sopenharmony_ci vs_traits |= VS_COMPOSITE; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci if (src_pic->src_pict) { 402bf215546Sopenharmony_ci if (!xa_handle_src_pict(ctx, src_pic->src_pict, false)) 403bf215546Sopenharmony_ci return -XA_ERR_INVAL; 404bf215546Sopenharmony_ci fs_traits |= FS_SRC_SRC; 405bf215546Sopenharmony_ci vs_traits |= VS_SRC_SRC; 406bf215546Sopenharmony_ci } else 407bf215546Sopenharmony_ci fs_traits |= picture_format_fixups(src_pic, 0); 408bf215546Sopenharmony_ci } 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci if (mask_pic) { 411bf215546Sopenharmony_ci vs_traits |= VS_MASK; 412bf215546Sopenharmony_ci fs_traits |= FS_MASK; 413bf215546Sopenharmony_ci if (mask_pic->component_alpha) 414bf215546Sopenharmony_ci fs_traits |= FS_CA; 415bf215546Sopenharmony_ci if (mask_pic->src_pict) { 416bf215546Sopenharmony_ci if (!xa_handle_src_pict(ctx, mask_pic->src_pict, true)) 417bf215546Sopenharmony_ci return -XA_ERR_INVAL; 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci if (ctx->has_solid_src) { 420bf215546Sopenharmony_ci vs_traits &= ~VS_MASK; 421bf215546Sopenharmony_ci fs_traits &= ~FS_MASK; 422bf215546Sopenharmony_ci } else { 423bf215546Sopenharmony_ci vs_traits |= VS_MASK_SRC; 424bf215546Sopenharmony_ci fs_traits |= FS_MASK_SRC; 425bf215546Sopenharmony_ci } 426bf215546Sopenharmony_ci } else { 427bf215546Sopenharmony_ci if (mask_pic->wrap == xa_wrap_clamp_to_border && 428bf215546Sopenharmony_ci mask_pic->has_transform) 429bf215546Sopenharmony_ci fs_traits |= FS_MASK_REPEAT_NONE; 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci fs_traits |= picture_format_fixups(mask_pic, 1); 432bf215546Sopenharmony_ci } 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci if (ctx->srf->format == PIPE_FORMAT_L8_UNORM || 436bf215546Sopenharmony_ci ctx->srf->format == PIPE_FORMAT_R8_UNORM) 437bf215546Sopenharmony_ci fs_traits |= FS_DST_LUMINANCE; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci shader = xa_shaders_get(ctx->shaders, vs_traits, fs_traits); 440bf215546Sopenharmony_ci cso_set_vertex_shader_handle(ctx->cso, shader.vs); 441bf215546Sopenharmony_ci cso_set_fragment_shader_handle(ctx->cso, shader.fs); 442bf215546Sopenharmony_ci return XA_ERR_NONE; 443bf215546Sopenharmony_ci} 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_cistatic void 446bf215546Sopenharmony_cibind_samplers(struct xa_context *ctx, 447bf215546Sopenharmony_ci const struct xa_composite *comp) 448bf215546Sopenharmony_ci{ 449bf215546Sopenharmony_ci struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 450bf215546Sopenharmony_ci struct pipe_sampler_state src_sampler, mask_sampler; 451bf215546Sopenharmony_ci struct pipe_sampler_view view_templ; 452bf215546Sopenharmony_ci struct pipe_sampler_view *src_view; 453bf215546Sopenharmony_ci struct pipe_context *pipe = ctx->pipe; 454bf215546Sopenharmony_ci struct xa_picture *src_pic = comp->src; 455bf215546Sopenharmony_ci struct xa_picture *mask_pic = comp->mask; 456bf215546Sopenharmony_ci int num_samplers = 0; 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci xa_ctx_sampler_views_destroy(ctx); 459bf215546Sopenharmony_ci memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); 460bf215546Sopenharmony_ci memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci if (src_pic && !ctx->has_solid_src) { 463bf215546Sopenharmony_ci unsigned src_wrap = xa_repeat_to_gallium(src_pic->wrap); 464bf215546Sopenharmony_ci int filter; 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci (void) xa_filter_to_gallium(src_pic->filter, &filter); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci src_sampler.wrap_s = src_wrap; 469bf215546Sopenharmony_ci src_sampler.wrap_t = src_wrap; 470bf215546Sopenharmony_ci src_sampler.min_img_filter = filter; 471bf215546Sopenharmony_ci src_sampler.mag_img_filter = filter; 472bf215546Sopenharmony_ci src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 473bf215546Sopenharmony_ci src_sampler.normalized_coords = 1; 474bf215546Sopenharmony_ci samplers[0] = &src_sampler; 475bf215546Sopenharmony_ci u_sampler_view_default_template(&view_templ, 476bf215546Sopenharmony_ci src_pic->srf->tex,+ src_pic->srf->tex->format); 477bf215546Sopenharmony_ci src_view = pipe->create_sampler_view(pipe, src_pic->srf->tex, 478bf215546Sopenharmony_ci &view_templ); 479bf215546Sopenharmony_ci ctx->bound_sampler_views[0] = src_view; 480bf215546Sopenharmony_ci num_samplers++; 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci if (mask_pic && !ctx->has_solid_mask) { 484bf215546Sopenharmony_ci unsigned mask_wrap = xa_repeat_to_gallium(mask_pic->wrap); 485bf215546Sopenharmony_ci int filter; 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci (void) xa_filter_to_gallium(mask_pic->filter, &filter); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci mask_sampler.wrap_s = mask_wrap; 490bf215546Sopenharmony_ci mask_sampler.wrap_t = mask_wrap; 491bf215546Sopenharmony_ci mask_sampler.min_img_filter = filter; 492bf215546Sopenharmony_ci mask_sampler.mag_img_filter = filter; 493bf215546Sopenharmony_ci src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; 494bf215546Sopenharmony_ci mask_sampler.normalized_coords = 1; 495bf215546Sopenharmony_ci samplers[num_samplers] = &mask_sampler; 496bf215546Sopenharmony_ci u_sampler_view_default_template(&view_templ, 497bf215546Sopenharmony_ci mask_pic->srf->tex, 498bf215546Sopenharmony_ci mask_pic->srf->tex->format); 499bf215546Sopenharmony_ci src_view = pipe->create_sampler_view(pipe, mask_pic->srf->tex, 500bf215546Sopenharmony_ci &view_templ); 501bf215546Sopenharmony_ci ctx->bound_sampler_views[num_samplers] = src_view; 502bf215546Sopenharmony_ci num_samplers++; 503bf215546Sopenharmony_ci } 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci cso_set_samplers(ctx->cso, PIPE_SHADER_FRAGMENT, num_samplers, 506bf215546Sopenharmony_ci (const struct pipe_sampler_state **)samplers); 507bf215546Sopenharmony_ci pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num_samplers, 0, 508bf215546Sopenharmony_ci false, ctx->bound_sampler_views); 509bf215546Sopenharmony_ci ctx->num_bound_samplers = num_samplers; 510bf215546Sopenharmony_ci} 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ciXA_EXPORT int 513bf215546Sopenharmony_cixa_composite_prepare(struct xa_context *ctx, 514bf215546Sopenharmony_ci const struct xa_composite *comp) 515bf215546Sopenharmony_ci{ 516bf215546Sopenharmony_ci struct xa_surface *dst_srf = comp->dst->srf; 517bf215546Sopenharmony_ci int ret; 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci ret = xa_ctx_srf_create(ctx, dst_srf); 520bf215546Sopenharmony_ci if (ret != XA_ERR_NONE) 521bf215546Sopenharmony_ci return ret; 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci ctx->dst = dst_srf; 524bf215546Sopenharmony_ci renderer_bind_destination(ctx, ctx->srf); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci ret = bind_composite_blend_state(ctx, comp); 527bf215546Sopenharmony_ci if (ret != XA_ERR_NONE) 528bf215546Sopenharmony_ci return ret; 529bf215546Sopenharmony_ci ret = bind_shaders(ctx, comp); 530bf215546Sopenharmony_ci if (ret != XA_ERR_NONE) 531bf215546Sopenharmony_ci return ret; 532bf215546Sopenharmony_ci bind_samplers(ctx, comp); 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci if (ctx->num_bound_samplers == 0 ) { /* solid fill */ 535bf215546Sopenharmony_ci renderer_begin_solid(ctx); 536bf215546Sopenharmony_ci } else { 537bf215546Sopenharmony_ci renderer_begin_textures(ctx); 538bf215546Sopenharmony_ci ctx->comp = comp; 539bf215546Sopenharmony_ci } 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci xa_ctx_srf_destroy(ctx); 542bf215546Sopenharmony_ci return XA_ERR_NONE; 543bf215546Sopenharmony_ci} 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ciXA_EXPORT void 546bf215546Sopenharmony_cixa_composite_rect(struct xa_context *ctx, 547bf215546Sopenharmony_ci int srcX, int srcY, int maskX, int maskY, 548bf215546Sopenharmony_ci int dstX, int dstY, int width, int height) 549bf215546Sopenharmony_ci{ 550bf215546Sopenharmony_ci if (ctx->num_bound_samplers == 0 ) { /* solid fill */ 551bf215546Sopenharmony_ci xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); 552bf215546Sopenharmony_ci renderer_solid(ctx, dstX, dstY, dstX + width, dstY + height); 553bf215546Sopenharmony_ci } else { 554bf215546Sopenharmony_ci const struct xa_composite *comp = ctx->comp; 555bf215546Sopenharmony_ci int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY}; 556bf215546Sopenharmony_ci const float *src_matrix = NULL; 557bf215546Sopenharmony_ci const float *mask_matrix = NULL; 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci xa_scissor_update(ctx, dstX, dstY, dstX + width, dstY + height); 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci if (comp->src->has_transform) 562bf215546Sopenharmony_ci src_matrix = comp->src->transform; 563bf215546Sopenharmony_ci if (comp->mask && comp->mask->has_transform) 564bf215546Sopenharmony_ci mask_matrix = comp->mask->transform; 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci renderer_texture(ctx, pos, width, height, 567bf215546Sopenharmony_ci src_matrix, mask_matrix); 568bf215546Sopenharmony_ci } 569bf215546Sopenharmony_ci} 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ciXA_EXPORT void 572bf215546Sopenharmony_cixa_composite_done(struct xa_context *ctx) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci renderer_draw_flush(ctx); 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci ctx->comp = NULL; 577bf215546Sopenharmony_ci ctx->has_solid_src = FALSE; 578bf215546Sopenharmony_ci ctx->has_solid_mask = FALSE; 579bf215546Sopenharmony_ci xa_ctx_sampler_views_destroy(ctx); 580bf215546Sopenharmony_ci} 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_cistatic const struct xa_composite_allocation a = { 583bf215546Sopenharmony_ci .xa_composite_size = sizeof(struct xa_composite), 584bf215546Sopenharmony_ci .xa_picture_size = sizeof(struct xa_picture), 585bf215546Sopenharmony_ci .xa_source_pict_size = sizeof(union xa_source_pict), 586bf215546Sopenharmony_ci}; 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ciXA_EXPORT const struct xa_composite_allocation * 589bf215546Sopenharmony_cixa_composite_allocation(void) 590bf215546Sopenharmony_ci{ 591bf215546Sopenharmony_ci return &a; 592bf215546Sopenharmony_ci} 593