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