blob: 40a4a32a6800af5ea5cebb48b449c2dd0f164da3 [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:
167 case GL_BOOL_VEC2:
168 case GL_FLOAT_VEC2:
169 case GL_INT_VEC2:
170 case GL_INT_VEC3:
171 case GL_FLOAT_VEC3:
172 case GL_BOOL_VEC3:
173 case GL_BOOL_VEC4:
174 case GL_FLOAT_VEC4:
175 case GL_INT_VEC4:
daniel@transgaming.comda8d3802012-12-20 21:12:55 +0000176 case GL_SAMPLER_2D:
177 case GL_SAMPLER_CUBE:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000178 return 1;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000179 case GL_FLOAT_MAT2:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000180 case GL_FLOAT_MAT3x2:
181 case GL_FLOAT_MAT4x2:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000182 return 2;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000183 case GL_FLOAT_MAT3:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000184 case GL_FLOAT_MAT2x3:
185 case GL_FLOAT_MAT4x3:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000186 return 3;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000187 case GL_FLOAT_MAT4:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000188 case GL_FLOAT_MAT2x4:
189 case GL_FLOAT_MAT3x4:
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000190 return 4;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000191 default:
192 UNREACHABLE();
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000193 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000194
195 return 0;
196}
197
198int VariableColumnCount(GLenum type)
199{
200 switch (type)
201 {
202 case GL_NONE:
203 return 0;
204 case GL_BOOL:
205 case GL_FLOAT:
206 case GL_INT:
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000207 case GL_SAMPLER_2D:
208 case GL_SAMPLER_CUBE:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000209 return 1;
210 case GL_BOOL_VEC2:
211 case GL_FLOAT_VEC2:
212 case GL_INT_VEC2:
213 case GL_FLOAT_MAT2:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000214 case GL_FLOAT_MAT2x3:
215 case GL_FLOAT_MAT2x4:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000216 return 2;
217 case GL_INT_VEC3:
218 case GL_FLOAT_VEC3:
219 case GL_BOOL_VEC3:
220 case GL_FLOAT_MAT3:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000221 case GL_FLOAT_MAT3x2:
222 case GL_FLOAT_MAT3x4:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000223 return 3;
224 case GL_BOOL_VEC4:
225 case GL_FLOAT_VEC4:
226 case GL_INT_VEC4:
227 case GL_FLOAT_MAT4:
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000228 case GL_FLOAT_MAT4x2:
229 case GL_FLOAT_MAT4x3:
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000230 return 4;
231 default:
232 UNREACHABLE();
233 }
234
235 return 0;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000236}
237
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000238bool IsMatrixType(GLenum type)
239{
240 return VariableRowCount(type) > 1;
241}
242
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000243int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
244{
245 ASSERT(allocationSize <= bitsSize);
246
247 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
248
249 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
250 {
251 if ((*bits & mask) == 0)
252 {
253 *bits |= mask;
254 return i;
255 }
256
257 mask <<= 1;
258 }
259
260 return -1;
261}
262
daniel@transgaming.com8e91d252012-10-17 18:22:44 +0000263bool IsStencilTexture(GLenum format)
264{
265 if (format == GL_DEPTH_STENCIL_OES ||
266 format == GL_DEPTH24_STENCIL8_OES)
267 {
268 return true;
269 }
270
271 return false;
272}
273
daniel@transgaming.comb9d7e6f2012-10-31 19:08:32 +0000274void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
275{
276 int upsampleCount = 0;
277
278 if (isCompressed)
279 {
280 // Don't expand the size of full textures that are at least 4x4
281 // already.
282 if (isImage || *requestWidth < 4 || *requestHeight < 4)
283 {
284 while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
285 {
286 *requestWidth <<= 1;
287 *requestHeight <<= 1;
288 upsampleCount++;
289 }
290 }
291 }
292 *levelOffset = upsampleCount;
293}
294
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000295// Returns the size, in bytes, of a single texel in an Image
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000296int ComputePixelSize(GLint internalformat)
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000297{
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000298 switch (internalformat)
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000299 {
daniel@transgaming.com6452adf2012-10-17 18:22:35 +0000300 case GL_ALPHA8_EXT: return sizeof(unsigned char);
301 case GL_LUMINANCE8_EXT: return sizeof(unsigned char);
302 case GL_ALPHA32F_EXT: return sizeof(float);
303 case GL_LUMINANCE32F_EXT: return sizeof(float);
304 case GL_ALPHA16F_EXT: return sizeof(unsigned short);
305 case GL_LUMINANCE16F_EXT: return sizeof(unsigned short);
306 case GL_LUMINANCE8_ALPHA8_EXT: return sizeof(unsigned char) * 2;
307 case GL_LUMINANCE_ALPHA32F_EXT: return sizeof(float) * 2;
308 case GL_LUMINANCE_ALPHA16F_EXT: return sizeof(unsigned short) * 2;
309 case GL_RGB8_OES: return sizeof(unsigned char) * 3;
310 case GL_RGB565: return sizeof(unsigned short);
311 case GL_RGB32F_EXT: return sizeof(float) * 3;
312 case GL_RGB16F_EXT: return sizeof(unsigned short) * 3;
313 case GL_RGBA8_OES: return sizeof(unsigned char) * 4;
314 case GL_RGBA4: return sizeof(unsigned short);
315 case GL_RGB5_A1: return sizeof(unsigned short);
316 case GL_RGBA32F_EXT: return sizeof(float) * 4;
317 case GL_RGBA16F_EXT: return sizeof(unsigned short) * 4;
318 case GL_BGRA8_EXT: return sizeof(unsigned char) * 4;
shannon.woods%transgaming.com@gtempaccount.com8dce6512013-04-13 03:42:19 +0000319 case GL_SRGB8_ALPHA8: return sizeof(unsigned char) * 4;
320 case GL_RGB10_A2: return sizeof(unsigned char) * 4;
321 case GL_RG8: return sizeof(unsigned char) * 2;
322 case GL_R8: return sizeof(unsigned char);
daniel@transgaming.com6b1a0a02012-10-17 18:22:47 +0000323 case GL_BGRA4_ANGLEX: return sizeof(unsigned short);
324 case GL_BGR5_A1_ANGLEX: return sizeof(unsigned short);
shannon.woods%transgaming.com@gtempaccount.com8dce6512013-04-13 03:42:19 +0000325 default:
326 UNIMPLEMENTED(); // TODO: Remaining ES3 formats
327 UNREACHABLE();
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000328 }
329
330 return 0;
331}
332
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000333bool IsCubemapTextureTarget(GLenum target)
334{
335 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
336}
337
apatrick@chromium.org551022e2012-01-23 19:56:54 +0000338bool IsInternalTextureTarget(GLenum target)
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000339{
340 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
341}
342
daniel@transgaming.com97c852b2012-12-20 20:56:23 +0000343bool IsTriangleMode(GLenum drawMode)
344{
345 switch (drawMode)
346 {
347 case GL_TRIANGLES:
348 case GL_TRIANGLE_FAN:
349 case GL_TRIANGLE_STRIP:
350 return true;
351 case GL_POINTS:
352 case GL_LINES:
353 case GL_LINE_LOOP:
354 case GL_LINE_STRIP:
355 return false;
356 default: UNREACHABLE();
357 }
358
359 return false;
360}
361
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000362}
363
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000364std::string getTempPath()
365{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000366 char path[MAX_PATH];
367 DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
368 if (pathLen == 0)
369 {
370 UNREACHABLE();
371 return std::string();
372 }
373
374 UINT unique = GetTempFileNameA(path, "sh", 0, path);
375 if (unique == 0)
376 {
377 UNREACHABLE();
378 return std::string();
379 }
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +0000380
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000381 return path;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000382}
383
384void writeFile(const char* path, const void* content, size_t size)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000385{
386 FILE* file = fopen(path, "w");
387 if (!file)
388 {
389 UNREACHABLE();
390 return;
391 }
392
393 fwrite(content, sizeof(char), size, file);
394 fclose(file);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000395}