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.compat.annotation.UnsupportedAppUsage;
20 import android.hardware.HardwareBuffer;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 
24 /**
25  * Simple wrapper for the native GraphicBuffer class.
26  *
27  * @hide
28  */
29 @SuppressWarnings("UnusedDeclaration")
30 public class GraphicBuffer implements Parcelable {
31     // Note: keep usage flags in sync with GraphicBuffer.h and gralloc.h
32     public static final int USAGE_SW_READ_NEVER = 0x0;
33     public static final int USAGE_SW_READ_RARELY = 0x2;
34     public static final int USAGE_SW_READ_OFTEN = 0x3;
35     public static final int USAGE_SW_READ_MASK = 0xF;
36 
37     public static final int USAGE_SW_WRITE_NEVER = 0x0;
38     public static final int USAGE_SW_WRITE_RARELY = 0x20;
39     public static final int USAGE_SW_WRITE_OFTEN = 0x30;
40     public static final int USAGE_SW_WRITE_MASK = 0xF0;
41 
42     public static final int USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK | USAGE_SW_WRITE_MASK;
43 
44     public static final int USAGE_PROTECTED = 0x4000;
45 
46     public static final int USAGE_HW_TEXTURE = 0x100;
47     public static final int USAGE_HW_RENDER = 0x200;
48     public static final int USAGE_HW_2D = 0x400;
49     public static final int USAGE_HW_COMPOSER = 0x800;
50     public static final int USAGE_HW_VIDEO_ENCODER = 0x10000;
51     public static final int USAGE_HW_MASK = 0x71F00;
52 
53     private final int mWidth;
54     private final int mHeight;
55     private final int mFormat;
56     private final int mUsage;
57     // Note: do not rename, this field is used by native code
58     @UnsupportedAppUsage
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      */
90     @UnsupportedAppUsage
GraphicBuffer(int width, int height, int format, int usage, long nativeObject)91     private GraphicBuffer(int width, int height, int format, int usage, long nativeObject) {
92         mWidth = width;
93         mHeight = height;
94         mFormat = format;
95         mUsage = usage;
96         mNativeObject = nativeObject;
97     }
98 
99     /**
100      * For SurfaceControl JNI.
101      * @hide
102      */
103     @UnsupportedAppUsage
createFromExisting(int width, int height, int format, int usage, long unwrappedNativeObject)104     public static GraphicBuffer createFromExisting(int width, int height,
105             int format, int usage, long unwrappedNativeObject) {
106         long nativeObject = nWrapGraphicBuffer(unwrappedNativeObject);
107         if (nativeObject != 0) {
108             return new GraphicBuffer(width, height, format, usage, nativeObject);
109         }
110         return null;
111     }
112 
113     /**
114      * For Bitmap until all usages are updated to AHB
115      * @hide
116      */
createFromHardwareBuffer(HardwareBuffer buffer)117     public static final GraphicBuffer createFromHardwareBuffer(HardwareBuffer buffer) {
118         return nCreateFromHardwareBuffer(buffer);
119     }
120 
121     /**
122      * Returns the width of this buffer in pixels.
123      */
getWidth()124     public int getWidth() {
125         return mWidth;
126     }
127 
128     /**
129      * Returns the height of this buffer in pixels.
130      */
getHeight()131     public int getHeight() {
132         return mHeight;
133     }
134 
135     /**
136      * Returns the pixel format of this buffer. The pixel format must be one of
137      * the formats defined in {@link PixelFormat}.
138      */
getFormat()139     public int getFormat() {
140         return mFormat;
141     }
142 
143     /**
144      * Returns the usage hint set on this buffer.
145      */
getUsage()146     public int getUsage() {
147         return mUsage;
148     }
149 
150     /**
151      * <p>Start editing the pixels in the buffer. A null is returned if the buffer
152      * cannot be locked for editing.</p>
153      *
154      * <p>The content of the buffer is preserved between unlockCanvas()
155      * and lockCanvas().</p>
156      *
157      * <p>If this method is called after {@link #destroy()}, the return value will
158      * always be null.</p>
159      *
160      * @return A Canvas used to draw into the buffer, or null.
161      *
162      * @see #lockCanvas(android.graphics.Rect)
163      * @see #unlockCanvasAndPost(android.graphics.Canvas)
164      * @see #isDestroyed()
165      */
lockCanvas()166     public Canvas lockCanvas() {
167         return lockCanvas(null);
168     }
169 
170     /**
171      * Just like {@link #lockCanvas()} but allows specification of a dirty
172      * rectangle.
173      *
174      * <p>If this method is called after {@link #destroy()}, the return value will
175      * always be null.</p>
176      *
177      * @param dirty Area of the buffer that may be modified.
178 
179      * @return A Canvas used to draw into the surface, or null.
180      *
181      * @see #lockCanvas()
182      * @see #unlockCanvasAndPost(android.graphics.Canvas)
183      * @see #isDestroyed()
184      */
lockCanvas(Rect dirty)185     public Canvas lockCanvas(Rect dirty) {
186         if (mDestroyed) {
187             return null;
188         }
189 
190         if (mCanvas == null) {
191             mCanvas = new Canvas();
192         }
193 
194         if (nLockCanvas(mNativeObject, mCanvas, dirty)) {
195             mSaveCount = mCanvas.save();
196             return mCanvas;
197         }
198 
199         return null;
200     }
201 
202     /**
203      * Finish editing pixels in the buffer.
204      *
205      * <p>This method doesn't do anything if {@link #destroy()} was
206      * previously called.</p>
207      *
208      * @param canvas The Canvas previously returned by lockCanvas()
209      *
210      * @see #lockCanvas()
211      * @see #lockCanvas(android.graphics.Rect)
212      * @see #isDestroyed()
213      */
unlockCanvasAndPost(Canvas canvas)214     public void unlockCanvasAndPost(Canvas canvas) {
215         if (!mDestroyed && mCanvas != null && canvas == mCanvas) {
216             canvas.restoreToCount(mSaveCount);
217             mSaveCount = 0;
218 
219             nUnlockCanvasAndPost(mNativeObject, mCanvas);
220         }
221     }
222 
223     /**
224      * Destroyes this buffer immediately. Calling this method frees up any
225      * underlying native resources. After calling this method, this buffer
226      * must not be used in any way ({@link #lockCanvas()} must not be called,
227      * etc.)
228      *
229      * @see #isDestroyed()
230      */
destroy()231     public void destroy() {
232         if (!mDestroyed) {
233             mDestroyed = true;
234             nDestroyGraphicBuffer(mNativeObject);
235         }
236     }
237 
238     /**
239      * Indicates whether this buffer has been destroyed. A destroyed buffer
240      * cannot be used in any way: locking a Canvas will return null, the buffer
241      * cannot be written to a parcel, etc.
242      *
243      * @return True if this <code>GraphicBuffer</code> is in a destroyed state,
244      *         false otherwise.
245      *
246      * @see #destroy()
247      */
isDestroyed()248     public boolean isDestroyed() {
249         return mDestroyed;
250     }
251 
252     @Override
finalize()253     protected void finalize() throws Throwable {
254         try {
255             if (!mDestroyed) nDestroyGraphicBuffer(mNativeObject);
256         } finally {
257             super.finalize();
258         }
259     }
260 
261     @Override
describeContents()262     public int describeContents() {
263         return 0;
264     }
265 
266     /**
267      * Flatten this object in to a Parcel.
268      *
269      * <p>Calling this method will throw an <code>IllegalStateException</code> if
270      * {@link #destroy()} has been previously called.</p>
271      *
272      * @param dest The Parcel in which the object should be written.
273      * @param flags Additional flags about how the object should be written.
274      *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
275      */
276     @Override
writeToParcel(Parcel dest, int flags)277     public void writeToParcel(Parcel dest, int flags) {
278         if (mDestroyed) {
279             throw new IllegalStateException("This GraphicBuffer has been destroyed and cannot be "
280                     + "written to a parcel.");
281         }
282 
283         dest.writeInt(mWidth);
284         dest.writeInt(mHeight);
285         dest.writeInt(mFormat);
286         dest.writeInt(mUsage);
287         nWriteGraphicBufferToParcel(mNativeObject, dest);
288     }
289 
290     @UnsupportedAppUsage
291     public static final @android.annotation.NonNull Parcelable.Creator<GraphicBuffer> CREATOR =
292             new Parcelable.Creator<GraphicBuffer>() {
293         public GraphicBuffer createFromParcel(Parcel in) {
294             int width = in.readInt();
295             int height = in.readInt();
296             int format = in.readInt();
297             int usage = in.readInt();
298             long nativeObject = nReadGraphicBufferFromParcel(in);
299             if (nativeObject != 0) {
300                 return new GraphicBuffer(width, height, format, usage, nativeObject);
301             }
302             return null;
303         }
304 
305         public GraphicBuffer[] newArray(int size) {
306             return new GraphicBuffer[size];
307         }
308     };
309 
nCreateGraphicBuffer(int width, int height, int format, int usage)310     private static native long nCreateGraphicBuffer(int width, int height, int format, int usage);
nDestroyGraphicBuffer(long nativeObject)311     private static native void nDestroyGraphicBuffer(long nativeObject);
nWriteGraphicBufferToParcel(long nativeObject, Parcel dest)312     private static native void nWriteGraphicBufferToParcel(long nativeObject, Parcel dest);
nReadGraphicBufferFromParcel(Parcel in)313     private static native long nReadGraphicBufferFromParcel(Parcel in);
nLockCanvas(long nativeObject, Canvas canvas, Rect dirty)314     private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty);
nUnlockCanvasAndPost(long nativeObject, Canvas canvas)315     private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas);
nWrapGraphicBuffer(long nativeObject)316     private static native long nWrapGraphicBuffer(long nativeObject);
nCreateFromHardwareBuffer(HardwareBuffer buffer)317     private static native GraphicBuffer nCreateFromHardwareBuffer(HardwareBuffer buffer);
318 }
319