Home | History | Annotate | Download | only in rs
      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 
     20 using namespace android;
     21 using namespace android::renderscript;
     22 
     23 
     24 Element::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 
     33 Element::~Element() {
     34     clear();
     35 }
     36 
     37 void 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 
     46 void Element::clear() {
     47     delete [] mFields;
     48     mFields = NULL;
     49     mFieldCount = 0;
     50     mHasReference = false;
     51 
     52     delete [] mHal.state.fields;
     53     delete [] mHal.state.fieldArraySizes;
     54     delete [] mHal.state.fieldNames;
     55     delete [] mHal.state.fieldNameLengths;
     56     delete [] mHal.state.fieldOffsetBytes;
     57 }
     58 
     59 size_t Element::getSizeBits() const {
     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 
     71 size_t Element::getSizeBitsUnpadded() const {
     72     if (!mFieldCount) {
     73         return mBitsUnpadded;
     74     }
     75 
     76     size_t total = 0;
     77     for (size_t ct=0; ct < mFieldCount; ct++) {
     78         total += mFields[ct].e->mBitsUnpadded * mFields[ct].arraySize;
     79     }
     80     return total;
     81 }
     82 
     83 void Element::dumpLOGV(const char *prefix) const {
     84     ObjectBase::dumpLOGV(prefix);
     85     ALOGV("%s Element: fieldCount: %zu,  size bytes: %zu", prefix, mFieldCount, getSizeBytes());
     86     mComponent.dumpLOGV(prefix);
     87     for (uint32_t ct = 0; ct < mFieldCount; ct++) {
     88         ALOGV("%s Element field index: %u ------------------", prefix, ct);
     89         ALOGV("%s name: %s, offsetBits: %u, arraySize: %u",
     90              prefix, mFields[ct].name.string(), mFields[ct].offsetBits, mFields[ct].arraySize);
     91         mFields[ct].e->dumpLOGV(prefix);
     92     }
     93 }
     94 
     95 void Element::serialize(Context *rsc, OStream *stream) const {
     96     // Need to identify ourselves
     97     stream->addU32((uint32_t)getClassId());
     98 
     99     String8 name(getName());
    100     stream->addString(&name);
    101 
    102     mComponent.serialize(stream);
    103 
    104     // Now serialize all the fields
    105     stream->addU32(mFieldCount);
    106     for (uint32_t ct = 0; ct < mFieldCount; ct++) {
    107         stream->addString(&mFields[ct].name);
    108         stream->addU32(mFields[ct].arraySize);
    109         mFields[ct].e->serialize(rsc, stream);
    110     }
    111 }
    112 
    113 Element *Element::createFromStream(Context *rsc, IStream *stream) {
    114     // First make sure we are reading the correct object
    115     RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
    116     if (classID != RS_A3D_CLASS_ID_ELEMENT) {
    117         ALOGE("element loading skipped due to invalid class id\n");
    118         return NULL;
    119     }
    120 
    121     String8 name;
    122     stream->loadString(&name);
    123 
    124     Component component;
    125     component.loadFromStream(stream);
    126 
    127     uint32_t fieldCount = stream->loadU32();
    128     if (!fieldCount) {
    129         return (Element *)Element::create(rsc,
    130                                           component.getType(),
    131                                           component.getKind(),
    132                                           component.getIsNormalized(),
    133                                           component.getVectorSize());
    134     }
    135 
    136     const Element **subElems = new const Element *[fieldCount];
    137     const char **subElemNames = new const char *[fieldCount];
    138     size_t *subElemNamesLengths = new size_t[fieldCount];
    139     uint32_t *arraySizes = new uint32_t[fieldCount];
    140 
    141     String8 elemName;
    142     for (uint32_t ct = 0; ct < fieldCount; ct ++) {
    143         stream->loadString(&elemName);
    144         subElemNamesLengths[ct] = elemName.length();
    145         char *tmpName = new char[subElemNamesLengths[ct]];
    146         memcpy(tmpName, elemName.string(), subElemNamesLengths[ct]);
    147         subElemNames[ct] = tmpName;
    148         arraySizes[ct] = stream->loadU32();
    149         subElems[ct] = Element::createFromStream(rsc, stream);
    150     }
    151 
    152     const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames,
    153                                           subElemNamesLengths, arraySizes);
    154     for (uint32_t ct = 0; ct < fieldCount; ct ++) {
    155         delete [] subElemNames[ct];
    156         subElems[ct]->decUserRef();
    157     }
    158     delete[] subElems;
    159     delete[] subElemNames;
    160     delete[] subElemNamesLengths;
    161     delete[] arraySizes;
    162 
    163     return (Element *)elem;
    164 }
    165 
    166 void Element::compute() {
    167     mHal.state.dataType = mComponent.getType();
    168     mHal.state.dataKind = mComponent.getKind();
    169     mHal.state.vectorSize = mComponent.getVectorSize();
    170 
    171     if (mFieldCount == 0) {
    172         mBits = mComponent.getBits();
    173         mBitsUnpadded = mComponent.getBitsUnpadded();
    174         mHasReference = mComponent.isReference();
    175 
    176         mHal.state.elementSizeBytes = getSizeBytes();
    177         return;
    178     }
    179 
    180     uint32_t noPaddingFieldCount = 0;
    181     for (uint32_t ct = 0; ct < mFieldCount; ct ++) {
    182         if (mFields[ct].name.string()[0] != '#') {
    183             noPaddingFieldCount ++;
    184         }
    185     }
    186 
    187     mHal.state.fields = new const Element*[noPaddingFieldCount];
    188     mHal.state.fieldArraySizes = new uint32_t[noPaddingFieldCount];
    189     mHal.state.fieldNames = new const char*[noPaddingFieldCount];
    190     mHal.state.fieldNameLengths = new uint32_t[noPaddingFieldCount];
    191     mHal.state.fieldOffsetBytes = new uint32_t[noPaddingFieldCount];
    192     mHal.state.fieldsCount = noPaddingFieldCount;
    193 
    194     size_t bits = 0;
    195     size_t bitsUnpadded = 0;
    196     for (size_t ct = 0, ctNoPadding = 0; ct < mFieldCount; ct++) {
    197         mFields[ct].offsetBits = bits;
    198         mFields[ct].offsetBitsUnpadded = bitsUnpadded;
    199         bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize;
    200         bitsUnpadded += mFields[ct].e->getSizeBitsUnpadded() * mFields[ct].arraySize;
    201 
    202         if (mFields[ct].e->mHasReference) {
    203             mHasReference = true;
    204         }
    205 
    206         if (mFields[ct].name.string()[0] == '#') {
    207             continue;
    208         }
    209 
    210         mHal.state.fields[ctNoPadding] = mFields[ct].e.get();
    211         mHal.state.fieldArraySizes[ctNoPadding] = mFields[ct].arraySize;
    212         mHal.state.fieldNames[ctNoPadding] = mFields[ct].name.string();
    213         mHal.state.fieldNameLengths[ctNoPadding] = mFields[ct].name.length() + 1; // to include 0
    214         mHal.state.fieldOffsetBytes[ctNoPadding] = mFields[ct].offsetBits >> 3;
    215 
    216         ctNoPadding ++;
    217     }
    218 
    219     mHal.state.elementSizeBytes = getSizeBytes();
    220 }
    221 
    222 ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk,
    223                                 bool isNorm, uint32_t vecSize) {
    224     ObjectBaseRef<const Element> returnRef;
    225     // Look for an existing match.
    226     ObjectBase::asyncLock();
    227     for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
    228         const Element *ee = rsc->mStateElement.mElements[ct];
    229         if (!ee->getFieldCount() &&
    230             (ee->getComponent().getType() == dt) &&
    231             (ee->getComponent().getKind() == dk) &&
    232             (ee->getComponent().getIsNormalized() == isNorm) &&
    233             (ee->getComponent().getVectorSize() == vecSize)) {
    234             // Match
    235             returnRef.set(ee);
    236             ObjectBase::asyncUnlock();
    237             return ee;
    238         }
    239     }
    240     ObjectBase::asyncUnlock();
    241 
    242     Element *e = new Element(rsc);
    243     returnRef.set(e);
    244     e->mComponent.set(dt, dk, isNorm, vecSize);
    245     e->compute();
    246 
    247     ObjectBase::asyncLock();
    248     rsc->mStateElement.mElements.push(e);
    249     ObjectBase::asyncUnlock();
    250 
    251     return returnRef;
    252 }
    253 
    254 ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein,
    255                             const char **nin, const size_t * lengths, const uint32_t *asin) {
    256 
    257     ObjectBaseRef<const Element> returnRef;
    258     // Look for an existing match.
    259     ObjectBase::asyncLock();
    260     for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
    261         const Element *ee = rsc->mStateElement.mElements[ct];
    262         if (ee->getFieldCount() == count) {
    263             bool match = true;
    264             for (uint32_t i=0; i < count; i++) {
    265                 if ((ee->mFields[i].e.get() != ein[i]) ||
    266                     (ee->mFields[i].name.length() != lengths[i]) ||
    267                     (ee->mFields[i].name != nin[i]) ||
    268                     (ee->mFields[i].arraySize != asin[i])) {
    269                     match = false;
    270                     break;
    271                 }
    272             }
    273             if (match) {
    274                 returnRef.set(ee);
    275                 ObjectBase::asyncUnlock();
    276                 return returnRef;
    277             }
    278         }
    279     }
    280     ObjectBase::asyncUnlock();
    281 
    282     Element *e = new Element(rsc);
    283     returnRef.set(e);
    284     e->mFields = new ElementField_t [count];
    285     e->mFieldCount = count;
    286     for (size_t ct=0; ct < count; ct++) {
    287         e->mFields[ct].e.set(ein[ct]);
    288         e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
    289         e->mFields[ct].arraySize = asin[ct];
    290     }
    291     e->compute();
    292 
    293     ObjectBase::asyncLock();
    294     rsc->mStateElement.mElements.push(e);
    295     ObjectBase::asyncUnlock();
    296 
    297     return returnRef;
    298 }
    299 
    300 void Element::incRefs(const void *ptr) const {
    301     if (!mFieldCount) {
    302         if (mComponent.isReference()) {
    303             ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
    304             ObjectBase *ob = obp[0];
    305             if (ob) ob->incSysRef();
    306         }
    307         return;
    308     }
    309 
    310     const uint8_t *p = static_cast<const uint8_t *>(ptr);
    311     for (uint32_t i=0; i < mFieldCount; i++) {
    312         if (mFields[i].e->mHasReference) {
    313             const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
    314             for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
    315                 mFields[i].e->incRefs(p2);
    316                 p2 += mFields[i].e->getSizeBytes();
    317             }
    318         }
    319     }
    320 }
    321 
    322 void Element::decRefs(const void *ptr) const {
    323     if (!mFieldCount) {
    324         if (mComponent.isReference()) {
    325             ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
    326             ObjectBase *ob = obp[0];
    327             if (ob) ob->decSysRef();
    328         }
    329         return;
    330     }
    331 
    332     const uint8_t *p = static_cast<const uint8_t *>(ptr);
    333     for (uint32_t i=0; i < mFieldCount; i++) {
    334         if (mFields[i].e->mHasReference) {
    335             const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
    336             for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
    337                 mFields[i].e->decRefs(p2);
    338                 p2 += mFields[i].e->getSizeBytes();
    339             }
    340         }
    341     }
    342 }
    343 
    344 Element::Builder::Builder() {
    345     const uint32_t initialCapacity = 32;
    346     mBuilderElementRefs.setCapacity(initialCapacity);
    347     mBuilderElements.setCapacity(initialCapacity);
    348     mBuilderNameStrings.setCapacity(initialCapacity);
    349     mBuilderNameLengths.setCapacity(initialCapacity);
    350     mBuilderArrays.setCapacity(initialCapacity);
    351 }
    352 
    353 void Element::Builder::add(const Element *e, const char *nameStr, uint32_t arraySize) {
    354     mBuilderElementRefs.push(ObjectBaseRef<const Element>(e));
    355     mBuilderElements.push(e);
    356     mBuilderNameStrings.push(nameStr);
    357     mBuilderNameLengths.push(strlen(nameStr));
    358     mBuilderArrays.push(arraySize);
    359 
    360 }
    361 
    362 ObjectBaseRef<const Element> Element::Builder::create(Context *rsc) {
    363     return Element::createRef(rsc, mBuilderElements.size(),
    364                               &(mBuilderElements.editArray()[0]),
    365                               &(mBuilderNameStrings.editArray()[0]),
    366                               mBuilderNameLengths.editArray(),
    367                               mBuilderArrays.editArray());
    368 }
    369 
    370 
    371 ElementState::ElementState() {
    372 }
    373 
    374 ElementState::~ElementState() {
    375     rsAssert(!mElements.size());
    376 }
    377 
    378 /////////////////////////////////////////
    379 //
    380 
    381 namespace android {
    382 namespace renderscript {
    383 
    384 RsElement 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 
    393 RsElement 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 
    410 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 
    423 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