• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008-2012 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 package android.renderscript;
18 
19 import java.io.IOException;
20 import java.io.InputStream;
21 import android.content.res.Resources;
22 import android.content.res.AssetManager;
23 import android.graphics.Bitmap;
24 import android.graphics.BitmapFactory;
25 import android.view.Surface;
26 import android.graphics.SurfaceTexture;
27 import android.util.Log;
28 import android.util.TypedValue;
29 
30 /**
31  * <p>
32  * Memory allocation class for renderscript.  An allocation combines a
33  * {@link android.renderscript.Type} with the memory to provide storage for user data and objects.
34  * This implies that all memory in Renderscript is typed.
35  * </p>
36  *
37  * <p>Allocations are the primary way data moves into and out of scripts. Memory is user
38  * synchronized and it's possible for allocations to exist in multiple memory spaces
39  * concurrently. Currently those spaces are:</p>
40  * <ul>
41  * <li>Script: accessable by RS scripts.</li>
42  * <li>Graphics Texture: accessable as a graphics texture.</li>
43  * <li>Graphics Vertex: accessable as graphical vertex data.</li>
44  * <li>Graphics Constants: Accessable as constants in user shaders</li>
45  * </ul>
46  * </p>
47  * <p>
48  * For example, when creating a allocation for a texture, the user can
49  * specify its memory spaces as both script and textures. This means that it can both
50  * be used as script binding and as a GPU texture for rendering. To maintain
51  * synchronization if a script modifies an allocation used by other targets it must
52  * call a synchronizing function to push the updates to the memory, otherwise the results
53  * are undefined.
54  * </p>
55  * <p>By default, Android system side updates are always applied to the script accessable
56  * memory. If this is not present, they are then applied to the various HW
57  * memory types.  A {@link android.renderscript.Allocation#syncAll syncAll()}
58  * call is necessary after the script data is updated to
59  * keep the other memory spaces in sync.</p>
60  *
61  * <p>Allocation data is uploaded in one of two primary ways. For simple
62  * arrays there are copyFrom() functions that take an array from the control code and
63  * copy it to the slave memory store. Both type checked and unchecked copies are provided.
64  * The unchecked variants exist to allow apps to copy over arrays of structures from a
65  * control language that does not support structures.</p>
66  *
67  * <div class="special reference">
68  * <h3>Developer Guides</h3>
69  * <p>For more information about creating an application that uses Renderscript, read the
70  * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
71  * </div>
72  **/
73 public class Allocation extends BaseObj {
74     Type mType;
75     Bitmap mBitmap;
76     int mUsage;
77     Allocation mAdaptedAllocation;
78 
79     boolean mConstrainedLOD;
80     boolean mConstrainedFace;
81     boolean mConstrainedY;
82     boolean mConstrainedZ;
83     boolean mReadAllowed = true;
84     boolean mWriteAllowed = true;
85     int mSelectedY;
86     int mSelectedZ;
87     int mSelectedLOD;
88     Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
89 
90     int mCurrentDimX;
91     int mCurrentDimY;
92     int mCurrentDimZ;
93     int mCurrentCount;
94 
95 
96     /**
97      * The usage of the allocation.  These signal to renderscript
98      * where to place the allocation in memory.
99      *
100      * SCRIPT The allocation will be bound to and accessed by
101      * scripts.
102      */
103     public static final int USAGE_SCRIPT = 0x0001;
104 
105     /**
106      * GRAPHICS_TEXTURE The allocation will be used as a texture
107      * source by one or more graphics programs.
108      *
109      */
110     public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
111 
112     /**
113      * GRAPHICS_VERTEX The allocation will be used as a graphics
114      * mesh.
115      *
116      */
117     public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
118 
119 
120     /**
121      * GRAPHICS_CONSTANTS The allocation will be used as the source
122      * of shader constants by one or more programs.
123      *
124      */
125     public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
126 
127     /**
128      * USAGE_GRAPHICS_RENDER_TARGET The allocation will be used as a
129      * target for offscreen rendering
130      *
131      */
132     public static final int USAGE_GRAPHICS_RENDER_TARGET = 0x0010;
133 
134     /**
135      * USAGE_IO_INPUT The allocation will be used as SurfaceTexture
136      * consumer.  This usage will cause the allocation to be created
137      * read only.
138      *
139      */
140     public static final int USAGE_IO_INPUT = 0x0020;
141 
142     /**
143      * USAGE_IO_OUTPUT The allocation will be used as a
144      * SurfaceTexture producer.  The dimensions and format of the
145      * SurfaceTexture will be forced to those of the allocation.
146      *
147      */
148     public static final int USAGE_IO_OUTPUT = 0x0040;
149 
150     /**
151      * Controls mipmap behavior when using the bitmap creation and
152      * update functions.
153      */
154     public enum MipmapControl {
155         /**
156          * No mipmaps will be generated and the type generated from the
157          * incoming bitmap will not contain additional LODs.
158          */
159         MIPMAP_NONE(0),
160 
161         /**
162          * A Full mipmap chain will be created in script memory.  The
163          * type of the allocation will contain a full mipmap chain.  On
164          * upload to graphics the full chain will be transfered.
165          */
166         MIPMAP_FULL(1),
167 
168         /**
169          * The type of the allocation will be the same as MIPMAP_NONE.
170          * It will not contain mipmaps.  On upload to graphics the
171          * graphics copy of the allocation data will contain a full
172          * mipmap chain generated from the top level in script memory.
173          */
174         MIPMAP_ON_SYNC_TO_TEXTURE(2);
175 
176         int mID;
MipmapControl(int id)177         MipmapControl(int id) {
178             mID = id;
179         }
180     }
181 
182 
getIDSafe()183     private int getIDSafe() {
184         if (mAdaptedAllocation != null) {
185             return mAdaptedAllocation.getID(mRS);
186         }
187         return getID(mRS);
188     }
189 
190 
191    /**
192      * Get the element of the type of the Allocation.
193      *
194      * @return Element that describes the structure of data in the
195      *         allocation
196      *
197      */
getElement()198     public Element getElement() {
199         return mType.getElement();
200     }
201 
202     /**
203      * Get the usage flags of the Allocation.
204      *
205      * @return usage flags associated with the allocation. e.g.
206      *         script, texture, etc.
207      *
208      */
getUsage()209     public int getUsage() {
210         return mUsage;
211     }
212 
213     /**
214      * Get the size of the Allocation in bytes.
215      *
216      * @return size of the Allocation in bytes.
217      *
218      */
getBytesSize()219     public int getBytesSize() {
220         return mType.getCount() * mType.getElement().getBytesSize();
221     }
222 
updateCacheInfo(Type t)223     private void updateCacheInfo(Type t) {
224         mCurrentDimX = t.getX();
225         mCurrentDimY = t.getY();
226         mCurrentDimZ = t.getZ();
227         mCurrentCount = mCurrentDimX;
228         if (mCurrentDimY > 1) {
229             mCurrentCount *= mCurrentDimY;
230         }
231         if (mCurrentDimZ > 1) {
232             mCurrentCount *= mCurrentDimZ;
233         }
234     }
235 
Allocation(int id, RenderScript rs, Type t, int usage)236     Allocation(int id, RenderScript rs, Type t, int usage) {
237         super(id, rs);
238         if ((usage & ~(USAGE_SCRIPT |
239                        USAGE_GRAPHICS_TEXTURE |
240                        USAGE_GRAPHICS_VERTEX |
241                        USAGE_GRAPHICS_CONSTANTS |
242                        USAGE_GRAPHICS_RENDER_TARGET |
243                        USAGE_IO_INPUT |
244                        USAGE_IO_OUTPUT)) != 0) {
245             throw new RSIllegalArgumentException("Unknown usage specified.");
246         }
247 
248         if ((usage & USAGE_IO_INPUT) != 0) {
249             mWriteAllowed = false;
250 
251             if ((usage & ~(USAGE_IO_INPUT |
252                            USAGE_GRAPHICS_TEXTURE |
253                            USAGE_SCRIPT)) != 0) {
254                 throw new RSIllegalArgumentException("Invalid usage combination.");
255             }
256         }
257 
258         mType = t;
259         mUsage = usage;
260 
261         if (t != null) {
262             updateCacheInfo(t);
263         }
264     }
265 
validateIsInt32()266     private void validateIsInt32() {
267         if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
268             (mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
269             return;
270         }
271         throw new RSIllegalArgumentException(
272             "32 bit integer source does not match allocation type " + mType.mElement.mType);
273     }
274 
validateIsInt16()275     private void validateIsInt16() {
276         if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
277             (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
278             return;
279         }
280         throw new RSIllegalArgumentException(
281             "16 bit integer source does not match allocation type " + mType.mElement.mType);
282     }
283 
validateIsInt8()284     private void validateIsInt8() {
285         if ((mType.mElement.mType == Element.DataType.SIGNED_8) ||
286             (mType.mElement.mType == Element.DataType.UNSIGNED_8)) {
287             return;
288         }
289         throw new RSIllegalArgumentException(
290             "8 bit integer source does not match allocation type " + mType.mElement.mType);
291     }
292 
validateIsFloat32()293     private void validateIsFloat32() {
294         if (mType.mElement.mType == Element.DataType.FLOAT_32) {
295             return;
296         }
297         throw new RSIllegalArgumentException(
298             "32 bit float source does not match allocation type " + mType.mElement.mType);
299     }
300 
validateIsObject()301     private void validateIsObject() {
302         if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
303             (mType.mElement.mType == Element.DataType.RS_TYPE) ||
304             (mType.mElement.mType == Element.DataType.RS_ALLOCATION) ||
305             (mType.mElement.mType == Element.DataType.RS_SAMPLER) ||
306             (mType.mElement.mType == Element.DataType.RS_SCRIPT) ||
307             (mType.mElement.mType == Element.DataType.RS_MESH) ||
308             (mType.mElement.mType == Element.DataType.RS_PROGRAM_FRAGMENT) ||
309             (mType.mElement.mType == Element.DataType.RS_PROGRAM_VERTEX) ||
310             (mType.mElement.mType == Element.DataType.RS_PROGRAM_RASTER) ||
311             (mType.mElement.mType == Element.DataType.RS_PROGRAM_STORE)) {
312             return;
313         }
314         throw new RSIllegalArgumentException(
315             "Object source does not match allocation type " + mType.mElement.mType);
316     }
317 
318     @Override
updateFromNative()319     void updateFromNative() {
320         super.updateFromNative();
321         int typeID = mRS.nAllocationGetType(getID(mRS));
322         if(typeID != 0) {
323             mType = new Type(typeID, mRS);
324             mType.updateFromNative();
325             updateCacheInfo(mType);
326         }
327     }
328 
329     /**
330      * Get the type of the Allocation.
331      *
332      * @return Type
333      *
334      */
getType()335     public Type getType() {
336         return mType;
337     }
338 
339     /**
340      * Propagate changes from one usage of the allocation to the
341      * remaining usages of the allocation.
342      *
343      */
syncAll(int srcLocation)344     public void syncAll(int srcLocation) {
345         switch (srcLocation) {
346         case USAGE_SCRIPT:
347         case USAGE_GRAPHICS_CONSTANTS:
348         case USAGE_GRAPHICS_TEXTURE:
349         case USAGE_GRAPHICS_VERTEX:
350             break;
351         default:
352             throw new RSIllegalArgumentException("Source must be exactly one usage type.");
353         }
354         mRS.validate();
355         mRS.nAllocationSyncAll(getIDSafe(), srcLocation);
356     }
357 
358     /**
359      * Send a buffer to the output stream.  The contents of the
360      * Allocation will be undefined after this operation.
361      *
362      */
ioSend()363     public void ioSend() {
364         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
365             throw new RSIllegalArgumentException(
366                 "Can only send buffer if IO_OUTPUT usage specified.");
367         }
368         mRS.validate();
369         mRS.nAllocationIoSend(getID(mRS));
370     }
371 
372     /**
373      * Delete once code is updated.
374      * @hide
375      */
ioSendOutput()376     public void ioSendOutput() {
377         ioSend();
378     }
379 
380     /**
381      * Receive the latest input into the Allocation.
382      *
383      */
ioReceive()384     public void ioReceive() {
385         if ((mUsage & USAGE_IO_INPUT) == 0) {
386             throw new RSIllegalArgumentException(
387                 "Can only receive if IO_INPUT usage specified.");
388         }
389         mRS.validate();
390         mRS.nAllocationIoReceive(getID(mRS));
391     }
392 
393     /**
394      * Copy an array of RS objects to the allocation.
395      *
396      * @param d Source array.
397      */
copyFrom(BaseObj[] d)398     public void copyFrom(BaseObj[] d) {
399         mRS.validate();
400         validateIsObject();
401         if (d.length != mCurrentCount) {
402             throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
403                                                  mCurrentCount + ", array length = " + d.length);
404         }
405         int i[] = new int[d.length];
406         for (int ct=0; ct < d.length; ct++) {
407             i[ct] = d[ct].getID(mRS);
408         }
409         copy1DRangeFromUnchecked(0, mCurrentCount, i);
410     }
411 
validateBitmapFormat(Bitmap b)412     private void validateBitmapFormat(Bitmap b) {
413         Bitmap.Config bc = b.getConfig();
414         switch (bc) {
415         case ALPHA_8:
416             if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
417                 throw new RSIllegalArgumentException("Allocation kind is " +
418                                                      mType.getElement().mKind + ", type " +
419                                                      mType.getElement().mType +
420                                                      " of " + mType.getElement().getBytesSize() +
421                                                      " bytes, passed bitmap was " + bc);
422             }
423             break;
424         case ARGB_8888:
425             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
426                 (mType.getElement().getBytesSize() != 4)) {
427                 throw new RSIllegalArgumentException("Allocation kind is " +
428                                                      mType.getElement().mKind + ", type " +
429                                                      mType.getElement().mType +
430                                                      " of " + mType.getElement().getBytesSize() +
431                                                      " bytes, passed bitmap was " + bc);
432             }
433             break;
434         case RGB_565:
435             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
436                 (mType.getElement().getBytesSize() != 2)) {
437                 throw new RSIllegalArgumentException("Allocation kind is " +
438                                                      mType.getElement().mKind + ", type " +
439                                                      mType.getElement().mType +
440                                                      " of " + mType.getElement().getBytesSize() +
441                                                      " bytes, passed bitmap was " + bc);
442             }
443             break;
444         case ARGB_4444:
445             if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
446                 (mType.getElement().getBytesSize() != 2)) {
447                 throw new RSIllegalArgumentException("Allocation kind is " +
448                                                      mType.getElement().mKind + ", type " +
449                                                      mType.getElement().mType +
450                                                      " of " + mType.getElement().getBytesSize() +
451                                                      " bytes, passed bitmap was " + bc);
452             }
453             break;
454 
455         }
456     }
457 
validateBitmapSize(Bitmap b)458     private void validateBitmapSize(Bitmap b) {
459         if((mCurrentDimX != b.getWidth()) || (mCurrentDimY != b.getHeight())) {
460             throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
461         }
462     }
463 
464     /**
465      * Copy an allocation from an array.  This variant is not type
466      * checked which allows an application to fill in structured
467      * data from an array.
468      *
469      * @param d the source data array
470      */
copyFromUnchecked(int[] d)471     public void copyFromUnchecked(int[] d) {
472         mRS.validate();
473         copy1DRangeFromUnchecked(0, mCurrentCount, d);
474     }
475     /**
476      * Copy an allocation from an array.  This variant is not type
477      * checked which allows an application to fill in structured
478      * data from an array.
479      *
480      * @param d the source data array
481      */
copyFromUnchecked(short[] d)482     public void copyFromUnchecked(short[] d) {
483         mRS.validate();
484         copy1DRangeFromUnchecked(0, mCurrentCount, d);
485     }
486     /**
487      * Copy an allocation from an array.  This variant is not type
488      * checked which allows an application to fill in structured
489      * data from an array.
490      *
491      * @param d the source data array
492      */
copyFromUnchecked(byte[] d)493     public void copyFromUnchecked(byte[] d) {
494         mRS.validate();
495         copy1DRangeFromUnchecked(0, mCurrentCount, d);
496     }
497     /**
498      * Copy an allocation from an array.  This variant is not type
499      * checked which allows an application to fill in structured
500      * data from an array.
501      *
502      * @param d the source data array
503      */
copyFromUnchecked(float[] d)504     public void copyFromUnchecked(float[] d) {
505         mRS.validate();
506         copy1DRangeFromUnchecked(0, mCurrentCount, d);
507     }
508 
509     /**
510      * Copy an allocation from an array.  This variant is type
511      * checked and will generate exceptions if the Allocation type
512      * is not a 32 bit integer type.
513      *
514      * @param d the source data array
515      */
copyFrom(int[] d)516     public void copyFrom(int[] d) {
517         mRS.validate();
518         copy1DRangeFrom(0, mCurrentCount, d);
519     }
520 
521     /**
522      * Copy an allocation from an array.  This variant is type
523      * checked and will generate exceptions if the Allocation type
524      * is not a 16 bit integer type.
525      *
526      * @param d the source data array
527      */
copyFrom(short[] d)528     public void copyFrom(short[] d) {
529         mRS.validate();
530         copy1DRangeFrom(0, mCurrentCount, d);
531     }
532 
533     /**
534      * Copy an allocation from an array.  This variant is type
535      * checked and will generate exceptions if the Allocation type
536      * is not a 8 bit integer type.
537      *
538      * @param d the source data array
539      */
copyFrom(byte[] d)540     public void copyFrom(byte[] d) {
541         mRS.validate();
542         copy1DRangeFrom(0, mCurrentCount, d);
543     }
544 
545     /**
546      * Copy an allocation from an array.  This variant is type
547      * checked and will generate exceptions if the Allocation type
548      * is not a 32 bit float type.
549      *
550      * @param d the source data array
551      */
copyFrom(float[] d)552     public void copyFrom(float[] d) {
553         mRS.validate();
554         copy1DRangeFrom(0, mCurrentCount, d);
555     }
556 
557     /**
558      * Copy an allocation from a bitmap.  The height, width, and
559      * format of the bitmap must match the existing allocation.
560      *
561      * @param b the source bitmap
562      */
copyFrom(Bitmap b)563     public void copyFrom(Bitmap b) {
564         mRS.validate();
565         validateBitmapSize(b);
566         validateBitmapFormat(b);
567         mRS.nAllocationCopyFromBitmap(getID(mRS), b);
568     }
569 
570     /**
571      * This is only intended to be used by auto-generate code reflected from the
572      * renderscript script files.
573      *
574      * @param xoff
575      * @param fp
576      */
setFromFieldPacker(int xoff, FieldPacker fp)577     public void setFromFieldPacker(int xoff, FieldPacker fp) {
578         mRS.validate();
579         int eSize = mType.mElement.getBytesSize();
580         final byte[] data = fp.getData();
581 
582         int count = data.length / eSize;
583         if ((eSize * count) != data.length) {
584             throw new RSIllegalArgumentException("Field packer length " + data.length +
585                                                " not divisible by element size " + eSize + ".");
586         }
587         copy1DRangeFromUnchecked(xoff, count, data);
588     }
589 
590     /**
591      * This is only intended to be used by auto-generate code reflected from the
592      * renderscript script files.
593      *
594      * @param xoff
595      * @param component_number
596      * @param fp
597      */
setFromFieldPacker(int xoff, int component_number, FieldPacker fp)598     public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
599         mRS.validate();
600         if (component_number >= mType.mElement.mElements.length) {
601             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
602         }
603         if(xoff < 0) {
604             throw new RSIllegalArgumentException("Offset must be >= 0.");
605         }
606 
607         final byte[] data = fp.getData();
608         int eSize = mType.mElement.mElements[component_number].getBytesSize();
609         eSize *= mType.mElement.mArraySizes[component_number];
610 
611         if (data.length != eSize) {
612             throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
613                                                " does not match component size " + eSize + ".");
614         }
615 
616         mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
617                                      component_number, data, data.length);
618     }
619 
data1DChecks(int off, int count, int len, int dataSize)620     private void data1DChecks(int off, int count, int len, int dataSize) {
621         mRS.validate();
622         if(off < 0) {
623             throw new RSIllegalArgumentException("Offset must be >= 0.");
624         }
625         if(count < 1) {
626             throw new RSIllegalArgumentException("Count must be >= 1.");
627         }
628         if((off + count) > mCurrentCount) {
629             throw new RSIllegalArgumentException("Overflow, Available count " + mCurrentCount +
630                                                ", got " + count + " at offset " + off + ".");
631         }
632         if(len < dataSize) {
633             throw new RSIllegalArgumentException("Array too small for allocation type.");
634         }
635     }
636 
637     /**
638      * Generate a mipmap chain.  Requires the type of the allocation
639      * include mipmaps.
640      *
641      * This function will generate a complete set of mipmaps from
642      * the top level lod and place them into the script memoryspace.
643      *
644      * If the allocation is also using other memory spaces a
645      * followup sync will be required.
646      */
generateMipmaps()647     public void generateMipmaps() {
648         mRS.nAllocationGenerateMipmaps(getID(mRS));
649     }
650 
651     /**
652      * Copy part of an allocation from an array.  This variant is
653      * not type checked which allows an application to fill in
654      * structured data from an array.
655      *
656      * @param off The offset of the first element to be copied.
657      * @param count The number of elements to be copied.
658      * @param d the source data array
659      */
copy1DRangeFromUnchecked(int off, int count, int[] d)660     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
661         int dataSize = mType.mElement.getBytesSize() * count;
662         data1DChecks(off, count, d.length * 4, dataSize);
663         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
664     }
665     /**
666      * Copy part of an allocation from an array.  This variant is
667      * not type checked which allows an application to fill in
668      * structured data from an array.
669      *
670      * @param off The offset of the first element to be copied.
671      * @param count The number of elements to be copied.
672      * @param d the source data array
673      */
copy1DRangeFromUnchecked(int off, int count, short[] d)674     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
675         int dataSize = mType.mElement.getBytesSize() * count;
676         data1DChecks(off, count, d.length * 2, dataSize);
677         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
678     }
679     /**
680      * Copy part of an allocation from an array.  This variant is
681      * not type checked which allows an application to fill in
682      * structured data from an array.
683      *
684      * @param off The offset of the first element to be copied.
685      * @param count The number of elements to be copied.
686      * @param d the source data array
687      */
copy1DRangeFromUnchecked(int off, int count, byte[] d)688     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
689         int dataSize = mType.mElement.getBytesSize() * count;
690         data1DChecks(off, count, d.length, dataSize);
691         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
692     }
693     /**
694      * Copy part of an allocation from an array.  This variant is
695      * not type checked which allows an application to fill in
696      * structured data from an array.
697      *
698      * @param off The offset of the first element to be copied.
699      * @param count The number of elements to be copied.
700      * @param d the source data array
701      */
copy1DRangeFromUnchecked(int off, int count, float[] d)702     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
703         int dataSize = mType.mElement.getBytesSize() * count;
704         data1DChecks(off, count, d.length * 4, dataSize);
705         mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize);
706     }
707 
708     /**
709      * Copy part of an allocation from an array.  This variant is
710      * type checked and will generate exceptions if the Allocation
711      * type is not a 32 bit integer type.
712      *
713      * @param off The offset of the first element to be copied.
714      * @param count The number of elements to be copied.
715      * @param d the source data array
716      */
copy1DRangeFrom(int off, int count, int[] d)717     public void copy1DRangeFrom(int off, int count, int[] d) {
718         validateIsInt32();
719         copy1DRangeFromUnchecked(off, count, d);
720     }
721 
722     /**
723      * Copy part of an allocation from an array.  This variant is
724      * type checked and will generate exceptions if the Allocation
725      * type is not a 16 bit integer type.
726      *
727      * @param off The offset of the first element to be copied.
728      * @param count The number of elements to be copied.
729      * @param d the source data array
730      */
copy1DRangeFrom(int off, int count, short[] d)731     public void copy1DRangeFrom(int off, int count, short[] d) {
732         validateIsInt16();
733         copy1DRangeFromUnchecked(off, count, d);
734     }
735 
736     /**
737      * Copy part of an allocation from an array.  This variant is
738      * type checked and will generate exceptions if the Allocation
739      * type is not a 8 bit integer type.
740      *
741      * @param off The offset of the first element to be copied.
742      * @param count The number of elements to be copied.
743      * @param d the source data array
744      */
copy1DRangeFrom(int off, int count, byte[] d)745     public void copy1DRangeFrom(int off, int count, byte[] d) {
746         validateIsInt8();
747         copy1DRangeFromUnchecked(off, count, d);
748     }
749 
750     /**
751      * Copy part of an allocation from an array.  This variant is
752      * type checked and will generate exceptions if the Allocation
753      * type is not a 32 bit float type.
754      *
755      * @param off The offset of the first element to be copied.
756      * @param count The number of elements to be copied.
757      * @param d the source data array.
758      */
copy1DRangeFrom(int off, int count, float[] d)759     public void copy1DRangeFrom(int off, int count, float[] d) {
760         validateIsFloat32();
761         copy1DRangeFromUnchecked(off, count, d);
762     }
763 
764      /**
765      * Copy part of an allocation from another allocation.
766      *
767      * @param off The offset of the first element to be copied.
768      * @param count The number of elements to be copied.
769      * @param data the source data allocation.
770      * @param dataOff off The offset of the first element in data to
771      *          be copied.
772      */
copy1DRangeFrom(int off, int count, Allocation data, int dataOff)773     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
774         mRS.nAllocationData2D(getIDSafe(), off, 0,
775                               mSelectedLOD, mSelectedFace.mID,
776                               count, 1, data.getID(mRS), dataOff, 0,
777                               data.mSelectedLOD, data.mSelectedFace.mID);
778     }
779 
validate2DRange(int xoff, int yoff, int w, int h)780     private void validate2DRange(int xoff, int yoff, int w, int h) {
781         if (mAdaptedAllocation != null) {
782 
783         } else {
784 
785             if (xoff < 0 || yoff < 0) {
786                 throw new RSIllegalArgumentException("Offset cannot be negative.");
787             }
788             if (h < 0 || w < 0) {
789                 throw new RSIllegalArgumentException("Height or width cannot be negative.");
790             }
791             if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
792                 throw new RSIllegalArgumentException("Updated region larger than allocation.");
793             }
794         }
795     }
796 
797     /**
798      * Copy a rectangular region from the array into the allocation.
799      * The incoming array is assumed to be tightly packed.
800      *
801      * @param xoff X offset of the region to update
802      * @param yoff Y offset of the region to update
803      * @param w Width of the incoming region to update
804      * @param h Height of the incoming region to update
805      * @param data to be placed into the allocation
806      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data)807     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
808         mRS.validate();
809         validate2DRange(xoff, yoff, w, h);
810         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
811                               w, h, data, data.length);
812     }
813 
copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data)814     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
815         mRS.validate();
816         validate2DRange(xoff, yoff, w, h);
817         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
818                               w, h, data, data.length * 2);
819     }
820 
copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data)821     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
822         mRS.validate();
823         validate2DRange(xoff, yoff, w, h);
824         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
825                               w, h, data, data.length * 4);
826     }
827 
copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data)828     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
829         mRS.validate();
830         validate2DRange(xoff, yoff, w, h);
831         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
832                               w, h, data, data.length * 4);
833     }
834 
835     /**
836      * Copy a rectangular region into the allocation from another
837      * allocation.
838      *
839      * @param xoff X offset of the region to update.
840      * @param yoff Y offset of the region to update.
841      * @param w Width of the incoming region to update.
842      * @param h Height of the incoming region to update.
843      * @param data source allocation.
844      * @param dataXoff X offset in data of the region to update.
845      * @param dataYoff Y offset in data of the region to update.
846      */
copy2DRangeFrom(int xoff, int yoff, int w, int h, Allocation data, int dataXoff, int dataYoff)847     public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
848                                 Allocation data, int dataXoff, int dataYoff) {
849         mRS.validate();
850         validate2DRange(xoff, yoff, w, h);
851         mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
852                               mSelectedLOD, mSelectedFace.mID,
853                               w, h, data.getID(mRS), dataXoff, dataYoff,
854                               data.mSelectedLOD, data.mSelectedFace.mID);
855     }
856 
857     /**
858      * Copy a bitmap into an allocation.  The height and width of
859      * the update will use the height and width of the incoming
860      * bitmap.
861      *
862      * @param xoff X offset of the region to update
863      * @param yoff Y offset of the region to update
864      * @param data the bitmap to be copied
865      */
copy2DRangeFrom(int xoff, int yoff, Bitmap data)866     public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
867         mRS.validate();
868         validateBitmapFormat(data);
869         validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
870         mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, data);
871     }
872 
873 
874     /**
875      * Copy from the Allocation into a Bitmap.  The bitmap must
876      * match the dimensions of the Allocation.
877      *
878      * @param b The bitmap to be set from the Allocation.
879      */
copyTo(Bitmap b)880     public void copyTo(Bitmap b) {
881         mRS.validate();
882         validateBitmapFormat(b);
883         validateBitmapSize(b);
884         mRS.nAllocationCopyToBitmap(getID(mRS), b);
885     }
886 
887     /**
888      * Copy from the Allocation into a byte array.  The array must
889      * be at least as large as the Allocation.  The allocation must
890      * be of an 8 bit elemental type.
891      *
892      * @param d The array to be set from the Allocation.
893      */
copyTo(byte[] d)894     public void copyTo(byte[] d) {
895         validateIsInt8();
896         mRS.validate();
897         mRS.nAllocationRead(getID(mRS), d);
898     }
899 
900     /**
901      * Copy from the Allocation into a short array.  The array must
902      * be at least as large as the Allocation.  The allocation must
903      * be of an 16 bit elemental type.
904      *
905      * @param d The array to be set from the Allocation.
906      */
copyTo(short[] d)907     public void copyTo(short[] d) {
908         validateIsInt16();
909         mRS.validate();
910         mRS.nAllocationRead(getID(mRS), d);
911     }
912 
913     /**
914      * Copy from the Allocation into a int array.  The array must be
915      * at least as large as the Allocation.  The allocation must be
916      * of an 32 bit elemental type.
917      *
918      * @param d The array to be set from the Allocation.
919      */
copyTo(int[] d)920     public void copyTo(int[] d) {
921         validateIsInt32();
922         mRS.validate();
923         mRS.nAllocationRead(getID(mRS), d);
924     }
925 
926     /**
927      * Copy from the Allocation into a float array.  The array must
928      * be at least as large as the Allocation.  The allocation must
929      * be of an 32 bit float elemental type.
930      *
931      * @param d The array to be set from the Allocation.
932      */
copyTo(float[] d)933     public void copyTo(float[] d) {
934         validateIsFloat32();
935         mRS.validate();
936         mRS.nAllocationRead(getID(mRS), d);
937     }
938 
939     /**
940      * Resize a 1D allocation.  The contents of the allocation are
941      * preserved.  If new elements are allocated objects are created
942      * with null contents and the new region is otherwise undefined.
943      *
944      * If the new region is smaller the references of any objects
945      * outside the new region will be released.
946      *
947      * A new type will be created with the new dimension.
948      *
949      * @param dimX The new size of the allocation.
950      */
resize(int dimX)951     public synchronized void resize(int dimX) {
952         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
953             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
954         }
955         mRS.nAllocationResize1D(getID(mRS), dimX);
956         mRS.finish();  // Necessary because resize is fifoed and update is async.
957 
958         int typeID = mRS.nAllocationGetType(getID(mRS));
959         mType = new Type(typeID, mRS);
960         mType.updateFromNative();
961         updateCacheInfo(mType);
962     }
963 
964     /**
965      * Resize a 2D allocation.  The contents of the allocation are
966      * preserved.  If new elements are allocated objects are created
967      * with null contents and the new region is otherwise undefined.
968      *
969      * If the new region is smaller the references of any objects
970      * outside the new region will be released.
971      *
972      * A new type will be created with the new dimension.
973      *
974      * @hide
975      * @param dimX The new size of the allocation.
976      * @param dimY The new size of the allocation.
977      */
resize(int dimX, int dimY)978     public void resize(int dimX, int dimY) {
979         if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
980             throw new RSInvalidStateException(
981                 "Resize only support for 2D allocations at this time.");
982         }
983         if (mType.getY() == 0) {
984             throw new RSInvalidStateException(
985                 "Resize only support for 2D allocations at this time.");
986         }
987         mRS.nAllocationResize2D(getID(mRS), dimX, dimY);
988         mRS.finish();  // Necessary because resize is fifoed and update is async.
989 
990         int typeID = mRS.nAllocationGetType(getID(mRS));
991         mType = new Type(typeID, mRS);
992         mType.updateFromNative();
993         updateCacheInfo(mType);
994     }
995 
996 
997 
998     // creation
999 
1000     static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
1001     static {
1002         mBitmapOptions.inScaled = false;
1003     }
1004 
1005     /**
1006      *
1007      * @param type renderscript type describing data layout
1008      * @param mips specifies desired mipmap behaviour for the
1009      *             allocation
1010      * @param usage bit field specifying how the allocation is
1011      *              utilized
1012      */
createTyped(RenderScript rs, Type type, MipmapControl mips, int usage)1013     static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
1014         rs.validate();
1015         if (type.getID(rs) == 0) {
1016             throw new RSInvalidStateException("Bad Type");
1017         }
1018         int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
1019         if (id == 0) {
1020             throw new RSRuntimeException("Allocation creation failed.");
1021         }
1022         return new Allocation(id, rs, type, usage);
1023     }
1024 
1025     /**
1026      * Creates a renderscript allocation with the size specified by
1027      * the type and no mipmaps generated by default
1028      *
1029      * @param rs Context to which the allocation will belong.
1030      * @param type renderscript type describing data layout
1031      * @param usage bit field specifying how the allocation is
1032      *              utilized
1033      *
1034      * @return allocation
1035      */
createTyped(RenderScript rs, Type type, int usage)1036     static public Allocation createTyped(RenderScript rs, Type type, int usage) {
1037         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
1038     }
1039 
1040     /**
1041      * Creates a renderscript allocation for use by the script with
1042      * the size specified by the type and no mipmaps generated by
1043      * default
1044      *
1045      * @param rs Context to which the allocation will belong.
1046      * @param type renderscript type describing data layout
1047      *
1048      * @return allocation
1049      */
createTyped(RenderScript rs, Type type)1050     static public Allocation createTyped(RenderScript rs, Type type) {
1051         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
1052     }
1053 
1054     /**
1055      * Creates a renderscript allocation with a specified number of
1056      * given elements
1057      *
1058      * @param rs Context to which the allocation will belong.
1059      * @param e describes what each element of an allocation is
1060      * @param count specifies the number of element in the allocation
1061      * @param usage bit field specifying how the allocation is
1062      *              utilized
1063      *
1064      * @return allocation
1065      */
createSized(RenderScript rs, Element e, int count, int usage)1066     static public Allocation createSized(RenderScript rs, Element e,
1067                                          int count, int usage) {
1068         rs.validate();
1069         Type.Builder b = new Type.Builder(rs, e);
1070         b.setX(count);
1071         Type t = b.create();
1072 
1073         int id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
1074         if (id == 0) {
1075             throw new RSRuntimeException("Allocation creation failed.");
1076         }
1077         return new Allocation(id, rs, t, usage);
1078     }
1079 
1080     /**
1081      * Creates a renderscript allocation with a specified number of
1082      * given elements
1083      *
1084      * @param rs Context to which the allocation will belong.
1085      * @param e describes what each element of an allocation is
1086      * @param count specifies the number of element in the allocation
1087      *
1088      * @return allocation
1089      */
createSized(RenderScript rs, Element e, int count)1090     static public Allocation createSized(RenderScript rs, Element e, int count) {
1091         return createSized(rs, e, count, USAGE_SCRIPT);
1092     }
1093 
elementFromBitmap(RenderScript rs, Bitmap b)1094     static Element elementFromBitmap(RenderScript rs, Bitmap b) {
1095         final Bitmap.Config bc = b.getConfig();
1096         if (bc == Bitmap.Config.ALPHA_8) {
1097             return Element.A_8(rs);
1098         }
1099         if (bc == Bitmap.Config.ARGB_4444) {
1100             return Element.RGBA_4444(rs);
1101         }
1102         if (bc == Bitmap.Config.ARGB_8888) {
1103             return Element.RGBA_8888(rs);
1104         }
1105         if (bc == Bitmap.Config.RGB_565) {
1106             return Element.RGB_565(rs);
1107         }
1108         throw new RSInvalidStateException("Bad bitmap type: " + bc);
1109     }
1110 
typeFromBitmap(RenderScript rs, Bitmap b, MipmapControl mip)1111     static Type typeFromBitmap(RenderScript rs, Bitmap b,
1112                                        MipmapControl mip) {
1113         Element e = elementFromBitmap(rs, b);
1114         Type.Builder tb = new Type.Builder(rs, e);
1115         tb.setX(b.getWidth());
1116         tb.setY(b.getHeight());
1117         tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
1118         return tb.create();
1119     }
1120 
1121     /**
1122      * Creates a renderscript allocation from a bitmap
1123      *
1124      * @param rs Context to which the allocation will belong.
1125      * @param b bitmap source for the allocation data
1126      * @param mips specifies desired mipmap behaviour for the
1127      *             allocation
1128      * @param usage bit field specifying how the allocation is
1129      *              utilized
1130      *
1131      * @return renderscript allocation containing bitmap data
1132      *
1133      */
createFromBitmap(RenderScript rs, Bitmap b, MipmapControl mips, int usage)1134     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
1135                                               MipmapControl mips,
1136                                               int usage) {
1137         rs.validate();
1138         Type t = typeFromBitmap(rs, b, mips);
1139 
1140         int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1141         if (id == 0) {
1142             throw new RSRuntimeException("Load failed.");
1143         }
1144         return new Allocation(id, rs, t, usage);
1145     }
1146 
1147     /**
1148      *
1149      *
1150      * @hide
1151      *
1152      */
getSurfaceTexture()1153     public SurfaceTexture getSurfaceTexture() {
1154         if ((mUsage & USAGE_IO_INPUT) == 0) {
1155             throw new RSInvalidStateException("Allocation is not a surface texture.");
1156         }
1157 
1158         int id = mRS.nAllocationGetSurfaceTextureID(getID(mRS));
1159         SurfaceTexture st = new SurfaceTexture(id);
1160         mRS.nAllocationGetSurfaceTextureID2(getID(mRS), st);
1161 
1162         return st;
1163     }
1164 
1165     /**
1166      * For allocations used with io operations, returns the handle
1167      * onto a raw buffer that is being managed by the screen
1168      * compositor.
1169      *
1170      * @return Surface object associated with allocation
1171      *
1172      */
getSurface()1173     public Surface getSurface() {
1174         return new Surface(getSurfaceTexture());
1175     }
1176 
1177     /**
1178      * Associate a surface for io output with this allocation
1179      *
1180      * @param sur Surface to associate with allocation
1181      */
setSurface(Surface sur)1182     public void setSurface(Surface sur) {
1183         mRS.validate();
1184         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
1185             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
1186         }
1187 
1188         mRS.nAllocationSetSurface(getID(mRS), sur);
1189     }
1190 
1191     /**
1192      * @hide
1193      */
setSurfaceTexture(SurfaceTexture st)1194     public void setSurfaceTexture(SurfaceTexture st) {
1195         mRS.validate();
1196         if ((mUsage & USAGE_IO_OUTPUT) == 0) {
1197             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
1198         }
1199 
1200         Surface s = new Surface(st);
1201         mRS.nAllocationSetSurface(getID(mRS), s);
1202     }
1203 
1204     /**
1205      * Creates a non-mipmapped renderscript allocation to use as a
1206      * graphics texture
1207      *
1208      * @param rs Context to which the allocation will belong.
1209      * @param b bitmap source for the allocation data
1210      *
1211      * @return renderscript allocation containing bitmap data
1212      *
1213      */
createFromBitmap(RenderScript rs, Bitmap b)1214     static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
1215         return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1216                                 USAGE_GRAPHICS_TEXTURE);
1217     }
1218 
1219     /**
1220      * Creates a cubemap allocation from a bitmap containing the
1221      * horizontal list of cube faces. Each individual face must be
1222      * the same size and power of 2
1223      *
1224      * @param rs Context to which the allocation will belong.
1225      * @param b bitmap with cubemap faces layed out in the following
1226      *          format: right, left, top, bottom, front, back
1227      * @param mips specifies desired mipmap behaviour for the cubemap
1228      * @param usage bit field specifying how the cubemap is utilized
1229      *
1230      * @return allocation containing cubemap data
1231      *
1232      */
createCubemapFromBitmap(RenderScript rs, Bitmap b, MipmapControl mips, int usage)1233     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
1234                                                      MipmapControl mips,
1235                                                      int usage) {
1236         rs.validate();
1237 
1238         int height = b.getHeight();
1239         int width = b.getWidth();
1240 
1241         if (width % 6 != 0) {
1242             throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
1243         }
1244         if (width / 6 != height) {
1245             throw new RSIllegalArgumentException("Only square cube map faces supported");
1246         }
1247         boolean isPow2 = (height & (height - 1)) == 0;
1248         if (!isPow2) {
1249             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1250         }
1251 
1252         Element e = elementFromBitmap(rs, b);
1253         Type.Builder tb = new Type.Builder(rs, e);
1254         tb.setX(height);
1255         tb.setY(height);
1256         tb.setFaces(true);
1257         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1258         Type t = tb.create();
1259 
1260         int id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
1261         if(id == 0) {
1262             throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
1263         }
1264         return new Allocation(id, rs, t, usage);
1265     }
1266 
1267     /**
1268      * Creates a non-mipmapped cubemap allocation for use as a
1269      * graphics texture from a bitmap containing the horizontal list
1270      * of cube faces. Each individual face must be the same size and
1271      * power of 2
1272      *
1273      * @param rs Context to which the allocation will belong.
1274      * @param b bitmap with cubemap faces layed out in the following
1275      *          format: right, left, top, bottom, front, back
1276      *
1277      * @return allocation containing cubemap data
1278      *
1279      */
createCubemapFromBitmap(RenderScript rs, Bitmap b)1280     static public Allocation createCubemapFromBitmap(RenderScript rs,
1281                                                      Bitmap b) {
1282         return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
1283                                        USAGE_GRAPHICS_TEXTURE);
1284     }
1285 
1286     /**
1287      * Creates a cubemap allocation from 6 bitmaps containing
1288      * the cube faces. All the faces must be the same size and
1289      * power of 2
1290      *
1291      * @param rs Context to which the allocation will belong.
1292      * @param xpos cubemap face in the positive x direction
1293      * @param xneg cubemap face in the negative x direction
1294      * @param ypos cubemap face in the positive y direction
1295      * @param yneg cubemap face in the negative y direction
1296      * @param zpos cubemap face in the positive z direction
1297      * @param zneg cubemap face in the negative z direction
1298      * @param mips specifies desired mipmap behaviour for the cubemap
1299      * @param usage bit field specifying how the cubemap is utilized
1300      *
1301      * @return allocation containing cubemap data
1302      *
1303      */
createCubemapFromCubeFaces(RenderScript rs, Bitmap xpos, Bitmap xneg, Bitmap ypos, Bitmap yneg, Bitmap zpos, Bitmap zneg, MipmapControl mips, int usage)1304     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1305                                                         Bitmap xpos,
1306                                                         Bitmap xneg,
1307                                                         Bitmap ypos,
1308                                                         Bitmap yneg,
1309                                                         Bitmap zpos,
1310                                                         Bitmap zneg,
1311                                                         MipmapControl mips,
1312                                                         int usage) {
1313         int height = xpos.getHeight();
1314         if (xpos.getWidth() != height ||
1315             xneg.getWidth() != height || xneg.getHeight() != height ||
1316             ypos.getWidth() != height || ypos.getHeight() != height ||
1317             yneg.getWidth() != height || yneg.getHeight() != height ||
1318             zpos.getWidth() != height || zpos.getHeight() != height ||
1319             zneg.getWidth() != height || zneg.getHeight() != height) {
1320             throw new RSIllegalArgumentException("Only square cube map faces supported");
1321         }
1322         boolean isPow2 = (height & (height - 1)) == 0;
1323         if (!isPow2) {
1324             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
1325         }
1326 
1327         Element e = elementFromBitmap(rs, xpos);
1328         Type.Builder tb = new Type.Builder(rs, e);
1329         tb.setX(height);
1330         tb.setY(height);
1331         tb.setFaces(true);
1332         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
1333         Type t = tb.create();
1334         Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
1335 
1336         AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
1337         adapter.setFace(Type.CubemapFace.POSITIVE_X);
1338         adapter.copyFrom(xpos);
1339         adapter.setFace(Type.CubemapFace.NEGATIVE_X);
1340         adapter.copyFrom(xneg);
1341         adapter.setFace(Type.CubemapFace.POSITIVE_Y);
1342         adapter.copyFrom(ypos);
1343         adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
1344         adapter.copyFrom(yneg);
1345         adapter.setFace(Type.CubemapFace.POSITIVE_Z);
1346         adapter.copyFrom(zpos);
1347         adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
1348         adapter.copyFrom(zneg);
1349 
1350         return cubemap;
1351     }
1352 
1353     /**
1354      * Creates a non-mipmapped cubemap allocation for use as a
1355      * graphics texture from 6 bitmaps containing
1356      * the cube faces. All the faces must be the same size and
1357      * power of 2
1358      *
1359      * @param rs Context to which the allocation will belong.
1360      * @param xpos cubemap face in the positive x direction
1361      * @param xneg cubemap face in the negative x direction
1362      * @param ypos cubemap face in the positive y direction
1363      * @param yneg cubemap face in the negative y direction
1364      * @param zpos cubemap face in the positive z direction
1365      * @param zneg cubemap face in the negative z direction
1366      *
1367      * @return allocation containing cubemap data
1368      *
1369      */
createCubemapFromCubeFaces(RenderScript rs, Bitmap xpos, Bitmap xneg, Bitmap ypos, Bitmap yneg, Bitmap zpos, Bitmap zneg)1370     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
1371                                                         Bitmap xpos,
1372                                                         Bitmap xneg,
1373                                                         Bitmap ypos,
1374                                                         Bitmap yneg,
1375                                                         Bitmap zpos,
1376                                                         Bitmap zneg) {
1377         return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
1378                                           zpos, zneg, MipmapControl.MIPMAP_NONE,
1379                                           USAGE_GRAPHICS_TEXTURE);
1380     }
1381 
1382     /**
1383      * Creates a renderscript allocation from the bitmap referenced
1384      * by resource id
1385      *
1386      * @param rs Context to which the allocation will belong.
1387      * @param res application resources
1388      * @param id resource id to load the data from
1389      * @param mips specifies desired mipmap behaviour for the
1390      *             allocation
1391      * @param usage bit field specifying how the allocation is
1392      *              utilized
1393      *
1394      * @return renderscript allocation containing resource data
1395      *
1396      */
createFromBitmapResource(RenderScript rs, Resources res, int id, MipmapControl mips, int usage)1397     static public Allocation createFromBitmapResource(RenderScript rs,
1398                                                       Resources res,
1399                                                       int id,
1400                                                       MipmapControl mips,
1401                                                       int usage) {
1402 
1403         rs.validate();
1404         Bitmap b = BitmapFactory.decodeResource(res, id);
1405         Allocation alloc = createFromBitmap(rs, b, mips, usage);
1406         b.recycle();
1407         return alloc;
1408     }
1409 
1410     /**
1411      * Creates a non-mipmapped renderscript allocation to use as a
1412      * graphics texture from the bitmap referenced by resource id
1413      *
1414      * @param rs Context to which the allocation will belong.
1415      * @param res application resources
1416      * @param id resource id to load the data from
1417      *
1418      * @return renderscript allocation containing resource data
1419      *
1420      */
createFromBitmapResource(RenderScript rs, Resources res, int id)1421     static public Allocation createFromBitmapResource(RenderScript rs,
1422                                                       Resources res,
1423                                                       int id) {
1424         return createFromBitmapResource(rs, res, id,
1425                                         MipmapControl.MIPMAP_NONE,
1426                                         USAGE_GRAPHICS_TEXTURE);
1427     }
1428 
1429     /**
1430      * Creates a renderscript allocation containing string data
1431      * encoded in UTF-8 format
1432      *
1433      * @param rs Context to which the allocation will belong.
1434      * @param str string to create the allocation from
1435      * @param usage bit field specifying how the allocaiton is
1436      *              utilized
1437      *
1438      */
createFromString(RenderScript rs, String str, int usage)1439     static public Allocation createFromString(RenderScript rs,
1440                                               String str,
1441                                               int usage) {
1442         rs.validate();
1443         byte[] allocArray = null;
1444         try {
1445             allocArray = str.getBytes("UTF-8");
1446             Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
1447             alloc.copyFrom(allocArray);
1448             return alloc;
1449         }
1450         catch (Exception e) {
1451             throw new RSRuntimeException("Could not convert string to utf-8.");
1452         }
1453     }
1454 }
1455 
1456 
1457