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