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 using android::Surface;
23 
getIDSafe() const24 void * Allocation::getIDSafe() const {
25     return getID();
26 }
27 
updateCacheInfo(const sp<const Type> & t)28 void Allocation::updateCacheInfo(const 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,const sp<const Allocation> & data,uint32_t dataOff)264 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const 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,const 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                                  const 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,const 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                                  const 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(const sp<RS> & rs,const sp<const Type> & type,RsAllocationMipmapControl mipmaps,uint32_t usage)424 sp<Allocation> Allocation::createTyped(const sp<RS>& rs, const 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(const sp<RS> & rs,const sp<const Type> & type,RsAllocationMipmapControl mipmaps,uint32_t usage,void * pointer)437 sp<Allocation> Allocation::createTyped(const sp<RS>& rs, const 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(const sp<RS> & rs,const sp<const Type> & type,uint32_t usage)452 sp<Allocation> Allocation::createTyped(const sp<RS>& rs, const sp<const Type>& type,
453                                     uint32_t usage) {
454     return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
455 }
456 
createSized(const sp<RS> & rs,const sp<const Element> & e,size_t count,uint32_t usage)457 sp<Allocation> Allocation::createSized(const sp<RS>& rs, const 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(const sp<RS> & rs,const sp<const Element> & e,size_t x,size_t y,uint32_t usage)466 sp<Allocation> Allocation::createSized2D(const sp<RS>& rs, const 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 #ifndef RS_COMPATIBILITY_LIB
497 #include <gui/Surface.h>
498 
getSurface()499 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     ANativeWindow *anw = (ANativeWindow *)RS::dispatch->AllocationGetSurface(mRS->getContext(),
505                                                                              getID());
506     sp<Surface> surface(static_cast<Surface*>(anw));
507     return surface;
508 }
509 
setSurface(const sp<Surface> & s)510 void Allocation::setSurface(const sp<Surface>& s) {
511     if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
512         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only set Surface if IO_OUTPUT usage specified.");
513         return;
514     }
515     tryDispatch(mRS, RS::dispatch->AllocationSetSurface(mRS->getContext(), getID(),
516                                                         static_cast<ANativeWindow *>(s.get())));
517 }
518 
519 #endif
520 
521