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