Home | History | Annotate | Download | only in rs
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "rsContext.h"
     18 #include "rs_hal.h"
     19 
     20 
     21 using namespace android;
     22 using namespace android::renderscript;
     23 
     24 Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages,
     25                        RsAllocationMipmapControl mc)
     26     : ObjectBase(rsc) {
     27 
     28     memset(&mHal, 0, sizeof(mHal));
     29     mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
     30     mHal.state.usageFlags = usages;
     31     mHal.state.mipmapControl = mc;
     32 
     33     setType(type);
     34     updateCache();
     35 }
     36 
     37 Allocation * Allocation::createAllocation(Context *rsc, const Type *type, uint32_t usages,
     38                               RsAllocationMipmapControl mc) {
     39     Allocation *a = new Allocation(rsc, type, usages, mc);
     40 
     41     if (!rsc->mHal.funcs.allocation.init(rsc, a, type->getElement()->getHasReferences())) {
     42         rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
     43         delete a;
     44         return NULL;
     45     }
     46     return a;
     47 }
     48 
     49 void Allocation::updateCache() {
     50     const Type *type = mHal.state.type;
     51     mHal.state.dimensionX = type->getDimX();
     52     mHal.state.dimensionY = type->getDimY();
     53     mHal.state.dimensionZ = type->getDimZ();
     54     mHal.state.hasFaces = type->getDimFaces();
     55     mHal.state.hasMipmaps = type->getDimLOD();
     56     mHal.state.elementSizeBytes = type->getElementSizeBytes();
     57     mHal.state.hasReferences = mHal.state.type->getElement()->getHasReferences();
     58 }
     59 
     60 Allocation::~Allocation() {
     61     freeChildrenUnlocked();
     62     mRSC->mHal.funcs.allocation.destroy(mRSC, this);
     63 }
     64 
     65 void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) {
     66     rsc->mHal.funcs.allocation.syncAll(rsc, this, src);
     67 }
     68 
     69 void Allocation::read(void *data) {
     70     memcpy(data, getPtr(), mHal.state.type->getSizeBytes());
     71 }
     72 
     73 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
     74                          uint32_t count, const void *data, uint32_t sizeBytes) {
     75     const uint32_t eSize = mHal.state.type->getElementSizeBytes();
     76 
     77     if ((count * eSize) != sizeBytes) {
     78         LOGE("Allocation::subData called with mismatched size expected %i, got %i",
     79              (count * eSize), sizeBytes);
     80         mHal.state.type->dumpLOGV("type info");
     81         return;
     82     }
     83 
     84     rsc->mHal.funcs.allocation.data1D(rsc, this, xoff, lod, count, data, sizeBytes);
     85     sendDirty(rsc);
     86 }
     87 
     88 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
     89              uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
     90     const uint32_t eSize = mHal.state.elementSizeBytes;
     91     const uint32_t lineSize = eSize * w;
     92 
     93     //LOGE("data2d %p,  %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes);
     94 
     95     if ((lineSize * h) != sizeBytes) {
     96         LOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes);
     97         rsAssert(!"Allocation::subData called with mismatched size");
     98         return;
     99     }
    100 
    101     rsc->mHal.funcs.allocation.data2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes);
    102     sendDirty(rsc);
    103 }
    104 
    105 void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
    106                       uint32_t lod, RsAllocationCubemapFace face,
    107                       uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
    108 }
    109 
    110 void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
    111                                 uint32_t cIdx, uint32_t sizeBytes) {
    112     uint32_t eSize = mHal.state.elementSizeBytes;
    113 
    114     if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
    115         LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
    116         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
    117         return;
    118     }
    119 
    120     if (x >= mHal.state.dimensionX) {
    121         LOGE("Error Allocation::subElementData X offset %i out of range.", x);
    122         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
    123         return;
    124     }
    125 
    126     const Element * e = mHal.state.type->getElement()->getField(cIdx);
    127     if (sizeBytes != e->getSizeBytes()) {
    128         LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes());
    129         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
    130         return;
    131     }
    132 
    133     rsc->mHal.funcs.allocation.elementData1D(rsc, this, x, data, cIdx, sizeBytes);
    134     sendDirty(rsc);
    135 }
    136 
    137 void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
    138                                 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
    139     uint32_t eSize = mHal.state.elementSizeBytes;
    140 
    141     if (x >= mHal.state.dimensionX) {
    142         LOGE("Error Allocation::subElementData X offset %i out of range.", x);
    143         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
    144         return;
    145     }
    146 
    147     if (y >= mHal.state.dimensionY) {
    148         LOGE("Error Allocation::subElementData X offset %i out of range.", x);
    149         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
    150         return;
    151     }
    152 
    153     if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
    154         LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
    155         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
    156         return;
    157     }
    158 
    159     const Element * e = mHal.state.type->getElement()->getField(cIdx);
    160 
    161     if (sizeBytes != e->getSizeBytes()) {
    162         LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes());
    163         rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
    164         return;
    165     }
    166 
    167     rsc->mHal.funcs.allocation.elementData2D(rsc, this, x, y, data, cIdx, sizeBytes);
    168     sendDirty(rsc);
    169 }
    170 
    171 void Allocation::addProgramToDirty(const Program *p) {
    172     mToDirtyList.push(p);
    173 }
    174 
    175 void Allocation::removeProgramToDirty(const Program *p) {
    176     for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
    177         if (mToDirtyList[ct] == p) {
    178             mToDirtyList.removeAt(ct);
    179             return;
    180         }
    181     }
    182     rsAssert(0);
    183 }
    184 
    185 void Allocation::dumpLOGV(const char *prefix) const {
    186     ObjectBase::dumpLOGV(prefix);
    187 
    188     String8 s(prefix);
    189     s.append(" type ");
    190     if (mHal.state.type) {
    191         mHal.state.type->dumpLOGV(s.string());
    192     }
    193 
    194     LOGV("%s allocation ptr=%p  mUsageFlags=0x04%x, mMipmapControl=0x%04x",
    195          prefix, getPtr(), mHal.state.usageFlags, mHal.state.mipmapControl);
    196 }
    197 
    198 void Allocation::serialize(OStream *stream) const {
    199     // Need to identify ourselves
    200     stream->addU32((uint32_t)getClassId());
    201 
    202     String8 name(getName());
    203     stream->addString(&name);
    204 
    205     // First thing we need to serialize is the type object since it will be needed
    206     // to initialize the class
    207     mHal.state.type->serialize(stream);
    208 
    209     uint32_t dataSize = mHal.state.type->getSizeBytes();
    210     // Write how much data we are storing
    211     stream->addU32(dataSize);
    212     // Now write the data
    213     stream->addByteArray(getPtr(), dataSize);
    214 }
    215 
    216 Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
    217     // First make sure we are reading the correct object
    218     RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
    219     if (classID != RS_A3D_CLASS_ID_ALLOCATION) {
    220         LOGE("allocation loading skipped due to invalid class id\n");
    221         return NULL;
    222     }
    223 
    224     String8 name;
    225     stream->loadString(&name);
    226 
    227     Type *type = Type::createFromStream(rsc, stream);
    228     if (!type) {
    229         return NULL;
    230     }
    231     type->compute();
    232 
    233     // Number of bytes we wrote out for this allocation
    234     uint32_t dataSize = stream->loadU32();
    235     if (dataSize != type->getSizeBytes()) {
    236         LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
    237         ObjectBase::checkDelete(type);
    238         return NULL;
    239     }
    240 
    241     Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
    242     alloc->setName(name.string(), name.size());
    243     type->decUserRef();
    244 
    245     uint32_t count = dataSize / type->getElementSizeBytes();
    246 
    247     // Read in all of our allocation data
    248     alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
    249     stream->reset(stream->getPos() + dataSize);
    250 
    251     return alloc;
    252 }
    253 
    254 void Allocation::sendDirty(const Context *rsc) const {
    255     for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
    256         mToDirtyList[ct]->forceDirty();
    257     }
    258     mRSC->mHal.funcs.allocation.markDirty(rsc, this);
    259 }
    260 
    261 void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const {
    262     const uint8_t *p = static_cast<const uint8_t *>(ptr);
    263     const Element *e = mHal.state.type->getElement();
    264     uint32_t stride = e->getSizeBytes();
    265 
    266     p += stride * startOff;
    267     while (ct > 0) {
    268         e->incRefs(p);
    269         ct --;
    270         p += stride;
    271     }
    272 }
    273 
    274 void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const {
    275     if (!mHal.state.hasReferences || !getIsScript()) {
    276         return;
    277     }
    278     const uint8_t *p = static_cast<const uint8_t *>(ptr);
    279     const Element *e = mHal.state.type->getElement();
    280     uint32_t stride = e->getSizeBytes();
    281 
    282     p += stride * startOff;
    283     while (ct > 0) {
    284         e->decRefs(p);
    285         ct --;
    286         p += stride;
    287     }
    288 }
    289 
    290 void Allocation::freeChildrenUnlocked () {
    291     decRefs(getPtr(), mHal.state.type->getSizeBytes() / mHal.state.type->getElementSizeBytes(), 0);
    292 }
    293 
    294 bool Allocation::freeChildren() {
    295     if (mHal.state.hasReferences) {
    296         incSysRef();
    297         freeChildrenUnlocked();
    298         return decSysRef();
    299     }
    300     return false;
    301 }
    302 
    303 void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) {
    304 }
    305 
    306 void Allocation::resize1D(Context *rsc, uint32_t dimX) {
    307     uint32_t oldDimX = mHal.state.dimensionX;
    308     if (dimX == oldDimX) {
    309         return;
    310     }
    311 
    312     ObjectBaseRef<Type> t = mHal.state.type->cloneAndResize1D(rsc, dimX);
    313     if (dimX < oldDimX) {
    314         decRefs(getPtr(), oldDimX - dimX, dimX);
    315     }
    316     rsc->mHal.funcs.allocation.resize(rsc, this, t.get(), mHal.state.hasReferences);
    317     setType(t.get());
    318     updateCache();
    319 }
    320 
    321 void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
    322     LOGE("not implemented");
    323 }
    324 
    325 /////////////////
    326 //
    327 
    328 namespace android {
    329 namespace renderscript {
    330 
    331 static void AllocationGenerateScriptMips(RsContext con, RsAllocation va);
    332 
    333 static void mip565(const Adapter2D &out, const Adapter2D &in) {
    334     uint32_t w = out.getDimX();
    335     uint32_t h = out.getDimY();
    336 
    337     for (uint32_t y=0; y < h; y++) {
    338         uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
    339         const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
    340         const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
    341 
    342         for (uint32_t x=0; x < w; x++) {
    343             *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
    344             oPtr ++;
    345             i1 += 2;
    346             i2 += 2;
    347         }
    348     }
    349 }
    350 
    351 static void mip8888(const Adapter2D &out, const Adapter2D &in) {
    352     uint32_t w = out.getDimX();
    353     uint32_t h = out.getDimY();
    354 
    355     for (uint32_t y=0; y < h; y++) {
    356         uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
    357         const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
    358         const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
    359 
    360         for (uint32_t x=0; x < w; x++) {
    361             *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
    362             oPtr ++;
    363             i1 += 2;
    364             i2 += 2;
    365         }
    366     }
    367 }
    368 
    369 static void mip8(const Adapter2D &out, const Adapter2D &in) {
    370     uint32_t w = out.getDimX();
    371     uint32_t h = out.getDimY();
    372 
    373     for (uint32_t y=0; y < h; y++) {
    374         uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
    375         const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
    376         const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
    377 
    378         for (uint32_t x=0; x < w; x++) {
    379             *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
    380             oPtr ++;
    381             i1 += 2;
    382             i2 += 2;
    383         }
    384     }
    385 }
    386 
    387 static void mip(const Adapter2D &out, const Adapter2D &in) {
    388     switch (out.getBaseType()->getElement()->getSizeBits()) {
    389     case 32:
    390         mip8888(out, in);
    391         break;
    392     case 16:
    393         mip565(out, in);
    394         break;
    395     case 8:
    396         mip8(out, in);
    397         break;
    398     }
    399 }
    400 
    401 void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType src) {
    402     Allocation *a = static_cast<Allocation *>(va);
    403     a->sendDirty(rsc);
    404     a->syncAll(rsc, src);
    405 }
    406 
    407 void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
    408     Allocation *texAlloc = static_cast<Allocation *>(va);
    409     AllocationGenerateScriptMips(rsc, texAlloc);
    410 }
    411 
    412 void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
    413     Allocation *texAlloc = static_cast<Allocation *>(va);
    414     const Type * t = texAlloc->getType();
    415 
    416     size_t s = t->getDimX() * t->getDimY() * t->getElementSizeBytes();
    417     if (s != dataLen) {
    418         rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size");
    419         return;
    420     }
    421 
    422     memcpy(data, texAlloc->getPtr(), s);
    423 }
    424 
    425 void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
    426                           uint32_t count, const void *data, size_t sizeBytes) {
    427     Allocation *a = static_cast<Allocation *>(va);
    428     a->data(rsc, xoff, lod, count, data, sizeBytes);
    429 }
    430 
    431 void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face,
    432                                  const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped
    433     Allocation *a = static_cast<Allocation *>(va);
    434     a->elementData(rsc, x, y, data, eoff, sizeBytes);
    435 }
    436 
    437 void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod,
    438                                  const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped
    439     Allocation *a = static_cast<Allocation *>(va);
    440     a->elementData(rsc, x, data, eoff, sizeBytes);
    441 }
    442 
    443 void rsi_Allocation2DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    444                           uint32_t w, uint32_t h, const void *data, size_t sizeBytes) {
    445     Allocation *a = static_cast<Allocation *>(va);
    446     a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes);
    447 }
    448 
    449 void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data, size_t data_length) {
    450     Allocation *a = static_cast<Allocation *>(va);
    451     a->read(data);
    452 }
    453 
    454 void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) {
    455     Allocation *a = static_cast<Allocation *>(va);
    456     a->resize1D(rsc, dimX);
    457 }
    458 
    459 void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY) {
    460     Allocation *a = static_cast<Allocation *>(va);
    461     a->resize2D(rsc, dimX, dimY);
    462 }
    463 
    464 static void AllocationGenerateScriptMips(RsContext con, RsAllocation va) {
    465     Context *rsc = static_cast<Context *>(con);
    466     Allocation *texAlloc = static_cast<Allocation *>(va);
    467     uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1;
    468     for (uint32_t face = 0; face < numFaces; face ++) {
    469         Adapter2D adapt(rsc, texAlloc);
    470         Adapter2D adapt2(rsc, texAlloc);
    471         adapt.setFace(face);
    472         adapt2.setFace(face);
    473         for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
    474             adapt.setLOD(lod);
    475             adapt2.setLOD(lod + 1);
    476             mip(adapt2, adapt);
    477         }
    478     }
    479 }
    480 
    481 RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype,
    482                                        RsAllocationMipmapControl mips,
    483                                        uint32_t usages) {
    484     Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mips);
    485     if (!alloc) {
    486         return NULL;
    487     }
    488     alloc->incUserRef();
    489     return alloc;
    490 }
    491 
    492 RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, RsType vtype,
    493                                             RsAllocationMipmapControl mips,
    494                                             const void *data, size_t data_length, uint32_t usages) {
    495     Type *t = static_cast<Type *>(vtype);
    496 
    497     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
    498     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
    499     if (texAlloc == NULL) {
    500         LOGE("Memory allocation failure");
    501         return NULL;
    502     }
    503 
    504     memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes());
    505     if (mips == RS_ALLOCATION_MIPMAP_FULL) {
    506         AllocationGenerateScriptMips(rsc, texAlloc);
    507     }
    508 
    509     texAlloc->sendDirty(rsc);
    510     return texAlloc;
    511 }
    512 
    513 RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype,
    514                                                 RsAllocationMipmapControl mips,
    515                                                 const void *data, size_t data_length, uint32_t usages) {
    516     Type *t = static_cast<Type *>(vtype);
    517 
    518     // Cubemap allocation's faces should be Width by Width each.
    519     // Source data should have 6 * Width by Width pixels
    520     // Error checking is done in the java layer
    521     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages);
    522     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
    523     if (texAlloc == NULL) {
    524         LOGE("Memory allocation failure");
    525         return NULL;
    526     }
    527 
    528     uint32_t faceSize = t->getDimX();
    529     uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes();
    530     uint32_t copySize = faceSize * t->getElementSizeBytes();
    531 
    532     uint8_t *sourcePtr = (uint8_t*)data;
    533     for (uint32_t face = 0; face < 6; face ++) {
    534         Adapter2D faceAdapter(rsc, texAlloc);
    535         faceAdapter.setFace(face);
    536 
    537         for (uint32_t dI = 0; dI < faceSize; dI ++) {
    538             memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize);
    539         }
    540 
    541         // Move the data pointer to the next cube face
    542         sourcePtr += copySize;
    543     }
    544 
    545     if (mips == RS_ALLOCATION_MIPMAP_FULL) {
    546         AllocationGenerateScriptMips(rsc, texAlloc);
    547     }
    548 
    549     texAlloc->sendDirty(rsc);
    550     return texAlloc;
    551 }
    552 
    553 void rsi_AllocationCopy2DRange(Context *rsc,
    554                                RsAllocation dstAlloc,
    555                                uint32_t dstXoff, uint32_t dstYoff,
    556                                uint32_t dstMip, uint32_t dstFace,
    557                                uint32_t width, uint32_t height,
    558                                RsAllocation srcAlloc,
    559                                uint32_t srcXoff, uint32_t srcYoff,
    560                                uint32_t srcMip, uint32_t srcFace) {
    561     Allocation *dst = static_cast<Allocation *>(dstAlloc);
    562     Allocation *src= static_cast<Allocation *>(srcAlloc);
    563     rsc->mHal.funcs.allocation.allocData2D(rsc, dst, dstXoff, dstYoff, dstMip,
    564                                            (RsAllocationCubemapFace)dstFace,
    565                                            width, height,
    566                                            src, srcXoff, srcYoff,srcMip,
    567                                            (RsAllocationCubemapFace)srcFace);
    568 }
    569 
    570 }
    571 }
    572 
    573 const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
    574     Allocation *a = static_cast<Allocation *>(va);
    575     a->getType()->incUserRef();
    576 
    577     return a->getType();
    578 }
    579