Allocation.java revision f7086090cfc8d97b5bd3b4d7801a27af11f7c207
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 validateBitmap(Bitmap b) {
166        mRS.validate();
167        if(mType.getX() != b.getWidth() ||
168           mType.getY() != b.getHeight()) {
169            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
170        }
171        Bitmap.Config bc = b.getConfig();
172        switch (bc) {
173        case ALPHA_8:
174            if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
175                throw new RSIllegalArgumentException("Allocation kind is " +
176                                                     mType.getElement().mKind + ", type " +
177                                                     mType.getElement().mType +
178                                                     " of " + mType.getElement().getSizeBytes() +
179                                                     " bytes, passed bitmap was " + bc);
180            }
181            break;
182        case ARGB_8888:
183            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
184                (mType.getElement().getSizeBytes() != 4)) {
185                throw new RSIllegalArgumentException("Allocation kind is " +
186                                                     mType.getElement().mKind + ", type " +
187                                                     mType.getElement().mType +
188                                                     " of " + mType.getElement().getSizeBytes() +
189                                                     " bytes, passed bitmap was " + bc);
190            }
191            break;
192        case RGB_565:
193            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
194                (mType.getElement().getSizeBytes() != 2)) {
195                throw new RSIllegalArgumentException("Allocation kind is " +
196                                                     mType.getElement().mKind + ", type " +
197                                                     mType.getElement().mType +
198                                                     " of " + mType.getElement().getSizeBytes() +
199                                                     " bytes, passed bitmap was " + bc);
200            }
201            break;
202        case ARGB_4444:
203            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
204                (mType.getElement().getSizeBytes() != 2)) {
205                throw new RSIllegalArgumentException("Allocation kind is " +
206                                                     mType.getElement().mKind + ", type " +
207                                                     mType.getElement().mType +
208                                                     " of " + mType.getElement().getSizeBytes() +
209                                                     " bytes, passed bitmap was " + bc);
210            }
211            break;
212
213        }
214    }
215
216    public void copyFrom(int[] d) {
217        mRS.validate();
218        copy1DRangeFrom(0, mType.getCount(), d);
219    }
220    public void copyFrom(short[] d) {
221        mRS.validate();
222        copy1DRangeFrom(0, mType.getCount(), d);
223    }
224    public void copyFrom(byte[] d) {
225        mRS.validate();
226        copy1DRangeFrom(0, mType.getCount(), d);
227    }
228    public void copyFrom(float[] d) {
229        mRS.validate();
230        copy1DRangeFrom(0, mType.getCount(), d);
231    }
232    public void copyFrom(Bitmap b) {
233        validateBitmap(b);
234        mRS.nAllocationCopyFromBitmap(getID(), b);
235    }
236
237    /**
238     * @hide
239     *
240     * This is only intended to be used by auto-generate code reflected from the
241     * renderscript script files.
242     *
243     * @param xoff
244     * @param fp
245     */
246    public void setOneElement(int xoff, FieldPacker fp) {
247        int eSize = mType.mElement.getSizeBytes();
248        final byte[] data = fp.getData();
249
250        int count = data.length / eSize;
251        if ((eSize * count) != data.length) {
252            throw new RSIllegalArgumentException("Field packer length " + data.length +
253                                               " not divisible by element size " + eSize + ".");
254        }
255        data1DChecks(xoff, count, data.length, data.length);
256        mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length);
257    }
258
259
260    /**
261     * @hide
262     *
263     * This is only intended to be used by auto-generate code reflected from the
264     * renderscript script files.
265     *
266     * @param xoff
267     * @param component_number
268     * @param fp
269     */
270    public void setOneComponent(int xoff, int component_number, FieldPacker fp) {
271        if (component_number >= mType.mElement.mElements.length) {
272            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
273        }
274        if(xoff < 0) {
275            throw new RSIllegalArgumentException("Offset must be >= 0.");
276        }
277
278        final byte[] data = fp.getData();
279        int eSize = mType.mElement.mElements[component_number].getSizeBytes();
280
281        if (data.length != eSize) {
282            throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
283                                               " does not match component size " + eSize + ".");
284        }
285
286        mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length);
287    }
288
289    private void data1DChecks(int off, int count, int len, int dataSize) {
290        mRS.validate();
291        if(off < 0) {
292            throw new RSIllegalArgumentException("Offset must be >= 0.");
293        }
294        if(count < 1) {
295            throw new RSIllegalArgumentException("Count must be >= 1.");
296        }
297        if((off + count) > mType.getCount()) {
298            throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() +
299                                               ", got " + count + " at offset " + off + ".");
300        }
301        if((len) < dataSize) {
302            throw new RSIllegalArgumentException("Array too small for allocation type.");
303        }
304    }
305
306    /**
307     * Generate a mipmap chain.  Requires the type of the allocation
308     * include mipmaps.
309     *
310     * This function will generate a complete set of mipmaps from
311     * the top level lod and place them into the script memoryspace.
312     *
313     * If the allocation is also using other memory spaces a
314     * followup sync will be required.
315     */
316    public void generateMipmaps() {
317        mRS.nAllocationGenerateMipmaps(getID());
318    }
319
320    public void copy1DRangeFrom(int off, int count, int[] d) {
321        int dataSize = mType.mElement.getSizeBytes() * count;
322        data1DChecks(off, count, d.length * 4, dataSize);
323        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
324    }
325    public void copy1DRangeFrom(int off, int count, short[] d) {
326        int dataSize = mType.mElement.getSizeBytes() * count;
327        data1DChecks(off, count, d.length * 2, dataSize);
328        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
329    }
330    public void copy1DRangeFrom(int off, int count, byte[] d) {
331        int dataSize = mType.mElement.getSizeBytes() * count;
332        data1DChecks(off, count, d.length, dataSize);
333        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
334    }
335    public void copy1DRangeFrom(int off, int count, float[] d) {
336        int dataSize = mType.mElement.getSizeBytes() * count;
337        data1DChecks(off, count, d.length * 4, dataSize);
338        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
339    }
340
341
342    /**
343     * Copy a rectanglular region from the array into the
344     * allocation.  The incoming array is assumed to be tightly
345     * packed.
346     *
347     * @param xoff X offset of the region to update
348     * @param yoff Y offset of the region to update
349     * @param w Width of the incoming region to update
350     * @param h Height of the incoming region to update
351     * @param data to be placed into the allocation
352     */
353    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
354        mRS.validate();
355        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length);
356    }
357
358    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
359        mRS.validate();
360        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2);
361    }
362
363    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
364        mRS.validate();
365        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
366    }
367
368    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
369        mRS.validate();
370        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
371    }
372
373    /**
374     * Copy a bitmap into an allocation.  The height and width of
375     * the update will use the height and width of the incoming
376     * bitmap.
377     *
378     * @param xoff X offset of the region to update
379     * @param yoff Y offset of the region to update
380     * @param data the bitmap to be copied
381     */
382    public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
383        mRS.validate();
384        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data);
385    }
386
387
388    public void copyTo(Bitmap b) {
389        validateBitmap(b);
390        mRS.nAllocationCopyToBitmap(getID(), b);
391    }
392
393    public void copyTo(byte[] d) {
394        mRS.validate();
395        mRS.nAllocationRead(getID(), d);
396    }
397
398    public void copyTo(short[] d) {
399        mRS.validate();
400        mRS.nAllocationRead(getID(), d);
401    }
402
403    public void copyTo(int[] d) {
404        mRS.validate();
405        mRS.nAllocationRead(getID(), d);
406    }
407
408    public void copyTo(float[] d) {
409        mRS.validate();
410        mRS.nAllocationRead(getID(), d);
411    }
412
413    /**
414     * Resize a 1D allocation.  The contents of the allocation are
415     * preserved.  If new elements are allocated objects are created
416     * with null contents and the new region is otherwise undefined.
417     *
418     * If the new region is smaller the references of any objects
419     * outside the new region will be released.
420     *
421     * A new type will be created with the new dimension.
422     *
423     * @param dimX The new size of the allocation.
424     */
425    public synchronized void resize(int dimX) {
426        if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
427            throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
428        }
429        mRS.nAllocationResize1D(getID(), dimX);
430        mRS.finish();  // Necessary because resize is fifoed and update is async.
431
432        int typeID = mRS.nAllocationGetType(getID());
433        mType = new Type(typeID, mRS);
434        mType.updateFromNative();
435    }
436
437    /*
438    public void resize(int dimX, int dimY) {
439        if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
440            throw new RSIllegalStateException("Resize only support for 2D allocations at this time.");
441        }
442        if (mType.getY() == 0) {
443            throw new RSIllegalStateException("Resize only support for 2D allocations at this time.");
444        }
445        mRS.nAllocationResize2D(getID(), dimX, dimY);
446    }
447    */
448
449
450
451    // creation
452
453    static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
454    static {
455        mBitmapOptions.inScaled = false;
456    }
457
458    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mc, int usage) {
459        rs.validate();
460        if (type.getID() == 0) {
461            throw new RSInvalidStateException("Bad Type");
462        }
463        int id = rs.nAllocationCreateTyped(type.getID(), mc.mID, usage);
464        if (id == 0) {
465            throw new RSRuntimeException("Allocation creation failed.");
466        }
467        return new Allocation(id, rs, type, usage);
468    }
469
470    static public Allocation createTyped(RenderScript rs, Type type, int usage) {
471        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
472    }
473
474    static public Allocation createTyped(RenderScript rs, Type type) {
475        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
476    }
477
478    static public Allocation createSized(RenderScript rs, Element e,
479                                         int count, int usage) {
480        rs.validate();
481        Type.Builder b = new Type.Builder(rs, e);
482        b.setX(count);
483        Type t = b.create();
484
485        int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage);
486        if (id == 0) {
487            throw new RSRuntimeException("Allocation creation failed.");
488        }
489        return new Allocation(id, rs, t, usage);
490    }
491
492    static public Allocation createSized(RenderScript rs, Element e, int count) {
493        return createSized(rs, e, count, USAGE_SCRIPT);
494    }
495
496    static Element elementFromBitmap(RenderScript rs, Bitmap b) {
497        final Bitmap.Config bc = b.getConfig();
498        if (bc == Bitmap.Config.ALPHA_8) {
499            return Element.A_8(rs);
500        }
501        if (bc == Bitmap.Config.ARGB_4444) {
502            return Element.RGBA_4444(rs);
503        }
504        if (bc == Bitmap.Config.ARGB_8888) {
505            return Element.RGBA_8888(rs);
506        }
507        if (bc == Bitmap.Config.RGB_565) {
508            return Element.RGB_565(rs);
509        }
510        throw new RSInvalidStateException("Bad bitmap type: " + bc);
511    }
512
513    static Type typeFromBitmap(RenderScript rs, Bitmap b,
514                                       MipmapControl mip) {
515        Element e = elementFromBitmap(rs, b);
516        Type.Builder tb = new Type.Builder(rs, e);
517        tb.setX(b.getWidth());
518        tb.setY(b.getHeight());
519        tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
520        return tb.create();
521    }
522
523    static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
524                                              MipmapControl mips,
525                                              int usage) {
526        rs.validate();
527        Type t = typeFromBitmap(rs, b, mips);
528
529        int id = rs.nAllocationCreateFromBitmap(t.getID(), mips.mID, b, usage);
530        if (id == 0) {
531            throw new RSRuntimeException("Load failed.");
532        }
533        return new Allocation(id, rs, t, usage);
534    }
535
536    static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
537        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
538                                USAGE_GRAPHICS_TEXTURE);
539    }
540
541    /**
542    * Creates a cubemap allocation from a bitmap containing the
543    * horizontal list of cube faces. Each individual face must be
544    * the same size and power of 2
545    *
546    * @param rs
547    * @param b bitmap with cubemap faces layed out in the following
548    *          format: right, left, top, bottom, front, back
549    * @param mips specifies desired mipmap behaviour for the cubemap
550    * @param usage bitfield specifying how the cubemap is utilized
551    *
552    **/
553    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
554                                                     MipmapControl mips,
555                                                     int usage) {
556        rs.validate();
557
558        int height = b.getHeight();
559        int width = b.getWidth();
560
561        if (width % 6 != 0) {
562            throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
563        }
564        if (width / 6 != height) {
565            throw new RSIllegalArgumentException("Only square cube map faces supported");
566        }
567        boolean isPow2 = (height & (height - 1)) == 0;
568        if (!isPow2) {
569            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
570        }
571
572        Element e = elementFromBitmap(rs, b);
573        Type.Builder tb = new Type.Builder(rs, e);
574        tb.setX(height);
575        tb.setY(height);
576        tb.setFaces(true);
577        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
578        Type t = tb.create();
579
580        int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage);
581        if(id == 0) {
582            throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
583        }
584        return new Allocation(id, rs, t, usage);
585    }
586
587    static public Allocation createCubemapFromBitmap(RenderScript rs,
588                                                     Bitmap b) {
589        return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
590                                       USAGE_GRAPHICS_TEXTURE);
591    }
592
593    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
594                                                        Bitmap xpos,
595                                                        Bitmap xneg,
596                                                        Bitmap ypos,
597                                                        Bitmap yneg,
598                                                        Bitmap zpos,
599                                                        Bitmap zneg,
600                                                        MipmapControl mips,
601                                                        int usage) {
602        int height = xpos.getHeight();
603        if (xpos.getWidth() != height ||
604            xneg.getWidth() != height || xneg.getHeight() != height ||
605            ypos.getWidth() != height || ypos.getHeight() != height ||
606            yneg.getWidth() != height || yneg.getHeight() != height ||
607            zpos.getWidth() != height || zpos.getHeight() != height ||
608            zneg.getWidth() != height || zneg.getHeight() != height) {
609            throw new RSIllegalArgumentException("Only square cube map faces supported");
610        }
611        boolean isPow2 = (height & (height - 1)) == 0;
612        if (!isPow2) {
613            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
614        }
615
616        Element e = elementFromBitmap(rs, xpos);
617        Type.Builder tb = new Type.Builder(rs, e);
618        tb.setX(height);
619        tb.setY(height);
620        tb.setFaces(true);
621        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
622        Type t = tb.create();
623        Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
624
625        AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
626        adapter.setFace(Type.CubemapFace.POSITVE_X);
627        adapter.copyFrom(xpos);
628        adapter.setFace(Type.CubemapFace.NEGATIVE_X);
629        adapter.copyFrom(xneg);
630        adapter.setFace(Type.CubemapFace.POSITVE_Y);
631        adapter.copyFrom(ypos);
632        adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
633        adapter.copyFrom(yneg);
634        adapter.setFace(Type.CubemapFace.POSITVE_Z);
635        adapter.copyFrom(zpos);
636        adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
637        adapter.copyFrom(zneg);
638
639        return cubemap;
640    }
641
642    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
643                                                        Bitmap xpos,
644                                                        Bitmap xneg,
645                                                        Bitmap ypos,
646                                                        Bitmap yneg,
647                                                        Bitmap zpos,
648                                                        Bitmap zneg) {
649        return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
650                                          zpos, zneg, MipmapControl.MIPMAP_NONE,
651                                          USAGE_GRAPHICS_TEXTURE);
652    }
653
654    static public Allocation createFromBitmapResource(RenderScript rs,
655                                                      Resources res,
656                                                      int id,
657                                                      MipmapControl mips,
658                                                      int usage) {
659
660        rs.validate();
661        Bitmap b = BitmapFactory.decodeResource(res, id);
662        Allocation alloc = createFromBitmap(rs, b, mips, usage);
663        b.recycle();
664        return alloc;
665    }
666
667    static public Allocation createFromBitmapResource(RenderScript rs,
668                                                      Resources res,
669                                                      int id) {
670        return createFromBitmapResource(rs, res, id,
671                                        MipmapControl.MIPMAP_NONE,
672                                        USAGE_GRAPHICS_TEXTURE);
673    }
674
675    static public Allocation createFromString(RenderScript rs,
676                                              String str,
677                                              int usage) {
678        rs.validate();
679        byte[] allocArray = null;
680        try {
681            allocArray = str.getBytes("UTF-8");
682            Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
683            alloc.copyFrom(allocArray);
684            return alloc;
685        }
686        catch (Exception e) {
687            throw new RSRuntimeException("Could not convert string to utf-8.");
688        }
689    }
690}
691
692
693