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