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 19 using namespace android; 20 using namespace android::renderscript; 21 22 Mesh::Mesh(Context *rsc) : ObjectBase(rsc) { 23 mHal.drv = NULL; 24 mHal.state.primitives = NULL; 25 mHal.state.primitivesCount = 0; 26 mHal.state.indexBuffers = NULL; 27 mHal.state.indexBuffersCount = 0; 28 mHal.state.vertexBuffers = NULL; 29 mHal.state.vertexBuffersCount = 0; 30 mInitialized = false; 31 32 mVertexBuffers = NULL; 33 mIndexBuffers = NULL; 34 } 35 36 Mesh::Mesh(Context *rsc, 37 uint32_t vertexBuffersCount, 38 uint32_t primitivesCount) : ObjectBase(rsc) { 39 mHal.drv = NULL; 40 mHal.state.primitivesCount = primitivesCount; 41 mHal.state.indexBuffersCount = primitivesCount; 42 mHal.state.primitives = new RsPrimitive[mHal.state.primitivesCount]; 43 mHal.state.indexBuffers = new Allocation *[mHal.state.indexBuffersCount]; 44 for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) { 45 mHal.state.primitives[i] = RS_PRIMITIVE_POINT; 46 } 47 for (uint32_t i = 0; i < mHal.state.indexBuffersCount; i ++) { 48 mHal.state.indexBuffers[i] = NULL; 49 } 50 mHal.state.vertexBuffersCount = vertexBuffersCount; 51 mHal.state.vertexBuffers = new Allocation *[mHal.state.vertexBuffersCount]; 52 for (uint32_t i = 0; i < mHal.state.vertexBuffersCount; i ++) { 53 mHal.state.vertexBuffers[i] = NULL; 54 } 55 56 mVertexBuffers = new ObjectBaseRef<Allocation>[mHal.state.vertexBuffersCount]; 57 mIndexBuffers = new ObjectBaseRef<Allocation>[mHal.state.primitivesCount]; 58 } 59 60 Mesh::~Mesh() { 61 #ifndef ANDROID_RS_SERIALIZE 62 mRSC->mHal.funcs.mesh.destroy(mRSC, this); 63 #endif 64 65 delete[] mHal.state.vertexBuffers; 66 delete[] mHal.state.primitives; 67 delete[] mHal.state.indexBuffers; 68 69 delete[] mVertexBuffers; 70 delete[] mIndexBuffers; 71 } 72 73 void Mesh::init() { 74 #ifndef ANDROID_RS_SERIALIZE 75 mRSC->mHal.funcs.mesh.init(mRSC, this); 76 #endif 77 } 78 79 void Mesh::serialize(OStream *stream) const { 80 // Need to identify ourselves 81 stream->addU32((uint32_t)getClassId()); 82 83 String8 name(getName()); 84 stream->addString(&name); 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(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(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 LOGE("mesh loading skipped due to invalid class id"); 111 return NULL; 112 } 113 114 String8 name; 115 stream->loadString(&name); 116 117 uint32_t vertexBuffersCount = stream->loadU32(); 118 ObjectBaseRef<Allocation> *vertexBuffers = NULL; 119 if (vertexBuffersCount) { 120 vertexBuffers = new ObjectBaseRef<Allocation>[vertexBuffersCount]; 121 122 for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) { 123 Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream); 124 vertexBuffers[vCount].set(vertexAlloc); 125 } 126 } 127 128 uint32_t primitivesCount = stream->loadU32(); 129 ObjectBaseRef<Allocation> *indexBuffers = NULL; 130 RsPrimitive *primitives = NULL; 131 if (primitivesCount) { 132 indexBuffers = new ObjectBaseRef<Allocation>[primitivesCount]; 133 primitives = new RsPrimitive[primitivesCount]; 134 135 // load all primitives 136 for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) { 137 primitives[pCount] = (RsPrimitive)stream->loadU8(); 138 139 // Check to see if the index buffer was stored 140 uint32_t isIndexPresent = stream->loadU32(); 141 if (isIndexPresent) { 142 Allocation *indexAlloc = Allocation::createFromStream(rsc, stream); 143 indexBuffers[pCount].set(indexAlloc); 144 } 145 } 146 } 147 148 Mesh *mesh = new Mesh(rsc, vertexBuffersCount, primitivesCount); 149 mesh->setName(name.string(), name.size()); 150 for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) { 151 mesh->setVertexBuffer(vertexBuffers[vCount].get(), vCount); 152 } 153 for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) { 154 mesh->setPrimitive(indexBuffers[pCount].get(), primitives[pCount], pCount); 155 } 156 157 // Cleanup 158 if (vertexBuffersCount) { 159 delete[] vertexBuffers; 160 } 161 if (primitivesCount) { 162 delete[] indexBuffers; 163 delete[] primitives; 164 } 165 166 #ifndef ANDROID_RS_SERIALIZE 167 mesh->init(); 168 mesh->uploadAll(rsc); 169 #endif 170 return mesh; 171 } 172 173 void Mesh::render(Context *rsc) const { 174 for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) { 175 renderPrimitive(rsc, ct); 176 } 177 } 178 179 void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const { 180 if (primIndex >= mHal.state.primitivesCount) { 181 LOGE("Invalid primitive index"); 182 return; 183 } 184 185 if (mHal.state.indexBuffers[primIndex]) { 186 renderPrimitiveRange(rsc, primIndex, 0, mHal.state.indexBuffers[primIndex]->getType()->getDimX()); 187 return; 188 } 189 190 renderPrimitiveRange(rsc, primIndex, 0, mHal.state.vertexBuffers[0]->getType()->getDimX()); 191 } 192 193 void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const { 194 if (len < 1 || primIndex >= mHal.state.primitivesCount) { 195 LOGE("Invalid mesh or parameters"); 196 return; 197 } 198 199 mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len); 200 } 201 202 void Mesh::uploadAll(Context *rsc) { 203 for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) { 204 if (mHal.state.vertexBuffers[ct]) { 205 rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct]); 206 } 207 } 208 209 for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) { 210 if (mHal.state.indexBuffers[ct]) { 211 rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.indexBuffers[ct]); 212 } 213 } 214 } 215 216 void Mesh::computeBBox() { 217 float *posPtr = NULL; 218 uint32_t vectorSize = 0; 219 uint32_t stride = 0; 220 uint32_t numVerts = 0; 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 posPtr = (float*)((uint8_t*)mHal.state.vertexBuffers[ct]->getPtr() + offset); 232 numVerts = bufferType->getDimX(); 233 break; 234 } 235 } 236 if (posPtr) { 237 break; 238 } 239 } 240 241 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6; 242 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6; 243 if (!posPtr) { 244 LOGE("Unable to compute bounding box"); 245 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f; 246 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f; 247 return; 248 } 249 250 for (uint32_t i = 0; i < numVerts; i ++) { 251 for (uint32_t v = 0; v < vectorSize; v ++) { 252 mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]); 253 mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]); 254 } 255 posPtr += stride; 256 } 257 } 258 259 namespace android { 260 namespace renderscript { 261 262 RsMesh rsi_MeshCreate(Context *rsc, 263 RsAllocation * vtx, size_t vtxCount, 264 RsAllocation * idx, size_t idxCount, 265 uint32_t * primType, size_t primTypeCount) { 266 rsAssert(idxCount == primTypeCount); 267 Mesh *sm = new Mesh(rsc, vtxCount, idxCount); 268 sm->incUserRef(); 269 270 for (uint32_t i = 0; i < vtxCount; i ++) { 271 sm->setVertexBuffer((Allocation*)vtx[i], i); 272 } 273 274 for (uint32_t i = 0; i < idxCount; i ++) { 275 sm->setPrimitive((Allocation*)idx[i], (RsPrimitive)primType[i], i); 276 } 277 278 sm->init(); 279 280 return sm; 281 } 282 283 }} 284 285 void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) { 286 Mesh *sm = static_cast<Mesh *>(mv); 287 *numVtx = sm->mHal.state.vertexBuffersCount; 288 } 289 290 void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) { 291 Mesh *sm = static_cast<Mesh *>(mv); 292 *numIdx = sm->mHal.state.primitivesCount; 293 } 294 295 void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) { 296 Mesh *sm = static_cast<Mesh *>(mv); 297 rsAssert(vtxDataCount == sm->mHal.state.vertexBuffersCount); 298 299 for (uint32_t ct = 0; ct < vtxDataCount; ct ++) { 300 vtxData[ct] = sm->mHal.state.vertexBuffers[ct]; 301 sm->mHal.state.vertexBuffers[ct]->incUserRef(); 302 } 303 } 304 305 void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) { 306 Mesh *sm = static_cast<Mesh *>(mv); 307 rsAssert(idxDataCount == sm->mHal.state.primitivesCount); 308 309 for (uint32_t ct = 0; ct < idxDataCount; ct ++) { 310 va[ct] = sm->mHal.state.indexBuffers[ct]; 311 primType[ct] = sm->mHal.state.primitives[ct]; 312 if (sm->mHal.state.indexBuffers[ct]) { 313 sm->mHal.state.indexBuffers[ct]->incUserRef(); 314 } 315 } 316 } 317