Implement EXT_shader_texture_lod

BUG=angle:551

Change-Id: I81d7574a15861f1b24ddf6147cf71adbf20e10f3
Reviewed-on: https://chromium-review.googlesource.com/194960
Tested-by: Nicolas Capens <nicolascapens@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index 6b7734a..d144562 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -351,6 +351,17 @@
         symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, float4);
     }
 
+    if (resources.EXT_shader_texture_lod)
+    {
+        /* The *Grad* variants are new to both vertex and fragment shaders; the fragment
+         * shader specific pieces are added separately below.
+         */
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DGradEXT", sampler2D, float2, float2, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2);
+        symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeGradEXT", samplerCube, float3, float3, float3);
+    }
+
     if (type == SH_FRAGMENT_SHADER)
     {
         symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1);
@@ -364,7 +375,7 @@
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdx", float2);
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdx", float3);
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdx", float4);
-            
+
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdy", float1);
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdy", float2);
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdy", float3);
@@ -375,6 +386,14 @@
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "fwidth", float3);
             symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "fwidth", float4);
         }
+
+        if (resources.EXT_shader_texture_lod)
+        {
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLodEXT", sampler2D, float2, float1);
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float3, float1);
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float4, float1);
+            symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLodEXT", samplerCube, float3, float1);
+        }
     }
 
     if(type == SH_VERTEX_SHADER)
@@ -668,7 +687,7 @@
     symbolTable.relateToOperator(COMMON_BUILTINS, "faceforward",  EOpFaceForward);
     symbolTable.relateToOperator(COMMON_BUILTINS, "reflect",      EOpReflect);
     symbolTable.relateToOperator(COMMON_BUILTINS, "refract",      EOpRefract);
-    
+
     symbolTable.relateToOperator(COMMON_BUILTINS, "any",          EOpAny);
     symbolTable.relateToOperator(COMMON_BUILTINS, "all",          EOpAll);
     symbolTable.relateToOperator(COMMON_BUILTINS, "not",          EOpVectorLogicalNot);
@@ -678,7 +697,8 @@
     case SH_VERTEX_SHADER:
         break;
     case SH_FRAGMENT_SHADER:
-        if (resources.OES_standard_derivatives) {
+        if (resources.OES_standard_derivatives)
+        {
             symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdx",   EOpDFdx);
             symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdy",   EOpDFdy);
             symbolTable.relateToOperator(ESSL1_BUILTINS, "fwidth", EOpFwidth);
@@ -687,6 +707,12 @@
             symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdy", "GL_OES_standard_derivatives");
             symbolTable.relateToExtension(ESSL1_BUILTINS, "fwidth", "GL_OES_standard_derivatives");
         }
+        if (resources.EXT_shader_texture_lod)
+        {
+            symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DLodEXT", "GL_EXT_shader_texture_lod");
+            symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjLodEXT", "GL_EXT_shader_texture_lod");
+            symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeLodEXT", "GL_EXT_shader_texture_lod");
+        }
         break;
     default: break;
     }
@@ -695,6 +721,13 @@
     symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdy",   EOpDFdy);
     symbolTable.relateToOperator(ESSL3_BUILTINS, "fwidth", EOpFwidth);
 
+    if (resources.EXT_shader_texture_lod)
+    {
+        symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DGradEXT", "GL_EXT_shader_texture_lod");
+        symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjGradEXT", "GL_EXT_shader_texture_lod");
+        symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeGradEXT", "GL_EXT_shader_texture_lod");
+    }
+
     // Finally add resource-specific variables.
     switch(type) {
     case SH_FRAGMENT_SHADER:
@@ -722,4 +755,6 @@
         extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
     if (resources.EXT_frag_depth)
         extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
+    if (resources.EXT_shader_texture_lod)
+        extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined;
 }