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