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 create(int width, int height, @Format int format, int layers, @Usage long usage)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 */ HardwareBuffer(long nativeObject)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 finalize()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 */ getWidth()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 */ getHeight()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 getFormat()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 */ getLayers()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 */ getUsage()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 destroy()263 public void destroy() { 264 close(); 265 } 266 267 /** @removed replaced by {@link #isClosed()} */ 268 @Deprecated isDestroyed()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 close()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 */ isClosed()299 public boolean isClosed() { 300 return mNativeObject == 0; 301 } 302 303 @Override describeContents()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 writeToParcel(Parcel dest, int flags)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 */ isSupportedFormat(@ormat int format)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 nCreateHardwareBuffer(int width, int height, int format, int layers, long usage)370 private static native long nCreateHardwareBuffer(int width, int height, int format, int layers, 371 long usage); nGetNativeFinalizer()372 private static native long nGetNativeFinalizer(); nWriteHardwareBufferToParcel(long nativeObject, Parcel dest)373 private static native void nWriteHardwareBufferToParcel(long nativeObject, Parcel dest); nReadHardwareBufferFromParcel(Parcel in)374 private static native long nReadHardwareBufferFromParcel(Parcel in); 375 @FastNative nGetWidth(long nativeObject)376 private static native int nGetWidth(long nativeObject); 377 @FastNative nGetHeight(long nativeObject)378 private static native int nGetHeight(long nativeObject); 379 @FastNative nGetFormat(long nativeObject)380 private static native int nGetFormat(long nativeObject); 381 @FastNative nGetLayers(long nativeObject)382 private static native int nGetLayers(long nativeObject); 383 @FastNative nGetUsage(long nativeObject)384 private static native long nGetUsage(long nativeObject); 385 } 386