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