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