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