HardwareBuffer.java revision 1a4d07d9193f843ebf4403ef49bac4cd61d34165
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 17package android.hardware; 18 19import android.annotation.IntDef; 20import android.annotation.NonNull; 21import android.os.Parcel; 22import android.os.Parcelable; 23 24import dalvik.annotation.optimization.FastNative; 25 26import java.lang.annotation.Retention; 27import java.lang.annotation.RetentionPolicy; 28 29import libcore.util.NativeAllocationRegistry; 30 31/** 32 * HardwareBuffer wraps a native <code>AHardwareBuffer</code> object, which is a low-level object 33 * representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing 34 * buffers across different application processes. In particular, HardwareBuffers may be mappable 35 * to memory accessibly to various hardware systems, such as the GPU, a sensor or context hub, or 36 * other auxiliary processing units. 37 * 38 * For more information, see the NDK documentation for <code>AHardwareBuffer</code>. 39 */ 40public final class HardwareBuffer implements Parcelable { 41 /** @hide */ 42 @Retention(RetentionPolicy.SOURCE) 43 @IntDef({RGBA_8888, RGBA_FP16, RGBX_8888, RGB_888, RGB_565}) 44 public @interface Format {}; 45 46 /** Format: 8 bits each red, green, blue, alpha */ 47 public static final int RGBA_8888 = 1; 48 /** Format: 8 bits each red, green, blue, alpha, alpha is always 0xFF */ 49 public static final int RGBX_8888 = 2; 50 /** Format: 8 bits each red, green, blue, no alpha */ 51 public static final int RGB_888 = 3; 52 /** Format: 5 bits each red and blue, 6 bits green, no alpha */ 53 public static final int RGB_565 = 4; 54 /** Format: 16 bits each red, green, blue, alpha */ 55 public static final int RGBA_FP16 = 5; 56 57 // Note: do not rename, this field is used by native code 58 private long mNativeObject; 59 60 // Invoked on destruction 61 private Runnable mCleaner; 62 63 /** @hide */ 64 @Retention(RetentionPolicy.SOURCE) 65 @IntDef(flag = true, value = {USAGE0_CPU_READ, USAGE0_CPU_READ_OFTEN, USAGE0_CPU_WRITE, 66 USAGE0_CPU_WRITE_OFTEN, USAGE0_GPU_SAMPLED_IMAGE, USAGE0_GPU_COLOR_OUTPUT, 67 USAGE0_GPU_STORAGE_IMAGE, USAGE0_GPU_CUBEMAP, USAGE0_GPU_DATA_BUFFER, 68 USAGE0_PROTECTED_CONTENT, USAGE0_SENSOR_DIRECT_DATA, USAGE0_VIDEO_ENCODE}) 69 public @interface Usage0 {}; 70 71 /** Usage0: the buffer will sometimes be read by the CPU */ 72 public static final long USAGE0_CPU_READ = (1 << 1); 73 /** Usage0: the buffer will often be read by the CPU*/ 74 public static final long USAGE0_CPU_READ_OFTEN = (1 << 2 | USAGE0_CPU_READ); 75 /** Usage0: the buffer will sometimes be written to by the CPU */ 76 public static final long USAGE0_CPU_WRITE = (1 << 5); 77 /** Usage0: the buffer will often be written to by the CPU */ 78 public static final long USAGE0_CPU_WRITE_OFTEN = (1 << 6 | USAGE0_CPU_WRITE); 79 /** Usage0: the buffer will be read from by the GPU */ 80 public static final long USAGE0_GPU_SAMPLED_IMAGE = (1 << 10); 81 /** Usage0: the buffer will be written to by the GPU */ 82 public static final long USAGE0_GPU_COLOR_OUTPUT = (1 << 11); 83 /** Usage0: the buffer will be read from and written to by the GPU */ 84 public static final long USAGE0_GPU_STORAGE_IMAGE = (USAGE0_GPU_SAMPLED_IMAGE | 85 USAGE0_GPU_COLOR_OUTPUT); 86 /** Usage0: the buffer will be used as a cubemap texture */ 87 public static final long USAGE0_GPU_CUBEMAP = (1 << 13); 88 /** Usage0: the buffer will be used as a shader storage or uniform buffer object*/ 89 public static final long USAGE0_GPU_DATA_BUFFER = (1 << 14); 90 /** Usage0: the buffer must not be used outside of a protected hardware path */ 91 public static final long USAGE0_PROTECTED_CONTENT = (1 << 18); 92 /** Usage0: the buffer will be used for sensor direct data */ 93 public static final long USAGE0_SENSOR_DIRECT_DATA = (1 << 29); 94 /** Usage0: the buffer will be read by a hardware video encoder */ 95 public static final long USAGE0_VIDEO_ENCODE = (1 << 21); 96 97 // The approximate size of a native AHardwareBuffer object. 98 private static final long NATIVE_HARDWARE_BUFFER_SIZE = 232; 99 /** 100 * Creates a new <code>HardwareBuffer</code> instance. 101 * 102 * <p>Calling this method will throw an <code>IllegalStateException</code> if 103 * format is not a supported Format type.</p> 104 * 105 * @param width The width in pixels of the buffer 106 * @param height The height in pixels of the buffer 107 * @param format The format of each pixel, one of {@link #RGBA_8888}, {@link #RGBA_FP16}, 108 * {@link #RGBX_8888}, {@link #RGB_565}, {@link #RGB_888} 109 * @param layers The number of layers in the buffer 110 * @param usage Flags describing how the buffer will be used, one of 111 * {@link #USAGE0_CPU_READ}, {@link #USAGE0_CPU_READ_OFTEN}, {@link #USAGE0_CPU_WRITE}, 112 * {@link #USAGE0_CPU_WRITE_OFTEN}, {@link #USAGE0_GPU_SAMPLED_IMAGE}, 113 * {@link #USAGE0_GPU_COLOR_OUTPUT},{@link #USAGE0_GPU_STORAGE_IMAGE}, 114 * {@link #USAGE0_GPU_CUBEMAP}, {@link #USAGE0_GPU_DATA_BUFFER}, 115 * {@link #USAGE0_PROTECTED_CONTENT}, {@link #USAGE0_SENSOR_DIRECT_DATA}, 116 * {@link #USAGE0_VIDEO_ENCODE} 117 * 118 * @return A <code>HardwareBuffer</code> instance if successful, or throws an 119 * IllegalArgumentException if the dimensions passed are invalid (either zero, negative, or 120 * too large to allocate), if the format is not supported, if the requested number of layers 121 * is less than one or not supported, or if the passed usage flags are not a supported set. 122 */ 123 @NonNull 124 public static HardwareBuffer create(int width, int height, @Format int format, int layers, 125 @Usage0 long usage) { 126 if (!HardwareBuffer.isSupportedFormat(format)) { 127 throw new IllegalArgumentException("Invalid pixel format " + format); 128 } 129 if (width <= 0) { 130 throw new IllegalArgumentException("Invalid width " + width); 131 } 132 if (height <= 0) { 133 throw new IllegalArgumentException("Invalid height " + height); 134 } 135 if (layers <= 0) { 136 throw new IllegalArgumentException("Invalid layer count " + layers); 137 } 138 long nativeObject = nCreateHardwareBuffer(width, height, format, layers, usage); 139 if (nativeObject == 0) { 140 throw new IllegalArgumentException("Unable to create a HardwareBuffer, either the " + 141 "dimensions passed were too large, too many image layers were requested, " + 142 "or an invalid set of usage flags was passed"); 143 } 144 return new HardwareBuffer(nativeObject); 145 } 146 147 /** 148 * Private use only. See {@link #create(int, int, int, int, int, long, long)}. May also be 149 * called from JNI using an already allocated native <code>HardwareBuffer</code>. 150 */ 151 private HardwareBuffer(long nativeObject) { 152 mNativeObject = nativeObject; 153 154 long nativeSize = NATIVE_HARDWARE_BUFFER_SIZE; 155 NativeAllocationRegistry registry = new NativeAllocationRegistry( 156 HardwareBuffer.class.getClassLoader(), nGetNativeFinalizer(), nativeSize); 157 mCleaner = registry.registerNativeAllocation(this, mNativeObject); 158 } 159 160 /** 161 * Returns the width of this buffer in pixels. 162 */ 163 public int getWidth() { 164 if (mNativeObject == 0) { 165 throw new IllegalStateException("This HardwareBuffer has been destroyed and its width " 166 + "cannot be obtained."); 167 } 168 return nGetWidth(mNativeObject); 169 } 170 171 /** 172 * Returns the height of this buffer in pixels. 173 */ 174 public int getHeight() { 175 if (mNativeObject == 0) { 176 throw new IllegalStateException("This HardwareBuffer has been destroyed and its height " 177 + "cannot be obtained."); 178 } 179 return nGetHeight(mNativeObject); 180 } 181 182 /** 183 * Returns the format of this buffer, one of {@link #RGBA_8888}, {@link #RGBA_FP16}, 184 * {@link #RGBX_8888}, {@link #RGB_565}, or {@link #RGB_888}. 185 */ 186 public int getFormat() { 187 if (mNativeObject == 0) { 188 throw new IllegalStateException("This HardwareBuffer has been destroyed and its format " 189 + "cannot be obtained."); 190 } 191 return nGetFormat(mNativeObject); 192 } 193 194 /** 195 * Returns the number of layers in this buffer. 196 */ 197 public int getLayers() { 198 if (mNativeObject == 0) { 199 throw new IllegalStateException("This HardwareBuffer has been destroyed and its layer " 200 + "count cannot be obtained."); 201 } 202 return nGetLayers(mNativeObject); 203 } 204 205 /** 206 * Returns the usage flags of the usage hints set on this buffer. 207 */ 208 public long getUsage() { 209 if (mNativeObject == 0) { 210 throw new IllegalStateException("This HardwareBuffer has been destroyed and its usage " 211 + "cannot be obtained."); 212 } 213 return nGetUsage(mNativeObject); 214 } 215 216 /** 217 * Destroys this buffer immediately. Calling this method frees up any 218 * underlying native resources. After calling this method, this buffer 219 * must not be used in any way. 220 * 221 * @see #isDestroyed() 222 */ 223 public void destroy() { 224 if (mNativeObject != 0) { 225 mNativeObject = 0; 226 mCleaner.run(); 227 mCleaner = null; 228 } 229 } 230 231 /** 232 * Indicates whether this buffer has been destroyed. A destroyed buffer 233 * cannot be used in any way: the buffer cannot be written to a parcel, etc. 234 * 235 * @return True if this <code>HardwareBuffer</code> is in a destroyed state, 236 * false otherwise. 237 * 238 * @see #destroy() 239 */ 240 public boolean isDestroyed() { 241 return mNativeObject == 0; 242 } 243 244 @Override 245 public int describeContents() { 246 return Parcelable.CONTENTS_FILE_DESCRIPTOR; 247 } 248 249 /** 250 * Flatten this object in to a Parcel. 251 * 252 * <p>Calling this method will throw an <code>IllegalStateException</code> if 253 * {@link #destroy()} has been previously called.</p> 254 * 255 * @param dest The Parcel in which the object should be written. 256 * @param flags Additional flags about how the object should be written. 257 * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. 258 */ 259 @Override 260 public void writeToParcel(Parcel dest, int flags) { 261 if (mNativeObject == 0) { 262 throw new IllegalStateException("This HardwareBuffer has been destroyed and cannot be " 263 + "written to a parcel."); 264 } 265 nWriteHardwareBufferToParcel(mNativeObject, dest); 266 } 267 268 public static final Parcelable.Creator<HardwareBuffer> CREATOR = 269 new Parcelable.Creator<HardwareBuffer>() { 270 public HardwareBuffer createFromParcel(Parcel in) { 271 long nativeObject = nReadHardwareBufferFromParcel(in); 272 if (nativeObject != 0) { 273 return new HardwareBuffer(nativeObject); 274 } 275 return null; 276 } 277 278 public HardwareBuffer[] newArray(int size) { 279 return new HardwareBuffer[size]; 280 } 281 }; 282 283 /** 284 * Validates whether a particular format is supported by HardwareBuffer. 285 * 286 * @param format The format to validate. 287 * 288 * @return True if <code>format</code> is a supported format. false otherwise. 289 * See {@link #create(int, int, int, int, int, long, long)}.a 290 */ 291 private static boolean isSupportedFormat(@Format int format) { 292 switch(format) { 293 case RGBA_8888: 294 case RGBA_FP16: 295 case RGBX_8888: 296 case RGB_565: 297 case RGB_888: 298 return true; 299 } 300 return false; 301 } 302 303 private static native long nCreateHardwareBuffer(int width, int height, int format, int layers, 304 long usage); 305 private static native long nGetNativeFinalizer(); 306 private static native void nWriteHardwareBufferToParcel(long nativeObject, Parcel dest); 307 private static native long nReadHardwareBufferFromParcel(Parcel in); 308 @FastNative 309 private static native int nGetWidth(long nativeObject); 310 @FastNative 311 private static native int nGetHeight(long nativeObject); 312 @FastNative 313 private static native int nGetFormat(long nativeObject); 314 @FastNative 315 private static native int nGetLayers(long nativeObject); 316 @FastNative 317 private static native long nGetUsage(long nativeObject); 318} 319