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    memset(&mHal, 0, sizeof(mHal));
31}
32
33Element::~Element() {
34    clear();
35}
36
37void Element::preDestroy() const {
38    for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
39        if (mRSC->mStateElement.mElements[ct] == this) {
40            mRSC->mStateElement.mElements.removeAt(ct);
41            break;
42        }
43    }
44}
45
46void Element::clear() {
47    if (mFields) {
48        for (size_t i = 0; i < mFieldCount; i++) {
49            delete[] mFields[i].name;
50        }
51        delete [] mFields;
52    }
53    mFields = NULL;
54    mFieldCount = 0;
55    mHasReference = false;
56
57    delete [] mHal.state.fields;
58    delete [] mHal.state.fieldArraySizes;
59    delete [] mHal.state.fieldNames;
60    delete [] mHal.state.fieldNameLengths;
61    delete [] mHal.state.fieldOffsetBytes;
62}
63
64size_t Element::getSizeBits() const {
65    if (!mFieldCount) {
66        return mBits;
67    }
68
69    size_t total = 0;
70    for (size_t ct=0; ct < mFieldCount; ct++) {
71        total += mFields[ct].e->mBits * mFields[ct].arraySize;
72    }
73    return total;
74}
75
76size_t Element::getSizeBitsUnpadded() const {
77    if (!mFieldCount) {
78        return mBitsUnpadded;
79    }
80
81    size_t total = 0;
82    for (size_t ct=0; ct < mFieldCount; ct++) {
83        total += mFields[ct].e->mBitsUnpadded * mFields[ct].arraySize;
84    }
85    return total;
86}
87
88void Element::dumpLOGV(const char *prefix) const {
89    ObjectBase::dumpLOGV(prefix);
90    ALOGV("%s Element: fieldCount: %zu,  size bytes: %zu", prefix, mFieldCount, getSizeBytes());
91    mComponent.dumpLOGV(prefix);
92    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
93        ALOGV("%s Element field index: %u ------------------", prefix, ct);
94        ALOGV("%s name: %s, offsetBits: %u, arraySize: %u",
95             prefix, mFields[ct].name, mFields[ct].offsetBits, mFields[ct].arraySize);
96        mFields[ct].e->dumpLOGV(prefix);
97    }
98}
99
100void Element::serialize(Context *rsc, OStream *stream) const {
101    // Need to identify ourselves
102    stream->addU32((uint32_t)getClassId());
103    stream->addString(getName());
104
105    mComponent.serialize(stream);
106
107    // Now serialize all the fields
108    stream->addU32(mFieldCount);
109    for (uint32_t ct = 0; ct < mFieldCount; ct++) {
110        stream->addString(mFields[ct].name);
111        stream->addU32(mFields[ct].arraySize);
112        mFields[ct].e->serialize(rsc, stream);
113    }
114}
115
116Element *Element::createFromStream(Context *rsc, IStream *stream) {
117    // First make sure we are reading the correct object
118    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
119    if (classID != RS_A3D_CLASS_ID_ELEMENT) {
120        ALOGE("element loading skipped due to invalid class id\n");
121        return NULL;
122    }
123
124    const char *name = stream->loadString();
125
126    Component component;
127    component.loadFromStream(stream);
128
129    uint32_t fieldCount = stream->loadU32();
130    if (!fieldCount) {
131        return (Element *)Element::create(rsc,
132                                          component.getType(),
133                                          component.getKind(),
134                                          component.getIsNormalized(),
135                                          component.getVectorSize());
136    }
137
138    const Element **subElems = new const Element *[fieldCount];
139    const char **subElemNames = new const char *[fieldCount];
140    size_t *subElemNamesLengths = new size_t[fieldCount];
141    uint32_t *arraySizes = new uint32_t[fieldCount];
142
143    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
144        subElemNames[ct] = stream->loadString();
145        subElemNamesLengths[ct] = strlen(subElemNames[ct]);
146        arraySizes[ct] = stream->loadU32();
147        subElems[ct] = Element::createFromStream(rsc, stream);
148    }
149
150    const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames,
151                                          subElemNamesLengths, arraySizes);
152    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
153        delete [] subElemNames[ct];
154        subElems[ct]->decUserRef();
155    }
156    delete[] name;
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    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 *e = new Element(rsc);
242    returnRef.set(e);
243    e->mComponent.set(dt, dk, isNorm, vecSize);
244    e->compute();
245
246    ObjectBase::asyncLock();
247    rsc->mStateElement.mElements.push(e);
248    ObjectBase::asyncUnlock();
249
250    return returnRef;
251}
252
253ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein,
254                            const char **nin, const size_t * lengths, const uint32_t *asin) {
255
256    ObjectBaseRef<const Element> returnRef;
257    // Look for an existing match.
258    ObjectBase::asyncLock();
259    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
260        const Element *ee = rsc->mStateElement.mElements[ct];
261        if (ee->getFieldCount() == count) {
262            bool match = true;
263            for (uint32_t i=0; i < count; i++) {
264                size_t len;
265                uint32_t asize = 1;
266                if (lengths) {
267                    len = lengths[i];
268                } else {
269                    len = strlen(nin[i]);
270                }
271                if (asin) {
272                    asize = asin[i];
273                }
274
275                if ((ee->mFields[i].e.get() != ein[i]) ||
276                    (strlen(ee->mFields[i].name) != len) ||
277                    strcmp(ee->mFields[i].name, nin[i]) ||
278                    (ee->mFields[i].arraySize != asize)) {
279                    match = false;
280                    break;
281                }
282            }
283            if (match) {
284                returnRef.set(ee);
285                ObjectBase::asyncUnlock();
286                return returnRef;
287            }
288        }
289    }
290    ObjectBase::asyncUnlock();
291
292    Element *e = new Element(rsc);
293    returnRef.set(e);
294    e->mFields = new ElementField_t [count];
295    e->mFieldCount = count;
296    for (size_t ct=0; ct < count; ct++) {
297        size_t len;
298        uint32_t asize = 1;
299        if (lengths) {
300            len = lengths[ct];
301        } else {
302            len = strlen(nin[ct]);
303        }
304        if (asin) {
305            asize = asin[ct];
306        }
307
308        e->mFields[ct].e.set(ein[ct]);
309        e->mFields[ct].name = rsuCopyString(nin[ct], len);
310        e->mFields[ct].arraySize = asize;
311    }
312    e->compute();
313
314    ObjectBase::asyncLock();
315    rsc->mStateElement.mElements.push(e);
316    ObjectBase::asyncUnlock();
317
318    return returnRef;
319}
320
321void Element::incRefs(const void *ptr) const {
322    if (!mFieldCount) {
323        if (mComponent.isReference()) {
324            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
325            ObjectBase *ob = obp[0];
326            if (ob) ob->incSysRef();
327        }
328        return;
329    }
330
331    const uint8_t *p = static_cast<const uint8_t *>(ptr);
332    for (uint32_t i=0; i < mFieldCount; i++) {
333        if (mFields[i].e->mHasReference) {
334            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
335            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
336                mFields[i].e->incRefs(p2);
337                p2 += mFields[i].e->getSizeBytes();
338            }
339        }
340    }
341}
342
343void Element::decRefs(const void *ptr) const {
344    if (!mFieldCount) {
345        if (mComponent.isReference()) {
346            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
347            ObjectBase *ob = obp[0];
348            if (ob) ob->decSysRef();
349        }
350        return;
351    }
352
353    const uint8_t *p = static_cast<const uint8_t *>(ptr);
354    for (uint32_t i=0; i < mFieldCount; i++) {
355        if (mFields[i].e->mHasReference) {
356            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
357            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
358                mFields[i].e->decRefs(p2);
359                p2 += mFields[i].e->getSizeBytes();
360            }
361        }
362    }
363}
364
365ElementState::ElementState() {
366}
367
368ElementState::~ElementState() {
369    rsAssert(!mElements.size());
370}
371
372/////////////////////////////////////////
373//
374
375namespace android {
376namespace renderscript {
377
378RsElement rsi_ElementCreate(Context *rsc,
379                            RsDataType dt,
380                            RsDataKind dk,
381                            bool norm,
382                            uint32_t vecSize) {
383    return (RsElement)Element::create(rsc, dt, dk, norm, vecSize);
384}
385
386
387RsElement rsi_ElementCreate2(Context *rsc,
388                             const RsElement * ein,
389                             size_t ein_length,
390
391                             const char ** names,
392                             size_t nameLengths_length,
393                             const size_t * nameLengths,
394
395                             const uint32_t * arraySizes,
396                             size_t arraySizes_length) {
397    return (RsElement)Element::create(rsc, ein_length, (const Element **)ein,
398                                      names, nameLengths, arraySizes);
399}
400
401}
402}
403
404extern "C" void rsaElementGetNativeData(RsContext con, RsElement elem,
405                             uint32_t *elemData, uint32_t elemDataSize) {
406    rsAssert(elemDataSize == 5);
407    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
408    Element *e = static_cast<Element *>(elem);
409
410    (*elemData++) = (uint32_t)e->getType();
411    (*elemData++) = (uint32_t)e->getKind();
412    (*elemData++) = e->getComponent().getIsNormalized() ? 1 : 0;
413    (*elemData++) = e->getComponent().getVectorSize();
414    (*elemData++) = e->getFieldCount();
415}
416
417extern "C" void rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids,
418                              const char **names, size_t *arraySizes, uint32_t dataSize) {
419    Element *e = static_cast<Element *>(elem);
420    rsAssert(e->getFieldCount() == dataSize);
421
422    for (uint32_t i = 0; i < dataSize; i ++) {
423        e->getField(i)->incUserRef();
424        ids[i] = (uintptr_t)e->getField(i);
425        names[i] = e->getFieldName(i);
426        arraySizes[i] = e->getFieldArraySize(i);
427    }
428}
429