Home | History | Annotate | Download | only in graphics
      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.os.Parcel;
     20 import android.os.Parcelable;
     21 
     22 /**
     23  * Simple wrapper for the native GraphicBuffer class.
     24  *
     25  * @hide
     26  */
     27 @SuppressWarnings("UnusedDeclaration")
     28 public 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