• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Mesh(Context * rsc)22 Mesh::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 
Mesh(Context * rsc,uint32_t vertexBuffersCount,uint32_t primitivesCount)31 Mesh::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 
~Mesh()44 Mesh::~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 
init()62 void Mesh::init() {
63 #ifndef ANDROID_RS_SERIALIZE
64     mRSC->mHal.funcs.mesh.init(mRSC, this);
65 #endif
66 }
67 
serialize(OStream * stream) const68 void 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 
createFromStream(Context * rsc,IStream * stream)97 Mesh *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 
render(Context * rsc) const164 void Mesh::render(Context *rsc) const {
165     for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
166         renderPrimitive(rsc, ct);
167     }
168 }
169 
renderPrimitive(Context * rsc,uint32_t primIndex) const170 void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const {
171     if (primIndex >= mHal.state.primitivesCount) {
172         LOGE("Invalid primitive index");
173         return;
174     }
175 
176     Primitive_t *prim = mHal.state.primitives[primIndex];
177 
178     if (prim->mIndexBuffer.get()) {
179         renderPrimitiveRange(rsc, primIndex, 0, prim->mIndexBuffer->getType()->getDimX());
180         return;
181     }
182 
183     renderPrimitiveRange(rsc, primIndex, 0, mHal.state.vertexBuffers[0]->getType()->getDimX());
184 }
185 
renderPrimitiveRange(Context * rsc,uint32_t primIndex,uint32_t start,uint32_t len) const186 void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
187     if (len < 1 || primIndex >= mHal.state.primitivesCount) {
188         LOGE("Invalid mesh or parameters");
189         return;
190     }
191 
192     mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len);
193 }
194 
uploadAll(Context * rsc)195 void Mesh::uploadAll(Context *rsc) {
196     for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) {
197         if (mHal.state.vertexBuffers[ct].get()) {
198             rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct].get());
199         }
200     }
201 
202     for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
203         if (mHal.state.primitives[ct]->mIndexBuffer.get()) {
204             rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.primitives[ct]->mIndexBuffer.get());
205         }
206     }
207 }
208 
computeBBox()209 void Mesh::computeBBox() {
210     float *posPtr = NULL;
211     uint32_t vectorSize = 0;
212     uint32_t stride = 0;
213     uint32_t numVerts = 0;
214     // First we need to find the position ptr and stride
215     for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) {
216         const Type *bufferType = mHal.state.vertexBuffers[ct]->getType();
217         const Element *bufferElem = bufferType->getElement();
218 
219         for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) {
220             if (strcmp(bufferElem->getFieldName(ct), "position") == 0) {
221                 vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
222                 stride = bufferElem->getSizeBytes() / sizeof(float);
223                 uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
224                 posPtr = (float*)((uint8_t*)mHal.state.vertexBuffers[ct]->getPtr() + offset);
225                 numVerts = bufferType->getDimX();
226                 break;
227             }
228         }
229         if (posPtr) {
230             break;
231         }
232     }
233 
234     mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6;
235     mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6;
236     if (!posPtr) {
237         LOGE("Unable to compute bounding box");
238         mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f;
239         mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f;
240         return;
241     }
242 
243     for (uint32_t i = 0; i < numVerts; i ++) {
244         for (uint32_t v = 0; v < vectorSize; v ++) {
245             mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]);
246             mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]);
247         }
248         posPtr += stride;
249     }
250 }
251 
252 namespace android {
253 namespace renderscript {
254 
rsi_MeshCreate(Context * rsc,RsAllocation * vtx,size_t vtxCount,RsAllocation * idx,size_t idxCount,uint32_t * primType,size_t primTypeCount)255 RsMesh rsi_MeshCreate(Context *rsc,
256                       RsAllocation * vtx, size_t vtxCount,
257                       RsAllocation * idx, size_t idxCount,
258                       uint32_t * primType, size_t primTypeCount) {
259     rsAssert(idxCount == primTypeCount);
260     Mesh *sm = new Mesh(rsc, vtxCount, idxCount);
261     sm->incUserRef();
262 
263     for (uint32_t i = 0; i < vtxCount; i ++) {
264         sm->setVertexBuffer((Allocation*)vtx[i], i);
265     }
266 
267     for (uint32_t i = 0; i < idxCount; i ++) {
268         sm->setPrimitive((Allocation*)idx[i], (RsPrimitive)primType[i], i);
269     }
270 
271     sm->init();
272 
273     return sm;
274 }
275 
276 }}
277 
rsaMeshGetVertexBufferCount(RsContext con,RsMesh mv,int32_t * numVtx)278 void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) {
279     Mesh *sm = static_cast<Mesh *>(mv);
280     *numVtx = sm->mHal.state.vertexBuffersCount;
281 }
282 
rsaMeshGetIndexCount(RsContext con,RsMesh mv,int32_t * numIdx)283 void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) {
284     Mesh *sm = static_cast<Mesh *>(mv);
285     *numIdx = sm->mHal.state.primitivesCount;
286 }
287 
rsaMeshGetVertices(RsContext con,RsMesh mv,RsAllocation * vtxData,uint32_t vtxDataCount)288 void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) {
289     Mesh *sm = static_cast<Mesh *>(mv);
290     rsAssert(vtxDataCount == sm->mHal.state.vertexBuffersCount);
291 
292     for (uint32_t ct = 0; ct < vtxDataCount; ct ++) {
293         vtxData[ct] = sm->mHal.state.vertexBuffers[ct].get();
294         sm->mHal.state.vertexBuffers[ct]->incUserRef();
295     }
296 }
297 
rsaMeshGetIndices(RsContext con,RsMesh mv,RsAllocation * va,uint32_t * primType,uint32_t idxDataCount)298 void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) {
299     Mesh *sm = static_cast<Mesh *>(mv);
300     rsAssert(idxDataCount == sm->mHal.state.primitivesCount);
301 
302     for (uint32_t ct = 0; ct < idxDataCount; ct ++) {
303         va[ct] = sm->mHal.state.primitives[ct]->mIndexBuffer.get();
304         primType[ct] = sm->mHal.state.primitives[ct]->mPrimitive;
305         if (sm->mHal.state.primitives[ct]->mIndexBuffer.get()) {
306             sm->mHal.state.primitives[ct]->mIndexBuffer->incUserRef();
307         }
308     }
309 }
310