1 //
2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // utilities.cpp: Conversion functions and other utility routines.
8
9 #include "common/utilities.h"
10 #include "common/mathutil.h"
11
12 #if defined(_WIN32)
13 #include <windows.h>
14 #endif
15
16 #include <set>
17
18 namespace gl
19 {
20
UniformComponentCount(GLenum type)21 int UniformComponentCount(GLenum type)
22 {
23 switch (type)
24 {
25 case GL_BOOL:
26 case GL_FLOAT:
27 case GL_INT:
28 case GL_SAMPLER_2D:
29 case GL_SAMPLER_3D:
30 case GL_SAMPLER_CUBE:
31 case GL_SAMPLER_2D_ARRAY:
32 case GL_INT_SAMPLER_2D:
33 case GL_INT_SAMPLER_3D:
34 case GL_INT_SAMPLER_CUBE:
35 case GL_INT_SAMPLER_2D_ARRAY:
36 case GL_UNSIGNED_INT_SAMPLER_2D:
37 case GL_UNSIGNED_INT_SAMPLER_3D:
38 case GL_UNSIGNED_INT_SAMPLER_CUBE:
39 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
40 case GL_SAMPLER_2D_SHADOW:
41 case GL_SAMPLER_CUBE_SHADOW:
42 case GL_SAMPLER_2D_ARRAY_SHADOW:
43 case GL_UNSIGNED_INT:
44 return 1;
45 case GL_BOOL_VEC2:
46 case GL_FLOAT_VEC2:
47 case GL_INT_VEC2:
48 case GL_UNSIGNED_INT_VEC2:
49 return 2;
50 case GL_INT_VEC3:
51 case GL_FLOAT_VEC3:
52 case GL_BOOL_VEC3:
53 case GL_UNSIGNED_INT_VEC3:
54 return 3;
55 case GL_BOOL_VEC4:
56 case GL_FLOAT_VEC4:
57 case GL_INT_VEC4:
58 case GL_UNSIGNED_INT_VEC4:
59 case GL_FLOAT_MAT2:
60 return 4;
61 case GL_FLOAT_MAT2x3:
62 case GL_FLOAT_MAT3x2:
63 return 6;
64 case GL_FLOAT_MAT2x4:
65 case GL_FLOAT_MAT4x2:
66 return 8;
67 case GL_FLOAT_MAT3:
68 return 9;
69 case GL_FLOAT_MAT3x4:
70 case GL_FLOAT_MAT4x3:
71 return 12;
72 case GL_FLOAT_MAT4:
73 return 16;
74 default:
75 UNREACHABLE();
76 }
77
78 return 0;
79 }
80
UniformComponentType(GLenum type)81 GLenum UniformComponentType(GLenum type)
82 {
83 switch(type)
84 {
85 case GL_BOOL:
86 case GL_BOOL_VEC2:
87 case GL_BOOL_VEC3:
88 case GL_BOOL_VEC4:
89 return GL_BOOL;
90 case GL_FLOAT:
91 case GL_FLOAT_VEC2:
92 case GL_FLOAT_VEC3:
93 case GL_FLOAT_VEC4:
94 case GL_FLOAT_MAT2:
95 case GL_FLOAT_MAT3:
96 case GL_FLOAT_MAT4:
97 case GL_FLOAT_MAT2x3:
98 case GL_FLOAT_MAT3x2:
99 case GL_FLOAT_MAT2x4:
100 case GL_FLOAT_MAT4x2:
101 case GL_FLOAT_MAT3x4:
102 case GL_FLOAT_MAT4x3:
103 return GL_FLOAT;
104 case GL_INT:
105 case GL_SAMPLER_2D:
106 case GL_SAMPLER_3D:
107 case GL_SAMPLER_CUBE:
108 case GL_SAMPLER_2D_ARRAY:
109 case GL_INT_SAMPLER_2D:
110 case GL_INT_SAMPLER_3D:
111 case GL_INT_SAMPLER_CUBE:
112 case GL_INT_SAMPLER_2D_ARRAY:
113 case GL_UNSIGNED_INT_SAMPLER_2D:
114 case GL_UNSIGNED_INT_SAMPLER_3D:
115 case GL_UNSIGNED_INT_SAMPLER_CUBE:
116 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
117 case GL_SAMPLER_2D_SHADOW:
118 case GL_SAMPLER_CUBE_SHADOW:
119 case GL_SAMPLER_2D_ARRAY_SHADOW:
120 case GL_INT_VEC2:
121 case GL_INT_VEC3:
122 case GL_INT_VEC4:
123 return GL_INT;
124 case GL_UNSIGNED_INT:
125 case GL_UNSIGNED_INT_VEC2:
126 case GL_UNSIGNED_INT_VEC3:
127 case GL_UNSIGNED_INT_VEC4:
128 return GL_UNSIGNED_INT;
129 default:
130 UNREACHABLE();
131 }
132
133 return GL_NONE;
134 }
135
UniformComponentSize(GLenum type)136 size_t UniformComponentSize(GLenum type)
137 {
138 switch(type)
139 {
140 case GL_BOOL: return sizeof(GLint);
141 case GL_FLOAT: return sizeof(GLfloat);
142 case GL_INT: return sizeof(GLint);
143 case GL_UNSIGNED_INT: return sizeof(GLuint);
144 default: UNREACHABLE();
145 }
146
147 return 0;
148 }
149
UniformInternalSize(GLenum type)150 size_t UniformInternalSize(GLenum type)
151 {
152 // Expanded to 4-element vectors
153 return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4;
154 }
155
UniformExternalSize(GLenum type)156 size_t UniformExternalSize(GLenum type)
157 {
158 return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type);
159 }
160
UniformBoolVectorType(GLenum type)161 GLenum UniformBoolVectorType(GLenum type)
162 {
163 switch (type)
164 {
165 case GL_FLOAT:
166 case GL_INT:
167 case GL_UNSIGNED_INT:
168 return GL_BOOL;
169 case GL_FLOAT_VEC2:
170 case GL_INT_VEC2:
171 case GL_UNSIGNED_INT_VEC2:
172 return GL_BOOL_VEC2;
173 case GL_FLOAT_VEC3:
174 case GL_INT_VEC3:
175 case GL_UNSIGNED_INT_VEC3:
176 return GL_BOOL_VEC3;
177 case GL_FLOAT_VEC4:
178 case GL_INT_VEC4:
179 case GL_UNSIGNED_INT_VEC4:
180 return GL_BOOL_VEC4;
181
182 default:
183 UNREACHABLE();
184 return GL_NONE;
185 }
186 }
187
VariableRowCount(GLenum type)188 int VariableRowCount(GLenum type)
189 {
190 switch (type)
191 {
192 case GL_NONE:
193 case GL_STRUCT_ANGLEX:
194 return 0;
195 case GL_BOOL:
196 case GL_FLOAT:
197 case GL_INT:
198 case GL_UNSIGNED_INT:
199 case GL_BOOL_VEC2:
200 case GL_FLOAT_VEC2:
201 case GL_INT_VEC2:
202 case GL_UNSIGNED_INT_VEC2:
203 case GL_BOOL_VEC3:
204 case GL_FLOAT_VEC3:
205 case GL_INT_VEC3:
206 case GL_UNSIGNED_INT_VEC3:
207 case GL_BOOL_VEC4:
208 case GL_FLOAT_VEC4:
209 case GL_INT_VEC4:
210 case GL_UNSIGNED_INT_VEC4:
211 case GL_SAMPLER_2D:
212 case GL_SAMPLER_3D:
213 case GL_SAMPLER_CUBE:
214 case GL_SAMPLER_2D_ARRAY:
215 case GL_INT_SAMPLER_2D:
216 case GL_INT_SAMPLER_3D:
217 case GL_INT_SAMPLER_CUBE:
218 case GL_INT_SAMPLER_2D_ARRAY:
219 case GL_UNSIGNED_INT_SAMPLER_2D:
220 case GL_UNSIGNED_INT_SAMPLER_3D:
221 case GL_UNSIGNED_INT_SAMPLER_CUBE:
222 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
223 case GL_SAMPLER_2D_SHADOW:
224 case GL_SAMPLER_CUBE_SHADOW:
225 case GL_SAMPLER_2D_ARRAY_SHADOW:
226 return 1;
227 case GL_FLOAT_MAT2:
228 case GL_FLOAT_MAT3x2:
229 case GL_FLOAT_MAT4x2:
230 return 2;
231 case GL_FLOAT_MAT3:
232 case GL_FLOAT_MAT2x3:
233 case GL_FLOAT_MAT4x3:
234 return 3;
235 case GL_FLOAT_MAT4:
236 case GL_FLOAT_MAT2x4:
237 case GL_FLOAT_MAT3x4:
238 return 4;
239 default:
240 UNREACHABLE();
241 }
242
243 return 0;
244 }
245
VariableColumnCount(GLenum type)246 int VariableColumnCount(GLenum type)
247 {
248 switch (type)
249 {
250 case GL_NONE:
251 case GL_STRUCT_ANGLEX:
252 return 0;
253 case GL_BOOL:
254 case GL_FLOAT:
255 case GL_INT:
256 case GL_UNSIGNED_INT:
257 case GL_SAMPLER_2D:
258 case GL_SAMPLER_3D:
259 case GL_SAMPLER_CUBE:
260 case GL_SAMPLER_2D_ARRAY:
261 case GL_INT_SAMPLER_2D:
262 case GL_INT_SAMPLER_3D:
263 case GL_INT_SAMPLER_CUBE:
264 case GL_INT_SAMPLER_2D_ARRAY:
265 case GL_UNSIGNED_INT_SAMPLER_2D:
266 case GL_UNSIGNED_INT_SAMPLER_3D:
267 case GL_UNSIGNED_INT_SAMPLER_CUBE:
268 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
269 case GL_SAMPLER_2D_SHADOW:
270 case GL_SAMPLER_CUBE_SHADOW:
271 case GL_SAMPLER_2D_ARRAY_SHADOW:
272 return 1;
273 case GL_BOOL_VEC2:
274 case GL_FLOAT_VEC2:
275 case GL_INT_VEC2:
276 case GL_UNSIGNED_INT_VEC2:
277 case GL_FLOAT_MAT2:
278 case GL_FLOAT_MAT2x3:
279 case GL_FLOAT_MAT2x4:
280 return 2;
281 case GL_BOOL_VEC3:
282 case GL_FLOAT_VEC3:
283 case GL_INT_VEC3:
284 case GL_UNSIGNED_INT_VEC3:
285 case GL_FLOAT_MAT3:
286 case GL_FLOAT_MAT3x2:
287 case GL_FLOAT_MAT3x4:
288 return 3;
289 case GL_BOOL_VEC4:
290 case GL_FLOAT_VEC4:
291 case GL_INT_VEC4:
292 case GL_UNSIGNED_INT_VEC4:
293 case GL_FLOAT_MAT4:
294 case GL_FLOAT_MAT4x2:
295 case GL_FLOAT_MAT4x3:
296 return 4;
297 default:
298 UNREACHABLE();
299 }
300
301 return 0;
302 }
303
IsSampler(GLenum type)304 bool IsSampler(GLenum type)
305 {
306 switch (type)
307 {
308 case GL_SAMPLER_2D:
309 case GL_SAMPLER_3D:
310 case GL_SAMPLER_CUBE:
311 case GL_SAMPLER_2D_ARRAY:
312 case GL_INT_SAMPLER_2D:
313 case GL_INT_SAMPLER_3D:
314 case GL_INT_SAMPLER_CUBE:
315 case GL_INT_SAMPLER_2D_ARRAY:
316 case GL_UNSIGNED_INT_SAMPLER_2D:
317 case GL_UNSIGNED_INT_SAMPLER_3D:
318 case GL_UNSIGNED_INT_SAMPLER_CUBE:
319 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
320 case GL_SAMPLER_2D_SHADOW:
321 case GL_SAMPLER_CUBE_SHADOW:
322 case GL_SAMPLER_2D_ARRAY_SHADOW:
323 return true;
324 }
325
326 return false;
327 }
328
IsMatrixType(GLenum type)329 bool IsMatrixType(GLenum type)
330 {
331 return VariableRowCount(type) > 1;
332 }
333
TransposeMatrixType(GLenum type)334 GLenum TransposeMatrixType(GLenum type)
335 {
336 if (!IsMatrixType(type))
337 {
338 return type;
339 }
340
341 switch (type)
342 {
343 case GL_FLOAT_MAT2: return GL_FLOAT_MAT2;
344 case GL_FLOAT_MAT3: return GL_FLOAT_MAT3;
345 case GL_FLOAT_MAT4: return GL_FLOAT_MAT4;
346 case GL_FLOAT_MAT2x3: return GL_FLOAT_MAT3x2;
347 case GL_FLOAT_MAT3x2: return GL_FLOAT_MAT2x3;
348 case GL_FLOAT_MAT2x4: return GL_FLOAT_MAT4x2;
349 case GL_FLOAT_MAT4x2: return GL_FLOAT_MAT2x4;
350 case GL_FLOAT_MAT3x4: return GL_FLOAT_MAT4x3;
351 case GL_FLOAT_MAT4x3: return GL_FLOAT_MAT3x4;
352 default: UNREACHABLE(); return GL_NONE;
353 }
354 }
355
MatrixRegisterCount(GLenum type,bool isRowMajorMatrix)356 int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix)
357 {
358 ASSERT(IsMatrixType(type));
359 return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type);
360 }
361
MatrixComponentCount(GLenum type,bool isRowMajorMatrix)362 int MatrixComponentCount(GLenum type, bool isRowMajorMatrix)
363 {
364 ASSERT(IsMatrixType(type));
365 return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type);
366 }
367
AttributeRegisterCount(GLenum type)368 int AttributeRegisterCount(GLenum type)
369 {
370 return IsMatrixType(type) ? VariableColumnCount(type) : 1;
371 }
372
AllocateFirstFreeBits(unsigned int * bits,unsigned int allocationSize,unsigned int bitsSize)373 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
374 {
375 ASSERT(allocationSize <= bitsSize);
376
377 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
378
379 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
380 {
381 if ((*bits & mask) == 0)
382 {
383 *bits |= mask;
384 return i;
385 }
386
387 mask <<= 1;
388 }
389
390 return -1;
391 }
392
IsCubemapTextureTarget(GLenum target)393 bool IsCubemapTextureTarget(GLenum target)
394 {
395 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
396 }
397
IsInternalTextureTarget(GLenum target,GLuint clientVersion)398 bool IsInternalTextureTarget(GLenum target, GLuint clientVersion)
399 {
400 if (clientVersion == 2)
401 {
402 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
403 }
404 else if (clientVersion == 3)
405 {
406 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target) ||
407 target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
408 }
409 else
410 {
411 UNREACHABLE();
412 return false;
413 }
414 }
415
IsTriangleMode(GLenum drawMode)416 bool IsTriangleMode(GLenum drawMode)
417 {
418 switch (drawMode)
419 {
420 case GL_TRIANGLES:
421 case GL_TRIANGLE_FAN:
422 case GL_TRIANGLE_STRIP:
423 return true;
424 case GL_POINTS:
425 case GL_LINES:
426 case GL_LINE_LOOP:
427 case GL_LINE_STRIP:
428 return false;
429 default: UNREACHABLE();
430 }
431
432 return false;
433 }
434
435 }
436
getTempPath()437 std::string getTempPath()
438 {
439 #if defined (_WIN32)
440 char path[MAX_PATH];
441 DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
442 if (pathLen == 0)
443 {
444 UNREACHABLE();
445 return std::string();
446 }
447
448 UINT unique = GetTempFileNameA(path, "sh", 0, path);
449 if (unique == 0)
450 {
451 UNREACHABLE();
452 return std::string();
453 }
454
455 return path;
456 #else
457 UNIMPLEMENTED();
458 return "";
459 #endif
460 }
461
writeFile(const char * path,const void * content,size_t size)462 void writeFile(const char* path, const void* content, size_t size)
463 {
464 FILE* file = fopen(path, "w");
465 if (!file)
466 {
467 UNREACHABLE();
468 return;
469 }
470
471 fwrite(content, sizeof(char), size, file);
472 fclose(file);
473 }
474