8d910f3c7495f4a98cd867ef8c18e1431498f0c7
[mesa.git] / src / mesa / shader / slang / slang_assemble_constructor.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_assemble_constructor.c
27 * slang constructor and vector swizzle assembler
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_utility.h"
33 #include "slang_assemble_constructor.h"
34 #include "slang_assemble_typeinfo.h"
35 #include "slang_storage.h"
36
37 /* _slang_is_swizzle() */
38
39 int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz)
40 {
41 unsigned int i;
42 int xyzw = 0, rgba = 0, stpq = 0;
43
44 /* the swizzle can be at most 4-component long */
45 swz->num_components = slang_string_length (field);
46 if (swz->num_components > 4)
47 return 0;
48
49 for (i = 0; i < swz->num_components; i++)
50 {
51 /* mark which swizzle group is used */
52 switch (field[i])
53 {
54 case 'x':
55 case 'y':
56 case 'z':
57 case 'w':
58 xyzw = 1;
59 break;
60 case 'r':
61 case 'g':
62 case 'b':
63 case 'a':
64 rgba = 1;
65 break;
66 case 's':
67 case 't':
68 case 'p':
69 case 'q':
70 stpq = 1;
71 break;
72 default:
73 return 0;
74 }
75
76 /* collect swizzle component */
77 switch (field[i])
78 {
79 case 'x':
80 case 'r':
81 case 's':
82 swz->swizzle[i] = 0;
83 break;
84 case 'y':
85 case 'g':
86 case 't':
87 swz->swizzle[i] = 1;
88 break;
89 case 'z':
90 case 'b':
91 case 'p':
92 swz->swizzle[i] = 2;
93 break;
94 case 'w':
95 case 'a':
96 case 'q':
97 swz->swizzle[i] = 3;
98 break;
99 }
100
101 /* check if the component is valid for given vector's row count */
102 if (rows <= swz->swizzle[i])
103 return 0;
104 }
105
106 /* only one swizzle group can be used */
107 if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
108 return 0;
109
110 return 1;
111 }
112
113 /* _slang_is_swizzle_mask() */
114
115 int _slang_is_swizzle_mask (const slang_swizzle *swz, unsigned int rows)
116 {
117 unsigned int i, c = 0;
118
119 /* the swizzle may not be longer than the vector dim */
120 if (swz->num_components > rows)
121 return 0;
122
123 /* the swizzle components cannot be duplicated */
124 for (i = 0; i < swz->num_components; i++)
125 {
126 if ((c & (1 << swz->swizzle[i])) != 0)
127 return 0;
128 c |= 1 << swz->swizzle[i];
129 }
130 return 1;
131 }
132
133 /* _slang_multiply_swizzles() */
134
135 void _slang_multiply_swizzles (slang_swizzle *dst, const slang_swizzle *left,
136 const slang_swizzle *right)
137 {
138 unsigned int i;
139
140 dst->num_components = right->num_components;
141 for (i = 0; i < right->num_components; i++)
142 dst->swizzle[i] = left->swizzle[right->swizzle[i]];
143 }
144
145 /* _slang_assemble_constructor() */
146 #if 0
147 static int constructor_aggregate (slang_assembly_file *file, const slang_storage_aggregate *flat,
148 unsigned int *index, slang_operation *op, unsigned int size, slang_assembly_flow_control *flow,
149 slang_assembly_name_space *space, slang_assembly_local_info *info)
150 {
151 slang_assembly_typeinfo ti;
152 int result;
153 slang_storage_aggregate agg, flat_agg;
154 slang_assembly_stack_info stk;
155 unsigned int i;
156
157 slang_assembly_typeinfo_construct (&ti);
158 if (!(result = _slang_typeof_operation (op, space, &ti)))
159 goto end1;
160
161 slang_storage_aggregate_construct (&agg);
162 if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs,
163 space->vars)))
164 goto end2;
165
166 slang_storage_aggregate_construct (&flat_agg);
167 if (!(result = _slang_flatten_aggregate (&flat_agg, &agg)))
168 goto end;
169
170 if (!(result = _slang_assemble_operation (file, op, 0, flow, space, info, &stk)))
171 goto end;
172
173 for (i = 0; i < flat_agg.count; i++)
174 {
175 const slang_storage_array *arr1 = flat_agg.arrays + i;
176 const slang_storage_array *arr2 = flat->arrays + *index;
177
178 if (arr1->type != arr2->type)
179 {
180 /* TODO: convert (generic) from arr1 to arr2 */
181 }
182 (*index)++;
183 /* TODO: watch the index, if it reaches the size, pop off the stack subsequent values */
184 }
185
186 result = 1;
187 end:
188 slang_storage_aggregate_destruct (&flat_agg);
189 end2:
190 slang_storage_aggregate_destruct (&agg);
191 end1:
192 slang_assembly_typeinfo_destruct (&ti);
193 return result;
194 }
195 #endif
196
197 /* XXX: general swizzle! */
198
199 #if 0
200 int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op,
201 slang_assembly_flow_control *flow, slang_assembly_name_space *space,
202 slang_assembly_local_info *info, struct slang_machine_ *pmach)
203 {
204 slang_assembly_typeinfo ti;
205 int result;
206 slang_storage_aggregate agg, flat;
207 unsigned int size, index, i;
208
209 if (!slang_assembly_typeinfo_construct (&ti))
210 return 0;
211 if (!(result = _slang_typeof_operation (op, space, &ti)))
212 goto end1;
213
214 if (!(result = slang_storage_aggregate_construct (&agg)))
215 goto end1;
216 if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs,
217 space->vars, pmach, file)))
218 goto end2;
219
220 size = _slang_sizeof_aggregate (&agg);
221
222 if (!(result = slang_storage_aggregate_construct (&flat)))
223 goto end2;
224 if (!(result = _slang_flatten_aggregate (&flat, &agg)))
225 goto end;
226
227 index = 0;
228 for (i = 0; i < op->num_children; i++)
229 {
230 if (!(result = constructor_aggregate (file, &flat, &index, op->children + i, size, flow,
231 space, info)))
232 goto end;
233 /* TODO: watch the index, if it reaches the size, raise an error */
234 }
235
236 result = 1;
237 end:
238 slang_storage_aggregate_destruct (&flat);
239 end2:
240 slang_storage_aggregate_destruct (&agg);
241 end1:
242 slang_assembly_typeinfo_destruct (&ti);
243 return result;
244 }
245 #endif
246
247 /* _slang_assemble_constructor_from_swizzle() */
248
249 int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const slang_swizzle *swz,
250 slang_type_specifier *spec, slang_type_specifier *master_spec, slang_assembly_local_info *info)
251 {
252 unsigned int master_rows, i;
253
254 master_rows = _slang_type_dim (master_spec->type);
255 for (i = 0; i < master_rows; i++)
256 {
257 switch (_slang_type_base (master_spec->type))
258 {
259 case slang_spec_bool:
260 if (!slang_assembly_file_push_label2 (file, slang_asm_bool_copy,
261 (master_rows - i) * 4, i * 4))
262 return 0;
263 break;
264 case slang_spec_int:
265 if (!slang_assembly_file_push_label2 (file, slang_asm_int_copy,
266 (master_rows - i) * 4, i * 4))
267 return 0;
268 break;
269 case slang_spec_float:
270 if (!slang_assembly_file_push_label2 (file, slang_asm_float_copy,
271 (master_rows - i) * 4, i * 4))
272 return 0;
273 break;
274 default:
275 break;
276 }
277 }
278 if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))
279 return 0;
280 for (i = swz->num_components; i > 0; i--)
281 {
282 unsigned int n = i - 1;
283
284 if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->swizzle_tmp, 16))
285 return 0;
286 if (!slang_assembly_file_push_label (file, slang_asm_addr_push, swz->swizzle[n] * 4))
287 return 0;
288 if (!slang_assembly_file_push (file, slang_asm_addr_add))
289 return 0;
290 switch (_slang_type_base (master_spec->type))
291 {
292 case slang_spec_bool:
293 if (!slang_assembly_file_push (file, slang_asm_bool_deref))
294 return 0;
295 break;
296 case slang_spec_int:
297 if (!slang_assembly_file_push (file, slang_asm_int_deref))
298 return 0;
299 break;
300 case slang_spec_float:
301 if (!slang_assembly_file_push (file, slang_asm_float_deref))
302 return 0;
303 break;
304 default:
305 break;
306 }
307 }
308 return 1;
309 }
310