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