blob: 39f7db20b0e887034621ba7058ad4c91e33bdcd9 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00009#include "libGLESv2/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000010
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +000011#include <limits>
12
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000013#include "common/debug.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000014
15#include "libGLESv2/mathutil.h"
16#include "libGLESv2/Context.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000017
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000018namespace 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 return 1;
29 case GL_BOOL_VEC2:
30 case GL_FLOAT_VEC2:
31 case GL_INT_VEC2:
32 return 2;
33 case GL_INT_VEC3:
34 case GL_FLOAT_VEC3:
35 case GL_BOOL_VEC3:
36 return 3;
37 case GL_BOOL_VEC4:
38 case GL_FLOAT_VEC4:
39 case GL_INT_VEC4:
40 case GL_FLOAT_MAT2:
41 return 4;
42 case GL_FLOAT_MAT3:
43 return 9;
44 case GL_FLOAT_MAT4:
45 return 16;
46 default:
47 UNREACHABLE();
48 }
49
50 return 0;
51}
52
53GLenum UniformComponentType(GLenum type)
54{
55 switch(type)
56 {
57 case GL_BOOL:
58 case GL_BOOL_VEC2:
59 case GL_BOOL_VEC3:
60 case GL_BOOL_VEC4:
61 return GL_BOOL;
62 case GL_FLOAT:
63 case GL_FLOAT_VEC2:
64 case GL_FLOAT_VEC3:
65 case GL_FLOAT_VEC4:
66 case GL_FLOAT_MAT2:
67 case GL_FLOAT_MAT3:
68 case GL_FLOAT_MAT4:
69 return GL_FLOAT;
70 case GL_INT:
71 case GL_INT_VEC2:
72 case GL_INT_VEC3:
73 case GL_INT_VEC4:
74 return GL_INT;
75 default:
76 UNREACHABLE();
77 }
78
79 return GL_NONE;
80}
81
82size_t UniformTypeSize(GLenum type)
83{
84 switch(type)
85 {
86 case GL_BOOL: return sizeof(GLboolean);
87 case GL_FLOAT: return sizeof(GLfloat);
88 case GL_INT: return sizeof(GLint);
89 }
90
91 return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
92}
93
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +000094int AttributeVectorCount(GLenum type)
95{
96 switch (type)
97 {
98 case GL_BOOL:
99 case GL_FLOAT:
100 case GL_INT:
101 case GL_BOOL_VEC2:
102 case GL_FLOAT_VEC2:
103 case GL_INT_VEC2:
104 case GL_INT_VEC3:
105 case GL_FLOAT_VEC3:
106 case GL_BOOL_VEC3:
107 case GL_BOOL_VEC4:
108 case GL_FLOAT_VEC4:
109 case GL_INT_VEC4:
110 return 1;
111
112 case GL_FLOAT_MAT2:
113 return 2;
114
115 case GL_FLOAT_MAT3:
116 return 3;
117
118 case GL_FLOAT_MAT4:
119 return 4;
120
121 default:
122 UNREACHABLE();
123 return 0;
124 }
125}
126
127int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
128{
129 ASSERT(allocationSize <= bitsSize);
130
131 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
132
133 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
134 {
135 if ((*bits & mask) == 0)
136 {
137 *bits |= mask;
138 return i;
139 }
140
141 mask <<= 1;
142 }
143
144 return -1;
145}
146
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000147}
148
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149namespace es2dx
150{
151
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000152D3DCMPFUNC ConvertComparison(GLenum comparison)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153{
154 D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
155 switch (comparison)
156 {
157 case GL_NEVER: d3dComp = D3DCMP_NEVER; break;
158 case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break;
159 case GL_LESS: d3dComp = D3DCMP_LESS; break;
160 case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break;
161 case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break;
162 case GL_GREATER: d3dComp = D3DCMP_GREATER; break;
163 case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break;
164 case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break;
165 default: UNREACHABLE();
166 }
167
168 return d3dComp;
169}
170
171D3DCOLOR ConvertColor(gl::Color color)
172{
173 return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174 gl::unorm<8>(color.green),
daniel@transgaming.comfe453652010-03-16 06:23:28 +0000175 gl::unorm<8>(color.blue),
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176 gl::unorm<8>(color.alpha));
177}
178
179D3DBLEND ConvertBlendFunc(GLenum blend)
180{
181 D3DBLEND d3dBlend = D3DBLEND_ZERO;
182
183 switch (blend)
184 {
185 case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break;
186 case GL_ONE: d3dBlend = D3DBLEND_ONE; break;
187 case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break;
188 case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break;
189 case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break;
190 case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break;
191 case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break;
192 case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break;
193 case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break;
194 case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break;
195 case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break;
196 case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
197 case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break;
198 case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
199 case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break;
200 default: UNREACHABLE();
201 }
202
203 return d3dBlend;
204}
205
206D3DBLENDOP ConvertBlendOp(GLenum blendOp)
207{
208 D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
209
210 switch (blendOp)
211 {
212 case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break;
213 case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break;
214 case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
215 default: UNREACHABLE();
216 }
217
218 return d3dBlendOp;
219}
220
221D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
222{
223 D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
224
225 switch (stencilOp)
226 {
227 case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break;
228 case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break;
229 case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break;
230 case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
231 case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
232 case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break;
233 case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break;
234 case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break;
235 default: UNREACHABLE();
236 }
237
238 return d3dStencilOp;
239}
240
241D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
242{
243 D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
244
245 switch (wrap)
246 {
247 case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break;
248 case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break;
249 case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
250 default: UNREACHABLE();
251 }
252
253 return d3dWrap;
254}
255
256D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
257{
258 D3DCULL cull = D3DCULL_CCW;
259 switch (cullFace)
260 {
261 case GL_FRONT:
262 cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
263 break;
264 case GL_BACK:
265 cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
266 break;
267 case GL_FRONT_AND_BACK:
daniel@transgaming.comace5e662010-03-21 04:31:20 +0000268 cull = D3DCULL_NONE; // culling will be handled during draw
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269 break;
270 default: UNREACHABLE();
271 }
272
273 return cull;
274}
275
276DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
277{
278 return (red ? D3DCOLORWRITEENABLE_RED : 0) |
279 (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
280 (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
281 (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
282}
283
284D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
285{
286 D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
287 switch (magFilter)
288 {
289 case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
290 case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
291 default: UNREACHABLE();
292 }
293
294 return d3dMagFilter;
295}
296
297void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter)
298{
299 switch (minFilter)
300 {
301 case GL_NEAREST:
302 *d3dMinFilter = D3DTEXF_POINT;
303 *d3dMipFilter = D3DTEXF_NONE;
304 break;
305 case GL_LINEAR:
306 *d3dMinFilter = D3DTEXF_LINEAR;
307 *d3dMipFilter = D3DTEXF_NONE;
308 break;
309 case GL_NEAREST_MIPMAP_NEAREST:
310 *d3dMinFilter = D3DTEXF_POINT;
311 *d3dMipFilter = D3DTEXF_POINT;
312 break;
313 case GL_LINEAR_MIPMAP_NEAREST:
314 *d3dMinFilter = D3DTEXF_LINEAR;
315 *d3dMipFilter = D3DTEXF_POINT;
316 break;
317 case GL_NEAREST_MIPMAP_LINEAR:
318 *d3dMinFilter = D3DTEXF_POINT;
319 *d3dMipFilter = D3DTEXF_LINEAR;
320 break;
321 case GL_LINEAR_MIPMAP_LINEAR:
322 *d3dMinFilter = D3DTEXF_LINEAR;
323 *d3dMipFilter = D3DTEXF_LINEAR;
324 break;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000325 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326 *d3dMinFilter = D3DTEXF_POINT;
327 *d3dMipFilter = D3DTEXF_NONE;
328 UNREACHABLE();
329 }
330}
331
332unsigned int GetStencilSize(D3DFORMAT stencilFormat)
333{
334 switch(stencilFormat)
335 {
336 case D3DFMT_D24FS8:
337 case D3DFMT_D24S8:
338 return 8;
339 case D3DFMT_D24X4S4:
340 return 4;
341 case D3DFMT_D15S1:
342 return 1;
343 case D3DFMT_D16_LOCKABLE:
344 case D3DFMT_D32:
345 case D3DFMT_D24X8:
346 case D3DFMT_D32F_LOCKABLE:
347 case D3DFMT_D16:
348 return 0;
349// case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
350// case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
351 default: UNREACHABLE();
352 }
353 return 0;
354}
355
356unsigned int GetAlphaSize(D3DFORMAT colorFormat)
357{
358 switch (colorFormat)
359 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000360 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361 return 2;
362 case D3DFMT_A8R8G8B8:
363 return 8;
364 case D3DFMT_A1R5G5B5:
365 return 1;
366 case D3DFMT_X8R8G8B8:
367 case D3DFMT_X1R5G5B5:
368 case D3DFMT_R5G6B5:
369 return 0;
370 default: UNREACHABLE();
371 }
372 return 0;
373}
374
375unsigned int GetRedSize(D3DFORMAT colorFormat)
376{
377 switch (colorFormat)
378 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000379 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380 return 10;
381 case D3DFMT_A8R8G8B8:
382 case D3DFMT_X8R8G8B8:
383 return 8;
384 case D3DFMT_A1R5G5B5:
385 case D3DFMT_R5G6B5:
386 case D3DFMT_X1R5G5B5:
387 return 5;
388 default: UNREACHABLE();
389 }
390 return 0;
391}
392
393unsigned int GetGreenSize(D3DFORMAT colorFormat)
394{
395 switch (colorFormat)
396 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000397 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398 return 10;
399 case D3DFMT_A8R8G8B8:
400 case D3DFMT_X8R8G8B8:
401 return 8;
402 case D3DFMT_A1R5G5B5:
403 case D3DFMT_X1R5G5B5:
404 return 5;
405 case D3DFMT_R5G6B5:
406 return 6;
407 default: UNREACHABLE();
408 }
409 return 0;
410}
411
412unsigned int GetBlueSize(D3DFORMAT colorFormat)
413{
414 switch (colorFormat)
415 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000416 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000417 return 10;
418 case D3DFMT_A8R8G8B8:
419 case D3DFMT_X8R8G8B8:
420 return 8;
421 case D3DFMT_A1R5G5B5:
422 case D3DFMT_R5G6B5:
423 case D3DFMT_X1R5G5B5:
424 return 5;
425 default: UNREACHABLE();
426 }
427 return 0;
428}
429
430unsigned int GetDepthSize(D3DFORMAT depthFormat)
431{
432 switch (depthFormat)
433 {
434 case D3DFMT_D16_LOCKABLE: return 16;
435 case D3DFMT_D32: return 32;
436 case D3DFMT_D15S1: return 15;
437 case D3DFMT_D24S8: return 24;
438 case D3DFMT_D24X8: return 24;
439 case D3DFMT_D24X4S4: return 24;
440 case D3DFMT_D16: return 16;
441 case D3DFMT_D32F_LOCKABLE: return 32;
442 case D3DFMT_D24FS8: return 24;
443// case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
444// case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
445 default:
446 UNREACHABLE();
447 }
448 return 0;
449}
450
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000451bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000452 D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
453{
454 switch (primitiveType)
455 {
456 case GL_POINTS:
457 *d3dPrimitiveType = D3DPT_POINTLIST;
458 *d3dPrimitiveCount = primitiveCount;
459 break;
460 case GL_LINES:
461 *d3dPrimitiveType = D3DPT_LINELIST;
462 *d3dPrimitiveCount = primitiveCount / 2;
463 break;
464 case GL_LINE_LOOP:
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +0000465 *d3dPrimitiveType = D3DPT_LINESTRIP;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466 *d3dPrimitiveCount = primitiveCount;
467 break;
468 case GL_LINE_STRIP:
469 *d3dPrimitiveType = D3DPT_LINESTRIP;
470 *d3dPrimitiveCount = primitiveCount - 1;
471 break;
472 case GL_TRIANGLES:
473 *d3dPrimitiveType = D3DPT_TRIANGLELIST;
474 *d3dPrimitiveCount = primitiveCount / 3;
475 break;
476 case GL_TRIANGLE_STRIP:
477 *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
478 *d3dPrimitiveCount = primitiveCount - 2;
479 break;
480 case GL_TRIANGLE_FAN:
481 *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
482 *d3dPrimitiveCount = primitiveCount - 2;
483 break;
484 default:
485 return false;
486 }
487
488 return true;
489}
490
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000491bool IsCubemapTextureTarget(GLenum target)
492{
493 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
494}
495
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000496bool IsTextureTarget(GLenum target)
497{
498 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
499}
500
daniel@transgaming.com00c75962010-03-11 20:36:15 +0000501// Verify that format/type are one of the combinations from table 3.4.
502bool CheckTextureFormatType(GLenum format, GLenum type)
503{
504 switch (type)
505 {
506 case GL_UNSIGNED_BYTE:
507 switch (format)
508 {
509 case GL_RGBA:
510 case GL_RGB:
511 case GL_ALPHA:
512 case GL_LUMINANCE:
513 case GL_LUMINANCE_ALPHA:
514 return true;
515
516 default:
517 return false;
518 }
519
520 case GL_UNSIGNED_SHORT_4_4_4_4:
521 case GL_UNSIGNED_SHORT_5_5_5_1:
522 return (format == GL_RGBA);
523
524 case GL_UNSIGNED_SHORT_5_6_5:
525 return (format == GL_RGB);
526
527 default:
528 return false;
529 }
530}
531
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000532D3DFORMAT ConvertRenderbufferFormat(GLenum format)
533{
534 switch (format)
535 {
536 case GL_RGBA4:
537 case GL_RGB5_A1: return D3DFMT_A8R8G8B8;
538 case GL_RGB565: return D3DFMT_R5G6B5;
539 case GL_DEPTH_COMPONENT16:
540 case GL_STENCIL_INDEX8: return D3DFMT_D24S8;
541 default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
542 }
543}
544
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545}