rsMesh.cpp revision a04e30dbb5ab11592b03666bb3d102070759c58e
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 for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) { 195 mHal.state.vertexBuffers[ct]->uploadCheck(rsc); 196 } 197 198 Primitive_t *prim = mHal.state.primitives[primIndex]; 199 if (prim->mIndexBuffer.get()) { 200 prim->mIndexBuffer->uploadCheck(rsc); 201 } 202 rsc->checkError("Mesh::renderPrimitiveRange upload check"); 203 204 mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len); 205 rsc->checkError("Mesh::renderPrimitiveRange draw"); 206} 207 208void Mesh::uploadAll(Context *rsc) { 209 for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) { 210 if (mHal.state.vertexBuffers[ct].get()) { 211 mHal.state.vertexBuffers[ct]->deferredUploadToBufferObject(rsc); 212 } 213 } 214 215 for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) { 216 if (mHal.state.primitives[ct]->mIndexBuffer.get()) { 217 mHal.state.primitives[ct]->mIndexBuffer->deferredUploadToBufferObject(rsc); 218 } 219 } 220} 221 222void Mesh::computeBBox() { 223 float *posPtr = NULL; 224 uint32_t vectorSize = 0; 225 uint32_t stride = 0; 226 uint32_t numVerts = 0; 227 // First we need to find the position ptr and stride 228 for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) { 229 const Type *bufferType = mHal.state.vertexBuffers[ct]->getType(); 230 const Element *bufferElem = bufferType->getElement(); 231 232 for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) { 233 if (strcmp(bufferElem->getFieldName(ct), "position") == 0) { 234 vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize(); 235 stride = bufferElem->getSizeBytes() / sizeof(float); 236 uint32_t offset = bufferElem->getFieldOffsetBytes(ct); 237 posPtr = (float*)((uint8_t*)mHal.state.vertexBuffers[ct]->getPtr() + 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 LOGE("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 265namespace android { 266namespace renderscript { 267 268RsMesh rsi_MeshCreate(Context *rsc, uint32_t vtxCount, uint32_t idxCount) { 269 Mesh *sm = new Mesh(rsc, vtxCount, idxCount); 270 sm->incUserRef(); 271 272 return sm; 273} 274 275void rsi_MeshBindVertex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t slot) { 276 Mesh *sm = static_cast<Mesh *>(mv); 277 rsAssert(slot < sm->mHal.state.vertexBuffersCount); 278 279 sm->setVertexBuffer((Allocation *)va, slot); 280} 281 282void rsi_MeshBindIndex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t primType, uint32_t slot) { 283 Mesh *sm = static_cast<Mesh *>(mv); 284 rsAssert(slot < sm->mHal.state.primitivesCount); 285 286 sm->setPrimitive((Allocation *)va, (RsPrimitive)primType, slot); 287} 288 289void rsi_MeshInitVertexAttribs(Context *rsc, RsMesh mv) { 290 Mesh *sm = static_cast<Mesh *>(mv); 291 sm->init(); 292} 293 294}} 295 296void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) { 297 Mesh *sm = static_cast<Mesh *>(mv); 298 *numVtx = sm->mHal.state.vertexBuffersCount; 299} 300 301void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) { 302 Mesh *sm = static_cast<Mesh *>(mv); 303 *numIdx = sm->mHal.state.primitivesCount; 304} 305 306void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) { 307 Mesh *sm = static_cast<Mesh *>(mv); 308 rsAssert(vtxDataCount == sm->mHal.state.vertexBuffersCount); 309 310 for (uint32_t ct = 0; ct < vtxDataCount; ct ++) { 311 vtxData[ct] = sm->mHal.state.vertexBuffers[ct].get(); 312 sm->mHal.state.vertexBuffers[ct]->incUserRef(); 313 } 314} 315 316void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) { 317 Mesh *sm = static_cast<Mesh *>(mv); 318 rsAssert(idxDataCount == sm->mHal.state.primitivesCount); 319 320 for (uint32_t ct = 0; ct < idxDataCount; ct ++) { 321 va[ct] = sm->mHal.state.primitives[ct]->mIndexBuffer.get(); 322 primType[ct] = sm->mHal.state.primitives[ct]->mPrimitive; 323 if (sm->mHal.state.primitives[ct]->mIndexBuffer.get()) { 324 sm->mHal.state.primitives[ct]->mIndexBuffer->incUserRef(); 325 } 326 } 327} 328 329#endif 330