Home | History | Annotate | Download | only in rs
      1 /*
      2  * Copyright (C) 2013 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 #include "rsContext.h"
     18 #include "rsAllocation.h"
     19 #include "rs_hal.h"
     20 
     21 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
     22 #include "system/window.h"
     23 #include "gui/GLConsumer.h"
     24 #endif
     25 
     26 using namespace android;
     27 using namespace android::renderscript;
     28 
     29 Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages,
     30                        RsAllocationMipmapControl mc, void * ptr)
     31     : ObjectBase(rsc) {
     32 
     33     memset(&mHal, 0, sizeof(mHal));
     34     mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
     35     mHal.state.usageFlags = usages;
     36     mHal.state.mipmapControl = mc;
     37     mHal.state.userProvidedPtr = ptr;
     38 
     39     setType(type);
     40     updateCache();
     41 }
     42 
     43 Allocation::Allocation(Context *rsc, const Allocation *alloc, const Type *type)
     44     : ObjectBase(rsc) {
     45 
     46     memset(&mHal, 0, sizeof(mHal));
     47     mHal.state.baseAlloc = alloc;
     48     mHal.state.usageFlags = alloc->mHal.state.usageFlags;
     49     mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
     50 
     51     setType(type);
     52     updateCache();
     53 }
     54 
     55 void Allocation::operator delete(void* ptr) {
     56     if (ptr) {
     57         Allocation *a = (Allocation*) ptr;
     58         a->getContext()->mHal.funcs.freeRuntimeMem(ptr);
     59     }
     60 }
     61 
     62 Allocation * Allocation::createAllocationStrided(Context *rsc, const Type *type, uint32_t usages,
     63                                                  RsAllocationMipmapControl mc, void * ptr,
     64                                                  size_t requiredAlignment) {
     65     // Allocation objects must use allocator specified by the driver
     66     void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Allocation), 0);
     67 
     68     if (!allocMem) {
     69         rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Allocation");
     70         return nullptr;
     71     }
     72 
     73     bool success = false;
     74     Allocation *a = nullptr;
     75     if (usages & RS_ALLOCATION_USAGE_OEM) {
     76         if (rsc->mHal.funcs.allocation.initOem != nullptr) {
     77             a = new (allocMem) Allocation(rsc, type, usages, mc, nullptr);
     78             success = rsc->mHal.funcs.allocation.initOem(rsc, a, type->getElement()->getHasReferences(), ptr);
     79         } else {
     80             rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation Init called with USAGE_OEM but driver does not support it");
     81             return nullptr;
     82         }
     83 #ifdef RS_COMPATIBILITY_LIB
     84     } else if (usages & RS_ALLOCATION_USAGE_INCREMENTAL_SUPPORT){
     85         a = new (allocMem) Allocation(rsc, type, usages, mc, ptr);
     86         success = rsc->mHal.funcs.allocation.initStrided(rsc, a, type->getElement()->getHasReferences(), requiredAlignment);
     87 #endif
     88     } else {
     89         a = new (allocMem) Allocation(rsc, type, usages, mc, ptr);
     90         success = rsc->mHal.funcs.allocation.init(rsc, a, type->getElement()->getHasReferences());
     91     }
     92 
     93     if (!success) {
     94         rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
     95         delete a;
     96         return nullptr;
     97     }
     98 
     99     return a;
    100 }
    101 
    102 Allocation * Allocation::createAllocation(Context *rsc, const Type *type, uint32_t usages,
    103                               RsAllocationMipmapControl mc, void * ptr) {
    104     return Allocation::createAllocationStrided(rsc, type, usages, mc, ptr, kMinimumRSAlignment);
    105 }
    106 
    107 Allocation * Allocation::createAdapter(Context *rsc, const Allocation *alloc, const Type *type) {
    108     // Allocation objects must use allocator specified by the driver
    109     void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Allocation), 0);
    110 
    111     if (!allocMem) {
    112         rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Allocation");
    113         return nullptr;
    114     }
    115 
    116     Allocation *a = new (allocMem) Allocation(rsc, alloc, type);
    117 
    118     if (!rsc->mHal.funcs.allocation.initAdapter(rsc, a)) {
    119         rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
    120         delete a;
    121         return nullptr;
    122     }
    123 
    124     return a;
    125 }
    126 
    127 void Allocation::adapterOffset(Context *rsc, const uint32_t *offsets, size_t len) {
    128     if (len >= sizeof(uint32_t) * 9) {
    129         mHal.state.originX = offsets[0];
    130         mHal.state.originY = offsets[1];
    131         mHal.state.originZ = offsets[2];
    132         mHal.state.originLOD = offsets[3];
    133         mHal.state.originFace = offsets[4];
    134         mHal.state.originArray[0] = offsets[5];
    135         mHal.state.originArray[1] = offsets[6];
    136         mHal.state.originArray[2] = offsets[7];
    137         mHal.state.originArray[3] = offsets[8];
    138     }
    139 
    140     rsc->mHal.funcs.allocation.adapterOffset(rsc, this);
    141 }
    142 
    143 
    144 
    145 void Allocation::updateCache() {
    146     const Type *type = mHal.state.type;
    147     mHal.state.yuv = type->getDimYuv();
    148     mHal.state.hasFaces = type->getDimFaces();
    149     mHal.state.hasMipmaps = type->getDimLOD();
    150     mHal.state.elementSizeBytes = type->getElementSizeBytes();
    151     mHal.state.hasReferences = mHal.state.type->getElement()->getHasReferences();
    152 }
    153 
    154 Allocation::~Allocation() {
    155 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
    156     if (mGrallocConsumer.get()) {
    157         mGrallocConsumer->releaseIdx(mCurrentIdx);
    158         mGrallocConsumer = nullptr;
    159     }
    160 #endif
    161 
    162     freeChildrenUnlocked();
    163     mRSC->mHal.funcs.allocation.destroy(mRSC, this);
    164 }
    165 
    166 void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) {
    167     rsc->mHal.funcs.allocation.syncAll(rsc, this, src);
    168 }
    169 
    170 void * Allocation::getPointer(const Context *rsc, uint32_t lod, RsAllocationCubemapFace face,
    171                           uint32_t z, uint32_t array, size_t *stride) {
    172 
    173     if ((lod >= mHal.drvState.lodCount) ||
    174         (z && (z >= mHal.drvState.lod[lod].dimZ)) ||
    175         ((face != RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X) && !mHal.state.hasFaces) ||
    176         (array != 0)) {
    177         return nullptr;
    178     }
    179 
    180     if (mRSC->mHal.funcs.allocation.getPointer != nullptr) {
    181         // Notify the driver, if present that the user is mapping the buffer
    182         mRSC->mHal.funcs.allocation.getPointer(rsc, this, lod, face, z, array);
    183     }
    184 
    185     size_t s = 0;
    186     if ((stride != nullptr) && mHal.drvState.lod[0].dimY) {
    187         *stride = mHal.drvState.lod[lod].stride;
    188     }
    189     return mHal.drvState.lod[lod].mallocPtr;
    190 }
    191 
    192 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
    193                          uint32_t count, const void *data, size_t sizeBytes) {
    194     const size_t eSize = mHal.state.type->getElementSizeBytes();
    195 
    196     if ((count * eSize) != sizeBytes) {
    197         char buf[1024];
    198         sprintf(buf, "Allocation::subData called with mismatched size expected %zu, got %zu",
    199                 (count * eSize), sizeBytes);
    200         rsc->setError(RS_ERROR_BAD_VALUE, buf);
    201         mHal.state.type->dumpLOGV("type info");
    202         return;
    203     }
    204 
    205     rsc->mHal.funcs.allocation.data1D(rsc, this, xoff, lod, count, data, sizeBytes);
    206     sendDirty(rsc);
    207 }
    208 
    209 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    210                       uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
    211     rsc->mHal.funcs.allocation.data2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
    212     sendDirty(rsc);
    213 }
    214 
    215 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
    216                       uint32_t lod,
    217                       uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes, size_t stride) {
    218     rsc->mHal.funcs.allocation.data3D(rsc, this, xoff, yoff, zoff, lod, w, h, d, data, sizeBytes, stride);
    219     sendDirty(rsc);
    220 }
    221 
    222 void Allocation::read(Context *rsc, uint32_t xoff, uint32_t lod,
    223                       uint32_t count, void *data, size_t sizeBytes) {
    224     const size_t eSize = mHal.state.type->getElementSizeBytes();
    225 
    226     if ((count * eSize) != sizeBytes) {
    227         char buf[1024];
    228         sprintf(buf, "Allocation::read called with mismatched size expected %zu, got %zu",
    229                 (count * eSize), sizeBytes);
    230         rsc->setError(RS_ERROR_BAD_VALUE, buf);
    231         mHal.state.type->dumpLOGV("type info");
    232         return;
    233     }
    234 
    235     rsc->mHal.funcs.allocation.read1D(rsc, this, xoff, lod, count, data, sizeBytes);
    236 }
    237 
    238 void Allocation::read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    239                       uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) {
    240     const size_t eSize = mHal.state.elementSizeBytes;
    241     const size_t lineSize = eSize * w;
    242     if (!stride) {
    243         stride = lineSize;
    244     } else {
    245         if ((lineSize * h) != sizeBytes) {
    246             char buf[1024];
    247             sprintf(buf, "Allocation size mismatch, expected %zu, got %zu", (lineSize * h), sizeBytes);
    248             rsc->setError(RS_ERROR_BAD_VALUE, buf);
    249             return;
    250         }
    251     }
    252 
    253     rsc->mHal.funcs.allocation.read2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
    254 }
    255 
    256 void Allocation::read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod,
    257                       uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) {
    258     const size_t eSize = mHal.state.elementSizeBytes;
    259     const size_t lineSize = eSize * w;
    260     if (!stride) {
    261         stride = lineSize;
    262     }
    263 
    264     rsc->mHal.funcs.allocation.read3D(rsc, this, xoff, yoff, zoff, lod, w, h, d, data, sizeBytes, stride);
    265 
    266 }
    267 
    268 void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y, uint32_t z,
    269                              const void *data, uint32_t cIdx, size_t sizeBytes) {
    270     size_t eSize = mHal.state.elementSizeBytes;
    271 
    272     if (x >= mHal.drvState.lod[0].dimX) {
    273         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
    274         return;
    275     }
    276 
    277     if (y > 0 && y >= mHal.drvState.lod[0].dimY) {
    278         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData Y offset out of range.");
    279         return;
    280     }
    281 
    282     if (z > 0 && z >= mHal.drvState.lod[0].dimZ) {
    283         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData Z offset out of range.");
    284         return;
    285     }
    286 
    287     if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
    288         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
    289         return;
    290     }
    291 
    292     const Element * e = mHal.state.type->getElement()->getField(cIdx);
    293     uint32_t elemArraySize = mHal.state.type->getElement()->getFieldArraySize(cIdx);
    294     if (sizeBytes != e->getSizeBytes() * elemArraySize) {
    295         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
    296         return;
    297     }
    298 
    299     rsc->mHal.funcs.allocation.elementData(rsc, this, x, y, z, data, cIdx, sizeBytes);
    300     sendDirty(rsc);
    301 }
    302 
    303 void Allocation::elementRead(Context *rsc, uint32_t x, uint32_t y, uint32_t z,
    304                              void *data, uint32_t cIdx, size_t sizeBytes) {
    305     size_t eSize = mHal.state.elementSizeBytes;
    306 
    307     if (x >= mHal.drvState.lod[0].dimX) {
    308         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
    309         return;
    310     }
    311 
    312     if (y > 0 && y >= mHal.drvState.lod[0].dimY) {
    313         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData Y offset out of range.");
    314         return;
    315     }
    316 
    317     if (z > 0 && z >= mHal.drvState.lod[0].dimZ) {
    318         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData Z offset out of range.");
    319         return;
    320     }
    321 
    322     if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
    323         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
    324         return;
    325     }
    326 
    327     const Element * e = mHal.state.type->getElement()->getField(cIdx);
    328     uint32_t elemArraySize = mHal.state.type->getElement()->getFieldArraySize(cIdx);
    329     if (sizeBytes != e->getSizeBytes() * elemArraySize) {
    330         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
    331         return;
    332     }
    333 
    334     rsc->mHal.funcs.allocation.elementRead(rsc, this, x, y, z, data, cIdx, sizeBytes);
    335 }
    336 
    337 void Allocation::addProgramToDirty(const Program *p) {
    338     mToDirtyList.push(p);
    339 }
    340 
    341 void Allocation::removeProgramToDirty(const Program *p) {
    342     for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
    343         if (mToDirtyList[ct] == p) {
    344             mToDirtyList.removeAt(ct);
    345             return;
    346         }
    347     }
    348     rsAssert(0);
    349 }
    350 
    351 void Allocation::dumpLOGV(const char *prefix) const {
    352     ObjectBase::dumpLOGV(prefix);
    353     char buf[1024];
    354 
    355     if ((strlen(prefix) + 10) < sizeof(buf)) {
    356         sprintf(buf, "%s type ", prefix);
    357         if (mHal.state.type) {
    358             mHal.state.type->dumpLOGV(buf);
    359         }
    360     }
    361     ALOGV("%s allocation ptr=%p  mUsageFlags=0x04%x, mMipmapControl=0x%04x",
    362          prefix, mHal.drvState.lod[0].mallocPtr, mHal.state.usageFlags, mHal.state.mipmapControl);
    363 }
    364 
    365 uint32_t Allocation::getPackedSize() const {
    366     uint32_t numItems = mHal.state.type->getCellCount();
    367     return numItems * mHal.state.type->getElement()->getSizeBytesUnpadded();
    368 }
    369 
    370 void Allocation::writePackedData(Context *rsc, const Type *type,
    371                                  uint8_t *dst, const uint8_t *src, bool dstPadded) {
    372     const Element *elem = type->getElement();
    373     uint32_t unpaddedBytes = elem->getSizeBytesUnpadded();
    374     uint32_t paddedBytes = elem->getSizeBytes();
    375     uint32_t numItems = type->getPackedSizeBytes() / paddedBytes;
    376 
    377     uint32_t srcInc = !dstPadded ? paddedBytes : unpaddedBytes;
    378     uint32_t dstInc =  dstPadded ? paddedBytes : unpaddedBytes;
    379 
    380     // no sub-elements
    381     uint32_t fieldCount = elem->getFieldCount();
    382     if (fieldCount == 0) {
    383         for (uint32_t i = 0; i < numItems; i ++) {
    384             memcpy(dst, src, unpaddedBytes);
    385             src += srcInc;
    386             dst += dstInc;
    387         }
    388         return;
    389     }
    390 
    391     // Cache offsets
    392     uint32_t *offsetsPadded = new uint32_t[fieldCount];
    393     uint32_t *offsetsUnpadded = new uint32_t[fieldCount];
    394     uint32_t *sizeUnpadded = new uint32_t[fieldCount];
    395 
    396     for (uint32_t i = 0; i < fieldCount; i++) {
    397         offsetsPadded[i] = elem->getFieldOffsetBytes(i);
    398         offsetsUnpadded[i] = elem->getFieldOffsetBytesUnpadded(i);
    399         sizeUnpadded[i] = elem->getField(i)->getSizeBytesUnpadded();
    400     }
    401 
    402     uint32_t *srcOffsets = !dstPadded ? offsetsPadded : offsetsUnpadded;
    403     uint32_t *dstOffsets =  dstPadded ? offsetsPadded : offsetsUnpadded;
    404 
    405     // complex elements, need to copy subelem after subelem
    406     for (uint32_t i = 0; i < numItems; i ++) {
    407         for (uint32_t fI = 0; fI < fieldCount; fI++) {
    408             memcpy(dst + dstOffsets[fI], src + srcOffsets[fI], sizeUnpadded[fI]);
    409         }
    410         src += srcInc;
    411         dst += dstInc;
    412     }
    413 
    414     delete[] offsetsPadded;
    415     delete[] offsetsUnpadded;
    416     delete[] sizeUnpadded;
    417 }
    418 
    419 void Allocation::unpackVec3Allocation(Context *rsc, const void *data, size_t dataSize) {
    420     const uint8_t *src = (const uint8_t*)data;
    421     uint8_t *dst = (uint8_t *)rsc->mHal.funcs.allocation.lock1D(rsc, this);
    422 
    423     writePackedData(rsc, getType(), dst, src, true);
    424     rsc->mHal.funcs.allocation.unlock1D(rsc, this);
    425 }
    426 
    427 void Allocation::packVec3Allocation(Context *rsc, OStream *stream) const {
    428     uint32_t paddedBytes = getType()->getElement()->getSizeBytes();
    429     uint32_t unpaddedBytes = getType()->getElement()->getSizeBytesUnpadded();
    430     uint32_t numItems = mHal.state.type->getCellCount();
    431 
    432     const uint8_t *src = (const uint8_t*)rsc->mHal.funcs.allocation.lock1D(rsc, this);
    433     uint8_t *dst = new uint8_t[numItems * unpaddedBytes];
    434 
    435     writePackedData(rsc, getType(), dst, src, false);
    436     stream->addByteArray(dst, getPackedSize());
    437 
    438     delete[] dst;
    439     rsc->mHal.funcs.allocation.unlock1D(rsc, this);
    440 }
    441 
    442 void Allocation::serialize(Context *rsc, OStream *stream) const {
    443     // Need to identify ourselves
    444     stream->addU32((uint32_t)getClassId());
    445     stream->addString(getName());
    446 
    447     // First thing we need to serialize is the type object since it will be needed
    448     // to initialize the class
    449     mHal.state.type->serialize(rsc, stream);
    450 
    451     uint32_t dataSize = mHal.state.type->getPackedSizeBytes();
    452     // 3 element vectors are padded to 4 in memory, but padding isn't serialized
    453     uint32_t packedSize = getPackedSize();
    454     // Write how much data we are storing
    455     stream->addU32(packedSize);
    456     if (dataSize == packedSize) {
    457         // Now write the data
    458         stream->addByteArray(rsc->mHal.funcs.allocation.lock1D(rsc, this), dataSize);
    459         rsc->mHal.funcs.allocation.unlock1D(rsc, this);
    460     } else {
    461         // Now write the data
    462         packVec3Allocation(rsc, stream);
    463     }
    464 }
    465 
    466 Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
    467     // First make sure we are reading the correct object
    468     RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
    469     if (classID != RS_A3D_CLASS_ID_ALLOCATION) {
    470         rsc->setError(RS_ERROR_FATAL_DRIVER,
    471                       "allocation loading failed due to corrupt file. (invalid id)\n");
    472         return nullptr;
    473     }
    474 
    475     const char *name = stream->loadString();
    476 
    477     Type *type = Type::createFromStream(rsc, stream);
    478     if (!type) {
    479         return nullptr;
    480     }
    481     type->compute();
    482 
    483     Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
    484     type->decUserRef();
    485 
    486     // Number of bytes we wrote out for this allocation
    487     uint32_t dataSize = stream->loadU32();
    488     // 3 element vectors are padded to 4 in memory, but padding isn't serialized
    489     uint32_t packedSize = alloc->getPackedSize();
    490     if (dataSize != type->getPackedSizeBytes() &&
    491         dataSize != packedSize) {
    492         rsc->setError(RS_ERROR_FATAL_DRIVER,
    493                       "allocation loading failed due to corrupt file. (invalid size)\n");
    494         ObjectBase::checkDelete(alloc);
    495         ObjectBase::checkDelete(type);
    496         return nullptr;
    497     }
    498 
    499     alloc->assignName(name);
    500     if (dataSize == type->getPackedSizeBytes()) {
    501         uint32_t count = dataSize / type->getElementSizeBytes();
    502         // Read in all of our allocation data
    503         alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
    504     } else {
    505         alloc->unpackVec3Allocation(rsc, stream->getPtr() + stream->getPos(), dataSize);
    506     }
    507     stream->reset(stream->getPos() + dataSize);
    508 
    509     return alloc;
    510 }
    511 
    512 void Allocation::sendDirty(const Context *rsc) const {
    513 #ifndef RS_COMPATIBILITY_LIB
    514     for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
    515         mToDirtyList[ct]->forceDirty();
    516     }
    517 #endif
    518     mRSC->mHal.funcs.allocation.markDirty(rsc, this);
    519 }
    520 
    521 void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const {
    522     mHal.state.type->incRefs(ptr, ct, startOff);
    523 }
    524 
    525 void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const {
    526     if (!mHal.state.hasReferences || !getIsScript()) {
    527         return;
    528     }
    529     mHal.state.type->decRefs(ptr, ct, startOff);
    530 }
    531 
    532 void Allocation::callUpdateCacheObject(const Context *rsc, void *dstObj) const {
    533     if (rsc->mHal.funcs.allocation.updateCachedObject != nullptr) {
    534         rsc->mHal.funcs.allocation.updateCachedObject(rsc, this, (rs_allocation *)dstObj);
    535     } else {
    536         *((const void **)dstObj) = this;
    537     }
    538 }
    539 
    540 
    541 void Allocation::freeChildrenUnlocked () {
    542     void *ptr = mRSC->mHal.funcs.allocation.lock1D(mRSC, this);
    543     decRefs(ptr, mHal.state.type->getCellCount(), 0);
    544     mRSC->mHal.funcs.allocation.unlock1D(mRSC, this);
    545 }
    546 
    547 bool Allocation::freeChildren() {
    548     if (mHal.state.hasReferences) {
    549         incSysRef();
    550         freeChildrenUnlocked();
    551         return decSysRef();
    552     }
    553     return false;
    554 }
    555 
    556 void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) {
    557 }
    558 
    559 void Allocation::resize1D(Context *rsc, uint32_t dimX) {
    560     uint32_t oldDimX = mHal.drvState.lod[0].dimX;
    561     if (dimX == oldDimX) {
    562         return;
    563     }
    564 
    565     ObjectBaseRef<Type> t = mHal.state.type->cloneAndResize1D(rsc, dimX);
    566     if (dimX < oldDimX) {
    567         decRefs(rsc->mHal.funcs.allocation.lock1D(rsc, this), oldDimX - dimX, dimX);
    568         rsc->mHal.funcs.allocation.unlock1D(rsc, this);
    569     }
    570     rsc->mHal.funcs.allocation.resize(rsc, this, t.get(), mHal.state.hasReferences);
    571     setType(t.get());
    572     updateCache();
    573 }
    574 
    575 void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
    576     rsc->setError(RS_ERROR_FATAL_DRIVER, "resize2d not implemented");
    577 }
    578 
    579 #ifndef RS_COMPATIBILITY_LIB
    580 Allocation::NewBufferListener::NewBufferListener(uint32_t numAlloc) {
    581     alloc = new const Allocation *[numAlloc];
    582     mNumAlloc = numAlloc;
    583     for (uint32_t i = 0; i < numAlloc; i++) {
    584         alloc[i] = nullptr;
    585     }
    586 }
    587 
    588 Allocation::NewBufferListener::~NewBufferListener() {
    589     delete[] alloc;
    590 }
    591 
    592 void Allocation::NewBufferListener::onFrameAvailable(const BufferItem& /* item */) {
    593     for (uint32_t i = 0; i < mNumAlloc; i++) {
    594         if (alloc[i] != nullptr) {
    595             intptr_t ip = (intptr_t)alloc[i];
    596             rsc->sendMessageToClient(&ip, RS_MESSAGE_TO_CLIENT_NEW_BUFFER, 0, sizeof(ip), true);
    597         }
    598     }
    599 }
    600 #endif
    601 
    602 void Allocation::setupGrallocConsumer(const Context *rsc, uint32_t numAlloc) {
    603 #ifndef RS_COMPATIBILITY_LIB
    604     // Configure GrallocConsumer to be in asynchronous mode
    605     if (numAlloc > MAX_NUM_ALLOC || numAlloc <= 0) {
    606         rsc->setError(RS_ERROR_FATAL_DRIVER, "resize2d not implemented");
    607         return;
    608     }
    609     sp<IGraphicBufferConsumer> bc;
    610     BufferQueue::createBufferQueue(&mGraphicBufferProducer, &bc);
    611     mGrallocConsumer = new GrallocConsumer(this, bc, mHal.drvState.grallocFlags, numAlloc);
    612 
    613     mBufferListener = new NewBufferListener(numAlloc);
    614     mBufferListener->rsc = rsc;
    615     mBufferListener->alloc[0] = this;
    616     mCurrentIdx = 0;
    617     mBufferQueueInited = true;
    618 
    619     mGrallocConsumer->setFrameAvailableListener(mBufferListener);
    620 #endif
    621 }
    622 
    623 void * Allocation::getSurface(const Context *rsc) {
    624 #ifndef RS_COMPATIBILITY_LIB
    625     // Configure GrallocConsumer to be in asynchronous mode
    626     if (!mBufferQueueInited) {
    627         // This case is only used for single frame processing,
    628         // since we will always call setupGrallocConsumer first in
    629         // multi-frame case.
    630         setupGrallocConsumer(rsc, 1);
    631     }
    632     mGraphicBufferProducer->incStrong(nullptr);
    633     return mGraphicBufferProducer.get();
    634 #else
    635     return nullptr;
    636 #endif
    637     //return rsc->mHal.funcs.allocation.getSurface(rsc, this);
    638 }
    639 
    640 void Allocation::shareBufferQueue(const Context *rsc, const Allocation *alloc) {
    641 #ifndef RS_COMPATIBILITY_LIB
    642     mGrallocConsumer = alloc->mGrallocConsumer;
    643     mCurrentIdx = mGrallocConsumer->getNextAvailableIdx(this);
    644     if (mCurrentIdx >= mGrallocConsumer->mNumAlloc) {
    645         rsc->setError(RS_ERROR_DRIVER, "Maximum allocations attached to a BufferQueue");
    646         return;
    647     }
    648 
    649     mGraphicBufferProducer = alloc->mGraphicBufferProducer;
    650     mBufferListener = alloc->mBufferListener;
    651     mBufferListener->alloc[mCurrentIdx] = this;
    652     mBufferQueueInited = true;
    653 #endif
    654 }
    655 
    656 
    657 void Allocation::setSurface(const Context *rsc, RsNativeWindow sur) {
    658     ANativeWindow *nw = (ANativeWindow *)sur;
    659     rsc->mHal.funcs.allocation.setSurface(rsc, this, nw);
    660 }
    661 
    662 void Allocation::ioSend(const Context *rsc) {
    663     rsc->mHal.funcs.allocation.ioSend(rsc, this);
    664 }
    665 
    666 void Allocation::ioReceive(const Context *rsc) {
    667     void *ptr = nullptr;
    668     size_t stride = 0;
    669 #ifndef RS_COMPATIBILITY_LIB
    670     if (mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
    671         status_t ret = mGrallocConsumer->lockNextBuffer(mCurrentIdx);
    672 
    673         if (ret == OK) {
    674             rsc->mHal.funcs.allocation.ioReceive(rsc, this);
    675         } else if (ret == BAD_VALUE) {
    676             // No new frame, don't do anything
    677         } else {
    678             rsc->setError(RS_ERROR_DRIVER, "Error receiving IO input buffer.");
    679         }
    680 
    681     }
    682 #endif
    683 }
    684 
    685 bool Allocation::hasSameDims(const Allocation *other) const {
    686     const Type *type0 = this->getType(),
    687                *type1 = other->getType();
    688 
    689     return (type0->getCellCount() == type1->getCellCount()) &&
    690            (type0->getDimLOD()    == type1->getDimLOD())    &&
    691            (type0->getDimFaces()  == type1->getDimFaces())  &&
    692            (type0->getDimYuv()    == type1->getDimYuv())    &&
    693            (type0->getDimX()      == type1->getDimX())      &&
    694            (type0->getDimY()      == type1->getDimY())      &&
    695            (type0->getDimZ()      == type1->getDimZ());
    696 }
    697 
    698 
    699 /////////////////
    700 //
    701 
    702 namespace android {
    703 namespace renderscript {
    704 
    705 void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType src) {
    706     Allocation *a = static_cast<Allocation *>(va);
    707     a->sendDirty(rsc);
    708     a->syncAll(rsc, src);
    709 }
    710 
    711 void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
    712     Allocation *alloc = static_cast<Allocation *>(va);
    713     rsc->mHal.funcs.allocation.generateMipmaps(rsc, alloc);
    714 }
    715 
    716 void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t sizeBytes) {
    717     Allocation *a = static_cast<Allocation *>(va);
    718     const Type * t = a->getType();
    719     a->read(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
    720             t->getDimX(), t->getDimY(), data, sizeBytes, 0);
    721 }
    722 
    723 void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
    724                           uint32_t count, const void *data, size_t sizeBytes) {
    725     Allocation *a = static_cast<Allocation *>(va);
    726     a->data(rsc, xoff, lod, count, data, sizeBytes);
    727 }
    728 
    729 void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x,
    730                                  uint32_t lod, const void *data, size_t sizeBytes, size_t eoff) {
    731     Allocation *a = static_cast<Allocation *>(va);
    732     a->elementData(rsc, x, 0, 0, data, eoff, sizeBytes);
    733 }
    734 
    735 void rsi_AllocationElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t z,
    736                                uint32_t lod, const void *data, size_t sizeBytes, size_t eoff) {
    737     Allocation *a = static_cast<Allocation *>(va);
    738     a->elementData(rsc, x, y, z, data, eoff, sizeBytes);
    739 }
    740 
    741 void rsi_Allocation2DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    742                           uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
    743     Allocation *a = static_cast<Allocation *>(va);
    744     a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
    745 }
    746 
    747 void rsi_Allocation3DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod,
    748                           uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes, size_t stride) {
    749     Allocation *a = static_cast<Allocation *>(va);
    750     a->data(rsc, xoff, yoff, zoff, lod, w, h, d, data, sizeBytes, stride);
    751 }
    752 
    753 
    754 void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data, size_t sizeBytes) {
    755     Allocation *a = static_cast<Allocation *>(va);
    756     const Type * t = a->getType();
    757     if(t->getDimZ()) {
    758         a->read(rsc, 0, 0, 0, 0, t->getDimX(), t->getDimY(), t->getDimZ(),
    759                 data, sizeBytes, 0);
    760     } else if(t->getDimY()) {
    761         a->read(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
    762                 t->getDimX(), t->getDimY(), data, sizeBytes, 0);
    763     } else {
    764         a->read(rsc, 0, 0, t->getDimX(), data, sizeBytes);
    765     }
    766 
    767 }
    768 
    769 void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) {
    770     Allocation *a = static_cast<Allocation *>(va);
    771     a->resize1D(rsc, dimX);
    772 }
    773 
    774 void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY) {
    775     Allocation *a = static_cast<Allocation *>(va);
    776     a->resize2D(rsc, dimX, dimY);
    777 }
    778 
    779 RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype,
    780                                        RsAllocationMipmapControl mipmaps,
    781                                        uint32_t usages, uintptr_t ptr) {
    782     Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mipmaps, (void*)ptr);
    783     if (!alloc) {
    784         return nullptr;
    785     }
    786     alloc->incUserRef();
    787     return alloc;
    788 }
    789 
    790 RsAllocation rsi_AllocationCreateStrided(Context *rsc, RsType vtype,
    791                                          RsAllocationMipmapControl mipmaps,
    792                                          uint32_t usages, uintptr_t ptr,
    793                                          size_t requiredAlignment) {
    794     Allocation * alloc = Allocation::createAllocationStrided(rsc, static_cast<Type *>(vtype), usages, mipmaps,
    795                                                              (void*)ptr, requiredAlignment);
    796     if (!alloc) {
    797         return nullptr;
    798     }
    799     alloc->incUserRef();
    800     return alloc;
    801 }
    802 
    803 RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, RsType vtype,
    804                                             RsAllocationMipmapControl mipmaps,
    805                                             const void *data, size_t sizeBytes, uint32_t usages) {
    806     Type *t = static_cast<Type *>(vtype);
    807 
    808     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mipmaps, usages, 0);
    809     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
    810     if (texAlloc == nullptr) {
    811         ALOGE("Memory allocation failure");
    812         return nullptr;
    813     }
    814 
    815     texAlloc->data(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
    816                    t->getDimX(), t->getDimY(), data, sizeBytes, 0);
    817     if (mipmaps == RS_ALLOCATION_MIPMAP_FULL) {
    818         rsc->mHal.funcs.allocation.generateMipmaps(rsc, texAlloc);
    819     }
    820 
    821     texAlloc->sendDirty(rsc);
    822     return texAlloc;
    823 }
    824 
    825 RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype,
    826                                                 RsAllocationMipmapControl mipmaps,
    827                                                 const void *data, size_t sizeBytes, uint32_t usages) {
    828     Type *t = static_cast<Type *>(vtype);
    829 
    830     // Cubemap allocation's faces should be Width by Width each.
    831     // Source data should have 6 * Width by Width pixels
    832     // Error checking is done in the java layer
    833     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mipmaps, usages, 0);
    834     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
    835     if (texAlloc == nullptr) {
    836         ALOGE("Memory allocation failure");
    837         return nullptr;
    838     }
    839 
    840     uint32_t faceSize = t->getDimX();
    841     uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes();
    842     uint32_t copySize = faceSize * t->getElementSizeBytes();
    843 
    844     uint8_t *sourcePtr = (uint8_t*)data;
    845     for (uint32_t face = 0; face < 6; face ++) {
    846         for (uint32_t dI = 0; dI < faceSize; dI ++) {
    847             texAlloc->data(rsc, 0, dI, 0, (RsAllocationCubemapFace)face,
    848                            t->getDimX(), 1, sourcePtr + strideBytes * dI, copySize, 0);
    849         }
    850 
    851         // Move the data pointer to the next cube face
    852         sourcePtr += copySize;
    853     }
    854 
    855     if (mipmaps == RS_ALLOCATION_MIPMAP_FULL) {
    856         rsc->mHal.funcs.allocation.generateMipmaps(rsc, texAlloc);
    857     }
    858 
    859     texAlloc->sendDirty(rsc);
    860     return texAlloc;
    861 }
    862 
    863 void rsi_AllocationCopy2DRange(Context *rsc,
    864                                RsAllocation dstAlloc,
    865                                uint32_t dstXoff, uint32_t dstYoff,
    866                                uint32_t dstMip, uint32_t dstFace,
    867                                uint32_t width, uint32_t height,
    868                                RsAllocation srcAlloc,
    869                                uint32_t srcXoff, uint32_t srcYoff,
    870                                uint32_t srcMip, uint32_t srcFace) {
    871     Allocation *dst = static_cast<Allocation *>(dstAlloc);
    872     Allocation *src= static_cast<Allocation *>(srcAlloc);
    873     rsc->mHal.funcs.allocation.allocData2D(rsc, dst, dstXoff, dstYoff, dstMip,
    874                                            (RsAllocationCubemapFace)dstFace,
    875                                            width, height,
    876                                            src, srcXoff, srcYoff,srcMip,
    877                                            (RsAllocationCubemapFace)srcFace);
    878 }
    879 
    880 void rsi_AllocationCopy3DRange(Context *rsc,
    881                                RsAllocation dstAlloc,
    882                                uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
    883                                uint32_t dstMip,
    884                                uint32_t width, uint32_t height, uint32_t depth,
    885                                RsAllocation srcAlloc,
    886                                uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
    887                                uint32_t srcMip) {
    888     Allocation *dst = static_cast<Allocation *>(dstAlloc);
    889     Allocation *src= static_cast<Allocation *>(srcAlloc);
    890     rsc->mHal.funcs.allocation.allocData3D(rsc, dst, dstXoff, dstYoff, dstZoff, dstMip,
    891                                            width, height, depth,
    892                                            src, srcXoff, srcYoff, srcZoff, srcMip);
    893 }
    894 
    895 void rsi_AllocationSetupBufferQueue(Context *rsc, RsAllocation valloc, uint32_t numAlloc) {
    896     Allocation *alloc = static_cast<Allocation *>(valloc);
    897     alloc->setupGrallocConsumer(rsc, numAlloc);
    898 }
    899 
    900 void * rsi_AllocationGetSurface(Context *rsc, RsAllocation valloc) {
    901     Allocation *alloc = static_cast<Allocation *>(valloc);
    902     void *s = alloc->getSurface(rsc);
    903     return s;
    904 }
    905 
    906 void rsi_AllocationShareBufferQueue(Context *rsc, RsAllocation valloc1, RsAllocation valloc2) {
    907     Allocation *alloc1 = static_cast<Allocation *>(valloc1);
    908     Allocation *alloc2 = static_cast<Allocation *>(valloc2);
    909     alloc1->shareBufferQueue(rsc, alloc2);
    910 }
    911 
    912 void rsi_AllocationSetSurface(Context *rsc, RsAllocation valloc, RsNativeWindow sur) {
    913     Allocation *alloc = static_cast<Allocation *>(valloc);
    914     alloc->setSurface(rsc, sur);
    915 }
    916 
    917 void rsi_AllocationIoSend(Context *rsc, RsAllocation valloc) {
    918     Allocation *alloc = static_cast<Allocation *>(valloc);
    919     alloc->ioSend(rsc);
    920 }
    921 
    922 int64_t rsi_AllocationIoReceive(Context *rsc, RsAllocation valloc) {
    923     Allocation *alloc = static_cast<Allocation *>(valloc);
    924     alloc->ioReceive(rsc);
    925     return alloc->getTimeStamp();
    926 }
    927 
    928 void *rsi_AllocationGetPointer(Context *rsc, RsAllocation valloc,
    929                           uint32_t lod, RsAllocationCubemapFace face,
    930                           uint32_t z, uint32_t array, size_t *stride, size_t strideLen) {
    931     Allocation *alloc = static_cast<Allocation *>(valloc);
    932     rsAssert(strideLen == sizeof(size_t));
    933 
    934     return alloc->getPointer(rsc, lod, face, z, array, stride);
    935 }
    936 
    937 void rsi_Allocation1DRead(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
    938                           uint32_t count, void *data, size_t sizeBytes) {
    939     Allocation *a = static_cast<Allocation *>(va);
    940     rsc->mHal.funcs.allocation.read1D(rsc, a, xoff, lod, count, data, sizeBytes);
    941 }
    942 
    943 void rsi_AllocationElementRead(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t z,
    944                                  uint32_t lod, void *data, size_t sizeBytes, size_t eoff) {
    945     Allocation *a = static_cast<Allocation *>(va);
    946     a->elementRead(rsc, x, y, z, data, eoff, sizeBytes);
    947 }
    948 
    949 void rsi_Allocation2DRead(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff,
    950                           uint32_t lod, RsAllocationCubemapFace face, uint32_t w,
    951                           uint32_t h, void *data, size_t sizeBytes, size_t stride) {
    952     Allocation *a = static_cast<Allocation *>(va);
    953     a->read(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
    954 }
    955 
    956 void rsi_Allocation3DRead(Context *rsc, RsAllocation va,
    957                           uint32_t xoff, uint32_t yoff, uint32_t zoff,
    958                           uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
    959                           void *data, size_t sizeBytes, size_t stride) {
    960     Allocation *a = static_cast<Allocation *>(va);
    961     a->read(rsc, xoff, yoff, zoff, lod, w, h, d, data, sizeBytes, stride);
    962 }
    963 
    964 RsAllocation rsi_AllocationAdapterCreate(Context *rsc, RsType vwindow, RsAllocation vbase) {
    965 
    966 
    967     Allocation * alloc = Allocation::createAdapter(rsc,
    968             static_cast<Allocation *>(vbase), static_cast<Type *>(vwindow));
    969     if (!alloc) {
    970         return nullptr;
    971     }
    972     alloc->incUserRef();
    973     return alloc;
    974 }
    975 
    976 void rsi_AllocationAdapterOffset(Context *rsc, RsAllocation va, const uint32_t *offsets, size_t len) {
    977     Allocation *a = static_cast<Allocation *>(va);
    978     a->adapterOffset(rsc, offsets, len);
    979 }
    980 
    981 
    982 }
    983 }
    984