Home | History | Annotate | Download | only in view
      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      */
     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     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      */
    101     public int getWidth() {
    102         return mWidth;
    103     }
    104 
    105     /**
    106      * Returns the height of this buffer in pixels.
    107      */
    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      */
    116     public int getFormat() {
    117         return mFormat;
    118     }
    119 
    120     /**
    121      * Returns the usage hint set on this buffer.
    122      */
    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      */
    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      */
    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      */
    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      */
    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      */
    225     public boolean isDestroyed() {
    226         return mDestroyed;
    227     }
    228 
    229     @Override
    230     protected void finalize() throws Throwable {
    231         try {
    232             if (!mDestroyed) nDestroyGraphicBuffer(mNativeObject);
    233         } finally {
    234             super.finalize();
    235         }
    236     }
    237 
    238     @Override
    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
    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 
    286     private static native long nCreateGraphicBuffer(int width, int height, int format, int usage);
    287     private static native void nDestroyGraphicBuffer(long nativeObject);
    288     private static native void nWriteGraphicBufferToParcel(long nativeObject, Parcel dest);
    289     private static native long nReadGraphicBufferFromParcel(Parcel in);
    290     private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty);
    291     private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas);
    292 }
    293