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