blob: d6f79b0eb57a088c6975f382bfb7df033ad1cbe4 [file] [log] [blame]
Jason Sams221a4b12012-02-22 15:22:41 -08001/*
Jason Sams3522f402012-03-23 11:47:26 -07002 * Copyright (C) 2012 The Android Open Source Project
Jason Sams221a4b12012-02-22 15:22:41 -08003 *
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
Jason Samsf1e6d222012-02-24 14:24:56 -080017#define LOG_TAG "libRS_cpp"
18
Jason Sams221a4b12012-02-22 15:22:41 -080019#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
Jason Sams69cccdf2012-04-02 19:11:49 -070027using namespace android;
28using namespace renderscriptCpp;
Jason Sams221a4b12012-02-22 15:22:41 -080029
30void * Allocation::getIDSafe() const {
31 //if (mAdaptedAllocation != NULL) {
32 //return mAdaptedAllocation.getID();
33 //}
34 return getID();
35}
36
Jason Sams69cccdf2012-04-02 19:11:49 -070037void Allocation::updateCacheInfo(sp<const Type> t) {
Jason Sams221a4b12012-02-22 15:22:41 -080038 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
Jason Sams69cccdf2012-04-02 19:11:49 -070050Allocation::Allocation(void *id, RenderScript *rs, sp<const Type> t, uint32_t usage) :
51 BaseObj(id, rs) {
52
Jason Sams221a4b12012-02-22 15:22:41 -080053 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 |
Jason Sams221a4b12012-02-22 15:22:41 -080058 RS_ALLOCATION_USAGE_IO_INPUT |
59 RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) {
60 ALOGE("Unknown usage specified.");
61 }
62
Jason Sams3522f402012-03-23 11:47:26 -070063 if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) {
Jason Sams221a4b12012-02-22 15:22:41 -080064 mWriteAllowed = false;
Jason Sams3522f402012-03-23 11:47:26 -070065 if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT |
Jason Sams221a4b12012-02-22 15:22:41 -080066 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
Jason Sams69cccdf2012-04-02 19:11:49 -070075 if (t.get() != NULL) {
Jason Sams221a4b12012-02-22 15:22:41 -080076 updateCacheInfo(t);
77 }
78}
79
80void 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
88void 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
96void 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
104void 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
112void 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
129void Allocation::updateFromNative() {
130 BaseObj::updateFromNative();
131
132 const void *typeID = rsaAllocationGetType(mRS->mContext, getID());
133 if(typeID != NULL) {
Jason Sams69cccdf2012-04-02 19:11:49 -0700134 sp<const Type> old = mType;
135 sp<Type> t = new Type((void *)typeID, mRS);
Jason Sams221a4b12012-02-22 15:22:41 -0800136 t->updateFromNative();
137 updateCacheInfo(t);
138 mType = t;
Jason Sams221a4b12012-02-22 15:22:41 -0800139 }
140}
141
142void 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
155void 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
162void 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/*
170void 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/*
187void 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
200void 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
223void Allocation::generateMipmaps() {
224 rsAllocationGenerateMipmaps(mRS->mContext, getID());
225}
226
Jason Sams69cccdf2012-04-02 19:11:49 -0700227void Allocation::copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data,
228 size_t dataLen) {
229
Jason Sams221a4b12012-02-22 15:22:41 -0800230 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
246void 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
251void 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
256void 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
261void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) {
262 validateIsFloat32();
263 copy1DRangeFromUnchecked(off, count, d, dataLen);
264}
265
Jason Sams69cccdf2012-04-02 19:11:49 -0700266void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data,
267 uint32_t dataOff) {
268
Jason Sams221a4b12012-02-22 15:22:41 -0800269 rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), off, 0,
270 mSelectedLOD, mSelectedFace,
271 count, 1, data->getIDSafe(), dataOff, 0,
272 data->mSelectedLOD, data->mSelectedFace);
273}
274
275void 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
285void 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
292void 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
299void 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
306void 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
313void 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/*
324void copyTo(byte[] d) {
325 validateIsInt8();
326 mRS.validate();
327 mRS.nAllocationRead(getID(), d);
328}
329
330void copyTo(short[] d) {
331 validateIsInt16();
332 mRS.validate();
333 mRS.nAllocationRead(getID(), d);
334}
335
336void copyTo(int[] d) {
337 validateIsInt32();
338 mRS.validate();
339 mRS.nAllocationRead(getID(), d);
340}
341
342void copyTo(float[] d) {
343 validateIsFloat32();
344 mRS.validate();
345 mRS.nAllocationRead(getID(), d);
346}
347
348void 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
361void 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
Jason Sams69cccdf2012-04-02 19:11:49 -0700381android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
Jason Sams221a4b12012-02-22 15:22:41 -0800382 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
Jason Sams69cccdf2012-04-02 19:11:49 -0700391android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
Jason Sams221a4b12012-02-22 15:22:41 -0800392 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
Jason Sams69cccdf2012-04-02 19:11:49 -0700400android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
401 uint32_t usage) {
Jason Sams221a4b12012-02-22 15:22:41 -0800402 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
403}
404
Jason Sams69cccdf2012-04-02 19:11:49 -0700405android::sp<Allocation> Allocation::createSized(RenderScript *rs, sp<const Element> e,
406 size_t count, uint32_t usage) {
407
Jason Sams221a4b12012-02-22 15:22:41 -0800408 Type::Builder b(rs, e);
409 b.setX(count);
Jason Sams69cccdf2012-04-02 19:11:49 -0700410 sp<const Type> t = b.create();
Jason Sams221a4b12012-02-22 15:22:41 -0800411
Jason Sams69cccdf2012-04-02 19:11:49 -0700412 void *id = rsAllocationCreateTyped(rs->mContext, t->getID(),
413 RS_ALLOCATION_MIPMAP_NONE, usage, 0);
Jason Sams221a4b12012-02-22 15:22:41 -0800414 if (id == 0) {
415 ALOGE("Allocation creation failed.");
416 }
417 return new Allocation(id, rs, t, usage);
418}
419
420
421/*
422SurfaceTexture 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
432void 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
442static 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
455static 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
463static 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