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