rsElement.cpp revision 50bfc354e61e174a465893fd0dafe913f1954478
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
18#include "rsContext.h"
19
20using namespace android;
21using namespace android::renderscript;
22
23
24Element::Element(Context *rsc) : ObjectBase(rsc) {
25    mBits = 0;
26    mBitsUnpadded = 0;
27    mFields = NULL;
28    mFieldCount = 0;
29    mHasReference = false;
30}
31
32Element::~Element() {
33    clear();
34}
35
36void Element::preDestroy() const {
37    for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
38        if (mRSC->mStateElement.mElements[ct] == this) {
39            mRSC->mStateElement.mElements.removeAt(ct);
40            break;
41        }
42    }
43}
44
45void Element::clear() {
46    delete [] mFields;
47    mFields = NULL;
48    mFieldCount = 0;
49    mHasReference = false;
50
51    delete [] mHal.state.fields;
52    delete [] mHal.state.fieldArraySizes;
53    delete [] mHal.state.fieldNames;
54    delete [] mHal.state.fieldNameLengths;
55    delete [] mHal.state.fieldOffsetBytes;
56}
57
58size_t Element::getSizeBits() const {
59    if (!mFieldCount) {
60        return mBits;
61    }
62
63    size_t total = 0;
64    for (size_t ct=0; ct < mFieldCount; ct++) {
65        total += mFields[ct].e->mBits * mFields[ct].arraySize;
66    }
67    return total;
68}
69
70size_t Element::getSizeBitsUnpadded() const {
71    if (!mFieldCount) {
72        return mBitsUnpadded;
73    }
74
75    size_t total = 0;
76    for (size_t ct=0; ct < mFieldCount; ct++) {
77        total += mFields[ct].e->mBitsUnpadded * mFields[ct].arraySize;
78    }
79    return total;
80}
81
82void Element::dumpLOGV(const char *prefix) const {
83    ObjectBase::dumpLOGV(prefix);
84    ALOGV("%s Element: fieldCount: %zu,  size bytes: %zu", prefix, mFieldCount, getSizeBytes());
85    mComponent.dumpLOGV(prefix);
86    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
87        ALOGV("%s Element field index: %u ------------------", prefix, ct);
88        ALOGV("%s name: %s, offsetBits: %u, arraySize: %u",
89             prefix, mFields[ct].name.string(), mFields[ct].offsetBits, mFields[ct].arraySize);
90        mFields[ct].e->dumpLOGV(prefix);
91    }
92}
93
94void Element::serialize(OStream *stream) const {
95    // Need to identify ourselves
96    stream->addU32((uint32_t)getClassId());
97
98    String8 name(getName());
99    stream->addString(&name);
100
101    mComponent.serialize(stream);
102
103    // Now serialize all the fields
104    stream->addU32(mFieldCount);
105    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
106        stream->addString(&mFields[ct].name);
107        stream->addU32(mFields[ct].arraySize);
108        mFields[ct].e->serialize(stream);
109    }
110}
111
112Element *Element::createFromStream(Context *rsc, IStream *stream) {
113    // First make sure we are reading the correct object
114    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
115    if (classID != RS_A3D_CLASS_ID_ELEMENT) {
116        LOGE("element loading skipped due to invalid class id\n");
117        return NULL;
118    }
119
120    String8 name;
121    stream->loadString(&name);
122
123    Component component;
124    component.loadFromStream(stream);
125
126    uint32_t fieldCount = stream->loadU32();
127    if (!fieldCount) {
128        return (Element *)Element::create(rsc,
129                                          component.getType(),
130                                          component.getKind(),
131                                          component.getIsNormalized(),
132                                          component.getVectorSize());;
133    }
134
135    const Element **subElems = new const Element *[fieldCount];
136    const char **subElemNames = new const char *[fieldCount];
137    size_t *subElemNamesLengths = new size_t[fieldCount];
138    uint32_t *arraySizes = new uint32_t[fieldCount];
139
140    String8 elemName;
141    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
142        stream->loadString(&elemName);
143        subElemNamesLengths[ct] = elemName.length();
144        char *tmpName = new char[subElemNamesLengths[ct]];
145        memcpy(tmpName, elemName.string(), subElemNamesLengths[ct]);
146        subElemNames[ct] = tmpName;
147        arraySizes[ct] = stream->loadU32();
148        subElems[ct] = Element::createFromStream(rsc, stream);
149    }
150
151    const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames,
152                                          subElemNamesLengths, arraySizes);
153    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
154        delete [] subElemNames[ct];
155        subElems[ct]->decUserRef();
156    }
157    delete[] subElems;
158    delete[] subElemNames;
159    delete[] subElemNamesLengths;
160    delete[] arraySizes;
161
162    return (Element *)elem;
163}
164
165void Element::compute() {
166    mHal.state.dataType = mComponent.getType();
167    mHal.state.dataKind = mComponent.getKind();
168    mHal.state.vectorSize = mComponent.getVectorSize();
169
170    if (mFieldCount == 0) {
171        mBits = mComponent.getBits();
172        mBitsUnpadded = mComponent.getBitsUnpadded();
173        mHasReference = mComponent.isReference();
174
175        mHal.state.elementSizeBytes = getSizeBytes();
176        return;
177    }
178
179    mHal.state.fields = new const Element*[mFieldCount];
180    mHal.state.fieldArraySizes = new uint32_t[mFieldCount];
181    mHal.state.fieldNames = new const char*[mFieldCount];
182    mHal.state.fieldNameLengths = new uint32_t[mFieldCount];
183    mHal.state.fieldOffsetBytes = new uint32_t[mFieldCount];
184    mHal.state.fieldsCount = mFieldCount;
185
186    size_t bits = 0;
187    size_t bitsUnpadded = 0;
188    for (size_t ct=0; ct < mFieldCount; ct++) {
189        mFields[ct].offsetBits = bits;
190        mFields[ct].offsetBitsUnpadded = bitsUnpadded;
191        bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize;
192        bitsUnpadded += mFields[ct].e->getSizeBitsUnpadded() * mFields[ct].arraySize;
193
194        if (mFields[ct].e->mHasReference) {
195            mHasReference = true;
196        }
197
198        mHal.state.fields[ct] = mFields[ct].e.get();
199        mHal.state.fieldArraySizes[ct] = mFields[ct].arraySize;
200        mHal.state.fieldNames[ct] = mFields[ct].name.string();
201        mHal.state.fieldNameLengths[ct] = mFields[ct].name.length() + 1; // to include 0
202        mHal.state.fieldOffsetBytes[ct] = mFields[ct].offsetBits >> 3;
203    }
204
205    mHal.state.elementSizeBytes = getSizeBytes();
206}
207
208ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk,
209                                bool isNorm, uint32_t vecSize) {
210    ObjectBaseRef<const Element> returnRef;
211    // Look for an existing match.
212    ObjectBase::asyncLock();
213    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
214        const Element *ee = rsc->mStateElement.mElements[ct];
215        if (!ee->getFieldCount() &&
216            (ee->getComponent().getType() == dt) &&
217            (ee->getComponent().getKind() == dk) &&
218            (ee->getComponent().getIsNormalized() == isNorm) &&
219            (ee->getComponent().getVectorSize() == vecSize)) {
220            // Match
221            returnRef.set(ee);
222            ObjectBase::asyncUnlock();
223            return ee;
224        }
225    }
226    ObjectBase::asyncUnlock();
227
228    Element *e = new Element(rsc);
229    returnRef.set(e);
230    e->mComponent.set(dt, dk, isNorm, vecSize);
231    e->compute();
232
233    ObjectBase::asyncLock();
234    rsc->mStateElement.mElements.push(e);
235    ObjectBase::asyncUnlock();
236
237    return returnRef;
238}
239
240ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein,
241                            const char **nin, const size_t * lengths, const uint32_t *asin) {
242
243    ObjectBaseRef<const Element> returnRef;
244    // Look for an existing match.
245    ObjectBase::asyncLock();
246    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
247        const Element *ee = rsc->mStateElement.mElements[ct];
248        if (ee->getFieldCount() == count) {
249            bool match = true;
250            for (uint32_t i=0; i < count; i++) {
251                if ((ee->mFields[i].e.get() != ein[i]) ||
252                    (ee->mFields[i].name.length() != lengths[i]) ||
253                    (ee->mFields[i].name != nin[i]) ||
254                    (ee->mFields[i].arraySize != asin[i])) {
255                    match = false;
256                    break;
257                }
258            }
259            if (match) {
260                returnRef.set(ee);
261                ObjectBase::asyncUnlock();
262                return returnRef;
263            }
264        }
265    }
266    ObjectBase::asyncUnlock();
267
268    Element *e = new Element(rsc);
269    returnRef.set(e);
270    e->mFields = new ElementField_t [count];
271    e->mFieldCount = count;
272    for (size_t ct=0; ct < count; ct++) {
273        e->mFields[ct].e.set(ein[ct]);
274        e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
275        e->mFields[ct].arraySize = asin[ct];
276    }
277    e->compute();
278
279    ObjectBase::asyncLock();
280    rsc->mStateElement.mElements.push(e);
281    ObjectBase::asyncUnlock();
282
283    return returnRef;
284}
285
286void Element::incRefs(const void *ptr) const {
287    if (!mFieldCount) {
288        if (mComponent.isReference()) {
289            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
290            ObjectBase *ob = obp[0];
291            if (ob) ob->incSysRef();
292        }
293        return;
294    }
295
296    const uint8_t *p = static_cast<const uint8_t *>(ptr);
297    for (uint32_t i=0; i < mFieldCount; i++) {
298        if (mFields[i].e->mHasReference) {
299            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
300            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
301                mFields[i].e->incRefs(p2);
302                p2 += mFields[i].e->getSizeBytes();
303            }
304        }
305    }
306}
307
308void Element::decRefs(const void *ptr) const {
309    if (!mFieldCount) {
310        if (mComponent.isReference()) {
311            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
312            ObjectBase *ob = obp[0];
313            if (ob) ob->decSysRef();
314        }
315        return;
316    }
317
318    const uint8_t *p = static_cast<const uint8_t *>(ptr);
319    for (uint32_t i=0; i < mFieldCount; i++) {
320        if (mFields[i].e->mHasReference) {
321            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
322            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
323                mFields[i].e->decRefs(p2);
324                p2 += mFields[i].e->getSizeBytes();
325            }
326        }
327    }
328}
329
330Element::Builder::Builder() {
331    const uint32_t initialCapacity = 32;
332    mBuilderElementRefs.setCapacity(initialCapacity);
333    mBuilderElements.setCapacity(initialCapacity);
334    mBuilderNameStrings.setCapacity(initialCapacity);
335    mBuilderNameLengths.setCapacity(initialCapacity);
336    mBuilderArrays.setCapacity(initialCapacity);
337}
338
339void Element::Builder::add(const Element *e, const char *nameStr, uint32_t arraySize) {
340    mBuilderElementRefs.push(ObjectBaseRef<const Element>(e));
341    mBuilderElements.push(e);
342    mBuilderNameStrings.push(nameStr);
343    mBuilderNameLengths.push(strlen(nameStr));
344    mBuilderArrays.push(arraySize);
345
346}
347
348ObjectBaseRef<const Element> Element::Builder::create(Context *rsc) {
349    return Element::createRef(rsc, mBuilderElements.size(),
350                              &(mBuilderElements.editArray()[0]),
351                              &(mBuilderNameStrings.editArray()[0]),
352                              mBuilderNameLengths.editArray(),
353                              mBuilderArrays.editArray());
354}
355
356
357ElementState::ElementState() {
358}
359
360ElementState::~ElementState() {
361    rsAssert(!mElements.size());
362}
363
364/////////////////////////////////////////
365//
366
367namespace android {
368namespace renderscript {
369
370RsElement rsi_ElementCreate(Context *rsc,
371                            RsDataType dt,
372                            RsDataKind dk,
373                            bool norm,
374                            uint32_t vecSize) {
375    return (RsElement)Element::create(rsc, dt, dk, norm, vecSize);
376}
377
378
379RsElement rsi_ElementCreate2(Context *rsc,
380                             const RsElement * ein,
381                             size_t ein_length,
382
383                             const char ** names,
384                             size_t nameLengths_length,
385                             const size_t * nameLengths,
386
387                             const uint32_t * arraySizes,
388                             size_t arraySizes_length) {
389    return (RsElement)Element::create(rsc, ein_length, (const Element **)ein,
390                                      names, nameLengths, arraySizes);
391}
392
393}
394}
395
396void rsaElementGetNativeData(RsContext con, RsElement elem,
397                             uint32_t *elemData, uint32_t elemDataSize) {
398    rsAssert(elemDataSize == 5);
399    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
400    Element *e = static_cast<Element *>(elem);
401
402    (*elemData++) = (uint32_t)e->getType();
403    (*elemData++) = (uint32_t)e->getKind();
404    (*elemData++) = e->getComponent().getIsNormalized() ? 1 : 0;
405    (*elemData++) = e->getComponent().getVectorSize();
406    (*elemData++) = e->getFieldCount();
407}
408
409void rsaElementGetSubElements(RsContext con, RsElement elem, uint32_t *ids,
410                              const char **names, uint32_t *arraySizes, uint32_t dataSize) {
411    Element *e = static_cast<Element *>(elem);
412    rsAssert(e->getFieldCount() == dataSize);
413
414    for (uint32_t i = 0; i < dataSize; i ++) {
415        e->getField(i)->incUserRef();
416        ids[i] = (uint32_t)e->getField(i);
417        names[i] = e->getFieldName(i);
418        arraySizes[i] = e->getFieldArraySize(i);
419    }
420}
421