1 /*
2 * Copyright (C) 2013 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 "RenderScript.h"
18 #include "rsCppInternal.h"
19
20 using namespace android;
21 using namespace RSC;
22
23
getIDSafe() const24 void * Allocation::getIDSafe() const {
25 return getID();
26 }
27
updateCacheInfo(sp<const Type> t)28 void Allocation::updateCacheInfo(sp<const Type> t) {
29 mCurrentDimX = t->getX();
30 mCurrentDimY = t->getY();
31 mCurrentDimZ = t->getZ();
32 mCurrentCount = mCurrentDimX;
33 if (mCurrentDimY > 1) {
34 mCurrentCount *= mCurrentDimY;
35 }
36 if (mCurrentDimZ > 1) {
37 mCurrentCount *= mCurrentDimZ;
38 }
39 }
40
Allocation(void * id,sp<RS> rs,sp<const Type> t,uint32_t usage)41 Allocation::Allocation(void *id, sp<RS> rs, sp<const Type> t, uint32_t usage) :
42 BaseObj(id, rs), mSelectedY(0), mSelectedZ(0), mSelectedLOD(0),
43 mSelectedFace(RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X) {
44
45 if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT |
46 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
47 RS_ALLOCATION_USAGE_GRAPHICS_VERTEX |
48 RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS |
49 RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET |
50 RS_ALLOCATION_USAGE_IO_INPUT |
51 RS_ALLOCATION_USAGE_IO_OUTPUT |
52 RS_ALLOCATION_USAGE_OEM |
53 RS_ALLOCATION_USAGE_SHARED)) != 0) {
54 ALOGE("Unknown usage specified.");
55 }
56
57 if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) {
58 mWriteAllowed = false;
59 if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT |
60 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
61 RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
62 ALOGE("Invalid usage combination.");
63 }
64 }
65
66 mType = t;
67 mUsage = usage;
68 mAutoPadding = false;
69 if (t != nullptr) {
70 updateCacheInfo(t);
71 }
72
73 }
74
75
validateIsInt64()76 void Allocation::validateIsInt64() {
77 RsDataType dt = mType->getElement()->getDataType();
78 if ((dt == RS_TYPE_SIGNED_64) || (dt == RS_TYPE_UNSIGNED_64)) {
79 return;
80 }
81 ALOGE("64 bit integer source does not match allocation type %i", dt);
82 }
83
validateIsInt32()84 void Allocation::validateIsInt32() {
85 RsDataType dt = mType->getElement()->getDataType();
86 if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
87 return;
88 }
89 ALOGE("32 bit integer source does not match allocation type %i", dt);
90 }
91
validateIsInt16()92 void Allocation::validateIsInt16() {
93 RsDataType dt = mType->getElement()->getDataType();
94 if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
95 return;
96 }
97 ALOGE("16 bit integer source does not match allocation type %i", dt);
98 }
99
validateIsInt8()100 void Allocation::validateIsInt8() {
101 RsDataType dt = mType->getElement()->getDataType();
102 if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
103 return;
104 }
105 ALOGE("8 bit integer source does not match allocation type %i", dt);
106 }
107
validateIsFloat32()108 void Allocation::validateIsFloat32() {
109 RsDataType dt = mType->getElement()->getDataType();
110 if (dt == RS_TYPE_FLOAT_32) {
111 return;
112 }
113 ALOGE("32 bit float source does not match allocation type %i", dt);
114 }
115
validateIsFloat64()116 void Allocation::validateIsFloat64() {
117 RsDataType dt = mType->getElement()->getDataType();
118 if (dt == RS_TYPE_FLOAT_64) {
119 return;
120 }
121 ALOGE("64 bit float source does not match allocation type %i", dt);
122 }
123
validateIsObject()124 void Allocation::validateIsObject() {
125 RsDataType dt = mType->getElement()->getDataType();
126 if ((dt == RS_TYPE_ELEMENT) ||
127 (dt == RS_TYPE_TYPE) ||
128 (dt == RS_TYPE_ALLOCATION) ||
129 (dt == RS_TYPE_SAMPLER) ||
130 (dt == RS_TYPE_SCRIPT) ||
131 (dt == RS_TYPE_MESH) ||
132 (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
133 (dt == RS_TYPE_PROGRAM_VERTEX) ||
134 (dt == RS_TYPE_PROGRAM_RASTER) ||
135 (dt == RS_TYPE_PROGRAM_STORE)) {
136 return;
137 }
138 ALOGE("Object source does not match allocation type %i", dt);
139 }
140
updateFromNative()141 void Allocation::updateFromNative() {
142 BaseObj::updateFromNative();
143
144 const void *typeID = RS::dispatch->AllocationGetType(mRS->getContext(), getID());
145 if(typeID != nullptr) {
146 sp<const Type> old = mType;
147 sp<Type> t = new Type((void *)typeID, mRS);
148 t->updateFromNative();
149 updateCacheInfo(t);
150 mType = t;
151 }
152 }
153
syncAll(RsAllocationUsageType srcLocation)154 void Allocation::syncAll(RsAllocationUsageType srcLocation) {
155 switch (srcLocation) {
156 case RS_ALLOCATION_USAGE_SCRIPT:
157 case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
158 case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
159 case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
160 case RS_ALLOCATION_USAGE_SHARED:
161 break;
162 default:
163 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Source must be exactly one usage type.");
164 return;
165 }
166 tryDispatch(mRS, RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation));
167 }
168
getPointer(size_t * stride)169 void * Allocation::getPointer(size_t *stride) {
170 void *p = nullptr;
171 if (!(mUsage & RS_ALLOCATION_USAGE_SHARED)) {
172 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Allocation does not support USAGE_SHARED.");
173 return nullptr;
174 }
175
176 // FIXME: decide if lack of getPointer should cause compat mode
177 if (RS::dispatch->AllocationGetPointer == nullptr) {
178 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Can't use getPointer on older APIs");
179 return nullptr;
180 }
181
182 p = RS::dispatch->AllocationGetPointer(mRS->getContext(), getIDSafe(), 0,
183 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0, stride, sizeof(size_t));
184 if (mRS->getError() != RS_SUCCESS) {
185 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation lock failed");
186 p = nullptr;
187 }
188 return p;
189 }
190
191 // ---------------------------------------------------------------------------
192 //Functions needed for autopadding & unpadding
copyWithPadding(void * ptr,const void * srcPtr,int mSize,int count)193 static void copyWithPadding(void* ptr, const void* srcPtr, int mSize, int count) {
194 int sizeBytesPad = mSize * 4;
195 int sizeBytes = mSize * 3;
196 uint8_t *dst = static_cast<uint8_t *>(ptr);
197 const uint8_t *src = static_cast<const uint8_t *>(srcPtr);
198 for (int i = 0; i < count; i++) {
199 memcpy(dst, src, sizeBytes);
200 dst += sizeBytesPad;
201 src += sizeBytes;
202 }
203 }
204
copyWithUnPadding(void * ptr,const void * srcPtr,int mSize,int count)205 static void copyWithUnPadding(void* ptr, const void* srcPtr, int mSize, int count) {
206 int sizeBytesPad = mSize * 4;
207 int sizeBytes = mSize * 3;
208 uint8_t *dst = static_cast<uint8_t *>(ptr);
209 const uint8_t *src = static_cast<const uint8_t *>(srcPtr);
210 for (int i = 0; i < count; i++) {
211 memcpy(dst, src, sizeBytes);
212 dst += sizeBytes;
213 src += sizeBytesPad;
214 }
215 }
216 // ---------------------------------------------------------------------------
217
copy1DRangeFrom(uint32_t off,size_t count,const void * data)218 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) {
219
220 if(count < 1) {
221 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
222 return;
223 }
224 if((off + count) > mCurrentCount) {
225 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off);
226 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
227 return;
228 }
229 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
230 size_t eSize = mType->getElement()->getSizeBytes();
231 void *ptr = malloc(eSize * count);
232 copyWithPadding(ptr, data, eSize / 4, count);
233 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
234 count, ptr, count * mType->getElement()->getSizeBytes()));
235 free(ptr);
236 } else {
237 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
238 count, data, count * mType->getElement()->getSizeBytes()));
239 }
240 }
241
copy1DRangeTo(uint32_t off,size_t count,void * data)242 void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) {
243 if(count < 1) {
244 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
245 return;
246 }
247 if((off + count) > mCurrentCount) {
248 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off);
249 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
250 return;
251 }
252 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
253 size_t eSize = mType->getElement()->getSizeBytes();
254 void *ptr = malloc(eSize * count);
255 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
256 count, ptr, count * mType->getElement()->getSizeBytes()));
257 copyWithUnPadding(data, ptr, eSize / 4, count);
258 free(ptr);
259 } else {
260 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
261 count, data, count * mType->getElement()->getSizeBytes()));
262 }
263 }
264
copy1DRangeFrom(uint32_t off,size_t count,sp<const Allocation> data,uint32_t dataOff)265 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data,
266 uint32_t dataOff) {
267
268 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0,
269 mSelectedLOD, mSelectedFace,
270 count, 1, data->getIDSafe(), dataOff, 0,
271 data->mSelectedLOD, data->mSelectedFace));
272 }
273
copy1DFrom(const void * data)274 void Allocation::copy1DFrom(const void* data) {
275 copy1DRangeFrom(0, mCurrentCount, data);
276 }
277
copy1DTo(void * data)278 void Allocation::copy1DTo(void* data) {
279 copy1DRangeTo(0, mCurrentCount, data);
280 }
281
282
validate2DRange(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h)283 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
284 if (mAdaptedAllocation != nullptr) {
285
286 } else {
287 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
288 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
289 }
290 }
291 }
292
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const void * data)293 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
294 const void *data) {
295 validate2DRange(xoff, yoff, w, h);
296 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
297 size_t eSize = mType->getElement()->getSizeBytes();
298 void *ptr = malloc(eSize * w * h);
299 copyWithPadding(ptr, data, eSize / 4, w * h);
300 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff,
301 yoff, mSelectedLOD, mSelectedFace,
302 w, h, ptr, w * h * mType->getElement()->getSizeBytes(),
303 w * mType->getElement()->getSizeBytes()));
304 free(ptr);
305 } else {
306 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff,
307 yoff, mSelectedLOD, mSelectedFace,
308 w, h, data, w * h * mType->getElement()->getSizeBytes(),
309 w * mType->getElement()->getSizeBytes()));
310 }
311 }
312
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,sp<const Allocation> data,uint32_t dataXoff,uint32_t dataYoff)313 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
314 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) {
315 validate2DRange(xoff, yoff, w, h);
316 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff,
317 mSelectedLOD, mSelectedFace,
318 w, h, data->getIDSafe(), dataXoff, dataYoff,
319 data->mSelectedLOD, data->mSelectedFace));
320 }
321
copy2DRangeTo(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,void * data)322 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
323 void* data) {
324 validate2DRange(xoff, yoff, w, h);
325 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
326 size_t eSize = mType->getElement()->getSizeBytes();
327 void *ptr = malloc(eSize * w * h);
328 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
329 mSelectedLOD, mSelectedFace, w, h, ptr,
330 w * h * mType->getElement()->getSizeBytes(),
331 w * mType->getElement()->getSizeBytes()));
332 copyWithUnPadding(data, ptr, eSize / 4, w * h);
333 free(ptr);
334 } else {
335 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
336 mSelectedLOD, mSelectedFace, w, h, data,
337 w * h * mType->getElement()->getSizeBytes(),
338 w * mType->getElement()->getSizeBytes()));
339 }
340 }
341
copy2DStridedFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const void * data,size_t stride)342 void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
343 const void *data, size_t stride) {
344 validate2DRange(xoff, yoff, w, h);
345 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff,
346 mSelectedLOD, mSelectedFace, w, h, data,
347 w * h * mType->getElement()->getSizeBytes(), stride));
348 }
349
copy2DStridedFrom(const void * data,size_t stride)350 void Allocation::copy2DStridedFrom(const void* data, size_t stride) {
351 copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
352 }
353
copy2DStridedTo(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,void * data,size_t stride)354 void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
355 void *data, size_t stride) {
356 validate2DRange(xoff, yoff, w, h);
357 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
358 mSelectedLOD, mSelectedFace, w, h, data,
359 w * h * mType->getElement()->getSizeBytes(), stride));
360 }
361
copy2DStridedTo(void * data,size_t stride)362 void Allocation::copy2DStridedTo(void* data, size_t stride) {
363 copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
364 }
365
validate3DRange(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d)366 void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
367 uint32_t h, uint32_t d) {
368 if (mAdaptedAllocation != nullptr) {
369
370 } else {
371 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
372 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
373 }
374 }
375 }
376
copy3DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d,const void * data)377 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
378 uint32_t h, uint32_t d, const void* data) {
379 validate3DRange(xoff, yoff, zoff, w, h, d);
380 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
381 size_t eSize = mType->getElement()->getSizeBytes();
382 void *ptr = malloc(eSize * w * h * d);
383 copyWithPadding(ptr, data, eSize / 4, w * h * d);
384 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
385 mSelectedLOD, w, h, d, ptr,
386 w * h * d * mType->getElement()->getSizeBytes(),
387 w * mType->getElement()->getSizeBytes()));
388 free(ptr);
389 } else {
390 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
391 mSelectedLOD, w, h, d, data,
392 w * h * d * mType->getElement()->getSizeBytes(),
393 w * mType->getElement()->getSizeBytes()));
394 }
395 }
396
copy3DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d,sp<const Allocation> data,uint32_t dataXoff,uint32_t dataYoff,uint32_t dataZoff)397 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d,
398 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) {
399 validate3DRange(xoff, yoff, zoff, w, h, d);
400 tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
401 mSelectedLOD, w, h, d, data->getIDSafe(),
402 dataXoff, dataYoff, dataZoff, data->mSelectedLOD));
403 }
404
copy3DRangeTo(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d,void * data)405 void Allocation::copy3DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
406 uint32_t h, uint32_t d, void* data) {
407 validate3DRange(xoff, yoff, zoff, w, h, d);
408 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
409 size_t eSize = mType->getElement()->getSizeBytes();
410 void *ptr = malloc(eSize * w * h * d);
411 tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
412 mSelectedLOD, w, h, d, ptr,
413 w * h * d * mType->getElement()->getSizeBytes(),
414 w * mType->getElement()->getSizeBytes()));
415 copyWithUnPadding(data, ptr, eSize / 4, w * h * d);
416 free(ptr);
417 } else {
418 tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
419 mSelectedLOD, w, h, d, data,
420 w * h * d * mType->getElement()->getSizeBytes(),
421 w * mType->getElement()->getSizeBytes()));
422 }
423 }
424
createTyped(sp<RS> rs,sp<const Type> type,RsAllocationMipmapControl mipmaps,uint32_t usage)425 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
426 RsAllocationMipmapControl mipmaps, uint32_t usage) {
427 void *id = 0;
428 if (rs->getError() == RS_SUCCESS) {
429 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 0);
430 }
431 if (id == 0) {
432 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
433 return nullptr;
434 }
435 return new Allocation(id, rs, type, usage);
436 }
437
createTyped(sp<RS> rs,sp<const Type> type,RsAllocationMipmapControl mipmaps,uint32_t usage,void * pointer)438 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
439 RsAllocationMipmapControl mipmaps, uint32_t usage,
440 void *pointer) {
441 void *id = 0;
442 if (rs->getError() == RS_SUCCESS) {
443 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage,
444 (uintptr_t)pointer);
445 }
446 if (id == 0) {
447 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
448 return nullptr;
449 }
450 return new Allocation(id, rs, type, usage);
451 }
452
createTyped(sp<RS> rs,sp<const Type> type,uint32_t usage)453 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
454 uint32_t usage) {
455 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
456 }
457
createSized(sp<RS> rs,sp<const Element> e,size_t count,uint32_t usage)458 sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e,
459 size_t count, uint32_t usage) {
460 Type::Builder b(rs, e);
461 b.setX(count);
462 sp<const Type> t = b.create();
463
464 return createTyped(rs, t, usage);
465 }
466
createSized2D(sp<RS> rs,sp<const Element> e,size_t x,size_t y,uint32_t usage)467 sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e,
468 size_t x, size_t y, uint32_t usage) {
469 Type::Builder b(rs, e);
470 b.setX(x);
471 b.setY(y);
472 sp<const Type> t = b.create();
473
474 return createTyped(rs, t, usage);
475 }
476
ioSendOutput()477 void Allocation::ioSendOutput() {
478 #ifndef RS_COMPATIBILITY_LIB
479 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
480 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified.");
481 return;
482 }
483 tryDispatch(mRS, RS::dispatch->AllocationIoSend(mRS->getContext(), getID()));
484 #endif
485 }
486
ioGetInput()487 void Allocation::ioGetInput() {
488 #ifndef RS_COMPATIBILITY_LIB
489 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
490 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get buffer if IO_INPUT usage specified.");
491 return;
492 }
493 tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID()));
494 #endif
495 }
496
497 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
498 #include <gui/Surface.h>
499
getSurface()500 RSC::sp<Surface> Allocation::getSurface() {
501 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
502 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get Surface if IO_INPUT usage specified.");
503 return nullptr;
504 }
505 IGraphicBufferProducer *v = (IGraphicBufferProducer *)RS::dispatch->AllocationGetSurface(mRS->getContext(),
506 getID());
507 android::sp<IGraphicBufferProducer> bp = v;
508 v->decStrong(nullptr);
509
510 return new Surface(bp, true);;
511 }
512
setSurface(RSC::sp<Surface> s)513 void Allocation::setSurface(RSC::sp<Surface> s) {
514 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
515 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only set Surface if IO_OUTPUT usage specified.");
516 return;
517 }
518 tryDispatch(mRS, RS::dispatch->AllocationSetSurface(mRS->getContext(), getID(),
519 static_cast<ANativeWindow *>(s.get())));
520 }
521
522 #endif
523
524