rsProgramFragment.cpp revision f0c1df480304a72ce41e7d4b088319cbd7f0938a
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ANDROID_RS_BUILD_FOR_HOST 18#include "rsContext.h" 19#include <GLES/gl.h> 20#include <GLES/glext.h> 21#include <GLES2/gl2.h> 22#include <GLES2/gl2ext.h> 23#else 24#include "rsContextHostStub.h" 25#include <OpenGL/gl.h> 26#include <OpenGL/glext.h> 27#endif //ANDROID_RS_BUILD_FOR_HOST 28 29#include "rsProgramFragment.h" 30 31using namespace android; 32using namespace android::renderscript; 33 34ProgramFragment::ProgramFragment(Context *rsc, const char * shaderText, 35 uint32_t shaderLength, const uint32_t * params, 36 uint32_t paramLength) : 37 Program(rsc, shaderText, shaderLength, params, paramLength) 38{ 39 mConstantColor[0] = 1.f; 40 mConstantColor[1] = 1.f; 41 mConstantColor[2] = 1.f; 42 mConstantColor[3] = 1.f; 43 44 init(rsc); 45} 46 47ProgramFragment::~ProgramFragment() 48{ 49 if(mShaderID) { 50 mRSC->mShaderCache.cleanupFragment(mShaderID); 51 } 52} 53 54void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b, float a) 55{ 56 if(isUserProgram()) { 57 LOGE("Attempting to set fixed function emulation color on user program"); 58 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set fixed function emulation color on user program"); 59 return; 60 } 61 if(mConstants[0].get() == NULL) { 62 LOGE("Unable to set fixed function emulation color because allocation is missing"); 63 rsc->setError(RS_ERROR_BAD_SHADER, "Unable to set fixed function emulation color because allocation is missing"); 64 return; 65 } 66 mConstantColor[0] = r; 67 mConstantColor[1] = g; 68 mConstantColor[2] = b; 69 mConstantColor[3] = a; 70 memcpy(mConstants[0]->getPtr(), mConstantColor, 4*sizeof(float)); 71 mDirty = true; 72} 73 74void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state, ShaderCache *sc) 75{ 76 //LOGE("sgl2 frag1 %x", glGetError()); 77 if ((state->mLast.get() == this) && !mDirty) { 78 return; 79 } 80 state->mLast.set(this); 81 82 rsc->checkError("ProgramFragment::setupGL2 start"); 83 84 rsc->checkError("ProgramFragment::setupGL2 begin uniforms"); 85 setupUserConstants(rsc, sc, true); 86 87 uint32_t numTexturesToBind = mTextureCount; 88 uint32_t numTexturesAvailable = rsc->getMaxFragmentTextures(); 89 if(numTexturesToBind >= numTexturesAvailable) { 90 LOGE("Attempting to bind %u textures on shader id %u, but only %u are available", 91 mTextureCount, (uint32_t)this, numTexturesAvailable); 92 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind more textuers than available"); 93 numTexturesToBind = numTexturesAvailable; 94 } 95 96 for (uint32_t ct=0; ct < numTexturesToBind; ct++) { 97 glActiveTexture(GL_TEXTURE0 + ct); 98 if (!mTextures[ct].get()) { 99 LOGE("No texture bound for shader id %u, texture unit %u", (uint)this, ct); 100 rsc->setError(RS_ERROR_BAD_SHADER, "No texture bound"); 101 continue; 102 } 103 104 mTextures[ct]->uploadCheck(rsc); 105 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID()); 106 rsc->checkError("ProgramFragment::setupGL2 tex bind"); 107 if (mSamplers[ct].get()) { 108 mSamplers[ct]->setupGL(rsc, mTextures[ct].get()); 109 } else { 110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 114 rsc->checkError("ProgramFragment::setupGL2 tex env"); 115 } 116 117 glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct); 118 rsc->checkError("ProgramFragment::setupGL2 uniforms"); 119 } 120 121 glActiveTexture(GL_TEXTURE0); 122 mDirty = false; 123 rsc->checkError("ProgramFragment::setupGL2"); 124} 125 126void ProgramFragment::loadShader(Context *rsc) { 127 Program::loadShader(rsc, GL_FRAGMENT_SHADER); 128} 129 130void ProgramFragment::createShader() 131{ 132 if (mUserShader.length() > 1) { 133 mShader.append("precision mediump float;\n"); 134 appendUserConstants(); 135 char buf[256]; 136 for (uint32_t ct=0; ct < mTextureCount; ct++) { 137 sprintf(buf, "uniform sampler2D UNI_Tex%i;\n", ct); 138 mShader.append(buf); 139 } 140 mShader.append(mUserShader); 141 } else { 142 LOGE("ProgramFragment::createShader cannot create program, shader code not defined"); 143 rsAssert(0); 144 } 145} 146 147void ProgramFragment::init(Context *rsc) 148{ 149 mUniformCount = 0; 150 if (mUserShader.size() > 0) { 151 for (uint32_t ct=0; ct < mConstantCount; ct++) { 152 initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, RS_SHADER_UNI); 153 } 154 } 155 mTextureUniformIndexStart = mUniformCount; 156 char buf[256]; 157 for (uint32_t ct=0; ct < mTextureCount; ct++) { 158 sprintf(buf, "UNI_Tex%i", ct); 159 mUniformNames[mUniformCount++].setTo(buf); 160 } 161 162 createShader(); 163} 164 165void ProgramFragment::serialize(OStream *stream) const 166{ 167 168} 169 170ProgramFragment *ProgramFragment::createFromStream(Context *rsc, IStream *stream) 171{ 172 return NULL; 173} 174 175ProgramFragmentState::ProgramFragmentState() 176{ 177 mPF = NULL; 178} 179 180ProgramFragmentState::~ProgramFragmentState() 181{ 182 ObjectBase::checkDelete(mPF); 183 mPF = NULL; 184} 185 186void ProgramFragmentState::init(Context *rsc) 187{ 188 String8 shaderString(RS_SHADER_INTERNAL); 189 shaderString.append("varying lowp vec4 varColor;\n"); 190 shaderString.append("varying vec2 varTex0;\n"); 191 shaderString.append("void main() {\n"); 192 shaderString.append(" lowp vec4 col = UNI_Color;\n"); 193 shaderString.append(" gl_FragColor = col;\n"); 194 shaderString.append("}\n"); 195 196 const Element *colorElem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 197 rsc->mStateElement.elementBuilderBegin(); 198 rsc->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 199 const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc); 200 201 Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false); 202 203 uint32_t tmp[4]; 204 tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 205 tmp[1] = (uint32_t)inputType; 206 tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT; 207 tmp[3] = 0; 208 209 Allocation *constAlloc = new Allocation(rsc, inputType); 210 ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(), 211 shaderString.length(), tmp, 4); 212 pf->bindAllocation(rsc, constAlloc, 0); 213 pf->setConstantColor(rsc, 1.0f, 1.0f, 1.0f, 1.0f); 214 215 mDefault.set(pf); 216} 217 218void ProgramFragmentState::deinit(Context *rsc) 219{ 220 mDefault.clear(); 221 mLast.clear(); 222} 223 224 225namespace android { 226namespace renderscript { 227 228RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc, const char * shaderText, 229 uint32_t shaderLength, const uint32_t * params, 230 uint32_t paramLength) 231{ 232 ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength); 233 pf->incUserRef(); 234 //LOGE("rsi_ProgramFragmentCreate %p", pf); 235 return pf; 236} 237 238} 239} 240 241