More GLSL code.
[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 GLboolean _slang_is_swizzle (const char *field, GLuint rows, slang_swizzle *swz)
40 {
41 GLuint i;
42 GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
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 GL_FALSE;
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 = GL_TRUE;
59 break;
60 case 'r':
61 case 'g':
62 case 'b':
63 case 'a':
64 rgba = GL_TRUE;
65 break;
66 case 's':
67 case 't':
68 case 'p':
69 case 'q':
70 stpq = GL_TRUE;
71 break;
72 default:
73 return GL_FALSE;
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 GL_FALSE;
104 }
105
106 /* only one swizzle group can be used */
107 if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
108 return GL_FALSE;
109
110 return GL_TRUE;
111 }
112
113 /* _slang_is_swizzle_mask() */
114
115 GLboolean _slang_is_swizzle_mask (const slang_swizzle *swz, GLuint rows)
116 {
117 GLuint i, c = 0;
118
119 /* the swizzle may not be longer than the vector dim */
120 if (swz->num_components > rows)
121 return GL_FALSE;
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 GL_FALSE;
128 c |= 1 << swz->swizzle[i];
129 }
130
131 return GL_TRUE;
132 }
133
134 /* _slang_multiply_swizzles() */
135
136 GLvoid _slang_multiply_swizzles (slang_swizzle *dst, const slang_swizzle *left,
137 const slang_swizzle *right)
138 {
139 GLuint i;
140
141 dst->num_components = right->num_components;
142 for (i = 0; i < right->num_components; i++)
143 dst->swizzle[i] = left->swizzle[right->swizzle[i]];
144 }
145
146 /* _slang_assemble_constructor() */
147
148 static GLboolean constructor_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *flat,
149 GLuint *index, slang_operation *op, GLuint size)
150 {
151 slang_assembly_typeinfo ti;
152 GLboolean result = GL_FALSE;
153 slang_storage_aggregate agg, flat_agg;
154 GLuint i;
155
156 if (!slang_assembly_typeinfo_construct (&ti))
157 return GL_FALSE;
158 if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))
159 goto end1;
160
161 if (!slang_storage_aggregate_construct (&agg))
162 goto end1;
163 if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, A->space.funcs, A->space.structs,
164 A->space.vars, A->mach, A->file, A->atoms))
165 goto end2;
166
167 if (!slang_storage_aggregate_construct (&flat_agg))
168 goto end2;
169 if (!_slang_flatten_aggregate (&flat_agg, &agg))
170 goto end;
171
172 if (!_slang_assemble_operation_ (A, op, slang_ref_forbid))
173 goto end;
174
175 for (i = 0; i < flat_agg.count; i++)
176 {
177 const slang_storage_array *arr1 = &flat_agg.arrays[i];
178 const slang_storage_array *arr2 = &flat->arrays[*index];
179
180 if (arr1->type != arr2->type)
181 {
182 /* TODO: convert (generic) from arr1 to arr2 */
183 }
184 (*index)++;
185 /* TODO: watch the index, if it reaches the size, pop off the stack subsequent values */
186 }
187
188 result = GL_TRUE;
189 end:
190 slang_storage_aggregate_destruct (&flat_agg);
191 end2:
192 slang_storage_aggregate_destruct (&agg);
193 end1:
194 slang_assembly_typeinfo_destruct (&ti);
195 return result;
196 }
197
198 GLboolean _slang_assemble_constructor (slang_assemble_ctx *A, slang_operation *op)
199 {
200 slang_assembly_typeinfo ti;
201 GLboolean result = GL_FALSE;
202 slang_storage_aggregate agg, flat;
203 GLuint size, index, i;
204
205 /* get typeinfo of the constructor (the result of constructor expression) */
206 if (!slang_assembly_typeinfo_construct (&ti))
207 return GL_FALSE;
208 if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))
209 goto end1;
210
211 /* create an aggregate of the constructor */
212 if (!slang_storage_aggregate_construct (&agg))
213 goto end1;
214 if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, A->space.funcs, A->space.structs,
215 A->space.vars, A->mach, A->file, A->atoms))
216 goto end2;
217
218 /* calculate size of the constructor */
219 size = _slang_sizeof_aggregate (&agg);
220
221 /* flatten the constructor */
222 if (!slang_storage_aggregate_construct (&flat))
223 goto end2;
224 if (!_slang_flatten_aggregate (&flat, &agg))
225 goto end;
226
227 /* XXX: The children operations are traversed in a reversed order, so it poses a
228 * problem when there is more data than the constructor needs. We must fix it! */
229
230 /* traverse the children that form the constructor expression */
231 index = 0;
232 for (i = op->num_children; i > 0; i--)
233 {
234 if (!constructor_aggregate (A, &flat, &index, &op->children[i - 1], size))
235 goto end;
236 /* TODO: watch the index, if it reaches the size, raise an error */
237 }
238
239 result = GL_TRUE;
240 end:
241 slang_storage_aggregate_destruct (&flat);
242 end2:
243 slang_storage_aggregate_destruct (&agg);
244 end1:
245 slang_assembly_typeinfo_destruct (&ti);
246 return result;
247 }
248
249 /* _slang_assemble_constructor_from_swizzle() */
250
251 GLboolean _slang_assemble_constructor_from_swizzle (slang_assemble_ctx *A, const slang_swizzle *swz,
252 slang_type_specifier *spec, slang_type_specifier *master_spec)
253 {
254 GLuint master_rows, i;
255
256 master_rows = _slang_type_dim (master_spec->type);
257 for (i = 0; i < master_rows; i++)
258 {
259 switch (_slang_type_base (master_spec->type))
260 {
261 case slang_spec_bool:
262 if (!slang_assembly_file_push_label2 (A->file, slang_asm_bool_copy,
263 (master_rows - i) * 4, i * 4))
264 return GL_FALSE;
265 break;
266 case slang_spec_int:
267 if (!slang_assembly_file_push_label2 (A->file, slang_asm_int_copy,
268 (master_rows - i) * 4, i * 4))
269 return GL_FALSE;
270 break;
271 case slang_spec_float:
272 if (!slang_assembly_file_push_label2 (A->file, slang_asm_float_copy,
273 (master_rows - i) * 4, i * 4))
274 return GL_FALSE;
275 break;
276 default:
277 break;
278 }
279 }
280 if (!slang_assembly_file_push_label (A->file, slang_asm_local_free, 4))
281 return GL_FALSE;
282 for (i = swz->num_components; i > 0; i--)
283 {
284 GLuint n = i - 1;
285
286 if (!slang_assembly_file_push_label2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
287 return GL_FALSE;
288 if (!slang_assembly_file_push_label (A->file, slang_asm_addr_push, swz->swizzle[n] * 4))
289 return GL_FALSE;
290 if (!slang_assembly_file_push (A->file, slang_asm_addr_add))
291 return GL_FALSE;
292 switch (_slang_type_base (master_spec->type))
293 {
294 case slang_spec_bool:
295 if (!slang_assembly_file_push (A->file, slang_asm_bool_deref))
296 return GL_FALSE;
297 break;
298 case slang_spec_int:
299 if (!slang_assembly_file_push (A->file, slang_asm_int_deref))
300 return GL_FALSE;
301 break;
302 case slang_spec_float:
303 if (!slang_assembly_file_push (A->file, slang_asm_float_deref))
304 return GL_FALSE;
305 break;
306 default:
307 break;
308 }
309 }
310
311 return GL_TRUE;
312 }
313