Home | History | Annotate | Download | only in hardware
      1 /*
      2  * Copyright (C) 2017 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.hardware;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.LongDef;
     21 import android.annotation.NonNull;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 
     25 import dalvik.annotation.optimization.FastNative;
     26 import dalvik.system.CloseGuard;
     27 
     28 import libcore.util.NativeAllocationRegistry;
     29 
     30 import java.lang.annotation.Retention;
     31 import java.lang.annotation.RetentionPolicy;
     32 
     33 /**
     34  * HardwareBuffer wraps a native <code>AHardwareBuffer</code> object, which is a low-level object
     35  * representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing
     36  * buffers across different application processes. In particular, HardwareBuffers may be mappable
     37  * to memory accessibly to various hardware systems, such as the GPU, a sensor or context hub, or
     38  * other auxiliary processing units.
     39  *
     40  * For more information, see the NDK documentation for <code>AHardwareBuffer</code>.
     41  */
     42 public final class HardwareBuffer implements Parcelable, AutoCloseable {
     43     /** @hide */
     44     @Retention(RetentionPolicy.SOURCE)
     45     @IntDef(prefix = { "RGB", "BLOB", "D_", "DS_", "S_" }, value = {
     46             RGBA_8888,
     47             RGBA_FP16,
     48             RGBA_1010102,
     49             RGBX_8888,
     50             RGB_888,
     51             RGB_565,
     52             BLOB,
     53             D_16,
     54             D_24,
     55             DS_24UI8,
     56             D_FP32,
     57             DS_FP32UI8,
     58             S_UI8,
     59     })
     60     public @interface Format {
     61     }
     62 
     63     @Format
     64     /** Format: 8 bits each red, green, blue, alpha */
     65     public static final int RGBA_8888    = 1;
     66     /** Format: 8 bits each red, green, blue, alpha, alpha is always 0xFF */
     67     public static final int RGBX_8888    = 2;
     68     /** Format: 8 bits each red, green, blue, no alpha */
     69     public static final int RGB_888      = 3;
     70     /** Format: 5 bits each red and blue, 6 bits green, no alpha */
     71     public static final int RGB_565      = 4;
     72     /** Format: 16 bits each red, green, blue, alpha */
     73     public static final int RGBA_FP16    = 0x16;
     74     /** Format: 10 bits each red, green, blue, 2 bits alpha */
     75     public static final int RGBA_1010102 = 0x2b;
     76     /** Format: opaque format used for raw data transfer; must have a height of 1 */
     77     public static final int BLOB         = 0x21;
     78     /** Format: 16 bits depth */
     79     public static final int D_16         = 0x30;
     80     /** Format: 24 bits depth */
     81     public static final int D_24         = 0x31;
     82     /** Format: 24 bits depth, 8 bits stencil */
     83     public static final int DS_24UI8     = 0x32;
     84     /** Format: 32 bits depth */
     85     public static final int D_FP32       = 0x33;
     86     /** Format: 32 bits depth, 8 bits stencil */
     87     public static final int DS_FP32UI8   = 0x34;
     88     /** Format: 8 bits stencil */
     89     public static final int S_UI8        = 0x35;
     90 
     91     // Note: do not rename, this field is used by native code
     92     private long mNativeObject;
     93 
     94     // Invoked on destruction
     95     private Runnable mCleaner;
     96 
     97     private final CloseGuard mCloseGuard = CloseGuard.get();
     98 
     99     /** @hide */
    100     @Retention(RetentionPolicy.SOURCE)
    101     @LongDef(flag = true, value = {USAGE_CPU_READ_RARELY, USAGE_CPU_READ_OFTEN,
    102             USAGE_CPU_WRITE_RARELY, USAGE_CPU_WRITE_OFTEN, USAGE_GPU_SAMPLED_IMAGE,
    103             USAGE_GPU_COLOR_OUTPUT, USAGE_PROTECTED_CONTENT, USAGE_VIDEO_ENCODE,
    104             USAGE_GPU_DATA_BUFFER, USAGE_SENSOR_DIRECT_DATA, USAGE_GPU_CUBE_MAP,
    105             USAGE_GPU_MIPMAP_COMPLETE})
    106     public @interface Usage {};
    107 
    108     @Usage
    109     /** Usage: The buffer will sometimes be read by the CPU */
    110     public static final long USAGE_CPU_READ_RARELY       = 2;
    111     /** Usage: The buffer will often be read by the CPU */
    112     public static final long USAGE_CPU_READ_OFTEN        = 3;
    113 
    114     /** Usage: The buffer will sometimes be written to by the CPU */
    115     public static final long USAGE_CPU_WRITE_RARELY      = 2 << 4;
    116     /** Usage: The buffer will often be written to by the CPU */
    117     public static final long USAGE_CPU_WRITE_OFTEN       = 3 << 4;
    118 
    119     /** Usage: The buffer will be read from by the GPU */
    120     public static final long USAGE_GPU_SAMPLED_IMAGE      = 1 << 8;
    121     /** Usage: The buffer will be written to by the GPU */
    122     public static final long USAGE_GPU_COLOR_OUTPUT       = 1 << 9;
    123     /** Usage: The buffer must not be used outside of a protected hardware path */
    124     public static final long USAGE_PROTECTED_CONTENT      = 1 << 14;
    125     /** Usage: The buffer will be read by a hardware video encoder */
    126     public static final long USAGE_VIDEO_ENCODE           = 1 << 16;
    127     /** Usage: The buffer will be used for sensor direct data */
    128     public static final long USAGE_SENSOR_DIRECT_DATA     = 1 << 23;
    129     /** Usage: The buffer will be used as a shader storage or uniform buffer object */
    130     public static final long USAGE_GPU_DATA_BUFFER        = 1 << 24;
    131     /** Usage: The buffer will be used as a cube map texture */
    132     public static final long USAGE_GPU_CUBE_MAP           = 1 << 25;
    133     /** Usage: The buffer contains a complete mipmap hierarchy */
    134     public static final long USAGE_GPU_MIPMAP_COMPLETE    = 1 << 26;
    135 
    136     // The approximate size of a native AHardwareBuffer object.
    137     private static final long NATIVE_HARDWARE_BUFFER_SIZE = 232;
    138     /**
    139      * Creates a new <code>HardwareBuffer</code> instance.
    140      *
    141      * <p>Calling this method will throw an <code>IllegalStateException</code> if
    142      * format is not a supported Format type.</p>
    143      *
    144      * @param width The width in pixels of the buffer
    145      * @param height The height in pixels of the buffer
    146      * @param format The @Format of each pixel
    147      * @param layers The number of layers in the buffer
    148      * @param usage The @Usage flags describing how the buffer will be used
    149      * @return A <code>HardwareBuffer</code> instance if successful, or throws an
    150      *     IllegalArgumentException if the dimensions passed are invalid (either zero, negative, or
    151      *     too large to allocate), if the format is not supported, if the requested number of layers
    152      *     is less than one or not supported, or if the passed usage flags are not a supported set.
    153      */
    154     @NonNull
    155     public static HardwareBuffer create(int width, int height, @Format int format, int layers,
    156             @Usage long usage) {
    157         if (!HardwareBuffer.isSupportedFormat(format)) {
    158             throw new IllegalArgumentException("Invalid pixel format " + format);
    159         }
    160         if (width <= 0) {
    161             throw new IllegalArgumentException("Invalid width " + width);
    162         }
    163         if (height <= 0) {
    164             throw new IllegalArgumentException("Invalid height " + height);
    165         }
    166         if (layers <= 0) {
    167             throw new IllegalArgumentException("Invalid layer count " + layers);
    168         }
    169         if (format == BLOB && height != 1) {
    170             throw new IllegalArgumentException("Height must be 1 when using the BLOB format");
    171         }
    172         long nativeObject = nCreateHardwareBuffer(width, height, format, layers, usage);
    173         if (nativeObject == 0) {
    174             throw new IllegalArgumentException("Unable to create a HardwareBuffer, either the " +
    175                     "dimensions passed were too large, too many image layers were requested, " +
    176                     "or an invalid set of usage flags or invalid format was passed");
    177         }
    178         return new HardwareBuffer(nativeObject);
    179     }
    180 
    181     /**
    182      * Private use only. See {@link #create(int, int, int, int, long)}. May also be
    183      * called from JNI using an already allocated native <code>HardwareBuffer</code>.
    184      */
    185     private HardwareBuffer(long nativeObject) {
    186         mNativeObject = nativeObject;
    187 
    188         ClassLoader loader = HardwareBuffer.class.getClassLoader();
    189         NativeAllocationRegistry registry = new NativeAllocationRegistry(
    190                 loader, nGetNativeFinalizer(), NATIVE_HARDWARE_BUFFER_SIZE);
    191         mCleaner = registry.registerNativeAllocation(this, mNativeObject);
    192         mCloseGuard.open("close");
    193     }
    194 
    195     @Override
    196     protected void finalize() throws Throwable {
    197         try {
    198             mCloseGuard.warnIfOpen();
    199             close();
    200         } finally {
    201             super.finalize();
    202         }
    203     }
    204 
    205     /**
    206      * Returns the width of this buffer in pixels.
    207      */
    208     public int getWidth() {
    209         if (isClosed()) {
    210             throw new IllegalStateException("This HardwareBuffer has been closed and its width "
    211                     + "cannot be obtained.");
    212         }
    213         return nGetWidth(mNativeObject);
    214     }
    215 
    216     /**
    217      * Returns the height of this buffer in pixels.
    218      */
    219     public int getHeight() {
    220         if (isClosed()) {
    221             throw new IllegalStateException("This HardwareBuffer has been closed and its height "
    222                     + "cannot be obtained.");
    223         }
    224         return nGetHeight(mNativeObject);
    225     }
    226 
    227     /**
    228      * Returns the @Format of this buffer.
    229      */
    230     @Format
    231     public int getFormat() {
    232         if (isClosed()) {
    233             throw new IllegalStateException("This HardwareBuffer has been closed and its format "
    234                     + "cannot be obtained.");
    235         }
    236         return nGetFormat(mNativeObject);
    237     }
    238 
    239     /**
    240      * Returns the number of layers in this buffer.
    241      */
    242     public int getLayers() {
    243         if (isClosed()) {
    244             throw new IllegalStateException("This HardwareBuffer has been closed and its layer "
    245                     + "count cannot be obtained.");
    246         }
    247         return nGetLayers(mNativeObject);
    248     }
    249 
    250     /**
    251      * Returns the usage flags of the usage hints set on this buffer.
    252      */
    253     public long getUsage() {
    254         if (isClosed()) {
    255             throw new IllegalStateException("This HardwareBuffer has been closed and its usage "
    256                     + "cannot be obtained.");
    257         }
    258         return nGetUsage(mNativeObject);
    259     }
    260 
    261     /** @removed replaced by {@link #close()} */
    262     @Deprecated
    263     public void destroy() {
    264         close();
    265     }
    266 
    267     /** @removed replaced by {@link #isClosed()} */
    268     @Deprecated
    269     public boolean isDestroyed() {
    270         return isClosed();
    271     }
    272 
    273     /**
    274      * Destroys this buffer immediately. Calling this method frees up any
    275      * underlying native resources. After calling this method, this buffer
    276      * must not be used in any way.
    277      *
    278      * @see #isClosed()
    279      */
    280     @Override
    281     public void close() {
    282         if (!isClosed()) {
    283             mCloseGuard.close();
    284             mNativeObject = 0;
    285             mCleaner.run();
    286             mCleaner = null;
    287         }
    288     }
    289 
    290     /**
    291      * Indicates whether this buffer has been closed. A closed buffer cannot
    292      * be used in any way: the buffer cannot be written to a parcel, etc.
    293      *
    294      * @return True if this <code>HardwareBuffer</code> is in a closed state,
    295      *         false otherwise.
    296      *
    297      * @see #close()
    298      */
    299     public boolean isClosed() {
    300         return mNativeObject == 0;
    301     }
    302 
    303     @Override
    304     public int describeContents() {
    305         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
    306     }
    307 
    308     /**
    309      * Flatten this object in to a Parcel.
    310      *
    311      * <p>Calling this method will throw an <code>IllegalStateException</code> if
    312      * {@link #close()} has been previously called.</p>
    313      *
    314      * @param dest The Parcel in which the object should be written.
    315      * @param flags Additional flags about how the object should be written.
    316      *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
    317      */
    318     @Override
    319     public void writeToParcel(Parcel dest, int flags) {
    320         if (isClosed()) {
    321             throw new IllegalStateException("This HardwareBuffer has been closed and cannot be "
    322                     + "written to a parcel.");
    323         }
    324         nWriteHardwareBufferToParcel(mNativeObject, dest);
    325     }
    326 
    327     public static final Parcelable.Creator<HardwareBuffer> CREATOR =
    328             new Parcelable.Creator<HardwareBuffer>() {
    329         public HardwareBuffer createFromParcel(Parcel in) {
    330             long nativeObject = nReadHardwareBufferFromParcel(in);
    331             if (nativeObject != 0) {
    332                 return new HardwareBuffer(nativeObject);
    333             }
    334             return null;
    335         }
    336 
    337         public HardwareBuffer[] newArray(int size) {
    338             return new HardwareBuffer[size];
    339         }
    340     };
    341 
    342     /**
    343      * Validates whether a particular format is supported by HardwareBuffer.
    344      *
    345      * @param format The format to validate.
    346      *
    347      * @return True if <code>format</code> is a supported format. false otherwise.
    348      * See {@link #create(int, int, int, int, long)}.
    349      */
    350     private static boolean isSupportedFormat(@Format int format) {
    351         switch(format) {
    352             case RGBA_8888:
    353             case RGBA_FP16:
    354             case RGBA_1010102:
    355             case RGBX_8888:
    356             case RGB_565:
    357             case RGB_888:
    358             case BLOB:
    359             case D_16:
    360             case D_24:
    361             case DS_24UI8:
    362             case D_FP32:
    363             case DS_FP32UI8:
    364             case S_UI8:
    365                 return true;
    366         }
    367         return false;
    368     }
    369 
    370     private static native long nCreateHardwareBuffer(int width, int height, int format, int layers,
    371             long usage);
    372     private static native long nGetNativeFinalizer();
    373     private static native void nWriteHardwareBufferToParcel(long nativeObject, Parcel dest);
    374     private static native long nReadHardwareBufferFromParcel(Parcel in);
    375     @FastNative
    376     private static native int nGetWidth(long nativeObject);
    377     @FastNative
    378     private static native int nGetHeight(long nativeObject);
    379     @FastNative
    380     private static native int nGetFormat(long nativeObject);
    381     @FastNative
    382     private static native int nGetLayers(long nativeObject);
    383     @FastNative
    384     private static native long nGetUsage(long nativeObject);
    385 }
    386