1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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 TUNGSTEN GRAPHICS 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.
26 **************************************************************************/
29 #include "i915_context.h"
33 #define A0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
34 #define D0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
35 #define T0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT)
36 #define A0_SRC0( reg ) (((reg)&UREG_MASK)>>UREG_A0_SRC0_SHIFT_LEFT)
37 #define A1_SRC0( reg ) (((reg)&UREG_MASK)<<UREG_A1_SRC0_SHIFT_RIGHT)
38 #define A1_SRC1( reg ) (((reg)&UREG_MASK)>>UREG_A1_SRC1_SHIFT_LEFT)
39 #define A2_SRC1( reg ) (((reg)&UREG_MASK)<<UREG_A2_SRC1_SHIFT_RIGHT)
40 #define A2_SRC2( reg ) (((reg)&UREG_MASK)>>UREG_A2_SRC2_SHIFT_LEFT)
42 /* These are special, and don't have swizzle/negate bits.
44 #define T0_SAMPLER( reg ) (GET_UREG_NR(reg)<<T0_SAMPLER_NR_SHIFT)
45 #define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg)<<T1_ADDRESS_REG_NR_SHIFT) | \
46 (GET_UREG_TYPE(reg)<<T1_ADDRESS_REG_TYPE_SHIFT))
49 /* Macros for translating UREG's into the various register fields used
50 * by the I915 programmable unit.
52 #define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT)
53 #define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT)
54 #define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
55 #define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT)
56 #define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT)
57 #define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT)
59 #define UREG_MASK 0xffffff00
60 #define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \
61 (REG_NR_MASK << UREG_NR_SHIFT))
65 i915_get_temp(struct i915_fp_compile
*p
)
67 int bit
= ffs(~p
->temp_flag
);
69 i915_program_error(p
, "i915_get_temp: out of temporaries\n");
73 p
->temp_flag
|= 1 << (bit
- 1);
74 return UREG(REG_TYPE_R
, (bit
- 1));
79 i915_get_utemp(struct i915_fp_compile
* p
)
81 int bit
= ffs(~p
->utemp_flag
);
83 i915_program_error(p
, "i915_get_utemp: out of temporaries\n");
87 p
->utemp_flag
|= 1 << (bit
- 1);
88 return UREG(REG_TYPE_U
, (bit
- 1));
92 i915_release_utemps(struct i915_fp_compile
*p
)
99 i915_emit_decl(struct i915_fp_compile
*p
,
100 uint type
, uint nr
, uint d0_flags
)
102 uint reg
= UREG(type
, nr
);
104 if (type
== REG_TYPE_T
) {
105 if (p
->decl_t
& (1 << nr
))
108 p
->decl_t
|= (1 << nr
);
110 else if (type
== REG_TYPE_S
) {
111 if (p
->decl_s
& (1 << nr
))
114 p
->decl_s
|= (1 << nr
);
119 *(p
->decl
++) = (D0_DCL
| D0_DEST(reg
) | d0_flags
);
120 *(p
->decl
++) = D1_MBZ
;
121 *(p
->decl
++) = D2_MBZ
;
128 i915_emit_arith(struct i915_fp_compile
* p
,
132 uint saturate
, uint src0
, uint src1
, uint src2
)
137 assert(GET_UREG_TYPE(dest
) != REG_TYPE_CONST
);
138 dest
= UREG(GET_UREG_TYPE(dest
), GET_UREG_NR(dest
));
141 if (GET_UREG_TYPE(src0
) == REG_TYPE_CONST
)
143 if (GET_UREG_TYPE(src1
) == REG_TYPE_CONST
)
145 if (GET_UREG_TYPE(src2
) == REG_TYPE_CONST
)
148 /* Recursively call this function to MOV additional const values
149 * into temporary registers. Use utemp registers for this -
150 * currently shouldn't be possible to run out, but keep an eye on
154 uint s
[3], first
, i
, old_utemp_flag
;
159 old_utemp_flag
= p
->utemp_flag
;
161 first
= GET_UREG_NR(s
[c
[0]]);
162 for (i
= 1; i
< nr_const
; i
++) {
163 if (GET_UREG_NR(s
[c
[i
]]) != first
) {
164 uint tmp
= i915_get_utemp(p
);
166 i915_emit_arith(p
, A0_MOV
, tmp
, A0_DEST_CHANNEL_ALL
, 0,
175 p
->utemp_flag
= old_utemp_flag
; /* restore */
178 *(p
->csr
++) = (op
| A0_DEST(dest
) | mask
| saturate
| A0_SRC0(src0
));
179 *(p
->csr
++) = (A1_SRC0(src0
) | A1_SRC1(src1
));
180 *(p
->csr
++) = (A2_SRC1(src1
) | A2_SRC2(src2
));
186 uint
i915_emit_texld( struct i915_fp_compile
*p
,
193 uint k
= UREG(GET_UREG_TYPE(coord
), GET_UREG_NR(coord
));
195 /* No real way to work around this in the general case - need to
196 * allocate and declare a new temporary register (a utemp won't
197 * do). Will fallback for now.
199 i915_program_error(p
, "Can't (yet) swizzle TEX arguments");
204 /* Don't worry about saturate as we only support
206 if (destmask
!= A0_DEST_CHANNEL_ALL
) {
207 uint tmp
= i915_get_utemp(p
);
208 i915_emit_texld( p
, tmp
, A0_DEST_CHANNEL_ALL
, sampler
, coord
, op
);
209 i915_emit_arith( p
, A0_MOV
, dest
, destmask
, 0, tmp
, 0, 0 );
213 assert(GET_UREG_TYPE(dest
) != REG_TYPE_CONST
);
214 assert(dest
= UREG(GET_UREG_TYPE(dest
), GET_UREG_NR(dest
)));
216 if (GET_UREG_TYPE(coord
) != REG_TYPE_T
) {
217 p
->nr_tex_indirect
++;
222 T0_SAMPLER( sampler
));
224 *(p
->csr
++) = T1_ADDRESS_REG( coord
);
225 *(p
->csr
++) = T2_MBZ
;
234 i915_emit_const1f(struct i915_fp_compile
* p
, float c0
)
236 struct i915_fragment_shader
*ifs
= p
->shader
;
240 return swizzle(UREG(REG_TYPE_R
, 0), ZERO
, ZERO
, ZERO
, ZERO
);
242 return swizzle(UREG(REG_TYPE_R
, 0), ONE
, ONE
, ONE
, ONE
);
244 for (reg
= 0; reg
< I915_MAX_CONSTANT
; reg
++) {
245 if (ifs
->constant_flags
[reg
] == I915_CONSTFLAG_USER
)
247 for (idx
= 0; idx
< 4; idx
++) {
248 if (!(ifs
->constant_flags
[reg
] & (1 << idx
)) ||
249 ifs
->constants
[reg
][idx
] == c0
) {
250 ifs
->constants
[reg
][idx
] = c0
;
251 ifs
->constant_flags
[reg
] |= 1 << idx
;
252 if (reg
+ 1 > ifs
->num_constants
)
253 ifs
->num_constants
= reg
+ 1;
254 return swizzle(UREG(REG_TYPE_CONST
, reg
), idx
, ZERO
, ZERO
, ONE
);
259 i915_program_error(p
, "i915_emit_const1f: out of constants\n");
264 i915_emit_const2f(struct i915_fp_compile
* p
, float c0
, float c1
)
266 struct i915_fragment_shader
*ifs
= p
->shader
;
270 return swizzle(i915_emit_const1f(p
, c1
), ZERO
, X
, Z
, W
);
272 return swizzle(i915_emit_const1f(p
, c1
), ONE
, X
, Z
, W
);
275 return swizzle(i915_emit_const1f(p
, c0
), X
, ZERO
, Z
, W
);
277 return swizzle(i915_emit_const1f(p
, c0
), X
, ONE
, Z
, W
);
279 for (reg
= 0; reg
< I915_MAX_CONSTANT
; reg
++) {
280 if (ifs
->constant_flags
[reg
] == 0xf ||
281 ifs
->constant_flags
[reg
] == I915_CONSTFLAG_USER
)
283 for (idx
= 0; idx
< 3; idx
++) {
284 if (!(ifs
->constant_flags
[reg
] & (3 << idx
))) {
285 ifs
->constants
[reg
][idx
+ 0] = c0
;
286 ifs
->constants
[reg
][idx
+ 1] = c1
;
287 ifs
->constant_flags
[reg
] |= 3 << idx
;
288 if (reg
+ 1 > ifs
->num_constants
)
289 ifs
->num_constants
= reg
+ 1;
290 return swizzle(UREG(REG_TYPE_CONST
, reg
), idx
, idx
+ 1, ZERO
, ONE
);
295 i915_program_error(p
, "i915_emit_const2f: out of constants\n");
302 i915_emit_const4f(struct i915_fp_compile
* p
,
303 float c0
, float c1
, float c2
, float c3
)
305 struct i915_fragment_shader
*ifs
= p
->shader
;
308 for (reg
= 0; reg
< I915_MAX_CONSTANT
; reg
++) {
309 if (ifs
->constant_flags
[reg
] == 0xf &&
310 ifs
->constants
[reg
][0] == c0
&&
311 ifs
->constants
[reg
][1] == c1
&&
312 ifs
->constants
[reg
][2] == c2
&&
313 ifs
->constants
[reg
][3] == c3
) {
314 return UREG(REG_TYPE_CONST
, reg
);
316 else if (ifs
->constant_flags
[reg
] == 0) {
318 ifs
->constants
[reg
][0] = c0
;
319 ifs
->constants
[reg
][1] = c1
;
320 ifs
->constants
[reg
][2] = c2
;
321 ifs
->constants
[reg
][3] = c3
;
322 ifs
->constant_flags
[reg
] = 0xf;
323 if (reg
+ 1 > ifs
->num_constants
)
324 ifs
->num_constants
= reg
+ 1;
325 return UREG(REG_TYPE_CONST
, reg
);
329 i915_program_error(p
, "i915_emit_const4f: out of constants\n");
335 i915_emit_const4fv(struct i915_fp_compile
* p
, const float * c
)
337 return i915_emit_const4f(p
, c
[0], c
[1], c
[2], c
[3]);