Merge branch 'mesa_7_6_branch'
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_ureg.h
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #ifndef TGSI_UREG_H
29 #define TGSI_UREG_H
30
31 #include "pipe/p_compiler.h"
32 #include "pipe/p_shader_tokens.h"
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 struct ureg_program;
39
40 /* Almost a tgsi_src_register, but we need to pull in the Absolute
41 * flag from the _ext token. Indirect flag always implies ADDR[0].
42 */
43 struct ureg_src
44 {
45 unsigned File : 4; /* TGSI_FILE_ */
46 unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
47 unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
48 unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
49 unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
50 unsigned Pad : 1; /* BOOL */
51 unsigned Indirect : 1; /* BOOL */
52 unsigned Absolute : 1; /* BOOL */
53 int Index : 16; /* SINT */
54 unsigned Negate : 1; /* BOOL */
55 int IndirectIndex : 16; /* SINT */
56 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
57 };
58
59 /* Very similar to a tgsi_dst_register, removing unsupported fields
60 * and adding a Saturate flag. It's easier to push saturate into the
61 * destination register than to try and create a _SAT varient of each
62 * instruction function.
63 */
64 struct ureg_dst
65 {
66 unsigned File : 4; /* TGSI_FILE_ */
67 unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
68 unsigned Indirect : 1; /* BOOL */
69 unsigned Saturate : 1; /* BOOL */
70 int Index : 16; /* SINT */
71 unsigned Pad1 : 5;
72 unsigned Pad2 : 1; /* BOOL */
73 int IndirectIndex : 16; /* SINT */
74 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
75 };
76
77 struct pipe_context;
78
79 struct ureg_program *
80 ureg_create( unsigned processor );
81
82 const struct tgsi_token *
83 ureg_finalize( struct ureg_program * );
84
85 /* Create and return a shader:
86 */
87 void *
88 ureg_create_shader( struct ureg_program *,
89 struct pipe_context *pipe );
90
91
92 /* Alternately, return the built token stream and hand ownership of
93 * that memory to the caller:
94 */
95 const struct tgsi_token *
96 ureg_get_tokens( struct ureg_program *ureg,
97 unsigned *nr_tokens );
98
99
100 void
101 ureg_destroy( struct ureg_program * );
102
103
104 /***********************************************************************
105 * Convenience routine:
106 */
107 static INLINE void *
108 ureg_create_shader_and_destroy( struct ureg_program *p,
109 struct pipe_context *pipe )
110 {
111 void *result = ureg_create_shader( p, pipe );
112 ureg_destroy( p );
113 return result;
114 }
115
116
117
118 /***********************************************************************
119 * Build shader declarations:
120 */
121
122 struct ureg_src
123 ureg_DECL_fs_input( struct ureg_program *,
124 unsigned semantic_name,
125 unsigned semantic_index,
126 unsigned interp_mode );
127
128 struct ureg_src
129 ureg_DECL_vs_input( struct ureg_program *,
130 unsigned index );
131
132 struct ureg_dst
133 ureg_DECL_output( struct ureg_program *,
134 unsigned semantic_name,
135 unsigned semantic_index );
136
137 struct ureg_src
138 ureg_DECL_immediate( struct ureg_program *,
139 const float *v,
140 unsigned nr );
141
142 struct ureg_src
143 ureg_DECL_constant( struct ureg_program *,
144 unsigned index );
145
146 struct ureg_dst
147 ureg_DECL_temporary( struct ureg_program * );
148
149 void
150 ureg_release_temporary( struct ureg_program *ureg,
151 struct ureg_dst tmp );
152
153 struct ureg_dst
154 ureg_DECL_address( struct ureg_program * );
155
156 /* Supply an index to the sampler declaration as this is the hook to
157 * the external pipe_sampler state. Users of this function probably
158 * don't want just any sampler, but a specific one which they've set
159 * up state for in the context.
160 */
161 struct ureg_src
162 ureg_DECL_sampler( struct ureg_program *,
163 unsigned index );
164
165
166 static INLINE struct ureg_src
167 ureg_imm4f( struct ureg_program *ureg,
168 float a, float b,
169 float c, float d)
170 {
171 float v[4];
172 v[0] = a;
173 v[1] = b;
174 v[2] = c;
175 v[3] = d;
176 return ureg_DECL_immediate( ureg, v, 4 );
177 }
178
179 static INLINE struct ureg_src
180 ureg_imm3f( struct ureg_program *ureg,
181 float a, float b,
182 float c)
183 {
184 float v[3];
185 v[0] = a;
186 v[1] = b;
187 v[2] = c;
188 return ureg_DECL_immediate( ureg, v, 3 );
189 }
190
191 static INLINE struct ureg_src
192 ureg_imm2f( struct ureg_program *ureg,
193 float a, float b)
194 {
195 float v[2];
196 v[0] = a;
197 v[1] = b;
198 return ureg_DECL_immediate( ureg, v, 2 );
199 }
200
201 static INLINE struct ureg_src
202 ureg_imm1f( struct ureg_program *ureg,
203 float a)
204 {
205 float v[1];
206 v[0] = a;
207 return ureg_DECL_immediate( ureg, v, 1 );
208 }
209
210 /***********************************************************************
211 * Functions for patching up labels
212 */
213
214
215 /* Will return a number which can be used in a label to point to the
216 * next instruction to be emitted.
217 */
218 unsigned
219 ureg_get_instruction_number( struct ureg_program *ureg );
220
221
222 /* Patch a given label (expressed as a token number) to point to a
223 * given instruction (expressed as an instruction number).
224 *
225 * Labels are obtained from instruction emitters, eg ureg_CAL().
226 * Instruction numbers are obtained from ureg_get_instruction_number(),
227 * above.
228 */
229 void
230 ureg_fixup_label(struct ureg_program *ureg,
231 unsigned label_token,
232 unsigned instruction_number );
233
234
235 /* Generic instruction emitter. Use if you need to pass the opcode as
236 * a parameter, rather than using the emit_OP() varients below.
237 */
238 void
239 ureg_insn(struct ureg_program *ureg,
240 unsigned opcode,
241 const struct ureg_dst *dst,
242 unsigned nr_dst,
243 const struct ureg_src *src,
244 unsigned nr_src );
245
246
247 void
248 ureg_tex_insn(struct ureg_program *ureg,
249 unsigned opcode,
250 const struct ureg_dst *dst,
251 unsigned nr_dst,
252 unsigned target,
253 const struct ureg_src *src,
254 unsigned nr_src );
255
256
257 void
258 ureg_label_insn(struct ureg_program *ureg,
259 unsigned opcode,
260 const struct ureg_src *src,
261 unsigned nr_src,
262 unsigned *label);
263
264
265 /***********************************************************************
266 * Internal instruction helpers, don't call these directly:
267 */
268
269 unsigned
270 ureg_emit_insn(struct ureg_program *ureg,
271 unsigned opcode,
272 boolean saturate,
273 unsigned num_dst,
274 unsigned num_src );
275
276 void
277 ureg_emit_label(struct ureg_program *ureg,
278 unsigned insn_token,
279 unsigned *label_token );
280
281 void
282 ureg_emit_texture(struct ureg_program *ureg,
283 unsigned insn_token,
284 unsigned target );
285
286 void
287 ureg_emit_dst( struct ureg_program *ureg,
288 struct ureg_dst dst );
289
290 void
291 ureg_emit_src( struct ureg_program *ureg,
292 struct ureg_src src );
293
294 void
295 ureg_fixup_insn_size(struct ureg_program *ureg,
296 unsigned insn );
297
298
299 #define OP00( op ) \
300 static INLINE void ureg_##op( struct ureg_program *ureg ) \
301 { \
302 unsigned opcode = TGSI_OPCODE_##op; \
303 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
304 ureg_fixup_insn_size( ureg, insn ); \
305 }
306
307 #define OP01( op ) \
308 static INLINE void ureg_##op( struct ureg_program *ureg, \
309 struct ureg_src src ) \
310 { \
311 unsigned opcode = TGSI_OPCODE_##op; \
312 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
313 ureg_emit_src( ureg, src ); \
314 ureg_fixup_insn_size( ureg, insn ); \
315 }
316
317 #define OP00_LBL( op ) \
318 static INLINE void ureg_##op( struct ureg_program *ureg, \
319 unsigned *label_token ) \
320 { \
321 unsigned opcode = TGSI_OPCODE_##op; \
322 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
323 ureg_emit_label( ureg, insn, label_token ); \
324 ureg_fixup_insn_size( ureg, insn ); \
325 }
326
327 #define OP01_LBL( op ) \
328 static INLINE void ureg_##op( struct ureg_program *ureg, \
329 struct ureg_src src, \
330 unsigned *label_token ) \
331 { \
332 unsigned opcode = TGSI_OPCODE_##op; \
333 unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
334 ureg_emit_label( ureg, insn, label_token ); \
335 ureg_emit_src( ureg, src ); \
336 ureg_fixup_insn_size( ureg, insn ); \
337 }
338
339 #define OP10( op ) \
340 static INLINE void ureg_##op( struct ureg_program *ureg, \
341 struct ureg_dst dst ) \
342 { \
343 unsigned opcode = TGSI_OPCODE_##op; \
344 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \
345 ureg_emit_dst( ureg, dst ); \
346 ureg_fixup_insn_size( ureg, insn ); \
347 }
348
349
350 #define OP11( op ) \
351 static INLINE void ureg_##op( struct ureg_program *ureg, \
352 struct ureg_dst dst, \
353 struct ureg_src src ) \
354 { \
355 unsigned opcode = TGSI_OPCODE_##op; \
356 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \
357 ureg_emit_dst( ureg, dst ); \
358 ureg_emit_src( ureg, src ); \
359 ureg_fixup_insn_size( ureg, insn ); \
360 }
361
362 #define OP12( op ) \
363 static INLINE void ureg_##op( struct ureg_program *ureg, \
364 struct ureg_dst dst, \
365 struct ureg_src src0, \
366 struct ureg_src src1 ) \
367 { \
368 unsigned opcode = TGSI_OPCODE_##op; \
369 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
370 ureg_emit_dst( ureg, dst ); \
371 ureg_emit_src( ureg, src0 ); \
372 ureg_emit_src( ureg, src1 ); \
373 ureg_fixup_insn_size( ureg, insn ); \
374 }
375
376 #define OP12_TEX( op ) \
377 static INLINE void ureg_##op( struct ureg_program *ureg, \
378 struct ureg_dst dst, \
379 unsigned target, \
380 struct ureg_src src0, \
381 struct ureg_src src1 ) \
382 { \
383 unsigned opcode = TGSI_OPCODE_##op; \
384 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
385 ureg_emit_texture( ureg, insn, target ); \
386 ureg_emit_dst( ureg, dst ); \
387 ureg_emit_src( ureg, src0 ); \
388 ureg_emit_src( ureg, src1 ); \
389 ureg_fixup_insn_size( ureg, insn ); \
390 }
391
392 #define OP13( op ) \
393 static INLINE void ureg_##op( struct ureg_program *ureg, \
394 struct ureg_dst dst, \
395 struct ureg_src src0, \
396 struct ureg_src src1, \
397 struct ureg_src src2 ) \
398 { \
399 unsigned opcode = TGSI_OPCODE_##op; \
400 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \
401 ureg_emit_dst( ureg, dst ); \
402 ureg_emit_src( ureg, src0 ); \
403 ureg_emit_src( ureg, src1 ); \
404 ureg_emit_src( ureg, src2 ); \
405 ureg_fixup_insn_size( ureg, insn ); \
406 }
407
408 #define OP14_TEX( op ) \
409 static INLINE void ureg_##op( struct ureg_program *ureg, \
410 struct ureg_dst dst, \
411 unsigned target, \
412 struct ureg_src src0, \
413 struct ureg_src src1, \
414 struct ureg_src src2, \
415 struct ureg_src src3 ) \
416 { \
417 unsigned opcode = TGSI_OPCODE_##op; \
418 unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \
419 ureg_emit_texture( ureg, insn, target ); \
420 ureg_emit_dst( ureg, dst ); \
421 ureg_emit_src( ureg, src0 ); \
422 ureg_emit_src( ureg, src1 ); \
423 ureg_emit_src( ureg, src2 ); \
424 ureg_emit_src( ureg, src3 ); \
425 ureg_fixup_insn_size( ureg, insn ); \
426 }
427
428
429 /* Use a template include to generate a correctly-typed ureg_OP()
430 * function for each TGSI opcode:
431 */
432 #include "tgsi_opcode_tmp.h"
433
434
435 /***********************************************************************
436 * Inline helpers for manipulating register structs:
437 */
438 static INLINE struct ureg_src
439 ureg_negate( struct ureg_src reg )
440 {
441 assert(reg.File != TGSI_FILE_NULL);
442 reg.Negate ^= 1;
443 return reg;
444 }
445
446 static INLINE struct ureg_src
447 ureg_abs( struct ureg_src reg )
448 {
449 assert(reg.File != TGSI_FILE_NULL);
450 reg.Absolute = 1;
451 reg.Negate = 0;
452 return reg;
453 }
454
455 static INLINE struct ureg_src
456 ureg_swizzle( struct ureg_src reg,
457 int x, int y, int z, int w )
458 {
459 unsigned swz = ( (reg.SwizzleX << 0) |
460 (reg.SwizzleY << 2) |
461 (reg.SwizzleZ << 4) |
462 (reg.SwizzleW << 6));
463
464 assert(reg.File != TGSI_FILE_NULL);
465 assert(x < 4);
466 assert(y < 4);
467 assert(z < 4);
468 assert(w < 4);
469
470 reg.SwizzleX = (swz >> (x*2)) & 0x3;
471 reg.SwizzleY = (swz >> (y*2)) & 0x3;
472 reg.SwizzleZ = (swz >> (z*2)) & 0x3;
473 reg.SwizzleW = (swz >> (w*2)) & 0x3;
474 return reg;
475 }
476
477 static INLINE struct ureg_src
478 ureg_scalar( struct ureg_src reg, int x )
479 {
480 return ureg_swizzle(reg, x, x, x, x);
481 }
482
483 static INLINE struct ureg_dst
484 ureg_writemask( struct ureg_dst reg,
485 unsigned writemask )
486 {
487 assert(reg.File != TGSI_FILE_NULL);
488 reg.WriteMask &= writemask;
489 return reg;
490 }
491
492 static INLINE struct ureg_dst
493 ureg_saturate( struct ureg_dst reg )
494 {
495 assert(reg.File != TGSI_FILE_NULL);
496 reg.Saturate = 1;
497 return reg;
498 }
499
500 static INLINE struct ureg_dst
501 ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
502 {
503 assert(reg.File != TGSI_FILE_NULL);
504 assert(addr.File == TGSI_FILE_ADDRESS);
505 reg.Indirect = 1;
506 reg.IndirectIndex = addr.Index;
507 reg.IndirectSwizzle = addr.SwizzleX;
508 return reg;
509 }
510
511 static INLINE struct ureg_src
512 ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
513 {
514 assert(reg.File != TGSI_FILE_NULL);
515 assert(addr.File == TGSI_FILE_ADDRESS);
516 reg.Indirect = 1;
517 reg.IndirectIndex = addr.Index;
518 reg.IndirectSwizzle = addr.SwizzleX;
519 return reg;
520 }
521
522 static INLINE struct ureg_dst
523 ureg_dst( struct ureg_src src )
524 {
525 struct ureg_dst dst;
526
527 dst.File = src.File;
528 dst.WriteMask = TGSI_WRITEMASK_XYZW;
529 dst.Indirect = src.Indirect;
530 dst.IndirectIndex = src.IndirectIndex;
531 dst.IndirectSwizzle = src.IndirectSwizzle;
532 dst.Saturate = 0;
533 dst.Index = src.Index;
534 dst.Pad1 = 0;
535 dst.Pad2 = 0;
536
537 return dst;
538 }
539
540 static INLINE struct ureg_src
541 ureg_src( struct ureg_dst dst )
542 {
543 struct ureg_src src;
544
545 src.File = dst.File;
546 src.SwizzleX = TGSI_SWIZZLE_X;
547 src.SwizzleY = TGSI_SWIZZLE_Y;
548 src.SwizzleZ = TGSI_SWIZZLE_Z;
549 src.SwizzleW = TGSI_SWIZZLE_W;
550 src.Pad = 0;
551 src.Indirect = dst.Indirect;
552 src.IndirectIndex = dst.IndirectIndex;
553 src.IndirectSwizzle = dst.IndirectSwizzle;
554 src.Absolute = 0;
555 src.Index = dst.Index;
556 src.Negate = 0;
557
558 return src;
559 }
560
561
562
563 static INLINE struct ureg_dst
564 ureg_dst_undef( void )
565 {
566 struct ureg_dst dst;
567
568 dst.File = TGSI_FILE_NULL;
569 dst.WriteMask = 0;
570 dst.Indirect = 0;
571 dst.IndirectIndex = 0;
572 dst.IndirectSwizzle = 0;
573 dst.Saturate = 0;
574 dst.Index = 0;
575 dst.Pad1 = 0;
576 dst.Pad2 = 0;
577
578 return dst;
579 }
580
581 static INLINE struct ureg_src
582 ureg_src_undef( void )
583 {
584 struct ureg_src src;
585
586 src.File = TGSI_FILE_NULL;
587 src.SwizzleX = 0;
588 src.SwizzleY = 0;
589 src.SwizzleZ = 0;
590 src.SwizzleW = 0;
591 src.Pad = 0;
592 src.Indirect = 0;
593 src.IndirectIndex = 0;
594 src.IndirectSwizzle = 0;
595 src.Absolute = 0;
596 src.Index = 0;
597 src.Negate = 0;
598
599 return src;
600 }
601
602 static INLINE boolean
603 ureg_src_is_undef( struct ureg_src src )
604 {
605 return src.File == TGSI_FILE_NULL;
606 }
607
608 static INLINE boolean
609 ureg_dst_is_undef( struct ureg_dst dst )
610 {
611 return dst.File == TGSI_FILE_NULL;
612 }
613
614
615 #ifdef __cplusplus
616 }
617 #endif
618
619 #endif