blob: ff7f0900b086d07492a7a3f3f71ca3265471b74a [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.com713914b2010-05-04 03:35:17 +0000147GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
148{
149 ASSERT(alignment > 0 && isPow2(alignment));
150
151 GLsizei rawPitch = ComputePixelSize(format, type) * width;
152 return (rawPitch + alignment - 1) & ~(alignment - 1);
153}
154
155// Returns the size, in bytes, of a single texel in an Image
156int ComputePixelSize(GLenum format, GLenum type)
157{
158 switch (type)
159 {
160 case GL_UNSIGNED_BYTE:
161 switch (format)
162 {
163 case GL_ALPHA: return sizeof(unsigned char);
164 case GL_LUMINANCE: return sizeof(unsigned char);
165 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
166 case GL_RGB: return sizeof(unsigned char) * 3;
167 case GL_RGBA: return sizeof(unsigned char) * 4;
168 default: UNREACHABLE();
169 }
170 break;
171 case GL_UNSIGNED_SHORT_4_4_4_4:
172 case GL_UNSIGNED_SHORT_5_5_5_1:
173 case GL_UNSIGNED_SHORT_5_6_5:
174 return sizeof(unsigned short);
175 default: UNREACHABLE();
176 }
177
178 return 0;
179}
180
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000181bool IsCubemapTextureTarget(GLenum target)
182{
183 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
184}
185
186bool IsTextureTarget(GLenum target)
187{
188 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
189}
190
191// Verify that format/type are one of the combinations from table 3.4.
192bool CheckTextureFormatType(GLenum format, GLenum type)
193{
194 switch (type)
195 {
196 case GL_UNSIGNED_BYTE:
197 switch (format)
198 {
199 case GL_RGBA:
200 case GL_RGB:
201 case GL_ALPHA:
202 case GL_LUMINANCE:
203 case GL_LUMINANCE_ALPHA:
204 return true;
205
206 default:
207 return false;
208 }
209
210 case GL_UNSIGNED_SHORT_4_4_4_4:
211 case GL_UNSIGNED_SHORT_5_5_5_1:
212 return (format == GL_RGBA);
213
214 case GL_UNSIGNED_SHORT_5_6_5:
215 return (format == GL_RGB);
216
217 default:
218 return false;
219 }
220}
221
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000222}
223
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224namespace es2dx
225{
226
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000227D3DCMPFUNC ConvertComparison(GLenum comparison)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228{
229 D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
230 switch (comparison)
231 {
232 case GL_NEVER: d3dComp = D3DCMP_NEVER; break;
233 case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break;
234 case GL_LESS: d3dComp = D3DCMP_LESS; break;
235 case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break;
236 case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break;
237 case GL_GREATER: d3dComp = D3DCMP_GREATER; break;
238 case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break;
239 case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break;
240 default: UNREACHABLE();
241 }
242
243 return d3dComp;
244}
245
246D3DCOLOR ConvertColor(gl::Color color)
247{
248 return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249 gl::unorm<8>(color.green),
daniel@transgaming.comfe453652010-03-16 06:23:28 +0000250 gl::unorm<8>(color.blue),
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 gl::unorm<8>(color.alpha));
252}
253
254D3DBLEND ConvertBlendFunc(GLenum blend)
255{
256 D3DBLEND d3dBlend = D3DBLEND_ZERO;
257
258 switch (blend)
259 {
260 case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break;
261 case GL_ONE: d3dBlend = D3DBLEND_ONE; break;
262 case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break;
263 case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break;
264 case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break;
265 case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break;
266 case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break;
267 case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break;
268 case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break;
269 case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break;
270 case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break;
271 case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
272 case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break;
273 case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
274 case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break;
275 default: UNREACHABLE();
276 }
277
278 return d3dBlend;
279}
280
281D3DBLENDOP ConvertBlendOp(GLenum blendOp)
282{
283 D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
284
285 switch (blendOp)
286 {
287 case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break;
288 case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break;
289 case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
290 default: UNREACHABLE();
291 }
292
293 return d3dBlendOp;
294}
295
296D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
297{
298 D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
299
300 switch (stencilOp)
301 {
302 case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break;
303 case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break;
304 case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break;
305 case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
306 case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
307 case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break;
308 case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break;
309 case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break;
310 default: UNREACHABLE();
311 }
312
313 return d3dStencilOp;
314}
315
316D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
317{
318 D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
319
320 switch (wrap)
321 {
322 case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break;
323 case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break;
324 case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
325 default: UNREACHABLE();
326 }
327
328 return d3dWrap;
329}
330
331D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
332{
333 D3DCULL cull = D3DCULL_CCW;
334 switch (cullFace)
335 {
336 case GL_FRONT:
337 cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
338 break;
339 case GL_BACK:
340 cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
341 break;
342 case GL_FRONT_AND_BACK:
daniel@transgaming.comace5e662010-03-21 04:31:20 +0000343 cull = D3DCULL_NONE; // culling will be handled during draw
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000344 break;
345 default: UNREACHABLE();
346 }
347
348 return cull;
349}
350
351DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
352{
353 return (red ? D3DCOLORWRITEENABLE_RED : 0) |
354 (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
355 (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
356 (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
357}
358
359D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
360{
361 D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
362 switch (magFilter)
363 {
364 case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
365 case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
366 default: UNREACHABLE();
367 }
368
369 return d3dMagFilter;
370}
371
372void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter)
373{
374 switch (minFilter)
375 {
376 case GL_NEAREST:
377 *d3dMinFilter = D3DTEXF_POINT;
378 *d3dMipFilter = D3DTEXF_NONE;
379 break;
380 case GL_LINEAR:
381 *d3dMinFilter = D3DTEXF_LINEAR;
382 *d3dMipFilter = D3DTEXF_NONE;
383 break;
384 case GL_NEAREST_MIPMAP_NEAREST:
385 *d3dMinFilter = D3DTEXF_POINT;
386 *d3dMipFilter = D3DTEXF_POINT;
387 break;
388 case GL_LINEAR_MIPMAP_NEAREST:
389 *d3dMinFilter = D3DTEXF_LINEAR;
390 *d3dMipFilter = D3DTEXF_POINT;
391 break;
392 case GL_NEAREST_MIPMAP_LINEAR:
393 *d3dMinFilter = D3DTEXF_POINT;
394 *d3dMipFilter = D3DTEXF_LINEAR;
395 break;
396 case GL_LINEAR_MIPMAP_LINEAR:
397 *d3dMinFilter = D3DTEXF_LINEAR;
398 *d3dMipFilter = D3DTEXF_LINEAR;
399 break;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000400 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401 *d3dMinFilter = D3DTEXF_POINT;
402 *d3dMipFilter = D3DTEXF_NONE;
403 UNREACHABLE();
404 }
405}
406
407unsigned int GetStencilSize(D3DFORMAT stencilFormat)
408{
409 switch(stencilFormat)
410 {
411 case D3DFMT_D24FS8:
412 case D3DFMT_D24S8:
413 return 8;
414 case D3DFMT_D24X4S4:
415 return 4;
416 case D3DFMT_D15S1:
417 return 1;
418 case D3DFMT_D16_LOCKABLE:
419 case D3DFMT_D32:
420 case D3DFMT_D24X8:
421 case D3DFMT_D32F_LOCKABLE:
422 case D3DFMT_D16:
423 return 0;
424// case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
425// case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
426 default: UNREACHABLE();
427 }
428 return 0;
429}
430
431unsigned int GetAlphaSize(D3DFORMAT colorFormat)
432{
433 switch (colorFormat)
434 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000435 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000436 return 2;
437 case D3DFMT_A8R8G8B8:
438 return 8;
439 case D3DFMT_A1R5G5B5:
440 return 1;
441 case D3DFMT_X8R8G8B8:
442 case D3DFMT_X1R5G5B5:
443 case D3DFMT_R5G6B5:
444 return 0;
445 default: UNREACHABLE();
446 }
447 return 0;
448}
449
450unsigned int GetRedSize(D3DFORMAT colorFormat)
451{
452 switch (colorFormat)
453 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000454 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000455 return 10;
456 case D3DFMT_A8R8G8B8:
457 case D3DFMT_X8R8G8B8:
458 return 8;
459 case D3DFMT_A1R5G5B5:
460 case D3DFMT_R5G6B5:
461 case D3DFMT_X1R5G5B5:
462 return 5;
463 default: UNREACHABLE();
464 }
465 return 0;
466}
467
468unsigned int GetGreenSize(D3DFORMAT colorFormat)
469{
470 switch (colorFormat)
471 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000472 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473 return 10;
474 case D3DFMT_A8R8G8B8:
475 case D3DFMT_X8R8G8B8:
476 return 8;
477 case D3DFMT_A1R5G5B5:
478 case D3DFMT_X1R5G5B5:
479 return 5;
480 case D3DFMT_R5G6B5:
481 return 6;
482 default: UNREACHABLE();
483 }
484 return 0;
485}
486
487unsigned int GetBlueSize(D3DFORMAT colorFormat)
488{
489 switch (colorFormat)
490 {
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000491 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000492 return 10;
493 case D3DFMT_A8R8G8B8:
494 case D3DFMT_X8R8G8B8:
495 return 8;
496 case D3DFMT_A1R5G5B5:
497 case D3DFMT_R5G6B5:
498 case D3DFMT_X1R5G5B5:
499 return 5;
500 default: UNREACHABLE();
501 }
502 return 0;
503}
504
505unsigned int GetDepthSize(D3DFORMAT depthFormat)
506{
507 switch (depthFormat)
508 {
509 case D3DFMT_D16_LOCKABLE: return 16;
510 case D3DFMT_D32: return 32;
511 case D3DFMT_D15S1: return 15;
512 case D3DFMT_D24S8: return 24;
513 case D3DFMT_D24X8: return 24;
514 case D3DFMT_D24X4S4: return 24;
515 case D3DFMT_D16: return 16;
516 case D3DFMT_D32F_LOCKABLE: return 32;
517 case D3DFMT_D24FS8: return 24;
518// case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
519// case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
520 default:
521 UNREACHABLE();
522 }
523 return 0;
524}
525
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000526bool ConvertPrimitiveType(GLenum primitiveType, GLsizei primitiveCount,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000527 D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
528{
529 switch (primitiveType)
530 {
531 case GL_POINTS:
532 *d3dPrimitiveType = D3DPT_POINTLIST;
533 *d3dPrimitiveCount = primitiveCount;
534 break;
535 case GL_LINES:
536 *d3dPrimitiveType = D3DPT_LINELIST;
537 *d3dPrimitiveCount = primitiveCount / 2;
538 break;
539 case GL_LINE_LOOP:
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +0000540 *d3dPrimitiveType = D3DPT_LINESTRIP;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000541 *d3dPrimitiveCount = primitiveCount;
542 break;
543 case GL_LINE_STRIP:
544 *d3dPrimitiveType = D3DPT_LINESTRIP;
545 *d3dPrimitiveCount = primitiveCount - 1;
546 break;
547 case GL_TRIANGLES:
548 *d3dPrimitiveType = D3DPT_TRIANGLELIST;
549 *d3dPrimitiveCount = primitiveCount / 3;
550 break;
551 case GL_TRIANGLE_STRIP:
552 *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
553 *d3dPrimitiveCount = primitiveCount - 2;
554 break;
555 case GL_TRIANGLE_FAN:
556 *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
557 *d3dPrimitiveCount = primitiveCount - 2;
558 break;
559 default:
560 return false;
561 }
562
563 return true;
564}
565
daniel@transgaming.com70d312a2010-04-20 18:52:38 +0000566D3DFORMAT ConvertRenderbufferFormat(GLenum format)
567{
568 switch (format)
569 {
570 case GL_RGBA4:
571 case GL_RGB5_A1: return D3DFMT_A8R8G8B8;
572 case GL_RGB565: return D3DFMT_R5G6B5;
573 case GL_DEPTH_COMPONENT16:
574 case GL_STENCIL_INDEX8: return D3DFMT_D24S8;
575 default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
576 }
577}
578
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000579}