GraphicBuffer.java revision 0a0f23163a7a62900d46c7f81d109320d73d6c6b
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 * Returns the width of this buffer in pixels. 97 */ 98 public int getWidth() { 99 return mWidth; 100 } 101 102 /** 103 * Returns the height of this buffer in pixels. 104 */ 105 public int getHeight() { 106 return mHeight; 107 } 108 109 /** 110 * Returns the pixel format of this buffer. The pixel format must be one of 111 * the formats defined in {@link PixelFormat}. 112 */ 113 public int getFormat() { 114 return mFormat; 115 } 116 117 /** 118 * Returns the usage hint set on this buffer. 119 */ 120 public int getUsage() { 121 return mUsage; 122 } 123 124 /** 125 * <p>Start editing the pixels in the buffer. A null is returned if the buffer 126 * cannot be locked for editing.</p> 127 * 128 * <p>The content of the buffer is preserved between unlockCanvas() 129 * and lockCanvas().</p> 130 * 131 * <p>If this method is called after {@link #destroy()}, the return value will 132 * always be null.</p> 133 * 134 * @return A Canvas used to draw into the buffer, or null. 135 * 136 * @see #lockCanvas(android.graphics.Rect) 137 * @see #unlockCanvasAndPost(android.graphics.Canvas) 138 * @see #isDestroyed() 139 */ 140 public Canvas lockCanvas() { 141 return lockCanvas(null); 142 } 143 144 /** 145 * Just like {@link #lockCanvas()} but allows specification of a dirty 146 * rectangle. 147 * 148 * <p>If this method is called after {@link #destroy()}, the return value will 149 * always be null.</p> 150 * 151 * @param dirty Area of the buffer that may be modified. 152 153 * @return A Canvas used to draw into the surface, or null. 154 * 155 * @see #lockCanvas() 156 * @see #unlockCanvasAndPost(android.graphics.Canvas) 157 * @see #isDestroyed() 158 */ 159 public Canvas lockCanvas(Rect dirty) { 160 if (mDestroyed) { 161 return null; 162 } 163 164 if (mCanvas == null) { 165 mCanvas = new Canvas(); 166 } 167 168 if (nLockCanvas(mNativeObject, mCanvas, dirty)) { 169 mSaveCount = mCanvas.save(); 170 return mCanvas; 171 } 172 173 return null; 174 } 175 176 /** 177 * Finish editing pixels in the buffer. 178 * 179 * <p>This method doesn't do anything if {@link #destroy()} was 180 * previously called.</p> 181 * 182 * @param canvas The Canvas previously returned by lockCanvas() 183 * 184 * @see #lockCanvas() 185 * @see #lockCanvas(android.graphics.Rect) 186 * @see #isDestroyed() 187 */ 188 public void unlockCanvasAndPost(Canvas canvas) { 189 if (!mDestroyed && mCanvas != null && canvas == mCanvas) { 190 canvas.restoreToCount(mSaveCount); 191 mSaveCount = 0; 192 193 nUnlockCanvasAndPost(mNativeObject, mCanvas); 194 } 195 } 196 197 /** 198 * Destroyes this buffer immediately. Calling this method frees up any 199 * underlying native resources. After calling this method, this buffer 200 * must not be used in any way ({@link #lockCanvas()} must not be called, 201 * etc.) 202 * 203 * @see #isDestroyed() 204 */ 205 public void destroy() { 206 if (!mDestroyed) { 207 mDestroyed = true; 208 nDestroyGraphicBuffer(mNativeObject); 209 } 210 } 211 212 /** 213 * Indicates whether this buffer has been destroyed. A destroyed buffer 214 * cannot be used in any way: locking a Canvas will return null, the buffer 215 * cannot be written to a parcel, etc. 216 * 217 * @return True if this <code>GraphicBuffer</code> is in a destroyed state, 218 * false otherwise. 219 * 220 * @see #destroy() 221 */ 222 public boolean isDestroyed() { 223 return mDestroyed; 224 } 225 226 @Override 227 protected void finalize() throws Throwable { 228 try { 229 if (!mDestroyed) nDestroyGraphicBuffer(mNativeObject); 230 } finally { 231 super.finalize(); 232 } 233 } 234 235 @Override 236 public int describeContents() { 237 return 0; 238 } 239 240 /** 241 * Flatten this object in to a Parcel. 242 * 243 * <p>Calling this method will throw an <code>IllegalStateException</code> if 244 * {@link #destroy()} has been previously called.</p> 245 * 246 * @param dest The Parcel in which the object should be written. 247 * @param flags Additional flags about how the object should be written. 248 * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. 249 */ 250 @Override 251 public void writeToParcel(Parcel dest, int flags) { 252 if (mDestroyed) { 253 throw new IllegalStateException("This GraphicBuffer has been destroyed and cannot be " 254 + "written to a parcel."); 255 } 256 257 dest.writeInt(mWidth); 258 dest.writeInt(mHeight); 259 dest.writeInt(mFormat); 260 dest.writeInt(mUsage); 261 nWriteGraphicBufferToParcel(mNativeObject, dest); 262 } 263 264 public static final Parcelable.Creator<GraphicBuffer> CREATOR = 265 new Parcelable.Creator<GraphicBuffer>() { 266 public GraphicBuffer createFromParcel(Parcel in) { 267 int width = in.readInt(); 268 int height = in.readInt(); 269 int format = in.readInt(); 270 int usage = in.readInt(); 271 long nativeObject = nReadGraphicBufferFromParcel(in); 272 if (nativeObject != 0) { 273 return new GraphicBuffer(width, height, format, usage, nativeObject); 274 } 275 return null; 276 } 277 278 public GraphicBuffer[] newArray(int size) { 279 return new GraphicBuffer[size]; 280 } 281 }; 282 283 private static native long nCreateGraphicBuffer(int width, int height, int format, int usage); 284 private static native void nDestroyGraphicBuffer(long nativeObject); 285 private static native void nWriteGraphicBufferToParcel(long nativeObject, Parcel dest); 286 private static native long nReadGraphicBufferFromParcel(Parcel in); 287 private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty); 288 private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas); 289} 290