rsAllocation.cpp revision f0c1df480304a72ce41e7d4b088319cbd7f0938a
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#ifndef ANDROID_RS_BUILD_FOR_HOST
17#include "rsContext.h"
18
19#include <GLES/gl.h>
20#include <GLES2/gl2.h>
21#include <GLES/glext.h>
22#else
23#include "rsContextHostStub.h"
24
25#include <OpenGL/gl.h>
26#include <OpenGl/glext.h>
27#endif
28
29#include "utils/StopWatch.h"
30
31using namespace android;
32using namespace android::renderscript;
33
34Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc)
35{
36    init(rsc, type);
37
38    mPtr = malloc(mType->getSizeBytes());
39    if (mType->getElement()->getHasReferences()) {
40        memset(mPtr, 0, mType->getSizeBytes());
41    }
42    if (!mPtr) {
43        LOGE("Allocation::Allocation, alloc failure");
44    }
45}
46
47Allocation::Allocation(Context *rsc, const Type *type, void *bmp,
48                       void *callbackData, RsBitmapCallback_t callback)
49: ObjectBase(rsc)
50{
51    init(rsc, type);
52
53    mPtr = bmp;
54    mUserBitmapCallback = callback;
55    mUserBitmapCallbackData = callbackData;
56}
57
58void Allocation::init(Context *rsc, const Type *type)
59{
60    mPtr = NULL;
61
62    mCpuWrite = false;
63    mCpuRead = false;
64    mGpuWrite = false;
65    mGpuRead = false;
66
67    mReadWriteRatio = 0;
68    mUpdateSize = 0;
69
70    mIsTexture = false;
71    mTextureID = 0;
72    mIsVertexBuffer = false;
73    mBufferID = 0;
74    mUploadDefered = false;
75
76    mUserBitmapCallback = NULL;
77    mUserBitmapCallbackData = NULL;
78
79    mType.set(type);
80    rsAssert(type);
81
82    mPtr = NULL;
83}
84
85Allocation::~Allocation()
86{
87    if (mUserBitmapCallback != NULL) {
88        mUserBitmapCallback(mUserBitmapCallbackData);
89    } else {
90        free(mPtr);
91    }
92    mPtr = NULL;
93
94    if (mBufferID) {
95        // Causes a SW crash....
96        //LOGV(" mBufferID %i", mBufferID);
97        //glDeleteBuffers(1, &mBufferID);
98        //mBufferID = 0;
99    }
100    if (mTextureID) {
101        glDeleteTextures(1, &mTextureID);
102        mTextureID = 0;
103    }
104}
105
106void Allocation::setCpuWritable(bool)
107{
108}
109
110void Allocation::setGpuWritable(bool)
111{
112}
113
114void Allocation::setCpuReadable(bool)
115{
116}
117
118void Allocation::setGpuReadable(bool)
119{
120}
121
122bool Allocation::fixAllocation()
123{
124    return false;
125}
126
127void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset)
128{
129    rsAssert(lodOffset < mType->getLODCount());
130    mIsTexture = true;
131    mTextureLOD = lodOffset;
132    mUploadDefered = true;
133    mTextureGenMipmap = !mType->getDimLOD() && genMipmap;
134}
135
136void Allocation::uploadToTexture(const Context *rsc)
137{
138    //rsAssert(!mTextureId);
139
140    mIsTexture = true;
141    if (!rsc->checkDriver()) {
142        mUploadDefered = true;
143        return;
144    }
145
146    GLenum type = mType->getElement()->getComponent().getGLType();
147    GLenum format = mType->getElement()->getComponent().getGLFormat();
148
149    if (!type || !format) {
150        return;
151    }
152
153    bool isFirstUpload = false;
154
155    if (!mTextureID) {
156        glGenTextures(1, &mTextureID);
157
158        if (!mTextureID) {
159            // This should not happen, however, its likely the cause of the
160            // white sqare bug.
161            // Force a crash to 1: restart the app, 2: make sure we get a bugreport.
162            LOGE("Upload to texture failed to gen mTextureID");
163            rsc->dumpDebug();
164            mUploadDefered = true;
165            return;
166        }
167        isFirstUpload = true;
168    }
169    glBindTexture(GL_TEXTURE_2D, mTextureID);
170    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
171
172    Adapter2D adapt(getContext(), this);
173    for(uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
174        adapt.setLOD(lod+mTextureLOD);
175
176        uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
177        if(isFirstUpload) {
178            glTexImage2D(GL_TEXTURE_2D, lod, format,
179                         adapt.getDimX(), adapt.getDimY(),
180                         0, format, type, ptr);
181        } else {
182            glTexSubImage2D(GL_TEXTURE_2D, lod, 0, 0,
183                         adapt.getDimX(), adapt.getDimY(),
184                         format, type, ptr);
185        }
186    }
187    if (mTextureGenMipmap) {
188#ifndef ANDROID_RS_BUILD_FOR_HOST
189        glGenerateMipmap(GL_TEXTURE_2D);
190#endif //ANDROID_RS_BUILD_FOR_HOST
191    }
192
193    rsc->checkError("Allocation::uploadToTexture");
194}
195
196void Allocation::deferedUploadToBufferObject(const Context *rsc)
197{
198    mIsVertexBuffer = true;
199    mUploadDefered = true;
200}
201
202void Allocation::uploadToBufferObject(const Context *rsc)
203{
204    rsAssert(!mType->getDimY());
205    rsAssert(!mType->getDimZ());
206
207    mIsVertexBuffer = true;
208    if (!rsc->checkDriver()) {
209        mUploadDefered = true;
210        return;
211    }
212
213    if (!mBufferID) {
214        glGenBuffers(1, &mBufferID);
215    }
216    if (!mBufferID) {
217        LOGE("Upload to buffer object failed");
218        mUploadDefered = true;
219        return;
220    }
221
222    glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
223    glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
224    glBindBuffer(GL_ARRAY_BUFFER, 0);
225    rsc->checkError("Allocation::uploadToBufferObject");
226}
227
228void Allocation::uploadCheck(const Context *rsc)
229{
230    if (mUploadDefered) {
231        mUploadDefered = false;
232        if (mIsVertexBuffer) {
233            uploadToBufferObject(rsc);
234        }
235        if (mIsTexture) {
236            uploadToTexture(rsc);
237        }
238    }
239}
240
241
242void Allocation::data(Context *rsc, const void *data, uint32_t sizeBytes)
243{
244    uint32_t size = mType->getSizeBytes();
245    if (size != sizeBytes) {
246        LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes);
247        return;
248    }
249
250    if (mType->getElement()->getHasReferences()) {
251        incRefs(data, sizeBytes / mType->getElement()->getSizeBytes());
252        decRefs(mPtr, sizeBytes / mType->getElement()->getSizeBytes());
253    }
254
255    memcpy(mPtr, data, size);
256    sendDirty();
257    mUploadDefered = true;
258}
259
260void Allocation::read(void *data)
261{
262    memcpy(data, mPtr, mType->getSizeBytes());
263}
264
265void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
266{
267    uint32_t eSize = mType->getElementSizeBytes();
268    uint8_t * ptr = static_cast<uint8_t *>(mPtr);
269    ptr += eSize * xoff;
270    uint32_t size = count * eSize;
271
272    if (size != sizeBytes) {
273        LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes);
274        mType->dumpLOGV("type info");
275        return;
276    }
277
278    if (mType->getElement()->getHasReferences()) {
279        incRefs(data, count);
280        decRefs(ptr, count);
281    }
282
283    memcpy(ptr, data, size);
284    sendDirty();
285    mUploadDefered = true;
286}
287
288void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff,
289             uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
290{
291    uint32_t eSize = mType->getElementSizeBytes();
292    uint32_t lineSize = eSize * w;
293    uint32_t destW = mType->getDimX();
294
295    const uint8_t *src = static_cast<const uint8_t *>(data);
296    uint8_t *dst = static_cast<uint8_t *>(mPtr);
297    dst += eSize * (xoff + yoff * destW);
298
299    if ((lineSize * eSize * h) != sizeBytes) {
300        rsAssert(!"Allocation::subData called with mismatched size");
301        return;
302    }
303
304    for (uint32_t line=yoff; line < (yoff+h); line++) {
305        if (mType->getElement()->getHasReferences()) {
306            incRefs(src, w);
307            decRefs(dst, w);
308        }
309        memcpy(dst, src, lineSize);
310        src += lineSize;
311        dst += destW * eSize;
312    }
313    sendDirty();
314    mUploadDefered = true;
315}
316
317void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
318             uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes)
319{
320}
321
322void Allocation::subElementData(Context *rsc, uint32_t x, const void *data,
323                                uint32_t cIdx, uint32_t sizeBytes)
324{
325    uint32_t eSize = mType->getElementSizeBytes();
326    uint8_t * ptr = static_cast<uint8_t *>(mPtr);
327    ptr += eSize * x;
328
329    if (cIdx >= mType->getElement()->getFieldCount()) {
330        LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
331        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
332        return;
333    }
334
335    if (x >= mType->getDimX()) {
336        LOGE("Error Allocation::subElementData X offset %i out of range.", x);
337        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
338        return;
339    }
340
341    const Element * e = mType->getElement()->getField(cIdx);
342    ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
343
344    if (sizeBytes != e->getSizeBytes()) {
345        LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
346        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
347        return;
348    }
349
350    if (e->getHasReferences()) {
351        e->incRefs(data);
352        e->decRefs(ptr);
353    }
354
355    memcpy(ptr, data, sizeBytes);
356    sendDirty();
357    mUploadDefered = true;
358}
359
360void Allocation::subElementData(Context *rsc, uint32_t x, uint32_t y,
361                                const void *data, uint32_t cIdx, uint32_t sizeBytes)
362{
363    uint32_t eSize = mType->getElementSizeBytes();
364    uint8_t * ptr = static_cast<uint8_t *>(mPtr);
365    ptr += eSize * (x + y * mType->getDimX());
366
367    if (x >= mType->getDimX()) {
368        LOGE("Error Allocation::subElementData X offset %i out of range.", x);
369        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
370        return;
371    }
372
373    if (y >= mType->getDimY()) {
374        LOGE("Error Allocation::subElementData X offset %i out of range.", x);
375        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
376        return;
377    }
378
379    if (cIdx >= mType->getElement()->getFieldCount()) {
380        LOGE("Error Allocation::subElementData component %i out of range.", cIdx);
381        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
382        return;
383    }
384
385    const Element * e = mType->getElement()->getField(cIdx);
386    ptr += mType->getElement()->getFieldOffsetBytes(cIdx);
387
388    if (sizeBytes != e->getSizeBytes()) {
389        LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes());
390        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
391        return;
392    }
393
394    if (e->getHasReferences()) {
395        e->incRefs(data);
396        e->decRefs(ptr);
397    }
398
399    memcpy(ptr, data, sizeBytes);
400    sendDirty();
401    mUploadDefered = true;
402}
403
404void Allocation::addProgramToDirty(const Program *p)
405{
406    mToDirtyList.push(p);
407}
408
409void Allocation::removeProgramToDirty(const Program *p)
410{
411    for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
412        if (mToDirtyList[ct] == p) {
413            mToDirtyList.removeAt(ct);
414            return;
415        }
416    }
417    rsAssert(0);
418}
419
420void Allocation::dumpLOGV(const char *prefix) const
421{
422    ObjectBase::dumpLOGV(prefix);
423
424    String8 s(prefix);
425    s.append(" type ");
426    if (mType.get()) {
427        mType->dumpLOGV(s.string());
428    }
429
430    LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i",
431          prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead);
432
433    LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i",
434          prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID);
435
436}
437
438void Allocation::serialize(OStream *stream) const
439{
440    // Need to identify ourselves
441    stream->addU32((uint32_t)getClassId());
442
443    String8 name(getName());
444    stream->addString(&name);
445
446    // First thing we need to serialize is the type object since it will be needed
447    // to initialize the class
448    mType->serialize(stream);
449
450    uint32_t dataSize = mType->getSizeBytes();
451    // Write how much data we are storing
452    stream->addU32(dataSize);
453    // Now write the data
454    stream->addByteArray(mPtr, dataSize);
455}
456
457Allocation *Allocation::createFromStream(Context *rsc, IStream *stream)
458{
459    // First make sure we are reading the correct object
460    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
461    if(classID != RS_A3D_CLASS_ID_ALLOCATION) {
462        LOGE("allocation loading skipped due to invalid class id\n");
463        return NULL;
464    }
465
466    String8 name;
467    stream->loadString(&name);
468
469    Type *type = Type::createFromStream(rsc, stream);
470    if(!type) {
471        return NULL;
472    }
473    type->compute();
474
475    // Number of bytes we wrote out for this allocation
476    uint32_t dataSize = stream->loadU32();
477    if(dataSize != type->getSizeBytes()) {
478        LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n");
479        ObjectBase::checkDelete(type);
480        return NULL;
481    }
482
483    Allocation *alloc = new Allocation(rsc, type);
484    alloc->setName(name.string(), name.size());
485
486    // Read in all of our allocation data
487    alloc->data(rsc, stream->getPtr() + stream->getPos(), dataSize);
488    stream->reset(stream->getPos() + dataSize);
489
490    return alloc;
491}
492
493void Allocation::sendDirty() const
494{
495    for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
496        mToDirtyList[ct]->forceDirty();
497    }
498}
499
500void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const
501{
502    const uint8_t *p = static_cast<const uint8_t *>(ptr);
503    const Element *e = mType->getElement();
504    uint32_t stride = e->getSizeBytes();
505
506    p += stride * startOff;
507    while (ct > 0) {
508        e->incRefs(p);
509        ct --;
510        p += stride;
511    }
512}
513
514void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const
515{
516    const uint8_t *p = static_cast<const uint8_t *>(ptr);
517    const Element *e = mType->getElement();
518    uint32_t stride = e->getSizeBytes();
519
520    p += stride * startOff;
521    while (ct > 0) {
522        e->decRefs(p);
523        ct --;
524        p += stride;
525    }
526}
527
528void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len)
529{
530}
531
532void Allocation::resize1D(Context *rsc, uint32_t dimX)
533{
534    Type *t = mType->cloneAndResize1D(rsc, dimX);
535
536    uint32_t oldDimX = mType->getDimX();
537    if (dimX == oldDimX) {
538        return;
539    }
540
541    if (dimX < oldDimX) {
542        decRefs(mPtr, oldDimX - dimX, dimX);
543    }
544    mPtr = realloc(mPtr, t->getSizeBytes());
545
546    if (dimX > oldDimX) {
547        const Element *e = mType->getElement();
548        uint32_t stride = e->getSizeBytes();
549        memset(((uint8_t *)mPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX));
550    }
551    mType.set(t);
552}
553
554void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY)
555{
556    LOGE("not implemented");
557}
558
559/////////////////
560//
561
562
563namespace android {
564namespace renderscript {
565
566void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel)
567{
568    Allocation *alloc = static_cast<Allocation *>(va);
569    alloc->deferedUploadToTexture(rsc, genmip, baseMipLevel);
570}
571
572void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
573{
574    Allocation *alloc = static_cast<Allocation *>(va);
575    alloc->deferedUploadToBufferObject(rsc);
576}
577
578static void mip565(const Adapter2D &out, const Adapter2D &in)
579{
580    uint32_t w = out.getDimX();
581    uint32_t h = out.getDimY();
582
583    for (uint32_t y=0; y < h; y++) {
584        uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
585        const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
586        const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
587
588        for (uint32_t x=0; x < w; x++) {
589            *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
590            oPtr ++;
591            i1 += 2;
592            i2 += 2;
593        }
594    }
595}
596
597static void mip8888(const Adapter2D &out, const Adapter2D &in)
598{
599    uint32_t w = out.getDimX();
600    uint32_t h = out.getDimY();
601
602    for (uint32_t y=0; y < h; y++) {
603        uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
604        const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
605        const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
606
607        for (uint32_t x=0; x < w; x++) {
608            *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
609            oPtr ++;
610            i1 += 2;
611            i2 += 2;
612        }
613    }
614}
615
616static void mip8(const Adapter2D &out, const Adapter2D &in)
617{
618    uint32_t w = out.getDimX();
619    uint32_t h = out.getDimY();
620
621    for (uint32_t y=0; y < h; y++) {
622        uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
623        const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
624        const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
625
626        for (uint32_t x=0; x < w; x++) {
627            *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
628            oPtr ++;
629            i1 += 2;
630            i2 += 2;
631        }
632    }
633}
634
635static void mip(const Adapter2D &out, const Adapter2D &in)
636{
637    switch(out.getBaseType()->getElement()->getSizeBits()) {
638    case 32:
639        mip8888(out, in);
640        break;
641    case 16:
642        mip565(out, in);
643        break;
644    case 8:
645        mip8(out, in);
646        break;
647
648    }
649
650}
651
652typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
653
654static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count)
655{
656    memcpy(dst, src, count * 2);
657}
658static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count)
659{
660    memcpy(dst, src, count);
661}
662static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count)
663{
664    memcpy(dst, src, count * 4);
665}
666
667
668static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count)
669{
670    uint16_t *d = static_cast<uint16_t *>(dst);
671    const uint8_t *s = static_cast<const uint8_t *>(src);
672
673    while(count--) {
674        *d = rs888to565(s[0], s[1], s[2]);
675        d++;
676        s+= 3;
677    }
678}
679
680static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count)
681{
682    uint16_t *d = static_cast<uint16_t *>(dst);
683    const uint8_t *s = static_cast<const uint8_t *>(src);
684
685    while(count--) {
686        *d = rs888to565(s[0], s[1], s[2]);
687        d++;
688        s+= 4;
689    }
690}
691
692static ElementConverter_t pickConverter(const Element *dst, const Element *src)
693{
694    GLenum srcGLType = src->getComponent().getGLType();
695    GLenum srcGLFmt = src->getComponent().getGLFormat();
696    GLenum dstGLType = dst->getComponent().getGLType();
697    GLenum dstGLFmt = dst->getComponent().getGLFormat();
698
699    if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
700        switch(dst->getSizeBytes()) {
701        case 4:
702            return elementConverter_cpy_32;
703        case 2:
704            return elementConverter_cpy_16;
705        case 1:
706            return elementConverter_cpy_8;
707        }
708    }
709
710    if (srcGLType == GL_UNSIGNED_BYTE &&
711        srcGLFmt == GL_RGB &&
712        dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
713        dstGLFmt == GL_RGB) {
714
715        return elementConverter_888_to_565;
716    }
717
718    if (srcGLType == GL_UNSIGNED_BYTE &&
719        srcGLFmt == GL_RGBA &&
720        dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
721        dstGLFmt == GL_RGB) {
722
723        return elementConverter_8888_to_565;
724    }
725
726    LOGE("pickConverter, unsuported combo, src %p,  dst %p", src, dst);
727    LOGE("pickConverter, srcGLType = %x,  srcGLFmt = %x", srcGLType, srcGLFmt);
728    LOGE("pickConverter, dstGLType = %x,  dstGLFmt = %x", dstGLType, dstGLFmt);
729    src->dumpLOGV("SRC ");
730    dst->dumpLOGV("DST ");
731    return 0;
732}
733
734#ifndef ANDROID_RS_BUILD_FOR_HOST
735
736RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype,
737                                           void *bmp, void *callbackData, RsBitmapCallback_t callback)
738{
739    const Type * type = static_cast<const Type *>(vtype);
740    Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback);
741    alloc->incUserRef();
742    return alloc;
743}
744
745void rsi_AllocationUpdateFromBitmap(Context *rsc, RsAllocation va, RsElement _src, const void *data)
746{
747    Allocation *texAlloc = static_cast<Allocation *>(va);
748    const Element *src = static_cast<const Element *>(_src);
749    const Element *dst = texAlloc->getType()->getElement();
750    uint32_t w = texAlloc->getType()->getDimX();
751    uint32_t h = texAlloc->getType()->getDimY();
752    bool genMips = texAlloc->getType()->getDimLOD();
753
754    ElementConverter_t cvt = pickConverter(dst, src);
755    if (cvt) {
756        cvt(texAlloc->getPtr(), data, w * h);
757        if (genMips) {
758            Adapter2D adapt(rsc, texAlloc);
759            Adapter2D adapt2(rsc, texAlloc);
760            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
761                adapt.setLOD(lod);
762                adapt2.setLOD(lod + 1);
763                mip(adapt2, adapt);
764            }
765        }
766    } else {
767        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
768    }
769}
770
771void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
772{
773    Allocation *a = static_cast<Allocation *>(va);
774    a->data(rsc, data, sizeBytes);
775}
776
777void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
778{
779    Allocation *a = static_cast<Allocation *>(va);
780    a->subData(rsc, xoff, count, data, sizeBytes);
781}
782
783void rsi_Allocation2DSubElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, const void *data, uint32_t eoff, uint32_t sizeBytes)
784{
785    Allocation *a = static_cast<Allocation *>(va);
786    a->subElementData(rsc, x, y, data, eoff, sizeBytes);
787}
788
789void rsi_Allocation1DSubElementData(Context *rsc, RsAllocation va, uint32_t x, const void *data, uint32_t eoff, uint32_t sizeBytes)
790{
791    Allocation *a = static_cast<Allocation *>(va);
792    a->subElementData(rsc, x, data, eoff, sizeBytes);
793}
794
795void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
796{
797    Allocation *a = static_cast<Allocation *>(va);
798    a->subData(rsc, xoff, yoff, w, h, data, sizeBytes);
799}
800
801void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data)
802{
803    Allocation *a = static_cast<Allocation *>(va);
804    a->read(data);
805}
806
807void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX)
808{
809    Allocation *a = static_cast<Allocation *>(va);
810    a->resize1D(rsc, dimX);
811}
812
813void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY)
814{
815    Allocation *a = static_cast<Allocation *>(va);
816    a->resize2D(rsc, dimX, dimY);
817}
818
819const void* rsi_AllocationGetType(Context *rsc, RsAllocation va)
820{
821    Allocation *a = static_cast<Allocation *>(va);
822    a->getType()->incUserRef();
823
824    return a->getType();
825}
826
827#endif //ANDROID_RS_BUILD_FOR_HOST
828
829}
830}
831
832RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype)
833{
834    Context *rsc = static_cast<Context *>(con);
835    Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype));
836    alloc->incUserRef();
837    return alloc;
838}
839
840RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
841{
842    Context *rsc = static_cast<Context *>(con);
843    const Element *src = static_cast<const Element *>(_src);
844    const Element *dst = static_cast<const Element *>(_dst);
845
846    //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
847    RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
848    uint32_t dimValues[] = {w, h, genMips};
849    RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
850
851    RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, type);
852    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
853    if (texAlloc == NULL) {
854        LOGE("Memory allocation failure");
855        return NULL;
856    }
857
858    ElementConverter_t cvt = pickConverter(dst, src);
859    if (cvt) {
860        cvt(texAlloc->getPtr(), data, w * h);
861        if (genMips) {
862            Adapter2D adapt(rsc, texAlloc);
863            Adapter2D adapt2(rsc, texAlloc);
864            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
865                adapt.setLOD(lod);
866                adapt2.setLOD(lod + 1);
867                mip(adapt2, adapt);
868            }
869        }
870    } else {
871        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
872    }
873
874    return texAlloc;
875}
876
877