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