xorg_exa_tgsi.c revision f1ce6b09cdb21d9217d6ad6057f7fb97375df8be
1#include "xorg_exa_tgsi.h" 2 3/*### stupidity defined in X11/extensions/XI.h */ 4#undef Absolute 5 6#include "pipe/p_format.h" 7#include "pipe/p_context.h" 8#include "pipe/p_state.h" 9#include "pipe/p_inlines.h" 10#include "pipe/p_shader_tokens.h" 11 12#include "util/u_memory.h" 13#include "util/u_simple_shaders.h" 14 15#include "tgsi/tgsi_ureg.h" 16 17#include "cso_cache/cso_context.h" 18#include "cso_cache/cso_hash.h" 19 20/* Vertex shader: 21 * IN[0] = vertex pos 22 * IN[1] = src tex coord | solid fill color 23 * IN[2] = mask tex coord 24 * IN[3] = dst tex coord 25 * CONST[0] = (2/dst_width, 2/dst_height, 1, 1) 26 * CONST[1] = (-1, -1, 0, 0) 27 * 28 * OUT[0] = vertex pos 29 * OUT[1] = src tex coord | solid fill color 30 * OUT[2] = mask tex coord 31 * OUT[3] = dst tex coord 32 */ 33 34/* Fragment shader: 35 * SAMP[0] = src 36 * SAMP[1] = mask 37 * SAMP[2] = dst 38 * IN[0] = pos src | solid fill color 39 * IN[1] = pos mask 40 * IN[2] = pos dst 41 * CONST[0] = (0, 0, 0, 1) 42 * 43 * OUT[0] = color 44 */ 45 46struct xorg_shaders { 47 struct exa_context *exa; 48 49 struct cso_hash *vs_hash; 50 struct cso_hash *fs_hash; 51}; 52 53static const char over_op[] = 54 "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n" 55 "MAD TEMP[3], TEMP[0], TEMP[3], TEMP[0]\n"; 56 57 58static INLINE void 59create_preamble(struct ureg_program *ureg) 60{ 61} 62 63 64static INLINE void 65src_in_mask(struct ureg_program *ureg, 66 struct ureg_dst dst, 67 struct ureg_src src, 68 struct ureg_src mask) 69{ 70 /* MUL dst, src, mask.wwww */ 71 ureg_MUL(ureg, dst, src, 72 ureg_scalar(mask, TGSI_SWIZZLE_W)); 73} 74 75static struct ureg_src 76vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords, 77 struct ureg_src const0, struct ureg_src const1) 78{ 79 struct ureg_dst tmp = ureg_DECL_temporary(ureg); 80 struct ureg_src ret; 81 ureg_MAD(ureg, tmp, coords, const0, const1); 82 ret = ureg_src(tmp); 83 ureg_release_temporary(ureg, tmp); 84 return ret; 85} 86 87static void 88linear_gradient(struct ureg_program *ureg, 89 struct ureg_dst out, 90 struct ureg_src pos, 91 struct ureg_src sampler, 92 struct ureg_src coords, 93 struct ureg_src const0124, 94 struct ureg_src matrow0, 95 struct ureg_src matrow1, 96 struct ureg_src matrow2) 97{ 98 struct ureg_dst temp0 = ureg_DECL_temporary(ureg); 99 struct ureg_dst temp1 = ureg_DECL_temporary(ureg); 100 struct ureg_dst temp2 = ureg_DECL_temporary(ureg); 101 struct ureg_dst temp3 = ureg_DECL_temporary(ureg); 102 struct ureg_dst temp4 = ureg_DECL_temporary(ureg); 103 struct ureg_dst temp5 = ureg_DECL_temporary(ureg); 104 105 ureg_MOV(ureg, 106 ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos); 107 ureg_MOV(ureg, 108 ureg_writemask(temp0, TGSI_WRITEMASK_Z), 109 ureg_scalar(const0124, TGSI_SWIZZLE_Y)); 110 111 ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); 112 ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); 113 ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); 114 ureg_RCP(ureg, temp3, ureg_src(temp3)); 115 ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); 116 ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); 117 118 ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X), 119 ureg_src(temp1)); 120 ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y), 121 ureg_src(temp2)); 122 123 ureg_MUL(ureg, temp0, 124 ureg_scalar(coords, TGSI_SWIZZLE_Y), 125 ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y)); 126 ureg_MAD(ureg, temp1, 127 ureg_scalar(coords, TGSI_SWIZZLE_X), 128 ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X), 129 ureg_src(temp0)); 130 131 ureg_MUL(ureg, temp2, 132 ureg_src(temp1), 133 ureg_scalar(coords, TGSI_SWIZZLE_Z)); 134 135 ureg_TEX(ureg, out, 136 TGSI_TEXTURE_1D, ureg_src(temp2), sampler); 137 138 ureg_release_temporary(ureg, temp0); 139 ureg_release_temporary(ureg, temp1); 140 ureg_release_temporary(ureg, temp2); 141 ureg_release_temporary(ureg, temp3); 142 ureg_release_temporary(ureg, temp4); 143 ureg_release_temporary(ureg, temp5); 144} 145 146 147static void 148radial_gradient(struct ureg_program *ureg, 149 struct ureg_dst out, 150 struct ureg_src pos, 151 struct ureg_src sampler, 152 struct ureg_src coords, 153 struct ureg_src const0124, 154 struct ureg_src matrow0, 155 struct ureg_src matrow1, 156 struct ureg_src matrow2) 157{ 158 struct ureg_dst temp0 = ureg_DECL_temporary(ureg); 159 struct ureg_dst temp1 = ureg_DECL_temporary(ureg); 160 struct ureg_dst temp2 = ureg_DECL_temporary(ureg); 161 struct ureg_dst temp3 = ureg_DECL_temporary(ureg); 162 struct ureg_dst temp4 = ureg_DECL_temporary(ureg); 163 struct ureg_dst temp5 = ureg_DECL_temporary(ureg); 164 165 ureg_MOV(ureg, 166 ureg_writemask(temp0, TGSI_WRITEMASK_XY), 167 pos); 168 ureg_MOV(ureg, 169 ureg_writemask(temp0, TGSI_WRITEMASK_Z), 170 ureg_scalar(const0124, TGSI_SWIZZLE_Y)); 171 172 ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0)); 173 ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0)); 174 ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0)); 175 ureg_RCP(ureg, temp3, ureg_src(temp3)); 176 ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3)); 177 ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3)); 178 179 ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X), 180 ureg_src(temp1)); 181 ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y), 182 ureg_src(temp2)); 183 184 ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y), 185 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); 186 ureg_MAD(ureg, temp1, 187 ureg_scalar(coords, TGSI_SWIZZLE_X), 188 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), 189 ureg_src(temp0)); 190 ureg_ADD(ureg, temp1, 191 ureg_src(temp1), ureg_src(temp1)); 192 ureg_MUL(ureg, temp3, 193 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y), 194 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y)); 195 ureg_MAD(ureg, temp4, 196 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), 197 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X), 198 ureg_src(temp3)); 199 ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4))); 200 ureg_MUL(ureg, temp2, 201 ureg_scalar(coords, TGSI_SWIZZLE_Z), 202 ureg_src(temp4)); 203 ureg_MUL(ureg, temp0, 204 ureg_scalar(const0124, TGSI_SWIZZLE_W), 205 ureg_src(temp2)); 206 ureg_MUL(ureg, temp3, 207 ureg_src(temp1), ureg_src(temp1)); 208 ureg_SUB(ureg, temp2, 209 ureg_src(temp3), ureg_src(temp0)); 210 ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2))); 211 ureg_RCP(ureg, temp2, ureg_src(temp2)); 212 ureg_SUB(ureg, temp1, 213 ureg_src(temp2), ureg_src(temp1)); 214 ureg_ADD(ureg, temp0, 215 ureg_scalar(coords, TGSI_SWIZZLE_Z), 216 ureg_scalar(coords, TGSI_SWIZZLE_Z)); 217 ureg_RCP(ureg, temp0, ureg_src(temp0)); 218 ureg_MUL(ureg, temp2, 219 ureg_src(temp1), ureg_src(temp0)); 220 ureg_TEX(ureg, out, TGSI_TEXTURE_1D, 221 ureg_src(temp2), sampler); 222 223 ureg_release_temporary(ureg, temp0); 224 ureg_release_temporary(ureg, temp1); 225 ureg_release_temporary(ureg, temp2); 226 ureg_release_temporary(ureg, temp3); 227 ureg_release_temporary(ureg, temp4); 228 ureg_release_temporary(ureg, temp5); 229} 230 231static void * 232create_vs(struct pipe_context *pipe, 233 unsigned vs_traits) 234{ 235 struct ureg_program *ureg; 236 struct ureg_src src; 237 struct ureg_dst dst; 238 struct ureg_src const0, const1; 239 boolean is_fill = vs_traits & VS_FILL; 240 boolean is_composite = vs_traits & VS_COMPOSITE; 241 boolean has_mask = vs_traits & VS_MASK; 242 unsigned input_slot = 0; 243 244 ureg = ureg_create(TGSI_PROCESSOR_VERTEX); 245 if (ureg == NULL) 246 return 0; 247 248 const0 = ureg_DECL_constant(ureg, 0); 249 const1 = ureg_DECL_constant(ureg, 1); 250 251 /* it has to be either a fill or a composite op */ 252 debug_assert(is_fill ^ is_composite); 253 254 src = ureg_DECL_vs_input(ureg, input_slot++); 255 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 256 src = vs_normalize_coords(ureg, src, 257 const0, const1); 258 ureg_MOV(ureg, dst, src); 259 260 if (is_composite) { 261 src = ureg_DECL_vs_input(ureg, input_slot++); 262 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); 263 ureg_MOV(ureg, dst, src); 264 } 265 266 if (is_fill) { 267 src = ureg_DECL_vs_input(ureg, input_slot++); 268 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 269 ureg_MOV(ureg, dst, src); 270 } 271 272 if (has_mask) { 273 src = ureg_DECL_vs_input(ureg, input_slot++); 274 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2); 275 ureg_MOV(ureg, dst, src); 276 } 277 278 ureg_END(ureg); 279 280 return ureg_create_shader_and_destroy(ureg, pipe); 281} 282 283static void * 284create_fs(struct pipe_context *pipe, 285 unsigned fs_traits) 286{ 287 struct ureg_program *ureg; 288 struct ureg_src /*dst_sampler,*/ src_sampler, mask_sampler; 289 struct ureg_src /*dst_pos,*/ src_input, mask_pos; 290 struct ureg_dst src, mask; 291 struct ureg_dst out; 292 boolean has_mask = fs_traits & FS_MASK; 293 boolean is_fill = fs_traits & FS_FILL; 294 boolean is_composite = fs_traits & FS_COMPOSITE; 295 boolean is_solid = fs_traits & FS_SOLID_FILL; 296 boolean is_lingrad = fs_traits & FS_LINGRAD_FILL; 297 boolean is_radgrad = fs_traits & FS_RADGRAD_FILL; 298 299 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); 300 if (ureg == NULL) 301 return 0; 302 303 /* it has to be either a fill or a composite op */ 304 debug_assert(is_fill ^ is_composite); 305 306 out = ureg_DECL_output(ureg, 307 TGSI_SEMANTIC_COLOR, 308 0); 309 310 if (is_composite) { 311 src_sampler = ureg_DECL_sampler(ureg, 0); 312 src_input = ureg_DECL_fs_input(ureg, 313 TGSI_SEMANTIC_POSITION, 314 0, 315 TGSI_INTERPOLATE_PERSPECTIVE); 316 } else { 317 debug_assert(is_fill); 318 if (is_solid) 319 src_input = ureg_DECL_fs_input(ureg, 320 TGSI_SEMANTIC_COLOR, 321 0, 322 TGSI_INTERPOLATE_PERSPECTIVE); 323 else 324 src_input = ureg_DECL_fs_input(ureg, 325 TGSI_SEMANTIC_POSITION, 326 0, 327 TGSI_INTERPOLATE_PERSPECTIVE); 328 } 329 330 if (has_mask) { 331 mask_sampler = ureg_DECL_sampler(ureg, 1); 332 mask_pos = ureg_DECL_fs_input(ureg, 333 TGSI_SEMANTIC_POSITION, 334 1, 335 TGSI_INTERPOLATE_PERSPECTIVE); 336 } 337 338#if 0 /* unused right now */ 339 dst_sampler = ureg_DECL_sampler(ureg, 2); 340 dst_pos = ureg_DECL_fs_input(ureg, 341 TGSI_SEMANTIC_POSITION, 342 2, 343 TGSI_INTERPOLATE_PERSPECTIVE); 344#endif 345 346 if (is_composite) { 347 if (has_mask) 348 src = ureg_DECL_temporary(ureg); 349 else 350 src = out; 351 ureg_TEX(ureg, src, 352 TGSI_TEXTURE_2D, src_input, src_sampler); 353 } else if (is_fill) { 354 if (is_solid) { 355 if (has_mask) 356 src = ureg_dst(src_input); 357 else 358 ureg_MOV(ureg, out, src_input); 359 } else if (is_lingrad || is_radgrad) { 360 struct ureg_src coords, const0124, 361 matrow0, matrow1, matrow2; 362 363 if (has_mask) 364 src = ureg_DECL_temporary(ureg); 365 else 366 src = out; 367 368 coords = ureg_DECL_constant(ureg, 0); 369 const0124 = ureg_DECL_constant(ureg, 1); 370 matrow0 = ureg_DECL_constant(ureg, 2); 371 matrow1 = ureg_DECL_constant(ureg, 3); 372 matrow2 = ureg_DECL_constant(ureg, 4); 373 374 if (is_lingrad) { 375 linear_gradient(ureg, src, 376 src_input, src_sampler, 377 coords, const0124, 378 matrow0, matrow1, matrow2); 379 } else if (is_radgrad) { 380 radial_gradient(ureg, src, 381 src_input, src_sampler, 382 coords, const0124, 383 matrow0, matrow1, matrow2); 384 } 385 } else 386 debug_assert(!"Unknown fill type!"); 387 } 388 389 if (has_mask) { 390 mask = ureg_DECL_temporary(ureg); 391 ureg_TEX(ureg, mask, 392 TGSI_TEXTURE_2D, mask_pos, mask_sampler); 393 /* src IN mask */ 394 src_in_mask(ureg, out, ureg_src(src), ureg_src(mask)); 395 ureg_release_temporary(ureg, mask); 396 } 397 398 ureg_END(ureg); 399 400 return ureg_create_shader_and_destroy(ureg, pipe); 401} 402 403struct xorg_shaders * xorg_shaders_create(struct exa_context *exa) 404{ 405 struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders); 406 407 sc->exa = exa; 408 sc->vs_hash = cso_hash_create(); 409 sc->fs_hash = cso_hash_create(); 410 411 return sc; 412} 413 414static void 415cache_destroy(struct cso_context *cso, 416 struct cso_hash *hash, 417 unsigned processor) 418{ 419 struct cso_hash_iter iter = cso_hash_first_node(hash); 420 while (!cso_hash_iter_is_null(iter)) { 421 void *shader = (void *)cso_hash_iter_data(iter); 422 if (processor == PIPE_SHADER_FRAGMENT) { 423 cso_delete_fragment_shader(cso, shader); 424 } else if (processor == PIPE_SHADER_VERTEX) { 425 cso_delete_vertex_shader(cso, shader); 426 } 427 iter = cso_hash_erase(hash, iter); 428 } 429 cso_hash_delete(hash); 430} 431 432void xorg_shaders_destroy(struct xorg_shaders *sc) 433{ 434 cache_destroy(sc->exa->cso, sc->vs_hash, 435 PIPE_SHADER_VERTEX); 436 cache_destroy(sc->exa->cso, sc->fs_hash, 437 PIPE_SHADER_FRAGMENT); 438 439 free(sc); 440} 441 442static INLINE void * 443shader_from_cache(struct pipe_context *pipe, 444 unsigned type, 445 struct cso_hash *hash, 446 unsigned key) 447{ 448 void *shader = 0; 449 450 struct cso_hash_iter iter = cso_hash_find(hash, key); 451 452 if (cso_hash_iter_is_null(iter)) { 453 if (type == PIPE_SHADER_VERTEX) 454 shader = create_vs(pipe, key); 455 else 456 shader = create_fs(pipe, key); 457 cso_hash_insert(hash, key, shader); 458 } else 459 shader = (void *)cso_hash_iter_data(iter); 460 461 return shader; 462} 463 464struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc, 465 unsigned vs_traits, 466 unsigned fs_traits) 467{ 468 struct xorg_shader shader = {0}; 469 void *vs, *fs; 470 471 vs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_VERTEX, 472 sc->vs_hash, vs_traits); 473 fs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_FRAGMENT, 474 sc->fs_hash, fs_traits); 475 476 debug_assert(vs && fs); 477 if (!vs || !fs) 478 return shader; 479 480 shader.vs = vs; 481 shader.fs = fs; 482 483 return shader; 484} 485