summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2/utilities.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/utilities.cpp')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/utilities.cpp1218
1 files changed, 1218 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp
new file mode 100644
index 0000000000..a3eb27d392
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp
@@ -0,0 +1,1218 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// utilities.cpp: Conversion functions and other utility routines.
+
+#include "libGLESv2/utilities.h"
+
+#include <limits>
+#include <stdio.h>
+#include <windows.h>
+
+#include "common/debug.h"
+
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/Context.h"
+
+namespace gl
+{
+
+// This is how much data the application expects for a uniform
+int UniformExternalComponentCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ return 2;
+ case GL_INT_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC3:
+ return 3;
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_FLOAT_MAT2:
+ return 4;
+ case GL_FLOAT_MAT3:
+ return 9;
+ case GL_FLOAT_MAT4:
+ return 16;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+// This is how much data we actually store for a uniform
+int UniformInternalComponentCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BOOL:
+ case GL_INT:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_INT_VEC2:
+ return 2;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ return 3;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ return 4;
+ case GL_FLOAT_MAT2:
+ return 8;
+ case GL_FLOAT_MAT3:
+ return 12;
+ case GL_FLOAT_MAT4:
+ return 16;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+GLenum UniformComponentType(GLenum type)
+{
+ switch(type)
+ {
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ return GL_BOOL;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT4:
+ return GL_FLOAT;
+ case GL_INT:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ return GL_INT;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_NONE;
+}
+
+size_t UniformComponentSize(GLenum type)
+{
+ switch(type)
+ {
+ case GL_BOOL: return sizeof(GLint);
+ case GL_FLOAT: return sizeof(GLfloat);
+ case GL_INT: return sizeof(GLint);
+ default: UNREACHABLE();
+ }
+
+ return 0;
+}
+
+size_t UniformInternalSize(GLenum type)
+{
+ return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type);
+}
+
+size_t UniformExternalSize(GLenum type)
+{
+ return UniformComponentSize(UniformComponentType(type)) * UniformExternalComponentCount(type);
+}
+
+int VariableRowCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_NONE:
+ return 0;
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ return 1;
+ case GL_FLOAT_MAT2:
+ return 2;
+ case GL_FLOAT_MAT3:
+ return 3;
+ case GL_FLOAT_MAT4:
+ return 4;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+int VariableColumnCount(GLenum type)
+{
+ switch (type)
+ {
+ case GL_NONE:
+ return 0;
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_FLOAT_MAT2:
+ return 2;
+ case GL_INT_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC3:
+ case GL_FLOAT_MAT3:
+ return 3;
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_FLOAT_MAT4:
+ return 4;
+ default:
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
+int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
+{
+ ASSERT(allocationSize <= bitsSize);
+
+ unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
+
+ for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
+ {
+ if ((*bits & mask) == 0)
+ {
+ *bits |= mask;
+ return i;
+ }
+
+ mask <<= 1;
+ }
+
+ return -1;
+}
+
+GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment)
+{
+ ASSERT(alignment > 0 && isPow2(alignment));
+
+ GLsizei rawPitch = ComputePixelSize(internalformat) * width;
+ return (rawPitch + alignment - 1) & ~(alignment - 1);
+}
+
+GLsizei ComputeCompressedPitch(GLsizei width, GLenum internalformat)
+{
+ return ComputeCompressedSize(width, 1, internalformat);
+}
+
+GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return 8 * ((width + 3) / 4) * ((height + 3) / 4);
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return 16 * ((width + 3) / 4) * ((height + 3) / 4);
+ default:
+ return 0;
+ }
+}
+
+bool IsCompressed(GLenum format)
+{
+ if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
+ format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool IsDepthTexture(GLenum format)
+{
+ if (format == GL_DEPTH_COMPONENT ||
+ format == GL_DEPTH_STENCIL_OES ||
+ format == GL_DEPTH_COMPONENT16 ||
+ format == GL_DEPTH_COMPONENT32_OES ||
+ format == GL_DEPTH24_STENCIL8_OES)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool IsStencilTexture(GLenum format)
+{
+ if (format == GL_DEPTH_STENCIL_OES ||
+ format == GL_DEPTH24_STENCIL8_OES)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// Returns the size, in bytes, of a single texel in an Image
+int ComputePixelSize(GLint internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_ALPHA8_EXT: return sizeof(unsigned char);
+ case GL_LUMINANCE8_EXT: return sizeof(unsigned char);
+ case GL_ALPHA32F_EXT: return sizeof(float);
+ case GL_LUMINANCE32F_EXT: return sizeof(float);
+ case GL_ALPHA16F_EXT: return sizeof(unsigned short);
+ case GL_LUMINANCE16F_EXT: return sizeof(unsigned short);
+ case GL_LUMINANCE8_ALPHA8_EXT: return sizeof(unsigned char) * 2;
+ case GL_LUMINANCE_ALPHA32F_EXT: return sizeof(float) * 2;
+ case GL_LUMINANCE_ALPHA16F_EXT: return sizeof(unsigned short) * 2;
+ case GL_RGB8_OES: return sizeof(unsigned char) * 3;
+ case GL_RGB565: return sizeof(unsigned short);
+ case GL_RGB32F_EXT: return sizeof(float) * 3;
+ case GL_RGB16F_EXT: return sizeof(unsigned short) * 3;
+ case GL_RGBA8_OES: return sizeof(unsigned char) * 4;
+ case GL_RGBA4: return sizeof(unsigned short);
+ case GL_RGB5_A1: return sizeof(unsigned short);
+ case GL_RGBA32F_EXT: return sizeof(float) * 4;
+ case GL_RGBA16F_EXT: return sizeof(unsigned short) * 4;
+ case GL_BGRA8_EXT: return sizeof(unsigned char) * 4;
+ case GL_BGRA4_ANGLEX: return sizeof(unsigned short);
+ case GL_BGR5_A1_ANGLEX: return sizeof(unsigned short);
+ default: UNREACHABLE();
+ }
+
+ return 0;
+}
+
+bool IsCubemapTextureTarget(GLenum target)
+{
+ return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+}
+
+bool IsInternalTextureTarget(GLenum target)
+{
+ return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
+}
+
+GLint ConvertSizedInternalFormat(GLenum format, GLenum type)
+{
+ switch (format)
+ {
+ case GL_ALPHA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: return GL_ALPHA8_EXT;
+ case GL_FLOAT: return GL_ALPHA32F_EXT;
+ case GL_HALF_FLOAT_OES: return GL_ALPHA16F_EXT;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ case GL_LUMINANCE:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_EXT;
+ case GL_FLOAT: return GL_LUMINANCE32F_EXT;
+ case GL_HALF_FLOAT_OES: return GL_LUMINANCE16F_EXT;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_ALPHA8_EXT;
+ case GL_FLOAT: return GL_LUMINANCE_ALPHA32F_EXT;
+ case GL_HALF_FLOAT_OES: return GL_LUMINANCE_ALPHA16F_EXT;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: return GL_RGB8_OES;
+ case GL_UNSIGNED_SHORT_5_6_5: return GL_RGB565;
+ case GL_FLOAT: return GL_RGB32F_EXT;
+ case GL_HALF_FLOAT_OES: return GL_RGB16F_EXT;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: return GL_RGBA8_OES;
+ case GL_UNSIGNED_SHORT_4_4_4_4: return GL_RGBA4;
+ case GL_UNSIGNED_SHORT_5_5_5_1: return GL_RGB5_A1;
+ case GL_FLOAT: return GL_RGBA32F_EXT;
+ case GL_HALF_FLOAT_OES: return GL_RGBA16F_EXT;
+ break;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: return GL_BGRA8_EXT;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return GL_BGRA4_ANGLEX;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return GL_BGR5_A1_ANGLEX;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return format;
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT: return GL_DEPTH_COMPONENT16;
+ case GL_UNSIGNED_INT: return GL_DEPTH_COMPONENT32_OES;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ case GL_DEPTH_STENCIL_OES:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8_OES: return GL_DEPTH24_STENCIL8_OES;
+ default: UNIMPLEMENTED();
+ }
+ break;
+ default:
+ UNIMPLEMENTED();
+ }
+
+ return GL_NONE;
+}
+
+GLenum ExtractFormat(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGB565: return GL_RGB;
+ case GL_RGBA4: return GL_RGBA;
+ case GL_RGB5_A1: return GL_RGBA;
+ case GL_RGB8_OES: return GL_RGB;
+ case GL_RGBA8_OES: return GL_RGBA;
+ case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA;
+ case GL_LUMINANCE8_EXT: return GL_LUMINANCE;
+ case GL_ALPHA8_EXT: return GL_ALPHA;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+ case GL_RGBA32F_EXT: return GL_RGBA;
+ case GL_RGB32F_EXT: return GL_RGB;
+ case GL_ALPHA32F_EXT: return GL_ALPHA;
+ case GL_LUMINANCE32F_EXT: return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA32F_EXT: return GL_LUMINANCE_ALPHA;
+ case GL_RGBA16F_EXT: return GL_RGBA;
+ case GL_RGB16F_EXT: return GL_RGB;
+ case GL_ALPHA16F_EXT: return GL_ALPHA;
+ case GL_LUMINANCE16F_EXT: return GL_LUMINANCE;
+ case GL_LUMINANCE_ALPHA16F_EXT: return GL_LUMINANCE_ALPHA;
+ case GL_BGRA8_EXT: return GL_BGRA_EXT;
+ case GL_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT;
+ case GL_DEPTH_COMPONENT32_OES: return GL_DEPTH_COMPONENT;
+ case GL_DEPTH24_STENCIL8_OES: return GL_DEPTH_STENCIL_OES;
+ default: return GL_NONE; // Unsupported
+ }
+}
+
+GLenum ExtractType(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5;
+ case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4;
+ case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1;
+ case GL_RGB8_OES: return GL_UNSIGNED_BYTE;
+ case GL_RGBA8_OES: return GL_UNSIGNED_BYTE;
+ case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
+ case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE;
+ case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
+ case GL_RGBA32F_EXT: return GL_FLOAT;
+ case GL_RGB32F_EXT: return GL_FLOAT;
+ case GL_ALPHA32F_EXT: return GL_FLOAT;
+ case GL_LUMINANCE32F_EXT: return GL_FLOAT;
+ case GL_LUMINANCE_ALPHA32F_EXT: return GL_FLOAT;
+ case GL_RGBA16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_RGB16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_LUMINANCE16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_LUMINANCE_ALPHA16F_EXT: return GL_HALF_FLOAT_OES;
+ case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE;
+ case GL_DEPTH_COMPONENT16: return GL_UNSIGNED_SHORT;
+ case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
+ case GL_DEPTH24_STENCIL8_OES: return GL_UNSIGNED_INT_24_8_OES;
+ default: return GL_NONE; // Unsupported
+ }
+}
+
+bool IsColorRenderable(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB565:
+ case GL_RGB8_OES:
+ case GL_RGBA8_OES:
+ return true;
+ case GL_DEPTH_COMPONENT16:
+ case GL_STENCIL_INDEX8:
+ case GL_DEPTH24_STENCIL8_OES:
+ return false;
+ default:
+ UNIMPLEMENTED();
+ }
+
+ return false;
+}
+
+bool IsDepthRenderable(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH24_STENCIL8_OES:
+ return true;
+ case GL_STENCIL_INDEX8:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB565:
+ case GL_RGB8_OES:
+ case GL_RGBA8_OES:
+ return false;
+ default:
+ UNIMPLEMENTED();
+ }
+
+ return false;
+}
+
+bool IsStencilRenderable(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_STENCIL_INDEX8:
+ case GL_DEPTH24_STENCIL8_OES:
+ return true;
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB565:
+ case GL_RGB8_OES:
+ case GL_RGBA8_OES:
+ case GL_DEPTH_COMPONENT16:
+ return false;
+ default:
+ UNIMPLEMENTED();
+ }
+
+ return false;
+}
+
+bool IsFloat32Format(GLint internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGBA32F_EXT:
+ case GL_RGB32F_EXT:
+ case GL_ALPHA32F_EXT:
+ case GL_LUMINANCE32F_EXT:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool IsFloat16Format(GLint internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGBA16F_EXT:
+ case GL_RGB16F_EXT:
+ case GL_ALPHA16F_EXT:
+ case GL_LUMINANCE16F_EXT:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+}
+
+namespace es2dx
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison)
+{
+ D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
+ switch (comparison)
+ {
+ case GL_NEVER: d3dComp = D3DCMP_NEVER; break;
+ case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break;
+ case GL_LESS: d3dComp = D3DCMP_LESS; break;
+ case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break;
+ case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break;
+ case GL_GREATER: d3dComp = D3DCMP_GREATER; break;
+ case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break;
+ case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dComp;
+}
+
+D3DCOLOR ConvertColor(gl::Color color)
+{
+ return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
+ gl::unorm<8>(color.green),
+ gl::unorm<8>(color.blue),
+ gl::unorm<8>(color.alpha));
+}
+
+D3DBLEND ConvertBlendFunc(GLenum blend)
+{
+ D3DBLEND d3dBlend = D3DBLEND_ZERO;
+
+ switch (blend)
+ {
+ case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break;
+ case GL_ONE: d3dBlend = D3DBLEND_ONE; break;
+ case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break;
+ case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break;
+ case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break;
+ case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break;
+ case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break;
+ case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break;
+ case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break;
+ case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break;
+ case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+ case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+ case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dBlend;
+}
+
+D3DBLENDOP ConvertBlendOp(GLenum blendOp)
+{
+ D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
+
+ switch (blendOp)
+ {
+ case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break;
+ case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break;
+ case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dBlendOp;
+}
+
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
+{
+ D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
+
+ switch (stencilOp)
+ {
+ case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break;
+ case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break;
+ case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break;
+ case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
+ case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
+ case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break;
+ case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break;
+ case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dStencilOp;
+}
+
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
+{
+ D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
+
+ switch (wrap)
+ {
+ case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break;
+ case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break;
+ case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dWrap;
+}
+
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
+{
+ D3DCULL cull = D3DCULL_CCW;
+ switch (cullFace)
+ {
+ case GL_FRONT:
+ cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+ break;
+ case GL_BACK:
+ cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+ break;
+ case GL_FRONT_AND_BACK:
+ cull = D3DCULL_NONE; // culling will be handled during draw
+ break;
+ default: UNREACHABLE();
+ }
+
+ return cull;
+}
+
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
+{
+ D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
+
+ switch (cubeFace)
+ {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ face = D3DCUBEMAP_FACE_POSITIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ face = D3DCUBEMAP_FACE_NEGATIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ face = D3DCUBEMAP_FACE_POSITIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ face = D3DCUBEMAP_FACE_POSITIVE_Z;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Z;
+ break;
+ default: UNREACHABLE();
+ }
+
+ return face;
+}
+
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ return (red ? D3DCOLORWRITEENABLE_RED : 0) |
+ (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
+ (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
+ (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
+}
+
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
+{
+ if (maxAnisotropy > 1.0f)
+ {
+ return D3DTEXF_ANISOTROPIC;
+ }
+
+ D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
+ switch (magFilter)
+ {
+ case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
+ case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dMagFilter;
+}
+
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
+{
+ switch (minFilter)
+ {
+ case GL_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ default:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ UNREACHABLE();
+ }
+
+ if (maxAnisotropy > 1.0f)
+ {
+ *d3dMinFilter = D3DTEXF_ANISOTROPIC;
+ }
+}
+
+bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount,
+ D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount)
+{
+ switch (primitiveType)
+ {
+ case GL_POINTS:
+ *d3dPrimitiveType = D3DPT_POINTLIST;
+ *d3dPrimitiveCount = elementCount;
+ break;
+ case GL_LINES:
+ *d3dPrimitiveType = D3DPT_LINELIST;
+ *d3dPrimitiveCount = elementCount / 2;
+ break;
+ case GL_LINE_LOOP:
+ *d3dPrimitiveType = D3DPT_LINESTRIP;
+ *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately
+ break;
+ case GL_LINE_STRIP:
+ *d3dPrimitiveType = D3DPT_LINESTRIP;
+ *d3dPrimitiveCount = elementCount - 1;
+ break;
+ case GL_TRIANGLES:
+ *d3dPrimitiveType = D3DPT_TRIANGLELIST;
+ *d3dPrimitiveCount = elementCount / 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ *d3dPrimitiveType = D3DPT_TRIANGLESTRIP;
+ *d3dPrimitiveCount = elementCount - 2;
+ break;
+ case GL_TRIANGLE_FAN:
+ *d3dPrimitiveType = D3DPT_TRIANGLEFAN;
+ *d3dPrimitiveCount = elementCount - 2;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+D3DFORMAT ConvertRenderbufferFormat(GLenum format)
+{
+ switch (format)
+ {
+ case GL_NONE: return D3DFMT_NULL;
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
+ case GL_RGB565: return D3DFMT_R5G6B5;
+ case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
+ case GL_DEPTH_COMPONENT16:
+ case GL_STENCIL_INDEX8:
+ case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
+ default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
+ }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
+{
+ if (samples <= 1)
+ return D3DMULTISAMPLE_NONE;
+ else
+ return (D3DMULTISAMPLE_TYPE)samples;
+}
+
+}
+
+namespace dx2es
+{
+
+unsigned int GetStencilSize(D3DFORMAT stencilFormat)
+{
+ if (stencilFormat == D3DFMT_INTZ)
+ {
+ return 8;
+ }
+ switch(stencilFormat)
+ {
+ case D3DFMT_D24FS8:
+ case D3DFMT_D24S8:
+ return 8;
+ case D3DFMT_D24X4S4:
+ return 4;
+ case D3DFMT_D15S1:
+ return 1;
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D32:
+ case D3DFMT_D24X8:
+ case D3DFMT_D32F_LOCKABLE:
+ case D3DFMT_D16:
+ return 0;
+ //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
+ //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
+ default:
+ return 0;
+ }
+}
+
+unsigned int GetAlphaSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A16B16G16R16F:
+ return 16;
+ case D3DFMT_A32B32G32R32F:
+ return 32;
+ case D3DFMT_A2R10G10B10:
+ return 2;
+ case D3DFMT_A8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ return 1;
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_R5G6B5:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+unsigned int GetRedSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A16B16G16R16F:
+ return 16;
+ case D3DFMT_A32B32G32R32F:
+ return 32;
+ case D3DFMT_A2R10G10B10:
+ return 10;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_R5G6B5:
+ return 5;
+ default:
+ return 0;
+ }
+}
+
+unsigned int GetGreenSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A16B16G16R16F:
+ return 16;
+ case D3DFMT_A32B32G32R32F:
+ return 32;
+ case D3DFMT_A2R10G10B10:
+ return 10;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ return 5;
+ case D3DFMT_R5G6B5:
+ return 6;
+ default:
+ return 0;
+ }
+}
+
+unsigned int GetBlueSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A16B16G16R16F:
+ return 16;
+ case D3DFMT_A32B32G32R32F:
+ return 32;
+ case D3DFMT_A2R10G10B10:
+ return 10;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_R5G6B5:
+ return 5;
+ default:
+ return 0;
+ }
+}
+
+unsigned int GetDepthSize(D3DFORMAT depthFormat)
+{
+ if (depthFormat == D3DFMT_INTZ)
+ {
+ return 24;
+ }
+ switch (depthFormat)
+ {
+ case D3DFMT_D16_LOCKABLE: return 16;
+ case D3DFMT_D32: return 32;
+ case D3DFMT_D15S1: return 15;
+ case D3DFMT_D24S8: return 24;
+ case D3DFMT_D24X8: return 24;
+ case D3DFMT_D24X4S4: return 24;
+ case D3DFMT_D16: return 16;
+ case D3DFMT_D32F_LOCKABLE: return 32;
+ case D3DFMT_D24FS8: return 24;
+ //case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only
+ //case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only
+ default: return 0;
+ }
+}
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
+{
+ if (type == D3DMULTISAMPLE_NONMASKABLE)
+ return 0;
+ else
+ return type;
+}
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
+{
+ switch (d3dformat)
+ {
+ case D3DFMT_L8:
+ return (format == GL_LUMINANCE);
+ case D3DFMT_A8L8:
+ return (format == GL_LUMINANCE_ALPHA);
+ case D3DFMT_DXT1:
+ return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
+ case D3DFMT_DXT3:
+ return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+ case D3DFMT_DXT5:
+ return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ return (format == GL_RGBA || format == GL_BGRA_EXT);
+ case D3DFMT_X8R8G8B8:
+ return (format == GL_RGB);
+ default:
+ if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format))
+ return true;
+ return false;
+ }
+}
+
+bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type)
+{
+ switch (d3dformat)
+ {
+ case D3DFMT_A8R8G8B8:
+ *type = GL_UNSIGNED_BYTE;
+ *format = GL_BGRA_EXT;
+ break;
+ case D3DFMT_X8R8G8B8:
+ *type = GL_UNSIGNED_BYTE;
+ *format = GL_RGB;
+ break;
+ case D3DFMT_R5G6B5:
+ *type = GL_UNSIGNED_SHORT_5_6_5;
+ *format = GL_RGB;
+ break;
+ case D3DFMT_A16B16G16R16F:
+ *type = GL_HALF_FLOAT_OES;
+ *format = GL_RGBA;
+ break;
+ case D3DFMT_A32B32G32R32F:
+ *type = GL_FLOAT;
+ *format = GL_RGBA;
+ break;
+ case D3DFMT_A4R4G4B4:
+ *type = GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT;
+ *format = GL_BGRA_EXT;
+ break;
+ case D3DFMT_A1R5G5B5:
+ *type = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
+ *format = GL_BGRA_EXT;
+ break;
+ default:
+ *type = GL_NONE;
+ *format = GL_NONE;
+ return false;
+ }
+ return true;
+}
+
+GLenum ConvertBackBufferFormat(D3DFORMAT format)
+{
+ switch (format)
+ {
+ case D3DFMT_A4R4G4B4: return GL_RGBA4;
+ case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
+ case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
+ case D3DFMT_R5G6B5: return GL_RGB565;
+ case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_RGBA4;
+}
+
+GLenum ConvertDepthStencilFormat(D3DFORMAT format)
+{
+ if (format == D3DFMT_INTZ)
+ {
+ return GL_DEPTH24_STENCIL8_OES;
+ }
+ switch (format)
+ {
+ case D3DFMT_D16:
+ case D3DFMT_D24X8:
+ return GL_DEPTH_COMPONENT16;
+ case D3DFMT_D24S8:
+ return GL_DEPTH24_STENCIL8_OES;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_DEPTH24_STENCIL8_OES;
+}
+
+}
+
+namespace dx
+{
+
+bool IsCompressedFormat(D3DFORMAT surfaceFormat)
+{
+ switch(surfaceFormat)
+ {
+ case D3DFMT_DXT1:
+ case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ return true;
+ default:
+ return false;
+ }
+}
+
+size_t ComputeRowSize(D3DFORMAT format, unsigned int width)
+{
+ if (format == D3DFMT_INTZ)
+ {
+ return 4 * width;
+ }
+ switch (format)
+ {
+ case D3DFMT_L8:
+ return 1 * width;
+ case D3DFMT_A8L8:
+ return 2 * width;
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ return 4 * width;
+ case D3DFMT_A16B16G16R16F:
+ return 8 * width;
+ case D3DFMT_A32B32G32R32F:
+ return 16 * width;
+ case D3DFMT_DXT1:
+ return 8 * ((width + 3) / 4);
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT5:
+ return 16 * ((width + 3) / 4);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+}
+
+std::string getTempPath()
+{
+ char path[MAX_PATH];
+ DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
+ if (pathLen == 0)
+ {
+ UNREACHABLE();
+ return std::string();
+ }
+
+ UINT unique = GetTempFileNameA(path, "sh", 0, path);
+ if (unique == 0)
+ {
+ UNREACHABLE();
+ return std::string();
+ }
+
+ return path;
+}
+
+void writeFile(const char* path, const void* content, size_t size)
+{
+ FILE* file = fopen(path, "w");
+ if (!file)
+ {
+ UNREACHABLE();
+ return;
+ }
+
+ fwrite(content, sizeof(char), size, file);
+ fclose(file);
+}