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