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