• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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