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
)
95 reg
.Negate
= NEGATE_NONE
;
97 if (opcode
== OPCODE_KIL
||
98 opcode
== OPCODE_TEX
||
99 opcode
== OPCODE_TXB
||
100 opcode
== OPCODE_TXP
) {
103 if (reg
.Abs
|| (reg
.Negate
!= NEGATE_XYZW
&&
104 reg
.Negate
!= NEGATE_NONE
))
107 for(j
= 0; j
< 4; ++j
) {
108 GLuint swz
= GET_SWZ(reg
.Swizzle
, j
);
109 if (swz
== SWIZZLE_NIL
)
121 for(j
= 0; j
< 3; ++j
)
122 if (GET_SWZ(reg
.Swizzle
, j
) != SWIZZLE_NIL
)
125 if ((reg
.Negate
& relevant
) && (reg
.Negate
& relevant
) != relevant
)
128 if (!lookup_native_swizzle(reg
.Swizzle
))
136 * Generate MOV dst, src using only native swizzles.
138 void r300FPBuildSwizzle(struct nqssadce_state
*s
, struct prog_dst_register dst
, struct prog_src_register src
)
141 src
.Negate
= NEGATE_NONE
;
143 while(dst
.WriteMask
) {
144 const struct swizzle_data
*best_swizzle
= 0;
145 GLuint best_matchcount
= 0;
146 GLuint best_matchmask
= 0;
150 for(i
= 0; i
< num_native_swizzles
; ++i
) {
151 const struct swizzle_data
*sd
= &native_swizzles
[i
];
152 GLuint matchcount
= 0;
153 GLuint matchmask
= 0;
154 for(comp
= 0; comp
< 3; ++comp
) {
155 if (!GET_BIT(dst
.WriteMask
, comp
))
157 GLuint swz
= GET_SWZ(src
.Swizzle
, comp
);
158 if (swz
== SWIZZLE_NIL
)
160 if (swz
== GET_SWZ(sd
->hash
, comp
)) {
162 matchmask
|= 1 << comp
;
165 if (matchcount
> best_matchcount
) {
167 best_matchcount
= matchcount
;
168 best_matchmask
= matchmask
;
169 if (matchmask
== (dst
.WriteMask
& WRITEMASK_XYZ
))
174 if ((src
.Negate
& best_matchmask
) != 0) {
175 best_matchmask
&= src
.Negate
;
176 rgbnegate
= !src
.Negate
;
178 rgbnegate
= src
.Negate
;
181 struct prog_instruction
*inst
;
183 _mesa_insert_instructions(s
->Program
, s
->IP
, 1);
184 inst
= s
->Program
->Instructions
+ s
->IP
++;
185 inst
->Opcode
= OPCODE_MOV
;
187 inst
->DstReg
.WriteMask
&= (best_matchmask
| WRITEMASK_W
);
188 inst
->SrcReg
[0] = src
;
189 /* Note: We rely on NqSSA/DCE to set unused swizzle components to NIL */
191 dst
.WriteMask
&= ~inst
->DstReg
.WriteMask
;
197 * Translate an RGB (XYZ) swizzle into the hardware code for the given
198 * instruction source.
200 GLuint
r300FPTranslateRGBSwizzle(GLuint src
, GLuint swizzle
)
202 const struct swizzle_data
* sd
= lookup_native_swizzle(swizzle
);
205 _mesa_printf("Not a native swizzle: %08x\n", swizzle
);
209 return sd
->base
+ src
*sd
->stride
;
214 * Translate an Alpha (W) swizzle into the hardware code for the given
215 * instruction source.
217 GLuint
r300FPTranslateAlphaSwizzle(GLuint src
, GLuint swizzle
)
220 return swizzle
+ 3*src
;
223 case SWIZZLE_W
: return R300_ALU_ARGA_SRC0A
+ src
;
224 case SWIZZLE_ONE
: return R300_ALU_ARGA_ONE
;
225 case SWIZZLE_ZERO
: return R300_ALU_ARGA_ZERO
;
226 default: return R300_ALU_ARGA_ONE
;