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