blob: c11f5c6fcdd1eb4cfb52a2a17f0dbc711fd90396 [file] [log] [blame]
daniel@transgaming.comd8e36562012-10-31 19:52:19 +00001//
2// Copyright (c) 2002-2012 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// renderer9_utils.cpp: Conversion functions and other utility routines
8// specific to the D3D9 renderer.
9
10#include "libGLESv2/renderer/renderer9_utils.h"
11#include "libGLESv2/mathutil.h"
12#include "libGLESv2/Context.h"
13
14#include "common/debug.h"
15
daniel@transgaming.com682a37c2012-11-28 19:34:44 +000016namespace gl_d3d9
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000017{
18
19D3DCMPFUNC ConvertComparison(GLenum comparison)
20{
21 D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
22 switch (comparison)
23 {
24 case GL_NEVER: d3dComp = D3DCMP_NEVER; break;
25 case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break;
26 case GL_LESS: d3dComp = D3DCMP_LESS; break;
27 case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break;
28 case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break;
29 case GL_GREATER: d3dComp = D3DCMP_GREATER; break;
30 case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break;
31 case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break;
32 default: UNREACHABLE();
33 }
34
35 return d3dComp;
36}
37
38D3DCOLOR ConvertColor(gl::Color color)
39{
40 return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
41 gl::unorm<8>(color.green),
42 gl::unorm<8>(color.blue),
43 gl::unorm<8>(color.alpha));
44}
45
46D3DBLEND ConvertBlendFunc(GLenum blend)
47{
48 D3DBLEND d3dBlend = D3DBLEND_ZERO;
49
50 switch (blend)
51 {
52 case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break;
53 case GL_ONE: d3dBlend = D3DBLEND_ONE; break;
54 case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break;
55 case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break;
56 case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break;
57 case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break;
58 case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break;
59 case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break;
60 case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break;
61 case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break;
62 case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break;
63 case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
64 case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break;
65 case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
66 case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break;
67 default: UNREACHABLE();
68 }
69
70 return d3dBlend;
71}
72
73D3DBLENDOP ConvertBlendOp(GLenum blendOp)
74{
75 D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
76
77 switch (blendOp)
78 {
79 case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break;
80 case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break;
81 case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
82 default: UNREACHABLE();
83 }
84
85 return d3dBlendOp;
86}
87
88D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
89{
90 D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
91
92 switch (stencilOp)
93 {
94 case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break;
95 case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break;
96 case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break;
97 case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
98 case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
99 case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break;
100 case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break;
101 case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break;
102 default: UNREACHABLE();
103 }
104
105 return d3dStencilOp;
106}
107
108D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
109{
110 D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
111
112 switch (wrap)
113 {
114 case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break;
115 case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break;
116 case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
117 default: UNREACHABLE();
118 }
119
120 return d3dWrap;
121}
122
123D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
124{
125 D3DCULL cull = D3DCULL_CCW;
126 switch (cullFace)
127 {
128 case GL_FRONT:
129 cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
130 break;
131 case GL_BACK:
132 cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
133 break;
134 case GL_FRONT_AND_BACK:
135 cull = D3DCULL_NONE; // culling will be handled during draw
136 break;
137 default: UNREACHABLE();
138 }
139
140 return cull;
141}
142
143D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
144{
145 D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
146
147 switch (cubeFace)
148 {
149 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
150 face = D3DCUBEMAP_FACE_POSITIVE_X;
151 break;
152 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
153 face = D3DCUBEMAP_FACE_NEGATIVE_X;
154 break;
155 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
156 face = D3DCUBEMAP_FACE_POSITIVE_Y;
157 break;
158 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
159 face = D3DCUBEMAP_FACE_NEGATIVE_Y;
160 break;
161 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
162 face = D3DCUBEMAP_FACE_POSITIVE_Z;
163 break;
164 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
165 face = D3DCUBEMAP_FACE_NEGATIVE_Z;
166 break;
167 default: UNREACHABLE();
168 }
169
170 return face;
171}
172
173DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
174{
175 return (red ? D3DCOLORWRITEENABLE_RED : 0) |
176 (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
177 (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
178 (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
179}
180
181D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
182{
183 if (maxAnisotropy > 1.0f)
184 {
185 return D3DTEXF_ANISOTROPIC;
186 }
187
188 D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
189 switch (magFilter)
190 {
191 case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
192 case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
193 default: UNREACHABLE();
194 }
195
196 return d3dMagFilter;
197}
198
199void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
200{
201 switch (minFilter)
202 {
203 case GL_NEAREST:
204 *d3dMinFilter = D3DTEXF_POINT;
205 *d3dMipFilter = D3DTEXF_NONE;
206 break;
207 case GL_LINEAR:
208 *d3dMinFilter = D3DTEXF_LINEAR;
209 *d3dMipFilter = D3DTEXF_NONE;
210 break;
211 case GL_NEAREST_MIPMAP_NEAREST:
212 *d3dMinFilter = D3DTEXF_POINT;
213 *d3dMipFilter = D3DTEXF_POINT;
214 break;
215 case GL_LINEAR_MIPMAP_NEAREST:
216 *d3dMinFilter = D3DTEXF_LINEAR;
217 *d3dMipFilter = D3DTEXF_POINT;
218 break;
219 case GL_NEAREST_MIPMAP_LINEAR:
220 *d3dMinFilter = D3DTEXF_POINT;
221 *d3dMipFilter = D3DTEXF_LINEAR;
222 break;
223 case GL_LINEAR_MIPMAP_LINEAR:
224 *d3dMinFilter = D3DTEXF_LINEAR;
225 *d3dMipFilter = D3DTEXF_LINEAR;
226 break;
227 default:
228 *d3dMinFilter = D3DTEXF_POINT;
229 *d3dMipFilter = D3DTEXF_NONE;
230 UNREACHABLE();
231 }
232
233 if (maxAnisotropy > 1.0f)
234 {
235 *d3dMinFilter = D3DTEXF_ANISOTROPIC;
236 }
237}
238
239bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
240 D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
241{
242 switch (primitiveType)
243 {
244 case GL_POINTS:
245 *d3dPrimitiveType = D3DPT_POINTLIST;
246 *d3dPrimitiveCount = elementCount;
247 break;
248 case GL_LINES:
249 *d3dPrimitiveType = D3DPT_LINELIST;
250 *d3dPrimitiveCount = elementCount / 2;
251 break;
252 case GL_LINE_LOOP:
253 *d3dPrimitiveType = D3DPT_LINESTRIP;
254 *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately
255 break;
256 case GL_LINE_STRIP:
257 *d3dPrimitiveType = D3DPT_LINESTRIP;
258 *d3dPrimitiveCount = elementCount - 1;
259 break;
260 case GL_TRIANGLES:
261 *d3dPrimitiveType = D3DPT_TRIANGLELIST;
262 *d3dPrimitiveCount = elementCount / 3;
263 break;
264 case GL_TRIANGLE_STRIP:
265 *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
266 *d3dPrimitiveCount = elementCount - 2;
267 break;
268 case GL_TRIANGLE_FAN:
269 *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
270 *d3dPrimitiveCount = elementCount - 2;
271 break;
272 default:
273 return false;
274 }
275
276 return true;
277}
278
279D3DFORMAT ConvertRenderbufferFormat(GLenum format)
280{
281 switch (format)
282 {
283 case GL_NONE: return D3DFMT_NULL;
284 case GL_RGBA4:
285 case GL_RGB5_A1:
286 case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
287 case GL_RGB565: return D3DFMT_R5G6B5;
288 case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
289 case GL_DEPTH_COMPONENT16:
290 case GL_STENCIL_INDEX8:
291 case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
292 default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
293 }
294}
295
296D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
297{
298 if (samples <= 1)
299 return D3DMULTISAMPLE_NONE;
300 else
301 return (D3DMULTISAMPLE_TYPE)samples;
302}
303
304}
305
daniel@transgaming.com682a37c2012-11-28 19:34:44 +0000306namespace d3d9_gl
daniel@transgaming.comd8e36562012-10-31 19:52:19 +0000307{
308
309unsigned int GetStencilSize(D3DFORMAT stencilFormat)
310{
311 if (stencilFormat == D3DFMT_INTZ)
312 {
313 return 8;
314 }
315 switch(stencilFormat)
316 {
317 case D3DFMT_D24FS8:
318 case D3DFMT_D24S8:
319 return 8;
320 case D3DFMT_D24X4S4:
321 return 4;
322 case D3DFMT_D15S1:
323 return 1;
324 case D3DFMT_D16_LOCKABLE:
325 case D3DFMT_D32:
326 case D3DFMT_D24X8:
327 case D3DFMT_D32F_LOCKABLE:
328 case D3DFMT_D16:
329 return 0;
330 //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
331 //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
332 default:
333 return 0;
334 }
335}
336
337unsigned int GetAlphaSize(D3DFORMAT colorFormat)
338{
339 switch (colorFormat)
340 {
341 case D3DFMT_A16B16G16R16F:
342 return 16;
343 case D3DFMT_A32B32G32R32F:
344 return 32;
345 case D3DFMT_A2R10G10B10:
346 return 2;
347 case D3DFMT_A8R8G8B8:
348 return 8;
349 case D3DFMT_A1R5G5B5:
350 return 1;
351 case D3DFMT_X8R8G8B8:
352 case D3DFMT_R5G6B5:
353 return 0;
354 default:
355 return 0;
356 }
357}
358
359GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
360{
361 if (type == D3DMULTISAMPLE_NONMASKABLE)
362 return 0;
363 else
364 return type;
365}
366
367bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
368{
369 switch (d3dformat)
370 {
371 case D3DFMT_L8:
372 return (format == GL_LUMINANCE);
373 case D3DFMT_A8L8:
374 return (format == GL_LUMINANCE_ALPHA);
375 case D3DFMT_DXT1:
376 return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
377 case D3DFMT_DXT3:
378 return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
379 case D3DFMT_DXT5:
380 return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
381 case D3DFMT_A8R8G8B8:
382 case D3DFMT_A16B16G16R16F:
383 case D3DFMT_A32B32G32R32F:
384 return (format == GL_RGBA || format == GL_BGRA_EXT);
385 case D3DFMT_X8R8G8B8:
386 return (format == GL_RGB);
387 default:
388 if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format))
389 return true;
390 return false;
391 }
392}
393
394GLenum ConvertBackBufferFormat(D3DFORMAT format)
395{
396 switch (format)
397 {
398 case D3DFMT_A4R4G4B4: return GL_RGBA4;
399 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
400 case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
401 case D3DFMT_R5G6B5: return GL_RGB565;
402 case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
403 default:
404 UNREACHABLE();
405 }
406
407 return GL_RGBA4;
408}
409
410GLenum ConvertDepthStencilFormat(D3DFORMAT format)
411{
412 if (format == D3DFMT_INTZ)
413 {
414 return GL_DEPTH24_STENCIL8_OES;
415 }
416 switch (format)
417 {
418 case D3DFMT_D16:
419 case D3DFMT_D24X8:
420 return GL_DEPTH_COMPONENT16;
421 case D3DFMT_D24S8:
422 return GL_DEPTH24_STENCIL8_OES;
423 case D3DFMT_UNKNOWN:
424 return GL_NONE;
425 default:
426 UNREACHABLE();
427 }
428
429 return GL_DEPTH24_STENCIL8_OES;
430}
431
daniel@transgaming.com4df38ce2012-11-28 19:37:03 +0000432GLenum ConvertRenderTargetFormat(D3DFORMAT format)
433{
434 if (format == D3DFMT_INTZ)
435 {
436 return GL_DEPTH24_STENCIL8_OES;
437 }
438
439 switch (format)
440 {
441 case D3DFMT_A4R4G4B4: return GL_RGBA4;
442 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
443 case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
444 case D3DFMT_R5G6B5: return GL_RGB565;
445 case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
446 case D3DFMT_D16:
447 case D3DFMT_D24X8:
448 return GL_DEPTH_COMPONENT16;
449 case D3DFMT_D24S8:
450 return GL_DEPTH24_STENCIL8_OES;
451 case D3DFMT_UNKNOWN:
452 return GL_NONE;
453 default:
454 UNREACHABLE();
455 }
456
457 return GL_RGBA4;
458}
459
daniel@transgaming.comd8e36562012-10-31 19:52:19 +0000460GLenum GetEquivalentFormat(D3DFORMAT format)
461{
462 if (format == D3DFMT_INTZ)
463 return GL_DEPTH24_STENCIL8_OES;
464 if (format == D3DFMT_NULL)
465 return GL_NONE;
466
467 switch (format)
468 {
469 case D3DFMT_A4R4G4B4: return GL_RGBA4;
470 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
471 case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
472 case D3DFMT_R5G6B5: return GL_RGB565;
473 case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
474 case D3DFMT_D16: return GL_DEPTH_COMPONENT16;
475 case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES;
476 case D3DFMT_UNKNOWN: return GL_NONE;
477 case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
478 case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
479 case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
480 case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT;
481 case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT;
482 case D3DFMT_L8: return GL_LUMINANCE8_EXT;
483 case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT;
484 default: UNREACHABLE();
485 return GL_NONE;
486 }
487}
488
489}
490
491namespace dx
492{
493
494bool IsCompressedFormat(D3DFORMAT surfaceFormat)
495{
496 switch(surfaceFormat)
497 {
498 case D3DFMT_DXT1:
499 case D3DFMT_DXT2:
500 case D3DFMT_DXT3:
501 case D3DFMT_DXT4:
502 case D3DFMT_DXT5:
503 return true;
504 default:
505 return false;
506 }
507}
508
509size_t ComputeRowSize(D3DFORMAT format, unsigned int width)
510{
511 if (format == D3DFMT_INTZ)
512 {
513 return 4 * width;
514 }
515 switch (format)
516 {
517 case D3DFMT_L8:
518 return 1 * width;
519 case D3DFMT_A8L8:
520 return 2 * width;
521 case D3DFMT_X8R8G8B8:
522 case D3DFMT_A8R8G8B8:
523 return 4 * width;
524 case D3DFMT_A16B16G16R16F:
525 return 8 * width;
526 case D3DFMT_A32B32G32R32F:
527 return 16 * width;
528 case D3DFMT_DXT1:
529 return 8 * ((width + 3) / 4);
530 case D3DFMT_DXT3:
531 case D3DFMT_DXT5:
532 return 16 * ((width + 3) / 4);
533 default:
534 UNREACHABLE();
535 return 0;
536 }
537}
538
539}