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