rsElement.cpp revision e3af53b643677c40d228ffd3624cf259f4dc68ed
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#ifdef RS_FIND_OFFSETS
247    ALOGE("pointer for element: %p", e);
248    ALOGE("pointer for element.drv: %p", &e->mHal.drv);
249#endif
250
251
252    ObjectBase::asyncLock();
253    rsc->mStateElement.mElements.push(e);
254    ObjectBase::asyncUnlock();
255
256    return returnRef;
257}
258
259ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein,
260                            const char **nin, const size_t * lengths, const uint32_t *asin) {
261
262    ObjectBaseRef<const Element> returnRef;
263    // Look for an existing match.
264    ObjectBase::asyncLock();
265    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
266        const Element *ee = rsc->mStateElement.mElements[ct];
267        if (ee->getFieldCount() == count) {
268            bool match = true;
269            for (uint32_t i=0; i < count; i++) {
270                size_t len;
271                uint32_t asize = 1;
272                if (lengths) {
273                    len = lengths[i];
274                } else {
275                    len = strlen(nin[i]);
276                }
277                if (asin) {
278                    asize = asin[i];
279                }
280
281                if ((ee->mFields[i].e.get() != ein[i]) ||
282                    (strlen(ee->mFields[i].name) != len) ||
283                    strcmp(ee->mFields[i].name, nin[i]) ||
284                    (ee->mFields[i].arraySize != asize)) {
285                    match = false;
286                    break;
287                }
288            }
289            if (match) {
290                returnRef.set(ee);
291                ObjectBase::asyncUnlock();
292                return returnRef;
293            }
294        }
295    }
296    ObjectBase::asyncUnlock();
297
298    Element *e = new Element(rsc);
299    returnRef.set(e);
300    e->mFields = new ElementField_t [count];
301    e->mFieldCount = count;
302    for (size_t ct=0; ct < count; ct++) {
303        size_t len;
304        uint32_t asize = 1;
305        if (lengths) {
306            len = lengths[ct];
307        } else {
308            len = strlen(nin[ct]);
309        }
310        if (asin) {
311            asize = asin[ct];
312        }
313
314        e->mFields[ct].e.set(ein[ct]);
315        e->mFields[ct].name = rsuCopyString(nin[ct], len);
316        e->mFields[ct].arraySize = asize;
317    }
318    e->compute();
319
320    ObjectBase::asyncLock();
321    rsc->mStateElement.mElements.push(e);
322    ObjectBase::asyncUnlock();
323
324    return returnRef;
325}
326
327void Element::incRefs(const void *ptr) const {
328    if (!mFieldCount) {
329        if (mComponent.isReference()) {
330            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
331            ObjectBase *ob = obp[0];
332            if (ob) ob->incSysRef();
333        }
334        return;
335    }
336
337    const uint8_t *p = static_cast<const uint8_t *>(ptr);
338    for (uint32_t i=0; i < mFieldCount; i++) {
339        if (mFields[i].e->mHasReference) {
340            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
341            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
342                mFields[i].e->incRefs(p2);
343                p2 += mFields[i].e->getSizeBytes();
344            }
345        }
346    }
347}
348
349void Element::decRefs(const void *ptr) const {
350    if (!mFieldCount) {
351        if (mComponent.isReference()) {
352            ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
353            ObjectBase *ob = obp[0];
354            if (ob) ob->decSysRef();
355        }
356        return;
357    }
358
359    const uint8_t *p = static_cast<const uint8_t *>(ptr);
360    for (uint32_t i=0; i < mFieldCount; i++) {
361        if (mFields[i].e->mHasReference) {
362            const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
363            for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
364                mFields[i].e->decRefs(p2);
365                p2 += mFields[i].e->getSizeBytes();
366            }
367        }
368    }
369}
370
371ElementState::ElementState() {
372}
373
374ElementState::~ElementState() {
375    rsAssert(!mElements.size());
376}
377
378/////////////////////////////////////////
379//
380
381namespace android {
382namespace renderscript {
383
384RsElement rsi_ElementCreate(Context *rsc,
385                            RsDataType dt,
386                            RsDataKind dk,
387                            bool norm,
388                            uint32_t vecSize) {
389    return (RsElement)Element::create(rsc, dt, dk, norm, vecSize);
390}
391
392
393RsElement rsi_ElementCreate2(Context *rsc,
394                             const RsElement * ein,
395                             size_t ein_length,
396
397                             const char ** names,
398                             size_t nameLengths_length,
399                             const size_t * nameLengths,
400
401                             const uint32_t * arraySizes,
402                             size_t arraySizes_length) {
403    return (RsElement)Element::create(rsc, ein_length, (const Element **)ein,
404                                      names, nameLengths, arraySizes);
405}
406
407}
408}
409
410extern "C" void rsaElementGetNativeData(RsContext con, RsElement elem,
411                             uint32_t *elemData, uint32_t elemDataSize) {
412    rsAssert(elemDataSize == 5);
413    // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
414    Element *e = static_cast<Element *>(elem);
415
416    (*elemData++) = (uint32_t)e->getType();
417    (*elemData++) = (uint32_t)e->getKind();
418    (*elemData++) = e->getComponent().getIsNormalized() ? 1 : 0;
419    (*elemData++) = e->getComponent().getVectorSize();
420    (*elemData++) = e->getFieldCount();
421}
422
423extern "C" void rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids,
424                              const char **names, size_t *arraySizes, uint32_t dataSize) {
425    Element *e = static_cast<Element *>(elem);
426    rsAssert(e->getFieldCount() == dataSize);
427
428    for (uint32_t i = 0; i < dataSize; i ++) {
429        e->getField(i)->incUserRef();
430        ids[i] = (uintptr_t)e->getField(i);
431        names[i] = e->getFieldName(i);
432        arraySizes[i] = e->getFieldArraySize(i);
433    }
434}
435