132e97315e2a55557ad7c372239e0823a81243221zmo@google.com// 232e97315e2a55557ad7c372239e0823a81243221zmo@google.com// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. 332e97315e2a55557ad7c372239e0823a81243221zmo@google.com// Use of this source code is governed by a BSD-style license that can be 432e97315e2a55557ad7c372239e0823a81243221zmo@google.com// found in the LICENSE file. 532e97315e2a55557ad7c372239e0823a81243221zmo@google.com// 632e97315e2a55557ad7c372239e0823a81243221zmo@google.com 7183bde5527317fa2208401e5e6b803ef51a0fdcbJamie Madill#include "angle_gl.h" 817732823f9c21bdba9cc51ffaceb545ce3857a8cGeoff Lang#include "compiler/translator/BuiltInFunctionEmulator.h" 917732823f9c21bdba9cc51ffaceb545ce3857a8cGeoff Lang#include "compiler/translator/SymbolTable.h" 1032e97315e2a55557ad7c372239e0823a81243221zmo@google.com 1132e97315e2a55557ad7c372239e0823a81243221zmo@google.comnamespace { 1232e97315e2a55557ad7c372239e0823a81243221zmo@google.com 13a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com// we use macros here instead of function definitions to work around more GLSL 14a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are 15a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com// problematic because if the argument has side-effects they will be repeatedly 16a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com// evaluated. This is unlikely to show up in real shaders, but is something to 17a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com// consider. 18a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.comconst char* kFunctionEmulationVertexSource[] = { 19a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for cos(float)", 20a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for cos(vec2)", 21a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for cos(vec3)", 22a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for cos(vec4)", 23a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 24a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", 25a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for distance(vec2, vec2)", 26a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for distance(vec3, vec3)", 27a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for distance(vec4, vec4)", 28a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 29a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#define webgl_dot_emu(x, y) ((x) * (y))", 30a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for dot(vec2, vec2)", 31a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for dot(vec3, vec3)", 32a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for dot(vec4, vec4)", 33a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 34a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", 35a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for length(vec2)", 36a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for length(vec3)", 37a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for length(vec4)", 38a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 39a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", 40a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for normalize(vec2)", 41a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for normalize(vec3)", 42a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for normalize(vec4)", 43a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 44a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", 45a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for reflect(vec2, vec2)", 46a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for reflect(vec3, vec3)", 47a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for reflect(vec4, vec4)" 48a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com}; 49a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 50a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.comconst char* kFunctionEmulationFragmentSource[] = { 51a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }", 52a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }", 53a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }", 54a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }", 55a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 5657442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", 57a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for distance(vec2, vec2)", 58a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for distance(vec3, vec3)", 59a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for distance(vec4, vec4)", 60a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 6157442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com "#define webgl_dot_emu(x, y) ((x) * (y))", 62a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for dot(vec2, vec2)", 63a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for dot(vec3, vec3)", 64a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for dot(vec4, vec4)", 65a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 6657442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", 67a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for length(vec2)", 68a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for length(vec3)", 69a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for length(vec4)", 70a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 7157442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", 72a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for normalize(vec2)", 73a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for normalize(vec3)", 74a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for normalize(vec4)", 75a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 7657442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", 77a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for reflect(vec2, vec2)", 78a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for reflect(vec3, vec3)", 79a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com "#error no emulation for reflect(vec4, vec4)" 8032e97315e2a55557ad7c372239e0823a81243221zmo@google.com}; 8132e97315e2a55557ad7c372239e0823a81243221zmo@google.com 82f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.comconst bool kFunctionEmulationVertexMask[] = { 83a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com#if defined(__APPLE__) 84a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com // Work around ATI driver bugs in Mac. 85a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionCos1 86a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionCos2 87a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionCos3 88a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionCos4 89a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com true, // TFunctionDistance1_1 90a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance2_2 91a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance3_3 92a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance4_4 93a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com true, // TFunctionDot1_1 94a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot2_2 95a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot3_3 96a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot4_4 97a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com true, // TFunctionLength1 98a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength2 99a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength3 100a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength4 101a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com true, // TFunctionNormalize1 102a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize2 103a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize3 104a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize4 105a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com true, // TFunctionReflect1_1 106a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect2_2 107a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect3_3 108a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect4_4 109a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com#else 110a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com // Work around D3D driver bug in Win. 111f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos1 112f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos2 113f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos3 114f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos4 115a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance1_1 116a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance2_2 117a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance3_3 118a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance4_4 119a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot1_1 120a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot2_2 121a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot3_3 122a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot4_4 123a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength1 124a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength2 125a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength3 126a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength4 127a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize1 128a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize2 129a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize3 130a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize4 131a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect1_1 132a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect2_2 133a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect3_3 134a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect4_4 135a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com#endif 136f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false // TFunctionUnknown 137f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com}; 138f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com 139f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.comconst bool kFunctionEmulationFragmentMask[] = { 140f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com#if defined(__APPLE__) 14157442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com // Work around ATI driver bugs in Mac. 142f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com true, // TFunctionCos1 143f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com true, // TFunctionCos2 144f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com true, // TFunctionCos3 145f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com true, // TFunctionCos4 14657442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com true, // TFunctionDistance1_1 14757442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionDistance2_2 14857442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionDistance3_3 14957442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionDistance4_4 15057442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com true, // TFunctionDot1_1 15157442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionDot2_2 15257442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionDot3_3 15357442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionDot4_4 15457442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com true, // TFunctionLength1 15557442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionLength2 15657442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionLength3 15757442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionLength4 15857442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com true, // TFunctionNormalize1 15957442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionNormalize2 16057442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionNormalize3 16157442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionNormalize4 16257442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com true, // TFunctionReflect1_1 16357442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionReflect2_2 16457442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionReflect3_3 16557442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com false, // TFunctionReflect4_4 166f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com#else 16757442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com // Work around D3D driver bug in Win. 168f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos1 169f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos2 170f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos3 171f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false, // TFunctionCos4 172a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance1_1 173a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance2_2 174a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance3_3 175a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDistance4_4 176a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot1_1 177a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot2_2 178a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot3_3 179a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionDot4_4 180a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength1 181a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength2 182a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength3 183a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionLength4 184a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize1 185a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize2 186a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize3 187a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionNormalize4 188a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect1_1 189a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect2_2 190a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect3_3 191a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com false, // TFunctionReflect4_4 19257442b1107c1ed347b5901c8d9b487ac409d90dczmo@google.com#endif 193f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com false // TFunctionUnknown 194f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com}; 195f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com 19632e97315e2a55557ad7c372239e0823a81243221zmo@google.comclass BuiltInFunctionEmulationMarker : public TIntermTraverser { 19732e97315e2a55557ad7c372239e0823a81243221zmo@google.compublic: 19832e97315e2a55557ad7c372239e0823a81243221zmo@google.com BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator) 19932e97315e2a55557ad7c372239e0823a81243221zmo@google.com : mEmulator(emulator) 20032e97315e2a55557ad7c372239e0823a81243221zmo@google.com { 20132e97315e2a55557ad7c372239e0823a81243221zmo@google.com } 20232e97315e2a55557ad7c372239e0823a81243221zmo@google.com 20332e97315e2a55557ad7c372239e0823a81243221zmo@google.com virtual bool visitUnary(Visit visit, TIntermUnary* node) 20432e97315e2a55557ad7c372239e0823a81243221zmo@google.com { 20532e97315e2a55557ad7c372239e0823a81243221zmo@google.com if (visit == PreVisit) { 20632e97315e2a55557ad7c372239e0823a81243221zmo@google.com bool needToEmulate = mEmulator.SetFunctionCalled( 20732e97315e2a55557ad7c372239e0823a81243221zmo@google.com node->getOp(), node->getOperand()->getType()); 20832e97315e2a55557ad7c372239e0823a81243221zmo@google.com if (needToEmulate) 20932e97315e2a55557ad7c372239e0823a81243221zmo@google.com node->setUseEmulatedFunction(); 21032e97315e2a55557ad7c372239e0823a81243221zmo@google.com } 21132e97315e2a55557ad7c372239e0823a81243221zmo@google.com return true; 21232e97315e2a55557ad7c372239e0823a81243221zmo@google.com } 21332e97315e2a55557ad7c372239e0823a81243221zmo@google.com 214f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com virtual bool visitAggregate(Visit visit, TIntermAggregate* node) 215f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com { 216f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (visit == PreVisit) { 217f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com // Here we handle all the built-in functions instead of the ones we 218f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com // currently identified as problematic. 219f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com switch (node->getOp()) { 220f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpLessThan: 221f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpGreaterThan: 222f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpLessThanEqual: 223f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpGreaterThanEqual: 224f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpVectorEqual: 225f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpVectorNotEqual: 226f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpMod: 227f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpPow: 228f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpAtan: 229f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpMin: 230f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpMax: 231f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpClamp: 232f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpMix: 233f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpStep: 234f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpSmoothStep: 235f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpDistance: 236f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpDot: 237f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpCross: 238f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpFaceForward: 239f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpReflect: 240f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpRefract: 241f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpMul: 242f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com break; 243f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com default: 244f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return true; 245f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com }; 246e40d1e9c70f1d1d5d0d92f24f8868fcf0b610639Zhenyao Mo const TIntermSequence& sequence = *(node->getSequence()); 247f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com // Right now we only handle built-in functions with two parameters. 248f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (sequence.size() != 2) 249f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return true; 250f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TIntermTyped* param1 = sequence[0]->getAsTyped(); 251f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TIntermTyped* param2 = sequence[1]->getAsTyped(); 252f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (!param1 || !param2) 253f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return true; 254f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com bool needToEmulate = mEmulator.SetFunctionCalled( 255f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com node->getOp(), param1->getType(), param2->getType()); 256f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (needToEmulate) 257f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com node->setUseEmulatedFunction(); 258f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com } 259f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return true; 260f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com } 261f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com 26232e97315e2a55557ad7c372239e0823a81243221zmo@google.comprivate: 26332e97315e2a55557ad7c372239e0823a81243221zmo@google.com BuiltInFunctionEmulator& mEmulator; 26432e97315e2a55557ad7c372239e0823a81243221zmo@google.com}; 26532e97315e2a55557ad7c372239e0823a81243221zmo@google.com 26632e97315e2a55557ad7c372239e0823a81243221zmo@google.com} // anonymous namepsace 26732e97315e2a55557ad7c372239e0823a81243221zmo@google.com 268183bde5527317fa2208401e5e6b803ef51a0fdcbJamie MadillBuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType) 26932e97315e2a55557ad7c372239e0823a81243221zmo@google.com{ 270183bde5527317fa2208401e5e6b803ef51a0fdcbJamie Madill if (shaderType == GL_FRAGMENT_SHADER) { 271f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com mFunctionMask = kFunctionEmulationFragmentMask; 272a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com mFunctionSource = kFunctionEmulationFragmentSource; 273a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com } else { 274f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com mFunctionMask = kFunctionEmulationVertexMask; 275a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com mFunctionSource = kFunctionEmulationVertexSource; 276a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com } 27732e97315e2a55557ad7c372239e0823a81243221zmo@google.com} 27832e97315e2a55557ad7c372239e0823a81243221zmo@google.com 27932e97315e2a55557ad7c372239e0823a81243221zmo@google.combool BuiltInFunctionEmulator::SetFunctionCalled( 280f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TOperator op, const TType& param) 28132e97315e2a55557ad7c372239e0823a81243221zmo@google.com{ 282f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TBuiltInFunction function = IdentifyFunction(op, param); 283f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return SetFunctionCalled(function); 284f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com} 285f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com 286f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.combool BuiltInFunctionEmulator::SetFunctionCalled( 287f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TOperator op, const TType& param1, const TType& param2) 288f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com{ 289f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TBuiltInFunction function = IdentifyFunction(op, param1, param2); 290f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return SetFunctionCalled(function); 291f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com} 292f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com 293f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.combool BuiltInFunctionEmulator::SetFunctionCalled( 294f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com BuiltInFunctionEmulator::TBuiltInFunction function) { 295f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (function == TFunctionUnknown || mFunctionMask[function] == false) 29632e97315e2a55557ad7c372239e0823a81243221zmo@google.com return false; 29732e97315e2a55557ad7c372239e0823a81243221zmo@google.com for (size_t i = 0; i < mFunctions.size(); ++i) { 29832e97315e2a55557ad7c372239e0823a81243221zmo@google.com if (mFunctions[i] == function) 29932e97315e2a55557ad7c372239e0823a81243221zmo@google.com return true; 30032e97315e2a55557ad7c372239e0823a81243221zmo@google.com } 301a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com mFunctions.push_back(function); 302a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com return true; 30332e97315e2a55557ad7c372239e0823a81243221zmo@google.com} 30432e97315e2a55557ad7c372239e0823a81243221zmo@google.com 30532e97315e2a55557ad7c372239e0823a81243221zmo@google.comvoid BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition( 30632e97315e2a55557ad7c372239e0823a81243221zmo@google.com TInfoSinkBase& out, bool withPrecision) const 30732e97315e2a55557ad7c372239e0823a81243221zmo@google.com{ 30832e97315e2a55557ad7c372239e0823a81243221zmo@google.com if (mFunctions.size() == 0) 30932e97315e2a55557ad7c372239e0823a81243221zmo@google.com return; 31032e97315e2a55557ad7c372239e0823a81243221zmo@google.com out << "// BEGIN: Generated code for built-in function emulation\n\n"; 31132e97315e2a55557ad7c372239e0823a81243221zmo@google.com if (withPrecision) { 312a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" 31393563fcf085045a0b7c6aef0c3507c2efce599a9zmo@google.com << "#define webgl_emu_precision highp\n" 31432e97315e2a55557ad7c372239e0823a81243221zmo@google.com << "#else\n" 31593563fcf085045a0b7c6aef0c3507c2efce599a9zmo@google.com << "#define webgl_emu_precision mediump\n" 31632e97315e2a55557ad7c372239e0823a81243221zmo@google.com << "#endif\n\n"; 317a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com } else { 31893563fcf085045a0b7c6aef0c3507c2efce599a9zmo@google.com out << "#define webgl_emu_precision\n\n"; 31932e97315e2a55557ad7c372239e0823a81243221zmo@google.com } 32032e97315e2a55557ad7c372239e0823a81243221zmo@google.com for (size_t i = 0; i < mFunctions.size(); ++i) { 321a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com out << mFunctionSource[mFunctions[i]] << "\n\n"; 32232e97315e2a55557ad7c372239e0823a81243221zmo@google.com } 32332e97315e2a55557ad7c372239e0823a81243221zmo@google.com out << "// END: Generated code for built-in function emulation\n\n"; 32432e97315e2a55557ad7c372239e0823a81243221zmo@google.com} 32532e97315e2a55557ad7c372239e0823a81243221zmo@google.com 32632e97315e2a55557ad7c372239e0823a81243221zmo@google.comBuiltInFunctionEmulator::TBuiltInFunction 327f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.comBuiltInFunctionEmulator::IdentifyFunction( 328f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TOperator op, const TType& param) 32932e97315e2a55557ad7c372239e0823a81243221zmo@google.com{ 33009e0988466ea9f3610dfb406f859b634b8e1e188shannonwoods@chromium.org if (param.getNominalSize() > 4 || param.getSecondarySize() > 4) 331a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com return TFunctionUnknown; 33232e97315e2a55557ad7c372239e0823a81243221zmo@google.com unsigned int function = TFunctionUnknown; 333f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com switch (op) { 334f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com case EOpCos: 335f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com function = TFunctionCos1; 336f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com break; 337a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com case EOpLength: 338a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com function = TFunctionLength1; 339a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com break; 340a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com case EOpNormalize: 341a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com function = TFunctionNormalize1; 342f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com break; 343f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com default: 344f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com break; 345f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com } 346f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (function == TFunctionUnknown) 347f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return TFunctionUnknown; 348f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (param.isVector()) 349f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com function += param.getNominalSize() - 1; 350f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return static_cast<TBuiltInFunction>(function); 351f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com} 35232e97315e2a55557ad7c372239e0823a81243221zmo@google.com 353f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.comBuiltInFunctionEmulator::TBuiltInFunction 354f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.comBuiltInFunctionEmulator::IdentifyFunction( 355f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com TOperator op, const TType& param1, const TType& param2) 356f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com{ 357f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com // Right now for all the emulated functions with two parameters, the two 358f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com // parameters have the same type. 35909e0988466ea9f3610dfb406f859b634b8e1e188shannonwoods@chromium.org if (param1.getNominalSize() != param2.getNominalSize() || 36009e0988466ea9f3610dfb406f859b634b8e1e188shannonwoods@chromium.org param1.getSecondarySize() != param2.getSecondarySize() || 36109e0988466ea9f3610dfb406f859b634b8e1e188shannonwoods@chromium.org param1.getNominalSize() > 4 || param1.getSecondarySize() > 4) 362f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return TFunctionUnknown; 363f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com 364f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com unsigned int function = TFunctionUnknown; 365f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com switch (op) { 366a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com case EOpDistance: 367a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com function = TFunctionDistance1_1; 368a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com break; 369a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com case EOpDot: 370a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com function = TFunctionDot1_1; 371a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com break; 372a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com case EOpReflect: 373a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com function = TFunctionReflect1_1; 374f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com break; 375f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com default: 376f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com break; 377f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com } 378f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (function == TFunctionUnknown) 379f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com return TFunctionUnknown; 380f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com if (param1.isVector()) 381f420c42442136e63c8c475446e01da1f6bcf5d32zmo@google.com function += param1.getNominalSize() - 1; 38232e97315e2a55557ad7c372239e0823a81243221zmo@google.com return static_cast<TBuiltInFunction>(function); 38332e97315e2a55557ad7c372239e0823a81243221zmo@google.com} 38432e97315e2a55557ad7c372239e0823a81243221zmo@google.com 38532e97315e2a55557ad7c372239e0823a81243221zmo@google.comvoid BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( 38632e97315e2a55557ad7c372239e0823a81243221zmo@google.com TIntermNode* root) 38732e97315e2a55557ad7c372239e0823a81243221zmo@google.com{ 38832e97315e2a55557ad7c372239e0823a81243221zmo@google.com ASSERT(root); 38932e97315e2a55557ad7c372239e0823a81243221zmo@google.com 39032e97315e2a55557ad7c372239e0823a81243221zmo@google.com BuiltInFunctionEmulationMarker marker(*this); 39132e97315e2a55557ad7c372239e0823a81243221zmo@google.com root->traverse(&marker); 39232e97315e2a55557ad7c372239e0823a81243221zmo@google.com} 39332e97315e2a55557ad7c372239e0823a81243221zmo@google.com 394a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.comvoid BuiltInFunctionEmulator::Cleanup() 395a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com{ 396a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com mFunctions.clear(); 397a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com} 398a3b4ab4c2beb1c020e474007ded4bed4a2383601zmo@google.com 39932e97315e2a55557ad7c372239e0823a81243221zmo@google.com//static 40032e97315e2a55557ad7c372239e0823a81243221zmo@google.comTString BuiltInFunctionEmulator::GetEmulatedFunctionName( 40132e97315e2a55557ad7c372239e0823a81243221zmo@google.com const TString& name) 40232e97315e2a55557ad7c372239e0823a81243221zmo@google.com{ 40332e97315e2a55557ad7c372239e0823a81243221zmo@google.com ASSERT(name[name.length() - 1] == '('); 40432e97315e2a55557ad7c372239e0823a81243221zmo@google.com return "webgl_" + name.substr(0, name.length() - 1) + "_emu("; 40532e97315e2a55557ad7c372239e0823a81243221zmo@google.com} 40632e97315e2a55557ad7c372239e0823a81243221zmo@google.com 407