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
18namespace gl
19{
20
21int 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
81GLenum 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
136size_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
150size_t UniformInternalSize(GLenum type)
151{
152    // Expanded to 4-element vectors
153    return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4;
154}
155
156size_t UniformExternalSize(GLenum type)
157{
158    return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type);
159}
160
161GLenum 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
188int 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
246int 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
304bool 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
329bool IsMatrixType(GLenum type)
330{
331    return VariableRowCount(type) > 1;
332}
333
334GLenum 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
356int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix)
357{
358    ASSERT(IsMatrixType(type));
359    return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type);
360}
361
362int MatrixComponentCount(GLenum type, bool isRowMajorMatrix)
363{
364    ASSERT(IsMatrixType(type));
365    return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type);
366}
367
368int AttributeRegisterCount(GLenum type)
369{
370    return IsMatrixType(type) ? VariableColumnCount(type) : 1;
371}
372
373int 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
393bool IsCubemapTextureTarget(GLenum target)
394{
395    return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
396}
397
398bool 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
416bool 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
437std::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
462void 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