rsProgramFragment.cpp revision 7ffcaf20cbb115326f3d72a983835d6c314a4cef
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 mAllocFile = __FILE__; 40 mAllocLine = __LINE__; 41 42 mConstantColor[0] = 1.f; 43 mConstantColor[1] = 1.f; 44 mConstantColor[2] = 1.f; 45 mConstantColor[3] = 1.f; 46 47 init(rsc); 48} 49 50ProgramFragment::~ProgramFragment() 51{ 52 if(mShaderID) { 53 mRSC->mShaderCache.cleanupFragment(mShaderID); 54 } 55} 56 57void ProgramFragment::setConstantColor(Context *rsc, float r, float g, float b, float a) 58{ 59 if(isUserProgram()) { 60 LOGE("Attempting to set fixed function emulation color on user program"); 61 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot set fixed function emulation color on user program"); 62 return; 63 } 64 if(mConstants[0].get() == NULL) { 65 LOGE("Unable to set fixed function emulation color because allocation is missing"); 66 rsc->setError(RS_ERROR_BAD_SHADER, "Unable to set fixed function emulation color because allocation is missing"); 67 return; 68 } 69 mConstantColor[0] = r; 70 mConstantColor[1] = g; 71 mConstantColor[2] = b; 72 mConstantColor[3] = a; 73 memcpy(mConstants[0]->getPtr(), mConstantColor, 4*sizeof(float)); 74 mDirty = true; 75} 76 77void ProgramFragment::setupGL2(Context *rsc, ProgramFragmentState *state, ShaderCache *sc) 78{ 79 //LOGE("sgl2 frag1 %x", glGetError()); 80 if ((state->mLast.get() == this) && !mDirty) { 81 return; 82 } 83 state->mLast.set(this); 84 85 rsc->checkError("ProgramFragment::setupGL2 start"); 86 87 rsc->checkError("ProgramFragment::setupGL2 begin uniforms"); 88 setupUserConstants(rsc, sc, true); 89 90 uint32_t numTexturesToBind = mTextureCount; 91 uint32_t numTexturesAvailable = rsc->getMaxFragmentTextures(); 92 if(numTexturesToBind >= numTexturesAvailable) { 93 LOGE("Attempting to bind %u textures on shader id %u, but only %u are available", 94 mTextureCount, (uint32_t)this, numTexturesAvailable); 95 rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind more textuers than available"); 96 numTexturesToBind = numTexturesAvailable; 97 } 98 99 for (uint32_t ct=0; ct < numTexturesToBind; ct++) { 100 glActiveTexture(GL_TEXTURE0 + ct); 101 if (!mTextures[ct].get()) { 102 LOGE("No texture bound for shader id %u, texture unit %u", (uint)this, ct); 103 rsc->setError(RS_ERROR_BAD_SHADER, "No texture bound"); 104 continue; 105 } 106 107 mTextures[ct]->uploadCheck(rsc); 108 glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID()); 109 rsc->checkError("ProgramFragment::setupGL2 tex bind"); 110 if (mSamplers[ct].get()) { 111 mSamplers[ct]->setupGL(rsc, mTextures[ct].get()); 112 } else { 113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 117 rsc->checkError("ProgramFragment::setupGL2 tex env"); 118 } 119 120 glUniform1i(sc->fragUniformSlot(mTextureUniformIndexStart + ct), ct); 121 rsc->checkError("ProgramFragment::setupGL2 uniforms"); 122 } 123 124 glActiveTexture(GL_TEXTURE0); 125 mDirty = false; 126 rsc->checkError("ProgramFragment::setupGL2"); 127} 128 129void ProgramFragment::loadShader(Context *rsc) { 130 Program::loadShader(rsc, GL_FRAGMENT_SHADER); 131} 132 133void ProgramFragment::createShader() 134{ 135 if (mUserShader.length() > 1) { 136 mShader.append("precision mediump float;\n"); 137 appendUserConstants(); 138 char buf[256]; 139 for (uint32_t ct=0; ct < mTextureCount; ct++) { 140 sprintf(buf, "uniform sampler2D UNI_Tex%i;\n", ct); 141 mShader.append(buf); 142 } 143 mShader.append(mUserShader); 144 } else { 145 LOGE("ProgramFragment::createShader cannot create program, shader code not defined"); 146 rsAssert(0); 147 } 148} 149 150void ProgramFragment::init(Context *rsc) 151{ 152 mUniformCount = 0; 153 if (mUserShader.size() > 0) { 154 for (uint32_t ct=0; ct < mConstantCount; ct++) { 155 initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, RS_SHADER_UNI); 156 } 157 } 158 mTextureUniformIndexStart = mUniformCount; 159 char buf[256]; 160 for (uint32_t ct=0; ct < mTextureCount; ct++) { 161 sprintf(buf, "UNI_Tex%i", ct); 162 mUniformNames[mUniformCount++].setTo(buf); 163 } 164 165 createShader(); 166} 167 168void ProgramFragment::serialize(OStream *stream) const 169{ 170 171} 172 173ProgramFragment *ProgramFragment::createFromStream(Context *rsc, IStream *stream) 174{ 175 return NULL; 176} 177 178ProgramFragmentState::ProgramFragmentState() 179{ 180 mPF = NULL; 181} 182 183ProgramFragmentState::~ProgramFragmentState() 184{ 185 delete mPF; 186 187} 188 189void ProgramFragmentState::init(Context *rsc) 190{ 191 String8 shaderString(RS_SHADER_INTERNAL); 192 shaderString.append("varying lowp vec4 varColor;\n"); 193 shaderString.append("varying vec2 varTex0;\n"); 194 shaderString.append("void main() {\n"); 195 shaderString.append(" lowp vec4 col = UNI_Color;\n"); 196 shaderString.append(" gl_FragColor = col;\n"); 197 shaderString.append("}\n"); 198 199 const Element *colorElem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4); 200 rsc->mStateElement.elementBuilderBegin(); 201 rsc->mStateElement.elementBuilderAdd(colorElem, "Color", 1); 202 const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc); 203 204 Type *inputType = new Type(rsc); 205 inputType->setElement(constInput); 206 inputType->setDimX(1); 207 inputType->compute(); 208 209 uint32_t tmp[4]; 210 tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 211 tmp[1] = (uint32_t)inputType; 212 tmp[2] = RS_PROGRAM_PARAM_TEXTURE_COUNT; 213 tmp[3] = 0; 214 215 Allocation *constAlloc = new Allocation(rsc, inputType); 216 ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(), 217 shaderString.length(), tmp, 4); 218 pf->bindAllocation(rsc, constAlloc, 0); 219 pf->setConstantColor(rsc, 1.0f, 1.0f, 1.0f, 1.0f); 220 221 mDefault.set(pf); 222} 223 224void ProgramFragmentState::deinit(Context *rsc) 225{ 226 mDefault.clear(); 227 mLast.clear(); 228} 229 230 231namespace android { 232namespace renderscript { 233 234RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc, const char * shaderText, 235 uint32_t shaderLength, const uint32_t * params, 236 uint32_t paramLength) 237{ 238 ProgramFragment *pf = new ProgramFragment(rsc, shaderText, shaderLength, params, paramLength); 239 pf->incUserRef(); 240 //LOGE("rsi_ProgramFragmentCreate %p", pf); 241 return pf; 242} 243 244} 245} 246 247