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"
38 #include "../r300_reg.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
))
92 * Check whether the given instruction supports the swizzle and negate
93 * combinations in the given source register.
95 static int r300_swizzle_is_native(rc_opcode opcode
, struct rc_src_register reg
)
97 const struct swizzle_data
* sd
;
98 unsigned int relevant
;
102 reg
.Negate
= RC_MASK_NONE
;
104 if (opcode
== RC_OPCODE_KIL
||
105 opcode
== RC_OPCODE_TEX
||
106 opcode
== RC_OPCODE_TXB
||
107 opcode
== RC_OPCODE_TXP
) {
108 if (reg
.Abs
|| reg
.Negate
)
111 for(j
= 0; j
< 4; ++j
) {
112 unsigned int swz
= GET_SWZ(reg
.Swizzle
, j
);
113 if (swz
== RC_SWIZZLE_UNUSED
)
124 for(j
= 0; j
< 3; ++j
)
125 if (GET_SWZ(reg
.Swizzle
, j
) != RC_SWIZZLE_UNUSED
)
128 if ((reg
.Negate
& relevant
) && ((reg
.Negate
& relevant
) != relevant
))
131 sd
= lookup_native_swizzle(reg
.Swizzle
);
132 if (!sd
|| (reg
.File
== RC_FILE_PRESUB
&& sd
->srcp_stride
== 0))
139 static void r300_swizzle_split(
140 struct rc_src_register src
, unsigned int mask
,
141 struct rc_swizzle_split
* split
)
144 src
.Negate
= RC_MASK_NONE
;
146 split
->NumPhases
= 0;
149 const struct swizzle_data
*best_swizzle
= 0;
150 unsigned int best_matchcount
= 0;
151 unsigned int best_matchmask
= 0;
154 for(i
= 0; i
< num_native_swizzles
; ++i
) {
155 const struct swizzle_data
*sd
= &native_swizzles
[i
];
156 unsigned int matchcount
= 0;
157 unsigned int matchmask
= 0;
158 for(comp
= 0; comp
< 3; ++comp
) {
160 if (!GET_BIT(mask
, comp
))
162 swz
= GET_SWZ(src
.Swizzle
, comp
);
163 if (swz
== RC_SWIZZLE_UNUSED
)
165 if (swz
== GET_SWZ(sd
->hash
, comp
)) {
166 /* check if the negate bit of current component
167 * is the same for already matched components */
168 if (matchmask
&& (!!(src
.Negate
& matchmask
) != !!(src
.Negate
& (1 << comp
))))
172 matchmask
|= 1 << comp
;
175 if (matchcount
> best_matchcount
) {
177 best_matchcount
= matchcount
;
178 best_matchmask
= matchmask
;
179 if (matchmask
== (mask
& RC_MASK_XYZ
))
184 if (mask
& RC_MASK_W
)
185 best_matchmask
|= RC_MASK_W
;
187 split
->Phase
[split
->NumPhases
++] = best_matchmask
;
188 mask
&= ~best_matchmask
;
192 struct rc_swizzle_caps r300_swizzle_caps
= {
193 .IsNative
= r300_swizzle_is_native
,
194 .Split
= r300_swizzle_split
199 * Translate an RGB (XYZ) swizzle into the hardware code for the given
200 * instruction source.
202 unsigned int r300FPTranslateRGBSwizzle(unsigned int src
, unsigned int swizzle
)
204 const struct swizzle_data
* sd
= lookup_native_swizzle(swizzle
);
206 if (!sd
|| (src
== RC_PAIR_PRESUB_SRC
&& sd
->srcp_stride
== 0)) {
207 fprintf(stderr
, "Not a native swizzle: %08x\n", swizzle
);
211 if (src
== RC_PAIR_PRESUB_SRC
) {
212 return sd
->base
+ sd
->srcp_stride
;
214 return sd
->base
+ src
*sd
->stride
;
220 * Translate an Alpha (W) swizzle into the hardware code for the given
221 * instruction source.
223 unsigned int r300FPTranslateAlphaSwizzle(unsigned int src
, unsigned int swizzle
)
225 if (src
== RC_PAIR_PRESUB_SRC
) {
226 return R300_ALU_ARGA_SRCP_X
+ swizzle
;
229 return swizzle
+ 3*src
;
232 case RC_SWIZZLE_W
: return R300_ALU_ARGA_SRC0A
+ src
;
233 case RC_SWIZZLE_ONE
: return R300_ALU_ARGA_ONE
;
234 case RC_SWIZZLE_ZERO
: return R300_ALU_ARGA_ZERO
;
235 case RC_SWIZZLE_HALF
: return R300_ALU_ARGA_HALF
;
236 default: return R300_ALU_ARGA_ONE
;