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 namespace android {
22 namespace renderscript {
23
Mesh(Context * rsc)24 Mesh::Mesh(Context *rsc) : ObjectBase(rsc) {
25 mHal.drv = nullptr;
26 mHal.state.primitives = nullptr;
27 mHal.state.primitivesCount = 0;
28 mHal.state.indexBuffers = nullptr;
29 mHal.state.indexBuffersCount = 0;
30 mHal.state.vertexBuffers = nullptr;
31 mHal.state.vertexBuffersCount = 0;
32 mInitialized = false;
33
34 mVertexBuffers = nullptr;
35 mIndexBuffers = nullptr;
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 = nullptr;
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] = nullptr;
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] = nullptr;
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(Context * rsc,OStream * stream) const81 void Mesh::serialize(Context *rsc, OStream *stream) const {
82 // Need to identify ourselves
83 stream->addU32((uint32_t)getClassId());
84 stream->addString(getName());
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(rsc, 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(rsc, stream);
100 } else {
101 stream->addU32(0);
102 }
103 }
104 }
105
createFromStream(Context * rsc,IStream * stream)106 Mesh *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 ALOGE("mesh loading skipped due to invalid class id");
111 return nullptr;
112 }
113
114 const char *name = stream->loadString();
115
116 uint32_t vertexBuffersCount = stream->loadU32();
117 ObjectBaseRef<Allocation> *vertexBuffers = nullptr;
118 if (vertexBuffersCount) {
119 vertexBuffers = new ObjectBaseRef<Allocation>[vertexBuffersCount];
120
121 for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
122 Allocation *vertexAlloc = Allocation::createFromStream(rsc, stream);
123 vertexBuffers[vCount].set(vertexAlloc);
124 }
125 }
126
127 uint32_t primitivesCount = stream->loadU32();
128 ObjectBaseRef<Allocation> *indexBuffers = nullptr;
129 RsPrimitive *primitives = nullptr;
130 if (primitivesCount) {
131 indexBuffers = new ObjectBaseRef<Allocation>[primitivesCount];
132 primitives = new RsPrimitive[primitivesCount];
133
134 // load all primitives
135 for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
136 primitives[pCount] = (RsPrimitive)stream->loadU8();
137
138 // Check to see if the index buffer was stored
139 uint32_t isIndexPresent = stream->loadU32();
140 if (isIndexPresent) {
141 Allocation *indexAlloc = Allocation::createFromStream(rsc, stream);
142 indexBuffers[pCount].set(indexAlloc);
143 }
144 }
145 }
146
147 Mesh *mesh = new Mesh(rsc, vertexBuffersCount, primitivesCount);
148 mesh->assignName(name);
149 for (uint32_t vCount = 0; vCount < vertexBuffersCount; vCount ++) {
150 mesh->setVertexBuffer(vertexBuffers[vCount].get(), vCount);
151 }
152 for (uint32_t pCount = 0; pCount < primitivesCount; pCount ++) {
153 mesh->setPrimitive(indexBuffers[pCount].get(), primitives[pCount], pCount);
154 }
155
156 // Cleanup
157 if (vertexBuffersCount) {
158 delete[] vertexBuffers;
159 }
160 if (primitivesCount) {
161 delete[] indexBuffers;
162 delete[] primitives;
163 }
164
165 #ifndef ANDROID_RS_SERIALIZE
166 mesh->init();
167 mesh->uploadAll(rsc);
168 #endif
169 return mesh;
170 }
171
render(Context * rsc) const172 void Mesh::render(Context *rsc) const {
173 for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
174 renderPrimitive(rsc, ct);
175 }
176 }
177
renderPrimitive(Context * rsc,uint32_t primIndex) const178 void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const {
179 if (primIndex >= mHal.state.primitivesCount) {
180 ALOGE("Invalid primitive index");
181 return;
182 }
183
184 if (mHal.state.indexBuffers[primIndex]) {
185 renderPrimitiveRange(rsc, primIndex, 0, mHal.state.indexBuffers[primIndex]->getType()->getDimX());
186 return;
187 }
188
189 renderPrimitiveRange(rsc, primIndex, 0, mHal.state.vertexBuffers[0]->getType()->getDimX());
190 }
191
renderPrimitiveRange(Context * rsc,uint32_t primIndex,uint32_t start,uint32_t len) const192 void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const {
193 if (len < 1 || primIndex >= mHal.state.primitivesCount) {
194 ALOGE("Invalid mesh or parameters");
195 return;
196 }
197
198 mRSC->mHal.funcs.mesh.draw(mRSC, this, primIndex, start, len);
199 }
200
uploadAll(Context * rsc)201 void Mesh::uploadAll(Context *rsc) {
202 for (uint32_t ct = 0; ct < mHal.state.vertexBuffersCount; ct ++) {
203 if (mHal.state.vertexBuffers[ct]) {
204 rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.vertexBuffers[ct]);
205 }
206 }
207
208 for (uint32_t ct = 0; ct < mHal.state.primitivesCount; ct ++) {
209 if (mHal.state.indexBuffers[ct]) {
210 rsc->mHal.funcs.allocation.markDirty(rsc, mHal.state.indexBuffers[ct]);
211 }
212 }
213 }
214
computeBBox(Context * rsc)215 void Mesh::computeBBox(Context *rsc) {
216 float *posPtr = nullptr;
217 uint32_t vectorSize = 0;
218 uint32_t stride = 0;
219 uint32_t numVerts = 0;
220 Allocation *posAlloc = nullptr;
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 posAlloc = mHal.state.vertexBuffers[ct];
232 const uint8_t *bp = (const uint8_t *)rsc->mHal.funcs.allocation.lock1D(
233 rsc, posAlloc);
234 posPtr = (float*)(bp + offset);
235 numVerts = bufferType->getDimX();
236 break;
237 }
238 }
239 if (posPtr) {
240 break;
241 }
242 }
243
244 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 1e6;
245 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = -1e6;
246 if (!posPtr) {
247 ALOGE("Unable to compute bounding box");
248 mBBoxMin[0] = mBBoxMin[1] = mBBoxMin[2] = 0.0f;
249 mBBoxMax[0] = mBBoxMax[1] = mBBoxMax[2] = 0.0f;
250 return;
251 }
252
253 for (uint32_t i = 0; i < numVerts; i ++) {
254 for (uint32_t v = 0; v < vectorSize; v ++) {
255 mBBoxMin[v] = rsMin(mBBoxMin[v], posPtr[v]);
256 mBBoxMax[v] = rsMax(mBBoxMax[v], posPtr[v]);
257 }
258 posPtr += stride;
259 }
260
261 if (posAlloc) {
262 rsc->mHal.funcs.allocation.unlock1D(rsc, posAlloc);
263 }
264 }
265
rsi_MeshCreate(Context * rsc,RsAllocation * vtx,size_t vtxCount,RsAllocation * idx,size_t idxCount,uint32_t * primType,size_t primTypeCount)266 RsMesh rsi_MeshCreate(Context *rsc,
267 RsAllocation * vtx, size_t vtxCount,
268 RsAllocation * idx, size_t idxCount,
269 uint32_t * primType, size_t primTypeCount) {
270 rsAssert(idxCount == primTypeCount);
271 Mesh *sm = new Mesh(rsc, vtxCount, idxCount);
272 sm->incUserRef();
273
274 for (uint32_t i = 0; i < vtxCount; i ++) {
275 sm->setVertexBuffer((Allocation*)vtx[i], i);
276 }
277
278 for (uint32_t i = 0; i < idxCount; i ++) {
279 sm->setPrimitive((Allocation*)idx[i], (RsPrimitive)primType[i], i);
280 }
281
282 sm->init();
283
284 return sm;
285 }
286
287 } // namespace renderscript
288 } // namespace android
289