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