fixing bugs 3053960, 3044804, 3044798
shader cleanup and removing unnecessary state setup.

Change-Id: Ibddf2ad3a26bb983fc43bdeb58b1cec6224920b4
diff --git a/rsContext.cpp b/rsContext.cpp
index 4752b35..6940033 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -241,6 +241,10 @@
     return true;
 }
 
+void Context::setupProgramStore() {
+    mFragmentStore->setupGL2(this, &mStateFragmentStore);
+}
+
 static bool getProp(const char *str)
 {
     char buf[PROPERTY_VALUE_MAX];
diff --git a/rsContext.h b/rsContext.h
index f90e4af..dabe196 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -118,6 +118,7 @@
     Font * getFont() {return mFont.get();}
 
     bool setupCheck();
+    void setupProgramStore();
     bool checkDriver() const {return mEGL.mSurface != 0;}
 
     void pause();
diff --git a/rsProgram.cpp b/rsProgram.cpp
index 2531a9b..10e00e6 100644
--- a/rsProgram.cpp
+++ b/rsProgram.cpp
@@ -115,6 +115,14 @@
 
 Program::~Program()
 {
+    if(mRSC->props.mLogShaders) {
+        LOGV("Program::~Program with shader id %u", mShaderID);
+    }
+
+    if(mShaderID) {
+        glDeleteShader(mShaderID);
+    }
+
     for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
         bindAllocation(NULL, NULL, ct);
     }
diff --git a/rsProgramFragment.cpp b/rsProgramFragment.cpp
index 275a1df..c94f294 100644
--- a/rsProgramFragment.cpp
+++ b/rsProgramFragment.cpp
@@ -49,6 +49,9 @@
 
 ProgramFragment::~ProgramFragment()
 {
+    if(mShaderID) {
+        mRSC->mShaderCache.cleanupFragment(mShaderID);
+    }
 }
 
 void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b, float a)
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index bd12989..d3dbfb2 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -45,15 +45,9 @@
 
 ProgramVertex::~ProgramVertex()
 {
-}
-
-static void logMatrix(const char *txt, const float *f)
-{
-    LOGV("Matrix %s, %p", txt, f);
-    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[0], f[4], f[8], f[12]);
-    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[1], f[5], f[9], f[13]);
-    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[2], f[6], f[10], f[14]);
-    LOGV("%6.4f, %6.4f, %6.4f, %6.4f", f[3], f[7], f[11], f[15]);
+    if(mShaderID) {
+        mRSC->mShaderCache.cleanupVertex(mShaderID);
+    }
 }
 
 void ProgramVertex::loadShader(Context *rsc) {
diff --git a/rsScriptC_LibGL.cpp b/rsScriptC_LibGL.cpp
index 7fd6406..88db761 100644
--- a/rsScriptC_LibGL.cpp
+++ b/rsScriptC_LibGL.cpp
@@ -319,9 +319,7 @@
 static void SC_ClearColor(float r, float g, float b, float a)
 {
     GET_TLS();
-    if (!rsc->setupCheck()) {
-        return;
-    }
+    rsc->setupProgramStore();
 
     glClearColor(r, g, b, a);
     glClear(GL_COLOR_BUFFER_BIT);
@@ -330,9 +328,7 @@
 static void SC_ClearDepth(float v)
 {
     GET_TLS();
-    if (!rsc->setupCheck()) {
-        return;
-    }
+    rsc->setupProgramStore();
 
     glClearDepthf(v);
     glClear(GL_DEPTH_BUFFER_BIT);
diff --git a/rsShaderCache.cpp b/rsShaderCache.cpp
index 28e3b1d..45f6207 100644
--- a/rsShaderCache.cpp
+++ b/rsShaderCache.cpp
@@ -29,20 +29,15 @@
 
 ShaderCache::ShaderCache()
 {
-    mEntryCount = 0;
-    mEntryAllocationCount = 16;
-    mEntries = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t));
+    mEntries.setCapacity(16);
 }
 
 ShaderCache::~ShaderCache()
 {
-    for (uint32_t ct=0; ct < mEntryCount; ct++) {
-        glDeleteProgram(mEntries[ct].program);
+    for (uint32_t ct=0; ct < mEntries.size(); ct++) {
+        glDeleteProgram(mEntries[ct]->program);
+        free(mEntries[ct]);
     }
-
-    mEntryCount = 0;
-    mEntryAllocationCount = 0;
-    free(mEntries);
 }
 
 bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag)
@@ -59,44 +54,30 @@
         return false;
     }
     //LOGV("ShaderCache lookup  vtx %i, frag %i", vtx->getShaderID(), frag->getShaderID());
+    uint32_t entryCount = mEntries.size();
+    for(uint32_t ct = 0; ct < entryCount; ct ++) {
+        if ((mEntries[ct]->vtx == vtx->getShaderID()) &&
+            (mEntries[ct]->frag == frag->getShaderID())) {
 
-    for (uint32_t ct=0; ct < mEntryCount; ct++) {
-        if ((mEntries[ct].vtx == vtx->getShaderID()) &&
-            (mEntries[ct].frag == frag->getShaderID())) {
-
-            //LOGV("SC using program %i", mEntries[ct].program);
-            glUseProgram(mEntries[ct].program);
-            mCurrent = &mEntries[ct];
+            //LOGV("SC using program %i", mEntries[ct]->program);
+            glUseProgram(mEntries[ct]->program);
+            mCurrent = mEntries[ct];
             //LOGV("ShaderCache hit, using %i", ct);
             rsc->checkError("ShaderCache::lookup (hit)");
             return true;
         }
     }
-    // Not in cache, add it.
 
-    if (mEntryAllocationCount == mEntryCount) {
-        // Out of space, make some.
-        mEntryAllocationCount *= 2;
-        entry_t *e = (entry_t *)calloc(mEntryAllocationCount, sizeof(entry_t));
-        if (!e) {
-            LOGE("Out of memory for ShaderCache::lookup");
-            return false;
-        }
-        memcpy(e, mEntries, sizeof(entry_t) * mEntryCount);
-        free(mEntries);
-        mEntries = e;
-    }
-
-    //LOGV("ShaderCache miss, using %i", mEntryCount);
+    //LOGV("ShaderCache miss");
     //LOGE("e0 %x", glGetError());
-
-    entry_t *e = &mEntries[mEntryCount];
+    entry_t *e = (entry_t *)malloc(sizeof(entry_t));
+    mEntries.push(e);
     mCurrent = e;
     e->vtx = vtx->getShaderID();
     e->frag = frag->getShaderID();
     e->program = glCreateProgram();
     e->vtxAttrCount = vtx->getAttribCount();
-    if (mEntries[mEntryCount].program) {
+    if (e->program) {
         GLuint pgm = e->program;
         glAttachShader(pgm, vtx->getShaderID());
         //LOGE("e1 %x", glGetError());
@@ -155,7 +136,6 @@
     e->mIsValid = true;
     //LOGV("SC made program %i", e->program);
     glUseProgram(e->program);
-    mEntryCount++;
     rsc->checkError("ShaderCache::lookup (miss)");
     return true;
 }
@@ -171,10 +151,32 @@
 
 void ShaderCache::cleanupVertex(uint32_t id)
 {
+    int32_t numEntries = (int32_t)mEntries.size();
+    for(int32_t ct = 0; ct < numEntries; ct ++) {
+        if (mEntries[ct]->vtx == id) {
+            glDeleteProgram(mEntries[ct]->program);
+
+            free(mEntries[ct]);
+            mEntries.removeAt(ct);
+            numEntries = (int32_t)mEntries.size();
+            ct --;
+        }
+    }
 }
 
 void ShaderCache::cleanupFragment(uint32_t id)
 {
+    int32_t numEntries = (int32_t)mEntries.size();
+    for(int32_t ct = 0; ct < numEntries; ct ++) {
+        if (mEntries[ct]->frag == id) {
+            glDeleteProgram(mEntries[ct]->program);
+
+            free(mEntries[ct]);
+            mEntries.removeAt(ct);
+            numEntries = (int32_t)mEntries.size();
+            ct --;
+        }
+    }
 }
 
 void ShaderCache::cleanupAll()
diff --git a/rsShaderCache.h b/rsShaderCache.h
index 312c251..35ff95b 100644
--- a/rsShaderCache.h
+++ b/rsShaderCache.h
@@ -58,11 +58,12 @@
         int32_t mFragUniformSlots[Program::MAX_UNIFORMS];
         bool mIsValid;
     } entry_t;
-    entry_t *mEntries;
+    //entry_t *mEntries;
+    Vector<entry_t*> mEntries;
     entry_t *mCurrent;
 
-    uint32_t mEntryCount;
-    uint32_t mEntryAllocationCount;
+    /*uint32_t mEntryCount;
+    uint32_t mEntryAllocationCount;*/
 
 };