blob: d528ec2f00ecf3d4293eef49e3f5220827d01308 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// 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
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +00009#include "common/utilities.h"
10#include "common/mathutil.h"
11
12#include <set>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000014namespace gl
15{
16
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +000017int UniformComponentCount(GLenum type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000018{
19 switch (type)
20 {
21 case GL_BOOL:
22 case GL_FLOAT:
23 case GL_INT:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +000024 case GL_SAMPLER_2D:
25 case GL_SAMPLER_CUBE:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +000026 case GL_UNSIGNED_INT:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000027 return 1;
28 case GL_BOOL_VEC2:
29 case GL_FLOAT_VEC2:
30 case GL_INT_VEC2:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +000031 case GL_UNSIGNED_INT_VEC2:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000032 return 2;
33 case GL_INT_VEC3:
34 case GL_FLOAT_VEC3:
35 case GL_BOOL_VEC3:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +000036 case GL_UNSIGNED_INT_VEC3:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000037 return 3;
38 case GL_BOOL_VEC4:
39 case GL_FLOAT_VEC4:
40 case GL_INT_VEC4:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +000041 case GL_UNSIGNED_INT_VEC4:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000042 case GL_FLOAT_MAT2:
43 return 4;
shannon.woods%transgaming.com@gtempaccount.come6ca6702013-04-13 03:40:44 +000044 case GL_FLOAT_MAT2x3:
45 case GL_FLOAT_MAT3x2:
46 return 6;
47 case GL_FLOAT_MAT2x4:
48 case GL_FLOAT_MAT4x2:
49 return 8;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000050 case GL_FLOAT_MAT3:
51 return 9;
shannon.woods%transgaming.com@gtempaccount.come6ca6702013-04-13 03:40:44 +000052 case GL_FLOAT_MAT3x4:
53 case GL_FLOAT_MAT4x3:
54 return 12;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000055 case GL_FLOAT_MAT4:
56 return 16;
57 default:
58 UNREACHABLE();
59 }
60
61 return 0;
62}
63
64GLenum UniformComponentType(GLenum type)
65{
66 switch(type)
67 {
68 case GL_BOOL:
69 case GL_BOOL_VEC2:
70 case GL_BOOL_VEC3:
71 case GL_BOOL_VEC4:
72 return GL_BOOL;
73 case GL_FLOAT:
74 case GL_FLOAT_VEC2:
75 case GL_FLOAT_VEC3:
76 case GL_FLOAT_VEC4:
77 case GL_FLOAT_MAT2:
78 case GL_FLOAT_MAT3:
79 case GL_FLOAT_MAT4:
shannon.woods%transgaming.com@gtempaccount.come6ca6702013-04-13 03:40:44 +000080 case GL_FLOAT_MAT2x3:
81 case GL_FLOAT_MAT3x2:
82 case GL_FLOAT_MAT2x4:
83 case GL_FLOAT_MAT4x2:
84 case GL_FLOAT_MAT3x4:
85 case GL_FLOAT_MAT4x3:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000086 return GL_FLOAT;
87 case GL_INT:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +000088 case GL_SAMPLER_2D:
89 case GL_SAMPLER_CUBE:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000090 case GL_INT_VEC2:
91 case GL_INT_VEC3:
92 case GL_INT_VEC4:
93 return GL_INT;
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +000094 case GL_UNSIGNED_INT:
95 case GL_UNSIGNED_INT_VEC2:
96 case GL_UNSIGNED_INT_VEC3:
97 case GL_UNSIGNED_INT_VEC4:
98 return GL_UNSIGNED_INT;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000099 default:
100 UNREACHABLE();
101 }
102
103 return GL_NONE;
104}
105
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000106size_t UniformComponentSize(GLenum type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000107{
108 switch(type)
109 {
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +0000110 case GL_BOOL: return sizeof(GLint);
111 case GL_FLOAT: return sizeof(GLfloat);
112 case GL_INT: return sizeof(GLint);
113 case GL_UNSIGNED_INT: return sizeof(GLuint);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000114 default: UNREACHABLE();
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000115 }
116
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000117 return 0;
118}
119
daniel@transgaming.come918ea22011-11-12 03:15:28 +0000120size_t UniformInternalSize(GLenum type)
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000121{
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000122 // Expanded to 4-element vectors
123 return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000124}
125
daniel@transgaming.com47c60052011-11-12 03:17:50 +0000126size_t UniformExternalSize(GLenum type)
127{
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000128 return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type);
daniel@transgaming.com47c60052011-11-12 03:17:50 +0000129}
130
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000131GLenum UniformBoolVectorType(GLenum type)
132{
133 switch (type)
134 {
135 case GL_FLOAT:
136 case GL_INT:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +0000137 case GL_UNSIGNED_INT:
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000138 return GL_BOOL;
139 case GL_FLOAT_VEC2:
140 case GL_INT_VEC2:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +0000141 case GL_UNSIGNED_INT_VEC2:
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000142 return GL_BOOL_VEC2;
143 case GL_FLOAT_VEC3:
144 case GL_INT_VEC3:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +0000145 case GL_UNSIGNED_INT_VEC3:
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000146 return GL_BOOL_VEC3;
147 case GL_FLOAT_VEC4:
148 case GL_INT_VEC4:
shannon.woods%transgaming.com@gtempaccount.com44ce5b12013-04-13 03:40:30 +0000149 case GL_UNSIGNED_INT_VEC4:
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000150 return GL_BOOL_VEC4;
151
152 default:
153 UNREACHABLE();
154 return GL_NONE;
155 }
156}
157
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000158int VariableRowCount(GLenum type)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000159{
160 switch (type)
161 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000162 case GL_NONE:
163 return 0;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000164 case GL_BOOL:
165 case GL_FLOAT:
166 case GL_INT:
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000167 case GL_UNSIGNED_INT:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000168 case GL_BOOL_VEC2:
169 case GL_FLOAT_VEC2:
170 case GL_INT_VEC2:
171 case GL_INT_VEC3:
172 case GL_FLOAT_VEC3:
173 case GL_BOOL_VEC3:
174 case GL_BOOL_VEC4:
175 case GL_FLOAT_VEC4:
176 case GL_INT_VEC4:
daniel@transgaming.comda8d3802012-12-20 21:12:55 +0000177 case GL_SAMPLER_2D:
178 case GL_SAMPLER_CUBE:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000179 return 1;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000180 case GL_FLOAT_MAT2:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000181 case GL_FLOAT_MAT3x2:
182 case GL_FLOAT_MAT4x2:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000183 return 2;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000184 case GL_FLOAT_MAT3:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000185 case GL_FLOAT_MAT2x3:
186 case GL_FLOAT_MAT4x3:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000187 return 3;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000188 case GL_FLOAT_MAT4:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000189 case GL_FLOAT_MAT2x4:
190 case GL_FLOAT_MAT3x4:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000191 return 4;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000192 default:
193 UNREACHABLE();
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000194 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000195
196 return 0;
197}
198
199int VariableColumnCount(GLenum type)
200{
201 switch (type)
202 {
203 case GL_NONE:
204 return 0;
205 case GL_BOOL:
206 case GL_FLOAT:
207 case GL_INT:
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000208 case GL_UNSIGNED_INT:
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000209 case GL_SAMPLER_2D:
210 case GL_SAMPLER_CUBE:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000211 return 1;
212 case GL_BOOL_VEC2:
213 case GL_FLOAT_VEC2:
214 case GL_INT_VEC2:
215 case GL_FLOAT_MAT2:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000216 case GL_FLOAT_MAT2x3:
217 case GL_FLOAT_MAT2x4:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000218 return 2;
219 case GL_INT_VEC3:
220 case GL_FLOAT_VEC3:
221 case GL_BOOL_VEC3:
222 case GL_FLOAT_MAT3:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000223 case GL_FLOAT_MAT3x2:
224 case GL_FLOAT_MAT3x4:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000225 return 3;
226 case GL_BOOL_VEC4:
227 case GL_FLOAT_VEC4:
228 case GL_INT_VEC4:
229 case GL_FLOAT_MAT4:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000230 case GL_FLOAT_MAT4x2:
231 case GL_FLOAT_MAT4x3:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000232 return 4;
233 default:
234 UNREACHABLE();
235 }
236
237 return 0;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000238}
239
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000240bool IsMatrixType(GLenum type)
241{
242 return VariableRowCount(type) > 1;
243}
244
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000245GLenum TransposeMatrixType(GLenum type)
246{
247 if (!IsMatrixType(type))
248 {
249 return type;
250 }
251
252 switch (type)
253 {
254 case GL_FLOAT_MAT2: return GL_FLOAT_MAT2;
255 case GL_FLOAT_MAT3: return GL_FLOAT_MAT3;
256 case GL_FLOAT_MAT4: return GL_FLOAT_MAT4;
257 case GL_FLOAT_MAT2x3: return GL_FLOAT_MAT3x2;
258 case GL_FLOAT_MAT3x2: return GL_FLOAT_MAT2x3;
259 case GL_FLOAT_MAT2x4: return GL_FLOAT_MAT4x2;
260 case GL_FLOAT_MAT4x2: return GL_FLOAT_MAT2x4;
261 case GL_FLOAT_MAT3x4: return GL_FLOAT_MAT4x3;
262 case GL_FLOAT_MAT4x3: return GL_FLOAT_MAT3x4;
263 default: UNREACHABLE(); return GL_NONE;
264 }
265}
266
267int AttributeRegisterCount(GLenum type)
268{
269 return IsMatrixType(type) ? VariableColumnCount(type) : 1;
270}
271
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000272int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
273{
274 ASSERT(allocationSize <= bitsSize);
275
276 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
277
278 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
279 {
280 if ((*bits & mask) == 0)
281 {
282 *bits |= mask;
283 return i;
284 }
285
286 mask <<= 1;
287 }
288
289 return -1;
290}
291
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000292bool IsStencilTexture(GLenum format)
293{
294 if (format == GL_DEPTH_STENCIL_OES ||
295 format == GL_DEPTH24_STENCIL8_OES)
296 {
297 return true;
298 }
299
300 return false;
301}
302
daniel@transgaming.comb9d7e6f2012-10-31 19:08:32 +0000303void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
304{
305 int upsampleCount = 0;
306
307 if (isCompressed)
308 {
309 // Don't expand the size of full textures that are at least 4x4
310 // already.
311 if (isImage || *requestWidth < 4 || *requestHeight < 4)
312 {
313 while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
314 {
315 *requestWidth <<= 1;
316 *requestHeight <<= 1;
317 upsampleCount++;
318 }
319 }
320 }
321 *levelOffset = upsampleCount;
322}
323
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000324// Returns the size, in bytes, of a single texel in an Image
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000325int ComputePixelSize(GLint internalformat)
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000326{
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000327 switch (internalformat)
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000328 {
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000329 case GL_ALPHA8_EXT: return sizeof(unsigned char);
330 case GL_LUMINANCE8_EXT: return sizeof(unsigned char);
331 case GL_ALPHA32F_EXT: return sizeof(float);
332 case GL_LUMINANCE32F_EXT: return sizeof(float);
333 case GL_ALPHA16F_EXT: return sizeof(unsigned short);
334 case GL_LUMINANCE16F_EXT: return sizeof(unsigned short);
335 case GL_LUMINANCE8_ALPHA8_EXT: return sizeof(unsigned char) * 2;
336 case GL_LUMINANCE_ALPHA32F_EXT: return sizeof(float) * 2;
337 case GL_LUMINANCE_ALPHA16F_EXT: return sizeof(unsigned short) * 2;
338 case GL_RGB8_OES: return sizeof(unsigned char) * 3;
339 case GL_RGB565: return sizeof(unsigned short);
340 case GL_RGB32F_EXT: return sizeof(float) * 3;
341 case GL_RGB16F_EXT: return sizeof(unsigned short) * 3;
342 case GL_RGBA8_OES: return sizeof(unsigned char) * 4;
343 case GL_RGBA4: return sizeof(unsigned short);
344 case GL_RGB5_A1: return sizeof(unsigned short);
345 case GL_RGBA32F_EXT: return sizeof(float) * 4;
346 case GL_RGBA16F_EXT: return sizeof(unsigned short) * 4;
347 case GL_BGRA8_EXT: return sizeof(unsigned char) * 4;
shannon.woods%transgaming.com@gtempaccount.com8dce6512013-04-13 03:42:19 +0000348 case GL_SRGB8_ALPHA8: return sizeof(unsigned char) * 4;
349 case GL_RGB10_A2: return sizeof(unsigned char) * 4;
350 case GL_RG8: return sizeof(unsigned char) * 2;
351 case GL_R8: return sizeof(unsigned char);
daniel@transgaming.com6b1a0a02012-10-17 18:22:47 +0000352 case GL_BGRA4_ANGLEX: return sizeof(unsigned short);
353 case GL_BGR5_A1_ANGLEX: return sizeof(unsigned short);
shannon.woods%transgaming.com@gtempaccount.com8dce6512013-04-13 03:42:19 +0000354 default:
355 UNIMPLEMENTED(); // TODO: Remaining ES3 formats
356 UNREACHABLE();
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000357 }
358
359 return 0;
360}
361
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000362bool IsCubemapTextureTarget(GLenum target)
363{
364 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
365}
366
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000367bool IsInternalTextureTarget(GLenum target)
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000368{
369 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
370}
371
daniel@transgaming.com97c852b2012-12-20 20:56:23 +0000372bool IsTriangleMode(GLenum drawMode)
373{
374 switch (drawMode)
375 {
376 case GL_TRIANGLES:
377 case GL_TRIANGLE_FAN:
378 case GL_TRIANGLE_STRIP:
379 return true;
380 case GL_POINTS:
381 case GL_LINES:
382 case GL_LINE_LOOP:
383 case GL_LINE_STRIP:
384 return false;
385 default: UNREACHABLE();
386 }
387
388 return false;
389}
390
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000391}
392
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000393std::string getTempPath()
394{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000395 char path[MAX_PATH];
396 DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
397 if (pathLen == 0)
398 {
399 UNREACHABLE();
400 return std::string();
401 }
402
403 UINT unique = GetTempFileNameA(path, "sh", 0, path);
404 if (unique == 0)
405 {
406 UNREACHABLE();
407 return std::string();
408 }
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +0000409
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000410 return path;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000411}
412
413void writeFile(const char* path, const void* content, size_t size)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000414{
415 FILE* file = fopen(path, "w");
416 if (!file)
417 {
418 UNREACHABLE();
419 return;
420 }
421
422 fwrite(content, sizeof(char), size, file);
423 fclose(file);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000424}