Type.java revision 355707e4f665904e31d9f5fcff1e3921f7db8cdd
1/*
2 * Copyright (C) 2013 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
19
20import java.lang.reflect.Field;
21
22import android.graphics.ImageFormat;
23import android.util.Log;
24
25/**
26 * <p>A Type describes the {@link android.renderscript.Element} and dimensions used for an {@link
27 * android.renderscript.Allocation} or a parallel operation. Types are created through {@link
28 * android.renderscript.Type.Builder}.</p>
29 *
30 * <p>A Type always includes an {@link android.renderscript.Element} and an X
31 * dimension. A Type may be multidimensional, up to three dimensions. A nonzero
32 * value in the Y or Z dimensions indicates that the dimension is present. Note
33 * that a Type with only a given X dimension and a Type with the same X
34 * dimension but Y = 1 are not equivalent.</p>
35 *
36 * <p>A Type also supports inclusion of level of detail (LOD) or cube map
37 * faces. LOD and cube map faces are booleans to indicate present or not
38 * present. </p>
39 *
40 * <p>A Type also supports YUV format information to support an
41 * {@link android.renderscript.Allocation} in a YUV format. The YUV formats
42 * supported are {@link android.graphics.ImageFormat#YV12},
43 * {@link android.graphics.ImageFormat#NV21}, and
44 * {@link android.graphics.ImageFormat#YUV_420_888}</p>
45 *
46 * <div class="special reference">
47 * <h3>Developer Guides</h3>
48 * <p>For more information about creating an application that uses RenderScript, read the
49 * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p>
50 * </div>
51 **/
52public class Type extends BaseObj {
53    int mDimX;
54    int mDimY;
55    int mDimZ;
56    boolean mDimMipmaps;
57    boolean mDimFaces;
58    int mDimYuv;
59    int mElementCount;
60    Element mElement;
61
62    public enum CubemapFace {
63        POSITIVE_X (0),
64        NEGATIVE_X (1),
65        POSITIVE_Y (2),
66        NEGATIVE_Y (3),
67        POSITIVE_Z (4),
68        NEGATIVE_Z (5),
69        @Deprecated
70        POSITVE_X (0),
71        @Deprecated
72        POSITVE_Y (2),
73        @Deprecated
74        POSITVE_Z (4);
75
76        int mID;
77        CubemapFace(int id) {
78            mID = id;
79        }
80    }
81
82    /**
83     * Return the element associated with this Type.
84     *
85     * @return Element
86     */
87    public Element getElement() {
88        return mElement;
89    }
90
91    /**
92     * Return the value of the X dimension.
93     *
94     * @return int
95     */
96    public int getX() {
97        return mDimX;
98    }
99
100    /**
101     * Return the value of the Y dimension or 0 for a 1D allocation.
102     *
103     * @return int
104     */
105    public int getY() {
106        return mDimY;
107    }
108
109    /**
110     * Return the value of the Z dimension or 0 for a 1D or 2D allocation.
111     *
112     * @return int
113     */
114    public int getZ() {
115        return mDimZ;
116    }
117
118    /**
119     * Get the YUV format
120     *
121     *
122     * @return int
123     */
124    public int getYuv() {
125        return mDimYuv;
126    }
127
128    /**
129     * Return if the Type has a mipmap chain.
130     *
131     * @return boolean
132     */
133    public boolean hasMipmaps() {
134        return mDimMipmaps;
135    }
136
137    /**
138     * Return if the Type is a cube map.
139     *
140     * @return boolean
141     */
142    public boolean hasFaces() {
143        return mDimFaces;
144    }
145
146    /**
147     * Return the total number of accessable cells in the Type.
148     *
149     * @return int
150     */
151    public int getCount() {
152        return mElementCount;
153    }
154
155    void calcElementCount() {
156        boolean hasLod = hasMipmaps();
157        int x = getX();
158        int y = getY();
159        int z = getZ();
160        int faces = 1;
161        if (hasFaces()) {
162            faces = 6;
163        }
164        if (x == 0) {
165            x = 1;
166        }
167        if (y == 0) {
168            y = 1;
169        }
170        if (z == 0) {
171            z = 1;
172        }
173
174        int count = x * y * z * faces;
175
176        while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
177            if(x > 1) {
178                x >>= 1;
179            }
180            if(y > 1) {
181                y >>= 1;
182            }
183            if(z > 1) {
184                z >>= 1;
185            }
186
187            count += x * y * z * faces;
188        }
189        mElementCount = count;
190    }
191
192
193    Type(long id, RenderScript rs) {
194        super(id, rs);
195    }
196
197    @Override
198    void updateFromNative() {
199        // FIXME: rsaTypeGetNativeData needs 32-bit and 64-bit paths
200
201        // We have 6 integer to obtain mDimX; mDimY; mDimZ;
202        // mDimLOD; mDimFaces; mElement;
203        int[] dataBuffer = new int[6];
204        mRS.nTypeGetNativeData((int)getID(mRS), dataBuffer);
205
206        mDimX = dataBuffer[0];
207        mDimY = dataBuffer[1];
208        mDimZ = dataBuffer[2];
209        mDimMipmaps = dataBuffer[3] == 1 ? true : false;
210        mDimFaces = dataBuffer[4] == 1 ? true : false;
211
212        int elementID = dataBuffer[5];
213        if(elementID != 0) {
214            mElement = new Element(elementID, mRS);
215            mElement.updateFromNative();
216        }
217        calcElementCount();
218    }
219
220    /**
221     * Utility function for creating basic 1D types. The type is
222     * created without mipmaps enabled.
223     *
224     * @param rs The RenderScript context
225     * @param e The Element for the Type
226     * @param dimX The X dimension, must be > 0
227     *
228     * @return Type
229     */
230    static public Type createX(RenderScript rs, Element e, int dimX) {
231        if (dimX < 1) {
232            throw new RSInvalidStateException("Dimension must be >= 1.");
233        }
234
235        long id = rs.nTypeCreate(e.getID(rs), dimX, 0, 0, false, false, 0);
236        Type t = new Type(id, rs);
237        t.mElement = e;
238        t.mDimX = dimX;
239        t.calcElementCount();
240        return t;
241    }
242
243    /**
244     * Utility function for creating basic 2D types. The type is
245     * created without mipmaps or cubemaps.
246     *
247     * @param rs The RenderScript context
248     * @param e The Element for the Type
249     * @param dimX The X dimension, must be > 0
250     * @param dimY The Y dimension, must be > 0
251     *
252     * @return Type
253     */
254    static public Type createXY(RenderScript rs, Element e, int dimX, int dimY) {
255        if ((dimX < 1) || (dimY < 1)) {
256            throw new RSInvalidStateException("Dimension must be >= 1.");
257        }
258
259        long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, 0, false, false, 0);
260        Type t = new Type(id, rs);
261        t.mElement = e;
262        t.mDimX = dimX;
263        t.mDimY = dimY;
264        t.calcElementCount();
265        return t;
266    }
267
268    /**
269     * Utility function for creating basic 3D types. The type is
270     * created without mipmaps.
271     *
272     * @param rs The RenderScript context
273     * @param e The Element for the Type
274     * @param dimX The X dimension, must be > 0
275     * @param dimY The Y dimension, must be > 0
276     * @param dimZ The Z dimension, must be > 0
277     *
278     * @return Type
279     */
280    static public Type createXYZ(RenderScript rs, Element e, int dimX, int dimY, int dimZ) {
281        if ((dimX < 1) || (dimY < 1) || (dimZ < 1)) {
282            throw new RSInvalidStateException("Dimension must be >= 1.");
283        }
284
285        long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, dimZ, false, false, 0);
286        Type t = new Type(id, rs);
287        t.mElement = e;
288        t.mDimX = dimX;
289        t.mDimY = dimY;
290        t.mDimZ = dimZ;
291        t.calcElementCount();
292        return t;
293    }
294
295    /**
296     * Builder class for Type.
297     *
298     */
299    public static class Builder {
300        RenderScript mRS;
301        int mDimX = 1;
302        int mDimY;
303        int mDimZ;
304        boolean mDimMipmaps;
305        boolean mDimFaces;
306        int mYuv;
307
308        Element mElement;
309
310        /**
311         * Create a new builder object.
312         *
313         * @param rs
314         * @param e The element for the type to be created.
315         */
316        public Builder(RenderScript rs, Element e) {
317            e.checkValid();
318            mRS = rs;
319            mElement = e;
320        }
321
322        /**
323         * Add a dimension to the Type.
324         *
325         *
326         * @param value
327         */
328        public Builder setX(int value) {
329            if(value < 1) {
330                throw new RSIllegalArgumentException("Values of less than 1 for Dimension X are not valid.");
331            }
332            mDimX = value;
333            return this;
334        }
335
336        public Builder setY(int value) {
337            if(value < 1) {
338                throw new RSIllegalArgumentException("Values of less than 1 for Dimension Y are not valid.");
339            }
340            mDimY = value;
341            return this;
342        }
343
344        public Builder setZ(int value) {
345            if(value < 1) {
346                throw new RSIllegalArgumentException("Values of less than 1 for Dimension Z are not valid.");
347            }
348            mDimZ = value;
349            return this;
350        }
351
352        public Builder setMipmaps(boolean value) {
353            mDimMipmaps = value;
354            return this;
355        }
356
357        public Builder setFaces(boolean value) {
358            mDimFaces = value;
359            return this;
360        }
361
362        /**
363         * Set the YUV layout for a Type.
364         *
365         * @param yuvFormat {@link android.graphics.ImageFormat#YV12}, {@link android.graphics.ImageFormat#NV21}, or
366         * {@link android.graphics.ImageFormat#YUV_420_888}.
367         */
368        public Builder setYuvFormat(int yuvFormat) {
369            switch (yuvFormat) {
370            case android.graphics.ImageFormat.NV21:
371            case android.graphics.ImageFormat.YV12:
372            case android.graphics.ImageFormat.YUV_420_888:
373                break;
374
375            default:
376                throw new RSIllegalArgumentException(
377                    "Only ImageFormat.NV21, .YV12, and .YUV_420_888 are supported..");
378            }
379
380            mYuv = yuvFormat;
381            return this;
382        }
383
384
385        /**
386         * Validate structure and create a new Type.
387         *
388         * @return Type
389         */
390        public Type create() {
391            if (mDimZ > 0) {
392                if ((mDimX < 1) || (mDimY < 1)) {
393                    throw new RSInvalidStateException("Both X and Y dimension required when Z is present.");
394                }
395                if (mDimFaces) {
396                    throw new RSInvalidStateException("Cube maps not supported with 3D types.");
397                }
398            }
399            if (mDimY > 0) {
400                if (mDimX < 1) {
401                    throw new RSInvalidStateException("X dimension required when Y is present.");
402                }
403            }
404            if (mDimFaces) {
405                if (mDimY < 1) {
406                    throw new RSInvalidStateException("Cube maps require 2D Types.");
407                }
408            }
409
410            if (mYuv != 0) {
411                if ((mDimZ != 0) || mDimFaces || mDimMipmaps) {
412                    throw new RSInvalidStateException("YUV only supports basic 2D.");
413                }
414            }
415
416            long id = mRS.nTypeCreate(mElement.getID(mRS),
417                                     mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces, mYuv);
418            Type t = new Type(id, mRS);
419            t.mElement = mElement;
420            t.mDimX = mDimX;
421            t.mDimY = mDimY;
422            t.mDimZ = mDimZ;
423            t.mDimMipmaps = mDimMipmaps;
424            t.mDimFaces = mDimFaces;
425            t.mDimYuv = mYuv;
426
427            t.calcElementCount();
428            return t;
429        }
430    }
431
432}
433