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