Moving renderscript GL code into the HAL
This change affects
 - shaders
 - meshes
 - fonts
 - quad rendering

Change-Id: I2a53acb4cd1fa8f4c6e67668f6ee969f3d7f7aa1
diff --git a/rsProgram.cpp b/rsProgram.cpp
index 4ef05bf..28fa061 100644
--- a/rsProgram.cpp
+++ b/rsProgram.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,11 +15,6 @@
  */
 
 #include "rsContext.h"
-#ifndef ANDROID_RS_SERIALIZE
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#endif //ANDROID_RS_SERIALIZE
-
 #include "rsProgram.h"
 
 using namespace android;
@@ -36,26 +31,22 @@
     initMemberVars();
     for (uint32_t ct=0; ct < paramLength; ct+=2) {
         if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
-            mInputCount++;
-        }
-        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
-            mOutputCount++;
+            mHal.state.inputElementsCount++;
         }
         if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
-            mConstantCount++;
+            mHal.state.constantsCount++;
         }
         if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
-            mTextureCount++;
+            mHal.state.texturesCount++;
         }
     }
 
-    mTextures = new ObjectBaseRef<Allocation>[mTextureCount];
-    mSamplers = new ObjectBaseRef<Sampler>[mTextureCount];
-    mTextureTargets = new RsTextureTarget[mTextureCount];
-    mInputElements = new ObjectBaseRef<Element>[mInputCount];
-    mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
-    mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
-    mConstants = new ObjectBaseRef<Allocation>[mConstantCount];
+    mHal.state.textures = new ObjectBaseRef<Allocation>[mHal.state.texturesCount];
+    mHal.state.samplers = new ObjectBaseRef<Sampler>[mHal.state.texturesCount];
+    mHal.state.textureTargets = new RsTextureTarget[mHal.state.texturesCount];
+    mHal.state.inputElements = new ObjectBaseRef<Element>[mHal.state.inputElementsCount];
+    mHal.state.constantTypes = new ObjectBaseRef<Type>[mHal.state.constantsCount];
+    mHal.state.constants = new ObjectBaseRef<Allocation>[mHal.state.constantsCount];
 
     uint32_t input = 0;
     uint32_t output = 0;
@@ -63,16 +54,13 @@
     uint32_t texture = 0;
     for (uint32_t ct=0; ct < paramLength; ct+=2) {
         if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
-            mInputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
-        }
-        if (params[ct] == RS_PROGRAM_PARAM_OUTPUT) {
-            mOutputElements[output++].set(reinterpret_cast<Element *>(params[ct+1]));
+            mHal.state.inputElements[input++].set(reinterpret_cast<Element *>(params[ct+1]));
         }
         if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) {
-            mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
+            mHal.state.constantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1]));
         }
         if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_TYPE) {
-            mTextureTargets[texture++] = (RsTextureTarget)params[ct+1];
+            mHal.state.textureTargets[texture++] = (RsTextureTarget)params[ct+1];
         }
     }
     mIsInternal = false;
@@ -84,88 +72,69 @@
         shaderLength -= internalTokenLen;
     }
     mUserShader.setTo(shaderText, shaderLength);
-
-    initAttribAndUniformArray();
 }
 
 Program::~Program() {
-    if (mRSC->props.mLogShaders) {
-        LOGV("Program::~Program with shader id %u", mShaderID);
-    }
 
-    if (mShaderID) {
-        glDeleteShader(mShaderID);
-    }
-
-    for (uint32_t ct=0; ct < mConstantCount; ct++) {
+    for (uint32_t ct=0; ct < mHal.state.constantsCount; ct++) {
         bindAllocation(NULL, NULL, ct);
     }
 
-    for (uint32_t ct=0; ct < mTextureCount; ct++) {
+    for (uint32_t ct=0; ct < mHal.state.texturesCount; ct++) {
         bindTexture(NULL, ct, NULL);
         bindSampler(NULL, ct, NULL);
     }
-    delete[] mTextures;
-    delete[] mSamplers;
-    delete[] mTextureTargets;
-    delete[] mInputElements;
-    delete[] mOutputElements;
-    delete[] mConstantTypes;
-    delete[] mConstants;
-    delete[] mAttribNames;
-    delete[] mUniformNames;
-    delete[] mUniformArraySizes;
-    mInputCount = 0;
-    mOutputCount = 0;
-    mConstantCount = 0;
+    delete[] mHal.state.textures;
+    delete[] mHal.state.samplers;
+    delete[] mHal.state.textureTargets;
+    delete[] mHal.state.inputElements;
+    delete[] mHal.state.constantTypes;
+    delete[] mHal.state.constants;
+    mHal.state.inputElementsCount = 0;
+    mHal.state.constantsCount = 0;
+    mHal.state.texturesCount = 0;
 }
 
 void Program::initMemberVars() {
     mDirty = true;
-    mShaderID = 0;
-    mAttribCount = 0;
-    mUniformCount = 0;
-    mTextureCount = 0;
 
-    mTextures = NULL;
-    mSamplers = NULL;
-    mTextureTargets = NULL;
-    mInputElements = NULL;
-    mOutputElements = NULL;
-    mConstantTypes = NULL;
-    mConstants = NULL;
-    mAttribNames = NULL;
-    mUniformNames = NULL;
-    mUniformArraySizes = NULL;
-    mInputCount = 0;
-    mOutputCount = 0;
-    mConstantCount = 0;
-    mIsValid = false;
+    mHal.drv = NULL;
+    mHal.state.textures = NULL;
+    mHal.state.samplers = NULL;
+    mHal.state.textureTargets = NULL;
+    mHal.state.inputElements = NULL;
+    mHal.state.constantTypes = NULL;
+    mHal.state.constants = NULL;
+
+    mHal.state.inputElementsCount = 0;
+    mHal.state.constantsCount = 0;
+    mHal.state.texturesCount = 0;
+
     mIsInternal = false;
 }
 
 void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot) {
     if (alloc != NULL) {
-        if (slot >= mConstantCount) {
+        if (slot >= mHal.state.constantsCount) {
             LOGE("Attempt to bind alloc at slot %u, on shader id %u, but const count is %u",
-                 slot, (uint32_t)this, mConstantCount);
+                 slot, (uint32_t)this, mHal.state.constantsCount);
             rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
             return;
         }
-        if (!alloc->getType()->isEqual(mConstantTypes[slot].get())) {
+        if (!alloc->getType()->isEqual(mHal.state.constantTypes[slot].get())) {
             LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch",
                  slot, (uint32_t)this);
             rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
             return;
         }
     }
-    if (mConstants[slot].get() == alloc) {
+    if (mHal.state.constants[slot].get() == alloc) {
         return;
     }
-    if (mConstants[slot].get()) {
-        mConstants[slot].get()->removeProgramToDirty(this);
+    if (mHal.state.constants[slot].get()) {
+        mHal.state.constants[slot].get()->removeProgramToDirty(this);
     }
-    mConstants[slot].set(alloc);
+    mHal.state.constants[slot].set(alloc);
     if (alloc) {
         alloc->addProgramToDirty(this);
     }
@@ -173,327 +142,38 @@
 }
 
 void Program::bindTexture(Context *rsc, uint32_t slot, Allocation *a) {
-    if (slot >= mTextureCount) {
-        LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mTextureCount);
+    if (slot >= mHal.state.texturesCount) {
+        LOGE("Attempt to bind texture to slot %u but tex count is %u", slot, mHal.state.texturesCount);
         rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind texture");
         return;
     }
 
-    if (a && a->getType()->getDimFaces() && mTextureTargets[slot] != RS_TEXTURE_CUBE) {
+    if (a && a->getType()->getDimFaces() && mHal.state.textureTargets[slot] != RS_TEXTURE_CUBE) {
         LOGE("Attempt to bind cubemap to slot %u but 2d texture needed", slot);
         rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind cubemap to 2d texture slot");
         return;
     }
 
     //LOGE("bindtex %i %p", slot, a);
-    mTextures[slot].set(a);
+    mHal.state.textures[slot].set(a);
     mDirty = true;
 }
 
 void Program::bindSampler(Context *rsc, uint32_t slot, Sampler *s) {
-    if (slot >= mTextureCount) {
-        LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mTextureCount);
+    if (slot >= mHal.state.texturesCount) {
+        LOGE("Attempt to bind sampler to slot %u but tex count is %u", slot, mHal.state.texturesCount);
         rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind sampler");
         return;
     }
 
-    mSamplers[slot].set(s);
+    mHal.state.samplers[slot].set(s);
     mDirty = true;
 }
 
-String8 Program::getGLSLInputString() const {
-    String8 s;
-    for (uint32_t ct=0; ct < mInputCount; ct++) {
-        const Element *e = mInputElements[ct].get();
-        for (uint32_t field=0; field < e->getFieldCount(); field++) {
-            const Element *f = e->getField(field);
-
-            // Cannot be complex
-            rsAssert(!f->getFieldCount());
-            switch (f->getComponent().getVectorSize()) {
-            case 1: s.append("attribute float ATTRIB_"); break;
-            case 2: s.append("attribute vec2 ATTRIB_"); break;
-            case 3: s.append("attribute vec3 ATTRIB_"); break;
-            case 4: s.append("attribute vec4 ATTRIB_"); break;
-            default:
-                rsAssert(0);
-            }
-
-            s.append(e->getFieldName(field));
-            s.append(";\n");
-        }
-    }
-    return s;
-}
-
-String8 Program::getGLSLOutputString() const {
-    return String8();
-}
-
-String8 Program::getGLSLConstantString() const {
-    return String8();
-}
-
-void Program::createShader() {
-}
-
-bool Program::loadShader(Context *rsc, uint32_t type) {
-    mShaderID = glCreateShader(type);
-    rsAssert(mShaderID);
-
-    if (rsc->props.mLogShaders) {
-        LOGV("Loading shader type %x, ID %i", type, mShaderID);
-        LOGV("%s", mShader.string());
-    }
-
-    if (mShaderID) {
-        const char * ss = mShader.string();
-        glShaderSource(mShaderID, 1, &ss, NULL);
-        glCompileShader(mShaderID);
-
-        GLint compiled = 0;
-        glGetShaderiv(mShaderID, GL_COMPILE_STATUS, &compiled);
-        if (!compiled) {
-            GLint infoLen = 0;
-            glGetShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLen);
-            if (infoLen) {
-                char* buf = (char*) malloc(infoLen);
-                if (buf) {
-                    glGetShaderInfoLog(mShaderID, infoLen, NULL, buf);
-                    LOGE("Could not compile shader \n%s\n", buf);
-                    free(buf);
-                }
-                glDeleteShader(mShaderID);
-                mShaderID = 0;
-                rsc->setError(RS_ERROR_BAD_SHADER, "Error returned from GL driver loading shader text,");
-                return false;
-            }
-        }
-    }
-
-    if (rsc->props.mLogShaders) {
-        LOGV("--Shader load result %x ", glGetError());
-    }
-    mIsValid = true;
-    return true;
-}
-
 void Program::setShader(const char *txt, uint32_t len) {
     mUserShader.setTo(txt, len);
 }
 
-void Program::appendUserConstants() {
-    for (uint32_t ct=0; ct < mConstantCount; ct++) {
-        const Element *e = mConstantTypes[ct]->getElement();
-        for (uint32_t field=0; field < e->getFieldCount(); field++) {
-            const Element *f = e->getField(field);
-            const char *fn = e->getFieldName(field);
-
-            if (fn[0] == '#') {
-                continue;
-            }
-
-            // Cannot be complex
-            rsAssert(!f->getFieldCount());
-            if (f->getType() == RS_TYPE_MATRIX_4X4) {
-                mShader.append("uniform mat4 UNI_");
-            } else if (f->getType() == RS_TYPE_MATRIX_3X3) {
-                mShader.append("uniform mat3 UNI_");
-            } else if (f->getType() == RS_TYPE_MATRIX_2X2) {
-                mShader.append("uniform mat2 UNI_");
-            } else {
-                switch (f->getComponent().getVectorSize()) {
-                case 1: mShader.append("uniform float UNI_"); break;
-                case 2: mShader.append("uniform vec2 UNI_"); break;
-                case 3: mShader.append("uniform vec3 UNI_"); break;
-                case 4: mShader.append("uniform vec4 UNI_"); break;
-                default:
-                    rsAssert(0);
-                }
-            }
-
-            mShader.append(fn);
-            if (e->getFieldArraySize(field) > 1) {
-                mShader.appendFormat("[%d]", e->getFieldArraySize(field));
-            }
-            mShader.append(";\n");
-        }
-    }
-}
-
-void Program::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
-    RsDataType dataType = field->getType();
-    uint32_t elementSize = field->getSizeBytes() / sizeof(float);
-    for (uint32_t i = 0; i < arraySize; i ++) {
-        if (arraySize > 1) {
-            LOGV("Array Element [%u]", i);
-        }
-        if (dataType == RS_TYPE_MATRIX_4X4) {
-            LOGV("Matrix4x4");
-            LOGV("{%f, %f, %f, %f",  fd[0], fd[4], fd[8], fd[12]);
-            LOGV(" %f, %f, %f, %f",  fd[1], fd[5], fd[9], fd[13]);
-            LOGV(" %f, %f, %f, %f",  fd[2], fd[6], fd[10], fd[14]);
-            LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
-        } else if (dataType == RS_TYPE_MATRIX_3X3) {
-            LOGV("Matrix3x3");
-            LOGV("{%f, %f, %f",  fd[0], fd[3], fd[6]);
-            LOGV(" %f, %f, %f",  fd[1], fd[4], fd[7]);
-            LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
-        } else if (dataType == RS_TYPE_MATRIX_2X2) {
-            LOGV("Matrix2x2");
-            LOGV("{%f, %f",  fd[0], fd[2]);
-            LOGV(" %f, %f}", fd[1], fd[3]);
-        } else {
-            switch (field->getComponent().getVectorSize()) {
-            case 1:
-                LOGV("Uniform 1 = %f", fd[0]);
-                break;
-            case 2:
-                LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
-                break;
-            case 3:
-                LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
-                break;
-            case 4:
-                LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
-                break;
-            default:
-                rsAssert(0);
-            }
-        }
-        LOGE("Element size %u data=%p", elementSize, fd);
-        fd += elementSize;
-        LOGE("New data=%p", fd);
-    }
-}
-
-void Program::setUniform(Context *rsc, const Element *field, const float *fd,
-                         int32_t slot, uint32_t arraySize ) {
-    RsDataType dataType = field->getType();
-    if (dataType == RS_TYPE_MATRIX_4X4) {
-        glUniformMatrix4fv(slot, arraySize, GL_FALSE, fd);
-    } else if (dataType == RS_TYPE_MATRIX_3X3) {
-        glUniformMatrix3fv(slot, arraySize, GL_FALSE, fd);
-    } else if (dataType == RS_TYPE_MATRIX_2X2) {
-        glUniformMatrix2fv(slot, arraySize, GL_FALSE, fd);
-    } else {
-        switch (field->getComponent().getVectorSize()) {
-        case 1:
-            glUniform1fv(slot, arraySize, fd);
-            break;
-        case 2:
-            glUniform2fv(slot, arraySize, fd);
-            break;
-        case 3:
-            glUniform3fv(slot, arraySize, fd);
-            break;
-        case 4:
-            glUniform4fv(slot, arraySize, fd);
-            break;
-        default:
-            rsAssert(0);
-        }
-    }
-}
-
-void Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment) {
-    uint32_t uidx = 0;
-    for (uint32_t ct=0; ct < mConstantCount; ct++) {
-        Allocation *alloc = mConstants[ct].get();
-        if (!alloc) {
-            LOGE("Attempting to set constants on shader id %u, but alloc at slot %u is not set", (uint32_t)this, ct);
-            rsc->setError(RS_ERROR_BAD_SHADER, "No constant allocation bound");
-            continue;
-        }
-
-        const uint8_t *data = static_cast<const uint8_t *>(alloc->getPtr());
-        const Element *e = mConstantTypes[ct]->getElement();
-        for (uint32_t field=0; field < e->getFieldCount(); field++) {
-            const Element *f = e->getField(field);
-            const char *fieldName = e->getFieldName(field);
-            // If this field is padding, skip it
-            if (fieldName[0] == '#') {
-                continue;
-            }
-
-            uint32_t offset = e->getFieldOffsetBytes(field);
-            const float *fd = reinterpret_cast<const float *>(&data[offset]);
-
-            int32_t slot = -1;
-            uint32_t arraySize = 1;
-            if (!isFragment) {
-                slot = sc->vtxUniformSlot(uidx);
-                arraySize = sc->vtxUniformSize(uidx);
-            } else {
-                slot = sc->fragUniformSlot(uidx);
-                arraySize = sc->fragUniformSize(uidx);
-            }
-            if (rsc->props.mLogShadersUniforms) {
-                LOGV("Uniform  slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
-            }
-            uidx ++;
-            if (slot < 0) {
-                continue;
-            }
-
-            if (rsc->props.mLogShadersUniforms) {
-                logUniform(f, fd, arraySize);
-            }
-            setUniform(rsc, f, fd, slot, arraySize);
-        }
-    }
-}
-
-void Program::initAttribAndUniformArray() {
-    mAttribCount = 0;
-    for (uint32_t ct=0; ct < mInputCount; ct++) {
-        const Element *elem = mInputElements[ct].get();
-        for (uint32_t field=0; field < elem->getFieldCount(); field++) {
-            if (elem->getFieldName(field)[0] != '#') {
-                mAttribCount ++;
-            }
-        }
-    }
-
-    mUniformCount = 0;
-    for (uint32_t ct=0; ct < mConstantCount; ct++) {
-        const Element *elem = mConstantTypes[ct]->getElement();
-
-        for (uint32_t field=0; field < elem->getFieldCount(); field++) {
-            if (elem->getFieldName(field)[0] != '#') {
-                mUniformCount ++;
-            }
-        }
-    }
-    mUniformCount += mTextureCount;
-
-    if (mAttribCount) {
-        mAttribNames = new String8[mAttribCount];
-    }
-    if (mUniformCount) {
-        mUniformNames = new String8[mUniformCount];
-        mUniformArraySizes = new uint32_t[mUniformCount];
-    }
-}
-
-void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix) {
-    rsAssert(e->getFieldCount());
-    for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
-        const Element *ce = e->getField(ct);
-        if (ce->getFieldCount()) {
-            initAddUserElement(ce, names, arrayLengths, count, prefix);
-        } else if (e->getFieldName(ct)[0] != '#') {
-            String8 tmp(prefix);
-            tmp.append(e->getFieldName(ct));
-            names[*count].setTo(tmp.string());
-            if (arrayLengths) {
-                arrayLengths[*count] = e->getFieldArraySize(ct);
-            }
-            (*count)++;
-        }
-    }
-}
-
 namespace android {
 namespace renderscript {