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