Allocation.java revision fb9f82ca4f11cf7e43a001f3e6fd1b381cc86210
1/*
2 * Copyright (C) 2008 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
17package android.renderscript;
18
19import java.io.IOException;
20import java.io.InputStream;
21import android.content.res.Resources;
22import android.content.res.AssetManager;
23import android.graphics.Bitmap;
24import android.graphics.BitmapFactory;
25import android.util.Log;
26import android.util.TypedValue;
27
28/**
29 * Memory allocation class for renderscript.  An allocation combines a Type with
30 * memory to provide storage for user data and objects.
31 *
32 * Allocations may exist in one or more memory spaces.  Currently those are
33 * Script: accessable by RS scripts.
34 * Graphics Texture: accessable as a graphics texture.
35 * Graphics Vertex: accessable as graphical vertex data.
36 * Graphics Constants: Accessable as constants in user shaders
37 *
38 * By default java side updates are always applied to the script accessable
39 * memory.  If this is not present they are then applied to the various HW
40 * memory types.  A syncAll call is necessary after the script data is update to
41 * keep the other memory spaces in sync.
42 *
43 **/
44public class Allocation extends BaseObj {
45    Type mType;
46    Bitmap mBitmap;
47    int mUsage;
48
49    /**
50     * The usage of the allocation.  These signal to renderscript
51     * where to place the allocation in memory.
52     *
53     * SCRIPT The allocation will be bound to and accessed by
54     * scripts.
55     */
56    public static final int USAGE_SCRIPT = 0x0001;
57
58    /**
59     * GRAPHICS_TEXTURE The allcation will be used as a texture
60     * source by one or more graphcics programs.
61     *
62     */
63    public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
64
65    /**
66     * GRAPHICS_VERTEX The allocation will be used as a graphics
67     * mesh.
68     *
69     */
70    public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
71
72
73    /**
74     * GRAPHICS_CONSTANTS The allocation will be used as the source
75     * of shader constants by one or more programs.
76     *
77     */
78    public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
79
80
81    /**
82     * Controls mipmap behavior when using the bitmap creation and
83     * update functions.
84     */
85    public enum MipmapControl {
86        /**
87         * No mipmaps will be generated and the type generated from the
88         * incoming bitmap will not contain additional LODs.
89         */
90        MIPMAP_NONE(0),
91
92        /**
93         * A Full mipmap chain will be created in script memory.  The
94         * type of the allocation will contain a full mipmap chain.  On
95         * upload to graphics the full chain will be transfered.
96         */
97        MIPMAP_FULL(1),
98
99        /**
100         * The type of the allocation will be the same as MIPMAP_NONE.
101         * It will not contain mipmaps.  On upload to graphics the
102         * graphics copy of the allocation data will contain a full
103         * mipmap chain generated from the top level in script memory.
104         */
105        MIPMAP_ON_SYNC_TO_TEXTURE(2);
106
107        int mID;
108        MipmapControl(int id) {
109            mID = id;
110        }
111    }
112
113    Allocation(int id, RenderScript rs, Type t, int usage) {
114        super(id, rs);
115        if ((usage & ~(USAGE_SCRIPT |
116                       USAGE_GRAPHICS_TEXTURE |
117                       USAGE_GRAPHICS_VERTEX |
118                       USAGE_GRAPHICS_CONSTANTS)) != 0) {
119            throw new RSIllegalArgumentException("Unknown usage specified.");
120        }
121        mType = t;
122    }
123
124    @Override
125    void updateFromNative() {
126        super.updateFromNative();
127        int typeID = mRS.nAllocationGetType(getID());
128        if(typeID != 0) {
129            mType = new Type(typeID, mRS);
130            mType.updateFromNative();
131        }
132    }
133
134    public Type getType() {
135        return mType;
136    }
137
138    public void syncAll(int srcLocation) {
139        switch (srcLocation) {
140        case USAGE_SCRIPT:
141        case USAGE_GRAPHICS_CONSTANTS:
142        case USAGE_GRAPHICS_TEXTURE:
143        case USAGE_GRAPHICS_VERTEX:
144            break;
145        default:
146            throw new RSIllegalArgumentException("Source must be exactly one usage type.");
147        }
148        mRS.validate();
149        mRS.nAllocationSyncAll(getID(), srcLocation);
150    }
151
152    public void copyFrom(BaseObj[] d) {
153        mRS.validate();
154        if (d.length != mType.getCount()) {
155            throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " +
156                                                 mType.getCount() + ", array length = " + d.length);
157        }
158        int i[] = new int[d.length];
159        for (int ct=0; ct < d.length; ct++) {
160            i[ct] = d[ct].getID();
161        }
162        copy1DRangeFrom(0, mType.getCount(), i);
163    }
164
165    private void validateBitmapFormat(Bitmap b) {
166        Bitmap.Config bc = b.getConfig();
167        switch (bc) {
168        case ALPHA_8:
169            if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
170                throw new RSIllegalArgumentException("Allocation kind is " +
171                                                     mType.getElement().mKind + ", type " +
172                                                     mType.getElement().mType +
173                                                     " of " + mType.getElement().getSizeBytes() +
174                                                     " bytes, passed bitmap was " + bc);
175            }
176            break;
177        case ARGB_8888:
178            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
179                (mType.getElement().getSizeBytes() != 4)) {
180                throw new RSIllegalArgumentException("Allocation kind is " +
181                                                     mType.getElement().mKind + ", type " +
182                                                     mType.getElement().mType +
183                                                     " of " + mType.getElement().getSizeBytes() +
184                                                     " bytes, passed bitmap was " + bc);
185            }
186            break;
187        case RGB_565:
188            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
189                (mType.getElement().getSizeBytes() != 2)) {
190                throw new RSIllegalArgumentException("Allocation kind is " +
191                                                     mType.getElement().mKind + ", type " +
192                                                     mType.getElement().mType +
193                                                     " of " + mType.getElement().getSizeBytes() +
194                                                     " bytes, passed bitmap was " + bc);
195            }
196            break;
197        case ARGB_4444:
198            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
199                (mType.getElement().getSizeBytes() != 2)) {
200                throw new RSIllegalArgumentException("Allocation kind is " +
201                                                     mType.getElement().mKind + ", type " +
202                                                     mType.getElement().mType +
203                                                     " of " + mType.getElement().getSizeBytes() +
204                                                     " bytes, passed bitmap was " + bc);
205            }
206            break;
207
208        }
209    }
210
211    private void validateBitmapSize(Bitmap b) {
212        if(mType.getX() != b.getWidth() ||
213           mType.getY() != b.getHeight()) {
214            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
215        }
216    }
217
218    public void copyFrom(int[] d) {
219        mRS.validate();
220        copy1DRangeFrom(0, mType.getCount(), d);
221    }
222    public void copyFrom(short[] d) {
223        mRS.validate();
224        copy1DRangeFrom(0, mType.getCount(), d);
225    }
226    public void copyFrom(byte[] d) {
227        mRS.validate();
228        copy1DRangeFrom(0, mType.getCount(), d);
229    }
230    public void copyFrom(float[] d) {
231        mRS.validate();
232        copy1DRangeFrom(0, mType.getCount(), d);
233    }
234    public void copyFrom(Bitmap b) {
235        mRS.validate();
236        validateBitmapSize(b);
237        validateBitmapFormat(b);
238        mRS.nAllocationCopyFromBitmap(getID(), b);
239    }
240
241    /**
242     * @hide
243     *
244     * This is only intended to be used by auto-generate code reflected from the
245     * renderscript script files.
246     *
247     * @param xoff
248     * @param fp
249     */
250    public void setOneElement(int xoff, FieldPacker fp) {
251        int eSize = mType.mElement.getSizeBytes();
252        final byte[] data = fp.getData();
253
254        int count = data.length / eSize;
255        if ((eSize * count) != data.length) {
256            throw new RSIllegalArgumentException("Field packer length " + data.length +
257                                               " not divisible by element size " + eSize + ".");
258        }
259        data1DChecks(xoff, count, data.length, data.length);
260        mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length);
261    }
262
263
264    /**
265     * @hide
266     *
267     * This is only intended to be used by auto-generate code reflected from the
268     * renderscript script files.
269     *
270     * @param xoff
271     * @param component_number
272     * @param fp
273     */
274    public void setOneComponent(int xoff, int component_number, FieldPacker fp) {
275        if (component_number >= mType.mElement.mElements.length) {
276            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
277        }
278        if(xoff < 0) {
279            throw new RSIllegalArgumentException("Offset must be >= 0.");
280        }
281
282        final byte[] data = fp.getData();
283        int eSize = mType.mElement.mElements[component_number].getSizeBytes();
284
285        if (data.length != eSize) {
286            throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
287                                               " does not match component size " + eSize + ".");
288        }
289
290        mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length);
291    }
292
293    private void data1DChecks(int off, int count, int len, int dataSize) {
294        mRS.validate();
295        if(off < 0) {
296            throw new RSIllegalArgumentException("Offset must be >= 0.");
297        }
298        if(count < 1) {
299            throw new RSIllegalArgumentException("Count must be >= 1.");
300        }
301        if((off + count) > mType.getCount()) {
302            throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() +
303                                               ", got " + count + " at offset " + off + ".");
304        }
305        if((len) < dataSize) {
306            throw new RSIllegalArgumentException("Array too small for allocation type.");
307        }
308    }
309
310    /**
311     * Generate a mipmap chain.  Requires the type of the allocation
312     * include mipmaps.
313     *
314     * This function will generate a complete set of mipmaps from
315     * the top level lod and place them into the script memoryspace.
316     *
317     * If the allocation is also using other memory spaces a
318     * followup sync will be required.
319     */
320    public void generateMipmaps() {
321        mRS.nAllocationGenerateMipmaps(getID());
322    }
323
324    public void copy1DRangeFrom(int off, int count, int[] d) {
325        int dataSize = mType.mElement.getSizeBytes() * count;
326        data1DChecks(off, count, d.length * 4, dataSize);
327        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
328    }
329    public void copy1DRangeFrom(int off, int count, short[] d) {
330        int dataSize = mType.mElement.getSizeBytes() * count;
331        data1DChecks(off, count, d.length * 2, dataSize);
332        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
333    }
334    public void copy1DRangeFrom(int off, int count, byte[] d) {
335        int dataSize = mType.mElement.getSizeBytes() * count;
336        data1DChecks(off, count, d.length, dataSize);
337        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
338    }
339    public void copy1DRangeFrom(int off, int count, float[] d) {
340        int dataSize = mType.mElement.getSizeBytes() * count;
341        data1DChecks(off, count, d.length * 4, dataSize);
342        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
343    }
344
345    private void validate2DRange(int xoff, int yoff, int w, int h) {
346        if (xoff < 0 || yoff < 0) {
347            throw new RSIllegalArgumentException("Offset cannot be negative.");
348        }
349        if (h < 0 || w < 0) {
350            throw new RSIllegalArgumentException("Height or width cannot be negative.");
351        }
352        if ((xoff + w) > mType.mDimX ||
353            (yoff + h) > mType.mDimY) {
354            throw new RSIllegalArgumentException("Updated region larger than allocation.");
355        }
356    }
357
358    /**
359     * Copy a rectanglular region from the array into the
360     * allocation.  The incoming array is assumed to be tightly
361     * packed.
362     *
363     * @param xoff X offset of the region to update
364     * @param yoff Y offset of the region to update
365     * @param w Width of the incoming region to update
366     * @param h Height of the incoming region to update
367     * @param data to be placed into the allocation
368     */
369    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
370        mRS.validate();
371        validate2DRange(xoff, yoff, w, h);
372        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length);
373    }
374
375    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
376        mRS.validate();
377        validate2DRange(xoff, yoff, w, h);
378        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2);
379    }
380
381    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
382        mRS.validate();
383        validate2DRange(xoff, yoff, w, h);
384        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
385    }
386
387    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
388        mRS.validate();
389        validate2DRange(xoff, yoff, w, h);
390        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
391    }
392
393    /**
394     * Copy a bitmap into an allocation.  The height and width of
395     * the update will use the height and width of the incoming
396     * bitmap.
397     *
398     * @param xoff X offset of the region to update
399     * @param yoff Y offset of the region to update
400     * @param data the bitmap to be copied
401     */
402    public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
403        mRS.validate();
404        validateBitmapFormat(data);
405        validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
406        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data);
407    }
408
409
410    public void copyTo(Bitmap b) {
411        mRS.validate();
412        validateBitmapFormat(b);
413        validateBitmapSize(b);
414        mRS.nAllocationCopyToBitmap(getID(), b);
415    }
416
417    public void copyTo(byte[] d) {
418        mRS.validate();
419        mRS.nAllocationRead(getID(), d);
420    }
421
422    public void copyTo(short[] d) {
423        mRS.validate();
424        mRS.nAllocationRead(getID(), d);
425    }
426
427    public void copyTo(int[] d) {
428        mRS.validate();
429        mRS.nAllocationRead(getID(), d);
430    }
431
432    public void copyTo(float[] d) {
433        mRS.validate();
434        mRS.nAllocationRead(getID(), d);
435    }
436
437    /**
438     * Resize a 1D allocation.  The contents of the allocation are
439     * preserved.  If new elements are allocated objects are created
440     * with null contents and the new region is otherwise undefined.
441     *
442     * If the new region is smaller the references of any objects
443     * outside the new region will be released.
444     *
445     * A new type will be created with the new dimension.
446     *
447     * @param dimX The new size of the allocation.
448     */
449    public synchronized void resize(int dimX) {
450        if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
451            throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
452        }
453        mRS.nAllocationResize1D(getID(), dimX);
454        mRS.finish();  // Necessary because resize is fifoed and update is async.
455
456        int typeID = mRS.nAllocationGetType(getID());
457        mType = new Type(typeID, mRS);
458        mType.updateFromNative();
459    }
460
461    /*
462    public void resize(int dimX, int dimY) {
463        if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
464            throw new RSIllegalStateException("Resize only support for 2D allocations at this time.");
465        }
466        if (mType.getY() == 0) {
467            throw new RSIllegalStateException("Resize only support for 2D allocations at this time.");
468        }
469        mRS.nAllocationResize2D(getID(), dimX, dimY);
470    }
471    */
472
473
474
475    // creation
476
477    static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
478    static {
479        mBitmapOptions.inScaled = false;
480    }
481
482    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mc, int usage) {
483        rs.validate();
484        if (type.getID() == 0) {
485            throw new RSInvalidStateException("Bad Type");
486        }
487        int id = rs.nAllocationCreateTyped(type.getID(), mc.mID, usage);
488        if (id == 0) {
489            throw new RSRuntimeException("Allocation creation failed.");
490        }
491        return new Allocation(id, rs, type, usage);
492    }
493
494    static public Allocation createTyped(RenderScript rs, Type type, int usage) {
495        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
496    }
497
498    static public Allocation createTyped(RenderScript rs, Type type) {
499        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
500    }
501
502    static public Allocation createSized(RenderScript rs, Element e,
503                                         int count, int usage) {
504        rs.validate();
505        Type.Builder b = new Type.Builder(rs, e);
506        b.setX(count);
507        Type t = b.create();
508
509        int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage);
510        if (id == 0) {
511            throw new RSRuntimeException("Allocation creation failed.");
512        }
513        return new Allocation(id, rs, t, usage);
514    }
515
516    static public Allocation createSized(RenderScript rs, Element e, int count) {
517        return createSized(rs, e, count, USAGE_SCRIPT);
518    }
519
520    static Element elementFromBitmap(RenderScript rs, Bitmap b) {
521        final Bitmap.Config bc = b.getConfig();
522        if (bc == Bitmap.Config.ALPHA_8) {
523            return Element.A_8(rs);
524        }
525        if (bc == Bitmap.Config.ARGB_4444) {
526            return Element.RGBA_4444(rs);
527        }
528        if (bc == Bitmap.Config.ARGB_8888) {
529            return Element.RGBA_8888(rs);
530        }
531        if (bc == Bitmap.Config.RGB_565) {
532            return Element.RGB_565(rs);
533        }
534        throw new RSInvalidStateException("Bad bitmap type: " + bc);
535    }
536
537    static Type typeFromBitmap(RenderScript rs, Bitmap b,
538                                       MipmapControl mip) {
539        Element e = elementFromBitmap(rs, b);
540        Type.Builder tb = new Type.Builder(rs, e);
541        tb.setX(b.getWidth());
542        tb.setY(b.getHeight());
543        tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
544        return tb.create();
545    }
546
547    static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
548                                              MipmapControl mips,
549                                              int usage) {
550        rs.validate();
551        Type t = typeFromBitmap(rs, b, mips);
552
553        int id = rs.nAllocationCreateFromBitmap(t.getID(), mips.mID, b, usage);
554        if (id == 0) {
555            throw new RSRuntimeException("Load failed.");
556        }
557        return new Allocation(id, rs, t, usage);
558    }
559
560    static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
561        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
562                                USAGE_GRAPHICS_TEXTURE);
563    }
564
565    /**
566    * Creates a cubemap allocation from a bitmap containing the
567    * horizontal list of cube faces. Each individual face must be
568    * the same size and power of 2
569    *
570    * @param rs
571    * @param b bitmap with cubemap faces layed out in the following
572    *          format: right, left, top, bottom, front, back
573    * @param mips specifies desired mipmap behaviour for the cubemap
574    * @param usage bitfield specifying how the cubemap is utilized
575    *
576    **/
577    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
578                                                     MipmapControl mips,
579                                                     int usage) {
580        rs.validate();
581
582        int height = b.getHeight();
583        int width = b.getWidth();
584
585        if (width % 6 != 0) {
586            throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
587        }
588        if (width / 6 != height) {
589            throw new RSIllegalArgumentException("Only square cube map faces supported");
590        }
591        boolean isPow2 = (height & (height - 1)) == 0;
592        if (!isPow2) {
593            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
594        }
595
596        Element e = elementFromBitmap(rs, b);
597        Type.Builder tb = new Type.Builder(rs, e);
598        tb.setX(height);
599        tb.setY(height);
600        tb.setFaces(true);
601        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
602        Type t = tb.create();
603
604        int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage);
605        if(id == 0) {
606            throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
607        }
608        return new Allocation(id, rs, t, usage);
609    }
610
611    static public Allocation createCubemapFromBitmap(RenderScript rs,
612                                                     Bitmap b) {
613        return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
614                                       USAGE_GRAPHICS_TEXTURE);
615    }
616
617    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
618                                                        Bitmap xpos,
619                                                        Bitmap xneg,
620                                                        Bitmap ypos,
621                                                        Bitmap yneg,
622                                                        Bitmap zpos,
623                                                        Bitmap zneg,
624                                                        MipmapControl mips,
625                                                        int usage) {
626        int height = xpos.getHeight();
627        if (xpos.getWidth() != height ||
628            xneg.getWidth() != height || xneg.getHeight() != height ||
629            ypos.getWidth() != height || ypos.getHeight() != height ||
630            yneg.getWidth() != height || yneg.getHeight() != height ||
631            zpos.getWidth() != height || zpos.getHeight() != height ||
632            zneg.getWidth() != height || zneg.getHeight() != height) {
633            throw new RSIllegalArgumentException("Only square cube map faces supported");
634        }
635        boolean isPow2 = (height & (height - 1)) == 0;
636        if (!isPow2) {
637            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
638        }
639
640        Element e = elementFromBitmap(rs, xpos);
641        Type.Builder tb = new Type.Builder(rs, e);
642        tb.setX(height);
643        tb.setY(height);
644        tb.setFaces(true);
645        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
646        Type t = tb.create();
647        Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
648
649        AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
650        adapter.setFace(Type.CubemapFace.POSITVE_X);
651        adapter.copyFrom(xpos);
652        adapter.setFace(Type.CubemapFace.NEGATIVE_X);
653        adapter.copyFrom(xneg);
654        adapter.setFace(Type.CubemapFace.POSITVE_Y);
655        adapter.copyFrom(ypos);
656        adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
657        adapter.copyFrom(yneg);
658        adapter.setFace(Type.CubemapFace.POSITVE_Z);
659        adapter.copyFrom(zpos);
660        adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
661        adapter.copyFrom(zneg);
662
663        return cubemap;
664    }
665
666    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
667                                                        Bitmap xpos,
668                                                        Bitmap xneg,
669                                                        Bitmap ypos,
670                                                        Bitmap yneg,
671                                                        Bitmap zpos,
672                                                        Bitmap zneg) {
673        return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
674                                          zpos, zneg, MipmapControl.MIPMAP_NONE,
675                                          USAGE_GRAPHICS_TEXTURE);
676    }
677
678    static public Allocation createFromBitmapResource(RenderScript rs,
679                                                      Resources res,
680                                                      int id,
681                                                      MipmapControl mips,
682                                                      int usage) {
683
684        rs.validate();
685        Bitmap b = BitmapFactory.decodeResource(res, id);
686        Allocation alloc = createFromBitmap(rs, b, mips, usage);
687        b.recycle();
688        return alloc;
689    }
690
691    static public Allocation createFromBitmapResource(RenderScript rs,
692                                                      Resources res,
693                                                      int id) {
694        return createFromBitmapResource(rs, res, id,
695                                        MipmapControl.MIPMAP_NONE,
696                                        USAGE_GRAPHICS_TEXTURE);
697    }
698
699    static public Allocation createFromString(RenderScript rs,
700                                              String str,
701                                              int usage) {
702        rs.validate();
703        byte[] allocArray = null;
704        try {
705            allocArray = str.getBytes("UTF-8");
706            Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
707            alloc.copyFrom(allocArray);
708            return alloc;
709        }
710        catch (Exception e) {
711            throw new RSRuntimeException("Could not convert string to utf-8.");
712        }
713    }
714}
715
716
717