[GLESv3] Shader state updates

- Track program pipelines
- Track separate shader programs
- Track original shader source in guest

Change-Id: I8f54089ddf12d03677275cde58ea7f267e410482
diff --git a/shared/OpenglCodecCommon/GLClientState.cpp b/shared/OpenglCodecCommon/GLClientState.cpp
index 9de12d9..1daad5e 100644
--- a/shared/OpenglCodecCommon/GLClientState.cpp
+++ b/shared/OpenglCodecCommon/GLClientState.cpp
@@ -647,6 +647,16 @@
     return it->second.numActiveUniforms;
 }
 
+void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
+    m_programPipelines[program] = pipeline;
+}
+
+GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
+    return m_programPipelines.begin();
+}
+
+GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
+    return m_programPipelines.end();
 }
 
 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
diff --git a/shared/OpenglCodecCommon/GLClientState.h b/shared/OpenglCodecCommon/GLClientState.h
index 92949d9..0d7a60d 100644
--- a/shared/OpenglCodecCommon/GLClientState.h
+++ b/shared/OpenglCodecCommon/GLClientState.h
@@ -257,6 +257,13 @@
 
     void setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms);
     size_t numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const;
+
+    typedef std::map<GLuint, GLuint> ProgramPipelineMap;
+    typedef ProgramPipelineMap::iterator ProgramPipelineIterator;
+    void associateProgramWithPipeline(GLuint program, GLuint pipeline);
+    ProgramPipelineIterator programPipelineBegin();
+    ProgramPipelineIterator programPipelineEnd();
+
     /* OES_EGL_image_external
      *
      * These functions manipulate GL state which interacts with the
@@ -445,6 +452,7 @@
     int m_nLocations;
     int m_activeTexture;
     GLint m_currentProgram;
+    ProgramPipelineMap m_programPipelines;
 
     enum TextureTarget {
         TEXTURE_2D = 0,
diff --git a/shared/OpenglCodecCommon/GLSharedGroup.cpp b/shared/OpenglCodecCommon/GLSharedGroup.cpp
index a41eb2c..58dc89a 100755
--- a/shared/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/shared/OpenglCodecCommon/GLSharedGroup.cpp
@@ -227,7 +227,8 @@
 GLSharedGroup::GLSharedGroup() :
     m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
     m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
-    m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
+    m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL)),
+    m_shaderPrograms(android::DefaultKeyedVector<GLuint, ShaderProgramData*>(NULL))
 {
 }
 
@@ -238,12 +239,15 @@
     clearObjectMap(m_buffers);
     clearObjectMap(m_programs);
     clearObjectMap(m_shaders);
+    clearObjectMap(m_shaderPrograms);
 }
 
-bool GLSharedGroup::isObject(GLuint obj)
+bool GLSharedGroup::isShaderOrProgramObject(GLuint obj)
 {
     android::AutoMutex _lock(m_lock);
-    return ((m_shaders.valueFor(obj)!=NULL) || (m_programs.valueFor(obj)!=NULL));
+    return ((m_shaders.valueFor(obj)!=NULL) ||
+            (m_programs.valueFor(obj)!=NULL) ||
+            (m_shaderPrograms.valueFor(m_shaderProgramIdMap[obj]) !=NULL));
 }
 
 BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
@@ -354,6 +358,11 @@
     {
         return pData->isInitialized();
     }
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) {
+        return spData->programData->isInitialized();
+    }
     return false;
 }
 
@@ -361,11 +370,21 @@
 {
     android::AutoMutex _lock(m_lock);
     ProgramData *pData = m_programs.valueFor(program);
-    if (pData)
+    if (pData) {
         delete pData;
+    }
     m_programs.removeItem(program);
+
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) {
+        delete spData;
+    }
+    m_shaderPrograms.removeItem(m_shaderProgramIdMap[program]);
+    m_shaderProgramIdMap.erase(program);
 }
 
+// No such thing for separable shader programs.
 void GLSharedGroup::attachShader(GLuint program, GLuint shader)
 {
     android::AutoMutex _lock(m_lock);
@@ -390,6 +409,7 @@
     }
 }
 
+// Not needed/used for separate shader programs.
 void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
 {
     android::AutoMutex _lock(m_lock);
@@ -423,10 +443,14 @@
     android::AutoMutex _lock(m_lock);
     ProgramData* pData = m_programs.valueFor(program);
     GLenum type=0;
-    if (pData)
-    {
+    if (pData) {
         type = pData->getTypeForLocation(location);
     }
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return type;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) {
+        type = spData->programData->getTypeForLocation(location);
+    }
     return type;
 }
 
@@ -434,7 +458,11 @@
 {
     android::AutoMutex _lock(m_lock);
     ProgramData* pData = m_programs.valueFor(program);
-    return (pData!=NULL);
+    if (pData) return true;
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) return true;
+    return false;
 }
 
 void GLSharedGroup::setupLocationShiftWAR(GLuint program)
@@ -449,7 +477,10 @@
     android::AutoMutex _lock(m_lock);
     ProgramData* pData = m_programs.valueFor(program);
     if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
-    else return hostLoc;
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return hostLoc;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) return spData->programData->locationWARHostToApp(hostLoc, arrIndex);
+    return hostLoc;
 }
 
 GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
@@ -457,7 +488,10 @@
     android::AutoMutex _lock(m_lock);
     ProgramData* pData = m_programs.valueFor(program);
     if (pData) return pData->locationWARAppToHost(appLoc);
-    else return appLoc;
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return appLoc;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) return spData->programData->locationWARAppToHost(appLoc);
+    return appLoc;
 }
 
 bool GLSharedGroup::needUniformLocationWAR(GLuint program)
@@ -465,6 +499,9 @@
     android::AutoMutex _lock(m_lock);
     ProgramData* pData = m_programs.valueFor(program);
     if (pData) return pData->needUniformLocationWAR();
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) return spData->programData->needUniformLocationWAR();
     return false;
 }
 
@@ -472,14 +509,22 @@
 {
     android::AutoMutex _lock(m_lock);
     ProgramData* pData = m_programs.valueFor(program);
-    return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
+    if (pData) return pData->getNextSamplerUniform(index, val, target);
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return -1;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap.at(program));
+    if (spData) return spData->programData->getNextSamplerUniform(index, val, target);
+    return -1;
 }
 
 bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
 {
     android::AutoMutex _lock(m_lock);
     ProgramData* pData = m_programs.valueFor(program);
-    return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
+    if (pData) return pData->setSamplerUniform(appLoc, val, target);
+    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) return false;
+    ShaderProgramData* spData = m_shaderPrograms.valueFor(m_shaderProgramIdMap[program]);
+    if (spData) return spData->programData->setSamplerUniform(appLoc, val, target);
+    return false;
 }
 
 bool  GLSharedGroup::isShader(GLuint shader)
@@ -534,3 +579,77 @@
         m_shaders.removeItemsAt(shaderIdx);
     }
 }
+
+uint32_t GLSharedGroup::addNewShaderProgramData() {
+    android::AutoMutex _lock(m_lock);
+    ShaderProgramData* data = new ShaderProgramData;
+    uint32_t currId = m_shaderProgramId;
+    m_shaderPrograms.add(currId, data);
+    m_shaderProgramId++;
+    return currId;
+}
+
+void GLSharedGroup::associateGLShaderProgram(GLuint shaderProgramName, uint32_t shaderProgramId) {
+    android::AutoMutex _lock(m_lock);
+    m_shaderProgramIdMap[shaderProgramName] = shaderProgramId;
+}
+
+ShaderProgramData* GLSharedGroup::getShaderProgramDataById(uint32_t id) {
+    android::AutoMutex _lock(m_lock);
+    return m_shaderPrograms.editValueAt(id);
+}
+
+ShaderProgramData* GLSharedGroup::getShaderProgramData(GLuint shaderProgramName) {
+    android::AutoMutex _lock(m_lock);
+    return m_shaderPrograms.editValueAt(m_shaderProgramIdMap[shaderProgramName]);
+}
+
+void GLSharedGroup::deleteShaderProgramDataById(uint32_t id) {
+    android::AutoMutex _lock(m_lock);
+    ShaderProgramData* data = m_shaderPrograms.valueFor(id);
+    delete data;
+    m_shaderPrograms.removeItemsAt(id);
+}
+
+
+void GLSharedGroup::deleteShaderProgramData(GLuint shaderProgramName) {
+    android::AutoMutex _lock(m_lock);
+    uint32_t id = m_shaderProgramIdMap[shaderProgramName];
+    ShaderProgramData* data = m_shaderPrograms.valueFor(id);
+    delete data;
+    m_shaderPrograms.removeItemsAt(id);
+    m_shaderProgramIdMap.erase(shaderProgramName);
+}
+
+void GLSharedGroup::initShaderProgramData(GLuint shaderProgram, GLuint numIndices) {
+    ShaderProgramData* spData = getShaderProgramData(shaderProgram);
+    spData->programData->initProgramData(numIndices);
+}
+
+void GLSharedGroup::setShaderProgramIndexInfo(GLuint shaderProgram, GLuint index, GLint base, GLint size, GLenum type, const char* name) {
+    ShaderProgramData* spData = getShaderProgramData(shaderProgram);
+    ProgramData* pData = spData->programData;
+    ShaderData* sData = spData->shaderData;
+
+    if (pData)
+    {
+        pData->setIndexInfo(index, base, size, type);
+
+        if (type == GL_SAMPLER_2D) {
+            ShaderData::StringList::iterator nameIter = sData->samplerExternalNames.begin();
+            ShaderData::StringList::iterator nameEnd  = sData->samplerExternalNames.end();
+            while (nameIter != nameEnd) {
+                if (*nameIter == name) {
+                    pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
+                    break;
+                }
+                ++nameIter;
+            }
+        }
+    }
+}
+
+void GLSharedGroup::setupShaderProgramLocationShiftWAR(GLuint shaderProgram) {
+    ShaderProgramData* spData = getShaderProgramData(shaderProgram);
+    spData->programData->setupLocationShiftWAR();
+}
diff --git a/shared/OpenglCodecCommon/GLSharedGroup.h b/shared/OpenglCodecCommon/GLSharedGroup.h
index d3663fa..ca33836 100755
--- a/shared/OpenglCodecCommon/GLSharedGroup.h
+++ b/shared/OpenglCodecCommon/GLSharedGroup.h
@@ -30,6 +30,9 @@
 #include <GLES2/gl2ext.h>
 
 #include <map>
+#include <string>
+#include <vector>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include "ErrorLog.h"
@@ -111,6 +114,21 @@
     typedef android::List<android::String8> StringList;
     StringList samplerExternalNames;
     int refcount;
+    std::vector<std::string> sources;
+};
+
+class ShaderProgramData {
+public:
+    ShaderProgramData() {
+        shaderData = new ShaderData();
+        programData = new ProgramData();
+    }
+    ~ShaderProgramData() {
+        delete shaderData;
+        delete programData;
+    }
+    ShaderData* shaderData;
+    ProgramData* programData;
 };
 
 class GLSharedGroup {
@@ -119,15 +137,20 @@
     android::DefaultKeyedVector<GLuint, BufferData*> m_buffers;
     android::DefaultKeyedVector<GLuint, ProgramData*> m_programs;
     android::DefaultKeyedVector<GLuint, ShaderData*> m_shaders;
+    android::DefaultKeyedVector<uint32_t, ShaderProgramData*> m_shaderPrograms;
+    std::map<GLuint, uint32_t> m_shaderProgramIdMap;
+
     mutable android::Mutex m_lock;
 
     void refShaderDataLocked(ssize_t shaderIdx);
     void unrefShaderDataLocked(ssize_t shaderIdx);
 
+    uint32_t m_shaderProgramId;
+
 public:
     GLSharedGroup();
     ~GLSharedGroup();
-    bool isObject(GLuint obj);
+    bool isShaderOrProgramObject(GLuint obj);
     BufferData * getBufferData(GLuint bufferId);
     SharedTextureDataMap* getTextureData();
     void    addBufferData(GLuint bufferId, GLsizeiptr size, void * data);
@@ -160,6 +183,17 @@
     // caller must hold a reference to the shader as long as it holds the pointer
     ShaderData* getShaderData(GLuint shader);
     void    unrefShaderData(GLuint shader);
+
+    // For separable shader programs.
+    uint32_t addNewShaderProgramData();
+    void associateGLShaderProgram(GLuint shaderProgramName, uint32_t shaderProgramId);
+    ShaderProgramData* getShaderProgramDataById(uint32_t id);
+    ShaderProgramData* getShaderProgramData(GLuint shaderProgramName);
+    void deleteShaderProgramDataById(uint32_t id);
+    void deleteShaderProgramData(GLuint shaderProgramName);
+    void initShaderProgramData(GLuint shaderProgram, GLuint numIndices);
+    void setShaderProgramIndexInfo(GLuint shaderProgram, GLuint index, GLint base, GLint size, GLenum type, const char* name);
+    void setupShaderProgramLocationShiftWAR(GLuint shaderProgram);
 };
 
 typedef SmartPtr<GLSharedGroup> GLSharedGroupPtr;