rsAllocation.cpp revision 442b7ff3ca1dffd1555d34e0afc1bdbb6387e8e2
1/*
2 * Copyright (C) 2013 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
17#include "rsContext.h"
18#include "rsAllocation.h"
19#include "rsAdapter.h"
20#include "rs_hal.h"
21
22#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
23#include "system/window.h"
24#include "gui/GLConsumer.h"
25#endif
26
27using namespace android;
28using namespace android::renderscript;
29
30Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages,
31                       RsAllocationMipmapControl mc, void * ptr)
32    : ObjectBase(rsc) {
33
34    memset(&mHal, 0, sizeof(mHal));
35    mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
36    mHal.state.usageFlags = usages;
37    mHal.state.mipmapControl = mc;
38    mHal.state.userProvidedPtr = ptr;
39
40    setType(type);
41    updateCache();
42}
43
44Allocation::Allocation(Context *rsc, const Allocation *alloc, const Type *type)
45    : ObjectBase(rsc) {
46
47    memset(&mHal, 0, sizeof(mHal));
48
49
50    mHal.state.baseAlloc = alloc;
51    mHal.state.type = type;
52    mHal.state.usageFlags = alloc->mHal.state.usageFlags;
53    mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE;
54
55    setType(type);
56    updateCache();
57
58
59
60
61    struct Hal {
62        void * drv;
63
64        struct DrvState {
65            struct LodState {
66                void * mallocPtr;
67                size_t stride;
68                uint32_t dimX;
69                uint32_t dimY;
70                uint32_t dimZ;
71            } lod[android::renderscript::Allocation::MAX_LOD];
72            size_t faceOffset;
73            uint32_t lodCount;
74            uint32_t faceCount;
75
76            struct YuvState {
77                uint32_t shift;
78                uint32_t step;
79            } yuv;
80
81            int grallocFlags;
82            uint32_t dimArray[Type::mMaxArrays];
83        };
84        mutable DrvState drvState;
85
86    };
87    Hal mHal;
88
89}
90
91void Allocation::operator delete(void* ptr) {
92    if (ptr) {
93        Allocation *a = (Allocation*) ptr;
94        a->getContext()->mHal.funcs.freeRuntimeMem(ptr);
95    }
96}
97
98Allocation * Allocation::createAllocation(Context *rsc, const Type *type, uint32_t usages,
99                              RsAllocationMipmapControl mc, void * ptr) {
100    // Allocation objects must use allocator specified by the driver
101    void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Allocation), 0);
102
103    if (!allocMem) {
104        rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Allocation");
105        return nullptr;
106    }
107
108    Allocation *a = new (allocMem) Allocation(rsc, type, usages, mc, ptr);
109
110    if (!rsc->mHal.funcs.allocation.init(rsc, a, type->getElement()->getHasReferences())) {
111        rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
112        delete a;
113        return nullptr;
114    }
115
116    return a;
117}
118
119Allocation * Allocation::createAdapter(Context *rsc, const Allocation *alloc, const Type *type) {
120    // Allocation objects must use allocator specified by the driver
121    void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Allocation), 0);
122
123    if (!allocMem) {
124        rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Allocation");
125        return nullptr;
126    }
127
128    Allocation *a = new (allocMem) Allocation(rsc, alloc, type);
129
130    if (!rsc->mHal.funcs.allocation.initAdapter(rsc, a)) {
131        rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure");
132        delete a;
133        return nullptr;
134    }
135
136    return a;
137}
138
139void Allocation::adapterOffset(Context *rsc, const uint32_t *offsets, size_t len) {
140    if (len >= sizeof(uint32_t) * 9) {
141        mHal.state.originX = offsets[0];
142        mHal.state.originY = offsets[1];
143        mHal.state.originZ = offsets[2];
144        mHal.state.originLOD = offsets[3];
145        mHal.state.originFace = offsets[4];
146        mHal.state.originArray[0] = offsets[5];
147        mHal.state.originArray[1] = offsets[6];
148        mHal.state.originArray[2] = offsets[7];
149        mHal.state.originArray[3] = offsets[8];
150    }
151
152    rsc->mHal.funcs.allocation.adapterOffset(rsc, this);
153}
154
155
156
157void Allocation::updateCache() {
158    const Type *type = mHal.state.type;
159    mHal.state.yuv = type->getDimYuv();
160    mHal.state.hasFaces = type->getDimFaces();
161    mHal.state.hasMipmaps = type->getDimLOD();
162    mHal.state.elementSizeBytes = type->getElementSizeBytes();
163    mHal.state.hasReferences = mHal.state.type->getElement()->getHasReferences();
164}
165
166Allocation::~Allocation() {
167#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
168    if (mGrallocConsumer.get()) {
169        mGrallocConsumer->unlockBuffer();
170        mGrallocConsumer = nullptr;
171    }
172#endif
173
174    freeChildrenUnlocked();
175    mRSC->mHal.funcs.allocation.destroy(mRSC, this);
176}
177
178void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) {
179    rsc->mHal.funcs.allocation.syncAll(rsc, this, src);
180}
181
182void * Allocation::getPointer(const Context *rsc, uint32_t lod, RsAllocationCubemapFace face,
183                          uint32_t z, uint32_t array, size_t *stride) {
184
185    if ((lod >= mHal.drvState.lodCount) ||
186        (z && (z >= mHal.drvState.lod[lod].dimZ)) ||
187        ((face != RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X) && !mHal.state.hasFaces) ||
188        (array != 0)) {
189        return nullptr;
190    }
191
192    size_t s = 0;
193    //void *ptr = mRSC->mHal.funcs.allocation.lock1D(rsc, this);
194    if ((stride != nullptr) && mHal.drvState.lod[0].dimY) {
195        *stride = mHal.drvState.lod[lod].stride;
196    }
197    return mHal.drvState.lod[lod].mallocPtr;
198}
199
200void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
201                         uint32_t count, const void *data, size_t sizeBytes) {
202    const size_t eSize = mHal.state.type->getElementSizeBytes();
203
204    if ((count * eSize) != sizeBytes) {
205        char buf[1024];
206        sprintf(buf, "Allocation::subData called with mismatched size expected %zu, got %zu",
207                (count * eSize), sizeBytes);
208        rsc->setError(RS_ERROR_BAD_VALUE, buf);
209        mHal.state.type->dumpLOGV("type info");
210        return;
211    }
212
213    rsc->mHal.funcs.allocation.data1D(rsc, this, xoff, lod, count, data, sizeBytes);
214    sendDirty(rsc);
215}
216
217void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
218                      uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
219    rsc->mHal.funcs.allocation.data2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
220    sendDirty(rsc);
221}
222
223void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
224                      uint32_t lod,
225                      uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes, size_t stride) {
226    rsc->mHal.funcs.allocation.data3D(rsc, this, xoff, yoff, zoff, lod, w, h, d, data, sizeBytes, stride);
227    sendDirty(rsc);
228}
229
230void Allocation::read(Context *rsc, uint32_t xoff, uint32_t lod,
231                      uint32_t count, void *data, size_t sizeBytes) {
232    const size_t eSize = mHal.state.type->getElementSizeBytes();
233
234    if ((count * eSize) != sizeBytes) {
235        char buf[1024];
236        sprintf(buf, "Allocation::read called with mismatched size expected %zu, got %zu",
237                (count * eSize), sizeBytes);
238        rsc->setError(RS_ERROR_BAD_VALUE, buf);
239        mHal.state.type->dumpLOGV("type info");
240        return;
241    }
242
243    rsc->mHal.funcs.allocation.read1D(rsc, this, xoff, lod, count, data, sizeBytes);
244}
245
246void Allocation::read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
247                      uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) {
248    const size_t eSize = mHal.state.elementSizeBytes;
249    const size_t lineSize = eSize * w;
250    if (!stride) {
251        stride = lineSize;
252    } else {
253        if ((lineSize * h) != sizeBytes) {
254            char buf[1024];
255            sprintf(buf, "Allocation size mismatch, expected %zu, got %zu", (lineSize * h), sizeBytes);
256            rsc->setError(RS_ERROR_BAD_VALUE, buf);
257            return;
258        }
259    }
260
261    rsc->mHal.funcs.allocation.read2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
262}
263
264void Allocation::read(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod,
265                      uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) {
266    const size_t eSize = mHal.state.elementSizeBytes;
267    const size_t lineSize = eSize * w;
268    if (!stride) {
269        stride = lineSize;
270    }
271
272    rsc->mHal.funcs.allocation.read3D(rsc, this, xoff, yoff, zoff, lod, w, h, d, data, sizeBytes, stride);
273
274}
275
276void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
277                                uint32_t cIdx, size_t sizeBytes) {
278    size_t eSize = mHal.state.elementSizeBytes;
279
280    if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
281        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range.");
282        return;
283    }
284
285    if (x >= mHal.drvState.lod[0].dimX) {
286        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
287        return;
288    }
289
290    const Element * e = mHal.state.type->getElement()->getField(cIdx);
291    uint32_t elemArraySize = mHal.state.type->getElement()->getFieldArraySize(cIdx);
292    if (sizeBytes != e->getSizeBytes() * elemArraySize) {
293        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
294        return;
295    }
296
297    rsc->mHal.funcs.allocation.elementData1D(rsc, this, x, data, cIdx, sizeBytes);
298    sendDirty(rsc);
299}
300
301void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
302                                const void *data, uint32_t cIdx, size_t sizeBytes) {
303    size_t eSize = mHal.state.elementSizeBytes;
304
305    if (x >= mHal.drvState.lod[0].dimX) {
306        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range.");
307        return;
308    }
309
310    if (y >= mHal.drvState.lod[0].dimY) {
311        rsc->setError(RS_ERROR_BAD_VALUE,
312                      "subElementData X offset out of range.");
313        return;
314    }
315
316    if (cIdx >= mHal.state.type->getElement()->getFieldCount()) {
317        rsc->setError(RS_ERROR_BAD_VALUE,
318                      "subElementData component out of range.");
319        return;
320    }
321
322    const Element * e = mHal.state.type->getElement()->getField(cIdx);
323    uint32_t elemArraySize =
324        mHal.state.type->getElement()->getFieldArraySize(cIdx);
325    if (sizeBytes != e->getSizeBytes() * elemArraySize) {
326        rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size.");
327        return;
328    }
329
330    rsc->mHal.funcs.allocation.elementData2D(rsc, this, x, y, data, cIdx,
331                                             sizeBytes);
332    sendDirty(rsc);
333}
334
335void Allocation::addProgramToDirty(const Program *p) {
336    mToDirtyList.push_back(p);
337}
338
339void Allocation::removeProgramToDirty(const Program *p) {
340    for (auto entryIter = mToDirtyList.begin(), endIter = mToDirtyList.end();
341         entryIter != endIter; entryIter++) {
342
343        if (p == *entryIter) {
344            mToDirtyList.erase(entryIter);
345            return;
346        }
347    }
348    rsAssert(0);
349}
350
351void Allocation::dumpLOGV(const char *prefix) const {
352    ObjectBase::dumpLOGV(prefix);
353    char buf[1024];
354
355    if ((strlen(prefix) + 10) < sizeof(buf)) {
356        sprintf(buf, "%s type ", prefix);
357        if (mHal.state.type) {
358            mHal.state.type->dumpLOGV(buf);
359        }
360    }
361    ALOGV("%s allocation ptr=%p  mUsageFlags=0x04%x, mMipmapControl=0x%04x",
362          prefix, mHal.drvState.lod[0].mallocPtr, mHal.state.usageFlags,
363          mHal.state.mipmapControl);
364}
365
366uint32_t Allocation::getPackedSize() const {
367    uint32_t numItems = mHal.state.type->getCellCount();
368    return numItems * mHal.state.type->getElement()->getSizeBytesUnpadded();
369}
370
371void Allocation::writePackedData(Context *rsc, const Type *type,
372                                 uint8_t *dst, const uint8_t *src, bool dstPadded) {
373    const Element *elem = type->getElement();
374    uint32_t unpaddedBytes = elem->getSizeBytesUnpadded();
375    uint32_t paddedBytes = elem->getSizeBytes();
376    uint32_t numItems = type->getPackedSizeBytes() / paddedBytes;
377
378    uint32_t srcInc = !dstPadded ? paddedBytes : unpaddedBytes;
379    uint32_t dstInc =  dstPadded ? paddedBytes : unpaddedBytes;
380
381    // no sub-elements
382    uint32_t fieldCount = elem->getFieldCount();
383    if (fieldCount == 0) {
384        for (uint32_t i = 0; i < numItems; i ++) {
385            memcpy(dst, src, unpaddedBytes);
386            src += srcInc;
387            dst += dstInc;
388        }
389        return;
390    }
391
392    // Cache offsets
393    uint32_t *offsetsPadded = new uint32_t[fieldCount];
394    uint32_t *offsetsUnpadded = new uint32_t[fieldCount];
395    uint32_t *sizeUnpadded = new uint32_t[fieldCount];
396
397    for (uint32_t i = 0; i < fieldCount; i++) {
398        offsetsPadded[i] = elem->getFieldOffsetBytes(i);
399        offsetsUnpadded[i] = elem->getFieldOffsetBytesUnpadded(i);
400        sizeUnpadded[i] = elem->getField(i)->getSizeBytesUnpadded();
401    }
402
403    uint32_t *srcOffsets = !dstPadded ? offsetsPadded : offsetsUnpadded;
404    uint32_t *dstOffsets =  dstPadded ? offsetsPadded : offsetsUnpadded;
405
406    // complex elements, need to copy subelem after subelem
407    for (uint32_t i = 0; i < numItems; i ++) {
408        for (uint32_t fI = 0; fI < fieldCount; fI++) {
409            memcpy(dst + dstOffsets[fI], src + srcOffsets[fI], sizeUnpadded[fI]);
410        }
411        src += srcInc;
412        dst += dstInc;
413    }
414
415    delete[] offsetsPadded;
416    delete[] offsetsUnpadded;
417    delete[] sizeUnpadded;
418}
419
420void Allocation::unpackVec3Allocation(Context *rsc, const void *data, size_t dataSize) {
421    const uint8_t *src = (const uint8_t*)data;
422    uint8_t *dst = (uint8_t *)rsc->mHal.funcs.allocation.lock1D(rsc, this);
423
424    writePackedData(rsc, getType(), dst, src, true);
425    rsc->mHal.funcs.allocation.unlock1D(rsc, this);
426}
427
428void Allocation::packVec3Allocation(Context *rsc, OStream *stream) const {
429    uint32_t paddedBytes = getType()->getElement()->getSizeBytes();
430    uint32_t unpaddedBytes = getType()->getElement()->getSizeBytesUnpadded();
431    uint32_t numItems = mHal.state.type->getCellCount();
432
433    const uint8_t *src = (const uint8_t*)rsc->mHal.funcs.allocation.lock1D(rsc, this);
434    uint8_t *dst = new uint8_t[numItems * unpaddedBytes];
435
436    writePackedData(rsc, getType(), dst, src, false);
437    stream->addByteArray(dst, getPackedSize());
438
439    delete[] dst;
440    rsc->mHal.funcs.allocation.unlock1D(rsc, this);
441}
442
443void Allocation::serialize(Context *rsc, OStream *stream) const {
444    // Need to identify ourselves
445    stream->addU32((uint32_t)getClassId());
446    stream->addString(getName());
447
448    // First thing we need to serialize is the type object since it will be needed
449    // to initialize the class
450    mHal.state.type->serialize(rsc, stream);
451
452    uint32_t dataSize = mHal.state.type->getPackedSizeBytes();
453    // 3 element vectors are padded to 4 in memory, but padding isn't serialized
454    uint32_t packedSize = getPackedSize();
455    // Write how much data we are storing
456    stream->addU32(packedSize);
457    if (dataSize == packedSize) {
458        // Now write the data
459        stream->addByteArray(rsc->mHal.funcs.allocation.lock1D(rsc, this), dataSize);
460        rsc->mHal.funcs.allocation.unlock1D(rsc, this);
461    } else {
462        // Now write the data
463        packVec3Allocation(rsc, stream);
464    }
465}
466
467Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) {
468    // First make sure we are reading the correct object
469    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
470    if (classID != RS_A3D_CLASS_ID_ALLOCATION) {
471        rsc->setError(RS_ERROR_FATAL_DRIVER,
472                      "allocation loading failed due to corrupt file. (invalid id)\n");
473        return nullptr;
474    }
475
476    const char *name = stream->loadString();
477
478    Type *type = Type::createFromStream(rsc, stream);
479    if (!type) {
480        return nullptr;
481    }
482    type->compute();
483
484    Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
485    type->decUserRef();
486
487    // Number of bytes we wrote out for this allocation
488    uint32_t dataSize = stream->loadU32();
489    // 3 element vectors are padded to 4 in memory, but padding isn't serialized
490    uint32_t packedSize = alloc->getPackedSize();
491    if (dataSize != type->getPackedSizeBytes() &&
492        dataSize != packedSize) {
493        rsc->setError(RS_ERROR_FATAL_DRIVER,
494                      "allocation loading failed due to corrupt file. (invalid size)\n");
495        ObjectBase::checkDelete(alloc);
496        ObjectBase::checkDelete(type);
497        return nullptr;
498    }
499
500    alloc->assignName(name);
501    if (dataSize == type->getPackedSizeBytes()) {
502        uint32_t count = dataSize / type->getElementSizeBytes();
503        // Read in all of our allocation data
504        alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
505    } else {
506        alloc->unpackVec3Allocation(rsc, stream->getPtr() + stream->getPos(), dataSize);
507    }
508    stream->reset(stream->getPos() + dataSize);
509
510    return alloc;
511}
512
513void Allocation::sendDirty(const Context *rsc) const {
514#ifndef RS_COMPATIBILITY_LIB
515    for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
516        mToDirtyList[ct]->forceDirty();
517    }
518#endif
519    mRSC->mHal.funcs.allocation.markDirty(rsc, this);
520}
521
522void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const {
523    mHal.state.type->incRefs(ptr, ct, startOff);
524}
525
526void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const {
527    if (!mHal.state.hasReferences || !getIsScript()) {
528        return;
529    }
530    mHal.state.type->decRefs(ptr, ct, startOff);
531}
532
533void Allocation::callUpdateCacheObject(const Context *rsc, void *dstObj) const {
534    if (rsc->mHal.funcs.allocation.updateCachedObject != nullptr) {
535        rsc->mHal.funcs.allocation.updateCachedObject(rsc, this, (rs_allocation *)dstObj);
536    } else {
537        *((const void **)dstObj) = this;
538    }
539}
540
541
542void Allocation::freeChildrenUnlocked () {
543    void *ptr = mRSC->mHal.funcs.allocation.lock1D(mRSC, this);
544    decRefs(ptr, mHal.state.type->getCellCount(), 0);
545    mRSC->mHal.funcs.allocation.unlock1D(mRSC, this);
546}
547
548bool Allocation::freeChildren() {
549    if (mHal.state.hasReferences) {
550        incSysRef();
551        freeChildrenUnlocked();
552        return decSysRef();
553    }
554    return false;
555}
556
557void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) {
558}
559
560void Allocation::resize1D(Context *rsc, uint32_t dimX) {
561    uint32_t oldDimX = mHal.drvState.lod[0].dimX;
562    if (dimX == oldDimX) {
563        return;
564    }
565
566    ObjectBaseRef<Type> t = mHal.state.type->cloneAndResize1D(rsc, dimX);
567    if (dimX < oldDimX) {
568        decRefs(rsc->mHal.funcs.allocation.lock1D(rsc, this), oldDimX - dimX, dimX);
569        rsc->mHal.funcs.allocation.unlock1D(rsc, this);
570    }
571    rsc->mHal.funcs.allocation.resize(rsc, this, t.get(), mHal.state.hasReferences);
572    setType(t.get());
573    updateCache();
574}
575
576void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) {
577    rsc->setError(RS_ERROR_FATAL_DRIVER, "resize2d not implemented");
578}
579
580#ifndef RS_COMPATIBILITY_LIB
581void Allocation::NewBufferListener::onFrameAvailable() {
582    intptr_t ip = (intptr_t)alloc;
583    rsc->sendMessageToClient(&ip, RS_MESSAGE_TO_CLIENT_NEW_BUFFER, 0, sizeof(ip), true);
584}
585#endif
586
587void * Allocation::getSurface(const Context *rsc) {
588#ifndef RS_COMPATIBILITY_LIB
589    // Configure GrallocConsumer to be in asynchronous mode
590    sp<IGraphicBufferProducer> bp;
591    sp<IGraphicBufferConsumer> bc;
592    BufferQueue::createBufferQueue(&bp, &bc);
593    mGrallocConsumer = new GrallocConsumer(this, bc, mHal.drvState.grallocFlags);
594    bp->incStrong(nullptr);
595
596    mBufferListener = new NewBufferListener();
597    mBufferListener->rsc = rsc;
598    mBufferListener->alloc = this;
599
600    mGrallocConsumer->setFrameAvailableListener(mBufferListener);
601    return bp.get();
602#else
603    return nullptr;
604#endif
605    //return rsc->mHal.funcs.allocation.getSurface(rsc, this);
606}
607
608void Allocation::setSurface(const Context *rsc, RsNativeWindow sur) {
609    ANativeWindow *nw = (ANativeWindow *)sur;
610    rsc->mHal.funcs.allocation.setSurface(rsc, this, nw);
611}
612
613void Allocation::ioSend(const Context *rsc) {
614    rsc->mHal.funcs.allocation.ioSend(rsc, this);
615}
616
617void Allocation::ioReceive(const Context *rsc) {
618    void *ptr = nullptr;
619    size_t stride = 0;
620#ifndef RS_COMPATIBILITY_LIB
621    if (mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
622        status_t ret = mGrallocConsumer->lockNextBuffer();
623
624        if (ret == OK) {
625            rsc->mHal.funcs.allocation.ioReceive(rsc, this);
626        } else if (ret == BAD_VALUE) {
627            // No new frame, don't do anything
628        } else {
629            rsc->setError(RS_ERROR_DRIVER, "Error receiving IO input buffer.");
630        }
631
632    }
633#endif
634}
635
636bool Allocation::hasSameDims(const Allocation *other) const {
637    const Type *type0 = this->getType(),
638               *type1 = other->getType();
639
640    return (type0->getCellCount() == type1->getCellCount()) &&
641           (type0->getDimLOD()    == type1->getDimLOD())    &&
642           (type0->getDimFaces()  == type1->getDimFaces())  &&
643           (type0->getDimYuv()    == type1->getDimYuv())    &&
644           (type0->getDimX()      == type1->getDimX())      &&
645           (type0->getDimY()      == type1->getDimY())      &&
646           (type0->getDimZ()      == type1->getDimZ());
647}
648
649
650/////////////////
651//
652
653namespace android {
654namespace renderscript {
655
656void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType src) {
657    Allocation *a = static_cast<Allocation *>(va);
658    a->sendDirty(rsc);
659    a->syncAll(rsc, src);
660}
661
662void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
663    Allocation *alloc = static_cast<Allocation *>(va);
664    rsc->mHal.funcs.allocation.generateMipmaps(rsc, alloc);
665}
666
667void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t sizeBytes) {
668    Allocation *a = static_cast<Allocation *>(va);
669    const Type * t = a->getType();
670    a->read(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
671            t->getDimX(), t->getDimY(), data, sizeBytes, 0);
672}
673
674void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
675                          uint32_t count, const void *data, size_t sizeBytes) {
676    Allocation *a = static_cast<Allocation *>(va);
677    a->data(rsc, xoff, lod, count, data, sizeBytes);
678}
679
680void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face,
681                                 const void *data, size_t sizeBytes, size_t eoff) {
682    Allocation *a = static_cast<Allocation *>(va);
683    a->elementData(rsc, x, y, data, eoff, sizeBytes);
684}
685
686void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod,
687                                 const void *data, size_t sizeBytes, size_t eoff) {
688    Allocation *a = static_cast<Allocation *>(va);
689    a->elementData(rsc, x, data, eoff, sizeBytes);
690}
691
692void rsi_Allocation2DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
693                          uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
694    Allocation *a = static_cast<Allocation *>(va);
695    a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
696}
697
698void rsi_Allocation3DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod,
699                          uint32_t w, uint32_t h, uint32_t d, const void *data, size_t sizeBytes, size_t stride) {
700    Allocation *a = static_cast<Allocation *>(va);
701    a->data(rsc, xoff, yoff, zoff, lod, w, h, d, data, sizeBytes, stride);
702}
703
704
705void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data, size_t sizeBytes) {
706    Allocation *a = static_cast<Allocation *>(va);
707    const Type * t = a->getType();
708    if(t->getDimY()) {
709        a->read(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
710                t->getDimX(), t->getDimY(), data, sizeBytes, 0);
711    } else {
712        a->read(rsc, 0, 0, t->getDimX(), data, sizeBytes);
713    }
714
715}
716
717void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) {
718    Allocation *a = static_cast<Allocation *>(va);
719    a->resize1D(rsc, dimX);
720}
721
722void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY) {
723    Allocation *a = static_cast<Allocation *>(va);
724    a->resize2D(rsc, dimX, dimY);
725}
726
727RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype,
728                                       RsAllocationMipmapControl mipmaps,
729                                       uint32_t usages, uintptr_t ptr) {
730    Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mipmaps, (void*)ptr);
731    if (!alloc) {
732        return nullptr;
733    }
734    alloc->incUserRef();
735    return alloc;
736}
737
738RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, RsType vtype,
739                                            RsAllocationMipmapControl mipmaps,
740                                            const void *data, size_t sizeBytes, uint32_t usages) {
741    Type *t = static_cast<Type *>(vtype);
742
743    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mipmaps, usages, 0);
744    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
745    if (texAlloc == nullptr) {
746        ALOGE("Memory allocation failure");
747        return nullptr;
748    }
749
750    texAlloc->data(rsc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
751                   t->getDimX(), t->getDimY(), data, sizeBytes, 0);
752    if (mipmaps == RS_ALLOCATION_MIPMAP_FULL) {
753        rsc->mHal.funcs.allocation.generateMipmaps(rsc, texAlloc);
754    }
755
756    texAlloc->sendDirty(rsc);
757    return texAlloc;
758}
759
760RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype,
761                                                RsAllocationMipmapControl mipmaps,
762                                                const void *data, size_t sizeBytes, uint32_t usages) {
763    Type *t = static_cast<Type *>(vtype);
764
765    // Cubemap allocation's faces should be Width by Width each.
766    // Source data should have 6 * Width by Width pixels
767    // Error checking is done in the java layer
768    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mipmaps, usages, 0);
769    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
770    if (texAlloc == nullptr) {
771        ALOGE("Memory allocation failure");
772        return nullptr;
773    }
774
775    uint32_t faceSize = t->getDimX();
776    uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes();
777    uint32_t copySize = faceSize * t->getElementSizeBytes();
778
779    uint8_t *sourcePtr = (uint8_t*)data;
780    for (uint32_t face = 0; face < 6; face ++) {
781        for (uint32_t dI = 0; dI < faceSize; dI ++) {
782            texAlloc->data(rsc, 0, dI, 0, (RsAllocationCubemapFace)face,
783                           t->getDimX(), 1, sourcePtr + strideBytes * dI, copySize, 0);
784        }
785
786        // Move the data pointer to the next cube face
787        sourcePtr += copySize;
788    }
789
790    if (mipmaps == RS_ALLOCATION_MIPMAP_FULL) {
791        rsc->mHal.funcs.allocation.generateMipmaps(rsc, texAlloc);
792    }
793
794    texAlloc->sendDirty(rsc);
795    return texAlloc;
796}
797
798void rsi_AllocationCopy2DRange(Context *rsc,
799                               RsAllocation dstAlloc,
800                               uint32_t dstXoff, uint32_t dstYoff,
801                               uint32_t dstMip, uint32_t dstFace,
802                               uint32_t width, uint32_t height,
803                               RsAllocation srcAlloc,
804                               uint32_t srcXoff, uint32_t srcYoff,
805                               uint32_t srcMip, uint32_t srcFace) {
806    Allocation *dst = static_cast<Allocation *>(dstAlloc);
807    Allocation *src= static_cast<Allocation *>(srcAlloc);
808    rsc->mHal.funcs.allocation.allocData2D(rsc, dst, dstXoff, dstYoff, dstMip,
809                                           (RsAllocationCubemapFace)dstFace,
810                                           width, height,
811                                           src, srcXoff, srcYoff,srcMip,
812                                           (RsAllocationCubemapFace)srcFace);
813}
814
815void rsi_AllocationCopy3DRange(Context *rsc,
816                               RsAllocation dstAlloc,
817                               uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
818                               uint32_t dstMip,
819                               uint32_t width, uint32_t height, uint32_t depth,
820                               RsAllocation srcAlloc,
821                               uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
822                               uint32_t srcMip) {
823    Allocation *dst = static_cast<Allocation *>(dstAlloc);
824    Allocation *src= static_cast<Allocation *>(srcAlloc);
825    rsc->mHal.funcs.allocation.allocData3D(rsc, dst, dstXoff, dstYoff, dstZoff, dstMip,
826                                           width, height, depth,
827                                           src, srcXoff, srcYoff, srcZoff, srcMip);
828}
829
830
831void * rsi_AllocationGetSurface(Context *rsc, RsAllocation valloc) {
832    Allocation *alloc = static_cast<Allocation *>(valloc);
833    void *s = alloc->getSurface(rsc);
834    return s;
835}
836
837void rsi_AllocationSetSurface(Context *rsc, RsAllocation valloc, RsNativeWindow sur) {
838    Allocation *alloc = static_cast<Allocation *>(valloc);
839    alloc->setSurface(rsc, sur);
840}
841
842void rsi_AllocationIoSend(Context *rsc, RsAllocation valloc) {
843    Allocation *alloc = static_cast<Allocation *>(valloc);
844    alloc->ioSend(rsc);
845}
846
847void rsi_AllocationIoReceive(Context *rsc, RsAllocation valloc) {
848    Allocation *alloc = static_cast<Allocation *>(valloc);
849    alloc->ioReceive(rsc);
850}
851
852void *rsi_AllocationGetPointer(Context *rsc, RsAllocation valloc,
853                          uint32_t lod, RsAllocationCubemapFace face,
854                          uint32_t z, uint32_t array, size_t *stride, size_t strideLen) {
855    Allocation *alloc = static_cast<Allocation *>(valloc);
856    rsAssert(strideLen == sizeof(size_t));
857
858    return alloc->getPointer(rsc, lod, face, z, array, stride);
859}
860
861void rsi_Allocation1DRead(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
862                          uint32_t count, void *data, size_t sizeBytes) {
863    Allocation *a = static_cast<Allocation *>(va);
864    rsc->mHal.funcs.allocation.read1D(rsc, a, xoff, lod, count, data, sizeBytes);
865}
866
867void rsi_Allocation2DRead(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff,
868                          uint32_t lod, RsAllocationCubemapFace face, uint32_t w,
869                          uint32_t h, void *data, size_t sizeBytes, size_t stride) {
870    Allocation *a = static_cast<Allocation *>(va);
871    a->read(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes, stride);
872}
873
874RsAllocation rsi_AllocationAdapterCreate(Context *rsc, RsType vwindow, RsAllocation vbase) {
875
876
877    Allocation * alloc = Allocation::createAdapter(rsc,
878            static_cast<Allocation *>(vbase), static_cast<Type *>(vwindow));
879    if (!alloc) {
880        return nullptr;
881    }
882    alloc->incUserRef();
883    return alloc;
884}
885
886void rsi_AllocationAdapterOffset(Context *rsc, RsAllocation va, const uint32_t *offsets, size_t len) {
887    Allocation *a = static_cast<Allocation *>(va);
888    a->adapterOffset(rsc, offsets, len);
889}
890
891
892}
893}
894
895extern "C" const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
896    Allocation *a = static_cast<Allocation *>(va);
897    a->getType()->incUserRef();
898
899    return a->getType();
900}
901