blob: 6a2a4055edcadc3b421fe1a55dadf0c0dae33454 [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>
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +000012#include <stdio.h>
13#include <windows.h>
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +000014
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000015#include "common/debug.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000016
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/Context.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000019
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000020namespace gl
21{
22
23int UniformComponentCount(GLenum type)
24{
25 switch (type)
26 {
27 case GL_BOOL:
28 case GL_FLOAT:
29 case GL_INT:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +000030 case GL_SAMPLER_2D:
31 case GL_SAMPLER_CUBE:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000032 return 1;
33 case GL_BOOL_VEC2:
34 case GL_FLOAT_VEC2:
35 case GL_INT_VEC2:
36 return 2;
37 case GL_INT_VEC3:
38 case GL_FLOAT_VEC3:
39 case GL_BOOL_VEC3:
40 return 3;
41 case GL_BOOL_VEC4:
42 case GL_FLOAT_VEC4:
43 case GL_INT_VEC4:
44 case GL_FLOAT_MAT2:
45 return 4;
46 case GL_FLOAT_MAT3:
47 return 9;
48 case GL_FLOAT_MAT4:
49 return 16;
50 default:
51 UNREACHABLE();
52 }
53
54 return 0;
55}
56
jbauman@chromium.org72e8f442011-10-20 00:22:01 +000057// This is how much data we actually store for a uniform
58int UniformInternalComponentCount(GLenum type)
59{
60 switch (type)
61 {
62 case GL_BOOL:
63 case GL_INT:
64 case GL_SAMPLER_2D:
65 case GL_SAMPLER_CUBE:
66 return 1;
67 case GL_BOOL_VEC2:
68 case GL_INT_VEC2:
69 return 2;
70 case GL_INT_VEC3:
71 case GL_BOOL_VEC3:
72 return 3;
73 case GL_FLOAT:
74 case GL_FLOAT_VEC2:
75 case GL_FLOAT_VEC3:
76 case GL_BOOL_VEC4:
77 case GL_FLOAT_VEC4:
78 case GL_INT_VEC4:
79 return 4;
80 case GL_FLOAT_MAT2:
81 return 8;
82 case GL_FLOAT_MAT3:
83 return 12;
84 case GL_FLOAT_MAT4:
85 return 16;
86 default:
87 UNREACHABLE();
88 }
89
90 return 0;
91}
92
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000093GLenum UniformComponentType(GLenum type)
94{
95 switch(type)
96 {
97 case GL_BOOL:
98 case GL_BOOL_VEC2:
99 case GL_BOOL_VEC3:
100 case GL_BOOL_VEC4:
101 return GL_BOOL;
102 case GL_FLOAT:
103 case GL_FLOAT_VEC2:
104 case GL_FLOAT_VEC3:
105 case GL_FLOAT_VEC4:
106 case GL_FLOAT_MAT2:
107 case GL_FLOAT_MAT3:
108 case GL_FLOAT_MAT4:
109 return GL_FLOAT;
110 case GL_INT:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000111 case GL_SAMPLER_2D:
112 case GL_SAMPLER_CUBE:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000113 case GL_INT_VEC2:
114 case GL_INT_VEC3:
115 case GL_INT_VEC4:
116 return GL_INT;
117 default:
118 UNREACHABLE();
119 }
120
121 return GL_NONE;
122}
123
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000124size_t UniformComponentSize(GLenum type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000125{
126 switch(type)
127 {
128 case GL_BOOL: return sizeof(GLboolean);
129 case GL_FLOAT: return sizeof(GLfloat);
130 case GL_INT: return sizeof(GLint);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000131 default: UNREACHABLE();
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000132 }
133
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000134 return 0;
135}
136
137size_t UniformTypeSize(GLenum type)
138{
139 return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type);
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000140}
141
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000142int VariableRowCount(GLenum type)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000143{
144 switch (type)
145 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000146 case GL_NONE:
147 return 0;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000148 case GL_BOOL:
149 case GL_FLOAT:
150 case GL_INT:
151 case GL_BOOL_VEC2:
152 case GL_FLOAT_VEC2:
153 case GL_INT_VEC2:
154 case GL_INT_VEC3:
155 case GL_FLOAT_VEC3:
156 case GL_BOOL_VEC3:
157 case GL_BOOL_VEC4:
158 case GL_FLOAT_VEC4:
159 case GL_INT_VEC4:
160 return 1;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000161 case GL_FLOAT_MAT2:
162 return 2;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000163 case GL_FLOAT_MAT3:
164 return 3;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000165 case GL_FLOAT_MAT4:
166 return 4;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000167 default:
168 UNREACHABLE();
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000169 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000170
171 return 0;
172}
173
174int VariableColumnCount(GLenum type)
175{
176 switch (type)
177 {
178 case GL_NONE:
179 return 0;
180 case GL_BOOL:
181 case GL_FLOAT:
182 case GL_INT:
183 return 1;
184 case GL_BOOL_VEC2:
185 case GL_FLOAT_VEC2:
186 case GL_INT_VEC2:
187 case GL_FLOAT_MAT2:
188 return 2;
189 case GL_INT_VEC3:
190 case GL_FLOAT_VEC3:
191 case GL_BOOL_VEC3:
192 case GL_FLOAT_MAT3:
193 return 3;
194 case GL_BOOL_VEC4:
195 case GL_FLOAT_VEC4:
196 case GL_INT_VEC4:
197 case GL_FLOAT_MAT4:
198 return 4;
199 default:
200 UNREACHABLE();
201 }
202
203 return 0;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000204}
205
206int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
207{
208 ASSERT(allocationSize <= bitsSize);
209
210 unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
211
212 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
213 {
214 if ((*bits & mask) == 0)
215 {
216 *bits |= mask;
217 return i;
218 }
219
220 mask <<= 1;
221 }
222
223 return -1;
224}
225
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000226GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
227{
228 ASSERT(alignment > 0 && isPow2(alignment));
229
230 GLsizei rawPitch = ComputePixelSize(format, type) * width;
231 return (rawPitch + alignment - 1) & ~(alignment - 1);
232}
233
daniel@transgaming.com01868132010-08-24 19:21:17 +0000234GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
235{
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +0000236 return ComputeCompressedSize(width, 1, format);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000237}
238
239GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
240{
241 switch (format)
242 {
243 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
244 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
gman@chromium.org50c526d2011-08-10 05:19:44 +0000245 return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000246 break;
gman@chromium.org50c526d2011-08-10 05:19:44 +0000247 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
248 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
249 return 16 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
daniel@transgaming.com01868132010-08-24 19:21:17 +0000250 default:
251 return 0;
252 }
253
daniel@transgaming.com01868132010-08-24 19:21:17 +0000254}
255
256bool IsCompressed(GLenum format)
257{
258 if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
gman@chromium.org50c526d2011-08-10 05:19:44 +0000259 format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
260 format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
261 format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
daniel@transgaming.com01868132010-08-24 19:21:17 +0000262 {
263 return true;
264 }
265 else
266 {
267 return false;
268 }
269}
270
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000271// Returns the size, in bytes, of a single texel in an Image
272int ComputePixelSize(GLenum format, GLenum type)
273{
274 switch (type)
275 {
276 case GL_UNSIGNED_BYTE:
277 switch (format)
278 {
279 case GL_ALPHA: return sizeof(unsigned char);
280 case GL_LUMINANCE: return sizeof(unsigned char);
281 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
282 case GL_RGB: return sizeof(unsigned char) * 3;
283 case GL_RGBA: return sizeof(unsigned char) * 4;
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000284 case GL_BGRA_EXT: return sizeof(unsigned char) * 4;
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000285 default: UNREACHABLE();
286 }
287 break;
288 case GL_UNSIGNED_SHORT_4_4_4_4:
289 case GL_UNSIGNED_SHORT_5_5_5_1:
290 case GL_UNSIGNED_SHORT_5_6_5:
291 return sizeof(unsigned short);
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000292 case GL_FLOAT:
293 switch (format)
294 {
295 case GL_ALPHA: return sizeof(float);
296 case GL_LUMINANCE: return sizeof(float);
297 case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
298 case GL_RGB: return sizeof(float) * 3;
299 case GL_RGBA: return sizeof(float) * 4;
300 default: UNREACHABLE();
301 }
302 break;
303 case GL_HALF_FLOAT_OES:
304 switch (format)
305 {
306 case GL_ALPHA: return sizeof(unsigned short);
307 case GL_LUMINANCE: return sizeof(unsigned short);
308 case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
309 case GL_RGB: return sizeof(unsigned short) * 3;
310 case GL_RGBA: return sizeof(unsigned short) * 4;
311 default: UNREACHABLE();
312 }
313 break;
daniel@transgaming.com713914b2010-05-04 03:35:17 +0000314 default: UNREACHABLE();
315 }
316
317 return 0;
318}
319
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000320bool IsCubemapTextureTarget(GLenum target)
321{
322 return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
323}
324
325bool IsTextureTarget(GLenum target)
326{
327 return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
328}
329
330// Verify that format/type are one of the combinations from table 3.4.
331bool CheckTextureFormatType(GLenum format, GLenum type)
332{
333 switch (type)
334 {
335 case GL_UNSIGNED_BYTE:
336 switch (format)
337 {
338 case GL_RGBA:
daniel@transgaming.coma9198d92010-08-08 04:49:56 +0000339 case GL_BGRA_EXT:
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000340 case GL_RGB:
341 case GL_ALPHA:
342 case GL_LUMINANCE:
343 case GL_LUMINANCE_ALPHA:
344 return true;
345
346 default:
347 return false;
348 }
349
daniel@transgaming.com0a337e92010-08-28 17:38:27 +0000350 case GL_FLOAT:
351 case GL_HALF_FLOAT_OES:
352 switch (format)
353 {
354 case GL_RGBA:
355 case GL_RGB:
356 case GL_ALPHA:
357 case GL_LUMINANCE:
358 case GL_LUMINANCE_ALPHA:
359 return true;
360
361 default:
362 return false;
363 }
364
daniel@transgaming.com19ffc242010-05-04 03:35:21 +0000365 case GL_UNSIGNED_SHORT_4_4_4_4:
366 case GL_UNSIGNED_SHORT_5_5_5_1:
367 return (format == GL_RGBA);
368
369 case GL_UNSIGNED_SHORT_5_6_5:
370 return (format == GL_RGB);
371
372 default:
373 return false;
374 }
375}
376
daniel@transgaming.com64a0fb22011-11-11 04:10:40 +0000377GLenum ExtractFormat(GLenum internalformat)
378{
379 switch (internalformat)
380 {
daniel@transgaming.come1077362011-11-11 04:16:50 +0000381 case GL_RGB565: return GL_RGB;
382 case GL_RGBA4: return GL_RGBA;
383 case GL_RGB5_A1: return GL_RGBA;
384 case GL_RGB8_OES: return GL_RGB;
385 case GL_RGBA8_OES: return GL_RGBA;
386 case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA;
387 case GL_LUMINANCE8_EXT: return GL_LUMINANCE;
388 case GL_ALPHA8_EXT: return GL_ALPHA;
389 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
390 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
391 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
392 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
daniel@transgaming.comff941aa2011-11-11 04:17:09 +0000393 case GL_RGBA32F_EXT: return GL_RGBA;
394 case GL_RGB32F_EXT: return GL_RGB;
395 case GL_ALPHA32F_EXT: return GL_ALPHA;
396 case GL_LUMINANCE32F_EXT: return GL_LUMINANCE;
397 case GL_LUMINANCE_ALPHA32F_EXT: return GL_LUMINANCE_ALPHA;
398 case GL_RGBA16F_EXT: return GL_RGBA;
399 case GL_RGB16F_EXT: return GL_RGB;
400 case GL_ALPHA16F_EXT: return GL_ALPHA;
401 case GL_LUMINANCE16F_EXT: return GL_LUMINANCE;
402 case GL_LUMINANCE_ALPHA16F_EXT: return GL_LUMINANCE_ALPHA;
403 case GL_BGRA8_EXT: return GL_BGRA_EXT;
daniel@transgaming.come1077362011-11-11 04:16:50 +0000404 default: return GL_NONE; // Unsupported
daniel@transgaming.com64a0fb22011-11-11 04:10:40 +0000405 }
406}
407
408GLenum ExtractType(GLenum internalformat)
409{
410 switch (internalformat)
411 {
daniel@transgaming.come1077362011-11-11 04:16:50 +0000412 case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
413 case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
414 case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
415 case GL_RGB8_OES: return GL_UNSIGNED_BYTE;
416 case GL_RGBA8_OES: return GL_UNSIGNED_BYTE;
417 case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
418 case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE;
419 case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
420 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
421 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
422 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
423 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
daniel@transgaming.comff941aa2011-11-11 04:17:09 +0000424 case GL_RGBA32F_EXT: return GL_FLOAT;
425 case GL_RGB32F_EXT: return GL_FLOAT;
426 case GL_ALPHA32F_EXT: return GL_FLOAT;
427 case GL_LUMINANCE32F_EXT: return GL_FLOAT;
428 case GL_LUMINANCE_ALPHA32F_EXT: return GL_FLOAT;
429 case GL_RGBA16F_EXT: return GL_HALF_FLOAT_OES;
430 case GL_RGB16F_EXT: return GL_HALF_FLOAT_OES;
431 case GL_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
432 case GL_LUMINANCE16F_EXT: return GL_HALF_FLOAT_OES;
433 case GL_LUMINANCE_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
434 case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
daniel@transgaming.come1077362011-11-11 04:16:50 +0000435 default: return GL_NONE; // Unsupported
daniel@transgaming.com64a0fb22011-11-11 04:10:40 +0000436 }
437}
438
daniel@transgaming.comedc19182010-10-15 17:57:55 +0000439bool IsColorRenderable(GLenum internalformat)
440{
441 switch (internalformat)
442 {
443 case GL_RGBA4:
444 case GL_RGB5_A1:
445 case GL_RGB565:
446 case GL_RGB8_OES:
447 case GL_RGBA8_OES:
448 return true;
449 case GL_DEPTH_COMPONENT16:
450 case GL_STENCIL_INDEX8:
451 case GL_DEPTH24_STENCIL8_OES:
452 return false;
453 default:
454 UNIMPLEMENTED();
455 }
456
457 return false;
458}
459
460bool IsDepthRenderable(GLenum internalformat)
461{
462 switch (internalformat)
463 {
464 case GL_DEPTH_COMPONENT16:
465 case GL_DEPTH24_STENCIL8_OES:
466 return true;
467 case GL_STENCIL_INDEX8:
468 case GL_RGBA4:
469 case GL_RGB5_A1:
470 case GL_RGB565:
471 case GL_RGB8_OES:
472 case GL_RGBA8_OES:
473 return false;
474 default:
475 UNIMPLEMENTED();
476 }
477
478 return false;
479}
480
481bool IsStencilRenderable(GLenum internalformat)
482{
483 switch (internalformat)
484 {
485 case GL_STENCIL_INDEX8:
486 case GL_DEPTH24_STENCIL8_OES:
487 return true;
488 case GL_RGBA4:
489 case GL_RGB5_A1:
490 case GL_RGB565:
491 case GL_RGB8_OES:
492 case GL_RGBA8_OES:
493 case GL_DEPTH_COMPONENT16:
494 return false;
495 default:
496 UNIMPLEMENTED();
497 }
498
499 return false;
500}
501
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000502}
503
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000504namespace es2dx
505{
506
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000507D3DCMPFUNC ConvertComparison(GLenum comparison)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508{
509 D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
510 switch (comparison)
511 {
512 case GL_NEVER: d3dComp = D3DCMP_NEVER; break;
513 case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break;
514 case GL_LESS: d3dComp = D3DCMP_LESS; break;
515 case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break;
516 case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break;
517 case GL_GREATER: d3dComp = D3DCMP_GREATER; break;
518 case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break;
519 case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break;
520 default: UNREACHABLE();
521 }
522
523 return d3dComp;
524}
525
526D3DCOLOR ConvertColor(gl::Color color)
527{
528 return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000529 gl::unorm<8>(color.green),
daniel@transgaming.comfe453652010-03-16 06:23:28 +0000530 gl::unorm<8>(color.blue),
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000531 gl::unorm<8>(color.alpha));
532}
533
534D3DBLEND ConvertBlendFunc(GLenum blend)
535{
536 D3DBLEND d3dBlend = D3DBLEND_ZERO;
537
538 switch (blend)
539 {
540 case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break;
541 case GL_ONE: d3dBlend = D3DBLEND_ONE; break;
542 case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break;
543 case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break;
544 case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break;
545 case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break;
546 case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break;
547 case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break;
548 case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break;
549 case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break;
550 case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break;
551 case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
552 case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break;
553 case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
554 case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break;
555 default: UNREACHABLE();
556 }
557
558 return d3dBlend;
559}
560
561D3DBLENDOP ConvertBlendOp(GLenum blendOp)
562{
563 D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
564
565 switch (blendOp)
566 {
567 case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break;
568 case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break;
569 case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
570 default: UNREACHABLE();
571 }
572
573 return d3dBlendOp;
574}
575
576D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
577{
578 D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
579
580 switch (stencilOp)
581 {
582 case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break;
583 case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break;
584 case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break;
585 case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
586 case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
587 case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break;
588 case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break;
589 case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break;
590 default: UNREACHABLE();
591 }
592
593 return d3dStencilOp;
594}
595
596D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
597{
598 D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
599
600 switch (wrap)
601 {
602 case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break;
603 case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break;
604 case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
605 default: UNREACHABLE();
606 }
607
608 return d3dWrap;
609}
610
611D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
612{
613 D3DCULL cull = D3DCULL_CCW;
614 switch (cullFace)
615 {
616 case GL_FRONT:
617 cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
618 break;
619 case GL_BACK:
620 cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
621 break;
622 case GL_FRONT_AND_BACK:
daniel@transgaming.comace5e662010-03-21 04:31:20 +0000623 cull = D3DCULL_NONE; // culling will be handled during draw
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000624 break;
625 default: UNREACHABLE();
626 }
627
628 return cull;
629}
630
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +0000631D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
632{
633 D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
634
635 // Map a cube map texture target to the corresponding D3D surface index. Note that the
636 // Y faces are swapped because the Y coordinate to the texture lookup intrinsic functions
637 // are negated in the pixel shader.
638 switch (cubeFace)
639 {
640 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
641 face = D3DCUBEMAP_FACE_POSITIVE_X;
642 break;
643 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
644 face = D3DCUBEMAP_FACE_NEGATIVE_X;
645 break;
646 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
647 face = D3DCUBEMAP_FACE_NEGATIVE_Y;
648 break;
649 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
650 face = D3DCUBEMAP_FACE_POSITIVE_Y;
651 break;
652 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
653 face = D3DCUBEMAP_FACE_POSITIVE_Z;
654 break;
655 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
656 face = D3DCUBEMAP_FACE_NEGATIVE_Z;
657 break;
658 default: UNREACHABLE();
659 }
660
661 return face;
662}
663
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000664DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
665{
666 return (red ? D3DCOLORWRITEENABLE_RED : 0) |
667 (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
668 (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
669 (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
670}
671
672D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
673{
674 D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
675 switch (magFilter)
676 {
677 case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
678 case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
679 default: UNREACHABLE();
680 }
681
682 return d3dMagFilter;
683}
684
685void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter)
686{
687 switch (minFilter)
688 {
689 case GL_NEAREST:
690 *d3dMinFilter = D3DTEXF_POINT;
691 *d3dMipFilter = D3DTEXF_NONE;
692 break;
693 case GL_LINEAR:
694 *d3dMinFilter = D3DTEXF_LINEAR;
695 *d3dMipFilter = D3DTEXF_NONE;
696 break;
697 case GL_NEAREST_MIPMAP_NEAREST:
698 *d3dMinFilter = D3DTEXF_POINT;
699 *d3dMipFilter = D3DTEXF_POINT;
700 break;
701 case GL_LINEAR_MIPMAP_NEAREST:
702 *d3dMinFilter = D3DTEXF_LINEAR;
703 *d3dMipFilter = D3DTEXF_POINT;
704 break;
705 case GL_NEAREST_MIPMAP_LINEAR:
706 *d3dMinFilter = D3DTEXF_POINT;
707 *d3dMipFilter = D3DTEXF_LINEAR;
708 break;
709 case GL_LINEAR_MIPMAP_LINEAR:
710 *d3dMinFilter = D3DTEXF_LINEAR;
711 *d3dMipFilter = D3DTEXF_LINEAR;
712 break;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000713 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000714 *d3dMinFilter = D3DTEXF_POINT;
715 *d3dMipFilter = D3DTEXF_NONE;
716 UNREACHABLE();
717 }
718}
719
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000720bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
721 D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
722{
723 switch (primitiveType)
724 {
725 case GL_POINTS:
726 *d3dPrimitiveType = D3DPT_POINTLIST;
727 *d3dPrimitiveCount = elementCount;
728 break;
729 case GL_LINES:
730 *d3dPrimitiveType = D3DPT_LINELIST;
731 *d3dPrimitiveCount = elementCount / 2;
732 break;
733 case GL_LINE_LOOP:
734 *d3dPrimitiveType = D3DPT_LINESTRIP;
735 *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately
736 break;
737 case GL_LINE_STRIP:
738 *d3dPrimitiveType = D3DPT_LINESTRIP;
739 *d3dPrimitiveCount = elementCount - 1;
740 break;
741 case GL_TRIANGLES:
742 *d3dPrimitiveType = D3DPT_TRIANGLELIST;
743 *d3dPrimitiveCount = elementCount / 3;
744 break;
745 case GL_TRIANGLE_STRIP:
746 *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
747 *d3dPrimitiveCount = elementCount - 2;
748 break;
749 case GL_TRIANGLE_FAN:
750 *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
751 *d3dPrimitiveCount = elementCount - 2;
752 break;
753 default:
754 return false;
755 }
756
757 return true;
758}
759
760D3DFORMAT ConvertRenderbufferFormat(GLenum format)
761{
762 switch (format)
763 {
764 case GL_RGBA4:
765 case GL_RGB5_A1:
766 case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
767 case GL_RGB565: return D3DFMT_R5G6B5;
768 case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
769 case GL_DEPTH_COMPONENT16:
770 case GL_STENCIL_INDEX8:
771 case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
772 default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
773 }
774}
775
776D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
777{
778 if (samples <= 1)
779 return D3DMULTISAMPLE_NONE;
780 else
781 return (D3DMULTISAMPLE_TYPE)samples;
782}
783
784}
785
786namespace dx2es
787{
788
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789unsigned int GetStencilSize(D3DFORMAT stencilFormat)
790{
791 switch(stencilFormat)
792 {
793 case D3DFMT_D24FS8:
794 case D3DFMT_D24S8:
795 return 8;
796 case D3DFMT_D24X4S4:
797 return 4;
798 case D3DFMT_D15S1:
799 return 1;
800 case D3DFMT_D16_LOCKABLE:
801 case D3DFMT_D32:
802 case D3DFMT_D24X8:
803 case D3DFMT_D32F_LOCKABLE:
804 case D3DFMT_D16:
805 return 0;
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000806 //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
807 //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
apatrick@chromium.org831fe2a2011-03-17 18:44:29 +0000808 default:
809 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811}
812
813unsigned int GetAlphaSize(D3DFORMAT colorFormat)
814{
815 switch (colorFormat)
816 {
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000817 case D3DFMT_A16B16G16R16F:
818 return 16;
819 case D3DFMT_A32B32G32R32F:
820 return 32;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000821 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000822 return 2;
823 case D3DFMT_A8R8G8B8:
824 return 8;
825 case D3DFMT_A1R5G5B5:
826 return 1;
827 case D3DFMT_X8R8G8B8:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828 case D3DFMT_R5G6B5:
829 return 0;
apatrick@chromium.org831fe2a2011-03-17 18:44:29 +0000830 default:
831 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000832 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000833}
834
835unsigned int GetRedSize(D3DFORMAT colorFormat)
836{
837 switch (colorFormat)
838 {
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000839 case D3DFMT_A16B16G16R16F:
840 return 16;
841 case D3DFMT_A32B32G32R32F:
842 return 32;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000843 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000844 return 10;
845 case D3DFMT_A8R8G8B8:
846 case D3DFMT_X8R8G8B8:
847 return 8;
848 case D3DFMT_A1R5G5B5:
849 case D3DFMT_R5G6B5:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000850 return 5;
apatrick@chromium.org831fe2a2011-03-17 18:44:29 +0000851 default:
852 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000854}
855
856unsigned int GetGreenSize(D3DFORMAT colorFormat)
857{
858 switch (colorFormat)
859 {
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000860 case D3DFMT_A16B16G16R16F:
861 return 16;
862 case D3DFMT_A32B32G32R32F:
863 return 32;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000864 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000865 return 10;
866 case D3DFMT_A8R8G8B8:
867 case D3DFMT_X8R8G8B8:
868 return 8;
869 case D3DFMT_A1R5G5B5:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000870 return 5;
871 case D3DFMT_R5G6B5:
872 return 6;
apatrick@chromium.org831fe2a2011-03-17 18:44:29 +0000873 default:
874 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000875 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876}
877
878unsigned int GetBlueSize(D3DFORMAT colorFormat)
879{
880 switch (colorFormat)
881 {
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000882 case D3DFMT_A16B16G16R16F:
883 return 16;
884 case D3DFMT_A32B32G32R32F:
885 return 32;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000886 case D3DFMT_A2R10G10B10:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000887 return 10;
888 case D3DFMT_A8R8G8B8:
889 case D3DFMT_X8R8G8B8:
890 return 8;
891 case D3DFMT_A1R5G5B5:
892 case D3DFMT_R5G6B5:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000893 return 5;
apatrick@chromium.org831fe2a2011-03-17 18:44:29 +0000894 default:
895 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000896 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000897}
898
899unsigned int GetDepthSize(D3DFORMAT depthFormat)
900{
901 switch (depthFormat)
902 {
903 case D3DFMT_D16_LOCKABLE: return 16;
904 case D3DFMT_D32: return 32;
905 case D3DFMT_D15S1: return 15;
906 case D3DFMT_D24S8: return 24;
907 case D3DFMT_D24X8: return 24;
908 case D3DFMT_D24X4S4: return 24;
909 case D3DFMT_D16: return 16;
910 case D3DFMT_D32F_LOCKABLE: return 32;
911 case D3DFMT_D24FS8: return 24;
daniel@transgaming.com83921382011-01-08 05:46:00 +0000912 //case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
913 //case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
apatrick@chromium.org831fe2a2011-03-17 18:44:29 +0000914 default: return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000915 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000916}
917
daniel@transgaming.combbeffbb2011-11-09 17:46:11 +0000918bool IsFloat32Format(D3DFORMAT surfaceFormat)
919{
920 switch(surfaceFormat)
921 {
922 case D3DFMT_R16F:
923 case D3DFMT_G16R16F:
924 case D3DFMT_A16B16G16R16F:
925 return false;
926 case D3DFMT_R32F:
927 case D3DFMT_G32R32F:
928 case D3DFMT_A32B32G32R32F:
929 return true;
930 case D3DFMT_A8R8G8B8:
931 case D3DFMT_X8R8G8B8:
932 case D3DFMT_A1R5G5B5:
933 case D3DFMT_R5G6B5:
934 return false;
935 default: UNREACHABLE();
936 }
937 return false;
938}
939
940bool IsFloat16Format(D3DFORMAT surfaceFormat)
941{
942 switch(surfaceFormat)
943 {
944 case D3DFMT_R16F:
945 case D3DFMT_G16R16F:
946 case D3DFMT_A16B16G16R16F:
947 return true;
948 case D3DFMT_R32F:
949 case D3DFMT_G32R32F:
950 case D3DFMT_A32B32G32R32F:
951 return false;
952 case D3DFMT_A8R8G8B8:
953 case D3DFMT_X8R8G8B8:
954 case D3DFMT_A1R5G5B5:
955 case D3DFMT_R5G6B5:
956 return false;
957 default: UNREACHABLE();
958 }
959 return false;
960}
961
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000962GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
963{
964 if (type == D3DMULTISAMPLE_NONMASKABLE)
965 return 0;
966 else
967 return type;
968}
969
daniel@transgaming.com73a5db62010-10-15 17:58:13 +0000970GLenum ConvertBackBufferFormat(D3DFORMAT format)
971{
972 switch (format)
973 {
974 case D3DFMT_A4R4G4B4: return GL_RGBA4;
975 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
976 case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
977 case D3DFMT_R5G6B5: return GL_RGB565;
978 case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
979 default:
980 UNREACHABLE();
981 }
982
983 return GL_RGBA4;
984}
985
986GLenum ConvertDepthStencilFormat(D3DFORMAT format)
987{
988 switch (format)
989 {
990 case D3DFMT_D16:
991 case D3DFMT_D24X8:
992 return GL_DEPTH_COMPONENT16;
993 case D3DFMT_D24S8:
994 return GL_DEPTH24_STENCIL8_OES;
995 default:
996 UNREACHABLE();
997 }
998
999 return GL_DEPTH24_STENCIL8_OES;
1000}
1001
1002}
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001003
1004std::string getTempPath()
1005{
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001006 char path[MAX_PATH];
1007 DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
1008 if (pathLen == 0)
1009 {
1010 UNREACHABLE();
1011 return std::string();
1012 }
1013
1014 UINT unique = GetTempFileNameA(path, "sh", 0, path);
1015 if (unique == 0)
1016 {
1017 UNREACHABLE();
1018 return std::string();
1019 }
1020
1021 return path;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001022}
1023
1024void writeFile(const char* path, const void* content, size_t size)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001025{
1026 FILE* file = fopen(path, "w");
1027 if (!file)
1028 {
1029 UNREACHABLE();
1030 return;
1031 }
1032
1033 fwrite(content, sizeof(char), size, file);
1034 fclose(file);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001035}