2 * Copyright (C) 2008 Nicolai Haehnle.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 * Utilities to deal with the somewhat odd restriction on R300 fragment
34 #include "r300_fragprog_swizzle.h"
39 #include "radeon_compiler.h"
41 #define MAKE_SWZ3(x, y, z) (RC_MAKE_SWIZZLE(RC_SWIZZLE_##x, RC_SWIZZLE_##y, RC_SWIZZLE_##z, RC_SWIZZLE_ZERO))
44 unsigned int hash
; /**< swizzle value this matches */
45 unsigned int base
; /**< base value for hw swizzle */
46 unsigned int stride
; /**< difference in base between arg0/1/2 */
47 unsigned int srcp_stride
; /**< difference in base between arg0/scrp */
50 static const struct swizzle_data native_swizzles
[] = {
51 {MAKE_SWZ3(X
, Y
, Z
), R300_ALU_ARGC_SRC0C_XYZ
, 4, 15},
52 {MAKE_SWZ3(X
, X
, X
), R300_ALU_ARGC_SRC0C_XXX
, 4, 15},
53 {MAKE_SWZ3(Y
, Y
, Y
), R300_ALU_ARGC_SRC0C_YYY
, 4, 15},
54 {MAKE_SWZ3(Z
, Z
, Z
), R300_ALU_ARGC_SRC0C_ZZZ
, 4, 15},
55 {MAKE_SWZ3(W
, W
, W
), R300_ALU_ARGC_SRC0A
, 1, 7},
56 {MAKE_SWZ3(Y
, Z
, X
), R300_ALU_ARGC_SRC0C_YZX
, 1, 0},
57 {MAKE_SWZ3(Z
, X
, Y
), R300_ALU_ARGC_SRC0C_ZXY
, 1, 0},
58 {MAKE_SWZ3(W
, Z
, Y
), R300_ALU_ARGC_SRC0CA_WZY
, 1, 0},
59 {MAKE_SWZ3(ONE
, ONE
, ONE
), R300_ALU_ARGC_ONE
, 0, 0},
60 {MAKE_SWZ3(ZERO
, ZERO
, ZERO
), R300_ALU_ARGC_ZERO
, 0, 0},
61 {MAKE_SWZ3(HALF
, HALF
, HALF
), R300_ALU_ARGC_HALF
, 0, 0}
64 static const int num_native_swizzles
= sizeof(native_swizzles
)/sizeof(native_swizzles
[0]);
67 * Find a native RGB swizzle that matches the given swizzle.
68 * Returns 0 if none found.
70 static const struct swizzle_data
* lookup_native_swizzle(unsigned int swizzle
)
74 for(i
= 0; i
< num_native_swizzles
; ++i
) {
75 const struct swizzle_data
* sd
= &native_swizzles
[i
];
76 for(comp
= 0; comp
< 3; ++comp
) {
77 unsigned int swz
= GET_SWZ(swizzle
, comp
);
78 if (swz
== RC_SWIZZLE_UNUSED
)
80 if (swz
!= GET_SWZ(sd
->hash
, comp
))
91 * Determines if the given swizzle is valid for r300/r400. In most situations
92 * it is better to use r300_swizzle_is_native() which can be accesed via
93 * struct radeon_compiler *c; c->SwizzleCaps->IsNative().
95 int r300_swizzle_is_native_basic(unsigned int swizzle
)
97 if(lookup_native_swizzle(swizzle
))
104 * Check whether the given instruction supports the swizzle and negate
105 * combinations in the given source register.
107 static int r300_swizzle_is_native(rc_opcode opcode
, struct rc_src_register reg
)
109 const struct swizzle_data
* sd
;
110 unsigned int relevant
;
113 if (opcode
== RC_OPCODE_KIL
||
114 opcode
== RC_OPCODE_TEX
||
115 opcode
== RC_OPCODE_TXB
||
116 opcode
== RC_OPCODE_TXP
) {
117 if (reg
.Abs
|| reg
.Negate
)
120 for(j
= 0; j
< 4; ++j
) {
121 unsigned int swz
= GET_SWZ(reg
.Swizzle
, j
);
122 if (swz
== RC_SWIZZLE_UNUSED
)
133 for(j
= 0; j
< 3; ++j
)
134 if (GET_SWZ(reg
.Swizzle
, j
) != RC_SWIZZLE_UNUSED
)
137 if ((reg
.Negate
& relevant
) && ((reg
.Negate
& relevant
) != relevant
))
140 sd
= lookup_native_swizzle(reg
.Swizzle
);
141 if (!sd
|| (reg
.File
== RC_FILE_PRESUB
&& sd
->srcp_stride
== 0))
148 static void r300_swizzle_split(
149 struct rc_src_register src
, unsigned int mask
,
150 struct rc_swizzle_split
* split
)
152 split
->NumPhases
= 0;
155 unsigned int best_matchcount
= 0;
156 unsigned int best_matchmask
= 0;
159 for(i
= 0; i
< num_native_swizzles
; ++i
) {
160 const struct swizzle_data
*sd
= &native_swizzles
[i
];
161 unsigned int matchcount
= 0;
162 unsigned int matchmask
= 0;
163 for(comp
= 0; comp
< 3; ++comp
) {
165 if (!GET_BIT(mask
, comp
))
167 swz
= GET_SWZ(src
.Swizzle
, comp
);
168 if (swz
== RC_SWIZZLE_UNUSED
)
170 if (swz
== GET_SWZ(sd
->hash
, comp
)) {
171 /* check if the negate bit of current component
172 * is the same for already matched components */
173 if (matchmask
&& (!!(src
.Negate
& matchmask
) != !!(src
.Negate
& (1 << comp
))))
177 matchmask
|= 1 << comp
;
180 if (matchcount
> best_matchcount
) {
181 best_matchcount
= matchcount
;
182 best_matchmask
= matchmask
;
183 if (matchmask
== (mask
& RC_MASK_XYZ
))
188 if (mask
& RC_MASK_W
)
189 best_matchmask
|= RC_MASK_W
;
191 split
->Phase
[split
->NumPhases
++] = best_matchmask
;
192 mask
&= ~best_matchmask
;
196 struct rc_swizzle_caps r300_swizzle_caps
= {
197 .IsNative
= r300_swizzle_is_native
,
198 .Split
= r300_swizzle_split
203 * Translate an RGB (XYZ) swizzle into the hardware code for the given
204 * instruction source.
206 unsigned int r300FPTranslateRGBSwizzle(unsigned int src
, unsigned int swizzle
)
208 const struct swizzle_data
* sd
= lookup_native_swizzle(swizzle
);
210 if (!sd
|| (src
== RC_PAIR_PRESUB_SRC
&& sd
->srcp_stride
== 0)) {
211 fprintf(stderr
, "Not a native swizzle: %08x\n", swizzle
);
215 if (src
== RC_PAIR_PRESUB_SRC
) {
216 return sd
->base
+ sd
->srcp_stride
;
218 return sd
->base
+ src
*sd
->stride
;
224 * Translate an Alpha (W) swizzle into the hardware code for the given
225 * instruction source.
227 unsigned int r300FPTranslateAlphaSwizzle(unsigned int src
, unsigned int swizzle
)
229 unsigned int swz
= GET_SWZ(swizzle
, 0);
230 if (src
== RC_PAIR_PRESUB_SRC
) {
231 return R300_ALU_ARGA_SRCP_X
+ swz
;
237 case RC_SWIZZLE_W
: return R300_ALU_ARGA_SRC0A
+ src
;
238 case RC_SWIZZLE_ONE
: return R300_ALU_ARGA_ONE
;
239 case RC_SWIZZLE_ZERO
: return R300_ALU_ARGA_ZERO
;
240 case RC_SWIZZLE_HALF
: return R300_ALU_ARGA_HALF
;
241 default: return R300_ALU_ARGA_ONE
;