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