AllocationAdapter.java revision ee2d809ab099e67698a37f13a42d22eaa2251f77
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 android.content.res.Resources;
20import android.content.res.AssetManager;
21import android.graphics.Bitmap;
22import android.graphics.BitmapFactory;
23import android.util.Log;
24import android.util.TypedValue;
25
26/**
27 *
28 **/
29public class AllocationAdapter extends Allocation {
30    private boolean mConstrainedLOD;
31    private boolean mConstrainedFace;
32    private boolean mConstrainedY;
33    private boolean mConstrainedZ;
34
35    private int mSelectedDimX;
36    private int mSelectedDimY;
37    private int mSelectedDimZ;
38    private int mSelectedCount;
39    private Allocation mAlloc;
40
41    private int mSelectedLOD = 0;
42    private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITIVE_X;
43
44    AllocationAdapter(int id, RenderScript rs, Allocation alloc) {
45        super(id, rs, null, alloc.mUsage);
46        mAlloc = alloc;
47    }
48
49
50    int getID() {
51        return mAlloc.getID();
52    }
53
54    public void copyFrom(BaseObj[] d) {
55        mRS.validate();
56        if (d.length != mSelectedCount) {
57            throw new RSIllegalArgumentException("Array size mismatch, allocation size = " +
58                                                 mSelectedCount + ", array length = " + d.length);
59        }
60        int i[] = new int[d.length];
61        for (int ct=0; ct < d.length; ct++) {
62            i[ct] = d[ct].getID();
63        }
64        subData1D(0, mAlloc.mType.getCount(), i);
65    }
66
67    void validateBitmap(Bitmap b) {
68        mRS.validate();
69        if(mSelectedDimX != b.getWidth() ||
70           mSelectedDimY != b.getHeight()) {
71            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
72        }
73    }
74
75    public void copyFrom(int[] d) {
76        mRS.validate();
77        subData1D(0, mSelectedCount, d);
78    }
79    public void copyFrom(short[] d) {
80        mRS.validate();
81        subData1D(0, mSelectedCount, d);
82    }
83    public void copyFrom(byte[] d) {
84        mRS.validate();
85        subData1D(0, mSelectedCount, d);
86    }
87    public void copyFrom(float[] d) {
88        mRS.validate();
89        subData1D(0, mSelectedCount, d);
90    }
91    public void copyFrom(Bitmap b) {
92        validateBitmap(b);
93        mRS.nAllocationCopyFromBitmap(getID(), b);
94    }
95
96    public void copyTo(Bitmap b) {
97        validateBitmap(b);
98        mRS.nAllocationCopyToBitmap(getID(), b);
99    }
100
101
102    public void subData(int xoff, FieldPacker fp) {
103        int eSize = mAlloc.mType.mElement.getSizeBytes();
104        final byte[] data = fp.getData();
105
106        int count = data.length / eSize;
107        if ((eSize * count) != data.length) {
108            throw new RSIllegalArgumentException("Field packer length " + data.length +
109                                               " not divisible by element size " + eSize + ".");
110        }
111        data1DChecks(xoff, count, data.length, data.length);
112        mRS.nAllocationData1D(getID(), xoff, mSelectedLOD, count, data, data.length);
113    }
114
115
116    public void subElementData(int xoff, int component_number, FieldPacker fp) {
117        if (component_number >= mAlloc.mType.mElement.mElements.length) {
118            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
119        }
120        if(xoff < 0) {
121            throw new RSIllegalArgumentException("Offset must be >= 0.");
122        }
123
124        final byte[] data = fp.getData();
125        int eSize = mAlloc.mType.mElement.mElements[component_number].getSizeBytes();
126
127        if (data.length != eSize) {
128            throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
129                                               " does not match component size " + eSize + ".");
130        }
131
132        mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD, component_number, data, data.length);
133    }
134
135    void data1DChecks(int off, int count, int len, int dataSize) {
136        mRS.validate();
137        if(off < 0) {
138            throw new RSIllegalArgumentException("Offset must be >= 0.");
139        }
140        if(count < 1) {
141            throw new RSIllegalArgumentException("Count must be >= 1.");
142        }
143        if((off + count) > mSelectedCount) {
144            throw new RSIllegalArgumentException("Overflow, Available count " + mAlloc.mType.getCount() +
145                                               ", got " + count + " at offset " + off + ".");
146        }
147        if((len) < dataSize) {
148            throw new RSIllegalArgumentException("Array too small for allocation type.  len = " +
149                                                 len + ", dataSize = " + dataSize);
150        }
151    }
152
153    public void subData1D(int off, int count, int[] d) {
154        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
155        data1DChecks(off, count, d.length * 4, dataSize);
156        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
157    }
158    public void subData1D(int off, int count, short[] d) {
159        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
160        data1DChecks(off, count, d.length * 2, dataSize);
161        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
162    }
163    public void subData1D(int off, int count, byte[] d) {
164        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
165        data1DChecks(off, count, d.length, dataSize);
166        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
167    }
168    public void subData1D(int off, int count, float[] d) {
169        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
170        data1DChecks(off, count, d.length * 4, dataSize);
171        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
172    }
173
174    /**
175     * Copy part of an allocation from another allocation.
176     *
177     * @param off The offset of the first element to be copied.
178     * @param count The number of elements to be copied.
179     * @param data the source data allocation.
180     * @param dataOff off The offset of the first element in data to
181     *          be copied.
182     */
183    public void subData1D(int off, int count, AllocationAdapter data, int dataOff) {
184        mRS.nAllocationData2D(getID(), off, 0,
185                              mSelectedLOD, mSelectedFace.mID,
186                              count, 1, data.getID(), dataOff, 0,
187                              data.mSelectedLOD, data.mSelectedFace.mID);
188    }
189
190
191    public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
192        mRS.validate();
193        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
194                              w, h, d, d.length * 4);
195    }
196
197    public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
198        mRS.validate();
199        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
200                              w, h, d, d.length * 4);
201    }
202
203    /**
204     * Copy a rectangular region into the allocation from another
205     * allocation.
206     *
207     * @param xoff X offset of the region to update.
208     * @param yoff Y offset of the region to update.
209     * @param w Width of the incoming region to update.
210     * @param h Height of the incoming region to update.
211     * @param data source allocation.
212     * @param dataXoff X offset in data of the region to update.
213     * @param dataYoff Y offset in data of the region to update.
214     */
215    public void subData2D(int xoff, int yoff, int w, int h,
216                          AllocationAdapter data, int dataXoff, int dataYoff) {
217        mRS.validate();
218        mRS.nAllocationData2D(getID(), xoff, yoff,
219                              mSelectedLOD, mSelectedFace.mID,
220                              w, h, data.getID(), dataXoff, dataYoff,
221                              data.mSelectedLOD, data.mSelectedFace.mID);
222    }
223
224    public void readData(int[] d) {
225        mRS.validate();
226        mRS.nAllocationRead(getID(), d);
227    }
228
229    public void readData(float[] d) {
230        mRS.validate();
231        mRS.nAllocationRead(getID(), d);
232    }
233
234    private void initLOD(int lod) {
235        if (lod < 0) {
236            throw new RSIllegalArgumentException("Attempting to set negative lod (" + lod + ").");
237        }
238
239        int tx = mAlloc.mType.getX();
240        int ty = mAlloc.mType.getY();
241        int tz = mAlloc.mType.getZ();
242
243        for (int ct=0; ct < lod; ct++) {
244            if ((tx==1) && (ty == 1) && (tz == 1)) {
245                throw new RSIllegalArgumentException("Attempting to set lod (" + lod + ") out of range.");
246            }
247
248            if (tx > 1) tx >>= 1;
249            if (ty > 1) ty >>= 1;
250            if (tz > 1) tz >>= 1;
251        }
252
253        mSelectedDimX = tx;
254        mSelectedDimY = ty;
255        mSelectedCount = tx;
256        if (ty > 1) {
257            mSelectedCount *= ty;
258        }
259        if (tz > 1) {
260            mSelectedCount *= tz;
261        }
262    }
263
264    /**
265     * Set the active LOD.  The LOD must be within the range for the
266     * type being adapted.
267     *
268     * @param lod The LOD to make active.
269     */
270    public void setLOD(int lod) {
271        if (!mAlloc.getType().hasMipmaps()) {
272            throw new RSInvalidStateException("Cannot set LOD when the allocation type does not include mipmaps.");
273        }
274        if (!mConstrainedLOD) {
275            throw new RSInvalidStateException("Cannot set LOD when the adapter includes mipmaps.");
276        }
277
278        initLOD(lod);
279    }
280
281    public void setFace(Type.CubemapFace cf) {
282        mSelectedFace = cf;
283    }
284
285    public void setY(int y) {
286        mSelectedDimY = y;
287    }
288
289    public void setZ(int z) {
290    }
291
292    // creation
293    //static public AllocationAdapter create1D(RenderScript rs, Allocation a) {
294    //}
295
296    static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
297        rs.validate();
298        AllocationAdapter aa = new AllocationAdapter(0, rs, a);
299        aa.mConstrainedLOD = true;
300        aa.mConstrainedFace = true;
301        aa.mConstrainedY = false;
302        aa.mConstrainedZ = true;
303        aa.initLOD(0);
304        return aa;
305    }
306
307
308}
309
310
311