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 "rsMesh.h" 19 #include "rs.h" 20 21 namespace android { 22 namespace renderscript { 23 24 Mesh::Mesh(Context *rsc) : ObjectBase(rsc) { 25 mHal.drv = nullptr; 26 mHal.state.primitives = nullptr; 27 mHal.state.primitivesCount = 0; 28 mHal.state.indexBuffers = nullptr; 29 mHal.state.indexBuffersCount = 0; 30 mHal.state.vertexBuffers = nullptr; 31 mHal.state.vertexBuffersCount = 0; 32 mInitialized = false; 33 34 mVertexBuffers = nullptr; 35 mIndexBuffers = nullptr; 36 } 37 38 Mesh::Mesh(Context *rsc, 39 uint32_t vertexBuffersCount, 40 uint32_t primitivesCount) : ObjectBase(rsc) { 41 mHal.drv = nullptr; 42 mHal.state.primitivesCount = primitivesCount; 43 mHal.state.indexBuffersCount = primitivesCount; 44 mHal.state.primitives = new RsPrimitive[mHal.state.primitivesCount]; 45 mHal.state.indexBuffers = new Allocation *[mHal.state.indexBuffersCount]; 46 for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) { 47 mHal.state.primitives[i] = RS_PRIMITIVE_POINT; 48 } 49 for (uint32_t i = 0; i < mHal.state.indexBuffersCount; i ++) { 50 mHal.state.indexBuffers[i] = nullptr; 51 } 52 mHal.state.vertexBuffersCount = vertexBuffersCount; 53 mHal.state.vertexBuffers = new Allocation *[mHal.state.vertexBuffersCount]; 54 for (uint32_t i = 0; i < mHal.state.vertexBuffersCount; i ++) { 55 mHal.state.vertexBuffers[i] = nullptr; 56 } 57 58 mVertexBuffers = new ObjectBaseRef<Allocation>[mHal.state.vertexBuffersCount]; 59 mIndexBuffers = new ObjectBaseRef<Allocation>[mHal.state.primitivesCount]; 60 } 61 62 Mesh::~Mesh() { 63 #ifndef ANDROID_RS_SERIALIZE 64 mRSC->mHal.funcs.mesh.destroy(mRSC, this); 65 #endif 66 67 delete[] mHal.state.vertexBuffers; 68 delete[] mHal.state.primitives; 69 delete[] mHal.state.indexBuffers; 70 71 delete[] mVertexBuffers; 72 delete[] mIndexBuffers; 73 } 74 75 void Mesh::init() { 76 #ifndef ANDROID_RS_SERIALIZE 77 mRSC->mHal.funcs.mesh.init(mRSC, this); 78 #endif 79 } 80 81 void Mesh::serialize(Context *rsc, OStream *stream) const { 82 // Need to identify ourselves 83 stream->addU32((uint32_t)getClassId()); 84 stream->addString(getName()); 85 86 // Store number of vertex streams 87 stream->addU32(mHal.state.vertexBuffersCount); 88 for (uint32_t vCount = 0; vCount < mHal.state.vertexBuffersCount; vCount ++) { 89 mHal.state.vertexBuffers[vCount]->serialize(rsc, stream); 90 } 91 92 stream->addU32(mHal.state.primitivesCount); 93 // Store the primitives 94 for (uint32_t pCount = 0; pCount < mHal.state.primitivesCount; pCount ++) { 95 stream->addU8((uint8_t)mHal.state.primitives[pCount]); 96 97 if (mHal.state.indexBuffers[pCount]) { 98 stream->addU32(1); 99 mHal.state.indexBuffers[pCount]->serialize(rsc, stream); 100 } else { 101 stream->addU32(0); 102 } 103 } 104 } 105 106 Mesh *Mesh::createFromStream(Context *rsc, IStream *stream) { 107 // First make sure we are reading the correct object 108 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 109 if (classID != RS_A3D_CLASS_ID_MESH) { 110 ALOGE("mesh loading skipped due to invalid class id"); 111 return nullptr; 112 } 113 114 const char *name = stream->loadString(); 115 116 uint32_t vertexBuffersCount = stream->loadU32(); 117 ObjectBaseRef<Allocation> *vertexBuffers = nullptr; 118 if (vertexBuffersCount) { 119 vertexBuffers = new ObjectBaseRef<Allocation>[vertexBuffersCount]; 120 121 for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) { 122 Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream); 123 vertexBuffers[vCount].set(vertexAlloc); 124 } 125 } 126 127 uint32_t primitivesCount = stream->loadU32(); 128 ObjectBaseRef<Allocation> *indexBuffers = nullptr; 129 RsPrimitive *primitives = nullptr; 130 if (primitivesCount) { 131 indexBuffers = new ObjectBaseRef<Allocation>[primitivesCount]; 132 primitives = new RsPrimitive[primitivesCount]; 133 134 // load all primitives 135 for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) { 136 primitives[pCount] = (RsPrimitive)stream->loadU8(); 137 138 // Check to see if the index buffer was stored 139 uint32_t isIndexPresent = stream->loadU32(); 140 if (isIndexPresent) { 141 Allocation *indexAlloc = Allocation::createFromStream(rsc, stream); 142 indexBuffers[pCount].set(indexAlloc); 143 } 144 } 145 } 146 147 Mesh *mesh = new Mesh(rsc, vertexBuffersCount, primitivesCount); 148 mesh->assignName(name); 149 for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) { 150 mesh->setVertexBuffer(vertexBuffers[vCount].get(), vCount); 151 } 152 for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) { 153 mesh->setPrimitive(indexBuffers[pCount].get(), primitives[pCount], pCount); 154 } 155 156 // Cleanup 157 if (vertexBuffersCount) { 158 delete[] vertexBuffers; 159 } 160 if (primitivesCount) { 161 delete[] indexBuffers; 162 delete[] primitives; 163 } 164 165 #ifndef ANDROID_RS_SERIALIZE 166 mesh->init(); 167 mesh->uploadAll(rsc); 168 #endif 169 return mesh; 170 } 171 172 void Mesh::render(Context *rsc) const { 173 for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) { 174 renderPrimitive(rsc, ct); 175 } 176 } 177 178 void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const { 179 if (primIndex >= mHal.state.primitivesCount) { 180 ALOGE("Invalid primitive index"); 181 return; 182 } 183 184 if (mHal.state.indexBuffers[primIndex]) { 185 renderPrimitiveRange(rsc, primIndex, 0, mHal.state.indexBuffers[primIndex]->getType()->getDimX()); 186 return; 187 } 188 189 renderPrimitiveRange(rsc, primIndex, 0, mHal.state.vertexBuffers[0]->getType()->getDimX()); 190 } 191 192 void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const { 193 if (len < 1 || primIndex >= mHal.state.primitivesCount) { 194 ALOGE("Invalid mesh or parameters"); 195 return; 196 } 197 198 mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len); 199 } 200 201 void Mesh::uploadAll(Context *rsc) { 202 for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) { 203 if (mHal.state.vertexBuffers[ct]) { 204 rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct]); 205 } 206 } 207 208 for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) { 209 if (mHal.state.indexBuffers[ct]) { 210 rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.indexBuffers[ct]); 211 } 212 } 213 } 214 215 void Mesh::computeBBox(Context *rsc) { 216 float *posPtr = nullptr; 217 uint32_t vectorSize = 0; 218 uint32_t stride = 0; 219 uint32_t numVerts = 0; 220 Allocation *posAlloc = nullptr; 221 // First we need to find the position ptr and stride 222 for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) { 223 const Type *bufferType = mHal.state.vertexBuffers[ct]->getType(); 224 const Element *bufferElem = bufferType->getElement(); 225 226 for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) { 227 if (strcmp(bufferElem->getFieldName(ct), "position") == 0) { 228 vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize(); 229 stride = bufferElem->getSizeBytes() / sizeof(float); 230 uint32_t offset = bufferElem->getFieldOffsetBytes(ct); 231 posAlloc = mHal.state.vertexBuffers[ct]; 232 const uint8_t *bp = (const uint8_t *)rsc->mHal.funcs.allocation.lock1D( 233 rsc, posAlloc); 234 posPtr = (float*)(bp + offset); 235 numVerts = bufferType->getDimX(); 236 break; 237 } 238 } 239 if (posPtr) { 240 break; 241 } 242 } 243 244 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6; 245 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6; 246 if (!posPtr) { 247 ALOGE("Unable to compute bounding box"); 248 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f; 249 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f; 250 return; 251 } 252 253 for (uint32_t i = 0; i < numVerts; i ++) { 254 for (uint32_t v = 0; v < vectorSize; v ++) { 255 mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]); 256 mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]); 257 } 258 posPtr += stride; 259 } 260 261 if (posAlloc) { 262 rsc->mHal.funcs.allocation.unlock1D(rsc, posAlloc); 263 } 264 } 265 266 RsMesh rsi_MeshCreate(Context *rsc, 267 RsAllocation * vtx, size_t vtxCount, 268 RsAllocation * idx, size_t idxCount, 269 uint32_t * primType, size_t primTypeCount) { 270 rsAssert(idxCount == primTypeCount); 271 Mesh *sm = new Mesh(rsc, vtxCount, idxCount); 272 sm->incUserRef(); 273 274 for (uint32_t i = 0; i < vtxCount; i ++) { 275 sm->setVertexBuffer((Allocation*)vtx[i], i); 276 } 277 278 for (uint32_t i = 0; i < idxCount; i ++) { 279 sm->setPrimitive((Allocation*)idx[i], (RsPrimitive)primType[i], i); 280 } 281 282 sm->init(); 283 284 return sm; 285 } 286 287 } // namespace renderscript 288 } // namespace android 289