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"
37 #include "radeon_nqssadce.h"
39 #define MAKE_SWZ3(x, y, z) (MAKE_SWIZZLE4(SWIZZLE_##x, SWIZZLE_##y, SWIZZLE_##z, SWIZZLE_ZERO))
42 GLuint hash
; /**< swizzle value this matches */
43 GLuint base
; /**< base value for hw swizzle */
44 GLuint stride
; /**< difference in base between arg0/1/2 */
47 static const struct swizzle_data native_swizzles
[] = {
48 {MAKE_SWZ3(X
, Y
, Z
), R300_ALU_ARGC_SRC0C_XYZ
, 4},
49 {MAKE_SWZ3(X
, X
, X
), R300_ALU_ARGC_SRC0C_XXX
, 4},
50 {MAKE_SWZ3(Y
, Y
, Y
), R300_ALU_ARGC_SRC0C_YYY
, 4},
51 {MAKE_SWZ3(Z
, Z
, Z
), R300_ALU_ARGC_SRC0C_ZZZ
, 4},
52 {MAKE_SWZ3(W
, W
, W
), R300_ALU_ARGC_SRC0A
, 1},
53 {MAKE_SWZ3(Y
, Z
, X
), R300_ALU_ARGC_SRC0C_YZX
, 1},
54 {MAKE_SWZ3(Z
, X
, Y
), R300_ALU_ARGC_SRC0C_ZXY
, 1},
55 {MAKE_SWZ3(W
, Z
, Y
), R300_ALU_ARGC_SRC0CA_WZY
, 1},
56 {MAKE_SWZ3(ONE
, ONE
, ONE
), R300_ALU_ARGC_ONE
, 0},
57 {MAKE_SWZ3(ZERO
, ZERO
, ZERO
), R300_ALU_ARGC_ZERO
, 0}
60 static const int num_native_swizzles
= sizeof(native_swizzles
)/sizeof(native_swizzles
[0]);
64 * Find a native RGB swizzle that matches the given swizzle.
65 * Returns 0 if none found.
67 static const struct swizzle_data
* lookup_native_swizzle(GLuint swizzle
)
71 for(i
= 0; i
< num_native_swizzles
; ++i
) {
72 const struct swizzle_data
* sd
= &native_swizzles
[i
];
73 for(comp
= 0; comp
< 3; ++comp
) {
74 GLuint swz
= GET_SWZ(swizzle
, comp
);
75 if (swz
== SWIZZLE_NIL
)
77 if (swz
!= GET_SWZ(sd
->hash
, comp
))
89 * Check whether the given instruction supports the swizzle and negate
90 * combinations in the given source register.
92 GLboolean
r300FPIsNativeSwizzle(GLuint opcode
, struct prog_src_register reg
)
97 if (opcode
== OPCODE_KIL
||
98 opcode
== OPCODE_TEX
||
99 opcode
== OPCODE_TXB
||
100 opcode
== OPCODE_TXP
) {
103 if (reg
.Abs
|| reg
.NegateBase
!= (15*reg
.NegateAbs
))
106 for(j
= 0; j
< 4; ++j
) {
107 GLuint swz
= GET_SWZ(reg
.Swizzle
, j
);
108 if (swz
== SWIZZLE_NIL
)
120 for(j
= 0; j
< 3; ++j
)
121 if (GET_SWZ(reg
.Swizzle
, j
) != SWIZZLE_NIL
)
124 if ((reg
.NegateBase
& relevant
) && (reg
.NegateBase
& relevant
) != relevant
)
127 if (!lookup_native_swizzle(reg
.Swizzle
))
135 * Generate MOV dst, src using only native swizzles.
137 void r300FPBuildSwizzle(struct nqssadce_state
*s
, struct prog_dst_register dst
, struct prog_src_register src
)
142 while(dst
.WriteMask
) {
143 const struct swizzle_data
*best_swizzle
= 0;
144 GLuint best_matchcount
= 0;
145 GLuint best_matchmask
= 0;
149 for(i
= 0; i
< num_native_swizzles
; ++i
) {
150 const struct swizzle_data
*sd
= &native_swizzles
[i
];
151 GLuint matchcount
= 0;
152 GLuint matchmask
= 0;
153 for(comp
= 0; comp
< 3; ++comp
) {
154 if (!GET_BIT(dst
.WriteMask
, comp
))
156 GLuint swz
= GET_SWZ(src
.Swizzle
, comp
);
157 if (swz
== SWIZZLE_NIL
)
159 if (swz
== GET_SWZ(sd
->hash
, comp
)) {
161 matchmask
|= 1 << comp
;
164 if (matchcount
> best_matchcount
) {
166 best_matchcount
= matchcount
;
167 best_matchmask
= matchmask
;
168 if (matchmask
== (dst
.WriteMask
& WRITEMASK_XYZ
))
173 if ((src
.NegateBase
& best_matchmask
) != 0) {
174 best_matchmask
&= src
.NegateBase
;
175 rgbnegate
= !src
.NegateAbs
;
177 rgbnegate
= src
.NegateAbs
;
180 struct prog_instruction
*inst
;
182 _mesa_insert_instructions(s
->Program
, s
->IP
, 1);
183 inst
= s
->Program
->Instructions
+ s
->IP
++;
184 inst
->Opcode
= OPCODE_MOV
;
186 inst
->DstReg
.WriteMask
&= (best_matchmask
| WRITEMASK_W
);
187 inst
->SrcReg
[0] = src
;
188 /* Note: We rely on NqSSA/DCE to set unused swizzle components to NIL */
190 dst
.WriteMask
&= ~inst
->DstReg
.WriteMask
;
196 * Translate an RGB (XYZ) swizzle into the hardware code for the given
197 * instruction source.
199 GLuint
r300FPTranslateRGBSwizzle(GLuint src
, GLuint swizzle
)
201 const struct swizzle_data
* sd
= lookup_native_swizzle(swizzle
);
204 _mesa_printf("Not a native swizzle: %08x\n", swizzle
);
208 return sd
->base
+ src
*sd
->stride
;
213 * Translate an Alpha (W) swizzle into the hardware code for the given
214 * instruction source.
216 GLuint
r300FPTranslateAlphaSwizzle(GLuint src
, GLuint swizzle
)
219 return swizzle
+ 3*src
;
222 case SWIZZLE_W
: return R300_ALU_ARGA_SRC0A
+ src
;
223 case SWIZZLE_ONE
: return R300_ALU_ARGA_ONE
;
224 case SWIZZLE_ZERO
: return R300_ALU_ARGA_ZERO
;
225 default: return R300_ALU_ARGA_ONE
;