Add ANGLE support for ESSL3 variant of mix()

This change adds support for ESSL3 variant of built-in function mix()
that takes last argument as a boolean vector. lerp() - HLSL equivalent
of mix() doesn't look to be supporting a variant that takes last
argument as a boolean vector so emulated it for HLSL.

BUG=angleproject:1006
TESTS=dEQP tests
Fixes "no matching overloaded function found " errors in below tests:
dEQP-GLES3.functional.shaders.constant_expressions.builtin_functions.common.mix_*_b*
(Note: These tests still fail because of constant expression issues)

Change-Id: I79b353933cb450516b8678b1fdaeabe60417e9a7
Reviewed-on: https://chromium-review.googlesource.com/271751
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
index 7123a0d..86d48a3 100644
--- a/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
+++ b/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
@@ -407,4 +407,35 @@
                             " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
         "    return cof / determinant(transpose(m));\n"
         "}\n");
+
+    TType bool1(EbtBool);
+    TType bool2(EbtBool, 2);
+    TType bool3(EbtBool, 3);
+    TType bool4(EbtBool, 4);
+
+    // Emulate ESSL3 variant of mix that takes last argument as boolean vector.
+    // genType mix (genType x, genType y, genBType a): Selects which vector each returned component comes from.
+    // For a component of 'a' that is false, the corresponding component of 'x' is returned.For a component of 'a' that is true,
+    // the corresponding component of 'y' is returned.
+    emu->addEmulatedFunction(EOpMix, float1, float1, bool1,
+        "float webgl_mix_emu(float x, float y, bool a)\n"
+        "{\n"
+        "    return a ? y : x;\n"
+        "}\n");
+    emu->addEmulatedFunction(EOpMix, float2, float2, bool2,
+        "float2 webgl_mix_emu(float2 x, float2 y, bool2 a)\n"
+        "{\n"
+        "    return a ? y : x;\n"
+        "}\n");
+    emu->addEmulatedFunction(EOpMix, float3, float3, bool3,
+        "float3 webgl_mix_emu(float3 x, float3 y, bool3 a)\n"
+        "{\n"
+        "    return a ? y : x;\n"
+        "}\n");
+    emu->addEmulatedFunction(EOpMix, float4, float4, bool4,
+        "float4 webgl_mix_emu(float4 x, float4 y, bool4 a)\n"
+        "{\n"
+        "    return a ? y : x;\n"
+        "}\n");
+
 }
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index 9e11405..0219e4e 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -96,6 +96,7 @@
     symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType);
+    symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMix, genType, "mix", genType, genType, genBType);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType);
     symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType);
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index dbdee4c..1f90aba 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -2253,7 +2253,22 @@
       case EOpMin:           outputTriplet(visit, "min(", ", ", ")");           break;
       case EOpMax:           outputTriplet(visit, "max(", ", ", ")");           break;
       case EOpClamp:         outputTriplet(visit, "clamp(", ", ", ")");         break;
-      case EOpMix:           outputTriplet(visit, "lerp(", ", ", ")");          break;
+      case EOpMix:
+        {
+            TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped();
+            if (lastParamNode->getType().getBasicType() == EbtBool)
+            {
+                // There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType y, genBType a)",
+                // so use emulated version.
+                ASSERT(node->getUseEmulatedFunction());
+                writeEmulatedFunctionTriplet(visit, "mix(");
+            }
+            else
+            {
+                outputTriplet(visit, "lerp(", ", ", ")");
+            }
+        }
+        break;
       case EOpStep:          outputTriplet(visit, "step(", ", ", ")");          break;
       case EOpSmoothStep:    outputTriplet(visit, "smoothstep(", ", ", ")");    break;
       case EOpDistance:      outputTriplet(visit, "distance(", ", ", ")");      break;