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