rsMesh.cpp revision 064aa7ed76db9564b041afcd4b75da5b3d12faba
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.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
36Mesh::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
60Mesh::~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
73void Mesh::init() {
74#ifndef ANDROID_RS_SERIALIZE
75    mRSC->mHal.funcs.mesh.init(mRSC, this);
76#endif
77}
78
79void 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
106Mesh *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
173void Mesh::render(Context *rsc) const {
174    for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
175        renderPrimitive(rsc, ct);
176    }
177}
178
179void 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
193void 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
202void 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
216void 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
259namespace android {
260namespace renderscript {
261
262RsMesh 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
285void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) {
286    Mesh *sm = static_cast<Mesh *>(mv);
287    *numVtx = sm->mHal.state.vertexBuffersCount;
288}
289
290void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) {
291    Mesh *sm = static_cast<Mesh *>(mv);
292    *numIdx = sm->mHal.state.primitivesCount;
293}
294
295void 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
305void 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