blob: 3474f0877c5d422b8aa9d0869e801d9df0a60671 [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
daniel@transgaming.comd8e36562012-10-31 19:52:19 +0000239D3DFORMAT ConvertRenderbufferFormat(GLenum format)
240{
241 switch (format)
242 {
243 case GL_NONE: return D3DFMT_NULL;
244 case GL_RGBA4:
245 case GL_RGB5_A1:
246 case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
247 case GL_RGB565: return D3DFMT_R5G6B5;
248 case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
249 case GL_DEPTH_COMPONENT16:
250 case GL_STENCIL_INDEX8:
251 case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
252 default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
253 }
254}
255
256D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
257{
258 if (samples <= 1)
259 return D3DMULTISAMPLE_NONE;
260 else
261 return (D3DMULTISAMPLE_TYPE)samples;
262}
263
264}
265
daniel@transgaming.com682a37c2012-11-28 19:34:44 +0000266namespace d3d9_gl
daniel@transgaming.comd8e36562012-10-31 19:52:19 +0000267{
268
269unsigned int GetStencilSize(D3DFORMAT stencilFormat)
270{
271 if (stencilFormat == D3DFMT_INTZ)
272 {
273 return 8;
274 }
275 switch(stencilFormat)
276 {
277 case D3DFMT_D24FS8:
278 case D3DFMT_D24S8:
279 return 8;
280 case D3DFMT_D24X4S4:
281 return 4;
282 case D3DFMT_D15S1:
283 return 1;
284 case D3DFMT_D16_LOCKABLE:
285 case D3DFMT_D32:
286 case D3DFMT_D24X8:
287 case D3DFMT_D32F_LOCKABLE:
288 case D3DFMT_D16:
289 return 0;
290 //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
291 //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
292 default:
293 return 0;
294 }
295}
296
297unsigned int GetAlphaSize(D3DFORMAT colorFormat)
298{
299 switch (colorFormat)
300 {
301 case D3DFMT_A16B16G16R16F:
302 return 16;
303 case D3DFMT_A32B32G32R32F:
304 return 32;
305 case D3DFMT_A2R10G10B10:
306 return 2;
307 case D3DFMT_A8R8G8B8:
308 return 8;
309 case D3DFMT_A1R5G5B5:
310 return 1;
311 case D3DFMT_X8R8G8B8:
312 case D3DFMT_R5G6B5:
313 return 0;
314 default:
315 return 0;
316 }
317}
318
319GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
320{
321 if (type == D3DMULTISAMPLE_NONMASKABLE)
322 return 0;
323 else
324 return type;
325}
326
327bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
328{
329 switch (d3dformat)
330 {
331 case D3DFMT_L8:
332 return (format == GL_LUMINANCE);
333 case D3DFMT_A8L8:
334 return (format == GL_LUMINANCE_ALPHA);
335 case D3DFMT_DXT1:
336 return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
337 case D3DFMT_DXT3:
338 return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
339 case D3DFMT_DXT5:
340 return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
341 case D3DFMT_A8R8G8B8:
342 case D3DFMT_A16B16G16R16F:
343 case D3DFMT_A32B32G32R32F:
344 return (format == GL_RGBA || format == GL_BGRA_EXT);
345 case D3DFMT_X8R8G8B8:
346 return (format == GL_RGB);
347 default:
348 if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format))
349 return true;
350 return false;
351 }
352}
353
354GLenum ConvertBackBufferFormat(D3DFORMAT format)
355{
356 switch (format)
357 {
358 case D3DFMT_A4R4G4B4: return GL_RGBA4;
359 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
360 case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
361 case D3DFMT_R5G6B5: return GL_RGB565;
362 case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
363 default:
364 UNREACHABLE();
365 }
366
367 return GL_RGBA4;
368}
369
370GLenum ConvertDepthStencilFormat(D3DFORMAT format)
371{
372 if (format == D3DFMT_INTZ)
373 {
374 return GL_DEPTH24_STENCIL8_OES;
375 }
376 switch (format)
377 {
378 case D3DFMT_D16:
379 case D3DFMT_D24X8:
380 return GL_DEPTH_COMPONENT16;
381 case D3DFMT_D24S8:
382 return GL_DEPTH24_STENCIL8_OES;
383 case D3DFMT_UNKNOWN:
384 return GL_NONE;
385 default:
386 UNREACHABLE();
387 }
388
389 return GL_DEPTH24_STENCIL8_OES;
390}
391
daniel@transgaming.com4df38ce2012-11-28 19:37:03 +0000392GLenum ConvertRenderTargetFormat(D3DFORMAT format)
393{
394 if (format == D3DFMT_INTZ)
395 {
396 return GL_DEPTH24_STENCIL8_OES;
397 }
398
399 switch (format)
400 {
401 case D3DFMT_A4R4G4B4: return GL_RGBA4;
402 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
403 case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
404 case D3DFMT_R5G6B5: return GL_RGB565;
405 case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
406 case D3DFMT_D16:
407 case D3DFMT_D24X8:
408 return GL_DEPTH_COMPONENT16;
409 case D3DFMT_D24S8:
410 return GL_DEPTH24_STENCIL8_OES;
411 case D3DFMT_UNKNOWN:
412 return GL_NONE;
413 default:
414 UNREACHABLE();
415 }
416
417 return GL_RGBA4;
418}
419
daniel@transgaming.comd8e36562012-10-31 19:52:19 +0000420GLenum GetEquivalentFormat(D3DFORMAT format)
421{
422 if (format == D3DFMT_INTZ)
423 return GL_DEPTH24_STENCIL8_OES;
424 if (format == D3DFMT_NULL)
425 return GL_NONE;
426
427 switch (format)
428 {
429 case D3DFMT_A4R4G4B4: return GL_RGBA4;
430 case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
431 case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
432 case D3DFMT_R5G6B5: return GL_RGB565;
433 case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
434 case D3DFMT_D16: return GL_DEPTH_COMPONENT16;
435 case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES;
436 case D3DFMT_UNKNOWN: return GL_NONE;
437 case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
438 case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
439 case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
440 case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT;
441 case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT;
442 case D3DFMT_L8: return GL_LUMINANCE8_EXT;
443 case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT;
444 default: UNREACHABLE();
445 return GL_NONE;
446 }
447}
448
449}
450
daniel@transgaming.com9a583652012-12-20 21:07:54 +0000451namespace d3d9
daniel@transgaming.comd8e36562012-10-31 19:52:19 +0000452{
453
454bool IsCompressedFormat(D3DFORMAT surfaceFormat)
455{
456 switch(surfaceFormat)
457 {
458 case D3DFMT_DXT1:
459 case D3DFMT_DXT2:
460 case D3DFMT_DXT3:
461 case D3DFMT_DXT4:
462 case D3DFMT_DXT5:
463 return true;
464 default:
465 return false;
466 }
467}
468
469size_t ComputeRowSize(D3DFORMAT format, unsigned int width)
470{
471 if (format == D3DFMT_INTZ)
472 {
473 return 4 * width;
474 }
475 switch (format)
476 {
477 case D3DFMT_L8:
478 return 1 * width;
479 case D3DFMT_A8L8:
480 return 2 * width;
481 case D3DFMT_X8R8G8B8:
482 case D3DFMT_A8R8G8B8:
483 return 4 * width;
484 case D3DFMT_A16B16G16R16F:
485 return 8 * width;
486 case D3DFMT_A32B32G32R32F:
487 return 16 * width;
488 case D3DFMT_DXT1:
489 return 8 * ((width + 3) / 4);
490 case D3DFMT_DXT3:
491 case D3DFMT_DXT5:
492 return 16 * ((width + 3) / 4);
493 default:
494 UNREACHABLE();
495 return 0;
496 }
497}
498
499}