Allocation.cpp revision 8f615d682f9e7e2cd4de2e4478e0e76fc359922c
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 "RenderScript.h"
18#include "rsCppInternal.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 != NULL) {
68        updateCacheInfo(t);
69    }
70
71}
72
73
74
75void Allocation::validateIsInt32() {
76    RsDataType dt = mType->getElement()->getDataType();
77    if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
78        return;
79    }
80    ALOGE("32 bit integer source does not match allocation type %i", dt);
81}
82
83void Allocation::validateIsInt16() {
84    RsDataType dt = mType->getElement()->getDataType();
85    if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
86        return;
87    }
88    ALOGE("16 bit integer source does not match allocation type %i", dt);
89}
90
91void Allocation::validateIsInt8() {
92    RsDataType dt = mType->getElement()->getDataType();
93    if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
94        return;
95    }
96    ALOGE("8 bit integer source does not match allocation type %i", dt);
97}
98
99void Allocation::validateIsFloat32() {
100    RsDataType dt = mType->getElement()->getDataType();
101    if (dt == RS_TYPE_FLOAT_32) {
102        return;
103    }
104    ALOGE("32 bit float source does not match allocation type %i", dt);
105}
106
107void Allocation::validateIsObject() {
108    RsDataType dt = mType->getElement()->getDataType();
109    if ((dt == RS_TYPE_ELEMENT) ||
110        (dt == RS_TYPE_TYPE) ||
111        (dt == RS_TYPE_ALLOCATION) ||
112        (dt == RS_TYPE_SAMPLER) ||
113        (dt == RS_TYPE_SCRIPT) ||
114        (dt == RS_TYPE_MESH) ||
115        (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
116        (dt == RS_TYPE_PROGRAM_VERTEX) ||
117        (dt == RS_TYPE_PROGRAM_RASTER) ||
118        (dt == RS_TYPE_PROGRAM_STORE)) {
119        return;
120    }
121    ALOGE("Object source does not match allocation type %i", dt);
122}
123
124void Allocation::updateFromNative() {
125    BaseObj::updateFromNative();
126
127    const void *typeID = RS::dispatch->AllocationGetType(mRS->getContext(), getID());
128    if(typeID != NULL) {
129        sp<const Type> old = mType;
130        sp<Type> t = new Type((void *)typeID, mRS);
131        t->updateFromNative();
132        updateCacheInfo(t);
133        mType = t;
134    }
135}
136
137void Allocation::syncAll(RsAllocationUsageType srcLocation) {
138    switch (srcLocation) {
139    case RS_ALLOCATION_USAGE_SCRIPT:
140    case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
141    case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
142    case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
143    case RS_ALLOCATION_USAGE_SHARED:
144        break;
145    default:
146        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Source must be exactly one usage type.");
147        return;
148    }
149    tryDispatch(mRS, RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation));
150}
151
152void Allocation::ioSendOutput() {
153#ifndef RS_COMPATIBILITY_LIB
154    if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
155        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified.");
156        return;
157    }
158    tryDispatch(mRS, RS::dispatch->AllocationIoSend(mRS->getContext(), getID()));
159#endif
160}
161
162void Allocation::ioGetInput() {
163#ifndef RS_COMPATIBILITY_LIB
164    if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
165        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified.");
166        return;
167    }
168    tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID()));
169#endif
170}
171
172void Allocation::generateMipmaps() {
173    tryDispatch(mRS, RS::dispatch->AllocationGenerateMipmaps(mRS->getContext(), getID()));
174}
175
176void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) {
177
178    if(count < 1) {
179        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
180        return;
181    }
182    if((off + count) > mCurrentCount) {
183        ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
184        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
185        return;
186    }
187
188    tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
189                                                    count, data, count * mType->getElement()->getSizeBytes()));
190}
191
192void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) {
193    if(count < 1) {
194        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
195        return;
196    }
197    if((off + count) > mCurrentCount) {
198        ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
199        mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
200        return;
201    }
202
203    tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
204                                                    count, data, count * mType->getElement()->getSizeBytes()));
205}
206
207void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data,
208                                 uint32_t dataOff) {
209
210    tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0,
211                                                         mSelectedLOD, mSelectedFace,
212                                                         count, 1, data->getIDSafe(), dataOff, 0,
213                                                         data->mSelectedLOD, data->mSelectedFace));
214}
215
216void Allocation::copy1DFrom(const void* data) {
217    copy1DRangeFrom(0, mCurrentCount, data);
218}
219
220void Allocation::copy1DTo(void* data) {
221    copy1DRangeTo(0, mCurrentCount, data);
222}
223
224
225void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
226    if (mAdaptedAllocation != NULL) {
227
228    } else {
229        if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
230            mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
231        }
232    }
233}
234
235void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
236                                 const void *data) {
237    validate2DRange(xoff, yoff, w, h);
238    tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff,
239                                                    yoff, mSelectedLOD, mSelectedFace,
240                                                    w, h, data, w * h * mType->getElement()->getSizeBytes(),
241                                                    w * mType->getElement()->getSizeBytes()));
242}
243
244void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
245                                 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) {
246    validate2DRange(xoff, yoff, w, h);
247    tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff,
248                                                         mSelectedLOD, mSelectedFace,
249                                                         w, h, data->getIDSafe(), dataXoff, dataYoff,
250                                                         data->mSelectedLOD, data->mSelectedFace));
251}
252
253void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
254                               void* data) {
255    validate2DRange(xoff, yoff, w, h);
256    tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
257                                                    mSelectedLOD, mSelectedFace, w, h, data,
258                                                    w * h * mType->getElement()->getSizeBytes(),
259                                                    w * mType->getElement()->getSizeBytes()));
260}
261
262void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
263                                   const void *data, size_t stride) {
264    validate2DRange(xoff, yoff, w, h);
265    tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff,
266                                                    mSelectedLOD, mSelectedFace, w, h, data,
267                                                    w * h * mType->getElement()->getSizeBytes(), stride));
268}
269
270void Allocation::copy2DStridedFrom(const void* data, size_t stride) {
271    copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
272}
273
274void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
275                                 void *data, size_t stride) {
276    validate2DRange(xoff, yoff, w, h);
277    tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
278                                                    mSelectedLOD, mSelectedFace, w, h, data,
279                                                    w * h * mType->getElement()->getSizeBytes(), stride));
280}
281
282void Allocation::copy2DStridedTo(void* data, size_t stride) {
283    copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
284}
285
286void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
287                                 uint32_t h, uint32_t d) {
288    if (mAdaptedAllocation != NULL) {
289
290    } else {
291        if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
292            mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
293        }
294    }
295}
296
297void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
298                                 uint32_t h, uint32_t d, const void* data) {
299    validate3DRange(xoff, yoff, zoff, w, h, d);
300    tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
301                                                    mSelectedLOD, w, h, d, data,
302                                                    w * h * d * mType->getElement()->getSizeBytes(),
303                                                    w * mType->getElement()->getSizeBytes()));
304}
305
306void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d,
307                                 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) {
308    validate3DRange(xoff, yoff, zoff, dataXoff, dataYoff, dataZoff);
309    tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
310                                                         mSelectedLOD, w, h, d, data->getIDSafe(),
311                                                         dataXoff, dataYoff, dataZoff, data->mSelectedLOD));
312}
313
314
315sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
316                                    RsAllocationMipmapControl mipmaps, uint32_t usage) {
317    void *id = 0;
318    if (rs->getError() == RS_SUCCESS) {
319        id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 0);
320    }
321    if (id == 0) {
322        rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
323        return NULL;
324    }
325    return new Allocation(id, rs, type, usage);
326}
327
328sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
329                                    RsAllocationMipmapControl mipmaps, uint32_t usage,
330                                    void *pointer) {
331    void *id = 0;
332    if (rs->getError() == RS_SUCCESS) {
333        id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage,
334                                                 (uintptr_t)pointer);
335    }
336    if (id == 0) {
337        rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
338        return NULL;
339    }
340    return new Allocation(id, rs, type, usage);
341}
342
343sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
344                                    uint32_t usage) {
345    return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
346}
347
348sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e,
349                                    size_t count, uint32_t usage) {
350    Type::Builder b(rs, e);
351    b.setX(count);
352    sp<const Type> t = b.create();
353
354    return createTyped(rs, t, usage);
355}
356
357sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e,
358                                      size_t x, size_t y, uint32_t usage) {
359    Type::Builder b(rs, e);
360    b.setX(x);
361    b.setY(y);
362    sp<const Type> t = b.create();
363
364    return createTyped(rs, t, usage);
365}
366