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 17package android.graphics; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21 22/** 23 * Simple wrapper for the native GraphicBuffer class. 24 * 25 * @hide 26 */ 27@SuppressWarnings("UnusedDeclaration") 28public class GraphicBuffer implements Parcelable { 29 // Note: keep usage flags in sync with GraphicBuffer.h and gralloc.h 30 public static final int USAGE_SW_READ_NEVER = 0x0; 31 public static final int USAGE_SW_READ_RARELY = 0x2; 32 public static final int USAGE_SW_READ_OFTEN = 0x3; 33 public static final int USAGE_SW_READ_MASK = 0xF; 34 35 public static final int USAGE_SW_WRITE_NEVER = 0x0; 36 public static final int USAGE_SW_WRITE_RARELY = 0x20; 37 public static final int USAGE_SW_WRITE_OFTEN = 0x30; 38 public static final int USAGE_SW_WRITE_MASK = 0xF0; 39 40 public static final int USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK | USAGE_SW_WRITE_MASK; 41 42 public static final int USAGE_PROTECTED = 0x4000; 43 44 public static final int USAGE_HW_TEXTURE = 0x100; 45 public static final int USAGE_HW_RENDER = 0x200; 46 public static final int USAGE_HW_2D = 0x400; 47 public static final int USAGE_HW_COMPOSER = 0x800; 48 public static final int USAGE_HW_VIDEO_ENCODER = 0x10000; 49 public static final int USAGE_HW_MASK = 0x71F00; 50 51 private final int mWidth; 52 private final int mHeight; 53 private final int mFormat; 54 private final int mUsage; 55 // Note: do not rename, this field is used by native code 56 private final long mNativeObject; 57 58 // These two fields are only used by lock/unlockCanvas() 59 private Canvas mCanvas; 60 private int mSaveCount; 61 62 // If set to true, this GraphicBuffer instance cannot be used anymore 63 private boolean mDestroyed; 64 65 /** 66 * Creates new <code>GraphicBuffer</code> instance. This method will return null 67 * if the buffer cannot be created. 68 * 69 * @param width The width in pixels of the buffer 70 * @param height The height in pixels of the buffer 71 * @param format The format of each pixel as specified in {@link PixelFormat} 72 * @param usage Hint indicating how the buffer will be used 73 * 74 * @return A <code>GraphicBuffer</code> instance or null 75 */ 76 public static GraphicBuffer create(int width, int height, int format, int usage) { 77 long nativeObject = nCreateGraphicBuffer(width, height, format, usage); 78 if (nativeObject != 0) { 79 return new GraphicBuffer(width, height, format, usage, nativeObject); 80 } 81 return null; 82 } 83 84 /** 85 * Private use only. See {@link #create(int, int, int, int)}. 86 */ 87 private GraphicBuffer(int width, int height, int format, int usage, long nativeObject) { 88 mWidth = width; 89 mHeight = height; 90 mFormat = format; 91 mUsage = usage; 92 mNativeObject = nativeObject; 93 } 94 95 /** 96 * For SurfaceControl JNI. 97 * @hide 98 */ 99 public static GraphicBuffer createFromExisting(int width, int height, 100 int format, int usage, long unwrappedNativeObject) { 101 long nativeObject = nWrapGraphicBuffer(unwrappedNativeObject); 102 if (nativeObject != 0) { 103 return new GraphicBuffer(width, height, format, usage, nativeObject); 104 } 105 return null; 106 } 107 108 /** 109 * Returns the width of this buffer in pixels. 110 */ 111 public int getWidth() { 112 return mWidth; 113 } 114 115 /** 116 * Returns the height of this buffer in pixels. 117 */ 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 */ 126 public int getFormat() { 127 return mFormat; 128 } 129 130 /** 131 * Returns the usage hint set on this buffer. 132 */ 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 */ 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 */ 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 */ 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 */ 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 */ 235 public boolean isDestroyed() { 236 return mDestroyed; 237 } 238 239 @Override 240 protected void finalize() throws Throwable { 241 try { 242 if (!mDestroyed) nDestroyGraphicBuffer(mNativeObject); 243 } finally { 244 super.finalize(); 245 } 246 } 247 248 @Override 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 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 public static final Parcelable.Creator<GraphicBuffer> CREATOR = 278 new Parcelable.Creator<GraphicBuffer>() { 279 public GraphicBuffer createFromParcel(Parcel in) { 280 int width = in.readInt(); 281 int height = in.readInt(); 282 int format = in.readInt(); 283 int usage = in.readInt(); 284 long nativeObject = nReadGraphicBufferFromParcel(in); 285 if (nativeObject != 0) { 286 return new GraphicBuffer(width, height, format, usage, nativeObject); 287 } 288 return null; 289 } 290 291 public GraphicBuffer[] newArray(int size) { 292 return new GraphicBuffer[size]; 293 } 294 }; 295 296 private static native long nCreateGraphicBuffer(int width, int height, int format, int usage); 297 private static native void nDestroyGraphicBuffer(long nativeObject); 298 private static native void nWriteGraphicBufferToParcel(long nativeObject, Parcel dest); 299 private static native long nReadGraphicBufferFromParcel(Parcel in); 300 private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty); 301 private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas); 302 private static native long nWrapGraphicBuffer(long nativeObject); 303} 304