blob: d69c55ff274923a58236e3a95d60c1e6b2a9ce51 [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
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 |
54 RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
55 RS_ALLOCATION_USAGE_IO_INPUT |
56 RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) {
57 ALOGE("Unknown usage specified.");
58 }
59
60 if ((usage & (RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
61 RS_ALLOCATION_USAGE_IO_INPUT)) != 0) {
62 mWriteAllowed = false;
63 if ((usage & ~(RS_ALLOCATION_USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE |
64 RS_ALLOCATION_USAGE_IO_INPUT |
65 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
66 RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
67 ALOGE("Invalid usage combination.");
68 }
69 }
70
71 mType = t;
72 mUsage = usage;
73
74 if (t != NULL) {
75 updateCacheInfo(t);
76 }
77}
78
79void Allocation::validateIsInt32() {
80 RsDataType dt = mType->getElement()->getDataType();
81 if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
82 return;
83 }
84 ALOGE("32 bit integer source does not match allocation type %i", dt);
85}
86
87void Allocation::validateIsInt16() {
88 RsDataType dt = mType->getElement()->getDataType();
89 if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
90 return;
91 }
92 ALOGE("16 bit integer source does not match allocation type %i", dt);
93}
94
95void Allocation::validateIsInt8() {
96 RsDataType dt = mType->getElement()->getDataType();
97 if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
98 return;
99 }
100 ALOGE("8 bit integer source does not match allocation type %i", dt);
101}
102
103void Allocation::validateIsFloat32() {
104 RsDataType dt = mType->getElement()->getDataType();
105 if (dt == RS_TYPE_FLOAT_32) {
106 return;
107 }
108 ALOGE("32 bit float source does not match allocation type %i", dt);
109}
110
111void Allocation::validateIsObject() {
112 RsDataType dt = mType->getElement()->getDataType();
113 if ((dt == RS_TYPE_ELEMENT) ||
114 (dt == RS_TYPE_TYPE) ||
115 (dt == RS_TYPE_ALLOCATION) ||
116 (dt == RS_TYPE_SAMPLER) ||
117 (dt == RS_TYPE_SCRIPT) ||
118 (dt == RS_TYPE_MESH) ||
119 (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
120 (dt == RS_TYPE_PROGRAM_VERTEX) ||
121 (dt == RS_TYPE_PROGRAM_RASTER) ||
122 (dt == RS_TYPE_PROGRAM_STORE)) {
123 return;
124 }
125 ALOGE("Object source does not match allocation type %i", dt);
126}
127
128void Allocation::updateFromNative() {
129 BaseObj::updateFromNative();
130
131 const void *typeID = rsaAllocationGetType(mRS->mContext, getID());
132 if(typeID != NULL) {
133 const Type *old = mType;
134 Type *t = new Type((void *)typeID, mRS);
135 t->updateFromNative();
136 updateCacheInfo(t);
137 mType = t;
138 delete old;
139 }
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
227void Allocation::copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data, size_t dataLen) {
228 if(count < 1) {
229 ALOGE("Count must be >= 1.");
230 return;
231 }
232 if((off + count) > mCurrentCount) {
233 ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
234 return;
235 }
236 if((count * mType->getElement()->getSizeBytes()) > dataLen) {
237 ALOGE("Array too small for allocation type.");
238 return;
239 }
240
241 rsAllocation1DData(mRS->mContext, getIDSafe(), off, mSelectedLOD, count, data, dataLen);
242}
243
244void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int32_t *d, size_t dataLen) {
245 validateIsInt32();
246 copy1DRangeFromUnchecked(off, count, d, dataLen);
247}
248
249void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int16_t *d, size_t dataLen) {
250 validateIsInt16();
251 copy1DRangeFromUnchecked(off, count, d, dataLen);
252}
253
254void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int8_t *d, size_t dataLen) {
255 validateIsInt8();
256 copy1DRangeFromUnchecked(off, count, d, dataLen);
257}
258
259void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) {
260 validateIsFloat32();
261 copy1DRangeFromUnchecked(off, count, d, dataLen);
262}
263
264void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data, uint32_t dataOff) {
265 rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), off, 0,
266 mSelectedLOD, mSelectedFace,
267 count, 1, data->getIDSafe(), dataOff, 0,
268 data->mSelectedLOD, data->mSelectedFace);
269}
270
271void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
272 if (mAdaptedAllocation != NULL) {
273
274 } else {
275 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
276 ALOGE("Updated region larger than allocation.");
277 }
278 }
279}
280
281void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
282 const int8_t *data, size_t dataLen) {
283 validate2DRange(xoff, yoff, w, h);
284 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
285 w, h, data, dataLen);
286}
287
288void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
289 const int16_t *data, size_t dataLen) {
290 validate2DRange(xoff, yoff, w, h);
291 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
292 w, h, data, dataLen);
293}
294
295void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
296 const int32_t *data, size_t dataLen) {
297 validate2DRange(xoff, yoff, w, h);
298 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
299 w, h, data, dataLen);
300}
301
302void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
303 const float *data, size_t dataLen) {
304 validate2DRange(xoff, yoff, w, h);
305 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
306 w, h, data, dataLen);
307}
308
309void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
310 const Allocation *data, size_t dataLen,
311 uint32_t dataXoff, uint32_t dataYoff) {
312 validate2DRange(xoff, yoff, w, h);
313 rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), xoff, yoff,
314 mSelectedLOD, mSelectedFace,
315 w, h, data->getIDSafe(), dataXoff, dataYoff,
316 data->mSelectedLOD, data->mSelectedFace);
317}
318
319/*
320void copyTo(byte[] d) {
321 validateIsInt8();
322 mRS.validate();
323 mRS.nAllocationRead(getID(), d);
324}
325
326void copyTo(short[] d) {
327 validateIsInt16();
328 mRS.validate();
329 mRS.nAllocationRead(getID(), d);
330}
331
332void copyTo(int[] d) {
333 validateIsInt32();
334 mRS.validate();
335 mRS.nAllocationRead(getID(), d);
336}
337
338void copyTo(float[] d) {
339 validateIsFloat32();
340 mRS.validate();
341 mRS.nAllocationRead(getID(), d);
342}
343
344void resize(int dimX) {
345 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
346 throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
347 }
348 mRS.nAllocationResize1D(getID(), dimX);
349 mRS.finish(); // Necessary because resize is fifoed and update is async.
350
351 int typeID = mRS.nAllocationGetType(getID());
352 mType = new Type(typeID, mRS);
353 mType.updateFromNative();
354 updateCacheInfo(mType);
355}
356
357void resize(int dimX, int dimY) {
358 if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
359 throw new RSInvalidStateException(
360 "Resize only support for 2D allocations at this time.");
361 }
362 if (mType.getY() == 0) {
363 throw new RSInvalidStateException(
364 "Resize only support for 2D allocations at this time.");
365 }
366 mRS.nAllocationResize2D(getID(), dimX, dimY);
367 mRS.finish(); // Necessary because resize is fifoed and update is async.
368
369 int typeID = mRS.nAllocationGetType(getID());
370 mType = new Type(typeID, mRS);
371 mType.updateFromNative();
372 updateCacheInfo(mType);
373}
374*/
375
376
377Allocation *Allocation::createTyped(RenderScript *rs, const Type *type,
378 RsAllocationMipmapControl mips, uint32_t usage) {
379 void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, 0);
380 if (id == 0) {
381 ALOGE("Allocation creation failed.");
382 return NULL;
383 }
384 return new Allocation(id, rs, type, usage);
385}
386
387Allocation *Allocation::createTyped(RenderScript *rs, const Type *type,
388 RsAllocationMipmapControl mips, uint32_t usage, void *pointer) {
389 void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, (uint32_t)pointer);
390 if (id == 0) {
391 ALOGE("Allocation creation failed.");
392 }
393 return new Allocation(id, rs, type, usage);
394}
395
396Allocation *Allocation::createTyped(RenderScript *rs, const Type *type, uint32_t usage) {
397 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
398}
399
400Allocation *Allocation::createSized(RenderScript *rs, const Element *e, size_t count, uint32_t usage) {
401 Type::Builder b(rs, e);
402 b.setX(count);
403 const Type *t = b.create();
404
405 void *id = rsAllocationCreateTyped(rs->mContext, t->getID(), RS_ALLOCATION_MIPMAP_NONE, usage, 0);
406 if (id == 0) {
407 ALOGE("Allocation creation failed.");
408 }
409 return new Allocation(id, rs, t, usage);
410}
411
412
413/*
414SurfaceTexture getSurfaceTexture() {
415 if ((mUsage & USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE) == 0) {
416 throw new RSInvalidStateException("Allocation is not a surface texture.");
417 }
418
419 int id = mRS.nAllocationGetSurfaceTextureID(getID());
420 return new SurfaceTexture(id);
421
422}
423
424void setSurfaceTexture(SurfaceTexture sur) {
425 if ((mUsage & USAGE_IO_OUTPUT) == 0) {
426 throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
427 }
428
429 mRS.validate();
430 mRS.nAllocationSetSurfaceTexture(getID(), sur);
431}
432
433
434static Allocation createFromBitmapResource(RenderScript rs,
435 Resources res,
436 int id,
437 MipmapControl mips,
438 int usage) {
439
440 rs.validate();
441 Bitmap b = BitmapFactory.decodeResource(res, id);
442 Allocation alloc = createFromBitmap(rs, b, mips, usage);
443 b.recycle();
444 return alloc;
445}
446
447static Allocation createFromBitmapResource(RenderScript rs,
448 Resources res,
449 int id) {
450 return createFromBitmapResource(rs, res, id,
451 MipmapControl.MIPMAP_NONE,
452 USAGE_GRAPHICS_TEXTURE);
453}
454
455static Allocation createFromString(RenderScript rs,
456 String str,
457 int usage) {
458 rs.validate();
459 byte[] allocArray = NULL;
460 try {
461 allocArray = str.getBytes("UTF-8");
462 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
463 alloc.copyFrom(allocArray);
464 return alloc;
465 }
466 catch (Exception e) {
467 throw new RSRuntimeException("Could not convert string to utf-8.");
468 }
469}
470*/
471