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