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