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_assemble.h"
33 #include "slang_storage.h"
34
35 /* _slang_is_swizzle() */
36
37 GLboolean _slang_is_swizzle (const char *field, GLuint rows, slang_swizzle *swz)
38 {
39 GLuint i;
40 GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
41
42 /* the swizzle can be at most 4-component long */
43 swz->num_components = slang_string_length (field);
44 if (swz->num_components > 4)
45 return GL_FALSE;
46
47 for (i = 0; i < swz->num_components; i++)
48 {
49 /* mark which swizzle group is used */
50 switch (field[i])
51 {
52 case 'x':
53 case 'y':
54 case 'z':
55 case 'w':
56 xyzw = GL_TRUE;
57 break;
58 case 'r':
59 case 'g':
60 case 'b':
61 case 'a':
62 rgba = GL_TRUE;
63 break;
64 case 's':
65 case 't':
66 case 'p':
67 case 'q':
68 stpq = GL_TRUE;
69 break;
70 default:
71 return GL_FALSE;
72 }
73
74 /* collect swizzle component */
75 switch (field[i])
76 {
77 case 'x':
78 case 'r':
79 case 's':
80 swz->swizzle[i] = 0;
81 break;
82 case 'y':
83 case 'g':
84 case 't':
85 swz->swizzle[i] = 1;
86 break;
87 case 'z':
88 case 'b':
89 case 'p':
90 swz->swizzle[i] = 2;
91 break;
92 case 'w':
93 case 'a':
94 case 'q':
95 swz->swizzle[i] = 3;
96 break;
97 }
98
99 /* check if the component is valid for given vector's row count */
100 if (rows <= swz->swizzle[i])
101 return GL_FALSE;
102 }
103
104 /* only one swizzle group can be used */
105 if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
106 return GL_FALSE;
107
108 return GL_TRUE;
109 }
110
111 /* _slang_is_swizzle_mask() */
112
113 GLboolean _slang_is_swizzle_mask (const slang_swizzle *swz, GLuint rows)
114 {
115 GLuint i, c = 0;
116
117 /* the swizzle may not be longer than the vector dim */
118 if (swz->num_components > rows)
119 return GL_FALSE;
120
121 /* the swizzle components cannot be duplicated */
122 for (i = 0; i < swz->num_components; i++)
123 {
124 if ((c & (1 << swz->swizzle[i])) != 0)
125 return GL_FALSE;
126 c |= 1 << swz->swizzle[i];
127 }
128
129 return GL_TRUE;
130 }
131
132 /* _slang_multiply_swizzles() */
133
134 GLvoid _slang_multiply_swizzles (slang_swizzle *dst, const slang_swizzle *left,
135 const slang_swizzle *right)
136 {
137 GLuint i;
138
139 dst->num_components = right->num_components;
140 for (i = 0; i < right->num_components; i++)
141 dst->swizzle[i] = left->swizzle[right->swizzle[i]];
142 }
143
144 /* _slang_assemble_constructor() */
145
146 static GLboolean constructor_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *flat,
147 GLuint *index, slang_operation *op, GLuint size)
148 {
149 slang_assembly_typeinfo ti;
150 GLboolean result = GL_FALSE;
151 slang_storage_aggregate agg, flat_agg;
152 GLuint i;
153
154 if (!slang_assembly_typeinfo_construct (&ti))
155 return GL_FALSE;
156 if (!_slang_typeof_operation (A, op, &ti))
157 goto end1;
158
159 if (!slang_storage_aggregate_construct (&agg))
160 goto end1;
161 if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs,
162 A->space.vars, A->mach, A->file, A->atoms))
163 goto end2;
164
165 if (!slang_storage_aggregate_construct (&flat_agg))
166 goto end2;
167 if (!_slang_flatten_aggregate (&flat_agg, &agg))
168 goto end;
169
170 if (!_slang_assemble_operation (A, op, slang_ref_forbid))
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 = GL_TRUE;
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
196 GLboolean _slang_assemble_constructor (slang_assemble_ctx *A, slang_operation *op)
197 {
198 slang_assembly_typeinfo ti;
199 GLboolean result = GL_FALSE;
200 slang_storage_aggregate agg, flat;
201 GLuint size, index, i;
202
203 /* get typeinfo of the constructor (the result of constructor expression) */
204 if (!slang_assembly_typeinfo_construct (&ti))
205 return GL_FALSE;
206 if (!_slang_typeof_operation (A, op, &ti))
207 goto end1;
208
209 /* create an aggregate of the constructor */
210 if (!slang_storage_aggregate_construct (&agg))
211 goto end1;
212 if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs,
213 A->space.vars, A->mach, A->file, A->atoms))
214 goto end2;
215
216 /* calculate size of the constructor */
217 size = _slang_sizeof_aggregate (&agg);
218
219 /* flatten the constructor */
220 if (!slang_storage_aggregate_construct (&flat))
221 goto end2;
222 if (!_slang_flatten_aggregate (&flat, &agg))
223 goto end;
224
225 /* XXX: The children operations are traversed in a reversed order, so it poses a
226 * problem when there is more data than the constructor needs. We must fix it! */
227
228 /* traverse the children that form the constructor expression */
229 index = 0;
230 for (i = op->num_children; i > 0; i--)
231 {
232 if (!constructor_aggregate (A, &flat, &index, &op->children[i - 1], size))
233 goto end;
234 /* TODO: watch the index, if it reaches the size, raise an error */
235 }
236
237 result = GL_TRUE;
238 end:
239 slang_storage_aggregate_destruct (&flat);
240 end2:
241 slang_storage_aggregate_destruct (&agg);
242 end1:
243 slang_assembly_typeinfo_destruct (&ti);
244 return result;
245 }
246
247 /* _slang_assemble_constructor_from_swizzle() */
248
249 GLboolean _slang_assemble_constructor_from_swizzle (slang_assemble_ctx *A, const slang_swizzle *swz,
250 slang_type_specifier *spec, slang_type_specifier *master_spec)
251 {
252 GLuint 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 (A->file, slang_asm_bool_copy,
261 (master_rows - i) * 4, i * 4))
262 return GL_FALSE;
263 break;
264 case slang_spec_int:
265 if (!slang_assembly_file_push_label2 (A->file, slang_asm_int_copy,
266 (master_rows - i) * 4, i * 4))
267 return GL_FALSE;
268 break;
269 case slang_spec_float:
270 if (!slang_assembly_file_push_label2 (A->file, slang_asm_float_copy,
271 (master_rows - i) * 4, i * 4))
272 return GL_FALSE;
273 break;
274 default:
275 break;
276 }
277 }
278 if (!slang_assembly_file_push_label (A->file, slang_asm_local_free, 4))
279 return GL_FALSE;
280 for (i = swz->num_components; i > 0; i--)
281 {
282 GLuint n = i - 1;
283
284 if (!slang_assembly_file_push_label2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
285 return GL_FALSE;
286 if (!slang_assembly_file_push_label (A->file, slang_asm_addr_push, swz->swizzle[n] * 4))
287 return GL_FALSE;
288 if (!slang_assembly_file_push (A->file, slang_asm_addr_add))
289 return GL_FALSE;
290 switch (_slang_type_base (master_spec->type))
291 {
292 case slang_spec_bool:
293 if (!slang_assembly_file_push (A->file, slang_asm_bool_deref))
294 return GL_FALSE;
295 break;
296 case slang_spec_int:
297 if (!slang_assembly_file_push (A->file, slang_asm_int_deref))
298 return GL_FALSE;
299 break;
300 case slang_spec_float:
301 if (!slang_assembly_file_push (A->file, slang_asm_float_deref))
302 return GL_FALSE;
303 break;
304 default:
305 break;
306 }
307 }
308
309 return GL_TRUE;
310 }
311