• 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 #include "rsMesh.h"
19 #include "rs.h"
20 
21 using namespace android;
22 using namespace android::renderscript;
23 
Mesh(Context * rsc)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 
Mesh(Context * rsc,uint32_t vertexBuffersCount,uint32_t primitivesCount)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 
~Mesh()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 
init()75 void Mesh::init() {
76 #ifndef ANDROID_RS_SERIALIZE
77     mRSC->mHal.funcs.mesh.init(mRSC, this);
78 #endif
79 }
80 
serialize(OStream * stream) const81 void Mesh::serialize(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(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(stream);
102         } else {
103             stream->addU32(0);
104         }
105     }
106 }
107 
createFromStream(Context * rsc,IStream * stream)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 
render(Context * rsc) const175 void Mesh::render(Context *rsc) const {
176     for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
177         renderPrimitive(rsc, ct);
178     }
179 }
180 
renderPrimitive(Context * rsc,uint32_t primIndex) const181 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 
renderPrimitiveRange(Context * rsc,uint32_t primIndex,uint32_t start,uint32_t len) const195 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 
uploadAll(Context * rsc)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 
computeBBox()218 void Mesh::computeBBox() {
219     float *posPtr = NULL;
220     uint32_t vectorSize = 0;
221     uint32_t stride = 0;
222     uint32_t numVerts = 0;
223     // First we need to find the position ptr and stride
224     for (uint32_t ct=0; ct < mHal.state.vertexBuffersCount; ct++) {
225         const Type *bufferType = mHal.state.vertexBuffers[ct]->getType();
226         const Element *bufferElem = bufferType->getElement();
227 
228         for (uint32_t ct=0; ct < bufferElem->getFieldCount(); ct++) {
229             if (strcmp(bufferElem->getFieldName(ct), "position") == 0) {
230                 vectorSize = bufferElem->getField(ct)->getComponent().getVectorSize();
231                 stride = bufferElem->getSizeBytes() / sizeof(float);
232                 uint32_t offset = bufferElem->getFieldOffsetBytes(ct);
233                 posPtr = (float*)((uint8_t*)mHal.state.vertexBuffers[ct]->getPtr() + offset);
234                 numVerts = bufferType->getDimX();
235                 break;
236             }
237         }
238         if (posPtr) {
239             break;
240         }
241     }
242 
243     mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6;
244     mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6;
245     if (!posPtr) {
246         ALOGE("Unable to compute bounding box");
247         mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f;
248         mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f;
249         return;
250     }
251 
252     for (uint32_t i = 0; i < numVerts; i ++) {
253         for (uint32_t v = 0; v < vectorSize; v ++) {
254             mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]);
255             mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]);
256         }
257         posPtr += stride;
258     }
259 }
260 
261 namespace android {
262 namespace renderscript {
263 
rsi_MeshCreate(Context * rsc,RsAllocation * vtx,size_t vtxCount,RsAllocation * idx,size_t idxCount,uint32_t * primType,size_t primTypeCount)264 RsMesh rsi_MeshCreate(Context *rsc,
265                       RsAllocation * vtx, size_t vtxCount,
266                       RsAllocation * idx, size_t idxCount,
267                       uint32_t * primType, size_t primTypeCount) {
268     rsAssert(idxCount == primTypeCount);
269     Mesh *sm = new Mesh(rsc, vtxCount, idxCount);
270     sm->incUserRef();
271 
272     for (uint32_t i = 0; i < vtxCount; i ++) {
273         sm->setVertexBuffer((Allocation*)vtx[i], i);
274     }
275 
276     for (uint32_t i = 0; i < idxCount; i ++) {
277         sm->setPrimitive((Allocation*)idx[i], (RsPrimitive)primType[i], i);
278     }
279 
280     sm->init();
281 
282     return sm;
283 }
284 
285 }}
286 
rsaMeshGetVertexBufferCount(RsContext con,RsMesh mv,int32_t * numVtx)287 void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx) {
288     Mesh *sm = static_cast<Mesh *>(mv);
289     *numVtx = sm->mHal.state.vertexBuffersCount;
290 }
291 
rsaMeshGetIndexCount(RsContext con,RsMesh mv,int32_t * numIdx)292 void rsaMeshGetIndexCount(RsContext con, RsMesh mv, int32_t *numIdx) {
293     Mesh *sm = static_cast<Mesh *>(mv);
294     *numIdx = sm->mHal.state.primitivesCount;
295 }
296 
rsaMeshGetVertices(RsContext con,RsMesh mv,RsAllocation * vtxData,uint32_t vtxDataCount)297 void rsaMeshGetVertices(RsContext con, RsMesh mv, RsAllocation *vtxData, uint32_t vtxDataCount) {
298     Mesh *sm = static_cast<Mesh *>(mv);
299     rsAssert(vtxDataCount == sm->mHal.state.vertexBuffersCount);
300 
301     for (uint32_t ct = 0; ct < vtxDataCount; ct ++) {
302         vtxData[ct] = sm->mHal.state.vertexBuffers[ct];
303         sm->mHal.state.vertexBuffers[ct]->incUserRef();
304     }
305 }
306 
rsaMeshGetIndices(RsContext con,RsMesh mv,RsAllocation * va,uint32_t * primType,uint32_t idxDataCount)307 void rsaMeshGetIndices(RsContext con, RsMesh mv, RsAllocation *va, uint32_t *primType, uint32_t idxDataCount) {
308     Mesh *sm = static_cast<Mesh *>(mv);
309     rsAssert(idxDataCount == sm->mHal.state.primitivesCount);
310 
311     for (uint32_t ct = 0; ct < idxDataCount; ct ++) {
312         va[ct] = sm->mHal.state.indexBuffers[ct];
313         primType[ct] = sm->mHal.state.primitives[ct];
314         if (sm->mHal.state.indexBuffers[ct]) {
315             sm->mHal.state.indexBuffers[ct]->incUserRef();
316         }
317     }
318 }
319