rsMesh.cpp revision 77d9f4bd05b2d2a161f30c12a2248f9c97eaac42
1/* 2 * Copyright (C) 2009 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#ifndef ANDROID_RS_SERIALIZE 19#include <GLES/gl.h> 20#include <GLES2/gl2.h> 21#include <GLES/glext.h> 22#endif 23 24using namespace android; 25using namespace android::renderscript; 26 27Mesh::Mesh(Context *rsc) : ObjectBase(rsc) { 28 mPrimitives = NULL; 29 mPrimitivesCount = 0; 30 mVertexBuffers = NULL; 31 mVertexBufferCount = 0; 32 33#ifndef ANDROID_RS_SERIALIZE 34 mAttribs = NULL; 35 mAttribAllocationIndex = NULL; 36 37 mAttribCount = 0; 38#endif 39} 40 41Mesh::~Mesh() { 42 if (mVertexBuffers) { 43 delete[] mVertexBuffers; 44 } 45 46 if (mPrimitives) { 47 for (uint32_t i = 0; i < mPrimitivesCount; i ++) { 48 delete mPrimitives[i]; 49 } 50 delete[] mPrimitives; 51 } 52 53#ifndef ANDROID_RS_SERIALIZE 54 if (mAttribs) { 55 delete[] mAttribs; 56 delete[] mAttribAllocationIndex; 57 } 58#endif 59} 60 61void Mesh::serialize(OStream *stream) const { 62 // Need to identify ourselves 63 stream->addU32((uint32_t)getClassId()); 64 65 String8 name(getName()); 66 stream->addString(&name); 67 68 // Store number of vertex streams 69 stream->addU32(mVertexBufferCount); 70 for (uint32_t vCount = 0; vCount < mVertexBufferCount; vCount ++) { 71 mVertexBuffers[vCount]->serialize(stream); 72 } 73 74 stream->addU32(mPrimitivesCount); 75 // Store the primitives 76 for (uint32_t pCount = 0; pCount < mPrimitivesCount; pCount ++) { 77 Primitive_t * prim = mPrimitives[pCount]; 78 79 stream->addU8((uint8_t)prim->mPrimitive); 80 81 if (prim->mIndexBuffer.get()) { 82 stream->addU32(1); 83 prim->mIndexBuffer->serialize(stream); 84 } else { 85 stream->addU32(0); 86 } 87 } 88} 89 90Mesh *Mesh::createFromStream(Context *rsc, IStream *stream) { 91 // First make sure we are reading the correct object 92 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 93 if (classID != RS_A3D_CLASS_ID_MESH) { 94 LOGE("mesh loading skipped due to invalid class id"); 95 return NULL; 96 } 97 98 Mesh * mesh = new Mesh(rsc); 99 100 String8 name; 101 stream->loadString(&name); 102 mesh->setName(name.string(), name.size()); 103 104 mesh->mVertexBufferCount = stream->loadU32(); 105 if (mesh->mVertexBufferCount) { 106 mesh->mVertexBuffers = new ObjectBaseRef<Allocation>[mesh->mVertexBufferCount]; 107 108 for (uint32_t vCount = 0; vCount < mesh->mVertexBufferCount; vCount ++) { 109 Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream); 110 mesh->mVertexBuffers[vCount].set(vertexAlloc); 111 } 112 } 113 114 mesh->mPrimitivesCount = stream->loadU32(); 115 if (mesh->mPrimitivesCount) { 116 mesh->mPrimitives = new Primitive_t *[mesh->mPrimitivesCount]; 117 118 // load all primitives 119 for (uint32_t pCount = 0; pCount < mesh->mPrimitivesCount; pCount ++) { 120 Primitive_t * prim = new Primitive_t; 121 mesh->mPrimitives[pCount] = prim; 122 123 prim->mPrimitive = (RsPrimitive)stream->loadU8(); 124 125 // Check to see if the index buffer was stored 126 uint32_t isIndexPresent = stream->loadU32(); 127 if (isIndexPresent) { 128 Allocation *indexAlloc = Allocation::createFromStream(rsc, stream); 129 prim->mIndexBuffer.set(indexAlloc); 130 } 131 } 132 } 133 134#ifndef ANDROID_RS_SERIALIZE 135 mesh->updateGLPrimitives(); 136 mesh->initVertexAttribs(); 137 mesh->uploadAll(rsc); 138#endif 139 return mesh; 140} 141 142#ifndef ANDROID_RS_SERIALIZE 143 144bool Mesh::isValidGLComponent(const Element *elem, uint32_t fieldIdx) { 145 // Do not create attribs for padding 146 if (elem->getFieldName(fieldIdx)[0] == '#') { 147 return false; 148 } 149 150 // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted. 151 // Filter rs types accordingly 152 RsDataType dt = elem->getField(fieldIdx)->getComponent().getType(); 153 if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 && 154 dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 && 155 dt != RS_TYPE_SIGNED_16) { 156 return false; 157 } 158 159 // Now make sure they are not arrays 160 uint32_t arraySize = elem->getFieldArraySize(fieldIdx); 161 if (arraySize != 1) { 162 return false; 163 } 164 165 return true; 166} 167 168void Mesh::initVertexAttribs() { 169 // Count the number of gl attrs to initialize 170 mAttribCount = 0; 171 for (uint32_t ct=0; ct < mVertexBufferCount; ct++) { 172 const Element *elem = mVertexBuffers[ct]->getType()->getElement(); 173 for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) { 174 if (isValidGLComponent(elem, ct)) { 175 mAttribCount ++; 176 } 177 } 178 } 179 180 if (mAttribs) { 181 delete [] mAttribs; 182 delete [] mAttribAllocationIndex; 183 mAttribs = NULL; 184 mAttribAllocationIndex = NULL; 185 } 186 if (!mAttribCount) { 187 return; 188 } 189 190 mAttribs = new VertexArray::Attrib[mAttribCount]; 191 mAttribAllocationIndex = new uint32_t[mAttribCount]; 192 193 uint32_t userNum = 0; 194 for (uint32_t ct=0; ct < mVertexBufferCount; ct++) { 195 const Element *elem = mVertexBuffers[ct]->getType()->getElement(); 196 uint32_t stride = elem->getSizeBytes(); 197 for (uint32_t fieldI=0; fieldI < elem->getFieldCount(); fieldI++) { 198 const Component &c = elem->getField(fieldI)->getComponent(); 199 200 if (!isValidGLComponent(elem, fieldI)) { 201 continue; 202 } 203 204 mAttribs[userNum].size = c.getVectorSize(); 205 mAttribs[userNum].offset = elem->getFieldOffsetBytes(fieldI); 206 mAttribs[userNum].type = c.getGLType(); 207 mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized(); 208 mAttribs[userNum].stride = stride; 209 String8 tmp(RS_SHADER_ATTR); 210 tmp.append(elem->getFieldName(fieldI)); 211 mAttribs[userNum].name.setTo(tmp.string()); 212 213 // Remember which allocation this attribute came from 214 mAttribAllocationIndex[userNum] = ct; 215 userNum ++; 216 } 217 } 218} 219 220void Mesh::render(Context *rsc) const { 221 for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) { 222 renderPrimitive(rsc, ct); 223 } 224} 225 226void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const { 227 if (primIndex >= mPrimitivesCount) { 228 LOGE("Invalid primitive index"); 229 return; 230 } 231 232 Primitive_t *prim = mPrimitives[primIndex]; 233 234 if (prim->mIndexBuffer.get()) { 235 renderPrimitiveRange(rsc, primIndex, 0, prim->mIndexBuffer->getType()->getDimX()); 236 return; 237 } 238 239 renderPrimitiveRange(rsc, primIndex, 0, mVertexBuffers[0]->getType()->getDimX()); 240} 241 242void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const { 243 if (len < 1 || primIndex >= mPrimitivesCount || mAttribCount == 0) { 244 LOGE("Invalid mesh or parameters"); 245 return; 246 } 247 248 rsc->checkError("Mesh::renderPrimitiveRange 1"); 249 for (uint32_t ct=0; ct < mVertexBufferCount; ct++) { 250 mVertexBuffers[ct]->uploadCheck(rsc); 251 } 252 // update attributes with either buffer information or data ptr based on their current state 253 for (uint32_t ct=0; ct < mAttribCount; ct++) { 254 uint32_t allocIndex = mAttribAllocationIndex[ct]; 255 Allocation *alloc = mVertexBuffers[allocIndex].get(); 256 if (alloc->getIsBufferObject()) { 257 mAttribs[ct].buffer = alloc->getBufferObjectID(); 258 mAttribs[ct].ptr = NULL; 259 } else { 260 mAttribs[ct].buffer = 0; 261 mAttribs[ct].ptr = (const uint8_t*)alloc->getPtr(); 262 } 263 } 264 265 VertexArray va(mAttribs, mAttribCount); 266 va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache); 267 268 rsc->checkError("Mesh::renderPrimitiveRange 2"); 269 Primitive_t *prim = mPrimitives[primIndex]; 270 if (prim->mIndexBuffer.get()) { 271 prim->mIndexBuffer->uploadCheck(rsc); 272 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prim->mIndexBuffer->getBufferObjectID()); 273 glDrawElements(prim->mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2)); 274 } else { 275 glDrawArrays(prim->mGLPrimitive, start, len); 276 } 277 278 rsc->checkError("Mesh::renderPrimitiveRange"); 279} 280 281 282void Mesh::uploadAll(Context *rsc) { 283 for (uint32_t ct = 0; ct < mVertexBufferCount; ct ++) { 284 if (mVertexBuffers[ct].get()) { 285 mVertexBuffers[ct]->deferedUploadToBufferObject(rsc); 286 } 287 } 288 289 for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) { 290 if (mPrimitives[ct]->mIndexBuffer.get()) { 291 mPrimitives[ct]->mIndexBuffer->deferedUploadToBufferObject(rsc); 292 } 293 } 294} 295 296void Mesh::updateGLPrimitives() { 297 for (uint32_t i = 0; i < mPrimitivesCount; i ++) { 298 switch (mPrimitives[i]->mPrimitive) { 299 case RS_PRIMITIVE_POINT: mPrimitives[i]->mGLPrimitive = GL_POINTS; break; 300 case RS_PRIMITIVE_LINE: mPrimitives[i]->mGLPrimitive = GL_LINES; break; 301 case RS_PRIMITIVE_LINE_STRIP: mPrimitives[i]->mGLPrimitive = GL_LINE_STRIP; break; 302 case RS_PRIMITIVE_TRIANGLE: mPrimitives[i]->mGLPrimitive = GL_TRIANGLES; break; 303 case RS_PRIMITIVE_TRIANGLE_STRIP: mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_STRIP; break; 304 case RS_PRIMITIVE_TRIANGLE_FAN: mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_FAN; break; 305 } 306 } 307} 308 309void Mesh::computeBBox() { 310 float *posPtr = NULL; 311 uint32_t vectorSize = 0; 312 uint32_t stride = 0; 313 uint32_t numVerts = 0; 314 // First we need to find the position ptr and stride 315 for (uint32_t ct=0; ct < mVertexBufferCount; ct++) { 316 const Type *bufferType = mVertexBuffers[ct]->getType(); 317 const Element *bufferElem = bufferType->getElement(); 318 319 for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) { 320 if (strcmp(bufferElem->getFieldName(ct), "position") == 0) { 321 vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize(); 322 stride = bufferElem->getSizeBytes() / sizeof(float); 323 uint32_t offset = bufferElem->getFieldOffsetBytes(ct); 324 posPtr = (float*)((uint8_t*)mVertexBuffers[ct]->getPtr() + offset); 325 numVerts = bufferType->getDimX(); 326 break; 327 } 328 } 329 if (posPtr) { 330 break; 331 } 332 } 333 334 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6; 335 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6; 336 if (!posPtr) { 337 LOGE("Unable to compute bounding box"); 338 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f; 339 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f; 340 return; 341 } 342 343 for (uint32_t i = 0; i < numVerts; i ++) { 344 for (uint32_t v = 0; v < vectorSize; v ++) { 345 mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]); 346 mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]); 347 } 348 posPtr += stride; 349 } 350} 351 352namespace android { 353namespace renderscript { 354 355RsMesh rsi_MeshCreate(Context *rsc, uint32_t vtxCount, uint32_t idxCount) { 356 Mesh *sm = new Mesh(rsc); 357 sm->incUserRef(); 358 359 sm->mPrimitivesCount = idxCount; 360 sm->mPrimitives = new Mesh::Primitive_t *[sm->mPrimitivesCount]; 361 for (uint32_t ct = 0; ct < idxCount; ct ++) { 362 sm->mPrimitives[ct] = new Mesh::Primitive_t; 363 } 364 365 sm->mVertexBufferCount = vtxCount; 366 sm->mVertexBuffers = new ObjectBaseRef<Allocation>[vtxCount]; 367 368 return sm; 369} 370 371void rsi_MeshBindVertex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t slot) { 372 Mesh *sm = static_cast<Mesh *>(mv); 373 rsAssert(slot < sm->mVertexBufferCount); 374 375 sm->mVertexBuffers[slot].set((Allocation *)va); 376} 377 378void rsi_MeshBindIndex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t primType, uint32_t slot) { 379 Mesh *sm = static_cast<Mesh *>(mv); 380 rsAssert(slot < sm->mPrimitivesCount); 381 382 sm->mPrimitives[slot]->mIndexBuffer.set((Allocation *)va); 383 sm->mPrimitives[slot]->mPrimitive = (RsPrimitive)primType; 384 sm->updateGLPrimitives(); 385} 386 387void rsi_MeshInitVertexAttribs(Context *rsc, RsMesh mv) { 388 Mesh *sm = static_cast<Mesh *>(mv); 389 sm->initVertexAttribs(); 390} 391 392}} 393 394void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) { 395 Mesh *sm = static_cast<Mesh *>(mv); 396 *numVtx = sm->mVertexBufferCount; 397} 398 399void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) { 400 Mesh *sm = static_cast<Mesh *>(mv); 401 *numIdx = sm->mPrimitivesCount; 402} 403 404void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) { 405 Mesh *sm = static_cast<Mesh *>(mv); 406 rsAssert(vtxDataCount == sm->mVertexBufferCount); 407 408 for (uint32_t ct = 0; ct < vtxDataCount; ct ++) { 409 vtxData[ct] = sm->mVertexBuffers[ct].get(); 410 sm->mVertexBuffers[ct]->incUserRef(); 411 } 412} 413 414void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) { 415 Mesh *sm = static_cast<Mesh *>(mv); 416 rsAssert(idxDataCount == sm->mPrimitivesCount); 417 418 for (uint32_t ct = 0; ct < idxDataCount; ct ++) { 419 va[ct] = sm->mPrimitives[ct]->mIndexBuffer.get(); 420 primType[ct] = sm->mPrimitives[ct]->mPrimitive; 421 if (sm->mPrimitives[ct]->mIndexBuffer.get()) { 422 sm->mPrimitives[ct]->mIndexBuffer->incUserRef(); 423 } 424 } 425} 426 427#endif 428