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