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