Support GL_OES_texture_border_clamp

Added support for GL_TEXTURE_BORDER_COLOR and GL_CLAMP_TO_BORDER in
OpenGL/OpenGLES, Direct3D9 and Direct3D11 backends.
For integer textures in OpenGLES3 contexts these additional entry points
are available now:

void glTexParameterIivOES(enum target, enum pname, const int *params);
void glTexParameterIuivOES(enum target, enum pname, const uint *params);

void glGetTexParameterIivOES(enum target, enum pname, int *params);
void glGetTexParameterIuivOES(enum target, enum pname, uint *params);

void glSamplerParameterIivOES(uint sampler, enum pname, const int *params);
void glSamplerParameterIuivOES(uint sampler, enum pname, const uint *params);

void glGetSamplerParameterIivOES(uint sampler, enum pname, int *params);
void glGetSamplerParameterIuivOES(uint sampler, enum pname, uint *params);

BUG=angleproject:2890
TEST=angle_end2end_tests.TextureBorderClamp*

Change-Id: Iee3eeb399d8d7851b3b30694ad8f21a2111f5828
Reviewed-on: https://chromium-review.googlesource.com/c/1257824
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index 45d18b2..60e5898 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -186,6 +186,31 @@
     return false;
 }
 
+inline bool IsIntegerSamplerUnsigned(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtISampler2D:
+        case EbtISampler3D:
+        case EbtISamplerCube:
+        case EbtISampler2DArray:
+        case EbtISampler2DMS:
+        case EbtISampler2DMSArray:
+            return false;
+        case EbtUSampler2D:
+        case EbtUSampler3D:
+        case EbtUSamplerCube:
+        case EbtUSampler2DArray:
+        case EbtUSampler2DMS:
+        case EbtUSampler2DMSArray:
+            return true;
+        default:
+            assert(!IsIntegerSampler(type));
+    }
+
+    return false;
+}
+
 inline bool IsSampler2DMS(TBasicType type)
 {
     switch (type)
diff --git a/src/compiler/translator/ResourcesHLSL.cpp b/src/compiler/translator/ResourcesHLSL.cpp
index 4cb4943..07223cf 100644
--- a/src/compiler/translator/ResourcesHLSL.cpp
+++ b/src/compiler/translator/ResourcesHLSL.cpp
@@ -509,6 +509,7 @@
                "        int internalFormatBits;\n"
                "        int wrapModes;\n"
                "        int padding;\n"
+               "        int4 intBorderColor;\n"
                "    };\n"
                "    SamplerMetadata samplerMetadata["
             << mSamplerCount << "] : packoffset(" << reg << ");\n";
diff --git a/src/compiler/translator/TextureFunctionHLSL.cpp b/src/compiler/translator/TextureFunctionHLSL.cpp
index edaf6fd..c3bd27a 100644
--- a/src/compiler/translator/TextureFunctionHLSL.cpp
+++ b/src/compiler/translator/TextureFunctionHLSL.cpp
@@ -32,17 +32,26 @@
     out << "int " << texCoordOutName << ";\n";
     out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset
         << ") / " << size << ";\n";
+    out << "bool " << texCoordOutName << "UseBorderColor = false;\n";
 
     // CLAMP_TO_EDGE
-    out << "if (" << wrapMode << " == 1)\n";
+    out << "if (" << wrapMode << " == 0)\n";
     out << "{\n";
     out << "    " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName
         << "Offset)), 0, int(" << size << ") - 1);\n";
     out << "}\n";
 
-    // MIRRORED_REPEAT
+    // CLAMP_TO_BORDER
     out << "else if (" << wrapMode << " == 3)\n";
     out << "{\n";
+    out << "    int texCoordInt = int(floor(" << size << " * " << texCoordOutName << "Offset));\n";
+    out << "    " << texCoordOutName << " = clamp(texCoordInt, 0, int(" << size << ") - 1);\n";
+    out << "    " << texCoordOutName << "UseBorderColor = (texCoordInt != " << texCoordOutName << ");\n";
+    out << "}\n";
+
+    // MIRRORED_REPEAT
+    out << "else if (" << wrapMode << " == 2)\n";
+    out << "{\n";
     out << "    float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName
         << "Offset) * 0.5) * 2.0 - 1.0);\n";
     out << "    " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n";
@@ -84,6 +93,8 @@
     }
     *texCoordY = ImmutableString("tiy");
 
+    bool tizAvailable = false;
+
     if (IsSamplerArray(textureFunction.sampler))
     {
         *texCoordZ = ImmutableString("int(max(0, min(layers - 1, floor(0.5 + t.z))))");
@@ -99,8 +110,12 @@
         {
             OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "0", "tiz");
         }
-        *texCoordZ = ImmutableString("tiz");
+        *texCoordZ   = ImmutableString("tiz");
+        tizAvailable = true;
     }
+
+    out << "bool useBorderColor = tixUseBorderColor || tiyUseBorderColor"
+        << (tizAvailable ? " || tizUseBorderColor" : "") << ";\n";
 }
 
 void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out,
@@ -907,6 +922,17 @@
 {
     out << "    return ";
 
+    if (IsIntegerSampler(textureFunction.sampler) && !IsSamplerCube(textureFunction.sampler) &&
+        textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH)
+    {
+        out << " useBorderColor ? ";
+        if (IsIntegerSamplerUnsigned(textureFunction.sampler))
+        {
+            out << "asuint";
+        }
+        out << "(samplerMetadata[samplerIndex].intBorderColor) : ";
+    }
+
     // HLSL intrinsic
     if (outputType == SH_HLSL_3_0_OUTPUT)
     {