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