rsElement.cpp revision a36c50a6ab87f4c9049318d4c6c8ec7b0a1e6e12
1589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian/*
2589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * Copyright (C) 2009 The Android Open Source Project
3589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian *
4589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
5589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * you may not use this file except in compliance with the License.
6589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * You may obtain a copy of the License at
7589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian *
8589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
9589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian *
10589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * Unless required by applicable law or agreed to in writing, software
11589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
12589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * See the License for the specific language governing permissions and
14589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * limitations under the License.
15589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian */
16589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
17801ea093b0e923a61b832f2adba698a273479880Mathias Agopian
18801ea093b0e923a61b832f2adba698a273479880Mathias Agopian#include "rsContext.h"
19589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
207b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopianusing namespace android;
2127c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozausing namespace android::renderscript;
22589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
23589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
2499fe3c6d3dcb6fb26bf283343f946d031b052dffMathias AgopianElement::Element(Context *rsc) : ObjectBase(rsc) {
25589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    mBits = 0;
26589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    mBitsUnpadded = 0;
27589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    mFields = NULL;
28589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    mFieldCount = 0;
29589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    mHasReference = false;
30589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    memset(&mHal, 0, sizeof(mHal));
3127c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza}
32589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
3327c8115510cebda13cbe24fd4caa946ea9c5003cDan StozaElement::~Element() {
3427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    clear();
3590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian}
367b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian
377d290174b08a56ae6bc6719bec58805ca38b348bDan Stozavoid Element::preDestroy() const {
3890ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
39589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian        if (mRSC->mStateElement.mElements[ct] == this) {
40589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian            mRSC->mStateElement.mElements.removeAt(ct);
417d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza            break;
42589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian        }
437d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    }
447d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza}
45589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
46589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopianvoid Element::clear() {
4790ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    if (mFields) {
4890ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian        for (size_t i = 0; i < mFieldCount; i++) {
4990ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian            delete[] mFields[i].name;
5090ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian        }
5190ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian        delete [] mFields;
5290ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    }
5327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    mFields = NULL;
5490ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    mFieldCount = 0;
5590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    mHasReference = false;
5690ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian
5790ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    delete [] mHal.state.fields;
587d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    delete [] mHal.state.fieldArraySizes;
597d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    delete [] mHal.state.fieldNames;
6090ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    delete [] mHal.state.fieldNameLengths;
617d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    delete [] mHal.state.fieldOffsetBytes;
627d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza}
6390ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian
6490ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopiansize_t Element::getSizeBits() const {
6590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    if (!mFieldCount) {
6627c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza        return mBits;
675cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    }
685cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian
695cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    size_t total = 0;
705cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    for (size_t ct=0; ct < mFieldCount; ct++) {
715cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian        total += mFields[ct].e->mBits * mFields[ct].arraySize;
725cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    }
7327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    return total;
74589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian}
75589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
76589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopiansize_t Element::getSizeBitsUnpadded() const {
7727c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    if (!mFieldCount) {
7856ae42613c91f6a6fb0dc3f626daa24666fd18c2Aravind Akella        return mBitsUnpadded;
7956ae42613c91f6a6fb0dc3f626daa24666fd18c2Aravind Akella    }
8056ae42613c91f6a6fb0dc3f626daa24666fd18c2Aravind Akella
816b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza    size_t total = 0;
826b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza    for (size_t ct=0; ct < mFieldCount; ct++) {
836b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza        total += mFields[ct].e->mBitsUnpadded * mFields[ct].arraySize;
846b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza    }
856b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza    return total;
866b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza}
876b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza
886b698e4fe4ff50dcef818452283637f9870ae770Dan Stozavoid Element::dumpLOGV(const char *prefix) const {
8927c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    ObjectBase::dumpLOGV(prefix);
905cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    ALOGV("%s Element: fieldCount: %zu,  size bytes: %zu", prefix, mFieldCount, getSizeBytes());
915cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    mComponent.dumpLOGV(prefix);
927b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
9390ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian        ALOGV("%s Element field index: %u ------------------", prefix, ct);
945cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian        ALOGV("%s name: %s, offsetBits: %u, arraySize: %u",
955cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian             prefix, mFields[ct].name, mFields[ct].offsetBits, mFields[ct].arraySize);
965cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian        mFields[ct].e->dumpLOGV(prefix);
97589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    }
98589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian}
9927c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza
1005cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopianvoid Element::serialize(Context *rsc, OStream *stream) const {
1015cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    // Need to identify ourselves
1027b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian    stream->addU32((uint32_t)getClassId());
1035cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian    stream->addString(getName());
1045cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian
1053ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian    mComponent.serialize(stream);
10627c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza
10727c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    // Now serialize all the fields
1083ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian    stream->addU32(mFieldCount);
1093ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
1105cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian        stream->addString(mFields[ct].name);
111589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian        stream->addU32(mFields[ct].arraySize);
112589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian        mFields[ct].e->serialize(rsc, stream);
11327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    }
11427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza}
115589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian
116589ce85ee4174829cfedce91b6b2509d2a4002ebMathias AgopianElement *Element::createFromStream(Context *rsc, IStream *stream) {
1177d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    // First make sure we are reading the correct object
118589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
119589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian    if (classID != RS_A3D_CLASS_ID_ELEMENT) {
120589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian        ALOGE("element loading skipped due to invalid class id\n");
1217d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza        return NULL;
1227d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    }
1237d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza
1247d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    const char *name = stream->loadString();
1257d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza
1267d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    Component component;
1277d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    component.loadFromStream(stream);
1287d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza
1297d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    uint32_t fieldCount = stream->loadU32();
1307d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza    if (!fieldCount) {
1317d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza        return (Element *)Element::create(rsc,
1326b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza                                          component.getType(),
13390ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian                                          component.getKind(),
13427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza                                          component.getIsNormalized(),
13590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian                                          component.getVectorSize());
13690ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    }
137d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza
13827c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    const Element **subElems = new const Element *[fieldCount];
13927c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    const char **subElemNames = new const char *[fieldCount];
14027c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    size_t *subElemNamesLengths = new size_t[fieldCount];
14190ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    uint32_t *arraySizes = new uint32_t[fieldCount];
14227c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza
143d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
1447b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian        subElemNames[ct] = stream->loadString();
1457b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian        subElemNamesLengths[ct] = strlen(subElemNames[ct]);
1466b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza        arraySizes[ct] = stream->loadU32();
14790ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian        subElems[ct] = Element::createFromStream(rsc, stream);
14827c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    }
14990ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian
15090ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames,
151d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza                                          subElemNamesLengths, arraySizes);
15227c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
15327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza        delete [] subElemNames[ct];
15427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza        subElems[ct]->decUserRef();
15590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian    }
15627c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    delete[] name;
157d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza    delete[] subElems;
1587b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian    delete[] subElemNames;
1597b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian    delete[] subElemNamesLengths;
16027c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza    delete[] arraySizes;
16127c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza
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    uint32_t noPaddingFieldCount = 0;
180    for (uint32_t ct = 0; ct < mFieldCount; ct ++) {
181        if (mFields[ct].name[0] != '#') {
182            noPaddingFieldCount ++;
183        }
184    }
185
186    mHal.state.fields = new const Element*[noPaddingFieldCount];
187    mHal.state.fieldArraySizes = new uint32_t[noPaddingFieldCount];
188    mHal.state.fieldNames = new const char*[noPaddingFieldCount];
189    mHal.state.fieldNameLengths = new uint32_t[noPaddingFieldCount];
190    mHal.state.fieldOffsetBytes = new uint32_t[noPaddingFieldCount];
191    mHal.state.fieldsCount = noPaddingFieldCount;
192
193    size_t bits = 0;
194    size_t bitsUnpadded = 0;
195    for (size_t ct = 0, ctNoPadding = 0; ct < mFieldCount; ct++) {
196        mFields[ct].offsetBits = bits;
197        mFields[ct].offsetBitsUnpadded = bitsUnpadded;
198        bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize;
199        bitsUnpadded += mFields[ct].e->getSizeBitsUnpadded() * mFields[ct].arraySize;
200
201        if (mFields[ct].e->mHasReference) {
202            mHasReference = true;
203        }
204
205        if (mFields[ct].name[0] == '#') {
206            continue;
207        }
208
209        mHal.state.fields[ctNoPadding] = mFields[ct].e.get();
210        mHal.state.fieldArraySizes[ctNoPadding] = mFields[ct].arraySize;
211        mHal.state.fieldNames[ctNoPadding] = mFields[ct].name;
212        mHal.state.fieldNameLengths[ctNoPadding] = strlen(mFields[ct].name) + 1; // to include 0
213        mHal.state.fieldOffsetBytes[ctNoPadding] = mFields[ct].offsetBits >> 3;
214
215        ctNoPadding ++;
216    }
217
218    mHal.state.elementSizeBytes = getSizeBytes();
219}
220
221ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk,
222                                bool isNorm, uint32_t vecSize) {
223    ObjectBaseRef<const Element> returnRef;
224    // Look for an existing match.
225    ObjectBase::asyncLock();
226    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
227        const Element *ee = rsc->mStateElement.mElements[ct];
228        if (!ee->getFieldCount() &&
229            (ee->getComponent().getType() == dt) &&
230            (ee->getComponent().getKind() == dk) &&
231            (ee->getComponent().getIsNormalized() == isNorm) &&
232            (ee->getComponent().getVectorSize() == vecSize)) {
233            // Match
234            returnRef.set(ee);
235            ObjectBase::asyncUnlock();
236            return ee;
237        }
238    }
239    ObjectBase::asyncUnlock();
240
241    // Element objects must use allocator specified by the driver
242    void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Element), 0);
243    if (!allocMem) {
244        rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Element");
245        return NULL;
246    }
247
248    Element *e = new (allocMem) Element(rsc);
249    returnRef.set(e);
250    e->mComponent.set(dt, dk, isNorm, vecSize);
251    e->compute();
252
253#ifdef RS_FIND_OFFSETS
254    ALOGE("pointer for element: %p", e);
255    ALOGE("pointer for element.drv: %p", &e->mHal.drv);
256#endif
257
258
259    ObjectBase::asyncLock();
260    rsc->mStateElement.mElements.push(e);
261    ObjectBase::asyncUnlock();
262
263    return returnRef;
264}
265
266ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein,
267                            const char **nin, const size_t * lengths, const uint32_t *asin) {
268
269    ObjectBaseRef<const Element> returnRef;
270    // Look for an existing match.
271    ObjectBase::asyncLock();
272    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
273        const Element *ee = rsc->mStateElement.mElements[ct];
274        if (ee->getFieldCount() == count) {
275            bool match = true;
276            for (uint32_t i=0; i < count; i++) {
277                size_t len;
278                uint32_t asize = 1;
279                if (lengths) {
280                    len = lengths[i];
281                } else {
282                    len = strlen(nin[i]);
283                }
284                if (asin) {
285                    asize = asin[i];
286                }
287
288                if ((ee->mFields[i].e.get() != ein[i]) ||
289                    (strlen(ee->mFields[i].name) != len) ||
290                    strcmp(ee->mFields[i].name, nin[i]) ||
291                    (ee->mFields[i].arraySize != asize)) {
292                    match = false;
293                    break;
294                }
295            }
296            if (match) {
297                returnRef.set(ee);
298                ObjectBase::asyncUnlock();
299                return returnRef;
300            }
301        }
302    }
303    ObjectBase::asyncUnlock();
304
305    // Element objects must use allocator specified by the driver
306    void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Element), 0);
307    if (!allocMem) {
308        rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Element");
309        return NULL;
310    }
311
312    Element *e = new (allocMem) Element(rsc);
313    returnRef.set(e);
314    e->mFields = new ElementField_t [count];
315    e->mFieldCount = count;
316    for (size_t ct=0; ct < count; ct++) {
317        size_t len;
318        uint32_t asize = 1;
319        if (lengths) {
320            len = lengths[ct];
321        } else {
322            len = strlen(nin[ct]);
323        }
324        if (asin) {
325            asize = asin[ct];
326        }
327
328        e->mFields[ct].e.set(ein[ct]);
329        e->mFields[ct].name = rsuCopyString(nin[ct], len);
330        e->mFields[ct].arraySize = asize;
331    }
332    e->compute();
333
334    ObjectBase::asyncLock();
335    rsc->mStateElement.mElements.push(e);
336    ObjectBase::asyncUnlock();
337
338    return returnRef;
339}
340
341void Element::incRefs(const void *ptr) const {
342    if (!mFieldCount) {
343        if (mComponent.isReference()) {
344            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
345            ObjectBase *ob = obp[0];
346            if (ob) ob->incSysRef();
347        }
348        return;
349    }
350
351    const uint8_t *p = static_cast<const uint8_t *>(ptr);
352    for (uint32_t i=0; i < mFieldCount; i++) {
353        if (mFields[i].e->mHasReference) {
354            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
355            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
356                mFields[i].e->incRefs(p2);
357                p2 += mFields[i].e->getSizeBytes();
358            }
359        }
360    }
361}
362
363void Element::decRefs(const void *ptr) const {
364    if (!mFieldCount) {
365        if (mComponent.isReference()) {
366            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
367            ObjectBase *ob = obp[0];
368            if (ob) ob->decSysRef();
369        }
370        return;
371    }
372
373    const uint8_t *p = static_cast<const uint8_t *>(ptr);
374    for (uint32_t i=0; i < mFieldCount; i++) {
375        if (mFields[i].e->mHasReference) {
376            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
377            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
378                mFields[i].e->decRefs(p2);
379                p2 += mFields[i].e->getSizeBytes();
380            }
381        }
382    }
383}
384
385void Element::callUpdateCacheObject(const Context *rsc, void *dstObj) const {
386    if (rsc->mHal.funcs.element.updateCachedObject != NULL) {
387        rsc->mHal.funcs.element.updateCachedObject(rsc, this, (rs_element *)dstObj);
388    } else {
389        *((const void **)dstObj) = this;
390    }
391}
392
393ElementState::ElementState() {
394}
395
396ElementState::~ElementState() {
397    rsAssert(!mElements.size());
398}
399
400/////////////////////////////////////////
401//
402
403namespace android {
404namespace renderscript {
405
406RsElement rsi_ElementCreate(Context *rsc,
407                            RsDataType dt,
408                            RsDataKind dk,
409                            bool norm,
410                            uint32_t vecSize) {
411    return (RsElement)Element::create(rsc, dt, dk, norm, vecSize);
412}
413
414
415RsElement rsi_ElementCreate2(Context *rsc,
416                             const RsElement * ein,
417                             size_t ein_length,
418
419                             const char ** names,
420                             size_t nameLengths_length,
421                             const size_t * nameLengths,
422
423                             const uint32_t * arraySizes,
424                             size_t arraySizes_length) {
425    return (RsElement)Element::create(rsc, ein_length, (const Element **)ein,
426                                      names, nameLengths, arraySizes);
427}
428
429}
430}
431
432extern "C" void rsaElementGetNativeData(RsContext con, RsElement elem,
433                             uint32_t *elemData, uint32_t elemDataSize) {
434    rsAssert(elemDataSize == 5);
435    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
436    Element *e = static_cast<Element *>(elem);
437
438    (*elemData++) = (uint32_t)e->getType();
439    (*elemData++) = (uint32_t)e->getKind();
440    (*elemData++) = e->getComponent().getIsNormalized() ? 1 : 0;
441    (*elemData++) = e->getComponent().getVectorSize();
442    (*elemData++) = e->getFieldCount();
443}
444
445extern "C" void rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids,
446                              const char **names, size_t *arraySizes, uint32_t dataSize) {
447    Element *e = static_cast<Element *>(elem);
448    rsAssert(e->getFieldCount() == dataSize);
449
450    for (uint32_t i = 0; i < dataSize; i ++) {
451        e->getField(i)->incUserRef();
452        ids[i] = (uintptr_t)e->getField(i);
453        names[i] = e->getFieldName(i);
454        arraySizes[i] = e->getFieldArraySize(i);
455    }
456}
457