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
, ir_dereference
*deref
,
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 static const 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 static const 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 };
80 /* Validate the first character in the swizzle string and look up the base
81 * index value as described above.
83 if ((str
[0] < 'a') || (str
[0] > 'z'))
86 const unsigned base
= base_idx
[str
[0] - 'a'];
89 for (i
= 0; (i
< 4) && (str
[i
] != '\0'); i
++) {
90 /* Validate the next character, and, as described above, convert it to a
93 if ((str
[i
] < 'a') || (str
[i
] > 'z'))
96 swiz_idx
[i
] = idx_map
[str
[i
] - 'a'] - base
;
97 if ((swiz_idx
[i
] < 0) || (swiz_idx
[i
] >= (int) vector_length
))
104 deref
->set_swizzle(swiz_idx
[0], swiz_idx
[1], swiz_idx
[2], swiz_idx
[3], i
);
110 _mesa_ast_field_selection_to_hir(const ast_expression
*expr
,
111 exec_list
*instructions
,
112 struct _mesa_glsl_parse_state
*state
)
115 ir_dereference
*deref
;
119 op
= expr
->subexpressions
[0]->hir(instructions
, state
);
120 deref
= new ir_dereference(op
);
122 /* Initially assume that the resulting type of the field selection is an
123 * error. This make the error paths below a bit easier to follow.
125 deref
->type
= glsl_error_type
;
127 /* If processing the thing being dereferenced generated an error, bail out
128 * now. Doing so prevents spurious error messages from being logged below.
130 if (is_error_type(op
->type
))
133 /* There are two kinds of field selection. There is the selection of a
134 * specific field from a structure, and there is the selection of a
135 * swizzle / mask from a vector. Which is which is determined entirely
136 * by the base type of the thing to which the field selection operator is
139 loc
= expr
->get_location();
140 if (op
->type
->is_vector()) {
141 if (generate_swizzle(expr
->primary_expression
.identifier
,
142 deref
, op
->type
->vector_elements
)) {
143 /* Based on the number of elements in the swizzle and the base type
144 * (i.e., float, int, unsigned, or bool) of the vector being swizzled,
145 * generate the type of the resulting value.
148 glsl_type::get_instance(op
->type
->base_type
,
149 deref
->selector
.swizzle
.num_components
,
152 /* FINISHME: Logging of error messages should be moved into
153 * FINISHME: generate_swizzle. This allows the generation of more
154 * FINISHME: specific error messages.
156 _mesa_glsl_error(& loc
, state
, "Invalid swizzle / mask `%s'",
157 expr
->primary_expression
.identifier
);
159 } else if (op
->type
->base_type
== GLSL_TYPE_STRUCT
) {
160 /* FINISHME: Handle field selection from structures. */
162 _mesa_glsl_error(& loc
, state
, "Cannot access field `%s' of "
163 "non-structure / non-vector.",
164 expr
->primary_expression
.identifier
);