Select texture type based on program usage.

TRAC #11410

Add Program::getSamplerType() and internal machinery to track the reported sampler uniforms.
Make State::samplerTexture into a 2D array with a dimension for sampler type.
Context::applyTextures queries the sampler type and asks for the right texture.

Author:    Andrew Lewycky
Signed-off-by: Shannon Woods
Signed-off-by: Daniel Koch

git-svn-id: https://angleproject.googlecode.com/svn/trunk@25 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/Include/Context.h b/Include/Context.h
index 75f917f..0e4426c 100644
--- a/Include/Context.h
+++ b/Include/Context.h
@@ -64,6 +64,14 @@
 // Because indices are accessed internally, we convert them to a common format.
 typedef unsigned short Index;
 
+enum SamplerType
+{
+    SAMPLER_2D,
+    SAMPLER_CUBE,
+
+    SAMPLER_TYPE_COUNT
+};
+
 struct Color
 {
     float red;
@@ -170,7 +178,7 @@
     GLuint currentProgram;
 
     AttributeState vertexAttribute[MAX_VERTEX_ATTRIBS];
-    GLuint samplerTexture[MAX_TEXTURE_IMAGE_UNITS];
+    GLuint samplerTexture[SAMPLER_TYPE_COUNT][MAX_TEXTURE_IMAGE_UNITS];
 
     unsigned int startIndex;
 };
@@ -231,7 +239,7 @@
     Program *getCurrentProgram();
     Texture2D *getTexture2D();
     TextureCubeMap *getTextureCubeMap();
-    Texture *getSamplerTexture(unsigned int sampler);
+    Texture *getSamplerTexture(unsigned int sampler, SamplerType type);
     Framebuffer *getFramebuffer();
 
     bool applyRenderTarget(bool ignoreViewport);
diff --git a/libGLESv2/Context.cpp b/libGLESv2/Context.cpp
index 52817ce..37db9a7 100644
--- a/libGLESv2/Context.cpp
+++ b/libGLESv2/Context.cpp
@@ -115,9 +115,12 @@
     bindFramebuffer(0);
     bindRenderbuffer(0);
 
-    for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+    for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
     {
-        samplerTexture[sampler] = 0;
+        for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+        {
+            samplerTexture[type][sampler] = 0;
+        }
     }
 
     currentProgram = 0;
@@ -458,7 +461,7 @@
 
     texture2D = texture;
 
-    samplerTexture[activeSampler] = texture;
+    samplerTexture[SAMPLER_2D][activeSampler] = texture;
 }
 
 void Context::bindTextureCubeMap(GLuint texture)
@@ -477,7 +480,7 @@
 
     textureCubeMap = texture;
 
-    samplerTexture[activeSampler] = texture;
+    samplerTexture[SAMPLER_CUBE][activeSampler] = texture;
 }
 
 void Context::bindFramebuffer(GLuint framebuffer)
@@ -718,9 +721,9 @@
     return (TextureCubeMap*)getTexture(textureCubeMap);
 }
 
-Texture *Context::getSamplerTexture(unsigned int sampler)
+Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
 {
-    return getTexture(samplerTexture[sampler]);
+    return getTexture(samplerTexture[type][sampler]);
 }
 
 Framebuffer *Context::getFramebuffer()
@@ -1051,11 +1054,13 @@
 
     for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
     {
-        unsigned int textureUnit = programObject->getSamplerMapping(sampler);
-        Texture *texture = getSamplerTexture(textureUnit);
-
-        if (texture && texture->isComplete())
+        int textureUnit = programObject->getSamplerMapping(sampler);
+        if (textureUnit != -1)
         {
+            SamplerType textureType = programObject->getSamplerType(sampler);
+
+            Texture *texture = getSamplerTexture(textureUnit, textureType);
+
             GLenum wrapS = texture->getWrapS();
             GLenum wrapT = texture->getWrapT();
             GLenum minFilter = texture->getMinFilter();
@@ -1072,6 +1077,10 @@
 
             device->SetTexture(sampler, texture->getTexture());
         }
+        else
+        {
+            device->SetTexture(sampler, NULL);
+        }
     }
 }
 
@@ -1637,11 +1646,14 @@
     // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
     // rebound to texture object zero
 
-    for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
+    for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
     {
-        if (samplerTexture[sampler] == texture)
+        for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
         {
-            samplerTexture[sampler] = 0;
+            if (samplerTexture[type][sampler] == texture)
+            {
+                samplerTexture[type][sampler] = 0;
+            }
         }
     }
 
diff --git a/libGLESv2/Program.cpp b/libGLESv2/Program.cpp
index 1d6e36d..7f18731 100644
--- a/libGLESv2/Program.cpp
+++ b/libGLESv2/Program.cpp
@@ -164,12 +164,22 @@
 // index referenced in the compiled HLSL shader
 GLint Program::getSamplerMapping(unsigned int samplerIndex)
 {
-    if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
+    assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
+
+    if (mSamplers[samplerIndex].active)
     {
-        return mSamplerMapping[samplerIndex];
+        return mSamplers[samplerIndex].logicalTextureUnit;
     }
 
-    return 0;
+    return -1;
+}
+
+SamplerType Program::getSamplerType(unsigned int samplerIndex)
+{
+    assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
+    assert(mSamplers[samplerIndex].active);
+
+    return mSamplers[samplerIndex].type;
 }
 
 GLint Program::getUniformLocation(const char *name)
@@ -434,6 +444,11 @@
                 return;
             }
 
+            for (int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
+            {
+                mSamplers[i].active = false;
+            }
+
             if (!linkUniforms(mConstantTablePS))
             {
                 return;
@@ -515,6 +530,17 @@
 // Returns true if succesful (uniform not already defined)
 bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
 {
+    if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
+    {
+        unsigned int samplerIndex = constantDescription.RegisterIndex;
+
+        assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
+
+        mSamplers[samplerIndex].active = true;
+        mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D;
+        mSamplers[samplerIndex].logicalTextureUnit = 0;
+    }
+
     switch(constantDescription.Class)
     {
       case D3DXPC_STRUCT:
@@ -858,7 +884,8 @@
                 {
                     if (samplerIndex >= 0 && samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
                     {
-                        mSamplerMapping[samplerIndex] = mappedSampler;
+                        ASSERT(mSamplers[samplerIndex].active);
+                        mSamplers[samplerIndex].logicalTextureUnit = mappedSampler;
                     }
                 }
             }
@@ -935,7 +962,7 @@
 
     for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
     {
-        mSamplerMapping[index] = 0;
+        mSamplers[index].active = false;
     }
 
     while (!mUniforms.empty())
diff --git a/libGLESv2/Program.h b/libGLESv2/Program.h
index 3e72d86..157e36e 100644
--- a/libGLESv2/Program.h
+++ b/libGLESv2/Program.h
@@ -65,6 +65,7 @@
     int getInputMapping(int attributeIndex);
 
     GLint getSamplerMapping(unsigned int samplerIndex);
+    SamplerType getSamplerType(unsigned int samplerIndex);
 
     GLint getUniformLocation(const char *name);
     bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
@@ -115,7 +116,14 @@
     char *mAttributeName[MAX_VERTEX_ATTRIBS];
     int mInputMapping[MAX_VERTEX_ATTRIBS];
 
-    GLint mSamplerMapping[MAX_TEXTURE_IMAGE_UNITS];
+    struct Sampler
+    {
+        bool active;
+        GLint logicalTextureUnit;
+        SamplerType type;
+    };
+
+    Sampler mSamplers[MAX_TEXTURE_IMAGE_UNITS];
 
     typedef std::vector<Uniform*> UniformArray;
     UniformArray mUniforms;