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