123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "rsContext.h"
- #include "rsMesh.h"
- #include "rs.h"
- namespace android {
- namespace renderscript {
- Mesh::Mesh(Context *rsc) : ObjectBase(rsc) {
- mHal.drv = nullptr;
- mHal.state.primitives = nullptr;
- mHal.state.primitivesCount = 0;
- mHal.state.indexBuffers = nullptr;
- mHal.state.indexBuffersCount = 0;
- mHal.state.vertexBuffers = nullptr;
- mHal.state.vertexBuffersCount = 0;
- mInitialized = false;
- mVertexBuffers = nullptr;
- mIndexBuffers = nullptr;
- }
- Mesh::Mesh(Context *rsc,
- uint32_t vertexBuffersCount,
- uint32_t primitivesCount) : ObjectBase(rsc) {
- mHal.drv = nullptr;
- mHal.state.primitivesCount = primitivesCount;
- mHal.state.indexBuffersCount = primitivesCount;
- mHal.state.primitives = new RsPrimitive[mHal.state.primitivesCount];
- mHal.state.indexBuffers = new Allocation *[mHal.state.indexBuffersCount];
- for (uint32_t i = 0; i < mHal.state.primitivesCount; i ++) {
- mHal.state.primitives[i] = RS_PRIMITIVE_POINT;
- }
- for (uint32_t i = 0; i < mHal.state.indexBuffersCount; i ++) {
- mHal.state.indexBuffers[i] = nullptr;
- }
- mHal.state.vertexBuffersCount = vertexBuffersCount;
- mHal.state.vertexBuffers = new Allocation *[mHal.state.vertexBuffersCount];
- for (uint32_t i = 0; i < mHal.state.vertexBuffersCount; i ++) {
- mHal.state.vertexBuffers[i] = nullptr;
- }
- mVertexBuffers = new ObjectBaseRef<Allocation>[mHal.state.vertexBuffersCount];
- mIndexBuffers = new ObjectBaseRef<Allocation>[mHal.state.primitivesCount];
- }
- Mesh::~Mesh() {
- #ifndef ANDROID_RS_SERIALIZE
- mRSC->mHal.funcs.mesh.destroy(mRSC, this);
- #endif
- delete[] mHal.state.vertexBuffers;
- delete[] mHal.state.primitives;
- delete[] mHal.state.indexBuffers;
- delete[] mVertexBuffers;
- delete[] mIndexBuffers;
- }
- void Mesh::init() {
- #ifndef ANDROID_RS_SERIALIZE
- mRSC->mHal.funcs.mesh.init(mRSC, this);
- #endif
- }
- void Mesh::serialize(Context *rsc, OStream *stream) const {
- // Need to identify ourselves
- stream->addU32((uint32_t)getClassId());
- stream->addString(getName());
- // Store number of vertex streams
- stream->addU32(mHal.state.vertexBuffersCount);
- for (uint32_t vCount = 0; vCount < mHal.state.vertexBuffersCount; vCount ++) {
- mHal.state.vertexBuffers[vCount]->serialize(rsc, stream);
- }
- stream->addU32(mHal.state.primitivesCount);
- // Store the primitives
- for (uint32_t pCount = 0; pCount < mHal.state.primitivesCount; pCount ++) {
- stream->addU8((uint8_t)mHal.state.primitives[pCount]);
- if (mHal.state.indexBuffers[pCount]) {
- stream->addU32(1);
- mHal.state.indexBuffers[pCount]->serialize(rsc, stream);
- } else {
- stream->addU32(0);
- }
- }
- }
- Mesh *Mesh::createFromStream(Context *rsc, IStream *stream) {
- // First make sure we are reading the correct object
- RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
- if (classID != RS_A3D_CLASS_ID_MESH) {
- ALOGE("mesh loading skipped due to invalid class id");
- return nullptr;
- }
- const char *name = stream->loadString();
- uint32_t vertexBuffersCount = stream->loadU32();
- ObjectBaseRef<Allocation> *vertexBuffers = nullptr;
- if (vertexBuffersCount) {
- vertexBuffers = new ObjectBaseRef<Allocation>[vertexBuffersCount];
- for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
- Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream);
- vertexBuffers[vCount].set(vertexAlloc);
- }
- }
- uint32_t primitivesCount = stream->loadU32();
- ObjectBaseRef<Allocation> *indexBuffers = nullptr;
- RsPrimitive *primitives = nullptr;
- if (primitivesCount) {
- indexBuffers = new ObjectBaseRef<Allocation>[primitivesCount];
- primitives = new RsPrimitive[primitivesCount];
- // load all primitives
- for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
- primitives[pCount] = (RsPrimitive)stream->loadU8();
- // Check to see if the index buffer was stored
- uint32_t isIndexPresent = stream->loadU32();
- if (isIndexPresent) {
- Allocation *indexAlloc = Allocation::createFromStream(rsc, stream);
- indexBuffers[pCount].set(indexAlloc);
- }
- }
- }
- Mesh *mesh = new Mesh(rsc, vertexBuffersCount, primitivesCount);
- mesh->assignName(name);
- for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
- mesh->setVertexBuffer(vertexBuffers[vCount].get(), vCount);
- }
- for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
- mesh->setPrimitive(indexBuffers[pCount].get(), primitives[pCount], pCount);
- }
- // Cleanup
- if (vertexBuffersCount) {
- delete[] vertexBuffers;
- }
- if (primitivesCount) {
- delete[] indexBuffers;
- delete[] primitives;
- }
- #ifndef ANDROID_RS_SERIALIZE
- mesh->init();
- mesh->uploadAll(rsc);
- #endif
- return mesh;
- }
- void Mesh::render(Context *rsc) const {
- for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
- renderPrimitive(rsc, ct);
- }
- }
- void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const {
- if (primIndex >= mHal.state.primitivesCount) {
- ALOGE("Invalid primitive index");
- return;
- }
- if (mHal.state.indexBuffers[primIndex]) {
- renderPrimitiveRange(rsc, primIndex, 0, mHal.state.indexBuffers[primIndex]->getType()->getDimX());
- return;
- }
- renderPrimitiveRange(rsc, primIndex, 0, mHal.state.vertexBuffers[0]->getType()->getDimX());
- }
- void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
- if (len < 1 || primIndex >= mHal.state.primitivesCount) {
- ALOGE("Invalid mesh or parameters");
- return;
- }
- mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len);
- }
- void Mesh::uploadAll(Context *rsc) {
- for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) {
- if (mHal.state.vertexBuffers[ct]) {
- rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct]);
- }
- }
- for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
- if (mHal.state.indexBuffers[ct]) {
- rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.indexBuffers[ct]);
- }
- }
- }
- void Mesh::computeBBox(Context *rsc) {
- float *posPtr = nullptr;
- uint32_t vectorSize = 0;
- uint32_t stride = 0;
- uint32_t numVerts = 0;
- Allocation *posAlloc = nullptr;
- // First we need to find the position ptr and stride
- for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) {
- const Type *bufferType = mHal.state.vertexBuffers[ct]->getType();
- const Element *bufferElem = bufferType->getElement();
- for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) {
- if (strcmp(bufferElem->getFieldName(ct), "position") == 0) {
- vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
- stride = bufferElem->getSizeBytes() / sizeof(float);
- uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
- posAlloc = mHal.state.vertexBuffers[ct];
- const uint8_t *bp = (const uint8_t *)rsc->mHal.funcs.allocation.lock1D(
- rsc, posAlloc);
- posPtr = (float*)(bp + offset);
- numVerts = bufferType->getDimX();
- break;
- }
- }
- if (posPtr) {
- break;
- }
- }
- mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6;
- mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6;
- if (!posPtr) {
- ALOGE("Unable to compute bounding box");
- mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f;
- mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f;
- return;
- }
- for (uint32_t i = 0; i < numVerts; i ++) {
- for (uint32_t v = 0; v < vectorSize; v ++) {
- mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]);
- mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]);
- }
- posPtr += stride;
- }
- if (posAlloc) {
- rsc->mHal.funcs.allocation.unlock1D(rsc, posAlloc);
- }
- }
- RsMesh rsi_MeshCreate(Context *rsc,
- RsAllocation * vtx, size_t vtxCount,
- RsAllocation * idx, size_t idxCount,
- uint32_t * primType, size_t primTypeCount) {
- rsAssert(idxCount == primTypeCount);
- Mesh *sm = new Mesh(rsc, vtxCount, idxCount);
- sm->incUserRef();
- for (uint32_t i = 0; i < vtxCount; i ++) {
- sm->setVertexBuffer((Allocation*)vtx[i], i);
- }
- for (uint32_t i = 0; i < idxCount; i ++) {
- sm->setPrimitive((Allocation*)idx[i], (RsPrimitive)primType[i], i);
- }
- sm->init();
- return sm;
- }
- } // namespace renderscript
- } // namespace android
|