Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright © 2010 Intel Corporation
3
 *
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:
10
 *
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
13
 * Software.
14
 *
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.
22
 */
23
 
24
#include "ast.h"
25
 
26
void
27
ast_type_specifier::print(void) const
28
{
29
   if (structure) {
30
      structure->print();
31
   } else {
32
      printf("%s ", type_name);
33
   }
34
 
35
   if (array_specifier) {
36
      array_specifier->print();
37
   }
38
}
39
 
40
bool
41
ast_fully_specified_type::has_qualifiers() const
42
{
43
   return this->qualifier.flags.i != 0;
44
}
45
 
46
bool ast_type_qualifier::has_interpolation() const
47
{
48
   return this->flags.q.smooth
49
          || this->flags.q.flat
50
          || this->flags.q.noperspective;
51
}
52
 
53
bool
54
ast_type_qualifier::has_layout() const
55
{
56
   return this->flags.q.origin_upper_left
57
          || this->flags.q.pixel_center_integer
58
          || this->flags.q.depth_any
59
          || this->flags.q.depth_greater
60
          || this->flags.q.depth_less
61
          || this->flags.q.depth_unchanged
62
          || this->flags.q.std140
63
          || this->flags.q.shared
64
          || this->flags.q.column_major
65
          || this->flags.q.row_major
66
          || this->flags.q.packed
67
          || this->flags.q.explicit_location
68
          || this->flags.q.explicit_index
69
          || this->flags.q.explicit_binding
70
          || this->flags.q.explicit_offset;
71
}
72
 
73
bool
74
ast_type_qualifier::has_storage() const
75
{
76
   return this->flags.q.constant
77
          || this->flags.q.attribute
78
          || this->flags.q.varying
79
          || this->flags.q.in
80
          || this->flags.q.out
81
          || this->flags.q.uniform;
82
}
83
 
84
bool
85
ast_type_qualifier::has_auxiliary_storage() const
86
{
87
   return this->flags.q.centroid
88
          || this->flags.q.sample;
89
}
90
 
91
const char*
92
ast_type_qualifier::interpolation_string() const
93
{
94
   if (this->flags.q.smooth)
95
      return "smooth";
96
   else if (this->flags.q.flat)
97
      return "flat";
98
   else if (this->flags.q.noperspective)
99
      return "noperspective";
100
   else
101
      return NULL;
102
}
103
 
104
bool
105
ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
106
				    _mesa_glsl_parse_state *state,
107
				    ast_type_qualifier q)
108
{
109
   ast_type_qualifier ubo_mat_mask;
110
   ubo_mat_mask.flags.i = 0;
111
   ubo_mat_mask.flags.q.row_major = 1;
112
   ubo_mat_mask.flags.q.column_major = 1;
113
 
114
   ast_type_qualifier ubo_layout_mask;
115
   ubo_layout_mask.flags.i = 0;
116
   ubo_layout_mask.flags.q.std140 = 1;
117
   ubo_layout_mask.flags.q.packed = 1;
118
   ubo_layout_mask.flags.q.shared = 1;
119
 
120
   ast_type_qualifier ubo_binding_mask;
121
   ubo_binding_mask.flags.i = 0;
122
   ubo_binding_mask.flags.q.explicit_binding = 1;
123
   ubo_binding_mask.flags.q.explicit_offset = 1;
124
 
125
   ast_type_qualifier stream_layout_mask;
126
   stream_layout_mask.flags.i = 0;
127
   stream_layout_mask.flags.q.stream = 1;
128
 
129
   /* Uniform block layout qualifiers get to overwrite each
130
    * other (rightmost having priority), while all other
131
    * qualifiers currently don't allow duplicates.
132
    */
133
   ast_type_qualifier allowed_duplicates_mask;
134
   allowed_duplicates_mask.flags.i =
135
      ubo_mat_mask.flags.i |
136
      ubo_layout_mask.flags.i |
137
      ubo_binding_mask.flags.i;
138
 
139
   /* Geometry shaders can have several layout qualifiers
140
    * assigning different stream values.
141
    */
142
   if (state->stage == MESA_SHADER_GEOMETRY)
143
      allowed_duplicates_mask.flags.i |=
144
         stream_layout_mask.flags.i;
145
 
146
   if ((this->flags.i & q.flags.i & ~allowed_duplicates_mask.flags.i) != 0) {
147
      _mesa_glsl_error(loc, state,
148
		       "duplicate layout qualifiers used");
149
      return false;
150
   }
151
 
152
   if (q.flags.q.prim_type) {
153
      if (this->flags.q.prim_type && this->prim_type != q.prim_type) {
154
	 _mesa_glsl_error(loc, state,
155
			  "conflicting primitive type qualifiers used");
156
	 return false;
157
      }
158
      this->prim_type = q.prim_type;
159
   }
160
 
161
   if (q.flags.q.max_vertices) {
162
      if (this->flags.q.max_vertices && this->max_vertices != q.max_vertices) {
163
	 _mesa_glsl_error(loc, state,
164
			  "geometry shader set conflicting max_vertices "
165
			  "(%d and %d)", this->max_vertices, q.max_vertices);
166
	 return false;
167
      }
168
      this->max_vertices = q.max_vertices;
169
   }
170
 
171
   if (q.flags.q.invocations) {
172
      if (this->flags.q.invocations && this->invocations != q.invocations) {
173
         _mesa_glsl_error(loc, state,
174
                          "geometry shader set conflicting invocations "
175
                          "(%d and %d)", this->invocations, q.invocations);
176
         return false;
177
      }
178
      this->invocations = q.invocations;
179
   }
180
 
181
   if (state->stage == MESA_SHADER_GEOMETRY &&
182
       state->has_explicit_attrib_stream()) {
183
      if (q.flags.q.stream && q.stream >= state->ctx->Const.MaxVertexStreams) {
184
         _mesa_glsl_error(loc, state,
185
                          "`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
186
                          "(%d > %d)",
187
                          q.stream, state->ctx->Const.MaxVertexStreams - 1);
188
      }
189
      if (this->flags.q.explicit_stream &&
190
          this->stream >= state->ctx->Const.MaxVertexStreams) {
191
         _mesa_glsl_error(loc, state,
192
                          "`stream' value is larger than MAX_VERTEX_STREAMS - 1 "
193
                          "(%d > %d)",
194
                          this->stream, state->ctx->Const.MaxVertexStreams - 1);
195
      }
196
 
197
      if (!this->flags.q.explicit_stream) {
198
         if (q.flags.q.stream) {
199
            this->flags.q.stream = 1;
200
            this->stream = q.stream;
201
         } else if (!this->flags.q.stream && this->flags.q.out) {
202
            /* Assign default global stream value */
203
            this->flags.q.stream = 1;
204
            this->stream = state->out_qualifier->stream;
205
         }
206
      } else {
207
         if (q.flags.q.explicit_stream) {
208
            _mesa_glsl_error(loc, state,
209
                             "duplicate layout `stream' qualifier");
210
         }
211
      }
212
   }
213
 
214
   if ((q.flags.i & ubo_mat_mask.flags.i) != 0)
215
      this->flags.i &= ~ubo_mat_mask.flags.i;
216
   if ((q.flags.i & ubo_layout_mask.flags.i) != 0)
217
      this->flags.i &= ~ubo_layout_mask.flags.i;
218
 
219
   for (int i = 0; i < 3; i++) {
220
      if (q.flags.q.local_size & (1 << i)) {
221
         if ((this->flags.q.local_size & (1 << i)) &&
222
             this->local_size[i] != q.local_size[i]) {
223
            _mesa_glsl_error(loc, state,
224
                             "compute shader set conflicting values for "
225
                             "local_size_%c (%d and %d)", 'x' + i,
226
                             this->local_size[i], q.local_size[i]);
227
            return false;
228
         }
229
         this->local_size[i] = q.local_size[i];
230
      }
231
   }
232
 
233
   this->flags.i |= q.flags.i;
234
 
235
   if (q.flags.q.explicit_location)
236
      this->location = q.location;
237
 
238
   if (q.flags.q.explicit_index)
239
      this->index = q.index;
240
 
241
   if (q.flags.q.explicit_binding)
242
      this->binding = q.binding;
243
 
244
   if (q.flags.q.explicit_offset)
245
      this->offset = q.offset;
246
 
247
   if (q.precision != ast_precision_none)
248
      this->precision = q.precision;
249
 
250
   if (q.flags.q.explicit_image_format) {
251
      this->image_format = q.image_format;
252
      this->image_base_type = q.image_base_type;
253
   }
254
 
255
   return true;
256
}
257
 
258
bool
259
ast_type_qualifier::merge_in_qualifier(YYLTYPE *loc,
260
                                       _mesa_glsl_parse_state *state,
261
                                       ast_type_qualifier q,
262
                                       ast_node* &node)
263
{
264
   void *mem_ctx = state;
265
   bool create_gs_ast = false;
266
   bool create_cs_ast = false;
267
   ast_type_qualifier valid_in_mask;
268
   valid_in_mask.flags.i = 0;
269
 
270
   switch (state->stage) {
271
   case MESA_SHADER_GEOMETRY:
272
      if (q.flags.q.prim_type) {
273
         /* Make sure this is a valid input primitive type. */
274
         switch (q.prim_type) {
275
         case GL_POINTS:
276
         case GL_LINES:
277
         case GL_LINES_ADJACENCY:
278
         case GL_TRIANGLES:
279
         case GL_TRIANGLES_ADJACENCY:
280
            break;
281
         default:
282
            _mesa_glsl_error(loc, state,
283
                             "invalid geometry shader input primitive type");
284
            break;
285
         }
286
      }
287
 
288
      create_gs_ast |=
289
         q.flags.q.prim_type &&
290
         !state->in_qualifier->flags.q.prim_type;
291
 
292
      valid_in_mask.flags.q.prim_type = 1;
293
      valid_in_mask.flags.q.invocations = 1;
294
      break;
295
   case MESA_SHADER_FRAGMENT:
296
      valid_in_mask.flags.q.early_fragment_tests = 1;
297
      break;
298
   case MESA_SHADER_COMPUTE:
299
      create_cs_ast |=
300
         q.flags.q.local_size != 0 &&
301
         state->in_qualifier->flags.q.local_size == 0;
302
 
303
      valid_in_mask.flags.q.local_size = 7;
304
      break;
305
   default:
306
      _mesa_glsl_error(loc, state,
307
                       "input layout qualifiers only valid in "
308
                       "geometry, fragment and compute shaders");
309
      break;
310
   }
311
 
312
   /* Generate an error when invalid input layout qualifiers are used. */
313
   if ((q.flags.i & ~valid_in_mask.flags.i) != 0) {
314
      _mesa_glsl_error(loc, state,
315
		       "invalid input layout qualifiers used");
316
      return false;
317
   }
318
 
319
   /* Input layout qualifiers can be specified multiple
320
    * times in separate declarations, as long as they match.
321
    */
322
   if (this->flags.q.prim_type) {
323
      if (q.flags.q.prim_type &&
324
          this->prim_type != q.prim_type) {
325
         _mesa_glsl_error(loc, state,
326
                          "conflicting input primitive types specified");
327
      }
328
   } else if (q.flags.q.prim_type) {
329
      state->in_qualifier->flags.q.prim_type = 1;
330
      state->in_qualifier->prim_type = q.prim_type;
331
   }
332
 
333
   if (this->flags.q.invocations &&
334
       q.flags.q.invocations &&
335
       this->invocations != q.invocations) {
336
      _mesa_glsl_error(loc, state,
337
                       "conflicting invocations counts specified");
338
      return false;
339
   } else if (q.flags.q.invocations) {
340
      this->flags.q.invocations = 1;
341
      this->invocations = q.invocations;
342
   }
343
 
344
   if (q.flags.q.early_fragment_tests) {
345
      state->fs_early_fragment_tests = true;
346
   }
347
 
348
   if (create_gs_ast) {
349
      node = new(mem_ctx) ast_gs_input_layout(*loc, q.prim_type);
350
   } else if (create_cs_ast) {
351
      /* Infer a local_size of 1 for every unspecified dimension */
352
      unsigned local_size[3];
353
      for (int i = 0; i < 3; i++) {
354
         if (q.flags.q.local_size & (1 << i))
355
            local_size[i] = q.local_size[i];
356
         else
357
            local_size[i] = 1;
358
      }
359
      node = new(mem_ctx) ast_cs_input_layout(*loc, local_size);
360
   }
361
 
362
   return true;
363
}