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