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
19
20import java.lang.reflect.Field;
21import android.util.Log;
22
23/**
24 * <p>Type is an allocation template. It consists of an Element and one or more
25 * dimensions. It describes only the layout of memory but does not allocate any
26 * storage for the data that is described.</p>
27 *
28 * <p>A Type consists of several dimensions. Those are X, Y, Z, LOD (level of
29 * detail), Faces (faces of a cube map).  The X,Y,Z dimensions can be assigned
30 * any positive integral value within the constraints of available memory.  A
31 * single dimension allocation would have an X dimension of greater than zero
32 * while the Y and Z dimensions would be zero to indicate not present.  In this
33 * regard an allocation of x=10, y=1 would be considered 2 dimensionsal while
34 * x=10, y=0 would be considered 1 dimensional.</p>
35 *
36 * <p>The LOD and Faces dimensions are booleans to indicate present or not present.</p>
37 *
38 * <div class="special reference">
39 * <h3>Developer Guides</h3>
40 * <p>For more information about creating an application that uses Renderscript, read the
41 * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
42 * </div>
43 **/
44public class Type extends BaseObj {
45    int mDimX;
46    int mDimY;
47    int mDimZ;
48    boolean mDimMipmaps;
49    boolean mDimFaces;
50    int mElementCount;
51    Element mElement;
52
53    public enum CubemapFace {
54        POSITIVE_X (0),
55        NEGATIVE_X (1),
56        POSITIVE_Y (2),
57        NEGATIVE_Y (3),
58        POSITIVE_Z (4),
59        NEGATIVE_Z (5),
60        @Deprecated
61        POSITVE_X (0),
62        @Deprecated
63        POSITVE_Y (2),
64        @Deprecated
65        POSITVE_Z (4);
66
67        int mID;
68        CubemapFace(int id) {
69            mID = id;
70        }
71    }
72
73    /**
74     * Return the element associated with this Type.
75     *
76     * @return Element
77     */
78    public Element getElement() {
79        return mElement;
80    }
81
82    /**
83     * Return the value of the X dimension.
84     *
85     * @return int
86     */
87    public int getX() {
88        return mDimX;
89    }
90
91    /**
92     * Return the value of the Y dimension or 0 for a 1D allocation.
93     *
94     * @return int
95     */
96    public int getY() {
97        return mDimY;
98    }
99
100    /**
101     * Return the value of the Z dimension or 0 for a 1D or 2D allocation.
102     *
103     * @return int
104     */
105    public int getZ() {
106        return mDimZ;
107    }
108
109    /**
110     * Return if the Type has a mipmap chain.
111     *
112     * @return boolean
113     */
114    public boolean hasMipmaps() {
115        return mDimMipmaps;
116    }
117
118    /**
119     * Return if the Type is a cube map.
120     *
121     * @return boolean
122     */
123    public boolean hasFaces() {
124        return mDimFaces;
125    }
126
127    /**
128     * Return the total number of accessable cells in the Type.
129     *
130     * @return int
131     */
132    public int getCount() {
133        return mElementCount;
134    }
135
136    void calcElementCount() {
137        boolean hasLod = hasMipmaps();
138        int x = getX();
139        int y = getY();
140        int z = getZ();
141        int faces = 1;
142        if (hasFaces()) {
143            faces = 6;
144        }
145        if (x == 0) {
146            x = 1;
147        }
148        if (y == 0) {
149            y = 1;
150        }
151        if (z == 0) {
152            z = 1;
153        }
154
155        int count = x * y * z * faces;
156
157        while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
158            if(x > 1) {
159                x >>= 1;
160            }
161            if(y > 1) {
162                y >>= 1;
163            }
164            if(z > 1) {
165                z >>= 1;
166            }
167
168            count += x * y * z * faces;
169        }
170        mElementCount = count;
171    }
172
173
174    Type(int id, RenderScript rs) {
175        super(id, rs);
176    }
177
178    @Override
179    void updateFromNative() {
180        // We have 6 integer to obtain mDimX; mDimY; mDimZ;
181        // mDimLOD; mDimFaces; mElement;
182        int[] dataBuffer = new int[6];
183        mRS.nTypeGetNativeData(getID(mRS), dataBuffer);
184
185        mDimX = dataBuffer[0];
186        mDimY = dataBuffer[1];
187        mDimZ = dataBuffer[2];
188        mDimMipmaps = dataBuffer[3] == 1 ? true : false;
189        mDimFaces = dataBuffer[4] == 1 ? true : false;
190
191        int elementID = dataBuffer[5];
192        if(elementID != 0) {
193            mElement = new Element(elementID, mRS);
194            mElement.updateFromNative();
195        }
196        calcElementCount();
197    }
198
199    /**
200     * Builder class for Type.
201     *
202     */
203    public static class Builder {
204        RenderScript mRS;
205        int mDimX = 1;
206        int mDimY;
207        int mDimZ;
208        boolean mDimMipmaps;
209        boolean mDimFaces;
210
211        Element mElement;
212
213        /**
214         * Create a new builder object.
215         *
216         * @param rs
217         * @param e The element for the type to be created.
218         */
219        public Builder(RenderScript rs, Element e) {
220            e.checkValid();
221            mRS = rs;
222            mElement = e;
223        }
224
225        /**
226         * Add a dimension to the Type.
227         *
228         *
229         * @param value
230         */
231        public Builder setX(int value) {
232            if(value < 1) {
233                throw new RSIllegalArgumentException("Values of less than 1 for Dimension X are not valid.");
234            }
235            mDimX = value;
236            return this;
237        }
238
239        public Builder setY(int value) {
240            if(value < 1) {
241                throw new RSIllegalArgumentException("Values of less than 1 for Dimension Y are not valid.");
242            }
243            mDimY = value;
244            return this;
245        }
246
247        public Builder setMipmaps(boolean value) {
248            mDimMipmaps = value;
249            return this;
250        }
251
252        public Builder setFaces(boolean value) {
253            mDimFaces = value;
254            return this;
255        }
256
257
258        /**
259         * Validate structure and create a new type.
260         *
261         * @return Type
262         */
263        public Type create() {
264            if (mDimZ > 0) {
265                if ((mDimX < 1) || (mDimY < 1)) {
266                    throw new RSInvalidStateException("Both X and Y dimension required when Z is present.");
267                }
268                if (mDimFaces) {
269                    throw new RSInvalidStateException("Cube maps not supported with 3D types.");
270                }
271            }
272            if (mDimY > 0) {
273                if (mDimX < 1) {
274                    throw new RSInvalidStateException("X dimension required when Y is present.");
275                }
276            }
277            if (mDimFaces) {
278                if (mDimY < 1) {
279                    throw new RSInvalidStateException("Cube maps require 2D Types.");
280                }
281            }
282
283            int id = mRS.nTypeCreate(mElement.getID(mRS),
284                                     mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces);
285            Type t = new Type(id, mRS);
286            t.mElement = mElement;
287            t.mDimX = mDimX;
288            t.mDimY = mDimY;
289            t.mDimZ = mDimZ;
290            t.mDimMipmaps = mDimMipmaps;
291            t.mDimFaces = mDimFaces;
292
293            t.calcElementCount();
294            return t;
295        }
296    }
297
298}
299