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