Home | History | Annotate | Download | only in renderscript
      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 
     17 package 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  **/
     46 public 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     int mArrays[];
     56 
     57     static final int mMaxArrays = 4;
     58 
     59     public enum CubemapFace {
     60         POSITIVE_X (0),
     61         NEGATIVE_X (1),
     62         POSITIVE_Y (2),
     63         NEGATIVE_Y (3),
     64         POSITIVE_Z (4),
     65         NEGATIVE_Z (5),
     66         @Deprecated
     67         POSITVE_X (0),
     68         @Deprecated
     69         POSITVE_Y (2),
     70         @Deprecated
     71         POSITVE_Z (4);
     72 
     73         int mID;
     74         CubemapFace(int id) {
     75             mID = id;
     76         }
     77     }
     78 
     79     /**
     80      * Return the element associated with this Type.
     81      *
     82      * @return Element
     83      */
     84     public Element getElement() {
     85         return mElement;
     86     }
     87 
     88     /**
     89      * Return the value of the X dimension.
     90      *
     91      * @return int
     92      */
     93     public int getX() {
     94         return mDimX;
     95     }
     96 
     97     /**
     98      * Return the value of the Y dimension or 0 for a 1D allocation.
     99      *
    100      * @return int
    101      */
    102     public int getY() {
    103         return mDimY;
    104     }
    105 
    106     /**
    107      * Return the value of the Z dimension or 0 for a 1D or 2D allocation.
    108      *
    109      * @return int
    110      */
    111     public int getZ() {
    112         return mDimZ;
    113     }
    114 
    115     /**
    116      * Get the YUV format
    117      *
    118      *
    119      * @return int
    120      */
    121     public int getYuv() {
    122         return mDimYuv;
    123     }
    124 
    125     /**
    126      * Return if the Type has a mipmap chain.
    127      *
    128      * @return boolean
    129      */
    130     public boolean hasMipmaps() {
    131         return mDimMipmaps;
    132     }
    133 
    134     /**
    135      * Return if the Type is a cube map.
    136      *
    137      * @return boolean
    138      */
    139     public boolean hasFaces() {
    140         return mDimFaces;
    141     }
    142 
    143     /**
    144      * Return the total number of accessable cells in the Type.
    145      *
    146      * @return int
    147      */
    148     public int getCount() {
    149         return mElementCount;
    150     }
    151 
    152     /**
    153      * @hide
    154       * Return the dimension of the specified array.
    155       *
    156       * @param arrayNum  The array dimension to query
    157       * @return int
    158       */
    159     public int getArray(int arrayNum) {
    160         if ((arrayNum < 0) || (arrayNum >= mMaxArrays)) {
    161             throw new RSIllegalArgumentException("Array dimension out of range.");
    162         }
    163 
    164         if (mArrays == null || arrayNum >= mArrays.length) {
    165             // Dimension in range but no array for that dimension allocated
    166             return 0;
    167         }
    168 
    169         return mArrays[arrayNum];
    170     }
    171 
    172     /**
    173      * @hide
    174       * Return the number of array dimensions.
    175       *
    176       * @return int
    177       */
    178     public int getArrayCount() {
    179         if (mArrays != null) return mArrays.length;
    180         return 0;
    181     }
    182 
    183     void calcElementCount() {
    184         boolean hasLod = hasMipmaps();
    185         int x = getX();
    186         int y = getY();
    187         int z = getZ();
    188         int faces = 1;
    189         if (hasFaces()) {
    190             faces = 6;
    191         }
    192         if (x == 0) {
    193             x = 1;
    194         }
    195         if (y == 0) {
    196             y = 1;
    197         }
    198         if (z == 0) {
    199             z = 1;
    200         }
    201 
    202         int count = x * y * z * faces;
    203 
    204         while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
    205             if(x > 1) {
    206                 x >>= 1;
    207             }
    208             if(y > 1) {
    209                 y >>= 1;
    210             }
    211             if(z > 1) {
    212                 z >>= 1;
    213             }
    214 
    215             count += x * y * z * faces;
    216         }
    217 
    218         if (mArrays != null) {
    219             for (int ct = 0; ct < mArrays.length; ct++) {
    220                 count *= mArrays[ct];
    221             }
    222         }
    223 
    224         mElementCount = count;
    225     }
    226 
    227 
    228     Type(long id, RenderScript rs) {
    229         super(id, rs);
    230     }
    231 
    232     @Override
    233     void updateFromNative() {
    234         // We have 6 integer/long to obtain mDimX; mDimY; mDimZ;
    235         // mDimLOD; mDimFaces; mElement;
    236         long[] dataBuffer = new long[6];
    237         mRS.nTypeGetNativeData(getID(mRS), dataBuffer);
    238 
    239         mDimX = (int)dataBuffer[0];
    240         mDimY = (int)dataBuffer[1];
    241         mDimZ = (int)dataBuffer[2];
    242         mDimMipmaps = dataBuffer[3] == 1 ? true : false;
    243         mDimFaces = dataBuffer[4] == 1 ? true : false;
    244 
    245         long elementID = dataBuffer[5];
    246         if(elementID != 0) {
    247             mElement = new Element(elementID, mRS);
    248             mElement.updateFromNative();
    249         }
    250         calcElementCount();
    251     }
    252 
    253     /**
    254      * Utility function for creating basic 1D types. The type is
    255      * created without mipmaps enabled.
    256      *
    257      * @param rs The RenderScript context
    258      * @param e The Element for the Type
    259      * @param dimX The X dimension, must be > 0
    260      *
    261      * @return Type
    262      */
    263     static public Type createX(RenderScript rs, Element e, int dimX) {
    264         if (dimX < 1) {
    265             throw new RSInvalidStateException("Dimension must be >= 1.");
    266         }
    267 
    268         long id = rs.nTypeCreate(e.getID(rs), dimX, 0, 0, false, false, 0);
    269         Type t = new Type(id, rs);
    270         t.mElement = e;
    271         t.mDimX = dimX;
    272         t.calcElementCount();
    273         return t;
    274     }
    275 
    276     /**
    277      * Utility function for creating basic 2D types. The type is
    278      * created without mipmaps or cubemaps.
    279      *
    280      * @param rs The RenderScript context
    281      * @param e The Element for the Type
    282      * @param dimX The X dimension, must be > 0
    283      * @param dimY The Y dimension, must be > 0
    284      *
    285      * @return Type
    286      */
    287     static public Type createXY(RenderScript rs, Element e, int dimX, int dimY) {
    288         if ((dimX < 1) || (dimY < 1)) {
    289             throw new RSInvalidStateException("Dimension must be >= 1.");
    290         }
    291 
    292         long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, 0, false, false, 0);
    293         Type t = new Type(id, rs);
    294         t.mElement = e;
    295         t.mDimX = dimX;
    296         t.mDimY = dimY;
    297         t.calcElementCount();
    298         return t;
    299     }
    300 
    301     /**
    302      * Utility function for creating basic 3D types. The type is
    303      * created without mipmaps.
    304      *
    305      * @param rs The RenderScript context
    306      * @param e The Element for the Type
    307      * @param dimX The X dimension, must be > 0
    308      * @param dimY The Y dimension, must be > 0
    309      * @param dimZ The Z dimension, must be > 0
    310      *
    311      * @return Type
    312      */
    313     static public Type createXYZ(RenderScript rs, Element e, int dimX, int dimY, int dimZ) {
    314         if ((dimX < 1) || (dimY < 1) || (dimZ < 1)) {
    315             throw new RSInvalidStateException("Dimension must be >= 1.");
    316         }
    317 
    318         long id = rs.nTypeCreate(e.getID(rs), dimX, dimY, dimZ, false, false, 0);
    319         Type t = new Type(id, rs);
    320         t.mElement = e;
    321         t.mDimX = dimX;
    322         t.mDimY = dimY;
    323         t.mDimZ = dimZ;
    324         t.calcElementCount();
    325         return t;
    326     }
    327 
    328     /**
    329      * Builder class for Type.
    330      *
    331      */
    332     public static class Builder {
    333         RenderScript mRS;
    334         int mDimX = 1;
    335         int mDimY;
    336         int mDimZ;
    337         boolean mDimMipmaps;
    338         boolean mDimFaces;
    339         int mYuv;
    340         int[] mArray = new int[mMaxArrays];
    341 
    342         Element mElement;
    343 
    344         /**
    345          * Create a new builder object.
    346          *
    347          * @param rs
    348          * @param e The element for the type to be created.
    349          */
    350         public Builder(RenderScript rs, Element e) {
    351             e.checkValid();
    352             mRS = rs;
    353             mElement = e;
    354         }
    355 
    356         /**
    357          * Add a dimension to the Type.
    358          *
    359          *
    360          * @param value
    361          */
    362         public Builder setX(int value) {
    363             if(value < 1) {
    364                 throw new RSIllegalArgumentException("Values of less than 1 for Dimension X are not valid.");
    365             }
    366             mDimX = value;
    367             return this;
    368         }
    369 
    370         public Builder setY(int value) {
    371             if(value < 1) {
    372                 throw new RSIllegalArgumentException("Values of less than 1 for Dimension Y are not valid.");
    373             }
    374             mDimY = value;
    375             return this;
    376         }
    377 
    378         public Builder setZ(int value) {
    379             if(value < 1) {
    380                 throw new RSIllegalArgumentException("Values of less than 1 for Dimension Z are not valid.");
    381             }
    382             mDimZ = value;
    383             return this;
    384         }
    385 
    386         /**
    387          * @hide
    388          * Adds an array dimension to the builder
    389          *
    390          * @param dim
    391          * @param value
    392          *
    393          * @return Builder
    394          */
    395         public Builder setArray(int dim, int value) {
    396             if(dim < 0 || dim >= mMaxArrays) {
    397                 throw new RSIllegalArgumentException("Array dimension out of range.");
    398             }
    399             mArray[dim] = value;
    400             return this;
    401         }
    402 
    403         public Builder setMipmaps(boolean value) {
    404             mDimMipmaps = value;
    405             return this;
    406         }
    407 
    408         public Builder setFaces(boolean value) {
    409             mDimFaces = value;
    410             return this;
    411         }
    412 
    413         /**
    414          * Set the YUV layout for a Type.
    415          *
    416          * @param yuvFormat {@link android.graphics.ImageFormat#YV12}, {@link android.graphics.ImageFormat#NV21}, or
    417          * {@link android.graphics.ImageFormat#YUV_420_888}.
    418          */
    419         public Builder setYuvFormat(int yuvFormat) {
    420             switch (yuvFormat) {
    421             case android.graphics.ImageFormat.NV21:
    422             case android.graphics.ImageFormat.YV12:
    423             case android.graphics.ImageFormat.YUV_420_888:
    424                 break;
    425 
    426             default:
    427                 throw new RSIllegalArgumentException(
    428                     "Only ImageFormat.NV21, .YV12, and .YUV_420_888 are supported..");
    429             }
    430 
    431             mYuv = yuvFormat;
    432             return this;
    433         }
    434 
    435 
    436         /**
    437          * Validate structure and create a new Type.
    438          *
    439          * @return Type
    440          */
    441         public Type create() {
    442             if (mDimZ > 0) {
    443                 if ((mDimX < 1) || (mDimY < 1)) {
    444                     throw new RSInvalidStateException("Both X and Y dimension required when Z is present.");
    445                 }
    446                 if (mDimFaces) {
    447                     throw new RSInvalidStateException("Cube maps not supported with 3D types.");
    448                 }
    449             }
    450             if (mDimY > 0) {
    451                 if (mDimX < 1) {
    452                     throw new RSInvalidStateException("X dimension required when Y is present.");
    453                 }
    454             }
    455             if (mDimFaces) {
    456                 if (mDimY < 1) {
    457                     throw new RSInvalidStateException("Cube maps require 2D Types.");
    458                 }
    459             }
    460 
    461             if (mYuv != 0) {
    462                 if ((mDimZ != 0) || mDimFaces || mDimMipmaps) {
    463                     throw new RSInvalidStateException("YUV only supports basic 2D.");
    464                 }
    465             }
    466 
    467             int[] arrays = null;
    468             for (int ct = mMaxArrays - 1; ct >= 0; ct--) {
    469                 if (mArray[ct] != 0 && arrays == null) {
    470                     arrays = new int[ct];
    471                 }
    472                 if ((mArray[ct] == 0) && (arrays != null)) {
    473                     throw new RSInvalidStateException("Array dimensions must be contigous from 0.");
    474                 }
    475             }
    476 
    477             long id = mRS.nTypeCreate(mElement.getID(mRS),
    478                                      mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces, mYuv);
    479             Type t = new Type(id, mRS);
    480             t.mElement = mElement;
    481             t.mDimX = mDimX;
    482             t.mDimY = mDimY;
    483             t.mDimZ = mDimZ;
    484             t.mDimMipmaps = mDimMipmaps;
    485             t.mDimFaces = mDimFaces;
    486             t.mDimYuv = mYuv;
    487             t.mArrays = arrays;
    488 
    489             t.calcElementCount();
    490             return t;
    491         }
    492     }
    493 
    494 }
    495