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