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