rsMesh.cpp revision 77d9f4bd05b2d2a161f30c12a2248f9c97eaac42
1/*
2 * Copyright (C) 2009 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#ifndef ANDROID_RS_SERIALIZE
19#include <GLES/gl.h>
20#include <GLES2/gl2.h>
21#include <GLES/glext.h>
22#endif
23
24using namespace android;
25using namespace android::renderscript;
26
27Mesh::Mesh(Context *rsc) : ObjectBase(rsc) {
28    mPrimitives = NULL;
29    mPrimitivesCount = 0;
30    mVertexBuffers = NULL;
31    mVertexBufferCount = 0;
32
33#ifndef ANDROID_RS_SERIALIZE
34    mAttribs = NULL;
35    mAttribAllocationIndex = NULL;
36
37    mAttribCount = 0;
38#endif
39}
40
41Mesh::~Mesh() {
42    if (mVertexBuffers) {
43        delete[] mVertexBuffers;
44    }
45
46    if (mPrimitives) {
47        for (uint32_t i = 0; i < mPrimitivesCount; i ++) {
48            delete mPrimitives[i];
49        }
50        delete[] mPrimitives;
51    }
52
53#ifndef ANDROID_RS_SERIALIZE
54    if (mAttribs) {
55        delete[] mAttribs;
56        delete[] mAttribAllocationIndex;
57    }
58#endif
59}
60
61void Mesh::serialize(OStream *stream) const {
62    // Need to identify ourselves
63    stream->addU32((uint32_t)getClassId());
64
65    String8 name(getName());
66    stream->addString(&name);
67
68    // Store number of vertex streams
69    stream->addU32(mVertexBufferCount);
70    for (uint32_t vCount = 0; vCount < mVertexBufferCount; vCount ++) {
71        mVertexBuffers[vCount]->serialize(stream);
72    }
73
74    stream->addU32(mPrimitivesCount);
75    // Store the primitives
76    for (uint32_t pCount = 0; pCount < mPrimitivesCount; pCount ++) {
77        Primitive_t * prim = mPrimitives[pCount];
78
79        stream->addU8((uint8_t)prim->mPrimitive);
80
81        if (prim->mIndexBuffer.get()) {
82            stream->addU32(1);
83            prim->mIndexBuffer->serialize(stream);
84        } else {
85            stream->addU32(0);
86        }
87    }
88}
89
90Mesh *Mesh::createFromStream(Context *rsc, IStream *stream) {
91    // First make sure we are reading the correct object
92    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
93    if (classID != RS_A3D_CLASS_ID_MESH) {
94        LOGE("mesh loading skipped due to invalid class id");
95        return NULL;
96    }
97
98    Mesh * mesh = new Mesh(rsc);
99
100    String8 name;
101    stream->loadString(&name);
102    mesh->setName(name.string(), name.size());
103
104    mesh->mVertexBufferCount = stream->loadU32();
105    if (mesh->mVertexBufferCount) {
106        mesh->mVertexBuffers = new ObjectBaseRef<Allocation>[mesh->mVertexBufferCount];
107
108        for (uint32_t vCount = 0; vCount < mesh->mVertexBufferCount; vCount ++) {
109            Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream);
110            mesh->mVertexBuffers[vCount].set(vertexAlloc);
111        }
112    }
113
114    mesh->mPrimitivesCount = stream->loadU32();
115    if (mesh->mPrimitivesCount) {
116        mesh->mPrimitives = new Primitive_t *[mesh->mPrimitivesCount];
117
118        // load all primitives
119        for (uint32_t pCount = 0; pCount < mesh->mPrimitivesCount; pCount ++) {
120            Primitive_t * prim = new Primitive_t;
121            mesh->mPrimitives[pCount] = prim;
122
123            prim->mPrimitive = (RsPrimitive)stream->loadU8();
124
125            // Check to see if the index buffer was stored
126            uint32_t isIndexPresent = stream->loadU32();
127            if (isIndexPresent) {
128                Allocation *indexAlloc = Allocation::createFromStream(rsc, stream);
129                prim->mIndexBuffer.set(indexAlloc);
130            }
131        }
132    }
133
134#ifndef ANDROID_RS_SERIALIZE
135    mesh->updateGLPrimitives();
136    mesh->initVertexAttribs();
137    mesh->uploadAll(rsc);
138#endif
139    return mesh;
140}
141
142#ifndef ANDROID_RS_SERIALIZE
143
144bool Mesh::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
145    // Do not create attribs for padding
146    if (elem->getFieldName(fieldIdx)[0] == '#') {
147        return false;
148    }
149
150    // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
151    // Filter rs types accordingly
152    RsDataType dt = elem->getField(fieldIdx)->getComponent().getType();
153    if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
154       dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
155       dt != RS_TYPE_SIGNED_16) {
156        return false;
157    }
158
159    // Now make sure they are not arrays
160    uint32_t arraySize = elem->getFieldArraySize(fieldIdx);
161    if (arraySize != 1) {
162        return false;
163    }
164
165    return true;
166}
167
168void Mesh::initVertexAttribs() {
169    // Count the number of gl attrs to initialize
170    mAttribCount = 0;
171    for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
172        const Element *elem = mVertexBuffers[ct]->getType()->getElement();
173        for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) {
174            if (isValidGLComponent(elem, ct)) {
175                mAttribCount ++;
176            }
177        }
178    }
179
180    if (mAttribs) {
181        delete [] mAttribs;
182        delete [] mAttribAllocationIndex;
183        mAttribs = NULL;
184        mAttribAllocationIndex = NULL;
185    }
186    if (!mAttribCount) {
187        return;
188    }
189
190    mAttribs = new VertexArray::Attrib[mAttribCount];
191    mAttribAllocationIndex = new uint32_t[mAttribCount];
192
193    uint32_t userNum = 0;
194    for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
195        const Element *elem = mVertexBuffers[ct]->getType()->getElement();
196        uint32_t stride = elem->getSizeBytes();
197        for (uint32_t fieldI=0; fieldI < elem->getFieldCount(); fieldI++) {
198            const Component &c = elem->getField(fieldI)->getComponent();
199
200            if (!isValidGLComponent(elem, fieldI)) {
201                continue;
202            }
203
204            mAttribs[userNum].size = c.getVectorSize();
205            mAttribs[userNum].offset = elem->getFieldOffsetBytes(fieldI);
206            mAttribs[userNum].type = c.getGLType();
207            mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
208            mAttribs[userNum].stride = stride;
209            String8 tmp(RS_SHADER_ATTR);
210            tmp.append(elem->getFieldName(fieldI));
211            mAttribs[userNum].name.setTo(tmp.string());
212
213            // Remember which allocation this attribute came from
214            mAttribAllocationIndex[userNum] = ct;
215            userNum ++;
216        }
217    }
218}
219
220void Mesh::render(Context *rsc) const {
221    for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) {
222        renderPrimitive(rsc, ct);
223    }
224}
225
226void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const {
227    if (primIndex >= mPrimitivesCount) {
228        LOGE("Invalid primitive index");
229        return;
230    }
231
232    Primitive_t *prim = mPrimitives[primIndex];
233
234    if (prim->mIndexBuffer.get()) {
235        renderPrimitiveRange(rsc, primIndex, 0, prim->mIndexBuffer->getType()->getDimX());
236        return;
237    }
238
239    renderPrimitiveRange(rsc, primIndex, 0, mVertexBuffers[0]->getType()->getDimX());
240}
241
242void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
243    if (len < 1 || primIndex >= mPrimitivesCount || mAttribCount == 0) {
244        LOGE("Invalid mesh or parameters");
245        return;
246    }
247
248    rsc->checkError("Mesh::renderPrimitiveRange 1");
249    for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
250        mVertexBuffers[ct]->uploadCheck(rsc);
251    }
252    // update attributes with either buffer information or data ptr based on their current state
253    for (uint32_t ct=0; ct < mAttribCount; ct++) {
254        uint32_t allocIndex = mAttribAllocationIndex[ct];
255        Allocation *alloc = mVertexBuffers[allocIndex].get();
256        if (alloc->getIsBufferObject()) {
257            mAttribs[ct].buffer = alloc->getBufferObjectID();
258            mAttribs[ct].ptr = NULL;
259        } else {
260            mAttribs[ct].buffer = 0;
261            mAttribs[ct].ptr = (const uint8_t*)alloc->getPtr();
262        }
263    }
264
265    VertexArray va(mAttribs, mAttribCount);
266    va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
267
268    rsc->checkError("Mesh::renderPrimitiveRange 2");
269    Primitive_t *prim = mPrimitives[primIndex];
270    if (prim->mIndexBuffer.get()) {
271        prim->mIndexBuffer->uploadCheck(rsc);
272        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prim->mIndexBuffer->getBufferObjectID());
273        glDrawElements(prim->mGLPrimitive, len, GL_UNSIGNED_SHORT, (uint16_t *)(start * 2));
274    } else {
275        glDrawArrays(prim->mGLPrimitive, start, len);
276    }
277
278    rsc->checkError("Mesh::renderPrimitiveRange");
279}
280
281
282void Mesh::uploadAll(Context *rsc) {
283    for (uint32_t ct = 0; ct < mVertexBufferCount; ct ++) {
284        if (mVertexBuffers[ct].get()) {
285            mVertexBuffers[ct]->deferedUploadToBufferObject(rsc);
286        }
287    }
288
289    for (uint32_t ct = 0; ct < mPrimitivesCount; ct ++) {
290        if (mPrimitives[ct]->mIndexBuffer.get()) {
291            mPrimitives[ct]->mIndexBuffer->deferedUploadToBufferObject(rsc);
292        }
293    }
294}
295
296void Mesh::updateGLPrimitives() {
297    for (uint32_t i = 0; i < mPrimitivesCount; i ++) {
298        switch (mPrimitives[i]->mPrimitive) {
299            case RS_PRIMITIVE_POINT:          mPrimitives[i]->mGLPrimitive = GL_POINTS; break;
300            case RS_PRIMITIVE_LINE:           mPrimitives[i]->mGLPrimitive = GL_LINES; break;
301            case RS_PRIMITIVE_LINE_STRIP:     mPrimitives[i]->mGLPrimitive = GL_LINE_STRIP; break;
302            case RS_PRIMITIVE_TRIANGLE:       mPrimitives[i]->mGLPrimitive = GL_TRIANGLES; break;
303            case RS_PRIMITIVE_TRIANGLE_STRIP: mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_STRIP; break;
304            case RS_PRIMITIVE_TRIANGLE_FAN:   mPrimitives[i]->mGLPrimitive = GL_TRIANGLE_FAN; break;
305        }
306    }
307}
308
309void Mesh::computeBBox() {
310    float *posPtr = NULL;
311    uint32_t vectorSize = 0;
312    uint32_t stride = 0;
313    uint32_t numVerts = 0;
314    // First we need to find the position ptr and stride
315    for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
316        const Type *bufferType = mVertexBuffers[ct]->getType();
317        const Element *bufferElem = bufferType->getElement();
318
319        for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) {
320            if (strcmp(bufferElem->getFieldName(ct), "position") == 0) {
321                vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
322                stride = bufferElem->getSizeBytes() / sizeof(float);
323                uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
324                posPtr = (float*)((uint8_t*)mVertexBuffers[ct]->getPtr() + offset);
325                numVerts = bufferType->getDimX();
326                break;
327            }
328        }
329        if (posPtr) {
330            break;
331        }
332    }
333
334    mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6;
335    mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6;
336    if (!posPtr) {
337        LOGE("Unable to compute bounding box");
338        mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f;
339        mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f;
340        return;
341    }
342
343    for (uint32_t i = 0; i < numVerts; i ++) {
344        for (uint32_t v = 0; v < vectorSize; v ++) {
345            mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]);
346            mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]);
347        }
348        posPtr += stride;
349    }
350}
351
352namespace android {
353namespace renderscript {
354
355RsMesh rsi_MeshCreate(Context *rsc, uint32_t vtxCount, uint32_t idxCount) {
356    Mesh *sm = new Mesh(rsc);
357    sm->incUserRef();
358
359    sm->mPrimitivesCount = idxCount;
360    sm->mPrimitives = new Mesh::Primitive_t *[sm->mPrimitivesCount];
361    for (uint32_t ct = 0; ct < idxCount; ct ++) {
362        sm->mPrimitives[ct] = new Mesh::Primitive_t;
363    }
364
365    sm->mVertexBufferCount = vtxCount;
366    sm->mVertexBuffers = new ObjectBaseRef<Allocation>[vtxCount];
367
368    return sm;
369}
370
371void rsi_MeshBindVertex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t slot) {
372    Mesh *sm = static_cast<Mesh *>(mv);
373    rsAssert(slot < sm->mVertexBufferCount);
374
375    sm->mVertexBuffers[slot].set((Allocation *)va);
376}
377
378void rsi_MeshBindIndex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t primType, uint32_t slot) {
379    Mesh *sm = static_cast<Mesh *>(mv);
380    rsAssert(slot < sm->mPrimitivesCount);
381
382    sm->mPrimitives[slot]->mIndexBuffer.set((Allocation *)va);
383    sm->mPrimitives[slot]->mPrimitive = (RsPrimitive)primType;
384    sm->updateGLPrimitives();
385}
386
387void rsi_MeshInitVertexAttribs(Context *rsc, RsMesh mv) {
388    Mesh *sm = static_cast<Mesh *>(mv);
389    sm->initVertexAttribs();
390}
391
392}}
393
394void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) {
395    Mesh *sm = static_cast<Mesh *>(mv);
396    *numVtx = sm->mVertexBufferCount;
397}
398
399void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) {
400    Mesh *sm = static_cast<Mesh *>(mv);
401    *numIdx = sm->mPrimitivesCount;
402}
403
404void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) {
405    Mesh *sm = static_cast<Mesh *>(mv);
406    rsAssert(vtxDataCount == sm->mVertexBufferCount);
407
408    for (uint32_t ct = 0; ct < vtxDataCount; ct ++) {
409        vtxData[ct] = sm->mVertexBuffers[ct].get();
410        sm->mVertexBuffers[ct]->incUserRef();
411    }
412}
413
414void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) {
415    Mesh *sm = static_cast<Mesh *>(mv);
416    rsAssert(idxDataCount == sm->mPrimitivesCount);
417
418    for (uint32_t ct = 0; ct < idxDataCount; ct ++) {
419        va[ct] = sm->mPrimitives[ct]->mIndexBuffer.get();
420        primType[ct] = sm->mPrimitives[ct]->mPrimitive;
421        if (sm->mPrimitives[ct]->mIndexBuffer.get()) {
422            sm->mPrimitives[ct]->mIndexBuffer->incUserRef();
423        }
424    }
425}
426
427#endif
428