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<Type> t = new Type((void *)typeID, mRS);
147 t->updateFromNative();
148 updateCacheInfo(t);
149 mType = t;
150 }
151 }
152
syncAll(RsAllocationUsageType srcLocation)153 void Allocation::syncAll(RsAllocationUsageType srcLocation) {
154 switch (srcLocation) {
155 case RS_ALLOCATION_USAGE_SCRIPT:
156 case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
157 case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
158 case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
159 case RS_ALLOCATION_USAGE_SHARED:
160 break;
161 default:
162 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Source must be exactly one usage type.");
163 return;
164 }
165 tryDispatch(mRS, RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation));
166 }
167
getPointer(size_t * stride)168 void * Allocation::getPointer(size_t *stride) {
169 void *p = nullptr;
170 if (!(mUsage & RS_ALLOCATION_USAGE_SHARED)) {
171 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Allocation does not support USAGE_SHARED.");
172 return nullptr;
173 }
174
175 // FIXME: decide if lack of getPointer should cause compat mode
176 if (RS::dispatch->AllocationGetPointer == nullptr) {
177 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Can't use getPointer on older APIs");
178 return nullptr;
179 }
180
181 p = RS::dispatch->AllocationGetPointer(mRS->getContext(), getIDSafe(), 0,
182 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0, stride, sizeof(size_t));
183 if (mRS->getError() != RS_SUCCESS) {
184 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation lock failed");
185 p = nullptr;
186 }
187 return p;
188 }
189
190 // ---------------------------------------------------------------------------
191 //Functions needed for autopadding & unpadding
copyWithPadding(void * ptr,const void * srcPtr,int mSize,int count)192 static void copyWithPadding(void* ptr, const void* srcPtr, int mSize, int count) {
193 int sizeBytesPad = mSize * 4;
194 int sizeBytes = mSize * 3;
195 uint8_t *dst = static_cast<uint8_t *>(ptr);
196 const uint8_t *src = static_cast<const uint8_t *>(srcPtr);
197 for (int i = 0; i < count; i++) {
198 memcpy(dst, src, sizeBytes);
199 dst += sizeBytesPad;
200 src += sizeBytes;
201 }
202 }
203
copyWithUnPadding(void * ptr,const void * srcPtr,int mSize,int count)204 static void copyWithUnPadding(void* ptr, const void* srcPtr, int mSize, int count) {
205 int sizeBytesPad = mSize * 4;
206 int sizeBytes = mSize * 3;
207 uint8_t *dst = static_cast<uint8_t *>(ptr);
208 const uint8_t *src = static_cast<const uint8_t *>(srcPtr);
209 for (int i = 0; i < count; i++) {
210 memcpy(dst, src, sizeBytes);
211 dst += sizeBytes;
212 src += sizeBytesPad;
213 }
214 }
215 // ---------------------------------------------------------------------------
216
copy1DRangeFrom(uint32_t off,size_t count,const void * data)217 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) {
218
219 if(count < 1) {
220 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
221 return;
222 }
223 if((off + count) > mCurrentCount) {
224 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off);
225 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
226 return;
227 }
228 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
229 size_t eSize = mType->getElement()->getSizeBytes();
230 void *ptr = malloc(eSize * count);
231 copyWithPadding(ptr, data, eSize / 4, count);
232 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
233 count, ptr, count * mType->getElement()->getSizeBytes()));
234 free(ptr);
235 } else {
236 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
237 count, data, count * mType->getElement()->getSizeBytes()));
238 }
239 }
240
copy1DRangeTo(uint32_t off,size_t count,void * data)241 void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) {
242 if(count < 1) {
243 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
244 return;
245 }
246 if((off + count) > mCurrentCount) {
247 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off);
248 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
249 return;
250 }
251 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
252 size_t eSize = mType->getElement()->getSizeBytes();
253 void *ptr = malloc(eSize * count);
254 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
255 count, ptr, count * mType->getElement()->getSizeBytes()));
256 copyWithUnPadding(data, ptr, eSize / 4, count);
257 free(ptr);
258 } else {
259 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
260 count, data, count * mType->getElement()->getSizeBytes()));
261 }
262 }
263
copy1DRangeFrom(uint32_t off,size_t count,sp<const Allocation> data,uint32_t dataOff)264 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data,
265 uint32_t dataOff) {
266
267 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0,
268 mSelectedLOD, mSelectedFace,
269 count, 1, data->getIDSafe(), dataOff, 0,
270 data->mSelectedLOD, data->mSelectedFace));
271 }
272
copy1DFrom(const void * data)273 void Allocation::copy1DFrom(const void* data) {
274 copy1DRangeFrom(0, mCurrentCount, data);
275 }
276
copy1DTo(void * data)277 void Allocation::copy1DTo(void* data) {
278 copy1DRangeTo(0, mCurrentCount, data);
279 }
280
281
validate2DRange(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h)282 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
283 if (mAdaptedAllocation != nullptr) {
284
285 } else {
286 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
287 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
288 }
289 }
290 }
291
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const void * data)292 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
293 const void *data) {
294 validate2DRange(xoff, yoff, w, h);
295 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
296 size_t eSize = mType->getElement()->getSizeBytes();
297 void *ptr = malloc(eSize * w * h);
298 copyWithPadding(ptr, data, eSize / 4, w * h);
299 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff,
300 yoff, mSelectedLOD, mSelectedFace,
301 w, h, ptr, w * h * mType->getElement()->getSizeBytes(),
302 w * mType->getElement()->getSizeBytes()));
303 free(ptr);
304 } else {
305 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff,
306 yoff, mSelectedLOD, mSelectedFace,
307 w, h, data, w * h * mType->getElement()->getSizeBytes(),
308 w * mType->getElement()->getSizeBytes()));
309 }
310 }
311
copy2DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,sp<const Allocation> data,uint32_t dataXoff,uint32_t dataYoff)312 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
313 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) {
314 validate2DRange(xoff, yoff, w, h);
315 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff,
316 mSelectedLOD, mSelectedFace,
317 w, h, data->getIDSafe(), dataXoff, dataYoff,
318 data->mSelectedLOD, data->mSelectedFace));
319 }
320
copy2DRangeTo(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,void * data)321 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
322 void* data) {
323 validate2DRange(xoff, yoff, w, h);
324 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
325 size_t eSize = mType->getElement()->getSizeBytes();
326 void *ptr = malloc(eSize * w * h);
327 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
328 mSelectedLOD, mSelectedFace, w, h, ptr,
329 w * h * mType->getElement()->getSizeBytes(),
330 w * mType->getElement()->getSizeBytes()));
331 copyWithUnPadding(data, ptr, eSize / 4, w * h);
332 free(ptr);
333 } else {
334 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
335 mSelectedLOD, mSelectedFace, w, h, data,
336 w * h * mType->getElement()->getSizeBytes(),
337 w * mType->getElement()->getSizeBytes()));
338 }
339 }
340
copy2DStridedFrom(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,const void * data,size_t stride)341 void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
342 const void *data, size_t stride) {
343 validate2DRange(xoff, yoff, w, h);
344 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff,
345 mSelectedLOD, mSelectedFace, w, h, data,
346 w * h * mType->getElement()->getSizeBytes(), stride));
347 }
348
copy2DStridedFrom(const void * data,size_t stride)349 void Allocation::copy2DStridedFrom(const void* data, size_t stride) {
350 copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
351 }
352
copy2DStridedTo(uint32_t xoff,uint32_t yoff,uint32_t w,uint32_t h,void * data,size_t stride)353 void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
354 void *data, size_t stride) {
355 validate2DRange(xoff, yoff, w, h);
356 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
357 mSelectedLOD, mSelectedFace, w, h, data,
358 w * h * mType->getElement()->getSizeBytes(), stride));
359 }
360
copy2DStridedTo(void * data,size_t stride)361 void Allocation::copy2DStridedTo(void* data, size_t stride) {
362 copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
363 }
364
validate3DRange(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d)365 void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
366 uint32_t h, uint32_t d) {
367 if (mAdaptedAllocation != nullptr) {
368
369 } else {
370 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
371 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
372 }
373 }
374 }
375
copy3DRangeFrom(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d,const void * data)376 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
377 uint32_t h, uint32_t d, const void* data) {
378 validate3DRange(xoff, yoff, zoff, w, h, d);
379 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
380 size_t eSize = mType->getElement()->getSizeBytes();
381 void *ptr = malloc(eSize * w * h * d);
382 copyWithPadding(ptr, data, eSize / 4, w * h * d);
383 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
384 mSelectedLOD, w, h, d, ptr,
385 w * h * d * mType->getElement()->getSizeBytes(),
386 w * mType->getElement()->getSizeBytes()));
387 free(ptr);
388 } else {
389 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
390 mSelectedLOD, w, h, d, data,
391 w * h * d * mType->getElement()->getSizeBytes(),
392 w * mType->getElement()->getSizeBytes()));
393 }
394 }
395
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)396 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d,
397 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) {
398 validate3DRange(xoff, yoff, zoff, w, h, d);
399 tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
400 mSelectedLOD, w, h, d, data->getIDSafe(),
401 dataXoff, dataYoff, dataZoff, data->mSelectedLOD));
402 }
403
copy3DRangeTo(uint32_t xoff,uint32_t yoff,uint32_t zoff,uint32_t w,uint32_t h,uint32_t d,void * data)404 void Allocation::copy3DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
405 uint32_t h, uint32_t d, void* data) {
406 validate3DRange(xoff, yoff, zoff, w, h, d);
407 if (mAutoPadding && (mType->getElement()->getVectorSize() == 3)) {
408 size_t eSize = mType->getElement()->getSizeBytes();
409 void *ptr = malloc(eSize * w * h * d);
410 tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
411 mSelectedLOD, w, h, d, ptr,
412 w * h * d * mType->getElement()->getSizeBytes(),
413 w * mType->getElement()->getSizeBytes()));
414 copyWithUnPadding(data, ptr, eSize / 4, w * h * d);
415 free(ptr);
416 } else {
417 tryDispatch(mRS, RS::dispatch->Allocation3DRead(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
418 mSelectedLOD, w, h, d, data,
419 w * h * d * mType->getElement()->getSizeBytes(),
420 w * mType->getElement()->getSizeBytes()));
421 }
422 }
423
createTyped(sp<RS> rs,sp<const Type> type,RsAllocationMipmapControl mipmaps,uint32_t usage)424 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
425 RsAllocationMipmapControl mipmaps, uint32_t usage) {
426 void *id = 0;
427 if (rs->getError() == RS_SUCCESS) {
428 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 0);
429 }
430 if (id == 0) {
431 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
432 return nullptr;
433 }
434 return new Allocation(id, rs, type, usage);
435 }
436
createTyped(sp<RS> rs,sp<const Type> type,RsAllocationMipmapControl mipmaps,uint32_t usage,void * pointer)437 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
438 RsAllocationMipmapControl mipmaps, uint32_t usage,
439 void *pointer) {
440 void *id = 0;
441 if (rs->getError() == RS_SUCCESS) {
442 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage,
443 (uintptr_t)pointer);
444 }
445 if (id == 0) {
446 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
447 return nullptr;
448 }
449 return new Allocation(id, rs, type, usage);
450 }
451
createTyped(sp<RS> rs,sp<const Type> type,uint32_t usage)452 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
453 uint32_t usage) {
454 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
455 }
456
createSized(sp<RS> rs,sp<const Element> e,size_t count,uint32_t usage)457 sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e,
458 size_t count, uint32_t usage) {
459 Type::Builder b(rs, e);
460 b.setX(count);
461 sp<const Type> t = b.create();
462
463 return createTyped(rs, t, usage);
464 }
465
createSized2D(sp<RS> rs,sp<const Element> e,size_t x,size_t y,uint32_t usage)466 sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e,
467 size_t x, size_t y, uint32_t usage) {
468 Type::Builder b(rs, e);
469 b.setX(x);
470 b.setY(y);
471 sp<const Type> t = b.create();
472
473 return createTyped(rs, t, usage);
474 }
475
ioSendOutput()476 void Allocation::ioSendOutput() {
477 #ifndef RS_COMPATIBILITY_LIB
478 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
479 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified.");
480 return;
481 }
482 tryDispatch(mRS, RS::dispatch->AllocationIoSend(mRS->getContext(), getID()));
483 #endif
484 }
485
ioGetInput()486 void Allocation::ioGetInput() {
487 #ifndef RS_COMPATIBILITY_LIB
488 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
489 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get buffer if IO_INPUT usage specified.");
490 return;
491 }
492 tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID()));
493 #endif
494 }
495
496 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
497 #include <gui/Surface.h>
498
getSurface()499 RSC::sp<Surface> Allocation::getSurface() {
500 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
501 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get Surface if IO_INPUT usage specified.");
502 return nullptr;
503 }
504 IGraphicBufferProducer *v = (IGraphicBufferProducer *)RS::dispatch->AllocationGetSurface(mRS->getContext(),
505 getID());
506 android::sp<IGraphicBufferProducer> bp = v;
507 v->decStrong(nullptr);
508
509 return new Surface(bp, true);;
510 }
511
setSurface(RSC::sp<Surface> s)512 void Allocation::setSurface(RSC::sp<Surface> s) {
513 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
514 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only set Surface if IO_OUTPUT usage specified.");
515 return;
516 }
517 tryDispatch(mRS, RS::dispatch->AllocationSetSurface(mRS->getContext(), getID(),
518 static_cast<ANativeWindow *>(s.get())));
519 }
520
521 #endif
522
523