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