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_ADD(ureg, temp2, ureg_src(temp3), ureg_negate(ureg_src(temp0))); 243 ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2))); 244 ureg_RCP(ureg, temp2, ureg_src(temp2)); 245 ureg_ADD(ureg, temp1, ureg_src(temp2), ureg_negate(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(PIPE_SHADER_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 ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D, 343 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, 344 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); 345 ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D, 346 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, 347 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); 348 ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D, 349 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, 350 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); 351 352 matrow0 = ureg_DECL_constant(ureg, 0); 353 matrow1 = ureg_DECL_constant(ureg, 1); 354 matrow2 = ureg_DECL_constant(ureg, 2); 355 matrow3 = ureg_DECL_constant(ureg, 3); 356 357 ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler); 358 ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler); 359 ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler); 360 361 ureg_MOV(ureg, rgb, matrow3); 362 ureg_MAD(ureg, rgb, 363 ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb)); 364 ureg_MAD(ureg, rgb, 365 ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb)); 366 ureg_MAD(ureg, rgb, 367 ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb)); 368 369 ureg_MOV(ureg, out, ureg_src(rgb)); 370 371 ureg_release_temporary(ureg, rgb); 372 ureg_release_temporary(ureg, y); 373 ureg_release_temporary(ureg, u); 374 ureg_release_temporary(ureg, v); 375 376 ureg_END(ureg); 377 378 return ureg_create_shader_and_destroy(ureg, pipe); 379 } 380 381 static inline void 382 xrender_tex(struct ureg_program *ureg, 383 struct ureg_dst dst, 384 struct ureg_src coords, 385 struct ureg_src sampler, 386 struct ureg_src imm0, 387 boolean repeat_none, boolean swizzle, boolean set_alpha) 388 { 389 if (repeat_none) { 390 struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); 391 struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); 392 393 ureg_SGT(ureg, tmp1, ureg_swizzle(coords, 394 TGSI_SWIZZLE_X, 395 TGSI_SWIZZLE_Y, 396 TGSI_SWIZZLE_X, 397 TGSI_SWIZZLE_Y), ureg_scalar(imm0, 398 TGSI_SWIZZLE_X)); 399 ureg_SLT(ureg, tmp0, 400 ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, 401 TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(imm0, 402 TGSI_SWIZZLE_W)); 403 ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); 404 ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), 405 ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); 406 ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); 407 if (swizzle) 408 ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), 409 TGSI_SWIZZLE_Z, 410 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, 411 TGSI_SWIZZLE_W)); 412 if (set_alpha) 413 ureg_MOV(ureg, 414 ureg_writemask(tmp1, TGSI_WRITEMASK_W), 415 ureg_scalar(imm0, TGSI_SWIZZLE_W)); 416 ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); 417 ureg_release_temporary(ureg, tmp0); 418 ureg_release_temporary(ureg, tmp1); 419 } else { 420 if (swizzle) { 421 struct ureg_dst tmp = ureg_DECL_temporary(ureg); 422 423 ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); 424 ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), 425 TGSI_SWIZZLE_Z, 426 TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X, 427 TGSI_SWIZZLE_W)); 428 ureg_release_temporary(ureg, tmp); 429 } else { 430 ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); 431 } 432 if (set_alpha) 433 ureg_MOV(ureg, 434 ureg_writemask(dst, TGSI_WRITEMASK_W), 435 ureg_scalar(imm0, TGSI_SWIZZLE_W)); 436 } 437 } 438 439 static void * 440 create_fs(struct pipe_context *pipe, unsigned fs_traits) 441 { 442 struct ureg_program *ureg; 443 struct ureg_src /*dst_sampler, */ src_sampler, mask_sampler; 444 struct ureg_src /*dst_pos, */ src_input, mask_pos; 445 struct ureg_dst src, mask; 446 struct ureg_dst out; 447 struct ureg_src imm0 = { 0 }; 448 unsigned has_mask = (fs_traits & FS_MASK) != 0; 449 unsigned is_fill = (fs_traits & FS_FILL) != 0; 450 unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0; 451 unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0; 452 unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0; 453 unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0; 454 unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA; 455 unsigned is_yuv = (fs_traits & FS_YUV) != 0; 456 unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; 457 unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; 458 unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; 459 unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; 460 unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; 461 unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0; 462 unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0; 463 unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0; 464 unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0; 465 466 #if 0 467 print_fs_traits(fs_traits); 468 #else 469 (void)print_fs_traits; 470 #endif 471 472 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 473 if (ureg == NULL) 474 return 0; 475 476 /* it has to be either a fill, a composite op or a yuv conversion */ 477 debug_assert((is_fill ^ is_composite) ^ is_yuv); 478 (void)is_yuv; 479 480 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 481 482 if (src_repeat_none || mask_repeat_none || 483 src_set_alpha || mask_set_alpha || src_luminance) { 484 imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); 485 } 486 if (is_composite) { 487 src_sampler = ureg_DECL_sampler(ureg, 0); 488 ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D, 489 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, 490 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); 491 src_input = ureg_DECL_fs_input(ureg, 492 TGSI_SEMANTIC_GENERIC, 0, 493 TGSI_INTERPOLATE_PERSPECTIVE); 494 } else if (is_fill) { 495 if (is_solid) 496 src_input = ureg_DECL_fs_input(ureg, 497 TGSI_SEMANTIC_COLOR, 0, 498 TGSI_INTERPOLATE_PERSPECTIVE); 499 else 500 src_input = ureg_DECL_fs_input(ureg, 501 TGSI_SEMANTIC_POSITION, 0, 502 TGSI_INTERPOLATE_PERSPECTIVE); 503 } else { 504 debug_assert(is_yuv); 505 return create_yuv_shader(pipe, ureg); 506 } 507 508 if (has_mask) { 509 mask_sampler = ureg_DECL_sampler(ureg, 1); 510 ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D, 511 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, 512 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); 513 mask_pos = ureg_DECL_fs_input(ureg, 514 TGSI_SEMANTIC_GENERIC, 1, 515 TGSI_INTERPOLATE_PERSPECTIVE); 516 } 517 #if 0 /* unused right now */ 518 dst_sampler = ureg_DECL_sampler(ureg, 2); 519 ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D, 520 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, 521 TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); 522 dst_pos = ureg_DECL_fs_input(ureg, 523 TGSI_SEMANTIC_POSITION, 2, 524 TGSI_INTERPOLATE_PERSPECTIVE); 525 #endif 526 527 if (is_composite) { 528 if (has_mask || src_luminance || dst_luminance) 529 src = ureg_DECL_temporary(ureg); 530 else 531 src = out; 532 xrender_tex(ureg, src, src_input, src_sampler, imm0, 533 src_repeat_none, src_swizzle, src_set_alpha); 534 } else if (is_fill) { 535 if (is_solid) { 536 if (has_mask || src_luminance || dst_luminance) 537 src = ureg_dst(src_input); 538 else 539 ureg_MOV(ureg, out, src_input); 540 } else if (is_lingrad || is_radgrad) { 541 struct ureg_src coords, const0124, matrow0, matrow1, matrow2; 542 543 if (has_mask || src_luminance || dst_luminance) 544 src = ureg_DECL_temporary(ureg); 545 else 546 src = out; 547 548 coords = ureg_DECL_constant(ureg, 0); 549 const0124 = ureg_DECL_constant(ureg, 1); 550 matrow0 = ureg_DECL_constant(ureg, 2); 551 matrow1 = ureg_DECL_constant(ureg, 3); 552 matrow2 = ureg_DECL_constant(ureg, 4); 553 554 if (is_lingrad) { 555 linear_gradient(ureg, src, 556 src_input, src_sampler, 557 coords, const0124, matrow0, matrow1, matrow2); 558 } else if (is_radgrad) { 559 radial_gradient(ureg, src, 560 src_input, src_sampler, 561 coords, const0124, matrow0, matrow1, matrow2); 562 } 563 } else 564 debug_assert(!"Unknown fill type!"); 565 } 566 if (src_luminance) { 567 ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X)); 568 ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ), 569 ureg_scalar(imm0, TGSI_SWIZZLE_X)); 570 if (!has_mask && !dst_luminance) 571 ureg_MOV(ureg, out, ureg_src(src)); 572 } 573 574 if (has_mask) { 575 mask = ureg_DECL_temporary(ureg); 576 xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0, 577 mask_repeat_none, mask_swizzle, mask_set_alpha); 578 /* src IN mask */ 579 580 src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src), 581 ureg_src(mask), 582 comp_alpha_mask, mask_luminance); 583 584 ureg_release_temporary(ureg, mask); 585 } 586 587 if (dst_luminance) { 588 /* 589 * Make sure the alpha channel goes into the output L8 surface. 590 */ 591 ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W)); 592 } 593 594 ureg_END(ureg); 595 596 return ureg_create_shader_and_destroy(ureg, pipe); 597 } 598 599 struct xa_shaders * 600 xa_shaders_create(struct xa_context *r) 601 { 602 struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders); 603 604 sc->r = r; 605 sc->vs_hash = cso_hash_create(); 606 sc->fs_hash = cso_hash_create(); 607 608 return sc; 609 } 610 611 static void 612 cache_destroy(struct cso_context *cso, 613 struct cso_hash *hash, unsigned processor) 614 { 615 struct cso_hash_iter iter = cso_hash_first_node(hash); 616 617 while (!cso_hash_iter_is_null(iter)) { 618 void *shader = (void *)cso_hash_iter_data(iter); 619 620 if (processor == PIPE_SHADER_FRAGMENT) { 621 cso_delete_fragment_shader(cso, shader); 622 } else if (processor == PIPE_SHADER_VERTEX) { 623 cso_delete_vertex_shader(cso, shader); 624 } 625 iter = cso_hash_erase(hash, iter); 626 } 627 cso_hash_delete(hash); 628 } 629 630 void 631 xa_shaders_destroy(struct xa_shaders *sc) 632 { 633 cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX); 634 cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT); 635 636 FREE(sc); 637 } 638 639 static inline void * 640 shader_from_cache(struct pipe_context *pipe, 641 unsigned type, struct cso_hash *hash, unsigned key) 642 { 643 void *shader = 0; 644 645 struct cso_hash_iter iter = cso_hash_find(hash, key); 646 647 if (cso_hash_iter_is_null(iter)) { 648 if (type == PIPE_SHADER_VERTEX) 649 shader = create_vs(pipe, key); 650 else 651 shader = create_fs(pipe, key); 652 cso_hash_insert(hash, key, shader); 653 } else 654 shader = (void *)cso_hash_iter_data(iter); 655 656 return shader; 657 } 658 659 struct xa_shader 660 xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits) 661 { 662 struct xa_shader shader = { NULL, NULL }; 663 void *vs, *fs; 664 665 vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, 666 sc->vs_hash, vs_traits); 667 fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, 668 sc->fs_hash, fs_traits); 669 670 debug_assert(vs && fs); 671 if (!vs || !fs) 672 return shader; 673 674 shader.vs = vs; 675 shader.fs = fs; 676 677 return shader; 678 } 679