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