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