• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "libRS_cpp"
18 
19 #include <utils/Log.h>
20 #include <malloc.h>
21 
22 #include "RenderScript.h"
23 #include "Element.h"
24 #include "Type.h"
25 #include "Allocation.h"
26 
27 using namespace android;
28 using namespace renderscriptCpp;
29 
getIDSafe() const30 void * Allocation::getIDSafe() const {
31     //if (mAdaptedAllocation != NULL) {
32         //return mAdaptedAllocation.getID();
33     //}
34     return getID();
35 }
36 
updateCacheInfo(sp<const Type> t)37 void Allocation::updateCacheInfo(sp<const Type> t) {
38     mCurrentDimX = t->getX();
39     mCurrentDimY = t->getY();
40     mCurrentDimZ = t->getZ();
41     mCurrentCount = mCurrentDimX;
42     if (mCurrentDimY > 1) {
43         mCurrentCount *= mCurrentDimY;
44     }
45     if (mCurrentDimZ > 1) {
46         mCurrentCount *= mCurrentDimZ;
47     }
48 }
49 
Allocation(void * id,RenderScript * rs,sp<const Type> t,uint32_t usage)50 Allocation::Allocation(void *id, RenderScript *rs, sp<const Type> t, uint32_t usage) :
51         BaseObj(id, rs) {
52 
53     if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT |
54                    RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
55                    RS_ALLOCATION_USAGE_GRAPHICS_VERTEX |
56                    RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS |
57                    RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET |
58                    RS_ALLOCATION_USAGE_IO_INPUT |
59                    RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) {
60         ALOGE("Unknown usage specified.");
61     }
62 
63     if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) {
64         mWriteAllowed = false;
65         if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT |
66                        RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
67                        RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
68             ALOGE("Invalid usage combination.");
69         }
70     }
71 
72     mType = t;
73     mUsage = usage;
74 
75     if (t.get() != NULL) {
76         updateCacheInfo(t);
77     }
78 }
79 
validateIsInt32()80 void Allocation::validateIsInt32() {
81     RsDataType dt = mType->getElement()->getDataType();
82     if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
83         return;
84     }
85     ALOGE("32 bit integer source does not match allocation type %i", dt);
86 }
87 
validateIsInt16()88 void Allocation::validateIsInt16() {
89     RsDataType dt = mType->getElement()->getDataType();
90     if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
91         return;
92     }
93     ALOGE("16 bit integer source does not match allocation type %i", dt);
94 }
95 
validateIsInt8()96 void Allocation::validateIsInt8() {
97     RsDataType dt = mType->getElement()->getDataType();
98     if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
99         return;
100     }
101     ALOGE("8 bit integer source does not match allocation type %i", dt);
102 }
103 
validateIsFloat32()104 void Allocation::validateIsFloat32() {
105     RsDataType dt = mType->getElement()->getDataType();
106     if (dt == RS_TYPE_FLOAT_32) {
107         return;
108     }
109     ALOGE("32 bit float source does not match allocation type %i", dt);
110 }
111 
validateIsObject()112 void Allocation::validateIsObject() {
113     RsDataType dt = mType->getElement()->getDataType();
114     if ((dt == RS_TYPE_ELEMENT) ||
115         (dt == RS_TYPE_TYPE) ||
116         (dt == RS_TYPE_ALLOCATION) ||
117         (dt == RS_TYPE_SAMPLER) ||
118         (dt == RS_TYPE_SCRIPT) ||
119         (dt == RS_TYPE_MESH) ||
120         (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
121         (dt == RS_TYPE_PROGRAM_VERTEX) ||
122         (dt == RS_TYPE_PROGRAM_RASTER) ||
123         (dt == RS_TYPE_PROGRAM_STORE)) {
124         return;
125     }
126     ALOGE("Object source does not match allocation type %i", dt);
127 }
128 
updateFromNative()129 void Allocation::updateFromNative() {
130     BaseObj::updateFromNative();
131 
132     const void *typeID = rsaAllocationGetType(mRS->mContext, getID());
133     if(typeID != NULL) {
134         sp<const Type> old = mType;
135         sp<Type> t = new Type((void *)typeID, mRS);
136         t->updateFromNative();
137         updateCacheInfo(t);
138         mType = t;
139     }
140 }
141 
syncAll(RsAllocationUsageType srcLocation)142 void Allocation::syncAll(RsAllocationUsageType srcLocation) {
143     switch (srcLocation) {
144     case RS_ALLOCATION_USAGE_SCRIPT:
145     case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
146     case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
147     case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
148         break;
149     default:
150         ALOGE("Source must be exactly one usage type.");
151     }
152     rsAllocationSyncAll(mRS->mContext, getIDSafe(), srcLocation);
153 }
154 
ioSendOutput()155 void Allocation::ioSendOutput() {
156     if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
157         ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
158     }
159     rsAllocationIoSend(mRS->mContext, getID());
160 }
161 
ioGetInput()162 void Allocation::ioGetInput() {
163     if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
164         ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
165     }
166     rsAllocationIoReceive(mRS->mContext, getID());
167 }
168 
169 /*
170 void copyFrom(BaseObj[] d) {
171     mRS.validate();
172     validateIsObject();
173     if (d.length != mCurrentCount) {
174         ALOGE("Array size mismatch, allocation sizeX = " +
175                                              mCurrentCount + ", array length = " + d.length);
176     }
177     int i[] = new int[d.length];
178     for (int ct=0; ct < d.length; ct++) {
179         i[ct] = d[ct].getID();
180     }
181     copy1DRangeFromUnchecked(0, mCurrentCount, i);
182 }
183 */
184 
185 
186 /*
187 void Allocation::setFromFieldPacker(int xoff, FieldPacker fp) {
188     mRS.validate();
189     int eSize = mType.mElement.getSizeBytes();
190     final byte[] data = fp.getData();
191 
192     int count = data.length / eSize;
193     if ((eSize * count) != data.length) {
194         ALOGE("Field packer length " + data.length +
195                                            " not divisible by element size " + eSize + ".");
196     }
197     copy1DRangeFromUnchecked(xoff, count, data);
198 }
199 
200 void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
201     mRS.validate();
202     if (component_number >= mType.mElement.mElements.length) {
203         ALOGE("Component_number " + component_number + " out of range.");
204     }
205     if(xoff < 0) {
206         ALOGE("Offset must be >= 0.");
207     }
208 
209     final byte[] data = fp.getData();
210     int eSize = mType.mElement.mElements[component_number].getSizeBytes();
211     eSize *= mType.mElement.mArraySizes[component_number];
212 
213     if (data.length != eSize) {
214         ALOGE("Field packer sizelength " + data.length +
215                                            " does not match component size " + eSize + ".");
216     }
217 
218     mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
219                                  component_number, data, data.length);
220 }
221 */
222 
generateMipmaps()223 void Allocation::generateMipmaps() {
224     rsAllocationGenerateMipmaps(mRS->mContext, getID());
225 }
226 
copy1DRangeFromUnchecked(uint32_t off,size_t count,const void * data,size_t dataLen)227 void Allocation::copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data,
228         size_t dataLen) {
229 
230     if(count < 1) {
231         ALOGE("Count must be >= 1.");
232         return;
233     }
234     if((off + count) > mCurrentCount) {
235         ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
236         return;
237     }
238     if((count * mType->getElement()->getSizeBytes()) > dataLen) {
239         ALOGE("Array too small for allocation type.");
240         return;
241     }
242 
243     rsAllocation1DData(mRS->mContext, getIDSafe(), off, mSelectedLOD, count, data, dataLen);
244 }
245 
copy1DRangeFrom(uint32_t off,size_t count,const int32_t * d,size_t dataLen)246 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int32_t *d, size_t dataLen) {
247     validateIsInt32();
248     copy1DRangeFromUnchecked(off, count, d, dataLen);
249 }
250 
copy1DRangeFrom(uint32_t off,size_t count,const int16_t * d,size_t dataLen)251 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int16_t *d, size_t dataLen) {
252     validateIsInt16();
253     copy1DRangeFromUnchecked(off, count, d, dataLen);
254 }
255 
copy1DRangeFrom(uint32_t off,size_t count,const int8_t * d,size_t dataLen)256 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int8_t *d, size_t dataLen) {
257     validateIsInt8();
258     copy1DRangeFromUnchecked(off, count, d, dataLen);
259 }
260 
copy1DRangeFrom(uint32_t off,size_t count,const float * d,size_t dataLen)261 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) {
262     validateIsFloat32();
263     copy1DRangeFromUnchecked(off, count, d, dataLen);
264 }
265 
copy1DRangeFrom(uint32_t off,size_t count,const Allocation * data,uint32_t dataOff)266 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data,
267         uint32_t dataOff) {
268 
269     rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), off, 0,
270                             mSelectedLOD, mSelectedFace,
271                             count, 1, data->getIDSafe(), dataOff, 0,
272                             data->mSelectedLOD, data->mSelectedFace);
273 }
274 
validate2DRange(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h)275 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
276     if (mAdaptedAllocation != NULL) {
277 
278     } else {
279         if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
280             ALOGE("Updated region larger than allocation.");
281         }
282     }
283 }
284 
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const int8_t * data,size_t dataLen)285 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
286                                  const int8_t *data, size_t dataLen) {
287     validate2DRange(xoff, yoff, w, h);
288     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
289                        w, h, data, dataLen);
290 }
291 
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const int16_t * data,size_t dataLen)292 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
293                                  const int16_t *data, size_t dataLen) {
294     validate2DRange(xoff, yoff, w, h);
295     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
296                        w, h, data, dataLen);
297 }
298 
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const int32_t * data,size_t dataLen)299 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
300                                  const int32_t *data, size_t dataLen) {
301     validate2DRange(xoff, yoff, w, h);
302     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
303                        w, h, data, dataLen);
304 }
305 
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const float * data,size_t dataLen)306 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
307                                  const float *data, size_t dataLen) {
308     validate2DRange(xoff, yoff, w, h);
309     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
310                        w, h, data, dataLen);
311 }
312 
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const Allocation * data,size_t dataLen,uint32_t dataXoff,uint32_t dataYoff)313 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
314                                  const Allocation *data, size_t dataLen,
315                                  uint32_t dataXoff, uint32_t dataYoff) {
316     validate2DRange(xoff, yoff, w, h);
317     rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), xoff, yoff,
318                             mSelectedLOD, mSelectedFace,
319                             w, h, data->getIDSafe(), dataXoff, dataYoff,
320                             data->mSelectedLOD, data->mSelectedFace);
321 }
322 
323 /*
324 void copyTo(byte[] d) {
325     validateIsInt8();
326     mRS.validate();
327     mRS.nAllocationRead(getID(), d);
328 }
329 
330 void copyTo(short[] d) {
331     validateIsInt16();
332     mRS.validate();
333     mRS.nAllocationRead(getID(), d);
334 }
335 
336 void copyTo(int[] d) {
337     validateIsInt32();
338     mRS.validate();
339     mRS.nAllocationRead(getID(), d);
340 }
341 
342 void copyTo(float[] d) {
343     validateIsFloat32();
344     mRS.validate();
345     mRS.nAllocationRead(getID(), d);
346 }
347 
348 void resize(int dimX) {
349     if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
350         throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
351     }
352     mRS.nAllocationResize1D(getID(), dimX);
353     mRS.finish();  // Necessary because resize is fifoed and update is async.
354 
355     int typeID = mRS.nAllocationGetType(getID());
356     mType = new Type(typeID, mRS);
357     mType.updateFromNative();
358     updateCacheInfo(mType);
359 }
360 
361 void resize(int dimX, int dimY) {
362     if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
363         throw new RSInvalidStateException(
364             "Resize only support for 2D allocations at this time.");
365     }
366     if (mType.getY() == 0) {
367         throw new RSInvalidStateException(
368             "Resize only support for 2D allocations at this time.");
369     }
370     mRS.nAllocationResize2D(getID(), dimX, dimY);
371     mRS.finish();  // Necessary because resize is fifoed and update is async.
372 
373     int typeID = mRS.nAllocationGetType(getID());
374     mType = new Type(typeID, mRS);
375     mType.updateFromNative();
376     updateCacheInfo(mType);
377 }
378 */
379 
380 
createTyped(RenderScript * rs,sp<const Type> type,RsAllocationMipmapControl mips,uint32_t usage)381 android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
382                         RsAllocationMipmapControl mips, uint32_t usage) {
383     void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, 0);
384     if (id == 0) {
385         ALOGE("Allocation creation failed.");
386         return NULL;
387     }
388     return new Allocation(id, rs, type, usage);
389 }
390 
createTyped(RenderScript * rs,sp<const Type> type,RsAllocationMipmapControl mips,uint32_t usage,void * pointer)391 android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
392                                     RsAllocationMipmapControl mips, uint32_t usage, void *pointer) {
393     void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, (uint32_t)pointer);
394     if (id == 0) {
395         ALOGE("Allocation creation failed.");
396     }
397     return new Allocation(id, rs, type, usage);
398 }
399 
createTyped(RenderScript * rs,sp<const Type> type,uint32_t usage)400 android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
401         uint32_t usage) {
402     return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
403 }
404 
createSized(RenderScript * rs,sp<const Element> e,size_t count,uint32_t usage)405 android::sp<Allocation> Allocation::createSized(RenderScript *rs, sp<const Element> e,
406         size_t count, uint32_t usage) {
407 
408     Type::Builder b(rs, e);
409     b.setX(count);
410     sp<const Type> t = b.create();
411 
412     void *id = rsAllocationCreateTyped(rs->mContext, t->getID(),
413         RS_ALLOCATION_MIPMAP_NONE, usage, 0);
414     if (id == 0) {
415         ALOGE("Allocation creation failed.");
416     }
417     return new Allocation(id, rs, t, usage);
418 }
419 
420 
421 /*
422 SurfaceTexture getSurfaceTexture() {
423     if ((mUsage & USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE) == 0) {
424         throw new RSInvalidStateException("Allocation is not a surface texture.");
425     }
426 
427     int id = mRS.nAllocationGetSurfaceTextureID(getID());
428     return new SurfaceTexture(id);
429 
430 }
431 
432 void setSurfaceTexture(SurfaceTexture sur) {
433     if ((mUsage & USAGE_IO_OUTPUT) == 0) {
434         throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
435     }
436 
437     mRS.validate();
438     mRS.nAllocationSetSurfaceTexture(getID(), sur);
439 }
440 
441 
442 static Allocation createFromBitmapResource(RenderScript rs,
443                                                   Resources res,
444                                                   int id,
445                                                   MipmapControl mips,
446                                                   int usage) {
447 
448     rs.validate();
449     Bitmap b = BitmapFactory.decodeResource(res, id);
450     Allocation alloc = createFromBitmap(rs, b, mips, usage);
451     b.recycle();
452     return alloc;
453 }
454 
455 static Allocation createFromBitmapResource(RenderScript rs,
456                                                   Resources res,
457                                                   int id) {
458     return createFromBitmapResource(rs, res, id,
459                                     MipmapControl.MIPMAP_NONE,
460                                     USAGE_GRAPHICS_TEXTURE);
461 }
462 
463 static Allocation createFromString(RenderScript rs,
464                                           String str,
465                                           int usage) {
466     rs.validate();
467     byte[] allocArray = NULL;
468     try {
469         allocArray = str.getBytes("UTF-8");
470         Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
471         alloc.copyFrom(allocArray);
472         return alloc;
473     }
474     catch (Exception e) {
475         throw new RSRuntimeException("Could not convert string to utf-8.");
476     }
477 }
478 */
479 
480