1//
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
9#include "libGLESv2/utilities.h"
10
11#include <limits>
12
13#include "common/debug.h"
14
15#include "libGLESv2/mathutil.h"
16#include "libGLESv2/Context.h"
17
18namespace 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      case GL_SAMPLER_2D:
29      case GL_SAMPLER_CUBE:
30          return 1;
31      case GL_BOOL_VEC2:
32      case GL_FLOAT_VEC2:
33      case GL_INT_VEC2:
34          return 2;
35      case GL_INT_VEC3:
36      case GL_FLOAT_VEC3:
37      case GL_BOOL_VEC3:
38          return 3;
39      case GL_BOOL_VEC4:
40      case GL_FLOAT_VEC4:
41      case GL_INT_VEC4:
42      case GL_FLOAT_MAT2:
43          return 4;
44      case GL_FLOAT_MAT3:
45          return 9;
46      case GL_FLOAT_MAT4:
47          return 16;
48      default:
49          UNREACHABLE();
50    }
51
52    return 0;
53}
54
55GLenum UniformComponentType(GLenum type)
56{
57    switch(type)
58    {
59      case GL_BOOL:
60      case GL_BOOL_VEC2:
61      case GL_BOOL_VEC3:
62      case GL_BOOL_VEC4:
63          return GL_BOOL;
64      case GL_FLOAT:
65      case GL_FLOAT_VEC2:
66      case GL_FLOAT_VEC3:
67      case GL_FLOAT_VEC4:
68      case GL_FLOAT_MAT2:
69      case GL_FLOAT_MAT3:
70      case GL_FLOAT_MAT4:
71          return GL_FLOAT;
72      case GL_INT:
73      case GL_SAMPLER_2D:
74      case GL_SAMPLER_CUBE:
75      case GL_INT_VEC2:
76      case GL_INT_VEC3:
77      case GL_INT_VEC4:
78          return GL_INT;
79      default:
80          UNREACHABLE();
81    }
82
83    return GL_NONE;
84}
85
86size_t UniformTypeSize(GLenum type)
87{
88    switch(type)
89    {
90      case GL_BOOL:  return sizeof(GLboolean);
91      case GL_FLOAT: return sizeof(GLfloat);
92      case GL_INT:   return sizeof(GLint);
93    }
94
95    return UniformTypeSize(UniformComponentType(type)) * UniformComponentCount(type);
96}
97
98int VariableRowCount(GLenum type)
99{
100    switch (type)
101    {
102      case GL_NONE:
103        return 0;
104      case GL_BOOL:
105      case GL_FLOAT:
106      case GL_INT:
107      case GL_BOOL_VEC2:
108      case GL_FLOAT_VEC2:
109      case GL_INT_VEC2:
110      case GL_INT_VEC3:
111      case GL_FLOAT_VEC3:
112      case GL_BOOL_VEC3:
113      case GL_BOOL_VEC4:
114      case GL_FLOAT_VEC4:
115      case GL_INT_VEC4:
116        return 1;
117      case GL_FLOAT_MAT2:
118        return 2;
119      case GL_FLOAT_MAT3:
120        return 3;
121      case GL_FLOAT_MAT4:
122        return 4;
123      default:
124        UNREACHABLE();
125    }
126
127    return 0;
128}
129
130int VariableColumnCount(GLenum type)
131{
132    switch (type)
133    {
134      case GL_NONE:
135        return 0;
136      case GL_BOOL:
137      case GL_FLOAT:
138      case GL_INT:
139        return 1;
140      case GL_BOOL_VEC2:
141      case GL_FLOAT_VEC2:
142      case GL_INT_VEC2:
143      case GL_FLOAT_MAT2:
144        return 2;
145      case GL_INT_VEC3:
146      case GL_FLOAT_VEC3:
147      case GL_BOOL_VEC3:
148      case GL_FLOAT_MAT3:
149        return 3;
150      case GL_BOOL_VEC4:
151      case GL_FLOAT_VEC4:
152      case GL_INT_VEC4:
153      case GL_FLOAT_MAT4:
154        return 4;
155      default:
156        UNREACHABLE();
157    }
158
159    return 0;
160}
161
162int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
163{
164    ASSERT(allocationSize <= bitsSize);
165
166    unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
167
168    for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
169    {
170        if ((*bits & mask) == 0)
171        {
172            *bits |= mask;
173            return i;
174        }
175
176        mask <<= 1;
177    }
178
179    return -1;
180}
181
182GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment)
183{
184    ASSERT(alignment > 0 && isPow2(alignment));
185
186    GLsizei rawPitch = ComputePixelSize(format, type) * width;
187    return (rawPitch + alignment - 1) & ~(alignment - 1);
188}
189
190GLsizei ComputeCompressedPitch(GLsizei width, GLenum format)
191{
192    switch (format)
193    {
194      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
195      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
196        break;
197      default:
198        return 0;
199    }
200
201    ASSERT(width % 4 == 0);
202
203    return 8 * width / 4;
204}
205
206GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format)
207{
208    switch (format)
209    {
210      case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
211      case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
212        break;
213      default:
214        return 0;
215    }
216
217    return 8 * (GLsizei)ceil((float)width / 4.0f) * (GLsizei)ceil((float)height / 4.0f);
218}
219
220bool IsCompressed(GLenum format)
221{
222    if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
223       format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
224    {
225        return true;
226    }
227    else
228    {
229        return false;
230    }
231}
232
233// Returns the size, in bytes, of a single texel in an Image
234int ComputePixelSize(GLenum format, GLenum type)
235{
236    switch (type)
237    {
238      case GL_UNSIGNED_BYTE:
239        switch (format)
240        {
241          case GL_ALPHA:           return sizeof(unsigned char);
242          case GL_LUMINANCE:       return sizeof(unsigned char);
243          case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
244          case GL_RGB:             return sizeof(unsigned char) * 3;
245          case GL_RGBA:            return sizeof(unsigned char) * 4;
246          case GL_BGRA_EXT:        return sizeof(unsigned char) * 4;
247          default: UNREACHABLE();
248        }
249        break;
250      case GL_UNSIGNED_SHORT_4_4_4_4:
251      case GL_UNSIGNED_SHORT_5_5_5_1:
252      case GL_UNSIGNED_SHORT_5_6_5:
253        return sizeof(unsigned short);
254      case GL_FLOAT:
255        switch (format)
256        {
257          case GL_ALPHA:           return sizeof(float);
258          case GL_LUMINANCE:       return sizeof(float);
259          case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
260          case GL_RGB:             return sizeof(float) * 3;
261          case GL_RGBA:            return sizeof(float) * 4;
262          default: UNREACHABLE();
263        }
264        break;
265      case GL_HALF_FLOAT_OES:
266        switch (format)
267        {
268          case GL_ALPHA:           return sizeof(unsigned short);
269          case GL_LUMINANCE:       return sizeof(unsigned short);
270          case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
271          case GL_RGB:             return sizeof(unsigned short) * 3;
272          case GL_RGBA:            return sizeof(unsigned short) * 4;
273          default: UNREACHABLE();
274        }
275        break;
276      default: UNREACHABLE();
277    }
278
279    return 0;
280}
281
282bool IsCubemapTextureTarget(GLenum target)
283{
284    return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
285}
286
287bool IsTextureTarget(GLenum target)
288{
289    return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
290}
291
292// Verify that format/type are one of the combinations from table 3.4.
293bool CheckTextureFormatType(GLenum format, GLenum type)
294{
295    switch (type)
296    {
297      case GL_UNSIGNED_BYTE:
298        switch (format)
299        {
300          case GL_RGBA:
301          case GL_BGRA_EXT:
302          case GL_RGB:
303          case GL_ALPHA:
304          case GL_LUMINANCE:
305          case GL_LUMINANCE_ALPHA:
306            return true;
307
308          default:
309            return false;
310        }
311
312      case GL_FLOAT:
313      case GL_HALF_FLOAT_OES:
314        switch (format)
315        {
316          case GL_RGBA:
317          case GL_RGB:
318          case GL_ALPHA:
319          case GL_LUMINANCE:
320          case GL_LUMINANCE_ALPHA:
321            return true;
322
323          default:
324            return false;
325        }
326
327      case GL_UNSIGNED_SHORT_4_4_4_4:
328      case GL_UNSIGNED_SHORT_5_5_5_1:
329        return (format == GL_RGBA);
330
331      case GL_UNSIGNED_SHORT_5_6_5:
332        return (format == GL_RGB);
333
334      default:
335        return false;
336    }
337}
338
339bool IsColorRenderable(GLenum internalformat)
340{
341    switch (internalformat)
342    {
343      case GL_RGBA4:
344      case GL_RGB5_A1:
345      case GL_RGB565:
346      case GL_RGB8_OES:
347      case GL_RGBA8_OES:
348        return true;
349      case GL_DEPTH_COMPONENT16:
350      case GL_STENCIL_INDEX8:
351      case GL_DEPTH24_STENCIL8_OES:
352        return false;
353      default:
354        UNIMPLEMENTED();
355    }
356
357    return false;
358}
359
360bool IsDepthRenderable(GLenum internalformat)
361{
362    switch (internalformat)
363    {
364      case GL_DEPTH_COMPONENT16:
365      case GL_DEPTH24_STENCIL8_OES:
366        return true;
367      case GL_STENCIL_INDEX8:
368      case GL_RGBA4:
369      case GL_RGB5_A1:
370      case GL_RGB565:
371      case GL_RGB8_OES:
372      case GL_RGBA8_OES:
373        return false;
374      default:
375        UNIMPLEMENTED();
376    }
377
378    return false;
379}
380
381bool IsStencilRenderable(GLenum internalformat)
382{
383    switch (internalformat)
384    {
385      case GL_STENCIL_INDEX8:
386      case GL_DEPTH24_STENCIL8_OES:
387        return true;
388      case GL_RGBA4:
389      case GL_RGB5_A1:
390      case GL_RGB565:
391      case GL_RGB8_OES:
392      case GL_RGBA8_OES:
393      case GL_DEPTH_COMPONENT16:
394        return false;
395      default:
396        UNIMPLEMENTED();
397    }
398
399    return false;
400}
401
402}
403
404namespace es2dx
405{
406
407D3DCMPFUNC ConvertComparison(GLenum comparison)
408{
409    D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
410    switch (comparison)
411    {
412      case GL_NEVER:    d3dComp = D3DCMP_NEVER;        break;
413      case GL_ALWAYS:   d3dComp = D3DCMP_ALWAYS;       break;
414      case GL_LESS:     d3dComp = D3DCMP_LESS;         break;
415      case GL_LEQUAL:   d3dComp = D3DCMP_LESSEQUAL;    break;
416      case GL_EQUAL:    d3dComp = D3DCMP_EQUAL;        break;
417      case GL_GREATER:  d3dComp = D3DCMP_GREATER;      break;
418      case GL_GEQUAL:   d3dComp = D3DCMP_GREATEREQUAL; break;
419      case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL;     break;
420      default: UNREACHABLE();
421    }
422
423    return d3dComp;
424}
425
426D3DCOLOR ConvertColor(gl::Color color)
427{
428    return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
429                         gl::unorm<8>(color.green),
430                         gl::unorm<8>(color.blue),
431                         gl::unorm<8>(color.alpha));
432}
433
434D3DBLEND ConvertBlendFunc(GLenum blend)
435{
436    D3DBLEND d3dBlend = D3DBLEND_ZERO;
437
438    switch (blend)
439    {
440      case GL_ZERO:                     d3dBlend = D3DBLEND_ZERO;           break;
441      case GL_ONE:                      d3dBlend = D3DBLEND_ONE;            break;
442      case GL_SRC_COLOR:                d3dBlend = D3DBLEND_SRCCOLOR;       break;
443      case GL_ONE_MINUS_SRC_COLOR:      d3dBlend = D3DBLEND_INVSRCCOLOR;    break;
444      case GL_DST_COLOR:                d3dBlend = D3DBLEND_DESTCOLOR;      break;
445      case GL_ONE_MINUS_DST_COLOR:      d3dBlend = D3DBLEND_INVDESTCOLOR;   break;
446      case GL_SRC_ALPHA:                d3dBlend = D3DBLEND_SRCALPHA;       break;
447      case GL_ONE_MINUS_SRC_ALPHA:      d3dBlend = D3DBLEND_INVSRCALPHA;    break;
448      case GL_DST_ALPHA:                d3dBlend = D3DBLEND_DESTALPHA;      break;
449      case GL_ONE_MINUS_DST_ALPHA:      d3dBlend = D3DBLEND_INVDESTALPHA;   break;
450      case GL_CONSTANT_COLOR:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
451      case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
452      case GL_CONSTANT_ALPHA:           d3dBlend = D3DBLEND_BLENDFACTOR;    break;
453      case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
454      case GL_SRC_ALPHA_SATURATE:       d3dBlend = D3DBLEND_SRCALPHASAT;    break;
455      default: UNREACHABLE();
456    }
457
458    return d3dBlend;
459}
460
461D3DBLENDOP ConvertBlendOp(GLenum blendOp)
462{
463    D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
464
465    switch (blendOp)
466    {
467      case GL_FUNC_ADD:              d3dBlendOp = D3DBLENDOP_ADD;         break;
468      case GL_FUNC_SUBTRACT:         d3dBlendOp = D3DBLENDOP_SUBTRACT;    break;
469      case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
470      default: UNREACHABLE();
471    }
472
473    return d3dBlendOp;
474}
475
476D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
477{
478    D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
479
480    switch (stencilOp)
481    {
482      case GL_ZERO:      d3dStencilOp = D3DSTENCILOP_ZERO;    break;
483      case GL_KEEP:      d3dStencilOp = D3DSTENCILOP_KEEP;    break;
484      case GL_REPLACE:   d3dStencilOp = D3DSTENCILOP_REPLACE; break;
485      case GL_INCR:      d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
486      case GL_DECR:      d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
487      case GL_INVERT:    d3dStencilOp = D3DSTENCILOP_INVERT;  break;
488      case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR;    break;
489      case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR;    break;
490      default: UNREACHABLE();
491    }
492
493    return d3dStencilOp;
494}
495
496D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
497{
498    D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
499
500    switch (wrap)
501    {
502      case GL_REPEAT:            d3dWrap = D3DTADDRESS_WRAP;   break;
503      case GL_CLAMP_TO_EDGE:     d3dWrap = D3DTADDRESS_CLAMP;  break;
504      case GL_MIRRORED_REPEAT:   d3dWrap = D3DTADDRESS_MIRROR; break;
505      default: UNREACHABLE();
506    }
507
508    return d3dWrap;
509}
510
511D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
512{
513    D3DCULL cull = D3DCULL_CCW;
514    switch (cullFace)
515    {
516      case GL_FRONT:
517        cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
518        break;
519      case GL_BACK:
520        cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
521        break;
522      case GL_FRONT_AND_BACK:
523        cull = D3DCULL_NONE; // culling will be handled during draw
524        break;
525      default: UNREACHABLE();
526    }
527
528    return cull;
529}
530
531DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
532{
533    return (red   ? D3DCOLORWRITEENABLE_RED   : 0) |
534           (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
535           (blue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
536           (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
537}
538
539D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter)
540{
541    D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
542    switch (magFilter)
543    {
544      case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT;  break;
545      case GL_LINEAR:  d3dMagFilter = D3DTEXF_LINEAR; break;
546      default: UNREACHABLE();
547    }
548
549    return d3dMagFilter;
550}
551
552void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter)
553{
554    switch (minFilter)
555    {
556      case GL_NEAREST:
557        *d3dMinFilter = D3DTEXF_POINT;
558        *d3dMipFilter = D3DTEXF_NONE;
559        break;
560      case GL_LINEAR:
561        *d3dMinFilter = D3DTEXF_LINEAR;
562        *d3dMipFilter = D3DTEXF_NONE;
563        break;
564      case GL_NEAREST_MIPMAP_NEAREST:
565        *d3dMinFilter = D3DTEXF_POINT;
566        *d3dMipFilter = D3DTEXF_POINT;
567        break;
568      case GL_LINEAR_MIPMAP_NEAREST:
569        *d3dMinFilter = D3DTEXF_LINEAR;
570        *d3dMipFilter = D3DTEXF_POINT;
571        break;
572      case GL_NEAREST_MIPMAP_LINEAR:
573        *d3dMinFilter = D3DTEXF_POINT;
574        *d3dMipFilter = D3DTEXF_LINEAR;
575        break;
576      case GL_LINEAR_MIPMAP_LINEAR:
577        *d3dMinFilter = D3DTEXF_LINEAR;
578        *d3dMipFilter = D3DTEXF_LINEAR;
579        break;
580      default:
581        *d3dMinFilter = D3DTEXF_POINT;
582        *d3dMipFilter = D3DTEXF_NONE;
583        UNREACHABLE();
584    }
585}
586
587unsigned int GetStencilSize(D3DFORMAT stencilFormat)
588{
589    switch(stencilFormat)
590    {
591      case D3DFMT_D24FS8:
592      case D3DFMT_D24S8:
593        return 8;
594      case D3DFMT_D24X4S4:
595        return 4;
596      case D3DFMT_D15S1:
597        return 1;
598      case D3DFMT_D16_LOCKABLE:
599      case D3DFMT_D32:
600      case D3DFMT_D24X8:
601      case D3DFMT_D32F_LOCKABLE:
602      case D3DFMT_D16:
603        return 0;
604//      case D3DFMT_D32_LOCKABLE:  return 0;   // DirectX 9Ex only
605//      case D3DFMT_S8_LOCKABLE:   return 8;   // DirectX 9Ex only
606      default: UNREACHABLE();
607    }
608    return 0;
609}
610
611unsigned int GetAlphaSize(D3DFORMAT colorFormat)
612{
613    switch (colorFormat)
614    {
615      case D3DFMT_A16B16G16R16F:
616        return 16;
617      case D3DFMT_A32B32G32R32F:
618        return 32;
619      case D3DFMT_A2R10G10B10:
620        return 2;
621      case D3DFMT_A8R8G8B8:
622        return 8;
623      case D3DFMT_A1R5G5B5:
624        return 1;
625      case D3DFMT_X8R8G8B8:
626      case D3DFMT_R5G6B5:
627        return 0;
628      default: UNREACHABLE();
629    }
630    return 0;
631}
632
633unsigned int GetRedSize(D3DFORMAT colorFormat)
634{
635    switch (colorFormat)
636    {
637      case D3DFMT_A16B16G16R16F:
638        return 16;
639      case D3DFMT_A32B32G32R32F:
640        return 32;
641      case D3DFMT_A2R10G10B10:
642        return 10;
643      case D3DFMT_A8R8G8B8:
644      case D3DFMT_X8R8G8B8:
645        return 8;
646      case D3DFMT_A1R5G5B5:
647      case D3DFMT_R5G6B5:
648        return 5;
649      default: UNREACHABLE();
650    }
651    return 0;
652}
653
654unsigned int GetGreenSize(D3DFORMAT colorFormat)
655{
656    switch (colorFormat)
657    {
658      case D3DFMT_A16B16G16R16F:
659        return 16;
660      case D3DFMT_A32B32G32R32F:
661        return 32;
662      case D3DFMT_A2R10G10B10:
663        return 10;
664      case D3DFMT_A8R8G8B8:
665      case D3DFMT_X8R8G8B8:
666        return 8;
667      case D3DFMT_A1R5G5B5:
668        return 5;
669      case D3DFMT_R5G6B5:
670        return 6;
671      default: UNREACHABLE();
672    }
673    return 0;
674}
675
676unsigned int GetBlueSize(D3DFORMAT colorFormat)
677{
678    switch (colorFormat)
679    {
680      case D3DFMT_A16B16G16R16F:
681        return 16;
682      case D3DFMT_A32B32G32R32F:
683        return 32;
684      case D3DFMT_A2R10G10B10:
685        return 10;
686      case D3DFMT_A8R8G8B8:
687      case D3DFMT_X8R8G8B8:
688        return 8;
689      case D3DFMT_A1R5G5B5:
690      case D3DFMT_R5G6B5:
691        return 5;
692      default: UNREACHABLE();
693    }
694    return 0;
695}
696
697unsigned int GetDepthSize(D3DFORMAT depthFormat)
698{
699    switch (depthFormat)
700    {
701      case D3DFMT_D16_LOCKABLE:  return 16;
702      case D3DFMT_D32:           return 32;
703      case D3DFMT_D15S1:         return 15;
704      case D3DFMT_D24S8:         return 24;
705      case D3DFMT_D24X8:         return 24;
706      case D3DFMT_D24X4S4:       return 24;
707      case D3DFMT_D16:           return 16;
708      case D3DFMT_D32F_LOCKABLE: return 32;
709      case D3DFMT_D24FS8:        return 24;
710    //case D3DFMT_D32_LOCKABLE:  return 32;   // D3D9Ex only
711    //case D3DFMT_S8_LOCKABLE:   return 0;    // D3D9Ex only
712      default:
713        UNREACHABLE();
714    }
715    return 0;
716}
717
718bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
719                          D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
720{
721    switch (primitiveType)
722    {
723      case GL_POINTS:
724        *d3dPrimitiveType = D3DPT_POINTLIST;
725        *d3dPrimitiveCount = elementCount;
726        break;
727      case GL_LINES:
728        *d3dPrimitiveType = D3DPT_LINELIST;
729        *d3dPrimitiveCount = elementCount / 2;
730        break;
731      case GL_LINE_LOOP:
732        *d3dPrimitiveType = D3DPT_LINESTRIP;
733        *d3dPrimitiveCount = elementCount - 1;   // D3D doesn't support line loops, so we draw the last line separately
734        break;
735      case GL_LINE_STRIP:
736        *d3dPrimitiveType = D3DPT_LINESTRIP;
737        *d3dPrimitiveCount = elementCount - 1;
738        break;
739      case GL_TRIANGLES:
740        *d3dPrimitiveType = D3DPT_TRIANGLELIST;
741        *d3dPrimitiveCount = elementCount / 3;
742        break;
743      case GL_TRIANGLE_STRIP:
744        *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
745        *d3dPrimitiveCount = elementCount - 2;
746        break;
747      case GL_TRIANGLE_FAN:
748        *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
749        *d3dPrimitiveCount = elementCount - 2;
750        break;
751      default:
752        return false;
753    }
754
755    return true;
756}
757
758D3DFORMAT ConvertRenderbufferFormat(GLenum format)
759{
760    switch (format)
761    {
762      case GL_RGBA4:
763      case GL_RGB5_A1:
764      case GL_RGBA8_OES:            return D3DFMT_A8R8G8B8;
765      case GL_RGB565:               return D3DFMT_R5G6B5;
766      case GL_RGB8_OES:             return D3DFMT_X8R8G8B8;
767      case GL_DEPTH_COMPONENT16:
768      case GL_STENCIL_INDEX8:
769      case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
770      default: UNREACHABLE();       return D3DFMT_A8R8G8B8;
771    }
772}
773
774GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
775{
776    if (type == D3DMULTISAMPLE_NONMASKABLE)
777        return 0;
778    else
779        return type;
780}
781
782D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
783{
784    if (samples <= 1)
785        return D3DMULTISAMPLE_NONE;
786    else
787        return (D3DMULTISAMPLE_TYPE)samples;
788}
789
790}
791
792namespace dx2es
793{
794
795GLenum ConvertBackBufferFormat(D3DFORMAT format)
796{
797    switch (format)
798    {
799      case D3DFMT_A4R4G4B4: return GL_RGBA4;
800      case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
801      case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
802      case D3DFMT_R5G6B5:   return GL_RGB565;
803      case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
804      default:
805        UNREACHABLE();
806    }
807
808    return GL_RGBA4;
809}
810
811GLenum ConvertDepthStencilFormat(D3DFORMAT format)
812{
813    switch (format)
814    {
815      case D3DFMT_D16:
816      case D3DFMT_D24X8:
817        return GL_DEPTH_COMPONENT16;
818      case D3DFMT_D24S8:
819        return GL_DEPTH24_STENCIL8_OES;
820      default:
821        UNREACHABLE();
822    }
823
824    return GL_DEPTH24_STENCIL8_OES;
825}
826
827}
828