Allocation.java revision 5edc608a0749ed4b7074b5c1243043eb722c3c31
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;
21
22import android.content.res.Resources;
23import android.content.res.AssetManager;
24import android.graphics.Bitmap;
25import android.graphics.BitmapFactory;
26import android.util.Log;
27import android.util.TypedValue;
28
29/**
30 * @hide
31 *
32 **/
33public class Allocation extends BaseObj {
34    Type mType;
35    Bitmap mBitmap;
36
37    Allocation(int id, RenderScript rs, Type t) {
38        super(id, rs);
39        mType = t;
40    }
41
42    Allocation(int id, RenderScript rs) {
43        super(id, rs);
44    }
45
46    @Override
47    void updateFromNative() {
48        mRS.validate();
49        mName = mRS.nGetName(mID);
50        int typeID = mRS.nAllocationGetType(mID);
51        if(typeID != 0) {
52            mType = new Type(typeID, mRS);
53            mType.updateFromNative();
54        }
55    }
56
57    public Type getType() {
58        return mType;
59    }
60
61    public void uploadToTexture(int baseMipLevel) {
62        mRS.validate();
63        mRS.nAllocationUploadToTexture(mID, false, baseMipLevel);
64    }
65
66    public void uploadToTexture(boolean genMips, int baseMipLevel) {
67        mRS.validate();
68        mRS.nAllocationUploadToTexture(mID, genMips, baseMipLevel);
69    }
70
71    public void uploadToBufferObject() {
72        mRS.validate();
73        mRS.nAllocationUploadToBufferObject(mID);
74    }
75
76    public void data(int[] d) {
77        mRS.validate();
78        subData1D(0, mType.getElementCount(), d);
79    }
80    public void data(short[] d) {
81        mRS.validate();
82        subData1D(0, mType.getElementCount(), d);
83    }
84    public void data(byte[] d) {
85        mRS.validate();
86        subData1D(0, mType.getElementCount(), d);
87    }
88    public void data(float[] d) {
89        mRS.validate();
90        subData1D(0, mType.getElementCount(), d);
91    }
92
93    public void subData(int xoff, FieldPacker fp) {
94        int eSize = mType.mElement.getSizeBytes();
95        final byte[] data = fp.getData();
96
97        int count = data.length / eSize;
98        if ((eSize * count) != data.length) {
99            throw new IllegalArgumentException("Field packer length " + data.length +
100                                               " not divisible by element size " + eSize + ".");
101        }
102        data1DChecks(xoff, count, data.length, data.length);
103        mRS.nAllocationSubData1D(mID, xoff, count, data, data.length);
104    }
105
106
107    public void subElementData(int xoff, int component_number, FieldPacker fp) {
108        if (component_number >= mType.mElement.mElements.length) {
109            throw new IllegalArgumentException("Component_number " + component_number + " out of range.");
110        }
111        if(xoff < 0) {
112            throw new IllegalArgumentException("Offset must be >= 0.");
113        }
114
115        final byte[] data = fp.getData();
116        int eSize = mType.mElement.mElements[component_number].getSizeBytes();
117
118        if (data.length != eSize) {
119            throw new IllegalArgumentException("Field packer sizelength " + data.length +
120                                               " does not match component size " + eSize + ".");
121        }
122
123        mRS.nAllocationSubElementData1D(mID, xoff, component_number, data, data.length);
124    }
125
126    private void data1DChecks(int off, int count, int len, int dataSize) {
127        mRS.validate();
128        if(off < 0) {
129            throw new IllegalArgumentException("Offset must be >= 0.");
130        }
131        if(count < 1) {
132            throw new IllegalArgumentException("Count must be >= 1.");
133        }
134        if((off + count) > mType.getElementCount()) {
135            throw new IllegalArgumentException("Overflow, Available count " + mType.getElementCount() +
136                                               ", got " + count + " at offset " + off + ".");
137        }
138        if((len) < dataSize) {
139            throw new IllegalArgumentException("Array too small for allocation type.");
140        }
141    }
142
143    public void subData1D(int off, int count, int[] d) {
144        int dataSize = mType.mElement.getSizeBytes() * count;
145        data1DChecks(off, count, d.length * 4, dataSize);
146        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
147    }
148    public void subData1D(int off, int count, short[] d) {
149        int dataSize = mType.mElement.getSizeBytes() * count;
150        data1DChecks(off, count, d.length * 2, dataSize);
151        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
152    }
153    public void subData1D(int off, int count, byte[] d) {
154        int dataSize = mType.mElement.getSizeBytes() * count;
155        data1DChecks(off, count, d.length, dataSize);
156        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
157    }
158    public void subData1D(int off, int count, float[] d) {
159        int dataSize = mType.mElement.getSizeBytes() * count;
160        data1DChecks(off, count, d.length * 4, dataSize);
161        mRS.nAllocationSubData1D(mID, off, count, d, dataSize);
162    }
163
164
165    public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
166        mRS.validate();
167        mRS.nAllocationSubData2D(mID, xoff, yoff, w, h, d, d.length * 4);
168    }
169
170    public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
171        mRS.validate();
172        mRS.nAllocationSubData2D(mID, xoff, yoff, w, h, d, d.length * 4);
173    }
174
175    public void readData(int[] d) {
176        mRS.validate();
177        mRS.nAllocationRead(mID, d);
178    }
179
180    public void readData(float[] d) {
181        mRS.validate();
182        mRS.nAllocationRead(mID, d);
183    }
184
185    public void resize(int dimX) {
186        if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
187            throw new IllegalStateException("Resize only support for 1D allocations at this time.");
188        }
189        mRS.nAllocationResize1D(mID, dimX);
190    }
191
192    /*
193    public void resize(int dimX, int dimY) {
194        if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
195            throw new IllegalStateException("Resize only support for 2D allocations at this time.");
196        }
197        if (mType.getY() == 0) {
198            throw new IllegalStateException("Resize only support for 2D allocations at this time.");
199        }
200        mRS.nAllocationResize2D(mID, dimX, dimY);
201    }
202    */
203
204    public class Adapter1D extends BaseObj {
205        Adapter1D(int id, RenderScript rs) {
206            super(id, rs);
207        }
208
209        public void setConstraint(Dimension dim, int value) {
210            mRS.validate();
211            mRS.nAdapter1DSetConstraint(mID, dim.mID, value);
212        }
213
214        public void data(int[] d) {
215            mRS.validate();
216            mRS.nAdapter1DData(mID, d);
217        }
218
219        public void data(float[] d) {
220            mRS.validate();
221            mRS.nAdapter1DData(mID, d);
222        }
223
224        public void subData(int off, int count, int[] d) {
225            mRS.validate();
226            mRS.nAdapter1DSubData(mID, off, count, d);
227        }
228
229        public void subData(int off, int count, float[] d) {
230            mRS.validate();
231            mRS.nAdapter1DSubData(mID, off, count, d);
232        }
233    }
234
235    public Adapter1D createAdapter1D() {
236        mRS.validate();
237        int id = mRS.nAdapter1DCreate();
238        if(id == 0) {
239            throw new IllegalStateException("allocation failed.");
240        }
241        mRS.nAdapter1DBindAllocation(id, mID);
242        return new Adapter1D(id, mRS);
243    }
244
245
246    public class Adapter2D extends BaseObj {
247        Adapter2D(int id, RenderScript rs) {
248            super(id, rs);
249        }
250
251        public void setConstraint(Dimension dim, int value) {
252            mRS.validate();
253            mRS.nAdapter2DSetConstraint(mID, dim.mID, value);
254        }
255
256        public void data(int[] d) {
257            mRS.validate();
258            mRS.nAdapter2DData(mID, d);
259        }
260
261        public void data(float[] d) {
262            mRS.validate();
263            mRS.nAdapter2DData(mID, d);
264        }
265
266        public void subData(int xoff, int yoff, int w, int h, int[] d) {
267            mRS.validate();
268            mRS.nAdapter2DSubData(mID, xoff, yoff, w, h, d);
269        }
270
271        public void subData(int xoff, int yoff, int w, int h, float[] d) {
272            mRS.validate();
273            mRS.nAdapter2DSubData(mID, xoff, yoff, w, h, d);
274        }
275    }
276
277    public Adapter2D createAdapter2D() {
278        mRS.validate();
279        int id = mRS.nAdapter2DCreate();
280        if(id == 0) {
281            throw new IllegalStateException("allocation failed.");
282        }
283        mRS.nAdapter2DBindAllocation(id, mID);
284        return new Adapter2D(id, mRS);
285    }
286
287
288    // creation
289
290    private static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
291    static {
292        mBitmapOptions.inScaled = false;
293    }
294
295    static public Allocation createTyped(RenderScript rs, Type type)
296        throws IllegalArgumentException {
297
298        rs.validate();
299        if(type.mID == 0) {
300            throw new IllegalStateException("Bad Type");
301        }
302        int id = rs.nAllocationCreateTyped(type.mID);
303        return new Allocation(id, rs, type);
304    }
305
306    static public Allocation createSized(RenderScript rs, Element e, int count)
307        throws IllegalArgumentException {
308
309        rs.validate();
310        Type.Builder b = new Type.Builder(rs, e);
311        b.add(Dimension.X, count);
312        Type t = b.create();
313
314        int id = rs.nAllocationCreateTyped(t.mID);
315        if(id == 0) {
316            throw new IllegalStateException("Bad element.");
317        }
318        return new Allocation(id, rs, t);
319    }
320
321    static private Element elementFromBitmap(RenderScript rs, Bitmap b) {
322        final Bitmap.Config bc = b.getConfig();
323        if (bc == Bitmap.Config.ALPHA_8) {
324            return Element.A_8(rs);
325        }
326        if (bc == Bitmap.Config.ARGB_4444) {
327            return Element.RGBA_4444(rs);
328        }
329        if (bc == Bitmap.Config.ARGB_8888) {
330            return Element.RGBA_8888(rs);
331        }
332        if (bc == Bitmap.Config.RGB_565) {
333            return Element.RGB_565(rs);
334        }
335        throw new IllegalStateException("Bad bitmap type.");
336    }
337
338    static private Type typeFromBitmap(RenderScript rs, Bitmap b) {
339        Element e = elementFromBitmap(rs, b);
340        Type.Builder tb = new Type.Builder(rs, e);
341        tb.add(Dimension.X, b.getWidth());
342        tb.add(Dimension.Y, b.getHeight());
343        return tb.create();
344    }
345
346    static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
347        throws IllegalArgumentException {
348
349        rs.validate();
350        Type t = typeFromBitmap(rs, b);
351
352        int id = rs.nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
353        if(id == 0) {
354            throw new IllegalStateException("Load failed.");
355        }
356        return new Allocation(id, rs, t);
357    }
358
359    static public Allocation createBitmapRef(RenderScript rs, Bitmap b)
360        throws IllegalArgumentException {
361
362        rs.validate();
363        Type t = typeFromBitmap(rs, b);
364
365        int id = rs.nAllocationCreateBitmapRef(t.getID(), b);
366        if(id == 0) {
367            throw new IllegalStateException("Load failed.");
368        }
369
370        Allocation a = new Allocation(id, rs, t);
371        a.mBitmap = b;
372        return a;
373    }
374
375    static Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
376        throws IllegalArgumentException {
377
378        rs.validate();
379        int id = rs.nAllocationCreateFromBitmapBoxed(dstFmt.mID, genMips, b);
380        if(id == 0) {
381            throw new IllegalStateException("Load failed.");
382        }
383        return new Allocation(id, rs, null);
384    }
385
386    static public Allocation createFromBitmapResource(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips)
387        throws IllegalArgumentException {
388
389        rs.validate();
390        InputStream is = null;
391        try {
392            final TypedValue value = new TypedValue();
393            is = res.openRawResource(id, value);
394
395            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
396            int allocationId = rs.nAllocationCreateFromAssetStream(dstFmt.mID, genMips,
397                    asset);
398
399            if(allocationId == 0) {
400                throw new IllegalStateException("Load failed.");
401            }
402            return new Allocation(allocationId, rs, null);
403        } catch (Exception e) {
404            // Ignore
405        } finally {
406            if (is != null) {
407                try {
408                    is.close();
409                } catch (IOException e) {
410                    // Ignore
411                }
412            }
413        }
414
415        return null;
416    }
417
418    static public Allocation createFromBitmapResourceBoxed(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips)
419        throws IllegalArgumentException {
420
421        mBitmapOptions.inPreferredConfig = null;
422        if (dstFmt == rs.mElement_RGBA_8888) {
423            mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
424        } else if (dstFmt == rs.mElement_RGB_888) {
425            mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
426        } else if (dstFmt == rs.mElement_RGBA_4444) {
427            mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_4444;
428        } else if (dstFmt == rs.mElement_RGB_565) {
429            mBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
430        }
431
432        Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
433        return createFromBitmapBoxed(rs, b, dstFmt, genMips);
434    }
435
436    static public Allocation createFromString(RenderScript rs, String str)
437        throws IllegalArgumentException {
438        byte[] allocArray = null;
439        try {
440            allocArray = str.getBytes("UTF-8");
441            Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length);
442            alloc.data(allocArray);
443            return alloc;
444        }
445        catch (Exception e) {
446            Log.e("rs", "could not convert string to utf-8");
447        }
448        return null;
449    }
450}
451
452
453