1 /* 2 * Copyright (C) 2011 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 #include "rsContext.h" 18 #include "rsProgramVertex.h" 19 20 using namespace android; 21 using namespace android::renderscript; 22 23 24 ProgramVertex::ProgramVertex(Context *rsc, const char * shaderText, 25 uint32_t shaderLength, const uint32_t * params, 26 uint32_t paramLength) 27 : Program(rsc, shaderText, shaderLength, params, paramLength) { 28 mRSC->mHal.funcs.vertex.init(mRSC, this, mUserShader.string(), mUserShader.length()); 29 } 30 31 ProgramVertex::~ProgramVertex() { 32 mRSC->mHal.funcs.vertex.destroy(mRSC, this); 33 } 34 35 void ProgramVertex::setup(Context *rsc, ProgramVertexState *state) { 36 if ((state->mLast.get() == this) && !mDirty) { 37 return; 38 } 39 40 if (!isUserProgram()) { 41 if (mHal.state.constants[0] == NULL) { 42 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 43 "Unable to set fixed function emulation matrices because allocation is missing"); 44 return; 45 } 46 float *f = static_cast<float *>(mHal.state.constants[0]->getPtr()); 47 Matrix4x4 mvp; 48 mvp.load(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]); 49 Matrix4x4 t; 50 t.load(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]); 51 mvp.multiply(&t); 52 for (uint32_t i = 0; i < 16; i ++) { 53 f[RS_PROGRAM_VERTEX_MVP_OFFSET + i] = mvp.m[i]; 54 } 55 } 56 57 state->mLast.set(this); 58 59 rsc->mHal.funcs.vertex.setActive(rsc, this); 60 } 61 62 void ProgramVertex::setProjectionMatrix(Context *rsc, const rsc_Matrix *m) const { 63 if (isUserProgram()) { 64 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 65 "Attempting to set fixed function emulation matrix projection on user program"); 66 return; 67 } 68 if (mHal.state.constants[0] == NULL) { 69 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 70 "Unable to set fixed function emulation matrix projection because allocation is missing"); 71 return; 72 } 73 float *f = static_cast<float *>(mHal.state.constants[0]->getPtr()); 74 memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix)); 75 mDirty = true; 76 } 77 78 void ProgramVertex::setModelviewMatrix(Context *rsc, const rsc_Matrix *m) const { 79 if (isUserProgram()) { 80 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 81 "Attempting to set fixed function emulation matrix modelview on user program"); 82 return; 83 } 84 if (mHal.state.constants[0] == NULL) { 85 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 86 "Unable to set fixed function emulation matrix modelview because allocation is missing"); 87 return; 88 } 89 float *f = static_cast<float *>(mHal.state.constants[0]->getPtr()); 90 memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix)); 91 mDirty = true; 92 } 93 94 void ProgramVertex::setTextureMatrix(Context *rsc, const rsc_Matrix *m) const { 95 if (isUserProgram()) { 96 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 97 "Attempting to set fixed function emulation matrix texture on user program"); 98 return; 99 } 100 if (mHal.state.constants[0] == NULL) { 101 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 102 "Unable to set fixed function emulation matrix texture because allocation is missing"); 103 return; 104 } 105 float *f = static_cast<float *>(mHal.state.constants[0]->getPtr()); 106 memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix)); 107 mDirty = true; 108 } 109 110 void ProgramVertex::getProjectionMatrix(Context *rsc, rsc_Matrix *m) const { 111 if (isUserProgram()) { 112 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 113 "Attempting to get fixed function emulation matrix projection on user program"); 114 return; 115 } 116 if (mHal.state.constants[0] == NULL) { 117 rsc->setError(RS_ERROR_FATAL_UNKNOWN, 118 "Unable to get fixed function emulation matrix projection because allocation is missing"); 119 return; 120 } 121 float *f = static_cast<float *>(mHal.state.constants[0]->getPtr()); 122 memcpy(m, &f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], sizeof(rsc_Matrix)); 123 } 124 125 void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v3in) const { 126 if (isUserProgram()) { 127 return; 128 } 129 float *f = static_cast<float *>(mHal.state.constants[0]->getPtr()); 130 Matrix4x4 mvp; 131 mvp.loadMultiply((Matrix4x4 *)&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], 132 (Matrix4x4 *)&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET]); 133 mvp.vectorMultiply(v4out, v3in); 134 } 135 136 void ProgramVertex::serialize(OStream *stream) const { 137 } 138 139 ProgramVertex *ProgramVertex::createFromStream(Context *rsc, IStream *stream) { 140 return NULL; 141 } 142 143 144 /////////////////////////////////////////////////////////////////////// 145 146 ProgramVertexState::ProgramVertexState() { 147 } 148 149 ProgramVertexState::~ProgramVertexState() { 150 } 151 152 void ProgramVertexState::init(Context *rsc) { 153 ObjectBaseRef<const Element> matrixElem = Element::createRef(rsc, RS_TYPE_MATRIX_4X4, 154 RS_KIND_USER, false, 1); 155 ObjectBaseRef<const Element> f2Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32, 156 RS_KIND_USER, false, 2); 157 ObjectBaseRef<const Element> f3Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32, 158 RS_KIND_USER, false, 3); 159 ObjectBaseRef<const Element> f4Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32, 160 RS_KIND_USER, false, 4); 161 162 Element::Builder constBuilder; 163 constBuilder.add(matrixElem.get(), "MV", 1); 164 constBuilder.add(matrixElem.get(), "P", 1); 165 constBuilder.add(matrixElem.get(), "TexMatrix", 1); 166 constBuilder.add(matrixElem.get(), "MVP", 1); 167 ObjectBaseRef<const Element> constInput = constBuilder.create(rsc); 168 169 Element::Builder inputBuilder; 170 inputBuilder.add(f4Elem.get(), "position", 1); 171 inputBuilder.add(f4Elem.get(), "color", 1); 172 inputBuilder.add(f3Elem.get(), "normal", 1); 173 inputBuilder.add(f2Elem.get(), "texture0", 1); 174 ObjectBaseRef<const Element> attrElem = inputBuilder.create(rsc); 175 176 ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false); 177 178 String8 shaderString(RS_SHADER_INTERNAL); 179 shaderString.append("varying vec4 varColor;\n"); 180 shaderString.append("varying vec2 varTex0;\n"); 181 shaderString.append("void main() {\n"); 182 shaderString.append(" gl_Position = UNI_MVP * ATTRIB_position;\n"); 183 shaderString.append(" gl_PointSize = 1.0;\n"); 184 shaderString.append(" varColor = ATTRIB_color;\n"); 185 shaderString.append(" varTex0 = ATTRIB_texture0;\n"); 186 shaderString.append("}\n"); 187 188 uint32_t tmp[4]; 189 tmp[0] = RS_PROGRAM_PARAM_CONSTANT; 190 tmp[1] = (uint32_t)inputType.get(); 191 tmp[2] = RS_PROGRAM_PARAM_INPUT; 192 tmp[3] = (uint32_t)attrElem.get(); 193 194 ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(), 195 shaderString.length(), tmp, 4); 196 Allocation *alloc = Allocation::createAllocation(rsc, inputType.get(), 197 RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS); 198 pv->bindAllocation(rsc, alloc, 0); 199 200 mDefaultAlloc.set(alloc); 201 mDefault.set(pv); 202 203 updateSize(rsc); 204 } 205 206 void ProgramVertexState::updateSize(Context *rsc) { 207 float *f = static_cast<float *>(mDefaultAlloc->getPtr()); 208 209 Matrix4x4 m; 210 m.loadOrtho(0,rsc->getWidth(), rsc->getHeight(),0, -1,1); 211 memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m.m, sizeof(m)); 212 memcpy(&f[RS_PROGRAM_VERTEX_MVP_OFFSET], m.m, sizeof(m)); 213 214 m.loadIdentity(); 215 memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m.m, sizeof(m)); 216 memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m.m, sizeof(m)); 217 } 218 219 void ProgramVertexState::deinit(Context *rsc) { 220 mDefaultAlloc.clear(); 221 mDefault.clear(); 222 mLast.clear(); 223 } 224 225 226 namespace android { 227 namespace renderscript { 228 229 RsProgramVertex rsi_ProgramVertexCreate(Context *rsc, const char * shaderText, 230 size_t shaderLength, const uint32_t * params, 231 size_t paramLength) { 232 ProgramVertex *pv = new ProgramVertex(rsc, shaderText, shaderLength, params, paramLength); 233 pv->incUserRef(); 234 return pv; 235 } 236 237 } 238 } 239