| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.renderscript; |
| |
| /** |
| * <p>A Type describes the {@link android.renderscript.Element} and dimensions used for an {@link |
| * android.renderscript.Allocation} or a parallel operation. Types are created through {@link |
| * android.renderscript.Type.Builder}.</p> |
| * |
| * <p>A Type always includes an {@link android.renderscript.Element} and an X |
| * dimension. A Type may be multidimensional, up to three dimensions. A nonzero |
| * value in the Y or Z dimensions indicates that the dimension is present. Note |
| * that a Type with only a given X dimension and a Type with the same X |
| * dimension but Y = 1 are not equivalent.</p> |
| * |
| * <p>A Type also supports inclusion of level of detail (LOD) or cube map |
| * faces. LOD and cube map faces are booleans to indicate present or not |
| * present. </p> |
| * |
| * <p>A Type also supports YUV format information to support an |
| * {@link android.renderscript.Allocation} in a YUV format. The YUV formats |
| * supported are {@link android.graphics.ImageFormat#YV12}, |
| * {@link android.graphics.ImageFormat#NV21}, and |
| * {@link android.graphics.ImageFormat#YUV_420_888}</p> |
| * |
| * <div class="special reference"> |
| * <h3>Developer Guides</h3> |
| * <p>For more information about creating an application that uses RenderScript, read the |
| * <a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a> developer guide.</p> |
| * </div> |
| **/ |
| public class Type extends BaseObj { |
| int mDimX; |
| int mDimY; |
| int mDimZ; |
| boolean mDimMipmaps; |
| boolean mDimFaces; |
| int mDimYuv; |
| int mElementCount; |
| Element mElement; |
| int mArrays[]; |
| |
| static final int mMaxArrays = 4; |
| |
| public enum CubemapFace { |
| POSITIVE_X (0), |
| NEGATIVE_X (1), |
| POSITIVE_Y (2), |
| NEGATIVE_Y (3), |
| POSITIVE_Z (4), |
| NEGATIVE_Z (5), |
| @Deprecated |
| POSITVE_X (0), |
| @Deprecated |
| POSITVE_Y (2), |
| @Deprecated |
| POSITVE_Z (4); |
| |
| int mID; |
| CubemapFace(int id) { |
| mID = id; |
| } |
| } |
| |
| /** |
| * Return the element associated with this Type. |
| * |
| * @return Element |
| */ |
| public Element getElement() { |
| return mElement; |
| } |
| |
| /** |
| * Return the value of the X dimension. |
| * |
| * @return int |
| */ |
| public int getX() { |
| return mDimX; |
| } |
| |
| /** |
| * Return the value of the Y dimension or 0 for a 1D allocation. |
| * |
| * @return int |
| */ |
| public int getY() { |
| return mDimY; |
| } |
| |
| /** |
| * Return the value of the Z dimension or 0 for a 1D or 2D allocation. |
| * |
| * @return int |
| */ |
| public int getZ() { |
| return mDimZ; |
| } |
| |
| /** |
| * Get the YUV format |
| * |
| * |
| * @return int |
| */ |
| public int getYuv() { |
| return mDimYuv; |
| } |
| |
| /** |
| * Return if the Type has a mipmap chain. |
| * |
| * @return boolean |
| */ |
| public boolean hasMipmaps() { |
| return mDimMipmaps; |
| } |
| |
| /** |
| * Return if the Type is a cube map. |
| * |
| * @return boolean |
| */ |
| public boolean hasFaces() { |
| return mDimFaces; |
| } |
| |
| /** |
| * Return the total number of accessable cells in the Type. |
| * |
| * @return int |
| */ |
| public int getCount() { |
| return mElementCount; |
| } |
| |
| /** |
| * @hide |
| * Return the dimension of the specified array. |
| * |
| * @param arrayNum The array dimension to query |
| * @return int |
| */ |
| public int getArray(int arrayNum) { |
| if ((arrayNum < 0) || (arrayNum >= mMaxArrays)) { |
| throw new RSIllegalArgumentException("Array dimension out of range."); |
| } |
| |
| if (mArrays == null || arrayNum >= mArrays.length) { |
| // Dimension in range but no array for that dimension allocated |
| return 0; |
| } |
| |
| return mArrays[arrayNum]; |
| } |
| |
| /** |
| * @hide |
| * Return the number of array dimensions. |
| * |
| * @return int |
| */ |
| public int getArrayCount() { |
| if (mArrays != null) return mArrays.length; |
| return 0; |
| } |
| |
| void calcElementCount() { |
| boolean hasLod = hasMipmaps(); |
| int x = getX(); |
| int y = getY(); |
| int z = getZ(); |
| int faces = 1; |
| if (hasFaces()) { |
| faces = 6; |
| } |
| if (x == 0) { |
| x = 1; |
| } |
| if (y == 0) { |
| y = 1; |
| } |
| if (z == 0) { |
| z = 1; |
| } |
| |
| int count = x * y * z * faces; |
| |
| while (hasLod && ((x > 1) || (y > 1) || (z > 1))) { |
| if(x > 1) { |
| x >>= 1; |
| } |
| if(y > 1) { |
| y >>= 1; |
| } |
| if(z > 1) { |
| z >>= 1; |
| } |
| |
| count += x * y * z * faces; |
| } |
| |
| if (mArrays != null) { |
| for (int ct = 0; ct < mArrays.length; ct++) { |
| count *= mArrays[ct]; |
| } |
| } |
| |
| mElementCount = count; |
| } |
| |
| |
| Type(long id, RenderScript rs) { |
| super(id, rs); |
| guard.open("destroy"); |
| } |
| |
| @Override |
| void updateFromNative() { |
| // We have 6 integer/long to obtain mDimX; mDimY; mDimZ; |
| // mDimLOD; mDimFaces; mElement; |
| long[] dataBuffer = new long[6]; |
| mRS.nTypeGetNativeData(getID(mRS), dataBuffer); |
| |
| mDimX = (int)dataBuffer[0]; |
| mDimY = (int)dataBuffer[1]; |
| mDimZ = (int)dataBuffer[2]; |
| mDimMipmaps = dataBuffer[3] == 1 ? true : false; |
| mDimFaces = dataBuffer[4] == 1 ? true : false; |
| |
| long elementID = dataBuffer[5]; |
| if(elementID != 0) { |
| mElement = new Element(elementID, mRS); |
| mElement.updateFromNative(); |
| } |
| calcElementCount(); |
| } |
| |
| /** |
| * Utility function for creating basic 1D types. The type is |
| * created without mipmaps enabled. |
| * |
| * @param rs The RenderScript context |
| * @param e The Element for the Type |
| * @param dimX The X dimension, must be > 0 |
| * |
| * @return Type |
| */ |
| static public Type createX(RenderScript rs, Element e, int dimX) { |
| if (dimX < 1) { |
| throw new RSInvalidStateException("Dimension must be >= 1."); |
| } |
| |
| long id = rs.nTypeCreate(e.getID(rs), dimX, 0, 0, false, false, 0); |
| Type t = new Type(id, rs); |
| t.mElement = e; |
| t.mDimX = dimX; |
| t.calcElementCount(); |
| return t; |
| } |
| |
| /** |
| * Utility function for creating basic 2D types. The type is |
| * created without mipmaps or cubemaps. |
| * |
| * @param rs The RenderScript context |
| * @param e The Element for the Type |
| * @param dimX The X dimension, must be > 0 |
| * @param dimY The Y dimension, must be > 0 |
| * |
| * @return Type |
| */ |
| static public Type createXY(RenderScript rs, Element e, int dimX, int dimY) { |
| if ((dimX < 1) || (dimY < 1)) { |
| throw new RSInvalidStateException("Dimension must be >= 1."); |
| } |
| |
| long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, 0, false, false, 0); |
| Type t = new Type(id, rs); |
| t.mElement = e; |
| t.mDimX = dimX; |
| t.mDimY = dimY; |
| t.calcElementCount(); |
| return t; |
| } |
| |
| /** |
| * Utility function for creating basic 3D types. The type is |
| * created without mipmaps. |
| * |
| * @param rs The RenderScript context |
| * @param e The Element for the Type |
| * @param dimX The X dimension, must be > 0 |
| * @param dimY The Y dimension, must be > 0 |
| * @param dimZ The Z dimension, must be > 0 |
| * |
| * @return Type |
| */ |
| static public Type createXYZ(RenderScript rs, Element e, int dimX, int dimY, int dimZ) { |
| if ((dimX < 1) || (dimY < 1) || (dimZ < 1)) { |
| throw new RSInvalidStateException("Dimension must be >= 1."); |
| } |
| |
| long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, dimZ, false, false, 0); |
| Type t = new Type(id, rs); |
| t.mElement = e; |
| t.mDimX = dimX; |
| t.mDimY = dimY; |
| t.mDimZ = dimZ; |
| t.calcElementCount(); |
| return t; |
| } |
| |
| /** |
| * Builder class for Type. |
| * |
| */ |
| public static class Builder { |
| RenderScript mRS; |
| int mDimX = 1; |
| int mDimY; |
| int mDimZ; |
| boolean mDimMipmaps; |
| boolean mDimFaces; |
| int mYuv; |
| int[] mArray = new int[mMaxArrays]; |
| |
| Element mElement; |
| |
| /** |
| * Create a new builder object. |
| * |
| * @param rs |
| * @param e The element for the type to be created. |
| */ |
| public Builder(RenderScript rs, Element e) { |
| e.checkValid(); |
| mRS = rs; |
| mElement = e; |
| } |
| |
| /** |
| * Add a dimension to the Type. |
| * |
| * |
| * @param value |
| */ |
| public Builder setX(int value) { |
| if(value < 1) { |
| throw new RSIllegalArgumentException("Values of less than 1 for Dimension X are not valid."); |
| } |
| mDimX = value; |
| return this; |
| } |
| |
| public Builder setY(int value) { |
| if(value < 1) { |
| throw new RSIllegalArgumentException("Values of less than 1 for Dimension Y are not valid."); |
| } |
| mDimY = value; |
| return this; |
| } |
| |
| public Builder setZ(int value) { |
| if(value < 1) { |
| throw new RSIllegalArgumentException("Values of less than 1 for Dimension Z are not valid."); |
| } |
| mDimZ = value; |
| return this; |
| } |
| |
| /** |
| * @hide |
| * Adds an array dimension to the builder |
| * |
| * @param dim |
| * @param value |
| * |
| * @return Builder |
| */ |
| public Builder setArray(int dim, int value) { |
| if(dim < 0 || dim >= mMaxArrays) { |
| throw new RSIllegalArgumentException("Array dimension out of range."); |
| } |
| mArray[dim] = value; |
| return this; |
| } |
| |
| public Builder setMipmaps(boolean value) { |
| mDimMipmaps = value; |
| return this; |
| } |
| |
| public Builder setFaces(boolean value) { |
| mDimFaces = value; |
| return this; |
| } |
| |
| /** |
| * Set the YUV layout for a Type. |
| * |
| * @param yuvFormat {@link android.graphics.ImageFormat#YV12}, {@link android.graphics.ImageFormat#NV21}, or |
| * {@link android.graphics.ImageFormat#YUV_420_888}. |
| */ |
| public Builder setYuvFormat(int yuvFormat) { |
| switch (yuvFormat) { |
| case android.graphics.ImageFormat.NV21: |
| case android.graphics.ImageFormat.YV12: |
| case android.graphics.ImageFormat.YUV_420_888: |
| break; |
| |
| default: |
| throw new RSIllegalArgumentException( |
| "Only ImageFormat.NV21, .YV12, and .YUV_420_888 are supported.."); |
| } |
| |
| mYuv = yuvFormat; |
| return this; |
| } |
| |
| |
| /** |
| * Validate structure and create a new Type. |
| * |
| * @return Type |
| */ |
| public Type create() { |
| if (mDimZ > 0) { |
| if ((mDimX < 1) || (mDimY < 1)) { |
| throw new RSInvalidStateException("Both X and Y dimension required when Z is present."); |
| } |
| if (mDimFaces) { |
| throw new RSInvalidStateException("Cube maps not supported with 3D types."); |
| } |
| } |
| if (mDimY > 0) { |
| if (mDimX < 1) { |
| throw new RSInvalidStateException("X dimension required when Y is present."); |
| } |
| } |
| if (mDimFaces) { |
| if (mDimY < 1) { |
| throw new RSInvalidStateException("Cube maps require 2D Types."); |
| } |
| } |
| |
| if (mYuv != 0) { |
| if ((mDimZ != 0) || mDimFaces || mDimMipmaps) { |
| throw new RSInvalidStateException("YUV only supports basic 2D."); |
| } |
| } |
| |
| int[] arrays = null; |
| for (int ct = mMaxArrays - 1; ct >= 0; ct--) { |
| if (mArray[ct] != 0 && arrays == null) { |
| arrays = new int[ct]; |
| } |
| if ((mArray[ct] == 0) && (arrays != null)) { |
| throw new RSInvalidStateException("Array dimensions must be contigous from 0."); |
| } |
| } |
| |
| long id = mRS.nTypeCreate(mElement.getID(mRS), |
| mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces, mYuv); |
| Type t = new Type(id, mRS); |
| t.mElement = mElement; |
| t.mDimX = mDimX; |
| t.mDimY = mDimY; |
| t.mDimZ = mDimZ; |
| t.mDimMipmaps = mDimMipmaps; |
| t.mDimFaces = mDimFaces; |
| t.mDimYuv = mYuv; |
| t.mArrays = arrays; |
| |
| t.calcElementCount(); |
| return t; |
| } |
| } |
| |
| } |