diff options
Diffstat (limited to 'libs/rs/driver/rsdShader.cpp')
| -rw-r--r-- | libs/rs/driver/rsdShader.cpp | 126 |
1 files changed, 91 insertions, 35 deletions
diff --git a/libs/rs/driver/rsdShader.cpp b/libs/rs/driver/rsdShader.cpp index 1e73b95..6d9fa90 100644 --- a/libs/rs/driver/rsdShader.cpp +++ b/libs/rs/driver/rsdShader.cpp @@ -39,34 +39,81 @@ RsdShader::RsdShader(const Program *p, uint32_t type, initMemberVars(); initAttribAndUniformArray(); init(textureNames, textureNamesCount, textureNamesLength); - createTexturesString(textureNames, textureNamesCount, textureNamesLength); + + for(size_t i=0; i < textureNamesCount; i++) { + mTextureNames.push(String8(textureNames[i], textureNamesLength[i])); + } } RsdShader::~RsdShader() { - if (mShaderID) { - glDeleteShader(mShaderID); + for (uint32_t i = 0; i < mStateBasedShaders.size(); i ++) { + StateBasedKey *state = mStateBasedShaders.itemAt(i); + if (state->mShaderID) { + glDeleteShader(state->mShaderID); + } + delete state; } delete[] mAttribNames; delete[] mUniformNames; delete[] mUniformArraySizes; - delete[] mTextureTargets; } void RsdShader::initMemberVars() { mDirty = true; - mShaderID = 0; mAttribCount = 0; mUniformCount = 0; mAttribNames = NULL; mUniformNames = NULL; mUniformArraySizes = NULL; - mTextureTargets = NULL; + mCurrentState = NULL; mIsValid = false; } +RsdShader::StateBasedKey *RsdShader::getExistingState() { + RsdShader::StateBasedKey *returnKey = NULL; + + for (uint32_t i = 0; i < mStateBasedShaders.size(); i ++) { + returnKey = mStateBasedShaders.itemAt(i); + + for (uint32_t ct = 0; ct < mRSProgram->mHal.state.texturesCount; ct ++) { + uint32_t texType = 0; + if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) { + Allocation *a = mRSProgram->mHal.state.textures[ct]; + if (a && a->mHal.state.surfaceTextureID) { + texType = GL_TEXTURE_EXTERNAL_OES; + } else { + texType = GL_TEXTURE_2D; + } + } else { + texType = GL_TEXTURE_CUBE_MAP; + } + if (texType != returnKey->mTextureTargets[ct]) { + returnKey = NULL; + break; + } + } + } + return returnKey; +} + +uint32_t RsdShader::getStateBasedShaderID(const Context *rsc) { + StateBasedKey *state = getExistingState(); + if (state != NULL) { + mCurrentState = state; + return mCurrentState->mShaderID; + } + // We have not created a shader for this particular state yet + state = new StateBasedKey(mTextureCount); + mCurrentState = state; + mStateBasedShaders.add(state); + createShader(); + loadShader(rsc); + return mCurrentState->mShaderID; +} + void RsdShader::init(const char** textureNames, size_t textureNamesCount, const size_t *textureNamesLength) { uint32_t attribCount = 0; @@ -138,70 +185,80 @@ void RsdShader::appendAttributes() { } } -void RsdShader::createTexturesString(const char** textureNames, size_t textureNamesCount, - const size_t *textureNamesLength) { - mShaderTextures.setTo(""); +void RsdShader::appendTextures() { + + // TODO: this does not yet handle cases where the texture changes between IO + // input and local + bool appendUsing = true; for (uint32_t ct = 0; ct < mRSProgram->mHal.state.texturesCount; ct ++) { if (mRSProgram->mHal.state.textureTargets[ct] == RS_TEXTURE_2D) { Allocation *a = mRSProgram->mHal.state.textures[ct]; if (a && a->mHal.state.surfaceTextureID) { - mShaderTextures.append("uniform samplerExternalOES UNI_"); + if(appendUsing) { + mShader.append("#extension GL_OES_EGL_image_external : require\n"); + appendUsing = false; + } + mShader.append("uniform samplerExternalOES UNI_"); + mCurrentState->mTextureTargets[ct] = GL_TEXTURE_EXTERNAL_OES; } else { - mShaderTextures.append("uniform sampler2D UNI_"); + mShader.append("uniform sampler2D UNI_"); + mCurrentState->mTextureTargets[ct] = GL_TEXTURE_2D; } - mTextureTargets[ct] = GL_TEXTURE_2D; } else { - mShaderTextures.append("uniform samplerCube UNI_"); - mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP; + mShader.append("uniform samplerCube UNI_"); + mCurrentState->mTextureTargets[ct] = GL_TEXTURE_CUBE_MAP; } - mShaderTextures.append(textureNames[ct], textureNamesLength[ct]); - mShaderTextures.append(";\n"); + mShader.append(mTextureNames[ct]); + mShader.append(";\n"); } } bool RsdShader::createShader() { - + mShader.clear(); if (mType == GL_FRAGMENT_SHADER) { mShader.append("precision mediump float;\n"); } appendUserConstants(); appendAttributes(); - mShader.append(mShaderTextures); - + appendTextures(); mShader.append(mUserShader); return true; } bool RsdShader::loadShader(const Context *rsc) { - mShaderID = glCreateShader(mType); - rsAssert(mShaderID); + mCurrentState->mShaderID = glCreateShader(mType); + rsAssert(mCurrentState->mShaderID); + + if(!mShader.length()) { + createShader(); + } if (rsc->props.mLogShaders) { - ALOGV("Loading shader type %x, ID %i", mType, mShaderID); + ALOGV("Loading shader type %x, ID %i", mType, mCurrentState->mShaderID); ALOGV("%s", mShader.string()); } - if (mShaderID) { + if (mCurrentState->mShaderID) { const char * ss = mShader.string(); - RSD_CALL_GL(glShaderSource, mShaderID, 1, &ss, NULL); - RSD_CALL_GL(glCompileShader, mShaderID); + RSD_CALL_GL(glShaderSource, mCurrentState->mShaderID, 1, &ss, NULL); + RSD_CALL_GL(glCompileShader, mCurrentState->mShaderID); GLint compiled = 0; - RSD_CALL_GL(glGetShaderiv, mShaderID, GL_COMPILE_STATUS, &compiled); + RSD_CALL_GL(glGetShaderiv, mCurrentState->mShaderID, GL_COMPILE_STATUS, &compiled); if (!compiled) { GLint infoLen = 0; - RSD_CALL_GL(glGetShaderiv, mShaderID, GL_INFO_LOG_LENGTH, &infoLen); + RSD_CALL_GL(glGetShaderiv, mCurrentState->mShaderID, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen) { char* buf = (char*) malloc(infoLen); if (buf) { - RSD_CALL_GL(glGetShaderInfoLog, mShaderID, infoLen, NULL, buf); + RSD_CALL_GL(glGetShaderInfoLog, mCurrentState->mShaderID, infoLen, NULL, buf); rsc->setError(RS_ERROR_FATAL_PROGRAM_LINK, buf); free(buf); } - RSD_CALL_GL(glDeleteShader, mShaderID); - mShaderID = 0; + RSD_CALL_GL(glDeleteShader, mCurrentState->mShaderID); + mCurrentState->mShaderID = 0; return false; } } @@ -418,12 +475,14 @@ void RsdShader::setupTextures(const Context *rsc, RsdShaderCache *sc) { if (!mRSProgram->mHal.state.textures[ct]) { // if nothing is bound, reset to default GL texture - RSD_CALL_GL(glBindTexture, mTextureTargets[ct], 0); + RSD_CALL_GL(glBindTexture, mCurrentState->mTextureTargets[ct], 0); continue; } DrvAllocation *drvTex = (DrvAllocation *)mRSProgram->mHal.state.textures[ct]->mHal.drv; - if (drvTex->glTarget != GL_TEXTURE_2D && drvTex->glTarget != GL_TEXTURE_CUBE_MAP) { + if (drvTex->glTarget != GL_TEXTURE_2D && + drvTex->glTarget != GL_TEXTURE_CUBE_MAP && + drvTex->glTarget != GL_TEXTURE_EXTERNAL_OES) { ALOGE("Attempting to bind unknown texture to shader id %u, texture unit %u", (uint)this, ct); rsc->setError(RS_ERROR_BAD_SHADER, "Non-texture allocation bound to a shader"); @@ -523,9 +582,6 @@ void RsdShader::initAttribAndUniformArray() { } mTextureCount = mRSProgram->mHal.state.texturesCount; - if (mTextureCount) { - mTextureTargets = new uint32_t[mTextureCount]; - } } void RsdShader::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, |
