1 /* 2 * Copyright (C) 2013 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.graphics; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.hardware.HardwareBuffer; 21 import android.os.Build; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 /** 26 * Simple wrapper for the native GraphicBuffer class. 27 * 28 * @hide 29 */ 30 @SuppressWarnings("UnusedDeclaration") 31 public class GraphicBuffer implements Parcelable { 32 // Note: keep usage flags in sync with GraphicBuffer.h and gralloc.h 33 public static final int USAGE_SW_READ_NEVER = 0x0; 34 public static final int USAGE_SW_READ_RARELY = 0x2; 35 public static final int USAGE_SW_READ_OFTEN = 0x3; 36 public static final int USAGE_SW_READ_MASK = 0xF; 37 38 public static final int USAGE_SW_WRITE_NEVER = 0x0; 39 public static final int USAGE_SW_WRITE_RARELY = 0x20; 40 public static final int USAGE_SW_WRITE_OFTEN = 0x30; 41 public static final int USAGE_SW_WRITE_MASK = 0xF0; 42 43 public static final int USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK | USAGE_SW_WRITE_MASK; 44 45 public static final int USAGE_PROTECTED = 0x4000; 46 47 public static final int USAGE_HW_TEXTURE = 0x100; 48 public static final int USAGE_HW_RENDER = 0x200; 49 public static final int USAGE_HW_2D = 0x400; 50 public static final int USAGE_HW_COMPOSER = 0x800; 51 public static final int USAGE_HW_VIDEO_ENCODER = 0x10000; 52 public static final int USAGE_HW_MASK = 0x71F00; 53 54 private final int mWidth; 55 private final int mHeight; 56 private final int mFormat; 57 private final int mUsage; 58 // Note: do not rename, this field is used by native code 59 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 60 private final long mNativeObject; 61 62 // These two fields are only used by lock/unlockCanvas() 63 private Canvas mCanvas; 64 private int mSaveCount; 65 66 // If set to true, this GraphicBuffer instance cannot be used anymore 67 private boolean mDestroyed; 68 69 /** 70 * Creates new <code>GraphicBuffer</code> instance. This method will return null 71 * if the buffer cannot be created. 72 * 73 * @param width The width in pixels of the buffer 74 * @param height The height in pixels of the buffer 75 * @param format The format of each pixel as specified in {@link PixelFormat} 76 * @param usage Hint indicating how the buffer will be used 77 * 78 * @return A <code>GraphicBuffer</code> instance or null 79 */ create(int width, int height, int format, int usage)80 public static GraphicBuffer create(int width, int height, int format, int usage) { 81 long nativeObject = nCreateGraphicBuffer(width, height, format, usage); 82 if (nativeObject != 0) { 83 return new GraphicBuffer(width, height, format, usage, nativeObject); 84 } 85 return null; 86 } 87 88 /** 89 * Private use only. See {@link #create(int, int, int, int)}. 90 */ 91 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) GraphicBuffer(int width, int height, int format, int usage, long nativeObject)92 private GraphicBuffer(int width, int height, int format, int usage, long nativeObject) { 93 mWidth = width; 94 mHeight = height; 95 mFormat = format; 96 mUsage = usage; 97 mNativeObject = nativeObject; 98 } 99 100 /** 101 * For Bitmap until all usages are updated to AHB 102 * @hide 103 */ createFromHardwareBuffer(HardwareBuffer buffer)104 public static final GraphicBuffer createFromHardwareBuffer(HardwareBuffer buffer) { 105 return nCreateFromHardwareBuffer(buffer); 106 } 107 108 /** 109 * Returns the width of this buffer in pixels. 110 */ getWidth()111 public int getWidth() { 112 return mWidth; 113 } 114 115 /** 116 * Returns the height of this buffer in pixels. 117 */ getHeight()118 public int getHeight() { 119 return mHeight; 120 } 121 122 /** 123 * Returns the pixel format of this buffer. The pixel format must be one of 124 * the formats defined in {@link PixelFormat}. 125 */ getFormat()126 public int getFormat() { 127 return mFormat; 128 } 129 130 /** 131 * Returns the usage hint set on this buffer. 132 */ getUsage()133 public int getUsage() { 134 return mUsage; 135 } 136 137 /** 138 * <p>Start editing the pixels in the buffer. A null is returned if the buffer 139 * cannot be locked for editing.</p> 140 * 141 * <p>The content of the buffer is preserved between unlockCanvas() 142 * and lockCanvas().</p> 143 * 144 * <p>If this method is called after {@link #destroy()}, the return value will 145 * always be null.</p> 146 * 147 * @return A Canvas used to draw into the buffer, or null. 148 * 149 * @see #lockCanvas(android.graphics.Rect) 150 * @see #unlockCanvasAndPost(android.graphics.Canvas) 151 * @see #isDestroyed() 152 */ lockCanvas()153 public Canvas lockCanvas() { 154 return lockCanvas(null); 155 } 156 157 /** 158 * Just like {@link #lockCanvas()} but allows specification of a dirty 159 * rectangle. 160 * 161 * <p>If this method is called after {@link #destroy()}, the return value will 162 * always be null.</p> 163 * 164 * @param dirty Area of the buffer that may be modified. 165 166 * @return A Canvas used to draw into the surface, or null. 167 * 168 * @see #lockCanvas() 169 * @see #unlockCanvasAndPost(android.graphics.Canvas) 170 * @see #isDestroyed() 171 */ lockCanvas(Rect dirty)172 public Canvas lockCanvas(Rect dirty) { 173 if (mDestroyed) { 174 return null; 175 } 176 177 if (mCanvas == null) { 178 mCanvas = new Canvas(); 179 } 180 181 if (nLockCanvas(mNativeObject, mCanvas, dirty)) { 182 mSaveCount = mCanvas.save(); 183 return mCanvas; 184 } 185 186 return null; 187 } 188 189 /** 190 * Finish editing pixels in the buffer. 191 * 192 * <p>This method doesn't do anything if {@link #destroy()} was 193 * previously called.</p> 194 * 195 * @param canvas The Canvas previously returned by lockCanvas() 196 * 197 * @see #lockCanvas() 198 * @see #lockCanvas(android.graphics.Rect) 199 * @see #isDestroyed() 200 */ unlockCanvasAndPost(Canvas canvas)201 public void unlockCanvasAndPost(Canvas canvas) { 202 if (!mDestroyed && mCanvas != null && canvas == mCanvas) { 203 canvas.restoreToCount(mSaveCount); 204 mSaveCount = 0; 205 206 nUnlockCanvasAndPost(mNativeObject, mCanvas); 207 } 208 } 209 210 /** 211 * Destroyes this buffer immediately. Calling this method frees up any 212 * underlying native resources. After calling this method, this buffer 213 * must not be used in any way ({@link #lockCanvas()} must not be called, 214 * etc.) 215 * 216 * @see #isDestroyed() 217 */ destroy()218 public void destroy() { 219 if (!mDestroyed) { 220 mDestroyed = true; 221 nDestroyGraphicBuffer(mNativeObject); 222 } 223 } 224 225 /** 226 * Indicates whether this buffer has been destroyed. A destroyed buffer 227 * cannot be used in any way: locking a Canvas will return null, the buffer 228 * cannot be written to a parcel, etc. 229 * 230 * @return True if this <code>GraphicBuffer</code> is in a destroyed state, 231 * false otherwise. 232 * 233 * @see #destroy() 234 */ isDestroyed()235 public boolean isDestroyed() { 236 return mDestroyed; 237 } 238 239 @Override finalize()240 protected void finalize() throws Throwable { 241 try { 242 if (!mDestroyed) nDestroyGraphicBuffer(mNativeObject); 243 } finally { 244 super.finalize(); 245 } 246 } 247 248 @Override describeContents()249 public int describeContents() { 250 return 0; 251 } 252 253 /** 254 * Flatten this object in to a Parcel. 255 * 256 * <p>Calling this method will throw an <code>IllegalStateException</code> if 257 * {@link #destroy()} has been previously called.</p> 258 * 259 * @param dest The Parcel in which the object should be written. 260 * @param flags Additional flags about how the object should be written. 261 * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. 262 */ 263 @Override writeToParcel(Parcel dest, int flags)264 public void writeToParcel(Parcel dest, int flags) { 265 if (mDestroyed) { 266 throw new IllegalStateException("This GraphicBuffer has been destroyed and cannot be " 267 + "written to a parcel."); 268 } 269 270 dest.writeInt(mWidth); 271 dest.writeInt(mHeight); 272 dest.writeInt(mFormat); 273 dest.writeInt(mUsage); 274 nWriteGraphicBufferToParcel(mNativeObject, dest); 275 } 276 277 @UnsupportedAppUsage 278 public static final @android.annotation.NonNull Parcelable.Creator<GraphicBuffer> CREATOR = 279 new Parcelable.Creator<GraphicBuffer>() { 280 public GraphicBuffer createFromParcel(Parcel in) { 281 int width = in.readInt(); 282 int height = in.readInt(); 283 int format = in.readInt(); 284 int usage = in.readInt(); 285 long nativeObject = nReadGraphicBufferFromParcel(in); 286 if (nativeObject != 0) { 287 return new GraphicBuffer(width, height, format, usage, nativeObject); 288 } 289 return null; 290 } 291 292 public GraphicBuffer[] newArray(int size) { 293 return new GraphicBuffer[size]; 294 } 295 }; 296 nCreateGraphicBuffer(int width, int height, int format, int usage)297 private static native long nCreateGraphicBuffer(int width, int height, int format, int usage); nDestroyGraphicBuffer(long nativeObject)298 private static native void nDestroyGraphicBuffer(long nativeObject); nWriteGraphicBufferToParcel(long nativeObject, Parcel dest)299 private static native void nWriteGraphicBufferToParcel(long nativeObject, Parcel dest); nReadGraphicBufferFromParcel(Parcel in)300 private static native long nReadGraphicBufferFromParcel(Parcel in); nLockCanvas(long nativeObject, Canvas canvas, Rect dirty)301 private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty); nUnlockCanvasAndPost(long nativeObject, Canvas canvas)302 private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas); nCreateFromHardwareBuffer(HardwareBuffer buffer)303 private static native GraphicBuffer nCreateFromHardwareBuffer(HardwareBuffer buffer); 304 } 305