1 /********************************************************** 2 * Copyright 2009-2011 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 ********************************************************* 25 * Authors: 26 * Zack Rusin <zackr-at-vmware-dot-com> 27 */ 28 #include "xa_priv.h" 29 30 #include "pipe/p_format.h" 31 #include "pipe/p_context.h" 32 #include "pipe/p_state.h" 33 #include "pipe/p_shader_tokens.h" 34 35 #include "util/u_memory.h" 36 37 #include "tgsi/tgsi_ureg.h" 38 39 #include "cso_cache/cso_context.h" 40 #include "cso_cache/cso_hash.h" 41 42 /* Vertex shader: 43 * IN[0] = vertex pos 44 * IN[1] = src tex coord | solid fill color 45 * IN[2] = mask tex coord 46 * IN[3] = dst tex coord 47 * CONST[0] = (2/dst_width, 2/dst_height, 1, 1) 48 * CONST[1] = (-1, -1, 0, 0) 49 * 50 * OUT[0] = vertex pos 51 * OUT[1] = src tex coord | solid fill color 52 * OUT[2] = mask tex coord 53 * OUT[3] = dst tex coord 54 */ 55 56 /* Fragment shader: 57 * SAMP[0] = src 58 * SAMP[1] = mask 59 * SAMP[2] = dst 60 * IN[0] = pos src | solid fill color 61 * IN[1] = pos mask 62 * IN[2] = pos dst 63 * CONST[0] = (0, 0, 0, 1) 64 * 65 * OUT[0] = color 66 */ 67 68 static void 69 print_fs_traits(int fs_traits) 70 { 71 const char *strings[] = { 72 "FS_COMPOSITE", /* = 1 << 0, */ 73 "FS_MASK", /* = 1 << 1, */ 74 "FS_SOLID_FILL", /* = 1 << 2, */ 75 "FS_LINGRAD_FILL", /* = 1 << 3, */ 76 "FS_RADGRAD_FILL", /* = 1 << 4, */ 77 "FS_CA_FULL", /* = 1 << 5, *//* src.rgba * mask.rgba */ 78 "FS_CA_SRCALPHA", /* = 1 << 6, *//* src.aaaa * mask.rgba */ 79 "FS_YUV", /* = 1 << 7, */ 80 "FS_SRC_REPEAT_NONE", /* = 1 << 8, */ 81 "FS_MASK_REPEAT_NONE", /* = 1 << 9, */ 82 "FS_SRC_SWIZZLE_RGB", /* = 1 << 10, */ 83 "FS_MASK_SWIZZLE_RGB", /* = 1 << 11, */ 84 "FS_SRC_SET_ALPHA", /* = 1 << 12, */ 85 "FS_MASK_SET_ALPHA", /* = 1 << 13, */ 86 "FS_SRC_LUMINANCE", /* = 1 << 14, */ 87 "FS_MASK_LUMINANCE", /* = 1 << 15, */ 88 "FS_DST_LUMINANCE", /* = 1 << 15, */ 89 }; 90 int i, k; 91 92 debug_printf("%s: ", __func__); 93 94 for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) { 95 if (fs_traits & k) 96 debug_printf("%s, ", strings[i]); 97 } 98 99 debug_printf("\n"); 100 } 101 102 struct xa_shaders { 103 struct xa_context *r; 104 105 struct cso_hash *vs_hash; 106 struct cso_hash *fs_hash; 107 }; 108 109 static INLINE void 110 src_in_mask(struct ureg_program *ureg, 111 struct ureg_dst dst, 112 struct ureg_src src, 113 struct ureg_src mask, 114 unsigned component_alpha, unsigned mask_luminance) 115 { 116 if (component_alpha == FS_CA_FULL) { 117 ureg_MUL(ureg, dst, src, mask); 118 } else if (component_alpha == FS_CA_SRCALPHA) { 119 ureg_MUL(ureg, dst, ureg_scalar(src, TGSI_SWIZZLE_W), mask); 120 } else { 121 if (mask_luminance) 122 ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X)); 123 else 124 ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W)); 125 } 126 } 127 128 static struct ureg_src 129 vs_normalize_coords(struct ureg_program *ureg, 130 struct ureg_src coords, 131 struct ureg_src const0, struct ureg_src const1) 132 { 133 struct ureg_dst tmp = ureg_DECL_temporary(ureg); 134 struct ureg_src ret; 135 136 ureg_MAD(ureg, tmp, coords, const0, const1); 137 ret = ureg_src(tmp); 138 ureg_release_temporary(ureg, tmp); 139 return ret; 140 } 141 142 static void 143 linear_gradient(struct ureg_program *ureg, 144 struct ureg_dst out, 145 struct ureg_src pos, 146 struct ureg_src sampler, 147 struct ureg_src coords, 148 struct ureg_src const0124, 149 struct ureg_src matrow0, 150 struct ureg_src matrow1, struct ureg_src matrow2) 151 { 152 struct ureg_dst temp0 = ureg_DECL_temporary(ureg); 153 struct ureg_dst temp1 = ureg_DECL_temporary(ureg); 154 struct ureg_dst temp2 = ureg_DECL_temporary(ureg); 155 struct ureg_dst temp3 = ureg_DECL_temporary(ureg); 156 struct ureg_dst temp4 = ureg_DECL_temporary(ureg); 157 struct ureg_dst temp5 = ureg_DECL_temporary(ureg); 158 159 ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); 160 ureg_MOV(ureg, 161 ureg_writemask(temp0, TGSI_WRITEMASK_Z), 162 ureg_scalar(const0124, TGSI_SWIZZLE_Y)); 163 164 ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); 165 ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); 166 ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); 167 ureg_RCP(ureg, temp3, ureg_src(temp3)); 168 ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); 169 ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); 170 171 ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X), ureg_src(temp1)); 172 ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y), ureg_src(temp2)); 173 174 ureg_MUL(ureg, temp0, 175 ureg_scalar(coords, TGSI_SWIZZLE_Y), 176 ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y)); 177 ureg_MAD(ureg, temp1, 178 ureg_scalar(coords, TGSI_SWIZZLE_X), 179 ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X), ureg_src(temp0)); 180 181 ureg_MUL(ureg, temp2, ureg_src(temp1), ureg_scalar(coords, TGSI_SWIZZLE_Z)); 182 183 ureg_TEX(ureg, out, TGSI_TEXTURE_1D, ureg_src(temp2), sampler); 184 185 ureg_release_temporary(ureg, temp0); 186 ureg_release_temporary(ureg, temp1); 187 ureg_release_temporary(ureg, temp2); 188 ureg_release_temporary(ureg, temp3); 189 ureg_release_temporary(ureg, temp4); 190 ureg_release_temporary(ureg, temp5); 191 } 192 193 static void 194 radial_gradient(struct ureg_program *ureg, 195 struct ureg_dst out, 196 struct ureg_src pos, 197 struct ureg_src sampler, 198 struct ureg_src coords, 199 struct ureg_src const0124, 200 struct ureg_src matrow0, 201 struct ureg_src matrow1, struct ureg_src matrow2) 202 { 203 struct ureg_dst temp0 = ureg_DECL_temporary(ureg); 204 struct ureg_dst temp1 = ureg_DECL_temporary(ureg); 205 struct ureg_dst temp2 = ureg_DECL_temporary(ureg); 206 struct ureg_dst temp3 = ureg_DECL_temporary(ureg); 207 struct ureg_dst temp4 = ureg_DECL_temporary(ureg); 208 struct ureg_dst temp5 = ureg_DECL_temporary(ureg); 209 210 ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); 211 ureg_MOV(ureg, 212 ureg_writemask(temp0, TGSI_WRITEMASK_Z), 213 ureg_scalar(const0124, TGSI_SWIZZLE_Y)); 214 215 ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); 216 ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); 217 ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); 218 ureg_RCP(ureg, temp3, ureg_src(temp3)); 219 ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); 220 ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); 221 222 ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X), ureg_src(temp1)); 223 ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y), ureg_src(temp2)); 224 225 ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y), 226 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); 227 ureg_MAD(ureg, temp1, 228 ureg_scalar(coords, TGSI_SWIZZLE_X), 229 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), ureg_src(temp0)); 230 ureg_ADD(ureg, temp1, ureg_src(temp1), ureg_src(temp1)); 231 ureg_MUL(ureg, temp3, 232 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y), 233 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); 234 ureg_MAD(ureg, temp4, 235 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), 236 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), ureg_src(temp3)); 237 ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4))); 238 ureg_MUL(ureg, temp2, ureg_scalar(coords, TGSI_SWIZZLE_Z), ureg_src(temp4)); 239 ureg_MUL(ureg, temp0, 240 ureg_scalar(const0124, TGSI_SWIZZLE_W), ureg_src(temp2)); 241 ureg_MUL(ureg, temp3, ureg_src(temp1), ureg_src(temp1)); 242 ureg_SUB(ureg, temp2, ureg_src(temp3), ureg_src(temp0)); 243 ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2))); 244 ureg_RCP(ureg, temp2, ureg_src(temp2)); 245 ureg_SUB(ureg, temp1, ureg_src(temp2), ureg_src(temp1)); 246 ureg_ADD(ureg, temp0, 247 ureg_scalar(coords, TGSI_SWIZZLE_Z), 248 ureg_scalar(coords, TGSI_SWIZZLE_Z)); 249 ureg_RCP(ureg, temp0, ureg_src(temp0)); 250 ureg_MUL(ureg, temp2, ureg_src(temp1), ureg_src(temp0)); 251 ureg_TEX(ureg, out, TGSI_TEXTURE_1D, ureg_src(temp2), sampler); 252 253 ureg_release_temporary(ureg, temp0); 254 ureg_release_temporary(ureg, temp1); 255 ureg_release_temporary(ureg, temp2); 256 ureg_release_temporary(ureg, temp3); 257 ureg_release_temporary(ureg, temp4); 258 ureg_release_temporary(ureg, temp5); 259 } 260 261 static void * 262 create_vs(struct pipe_context *pipe, unsigned vs_traits) 263 { 264 struct ureg_program *ureg; 265 struct ureg_src src; 266 struct ureg_dst dst; 267 struct ureg_src const0, const1; 268 boolean is_fill = (vs_traits & VS_FILL) != 0; 269 boolean is_composite = (vs_traits & VS_COMPOSITE) != 0; 270 boolean has_mask = (vs_traits & VS_MASK) != 0; 271 boolean is_yuv = (vs_traits & VS_YUV) != 0; 272 unsigned input_slot = 0; 273 274 ureg = ureg_create(TGSI_PROCESSOR_VERTEX); 275 if (ureg == NULL) 276 return 0; 277 278 const0 = ureg_DECL_constant(ureg, 0); 279 const1 = ureg_DECL_constant(ureg, 1); 280 281 /* it has to be either a fill or a composite op */ 282 debug_assert((is_fill ^ is_composite) ^ is_yuv); 283 284 src = ureg_DECL_vs_input(ureg, input_slot++); 285 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 286 src = vs_normalize_coords(ureg, src, const0, const1); 287 ureg_MOV(ureg, dst, src); 288 289 if (is_yuv) { 290 src = ureg_DECL_vs_input(ureg, input_slot++); 291 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); 292 ureg_MOV(ureg, dst, src); 293 } 294 295 if (is_composite) { 296 src = ureg_DECL_vs_input(ureg, input_slot++); 297 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); 298 ureg_MOV(ureg, dst, src); 299 } 300 301 if (is_fill) { 302 src = ureg_DECL_vs_input(ureg, input_slot++); 303 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 304 ureg_MOV(ureg, dst, src); 305 } 306 307 if (has_mask) { 308 src = ureg_DECL_vs_input(ureg, input_slot++); 309 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); 310 ureg_MOV(ureg, dst, src); 311 } 312 313 ureg_END(ureg); 314 315 return ureg_create_shader_and_destroy(ureg, pipe); 316 } 317 318 static void * 319 create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg) 320 { 321 struct ureg_src y_sampler, u_sampler, v_sampler; 322 struct ureg_src pos; 323 struct ureg_src matrow0, matrow1, matrow2, matrow3; 324 struct ureg_dst y, u, v, rgb; 325 struct ureg_dst out = ureg_DECL_output(ureg, 326 TGSI_SEMANTIC_COLOR, 327 0); 328 329 pos = ureg_DECL_fs_input(ureg, 330 TGSI_SEMANTIC_GENERIC, 0, 331 TGSI_INTERPOLATE_PERSPECTIVE); 332 333 rgb = ureg_DECL_temporary(ureg); 334 y = ureg_DECL_temporary(ureg); 335 u = ureg_DECL_temporary(ureg); 336 v = ureg_DECL_temporary(ureg); 337 338 y_sampler = ureg_DECL_sampler(ureg, 0); 339 u_sampler = ureg_DECL_sampler(ureg, 1); 340 v_sampler = ureg_DECL_sampler(ureg, 2); 341 342 matrow0 = ureg_DECL_constant(ureg, 0); 343 matrow1 = ureg_DECL_constant(ureg, 1); 344 matrow2 = ureg_DECL_constant(ureg, 2); 345 matrow3 = ureg_DECL_constant(ureg, 3); 346 347 ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler); 348 ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler); 349 ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler); 350 351 ureg_MOV(ureg, rgb, matrow3); 352 ureg_MAD(ureg, rgb, 353 ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb)); 354 ureg_MAD(ureg, rgb, 355 ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb)); 356 ureg_MAD(ureg, rgb, 357 ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb)); 358 359 ureg_MOV(ureg, out, ureg_src(rgb)); 360 361 ureg_release_temporary(ureg, rgb); 362 ureg_release_temporary(ureg, y); 363 ureg_release_temporary(ureg, u); 364 ureg_release_temporary(ureg, v); 365 366 ureg_END(ureg); 367 368 return ureg_create_shader_and_destroy(ureg, pipe); 369 } 370 371 static INLINE void 372 xrender_tex(struct ureg_program *ureg, 373 struct ureg_dst dst, 374 struct ureg_src coords, 375 struct ureg_src sampler, 376 struct ureg_src imm0, 377 boolean repeat_none, boolean swizzle, boolean set_alpha) 378 { 379 if (repeat_none) { 380 struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); 381 struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); 382 383 ureg_SGT(ureg, tmp1, ureg_swizzle(coords, 384 TGSI_SWIZZLE_X, 385 TGSI_SWIZZLE_Y, 386 TGSI_SWIZZLE_X, 387 TGSI_SWIZZLE_Y), ureg_scalar(imm0, 388 TGSI_SWIZZLE_X)); 389 ureg_SLT(ureg, tmp0, 390 ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 391 TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(imm0, 392 TGSI_SWIZZLE_W)); 393 ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); 394 ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), 395 ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); 396 ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); 397 if (swizzle) 398 ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), 399 TGSI_SWIZZLE_Z, 400 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, 401 TGSI_SWIZZLE_W)); 402 if (set_alpha) 403 ureg_MOV(ureg, 404 ureg_writemask(tmp1, TGSI_WRITEMASK_W), 405 ureg_scalar(imm0, TGSI_SWIZZLE_W)); 406 ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); 407 ureg_release_temporary(ureg, tmp0); 408 ureg_release_temporary(ureg, tmp1); 409 } else { 410 if (swizzle) { 411 struct ureg_dst tmp = ureg_DECL_temporary(ureg); 412 413 ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); 414 ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), 415 TGSI_SWIZZLE_Z, 416 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, 417 TGSI_SWIZZLE_W)); 418 ureg_release_temporary(ureg, tmp); 419 } else { 420 ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); 421 } 422 if (set_alpha) 423 ureg_MOV(ureg, 424 ureg_writemask(dst, TGSI_WRITEMASK_W), 425 ureg_scalar(imm0, TGSI_SWIZZLE_W)); 426 } 427 } 428 429 static void * 430 create_fs(struct pipe_context *pipe, unsigned fs_traits) 431 { 432 struct ureg_program *ureg; 433 struct ureg_src /*dst_sampler, */ src_sampler, mask_sampler; 434 struct ureg_src /*dst_pos, */ src_input, mask_pos; 435 struct ureg_dst src, mask; 436 struct ureg_dst out; 437 struct ureg_src imm0 = { 0 }; 438 unsigned has_mask = (fs_traits & FS_MASK) != 0; 439 unsigned is_fill = (fs_traits & FS_FILL) != 0; 440 unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0; 441 unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0; 442 unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0; 443 unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0; 444 unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA; 445 unsigned is_yuv = (fs_traits & FS_YUV) != 0; 446 unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; 447 unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; 448 unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; 449 unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; 450 unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; 451 unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0; 452 unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0; 453 unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0; 454 unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0; 455 456 #if 0 457 print_fs_traits(fs_traits); 458 #else 459 (void)print_fs_traits; 460 #endif 461 462 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); 463 if (ureg == NULL) 464 return 0; 465 466 /* it has to be either a fill, a composite op or a yuv conversion */ 467 debug_assert((is_fill ^ is_composite) ^ is_yuv); 468 (void)is_yuv; 469 470 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 471 472 if (src_repeat_none || mask_repeat_none || 473 src_set_alpha || mask_set_alpha || src_luminance) { 474 imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); 475 } 476 if (is_composite) { 477 src_sampler = ureg_DECL_sampler(ureg, 0); 478 src_input = ureg_DECL_fs_input(ureg, 479 TGSI_SEMANTIC_GENERIC, 0, 480 TGSI_INTERPOLATE_PERSPECTIVE); 481 } else if (is_fill) { 482 if (is_solid) 483 src_input = ureg_DECL_fs_input(ureg, 484 TGSI_SEMANTIC_COLOR, 0, 485 TGSI_INTERPOLATE_PERSPECTIVE); 486 else 487 src_input = ureg_DECL_fs_input(ureg, 488 TGSI_SEMANTIC_POSITION, 0, 489 TGSI_INTERPOLATE_PERSPECTIVE); 490 } else { 491 debug_assert(is_yuv); 492 return create_yuv_shader(pipe, ureg); 493 } 494 495 if (has_mask) { 496 mask_sampler = ureg_DECL_sampler(ureg, 1); 497 mask_pos = ureg_DECL_fs_input(ureg, 498 TGSI_SEMANTIC_GENERIC, 1, 499 TGSI_INTERPOLATE_PERSPECTIVE); 500 } 501 #if 0 /* unused right now */ 502 dst_sampler = ureg_DECL_sampler(ureg, 2); 503 dst_pos = ureg_DECL_fs_input(ureg, 504 TGSI_SEMANTIC_POSITION, 2, 505 TGSI_INTERPOLATE_PERSPECTIVE); 506 #endif 507 508 if (is_composite) { 509 if (has_mask || src_luminance || dst_luminance) 510 src = ureg_DECL_temporary(ureg); 511 else 512 src = out; 513 xrender_tex(ureg, src, src_input, src_sampler, imm0, 514 src_repeat_none, src_swizzle, src_set_alpha); 515 } else if (is_fill) { 516 if (is_solid) { 517 if (has_mask || src_luminance || dst_luminance) 518 src = ureg_dst(src_input); 519 else 520 ureg_MOV(ureg, out, src_input); 521 } else if (is_lingrad || is_radgrad) { 522 struct ureg_src coords, const0124, matrow0, matrow1, matrow2; 523 524 if (has_mask || src_luminance || dst_luminance) 525 src = ureg_DECL_temporary(ureg); 526 else 527 src = out; 528 529 coords = ureg_DECL_constant(ureg, 0); 530 const0124 = ureg_DECL_constant(ureg, 1); 531 matrow0 = ureg_DECL_constant(ureg, 2); 532 matrow1 = ureg_DECL_constant(ureg, 3); 533 matrow2 = ureg_DECL_constant(ureg, 4); 534 535 if (is_lingrad) { 536 linear_gradient(ureg, src, 537 src_input, src_sampler, 538 coords, const0124, matrow0, matrow1, matrow2); 539 } else if (is_radgrad) { 540 radial_gradient(ureg, src, 541 src_input, src_sampler, 542 coords, const0124, matrow0, matrow1, matrow2); 543 } 544 } else 545 debug_assert(!"Unknown fill type!"); 546 } 547 if (src_luminance) { 548 ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X)); 549 ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ), 550 ureg_scalar(imm0, TGSI_SWIZZLE_X)); 551 if (!has_mask && !dst_luminance) 552 ureg_MOV(ureg, out, ureg_src(src)); 553 } 554 555 if (has_mask) { 556 mask = ureg_DECL_temporary(ureg); 557 xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0, 558 mask_repeat_none, mask_swizzle, mask_set_alpha); 559 /* src IN mask */ 560 561 src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src), 562 ureg_src(mask), 563 comp_alpha_mask, mask_luminance); 564 565 ureg_release_temporary(ureg, mask); 566 } 567 568 if (dst_luminance) { 569 /* 570 * Make sure the alpha channel goes into the output L8 surface. 571 */ 572 ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W)); 573 } 574 575 ureg_END(ureg); 576 577 return ureg_create_shader_and_destroy(ureg, pipe); 578 } 579 580 struct xa_shaders * 581 xa_shaders_create(struct xa_context *r) 582 { 583 struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders); 584 585 sc->r = r; 586 sc->vs_hash = cso_hash_create(); 587 sc->fs_hash = cso_hash_create(); 588 589 return sc; 590 } 591 592 static void 593 cache_destroy(struct cso_context *cso, 594 struct cso_hash *hash, unsigned processor) 595 { 596 struct cso_hash_iter iter = cso_hash_first_node(hash); 597 598 while (!cso_hash_iter_is_null(iter)) { 599 void *shader = (void *)cso_hash_iter_data(iter); 600 601 if (processor == PIPE_SHADER_FRAGMENT) { 602 cso_delete_fragment_shader(cso, shader); 603 } else if (processor == PIPE_SHADER_VERTEX) { 604 cso_delete_vertex_shader(cso, shader); 605 } 606 iter = cso_hash_erase(hash, iter); 607 } 608 cso_hash_delete(hash); 609 } 610 611 void 612 xa_shaders_destroy(struct xa_shaders *sc) 613 { 614 cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX); 615 cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT); 616 617 FREE(sc); 618 } 619 620 static INLINE void * 621 shader_from_cache(struct pipe_context *pipe, 622 unsigned type, struct cso_hash *hash, unsigned key) 623 { 624 void *shader = 0; 625 626 struct cso_hash_iter iter = cso_hash_find(hash, key); 627 628 if (cso_hash_iter_is_null(iter)) { 629 if (type == PIPE_SHADER_VERTEX) 630 shader = create_vs(pipe, key); 631 else 632 shader = create_fs(pipe, key); 633 cso_hash_insert(hash, key, shader); 634 } else 635 shader = (void *)cso_hash_iter_data(iter); 636 637 return shader; 638 } 639 640 struct xa_shader 641 xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits) 642 { 643 struct xa_shader shader = { NULL, NULL }; 644 void *vs, *fs; 645 646 vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, 647 sc->vs_hash, vs_traits); 648 fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, 649 sc->fs_hash, fs_traits); 650 651 debug_assert(vs && fs); 652 if (!vs || !fs) 653 return shader; 654 655 shader.vs = vs; 656 shader.fs = fs; 657 658 return shader; 659 } 660