Context now detects if a texture needs to be swizzled and calls Renderer::generateSwizzles.

Change-Id: I89f30e028b1d6ec384536cdbeedd91bb98359e8f
Reviewed-on: https://chromium-review.googlesource.com/178440
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Commit-Queue: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Shannon Woods <shannonwoods@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index d50595d..633805d 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -2347,33 +2347,88 @@
 }
 
 // Applies the shaders and shader constants to the Direct3D 9 device
-void Context::applyShaders()
+void Context::applyShaders(ProgramBinary *programBinary)
 {
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
     mRenderer->applyShaders(programBinary);
     
     programBinary->applyUniforms();
 }
 
-// Applies the textures and sampler states to the Direct3D 9 device
-void Context::applyTextures()
+bool Context::getCurrentTextureAndSamplerState(ProgramBinary *programBinary, SamplerType type, int index, Texture **outTexture,
+                                               TextureType *outTextureType, SamplerState *outSampler)
 {
-    applyTextures(SAMPLER_PIXEL);
+    int textureUnit = programBinary->getSamplerMapping(type, index);   // OpenGL texture image unit index
 
-    if (mSupportsVertexTexture)
+    if (textureUnit != -1)
     {
-        applyTextures(SAMPLER_VERTEX);
+        TextureType textureType = programBinary->getSamplerTextureType(type, index);
+        Texture *texture = getSamplerTexture(textureUnit, textureType);
+
+        SamplerState samplerState;
+        texture->getSamplerState(&samplerState);
+
+        if (mState.samplers[textureUnit] != 0)
+        {
+            Sampler *samplerObject = getSampler(mState.samplers[textureUnit]);
+            samplerObject->getState(&samplerState);
+        }
+
+        *outTexture = texture;
+        *outTextureType = textureType;
+        *outSampler = samplerState;
+
+        return true;
+    }
+    else
+    {
+        return false;
     }
 }
 
-// For each Direct3D 9 sampler of either the pixel or vertex stage,
+void Context::generateSwizzles(ProgramBinary *programBinary)
+{
+    generateSwizzles(programBinary, SAMPLER_PIXEL);
+
+    if (mSupportsVertexTexture)
+    {
+        generateSwizzles(programBinary, SAMPLER_VERTEX);
+    }
+}
+
+void Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type)
+{
+    // Range of Direct3D samplers of given sampler type
+    int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits();
+    int samplerRange = programBinary->getUsedSamplerRange(type);
+
+    for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+    {
+        Texture *texture = NULL;
+        TextureType textureType;
+        SamplerState samplerState;
+        if (getCurrentTextureAndSamplerState(programBinary, type, samplerIndex, &texture, &textureType, &samplerState) && texture->isSwizzled())
+        {
+            mRenderer->generateSwizzle(texture);
+        }
+    }
+}
+
+// Applies the textures and sampler states to the Direct3D 9 device
+void Context::applyTextures(ProgramBinary *programBinary)
+{
+    applyTextures(programBinary, SAMPLER_PIXEL);
+
+    if (mSupportsVertexTexture)
+    {
+        applyTextures(programBinary, SAMPLER_VERTEX);
+    }
+}
+
+// For each Direct3D sampler of either the pixel or vertex stage,
 // looks up the corresponding OpenGL texture image unit and texture type,
 // and sets the texture and its addressing/filtering state (or NULL when inactive).
-void Context::applyTextures(SamplerType type)
+void Context::applyTextures(ProgramBinary *programBinary, SamplerType type)
 {
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
     FramebufferTextureSerialSet boundFramebufferTextures = getBoundFramebufferTextureSerials();
 
     // Range of Direct3D samplers of given sampler type
@@ -2382,29 +2437,16 @@
 
     for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
     {
-        int textureUnit = programBinary->getSamplerMapping(type, samplerIndex);   // OpenGL texture image unit index
-
-        if (textureUnit != -1)
+        Texture *texture = NULL;
+        TextureType textureType;
+        SamplerState samplerState;
+        if (getCurrentTextureAndSamplerState(programBinary, type, samplerIndex, &texture, &textureType, &samplerState))
         {
-            TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex);
-            Texture *texture = getSamplerTexture(textureUnit, textureType);
-
-            SamplerState samplerState;
-            texture->getSamplerState(&samplerState);
-
-            if ((mState.samplers[textureUnit] != 0) &&
-                (boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end()))
-            {
-                Sampler *samplerObject = getSampler(mState.samplers[textureUnit]);
-                samplerObject->getState(&samplerState);
-            }
-
-            if (texture->isSamplerComplete(samplerState))
+            if (texture->isSamplerComplete(samplerState) &&
+                boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end())
             {
                 mRenderer->setSamplerState(type, samplerIndex, samplerState);
-
                 mRenderer->setTexture(type, samplerIndex, texture);
-
                 texture->resetDirty();
             }
             else
@@ -2733,6 +2775,11 @@
         return gl::error(GL_INVALID_OPERATION);
     }
 
+    ProgramBinary *programBinary = getCurrentProgramBinary();
+    programBinary->applyUniforms();
+
+    generateSwizzles(programBinary);
+
     if (!mRenderer->applyPrimitiveType(mode, count))
     {
         return;
@@ -2745,16 +2792,14 @@
 
     applyState(mode);
 
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
     GLenum err = mRenderer->applyVertexBuffer(programBinary, getCurrentVertexArray()->getVertexAttributes(), mState.vertexAttribCurrentValues, first, count, instances);
     if (err != GL_NO_ERROR)
     {
         return gl::error(err);
     }
 
-    applyShaders();
-    applyTextures();
+    applyShaders(programBinary);
+    applyTextures(programBinary);
 
     if (!applyUniformBuffers())
     {
@@ -2784,7 +2829,12 @@
     {
         return gl::error(GL_INVALID_OPERATION);
     }
-    
+
+    ProgramBinary *programBinary = getCurrentProgramBinary();
+    programBinary->applyUniforms();
+
+    generateSwizzles(programBinary);
+
     if (!mRenderer->applyPrimitiveType(mode, count))
     {
         return;
@@ -2804,8 +2854,6 @@
         return gl::error(err);
     }
 
-    ProgramBinary *programBinary = getCurrentProgramBinary();
-
     GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
     err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.vertexAttribCurrentValues, indexInfo.minIndex, vertexCount, instances);
     if (err != GL_NO_ERROR)
@@ -2813,8 +2861,8 @@
         return gl::error(err);
     }
 
-    applyShaders();
-    applyTextures();
+    applyShaders(programBinary);
+    applyTextures(programBinary);
 
     if (!applyUniformBuffers())
     {
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 6e27131..3cce467 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -447,9 +447,9 @@
 
     bool applyRenderTarget(GLenum drawMode, bool ignoreViewport);
     void applyState(GLenum drawMode);
-    void applyShaders();
-    void applyTextures();
-    void applyTextures(SamplerType type);
+    void applyShaders(ProgramBinary *programBinary);
+    void applyTextures(ProgramBinary *programBinary);
+    void applyTextures(ProgramBinary *programBinary, SamplerType type);
     bool applyUniformBuffers();
 
     void detachBuffer(GLuint buffer);
@@ -459,6 +459,10 @@
     void detachVertexArray(GLuint vertexArray);
     void detachSampler(GLuint sampler);
 
+    void generateSwizzles(ProgramBinary *programBinary);
+    void generateSwizzles(ProgramBinary *programBinary, SamplerType type);
+    bool getCurrentTextureAndSamplerState(ProgramBinary *programBinary, SamplerType type, int index, Texture **outTexture,
+                                   TextureType *outTextureType, SamplerState *outSampler);
     Texture *getIncompleteTexture(TextureType type);
 
     bool skipDraw(GLenum drawMode);
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 6463f11..da2b9f2 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -118,6 +118,7 @@
 
     virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
 
+    virtual void generateSwizzle(gl::Texture *texture) = 0;
     virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0;
     virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
 
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
index 1f180d2..0a8849c 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
@@ -521,6 +521,11 @@
     return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
 }
 
+void Renderer11::generateSwizzle(gl::Texture *texture)
+{
+    UNIMPLEMENTED();
+}
+
 void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
 {
     if (type == gl::SAMPLER_PIXEL)
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/libGLESv2/renderer/d3d11/Renderer11.h
index 70da3ab..9127f79 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.h
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.h
@@ -57,6 +57,7 @@
 
     virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
 
+    virtual void generateSwizzle(gl::Texture *texture);
     virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
     virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
 
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
index 8632a89..67292c4 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
@@ -759,6 +759,12 @@
     return false;
 }
 
+void Renderer9::generateSwizzle(gl::Texture *texture)
+{
+    // Swizzled textures are not available in ES2 or D3D9
+    UNREACHABLE();
+}
+
 void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
 {
     bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/libGLESv2/renderer/d3d9/Renderer9.h
index 7be7120..cab5213 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.h
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.h
@@ -69,6 +69,7 @@
     void applyShaders();
     void applyConstants();
 #endif
+    virtual void generateSwizzle(gl::Texture *texture);
     virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
     virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);