2 * Copyright © 2010 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 #include "main/imports.h"
25 #include "symbol_table.h"
26 #include "glsl_parser_extras.h"
28 #include "glsl_types.h"
37 generate_swizzle(const char *str
, struct ir_swizzle_mask
*swiz
,
38 unsigned vector_length
)
40 /* For each possible swizzle character, this table encodes the value in
41 * \c idx_map that represents the 0th element of the vector. For invalid
42 * swizzle characters (e.g., 'k'), a special value is used that will allow
43 * detection of errors.
45 unsigned char base_idx
[26] = {
46 /* a b c d e f g h i j k l m */
47 R
, R
, I
, I
, I
, I
, R
, I
, I
, I
, I
, I
, I
,
48 /* n o p q r s t u v w x y z */
49 I
, I
, S
, S
, R
, S
, S
, I
, I
, X
, X
, X
, X
52 /* Each valid swizzle character has an entry in the previous table. This
53 * table encodes the base index encoded in the previous table plus the actual
54 * index of the swizzle character. When processing swizzles, the first
55 * character in the string is indexed in the previous table. Each character
56 * in the string is indexed in this table, and the value found there has the
57 * value form the first table subtracted. The result must be on the range
60 * For example, the string "wzyx" will get X from the first table. Each of
61 * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After
62 * subtraction, the swizzle values are { 3, 2, 1, 0 }.
64 * The string "wzrg" will get X from the first table. Each of the characters
65 * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the
66 * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range
67 * [0,3], the error is detected.
69 unsigned char idx_map
[26] = {
70 /* a b c d e f g h i j k l m */
71 R
+3, R
+2, 0, 0, 0, 0, R
+1, 0, 0, 0, 0, 0, 0,
72 /* n o p q r s t u v w x y z */
73 0, 0, S
+2, S
+3, R
+0, S
+0, S
+1, 0, 0, X
+3, X
+0, X
+1, X
+2
76 int swiz_idx
[4] = { 0, 0, 0, 0 };
78 unsigned dup_mask
= 0;
79 unsigned seen_mask
= 0;
83 /* Validate the first character in the swizzle string and look up the base
84 * index value as described above.
86 if ((str
[0] < 'a') || (str
[0] > 'z'))
89 base
= base_idx
[str
[0] - 'a'];
92 for (i
= 0; (i
< 4) && (str
[i
] != '\0'); i
++) {
95 /* Validate the next character, and, as described above, convert it to a
98 if ((str
[i
] < 'a') || (str
[i
] > 'z'))
101 swiz_idx
[i
] = idx_map
[str
[0] - 'a'] - base
;
102 if ((swiz_idx
[i
] < 0) || (swiz_idx
[i
] >= (int) vector_length
))
106 /* Track a bit-mask of the swizzle index values that have been seen. If
107 * a value is seen more than once, set the "duplicate" flag.
109 bit
= (1U << swiz_idx
[i
]);
110 dup_mask
|= seen_mask
& bit
;
117 swiz
->x
= swiz_idx
[0];
118 swiz
->y
= swiz_idx
[1];
119 swiz
->z
= swiz_idx
[2];
120 swiz
->w
= swiz_idx
[3];
121 swiz
->num_components
= i
;
122 swiz
->has_duplicates
= (dup_mask
!= 0);
128 struct ir_instruction
*
129 _mesa_ast_field_selection_to_hir(const ast_expression
*expr
,
130 exec_list
*instructions
,
131 struct _mesa_glsl_parse_state
*state
)
134 ir_dereference
*deref
;
138 op
= expr
->subexpressions
[0]->hir(instructions
, state
);
139 deref
= new ir_dereference(op
);
141 /* Initially assume that the resulting type of the field selection is an
142 * error. This make the error paths below a bit easier to follow.
144 deref
->type
= glsl_error_type
;
146 /* If processing the thing being dereferenced generated an error, bail out
147 * now. Doing so prevents spurious error messages from being logged below.
149 if (is_error_type(op
->type
))
150 return (struct ir_instruction
*) deref
;
152 /* There are two kinds of field selection. There is the selection of a
153 * specific field from a structure, and there is the selection of a
154 * swizzle / mask from a vector. Which is which is determined entirely
155 * by the base type of the thing to which the field selection operator is
158 loc
= expr
->get_location();
159 if (op
->type
->is_vector()) {
160 if (generate_swizzle(expr
->primary_expression
.identifier
,
161 & deref
->selector
.swizzle
,
162 op
->type
->vector_elements
)) {
163 /* Based on the number of elements in the swizzle and the base type
164 * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
165 * generate the type of the resulting value.
168 _mesa_glsl_get_vector_type(op
->type
->base_type
,
169 deref
->selector
.swizzle
.num_components
);
171 /* FINISHME: Logging of error messages should be moved into
172 * FINISHME: generate_swizzle. This allows the generation of more
173 * FINISHME: specific error messages.
175 _mesa_glsl_error(& loc
, state
, "Invalid swizzle / mask `%s'",
176 expr
->primary_expression
.identifier
);
178 } else if (op
->type
->base_type
== GLSL_TYPE_STRUCT
) {
179 /* FINISHME: Handle field selection from structures. */
181 _mesa_glsl_error(& loc
, state
, "Cannot access field `%s' of "
182 "non-structure / non-vector.",
183 expr
->primary_expression
.identifier
);
186 return (struct ir_instruction
*) deref
;