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