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