• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Build;
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     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
60     private final long mNativeObject;
61 
62     // These two fields are only used by lock/unlockCanvas()
63     private Canvas mCanvas;
64     private int mSaveCount;
65 
66     // If set to true, this GraphicBuffer instance cannot be used anymore
67     private boolean mDestroyed;
68 
69     /**
70      * Creates new <code>GraphicBuffer</code> instance. This method will return null
71      * if the buffer cannot be created.
72      *
73      * @param width The width in pixels of the buffer
74      * @param height The height in pixels of the buffer
75      * @param format The format of each pixel as specified in {@link PixelFormat}
76      * @param usage Hint indicating how the buffer will be used
77      *
78      * @return A <code>GraphicBuffer</code> instance or null
79      */
create(int width, int height, int format, int usage)80     public static GraphicBuffer create(int width, int height, int format, int usage) {
81         long nativeObject = nCreateGraphicBuffer(width, height, format, usage);
82         if (nativeObject != 0) {
83             return new GraphicBuffer(width, height, format, usage, nativeObject);
84         }
85         return null;
86     }
87 
88     /**
89      * Private use only. See {@link #create(int, int, int, int)}.
90      */
91     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
GraphicBuffer(int width, int height, int format, int usage, long nativeObject)92     private GraphicBuffer(int width, int height, int format, int usage, long nativeObject) {
93         mWidth = width;
94         mHeight = height;
95         mFormat = format;
96         mUsage = usage;
97         mNativeObject = nativeObject;
98     }
99 
100     /**
101      * For Bitmap until all usages are updated to AHB
102      * @hide
103      */
createFromHardwareBuffer(HardwareBuffer buffer)104     public static final GraphicBuffer createFromHardwareBuffer(HardwareBuffer buffer) {
105         return nCreateFromHardwareBuffer(buffer);
106     }
107 
108     /**
109      * Returns the width of this buffer in pixels.
110      */
getWidth()111     public int getWidth() {
112         return mWidth;
113     }
114 
115     /**
116      * Returns the height of this buffer in pixels.
117      */
getHeight()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      */
getFormat()126     public int getFormat() {
127         return mFormat;
128     }
129 
130     /**
131      * Returns the usage hint set on this buffer.
132      */
getUsage()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      */
lockCanvas()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      */
lockCanvas(Rect dirty)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      */
unlockCanvasAndPost(Canvas canvas)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      */
destroy()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      */
isDestroyed()235     public boolean isDestroyed() {
236         return mDestroyed;
237     }
238 
239     @Override
finalize()240     protected void finalize() throws Throwable {
241         try {
242             if (!mDestroyed) nDestroyGraphicBuffer(mNativeObject);
243         } finally {
244             super.finalize();
245         }
246     }
247 
248     @Override
describeContents()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
writeToParcel(Parcel dest, int flags)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     @UnsupportedAppUsage
278     public static final @android.annotation.NonNull Parcelable.Creator<GraphicBuffer> CREATOR =
279             new Parcelable.Creator<GraphicBuffer>() {
280         public GraphicBuffer createFromParcel(Parcel in) {
281             int width = in.readInt();
282             int height = in.readInt();
283             int format = in.readInt();
284             int usage = in.readInt();
285             long nativeObject = nReadGraphicBufferFromParcel(in);
286             if (nativeObject != 0) {
287                 return new GraphicBuffer(width, height, format, usage, nativeObject);
288             }
289             return null;
290         }
291 
292         public GraphicBuffer[] newArray(int size) {
293             return new GraphicBuffer[size];
294         }
295     };
296 
nCreateGraphicBuffer(int width, int height, int format, int usage)297     private static native long nCreateGraphicBuffer(int width, int height, int format, int usage);
nDestroyGraphicBuffer(long nativeObject)298     private static native void nDestroyGraphicBuffer(long nativeObject);
nWriteGraphicBufferToParcel(long nativeObject, Parcel dest)299     private static native void nWriteGraphicBufferToParcel(long nativeObject, Parcel dest);
nReadGraphicBufferFromParcel(Parcel in)300     private static native long nReadGraphicBufferFromParcel(Parcel in);
nLockCanvas(long nativeObject, Canvas canvas, Rect dirty)301     private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty);
nUnlockCanvasAndPost(long nativeObject, Canvas canvas)302     private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas);
nCreateFromHardwareBuffer(HardwareBuffer buffer)303     private static native GraphicBuffer nCreateFromHardwareBuffer(HardwareBuffer buffer);
304 }
305