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