diff options
Diffstat (limited to 'libs/rs/rsProgram.cpp')
-rw-r--r-- | libs/rs/rsProgram.cpp | 227 |
1 files changed, 219 insertions, 8 deletions
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp index 5f2a609..656a3c3 100644 --- a/libs/rs/rsProgram.cpp +++ b/libs/rs/rsProgram.cpp @@ -17,34 +17,245 @@ #include "rsContext.h" #include "rsProgram.h" +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + using namespace android; using namespace android::renderscript; -Program::Program(Context *rsc, Element *in, Element *out) : ObjectBase(rsc) +Program::Program(Context *rsc) : ObjectBase(rsc) { mAllocFile = __FILE__; mAllocLine = __LINE__; + mDirty = true; + mShaderID = 0; + mAttribCount = 0; + mUniformCount = 0; + + mInputElements = NULL; + mOutputElements = NULL; + mConstantTypes = NULL; + mInputCount = 0; + mOutputCount = 0; + mConstantCount = 0; +} + +Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength, + const uint32_t * params, uint32_t paramLength) : + ObjectBase(rsc) +{ + mAllocFile = __FILE__; + mAllocLine = __LINE__; + mDirty = true; + mShaderID = 0; + mAttribCount = 0; + mUniformCount = 0; + mTextureCount = 0; - mElementIn.set(in); - mElementOut.set(out); + mInputCount = 0; + mOutputCount = 0; + mConstantCount = 0; + + 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++; + } + if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { + mConstantCount++; + } + if (params[ct] == RS_PROGRAM_PARAM_TEXTURE_COUNT) { + mTextureCount = params[ct+1]; + } + } + + mInputElements = new ObjectBaseRef<Element>[mInputCount]; + mOutputElements = new ObjectBaseRef<Element>[mOutputCount]; + mConstantTypes = new ObjectBaseRef<Type>[mConstantCount]; + + uint32_t input = 0; + uint32_t output = 0; + uint32_t constant = 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])); + } + if (params[ct] == RS_PROGRAM_PARAM_CONSTANT) { + mConstantTypes[constant++].set(reinterpret_cast<Type *>(params[ct+1])); + } + } + mUserShader.setTo(shaderText, shaderLength); } Program::~Program() { + for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) { + bindAllocation(NULL, ct); + } + + delete[] mInputElements; + delete[] mOutputElements; + delete[] mConstantTypes; + mInputCount = 0; + mOutputCount = 0; + mConstantCount = 0; +} + + +void Program::bindAllocation(Allocation *alloc, uint32_t slot) +{ + if (mConstants[slot].get() == alloc) { + return; + } + if (mConstants[slot].get()) { + mConstants[slot].get()->removeProgramToDirty(this); + } + mConstants[slot].set(alloc); + if (alloc) { + alloc->addProgramToDirty(this); + } + mDirty = true; } +void Program::bindTexture(uint32_t slot, Allocation *a) +{ + if (slot >= MAX_TEXTURE) { + LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE"); + return; + } + + //LOGE("bindtex %i %p", slot, a); + mTextures[slot].set(a); + mDirty = true; +} -void Program::bindAllocation(Allocation *alloc) +void Program::bindSampler(uint32_t slot, Sampler *s) { - mConstants.set(alloc); + if (slot >= MAX_TEXTURE) { + LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE"); + return; + } + + mSamplers[slot].set(s); mDirty = true; } -void Program::checkUpdatedAllocation(const Allocation *alloc) +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) { - if (mConstants.get() == alloc) { - mDirty = true; + mShaderID = glCreateShader(type); + rsAssert(mShaderID); + + if (rsc->props.mLogShaders) { + LOGV("Loading shader type %x, ID %i", type, mShaderID); + LOGV(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; + return false; + } + } + } + + if (rsc->props.mLogShaders) { + LOGV("--Shader load result %x ", glGetError()); + } + return true; +} + +void Program::setShader(const char *txt, uint32_t len) +{ + mUserShader.setTo(txt, len); +} + + + +namespace android { +namespace renderscript { + + +void rsi_ProgramBindConstants(Context *rsc, RsProgram vp, uint32_t slot, RsAllocation constants) +{ + Program *p = static_cast<Program *>(vp); + p->bindAllocation(static_cast<Allocation *>(constants), slot); +} + +void rsi_ProgramBindTexture(Context *rsc, RsProgram vpf, uint32_t slot, RsAllocation a) +{ + Program *p = static_cast<Program *>(vpf); + p->bindTexture(slot, static_cast<Allocation *>(a)); +} + +void rsi_ProgramBindSampler(Context *rsc, RsProgram vpf, uint32_t slot, RsSampler s) +{ + Program *p = static_cast<Program *>(vpf); + p->bindSampler(slot, static_cast<Sampler *>(s)); +} + +} } |