Allocation.cpp revision baca6c3c3d79a324c7976ba873afdded0b6bcfb5
1/*
2 * Copyright (C) 2012 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 "RenderScript.h"
18
19using namespace android;
20using namespace renderscriptCpp;
21
22void * Allocation::getIDSafe() const {
23    return getID();
24}
25
26void Allocation::updateCacheInfo(sp<const Type> t) {
27    mCurrentDimX = t->getX();
28    mCurrentDimY = t->getY();
29    mCurrentDimZ = t->getZ();
30    mCurrentCount = mCurrentDimX;
31    if (mCurrentDimY > 1) {
32        mCurrentCount *= mCurrentDimY;
33    }
34    if (mCurrentDimZ > 1) {
35        mCurrentCount *= mCurrentDimZ;
36    }
37}
38
39Allocation::Allocation(void *id, sp<RS> rs, sp<const Type> t, uint32_t usage) :
40    BaseObj(id, rs), mSelectedY(0), mSelectedZ(0), mSelectedLOD(0),
41    mSelectedFace(RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X) {
42
43    if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT |
44                   RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
45                   RS_ALLOCATION_USAGE_GRAPHICS_VERTEX |
46                   RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS |
47                   RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET |
48                   RS_ALLOCATION_USAGE_IO_INPUT |
49                   RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) {
50        ALOGE("Unknown usage specified.");
51    }
52
53    if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) {
54        mWriteAllowed = false;
55        if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT |
56                       RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
57                       RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
58            ALOGE("Invalid usage combination.");
59        }
60    }
61
62    mType = t;
63    mUsage = usage;
64
65    if (t.get() != NULL) {
66        updateCacheInfo(t);
67    }
68}
69
70void Allocation::validateIsInt32() {
71    RsDataType dt = mType->getElement()->getDataType();
72    if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
73        return;
74    }
75    ALOGE("32 bit integer source does not match allocation type %i", dt);
76}
77
78void Allocation::validateIsInt16() {
79    RsDataType dt = mType->getElement()->getDataType();
80    if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
81        return;
82    }
83    ALOGE("16 bit integer source does not match allocation type %i", dt);
84}
85
86void Allocation::validateIsInt8() {
87    RsDataType dt = mType->getElement()->getDataType();
88    if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
89        return;
90    }
91    ALOGE("8 bit integer source does not match allocation type %i", dt);
92}
93
94void Allocation::validateIsFloat32() {
95    RsDataType dt = mType->getElement()->getDataType();
96    if (dt == RS_TYPE_FLOAT_32) {
97        return;
98    }
99    ALOGE("32 bit float source does not match allocation type %i", dt);
100}
101
102void Allocation::validateIsObject() {
103    RsDataType dt = mType->getElement()->getDataType();
104    if ((dt == RS_TYPE_ELEMENT) ||
105        (dt == RS_TYPE_TYPE) ||
106        (dt == RS_TYPE_ALLOCATION) ||
107        (dt == RS_TYPE_SAMPLER) ||
108        (dt == RS_TYPE_SCRIPT) ||
109        (dt == RS_TYPE_MESH) ||
110        (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
111        (dt == RS_TYPE_PROGRAM_VERTEX) ||
112        (dt == RS_TYPE_PROGRAM_RASTER) ||
113        (dt == RS_TYPE_PROGRAM_STORE)) {
114        return;
115    }
116    ALOGE("Object source does not match allocation type %i", dt);
117}
118
119void Allocation::updateFromNative() {
120    BaseObj::updateFromNative();
121
122    const void *typeID = rsaAllocationGetType(mRS->getContext(), getID());
123    if(typeID != NULL) {
124        sp<const Type> old = mType;
125        sp<Type> t = new Type((void *)typeID, mRS);
126        t->updateFromNative();
127        updateCacheInfo(t);
128        mType = t;
129    }
130}
131
132void Allocation::syncAll(RsAllocationUsageType srcLocation) {
133    switch (srcLocation) {
134    case RS_ALLOCATION_USAGE_SCRIPT:
135    case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
136    case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
137    case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
138        break;
139    default:
140        ALOGE("Source must be exactly one usage type.");
141    }
142    rsAllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation);
143}
144
145void Allocation::ioSendOutput() {
146    if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
147        ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
148    }
149    rsAllocationIoSend(mRS->getContext(), getID());
150}
151
152void Allocation::ioGetInput() {
153    if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
154        ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
155    }
156    rsAllocationIoReceive(mRS->getContext(), getID());
157}
158
159void Allocation::generateMipmaps() {
160    rsAllocationGenerateMipmaps(mRS->getContext(), getID());
161}
162
163void Allocation::copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data,
164        size_t dataLen) {
165
166    if(count < 1) {
167        ALOGE("Count must be >= 1.");
168        return;
169    }
170    if((off + count) > mCurrentCount) {
171        ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
172        return;
173    }
174    if((count * mType->getElement()->getSizeBytes()) > dataLen) {
175        ALOGE("Array too small for allocation type.");
176        return;
177    }
178
179    rsAllocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data, dataLen);
180}
181
182void Allocation::copy1DRangeToUnchecked(uint32_t off, size_t count, void *data, size_t dataLen) {
183    if(count < 1) {
184        ALOGE("Count must be >= 1.");
185        return;
186    }
187    if((off + count) > mCurrentCount) {
188        ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
189        return;
190    }
191    if((count * mType->getElement()->getSizeBytes()) > dataLen) {
192        ALOGE("Array too small for allocation type.");
193        return;
194    }
195    rsAllocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data, dataLen);
196}
197
198void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int32_t *d, size_t dataLen) {
199    validateIsInt32();
200    copy1DRangeFromUnchecked(off, count, d, dataLen);
201}
202
203void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int16_t *d, size_t dataLen) {
204    validateIsInt16();
205    copy1DRangeFromUnchecked(off, count, d, dataLen);
206}
207
208void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int8_t *d, size_t dataLen) {
209    validateIsInt8();
210    copy1DRangeFromUnchecked(off, count, d, dataLen);
211}
212
213void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) {
214    validateIsFloat32();
215    copy1DRangeFromUnchecked(off, count, d, dataLen);
216}
217
218void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data,
219        uint32_t dataOff) {
220
221    rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0,
222                            mSelectedLOD, mSelectedFace,
223                            count, 1, data->getIDSafe(), dataOff, 0,
224                            data->mSelectedLOD, data->mSelectedFace);
225}
226
227void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
228    if (mAdaptedAllocation != NULL) {
229
230    } else {
231        if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
232            ALOGE("Updated region larger than allocation.");
233        }
234    }
235}
236
237void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
238                                 const int8_t *data, size_t dataLen) {
239    validate2DRange(xoff, yoff, w, h);
240    rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
241                       w, h, data, dataLen);
242}
243
244void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
245                                 const int16_t *data, size_t dataLen) {
246    validate2DRange(xoff, yoff, w, h);
247    rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
248                       w, h, data, dataLen);
249}
250
251void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
252                                 const int32_t *data, size_t dataLen) {
253    validate2DRange(xoff, yoff, w, h);
254    rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
255                       w, h, data, dataLen);
256}
257
258void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
259                                 const float *data, size_t dataLen) {
260    validate2DRange(xoff, yoff, w, h);
261    rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
262                       w, h, data, dataLen);
263}
264
265void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
266                                 const Allocation *data, size_t dataLen,
267                                 uint32_t dataXoff, uint32_t dataYoff) {
268    validate2DRange(xoff, yoff, w, h);
269    rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff,
270                            mSelectedLOD, mSelectedFace,
271                            w, h, data->getIDSafe(), dataXoff, dataYoff,
272                            data->mSelectedLOD, data->mSelectedFace);
273}
274
275/*
276void resize(int dimX) {
277    if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
278        throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
279    }
280    mRS.nAllocationResize1D(getID(), dimX);
281    mRS.finish();  // Necessary because resize is fifoed and update is async.
282
283    int typeID = mRS.nAllocationGetType(getID());
284    mType = new Type(typeID, mRS);
285    mType.updateFromNative();
286    updateCacheInfo(mType);
287}
288
289void resize(int dimX, int dimY) {
290    if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
291        throw new RSInvalidStateException(
292            "Resize only support for 2D allocations at this time.");
293    }
294    if (mType.getY() == 0) {
295        throw new RSInvalidStateException(
296            "Resize only support for 2D allocations at this time.");
297    }
298    mRS.nAllocationResize2D(getID(), dimX, dimY);
299    mRS.finish();  // Necessary because resize is fifoed and update is async.
300
301    int typeID = mRS.nAllocationGetType(getID());
302    mType = new Type(typeID, mRS);
303    mType.updateFromNative();
304    updateCacheInfo(mType);
305}
306*/
307
308
309android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
310                        RsAllocationMipmapControl mips, uint32_t usage) {
311    void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0);
312    if (id == 0) {
313        ALOGE("Allocation creation failed.");
314        return NULL;
315    }
316    return new Allocation(id, rs, type, usage);
317}
318
319android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
320                                    RsAllocationMipmapControl mips, uint32_t usage, void *pointer) {
321    void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, (uint32_t)pointer);
322    if (id == 0) {
323        ALOGE("Allocation creation failed.");
324    }
325    return new Allocation(id, rs, type, usage);
326}
327
328android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
329        uint32_t usage) {
330    return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
331}
332
333android::sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e,
334        size_t count, uint32_t usage) {
335
336    Type::Builder b(rs, e);
337    b.setX(count);
338    sp<const Type> t = b.create();
339
340    void *id = rsAllocationCreateTyped(rs->getContext(), t->getID(),
341        RS_ALLOCATION_MIPMAP_NONE, usage, 0);
342    if (id == 0) {
343        ALOGE("Allocation creation failed.");
344    }
345    return new Allocation(id, rs, t, usage);
346}
347