rsAllocation.cpp revision 225afd317e101a7be5fe02c0a86361146ea89f05
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
566RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype)
567{
568    const Type * type = static_cast<const Type *>(vtype);
569
570    Allocation * alloc = new Allocation(rsc, type);
571    alloc->incUserRef();
572    return alloc;
573}
574
575RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count)
576{
577    Type * type = new Type(rsc);
578    type->setDimX(count);
579    type->setElement(static_cast<Element *>(e));
580    type->compute();
581    return rsi_AllocationCreateTyped(rsc, type);
582}
583
584void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel)
585{
586    Allocation *alloc = static_cast<Allocation *>(va);
587    alloc->deferedUploadToTexture(rsc, genmip, baseMipLevel);
588}
589
590void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
591{
592    Allocation *alloc = static_cast<Allocation *>(va);
593    alloc->deferedUploadToBufferObject(rsc);
594}
595
596static void mip565(const Adapter2D &out, const Adapter2D &in)
597{
598    uint32_t w = out.getDimX();
599    uint32_t h = out.getDimY();
600
601    for (uint32_t y=0; y < h; y++) {
602        uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
603        const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
604        const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
605
606        for (uint32_t x=0; x < w; x++) {
607            *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
608            oPtr ++;
609            i1 += 2;
610            i2 += 2;
611        }
612    }
613}
614
615static void mip8888(const Adapter2D &out, const Adapter2D &in)
616{
617    uint32_t w = out.getDimX();
618    uint32_t h = out.getDimY();
619
620    for (uint32_t y=0; y < h; y++) {
621        uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
622        const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
623        const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
624
625        for (uint32_t x=0; x < w; x++) {
626            *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
627            oPtr ++;
628            i1 += 2;
629            i2 += 2;
630        }
631    }
632}
633
634static void mip8(const Adapter2D &out, const Adapter2D &in)
635{
636    uint32_t w = out.getDimX();
637    uint32_t h = out.getDimY();
638
639    for (uint32_t y=0; y < h; y++) {
640        uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
641        const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
642        const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
643
644        for (uint32_t x=0; x < w; x++) {
645            *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
646            oPtr ++;
647            i1 += 2;
648            i2 += 2;
649        }
650    }
651}
652
653static void mip(const Adapter2D &out, const Adapter2D &in)
654{
655    switch(out.getBaseType()->getElement()->getSizeBits()) {
656    case 32:
657        mip8888(out, in);
658        break;
659    case 16:
660        mip565(out, in);
661        break;
662    case 8:
663        mip8(out, in);
664        break;
665
666    }
667
668}
669
670typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
671
672static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count)
673{
674    memcpy(dst, src, count * 2);
675}
676static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count)
677{
678    memcpy(dst, src, count);
679}
680static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count)
681{
682    memcpy(dst, src, count * 4);
683}
684
685
686static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count)
687{
688    uint16_t *d = static_cast<uint16_t *>(dst);
689    const uint8_t *s = static_cast<const uint8_t *>(src);
690
691    while(count--) {
692        *d = rs888to565(s[0], s[1], s[2]);
693        d++;
694        s+= 3;
695    }
696}
697
698static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count)
699{
700    uint16_t *d = static_cast<uint16_t *>(dst);
701    const uint8_t *s = static_cast<const uint8_t *>(src);
702
703    while(count--) {
704        *d = rs888to565(s[0], s[1], s[2]);
705        d++;
706        s+= 4;
707    }
708}
709
710static ElementConverter_t pickConverter(const Element *dst, const Element *src)
711{
712    GLenum srcGLType = src->getComponent().getGLType();
713    GLenum srcGLFmt = src->getComponent().getGLFormat();
714    GLenum dstGLType = dst->getComponent().getGLType();
715    GLenum dstGLFmt = dst->getComponent().getGLFormat();
716
717    if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
718        switch(dst->getSizeBytes()) {
719        case 4:
720            return elementConverter_cpy_32;
721        case 2:
722            return elementConverter_cpy_16;
723        case 1:
724            return elementConverter_cpy_8;
725        }
726    }
727
728    if (srcGLType == GL_UNSIGNED_BYTE &&
729        srcGLFmt == GL_RGB &&
730        dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
731        dstGLFmt == GL_RGB) {
732
733        return elementConverter_888_to_565;
734    }
735
736    if (srcGLType == GL_UNSIGNED_BYTE &&
737        srcGLFmt == GL_RGBA &&
738        dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
739        dstGLFmt == GL_RGB) {
740
741        return elementConverter_8888_to_565;
742    }
743
744    LOGE("pickConverter, unsuported combo, src %p,  dst %p", src, dst);
745    LOGE("pickConverter, srcGLType = %x,  srcGLFmt = %x", srcGLType, srcGLFmt);
746    LOGE("pickConverter, dstGLType = %x,  dstGLFmt = %x", dstGLType, dstGLFmt);
747    src->dumpLOGV("SRC ");
748    dst->dumpLOGV("DST ");
749    return 0;
750}
751
752#ifndef ANDROID_RS_BUILD_FOR_HOST
753
754RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype,
755                                           void *bmp, void *callbackData, RsBitmapCallback_t callback)
756{
757    const Type * type = static_cast<const Type *>(vtype);
758    Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback);
759    alloc->incUserRef();
760    return alloc;
761}
762
763void rsi_AllocationUpdateFromBitmap(Context *rsc, RsAllocation va, RsElement _src, const void *data)
764{
765    Allocation *texAlloc = static_cast<Allocation *>(va);
766    const Element *src = static_cast<const Element *>(_src);
767    const Element *dst = texAlloc->getType()->getElement();
768    uint32_t w = texAlloc->getType()->getDimX();
769    uint32_t h = texAlloc->getType()->getDimY();
770    bool genMips = texAlloc->getType()->getDimLOD();
771
772    ElementConverter_t cvt = pickConverter(dst, src);
773    if (cvt) {
774        cvt(texAlloc->getPtr(), data, w * h);
775        if (genMips) {
776            Adapter2D adapt(rsc, texAlloc);
777            Adapter2D adapt2(rsc, texAlloc);
778            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
779                adapt.setLOD(lod);
780                adapt2.setLOD(lod + 1);
781                mip(adapt2, adapt);
782            }
783        }
784    } else {
785        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
786    }
787}
788
789RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
790{
791    const Element *src = static_cast<const Element *>(_src);
792    const Element *dst = static_cast<const Element *>(_dst);
793
794    //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
795    RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
796    uint32_t dimValues[] = {w, h, genMips};
797    RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
798
799    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
800    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
801    if (texAlloc == NULL) {
802        LOGE("Memory allocation failure");
803        return NULL;
804    }
805
806    ElementConverter_t cvt = pickConverter(dst, src);
807    if (cvt) {
808        cvt(texAlloc->getPtr(), data, w * h);
809        if (genMips) {
810            Adapter2D adapt(rsc, texAlloc);
811            Adapter2D adapt2(rsc, texAlloc);
812            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
813                adapt.setLOD(lod);
814                adapt2.setLOD(lod + 1);
815                mip(adapt2, adapt);
816            }
817        }
818    } else {
819        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
820    }
821
822    return texAlloc;
823}
824
825void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
826{
827    Allocation *a = static_cast<Allocation *>(va);
828    a->data(rsc, data, sizeBytes);
829}
830
831void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
832{
833    Allocation *a = static_cast<Allocation *>(va);
834    a->subData(rsc, xoff, count, data, sizeBytes);
835}
836
837void rsi_Allocation2DSubElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, const void *data, uint32_t eoff, uint32_t sizeBytes)
838{
839    Allocation *a = static_cast<Allocation *>(va);
840    a->subElementData(rsc, x, y, data, eoff, sizeBytes);
841}
842
843void rsi_Allocation1DSubElementData(Context *rsc, RsAllocation va, uint32_t x, const void *data, uint32_t eoff, uint32_t sizeBytes)
844{
845    Allocation *a = static_cast<Allocation *>(va);
846    a->subElementData(rsc, x, data, eoff, sizeBytes);
847}
848
849void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
850{
851    Allocation *a = static_cast<Allocation *>(va);
852    a->subData(rsc, xoff, yoff, w, h, data, sizeBytes);
853}
854
855void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data)
856{
857    Allocation *a = static_cast<Allocation *>(va);
858    a->read(data);
859}
860
861void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX)
862{
863    Allocation *a = static_cast<Allocation *>(va);
864    a->resize1D(rsc, dimX);
865}
866
867void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY)
868{
869    Allocation *a = static_cast<Allocation *>(va);
870    a->resize2D(rsc, dimX, dimY);
871}
872
873const void* rsi_AllocationGetType(Context *rsc, RsAllocation va)
874{
875    Allocation *a = static_cast<Allocation *>(va);
876    a->getType()->incUserRef();
877
878    return a->getType();
879}
880
881#endif //ANDROID_RS_BUILD_FOR_HOST
882
883}
884}
885