xorg_exa_tgsi.c revision d918896a754460bfcc5a9ba1e2844255f21ecab7
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 "MUL TEMP[3], TEMP[0], TEMP[3]\n" 56 "ADD TEMP[0], TEMP[3], TEMP[0]\n"; 57 58 59static INLINE void 60create_preamble(struct ureg_program *ureg) 61{ 62} 63 64 65static INLINE void 66src_in_mask(struct ureg_program *ureg, 67 struct ureg_dst dst, 68 struct ureg_src src, 69 struct ureg_src mask) 70{ 71 /* MUL dst, src, mask.wwww */ 72 ureg_MUL(ureg, dst, src, 73 ureg_scalar(mask, TGSI_SWIZZLE_W)); 74} 75 76static struct ureg_src 77vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords, 78 struct ureg_src const0, struct ureg_src const1) 79{ 80 struct ureg_dst tmp = ureg_DECL_temporary(ureg); 81 struct ureg_src ret; 82 ureg_MUL(ureg, tmp, coords, const0); 83 ureg_ADD(ureg, tmp, ureg_src(tmp), const1); 84 ret = ureg_src(tmp); 85 ureg_release_temporary(ureg, tmp); 86 return ret; 87} 88 89static void * 90create_vs(struct pipe_context *pipe, 91 unsigned vs_traits) 92{ 93 struct ureg_program *ureg; 94 struct ureg_src src; 95 struct ureg_dst dst; 96 struct ureg_src const0, const1; 97 boolean is_fill = vs_traits & VS_FILL; 98 boolean is_composite = vs_traits & VS_COMPOSITE; 99 boolean has_mask = vs_traits & VS_MASK; 100 101 ureg = ureg_create(TGSI_PROCESSOR_VERTEX); 102 if (ureg == NULL) 103 return 0; 104 105 const0 = ureg_DECL_constant(ureg); 106 const1 = ureg_DECL_constant(ureg); 107 108 /* it has to be either a fill or a composite op */ 109 debug_assert(is_fill ^ is_composite); 110 111 src = ureg_DECL_vs_input(ureg, 112 TGSI_SEMANTIC_POSITION, 0); 113 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 114 src = vs_normalize_coords(ureg, src, 115 const0, const1); 116 ureg_MOV(ureg, dst, src); 117 118 119 if (is_composite) { 120 src = ureg_DECL_vs_input(ureg, 121 TGSI_SEMANTIC_GENERIC, 1); 122 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); 123 ureg_MOV(ureg, dst, src); 124 } 125 if (is_fill) { 126 src = ureg_DECL_vs_input(ureg, 127 TGSI_SEMANTIC_COLOR, 1); 128 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1); 129 ureg_MOV(ureg, dst, src); 130 } 131 132 if (has_mask) { 133 src = ureg_DECL_vs_input(ureg, 134 TGSI_SEMANTIC_GENERIC, 2); 135 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2); 136 ureg_MOV(ureg, dst, src); 137 } 138 139 ureg_END(ureg); 140 141 return ureg_create_shader_and_destroy(ureg, pipe); 142} 143 144static void * 145create_fs(struct pipe_context *pipe, 146 unsigned fs_traits) 147{ 148 struct ureg_program *ureg; 149 struct ureg_src dst_sampler, src_sampler, mask_sampler; 150 struct ureg_src dst_pos, src_pos, mask_pos; 151 struct ureg_src src, mask; 152 struct ureg_dst out; 153 boolean is_fill = fs_traits & VS_FILL; 154 boolean is_composite = fs_traits & VS_COMPOSITE; 155 boolean has_mask = fs_traits & VS_MASK; 156 157 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); 158 if (ureg == NULL) 159 return 0; 160 161 /* it has to be either a fill or a composite op */ 162 debug_assert(is_fill ^ is_composite); 163 164 out = ureg_DECL_output(ureg, 165 TGSI_SEMANTIC_COLOR, 166 0); 167 168 src_sampler = ureg_DECL_sampler(ureg); 169 if (is_composite) { 170 src_pos = ureg_DECL_fs_input(ureg, 171 TGSI_SEMANTIC_POSITION, 172 0, 173 TGSI_INTERPOLATE_PERSPECTIVE); 174 } 175 if (is_fill) { 176 src_pos = ureg_DECL_fs_input(ureg, 177 TGSI_SEMANTIC_COLOR, 178 0, 179 TGSI_INTERPOLATE_PERSPECTIVE); 180 } 181 182 if ((fs_traits & FS_MASK)) { 183 mask_sampler = ureg_DECL_sampler(ureg); 184 mask_pos = ureg_DECL_fs_input(ureg, 185 TGSI_SEMANTIC_POSITION, 186 1, 187 TGSI_INTERPOLATE_PERSPECTIVE); 188 } 189 190#if 0 /* unused right now */ 191 dst_sampler = ureg_DECL_sampler(ureg); 192 dst_pos = ureg_DECL_fs_input(ureg, 193 TGSI_SEMANTIC_POSITION, 194 2, 195 TGSI_INTERPOLATE_PERSPECTIVE); 196#endif 197 198 if ((fs_traits & FS_MASK)) { 199 ureg_TEX(ureg, ureg_dst(mask), 200 TGSI_TEXTURE_2D, mask_pos, mask_sampler); 201 /* src IN mask */ 202 src_in_mask(ureg, out, src, mask); 203 } else { 204 ureg_TEX(ureg, out, 205 TGSI_TEXTURE_2D, src_pos, src_sampler); 206 } 207 208 ureg_END(ureg); 209 210 return ureg_create_shader_and_destroy(ureg, pipe); 211} 212 213struct xorg_shaders * xorg_shaders_create(struct exa_context *exa) 214{ 215 struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders); 216 217 sc->exa = exa; 218 sc->vs_hash = cso_hash_create(); 219 sc->fs_hash = cso_hash_create(); 220 221 return sc; 222} 223 224static void 225cache_destroy(struct cso_context *cso, 226 struct cso_hash *hash, 227 unsigned processor) 228{ 229 struct cso_hash_iter iter = cso_hash_first_node(hash); 230 while (!cso_hash_iter_is_null(iter)) { 231 void *shader = (void *)cso_hash_iter_data(iter); 232 if (processor == PIPE_SHADER_FRAGMENT) { 233 cso_delete_fragment_shader(cso, shader); 234 } else if (processor == PIPE_SHADER_VERTEX) { 235 cso_delete_vertex_shader(cso, shader); 236 } 237 iter = cso_hash_erase(hash, iter); 238 } 239 cso_hash_delete(hash); 240} 241 242void xorg_shaders_destroy(struct xorg_shaders *sc) 243{ 244 cache_destroy(sc->exa->cso, sc->vs_hash, 245 PIPE_SHADER_VERTEX); 246 cache_destroy(sc->exa->cso, sc->fs_hash, 247 PIPE_SHADER_FRAGMENT); 248 249 free(sc); 250} 251 252static INLINE void * 253shader_from_cache(struct pipe_context *pipe, 254 unsigned type, 255 struct cso_hash *hash, 256 unsigned key) 257{ 258 void *shader = 0; 259 260 struct cso_hash_iter iter = cso_hash_find(hash, key); 261 262 if (cso_hash_iter_is_null(iter)) { 263 if (type == PIPE_SHADER_VERTEX) 264 shader = create_vs(pipe, key); 265 else 266 shader = create_fs(pipe, key); 267 cso_hash_insert(hash, key, shader); 268 } else 269 shader = (void *)cso_hash_iter_data(iter); 270 271 return shader; 272} 273 274struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc, 275 unsigned vs_traits, 276 unsigned fs_traits) 277{ 278 struct xorg_shader shader = {0}; 279 void *vs, *fs; 280 281 vs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_VERTEX, 282 sc->vs_hash, vs_traits); 283 fs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_FRAGMENT, 284 sc->fs_hash, fs_traits); 285 286 debug_assert(vs && fs); 287 if (!vs || !fs) 288 return shader; 289 290 shader.vs = vs; 291 shader.fs = fs; 292 293 return shader; 294} 295