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