blob: 17f07b5a2ad4028bb78643fc98d5a93da1a7cb6b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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.view;
18
Tor Norbyed9273d62013-05-30 15:59:53 -070019import android.annotation.IntDef;
Robert Carrda1d2422019-03-07 15:54:37 -080020import android.annotation.NonNull;
Mathew Inwooda570dee2018-08-17 14:56:00 +010021import android.annotation.UnsupportedAppUsage;
Mitsuru Oshima240f8a72009-07-22 20:39:14 -070022import android.content.res.CompatibilityInfo.Translator;
Jeff Brown0b722fe2012-08-24 22:40:14 -070023import android.graphics.Canvas;
Peiyong Linccc06b62019-06-25 17:31:09 -070024import android.graphics.ColorSpace;
Robert Carra35e5de2017-03-03 17:04:54 -080025import android.graphics.GraphicBuffer;
Jeff Brown0b722fe2012-08-24 22:40:14 -070026import android.graphics.Matrix;
John Reck32f140aa62018-10-04 15:08:24 -070027import android.graphics.RecordingCanvas;
Jeff Brown0b722fe2012-08-24 22:40:14 -070028import android.graphics.Rect;
John Reck32f140aa62018-10-04 15:08:24 -070029import android.graphics.RenderNode;
Jeff Brown0b722fe2012-08-24 22:40:14 -070030import android.graphics.SurfaceTexture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.Parcel;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080032import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.util.Log;
Tor Norbyed9273d62013-05-30 15:59:53 -070034
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070035import dalvik.system.CloseGuard;
36
Tor Norbyed9273d62013-05-30 15:59:53 -070037import java.lang.annotation.Retention;
38import java.lang.annotation.RetentionPolicy;
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040/**
Glenn Kasten334031c2010-11-09 21:54:38 -080041 * Handle onto a raw buffer that is being managed by the screen compositor.
Eino-Ville Talvalac4faf0c2016-09-16 13:34:52 -070042 *
43 * <p>A Surface is generally created by or from a consumer of image buffers (such as a
44 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
45 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
46 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
47 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
48 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
49 * into.</p>
50 *
51 * <p><strong>Note:</strong> A Surface acts like a
52 * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By
53 * itself it will not keep its parent consumer from being reclaimed.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054 */
55public class Surface implements Parcelable {
Jeff Brown64a55af2012-08-26 02:47:39 -070056 private static final String TAG = "Surface";
Mathias Agopianb9230662011-08-03 14:44:48 -070057
Ashok Bhat36bef0b2014-01-20 20:08:01 +000058 private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
Mathias Agopian29479eb2013-02-14 14:36:04 -080059 throws OutOfResourcesException;
Bryce Lee02949f12017-06-16 07:20:34 -070060
Ashok Bhat36bef0b2014-01-20 20:08:01 +000061 private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject);
Robert Carrd5686722019-01-25 14:30:52 -080062 private static native long nativeGetFromSurfaceControl(long surfaceObject,
63 long surfaceControlNativeObject);
Mathias Agopian52800612013-02-14 17:11:20 -080064
Ashok Bhat36bef0b2014-01-20 20:08:01 +000065 private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)
Jeff Brownfc0ebd72013-04-30 16:33:00 -070066 throws OutOfResourcesException;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000067 private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);
Mathias Agopian29479eb2013-02-14 14:36:04 -080068
Mathew Inwooda570dee2018-08-17 14:56:00 +010069 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +000070 private static native void nativeRelease(long nativeObject);
71 private static native boolean nativeIsValid(long nativeObject);
72 private static native boolean nativeIsConsumerRunningBehind(long nativeObject);
73 private static native long nativeReadFromParcel(long nativeObject, Parcel source);
74 private static native void nativeWriteToParcel(long nativeObject, Parcel dest);
Mathias Agopian29479eb2013-02-14 14:36:04 -080075
Dan Stoza5795d642014-06-20 13:01:36 -070076 private static native void nativeAllocateBuffers(long nativeObject);
77
John Reckb35c9602014-11-13 16:15:08 -080078 private static native int nativeGetWidth(long nativeObject);
79 private static native int nativeGetHeight(long nativeObject);
80
Rob Carr64e516f2015-10-29 00:20:45 +000081 private static native long nativeGetNextFrameNumber(long nativeObject);
Robert Carrcd9a18c2015-12-16 18:16:21 -080082 private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
Robert Carr387838b2016-09-07 14:12:44 -070083 private static native int nativeForceScopedDisconnect(long nativeObject);
Peiyong Linccc06b62019-06-25 17:31:09 -070084 private static native int nativeAttachAndQueueBufferWithColorSpace(long nativeObject,
85 GraphicBuffer buffer, int colorSpaceId);
Rob Carr64e516f2015-10-29 00:20:45 +000086
Romain Guy0bbf0b42017-07-20 08:57:07 -070087 private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
88 private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
89
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -070090 public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
Jeff Brown64a55af2012-08-26 02:47:39 -070091 new Parcelable.Creator<Surface>() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -070092 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070093 public Surface createFromParcel(Parcel source) {
94 try {
95 Surface s = new Surface();
96 s.readFromParcel(source);
97 return s;
98 } catch (Exception e) {
99 Log.e(TAG, "Exception creating surface from parcel", e);
100 return null;
101 }
Kevin Hesterb85c9332012-03-08 17:06:56 -0800102 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700103
104 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -0700105 public Surface[] newArray(int size) {
106 return new Surface[size];
107 }
108 };
Kevin Hesterb85c9332012-03-08 17:06:56 -0800109
Jeff Brown64a55af2012-08-26 02:47:39 -0700110 private final CloseGuard mCloseGuard = CloseGuard.get();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700111
112 // Guarded state.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100113 @UnsupportedAppUsage
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700114 final Object mLock = new Object(); // protects the native state
Mathew Inwooda570dee2018-08-17 14:56:00 +0100115 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700116 private String mName;
Mathew Inwooda570dee2018-08-17 14:56:00 +0100117 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000118 long mNativeObject; // package scope only for SurfaceControl access
Mathew Inwooda570dee2018-08-17 14:56:00 +0100119 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000120 private long mLockedObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700121 private int mGenerationId; // incremented each time mNativeObject changes
Jeff Brown64a55af2012-08-26 02:47:39 -0700122 private final Canvas mCanvas = new CompatibleCanvas();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700124 // A matrix to scale the matrix set by application. This is set to null for
125 // non compatibility mode.
126 private Matrix mCompatibleMatrix;
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700127
John Reckbb2d0cc2014-10-21 10:09:36 -0700128 private HwuiContext mHwuiContext;
129
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700130 private boolean mIsSingleBuffered;
Romain Guy0bbf0b42017-07-20 08:57:07 -0700131 private boolean mIsSharedBufferModeEnabled;
132 private boolean mIsAutoRefreshEnabled;
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700133
Tor Norbyed9273d62013-05-30 15:59:53 -0700134 /** @hide */
Robert Carrcd9a18c2015-12-16 18:16:21 -0800135 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700136 @IntDef(prefix = { "SCALING_MODE_" }, value = {
137 SCALING_MODE_FREEZE,
138 SCALING_MODE_SCALE_TO_WINDOW,
139 SCALING_MODE_SCALE_CROP,
140 SCALING_MODE_NO_SCALE_CROP
141 })
Robert Carrcd9a18c2015-12-16 18:16:21 -0800142 public @interface ScalingMode {}
143 // From system/window.h
144 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700145 public static final int SCALING_MODE_FREEZE = 0;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800146 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700147 public static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800148 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700149 public static final int SCALING_MODE_SCALE_CROP = 2;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800150 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700151 public static final int SCALING_MODE_NO_SCALE_CROP = 3;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800152
153 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700154 @IntDef(prefix = { "ROTATION_" }, value = {
155 ROTATION_0,
156 ROTATION_90,
157 ROTATION_180,
158 ROTATION_270
159 })
Tor Norbyed9273d62013-05-30 15:59:53 -0700160 @Retention(RetentionPolicy.SOURCE)
161 public @interface Rotation {}
162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 /**
Mathias Agopian29479eb2013-02-14 14:36:04 -0800164 * Rotation constant: 0 degree rotation (natural orientation)
165 */
166 public static final int ROTATION_0 = 0;
167
168 /**
169 * Rotation constant: 90 degree rotation.
170 */
171 public static final int ROTATION_90 = 1;
172
173 /**
174 * Rotation constant: 180 degree rotation.
175 */
176 public static final int ROTATION_180 = 2;
177
178 /**
179 * Rotation constant: 270 degree rotation.
180 */
181 public static final int ROTATION_270 = 3;
182
Mathias Agopian29479eb2013-02-14 14:36:04 -0800183 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700184 * Create an empty surface, which will later be filled in by readFromParcel().
Mathias Agopianb9230662011-08-03 14:44:48 -0700185 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100187 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 public Surface() {
Jeff Brown64a55af2012-08-26 02:47:39 -0700189 }
190
191 /**
Robert Carr76907ee2019-01-11 13:38:19 -0800192 * Create a Surface assosciated with a given {@link SurfaceControl}. Buffers submitted to this
193 * surface will be displayed by the system compositor according to the parameters
194 * specified by the control. Multiple surfaces may be constructed from one SurfaceControl,
195 * but only one can be connected (e.g. have an active EGL context) at a time.
196 *
197 * @param from The SurfaceControl to assosciate this Surface with
198 */
Robert Carrda1d2422019-03-07 15:54:37 -0800199 public Surface(@NonNull SurfaceControl from) {
Robert Carr76907ee2019-01-11 13:38:19 -0800200 copyFrom(from);
201 }
202
203 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700204 * Create Surface from a {@link SurfaceTexture}.
205 *
206 * Images drawn to the Surface will be made available to the {@link
207 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
208 * SurfaceTexture#updateTexImage}.
209 *
Eino-Ville Talvalaec99efa2017-11-29 15:35:42 -0800210 * Please note that holding onto the Surface created here is not enough to
211 * keep the provided SurfaceTexture from being reclaimed. In that sense,
212 * the Surface will act like a
213 * {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture.
214 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700215 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
216 * Surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700217 * @throws OutOfResourcesException if the surface could not be created.
Jeff Brown64a55af2012-08-26 02:47:39 -0700218 */
219 public Surface(SurfaceTexture surfaceTexture) {
220 if (surfaceTexture == null) {
221 throw new IllegalArgumentException("surfaceTexture must not be null");
222 }
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700223 mIsSingleBuffered = surfaceTexture.isSingleBuffered();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700224 synchronized (mLock) {
225 mName = surfaceTexture.toString();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700226 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Jeff Brown64a55af2012-08-26 02:47:39 -0700227 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700228 }
229
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700230 /* called from android_view_Surface_createFromIGraphicBufferProducer() */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100231 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000232 private Surface(long nativeObject) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700233 synchronized (mLock) {
234 setNativeObjectLocked(nativeObject);
235 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800236 }
237
Jeff Brown64a55af2012-08-26 02:47:39 -0700238 @Override
239 protected void finalize() throws Throwable {
240 try {
241 if (mCloseGuard != null) {
242 mCloseGuard.warnIfOpen();
243 }
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700244 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700245 } finally {
246 super.finalize();
247 }
248 }
249
250 /**
251 * Release the local reference to the server-side surface.
252 * Always call release() when you're done with a Surface.
253 * This will make the surface invalid.
254 */
255 public void release() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700256 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700257 if (mNativeObject != 0) {
258 nativeRelease(mNativeObject);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700259 setNativeObjectLocked(0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700260 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700261 if (mHwuiContext != null) {
262 mHwuiContext.destroy();
263 mHwuiContext = null;
264 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800265 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700266 }
267
268 /**
269 * Free all server-side state associated with this surface and
270 * release this object's reference. This method can only be
271 * called from the process that created the service.
272 * @hide
273 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100274 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700275 public void destroy() {
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700276 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700277 }
278
279 /**
Lucas Dupin41c25ce2018-03-27 09:50:19 -0700280 * Destroys the HwuiContext without completely
281 * releasing the Surface.
282 * @hide
283 */
284 public void hwuiDestroy() {
285 if (mHwuiContext != null) {
286 mHwuiContext.destroy();
287 mHwuiContext = null;
288 }
289 }
290
291 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700292 * Returns true if this object holds a valid surface.
293 *
294 * @return True if it holds a physical surface, so lockCanvas() will succeed.
295 * Otherwise returns false.
296 */
297 public boolean isValid() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700298 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700299 if (mNativeObject == 0) return false;
300 return nativeIsValid(mNativeObject);
301 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700302 }
303
304 /**
305 * Gets the generation number of this surface, incremented each time
306 * the native surface contained within this object changes.
307 *
308 * @return The current generation number.
309 * @hide
310 */
311 public int getGenerationId() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700312 synchronized (mLock) {
313 return mGenerationId;
314 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700315 }
316
317 /**
Rob Carr64e516f2015-10-29 00:20:45 +0000318 * Returns the next frame number which will be dequeued for rendering.
319 * Intended for use with SurfaceFlinger's deferred transactions API.
320 *
321 * @hide
322 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100323 @UnsupportedAppUsage
Rob Carr64e516f2015-10-29 00:20:45 +0000324 public long getNextFrameNumber() {
325 synchronized (mLock) {
Jorim Jaggi388090f2018-01-22 17:03:59 +0100326 checkNotReleasedLocked();
Rob Carr64e516f2015-10-29 00:20:45 +0000327 return nativeGetNextFrameNumber(mNativeObject);
328 }
329 }
330
331 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700332 * Returns true if the consumer of this Surface is running behind the producer.
333 *
334 * @return True if the consumer is more than one buffer ahead of the producer.
335 * @hide
336 */
337 public boolean isConsumerRunningBehind() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700338 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700339 checkNotReleasedLocked();
340 return nativeIsConsumerRunningBehind(mNativeObject);
341 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700342 }
343
344 /**
345 * Gets a {@link Canvas} for drawing into this surface.
346 *
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700347 * After drawing into the provided {@link Canvas}, the caller must
Jeff Brown64a55af2012-08-26 02:47:39 -0700348 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
349 *
Mathias Agopian30d7ab92013-02-14 15:38:40 -0800350 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
Jeff Brown64a55af2012-08-26 02:47:39 -0700351 * to redraw. This function may choose to expand the dirty rectangle if for example
352 * the surface has been resized or if the previous contents of the surface were
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700353 * not available. The caller must redraw the entire dirty region as represented
354 * by the contents of the inOutDirty rectangle upon return from this function.
Jeff Brown64a55af2012-08-26 02:47:39 -0700355 * The caller may also pass <code>null</code> instead, in the case where the
356 * entire surface should be redrawn.
357 * @return A canvas for drawing into the surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700358 *
359 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
360 * @throws OutOfResourcesException If the canvas cannot be locked.
Jeff Brown64a55af2012-08-26 02:47:39 -0700361 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800362 public Canvas lockCanvas(Rect inOutDirty)
Igor Murashkina86ab6402013-08-30 12:58:36 -0700363 throws Surface.OutOfResourcesException, IllegalArgumentException {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700364 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700365 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700366 if (mLockedObject != 0) {
367 // Ideally, nativeLockCanvas() would throw in this situation and prevent the
368 // double-lock, but that won't happen if mNativeObject was updated. We can't
369 // abandon the old mLockedObject because it might still be in use, so instead
370 // we just refuse to re-lock the Surface.
Jesse Halld7e55962014-10-13 11:01:15 -0700371 throw new IllegalArgumentException("Surface was already locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700372 }
373 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700374 return mCanvas;
Mathias Agopian7c116b52013-03-18 20:27:02 -0700375 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700376 }
377
378 /**
379 * Posts the new contents of the {@link Canvas} to the surface and
380 * releases the {@link Canvas}.
381 *
382 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
383 */
384 public void unlockCanvasAndPost(Canvas canvas) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700385 synchronized (mLock) {
386 checkNotReleasedLocked();
387
388 if (mHwuiContext != null) {
389 mHwuiContext.unlockAndPost(canvas);
390 } else {
391 unlockSwCanvasAndPost(canvas);
392 }
393 }
394 }
395
396 private void unlockSwCanvasAndPost(Canvas canvas) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700397 if (canvas != mCanvas) {
398 throw new IllegalArgumentException("canvas object must be the same instance that "
399 + "was previously returned by lockCanvas");
400 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700401 if (mNativeObject != mLockedObject) {
402 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
403 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
404 Long.toHexString(mLockedObject) +")");
405 }
406 if (mLockedObject == 0) {
407 throw new IllegalStateException("Surface was not locked");
408 }
409 try {
410 nativeUnlockCanvasAndPost(mLockedObject, canvas);
411 } finally {
412 nativeRelease(mLockedObject);
413 mLockedObject = 0;
414 }
415 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700416
John Reckbb2d0cc2014-10-21 10:09:36 -0700417 /**
418 * Gets a {@link Canvas} for drawing into this surface.
419 *
420 * After drawing into the provided {@link Canvas}, the caller must
421 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
422 *
423 * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated
424 * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
425 * unsupported drawing operations</a> for a list of what is and isn't
John Reck43a53282014-10-23 13:56:03 -0700426 * supported in a hardware-accelerated canvas. It is also required to
427 * fully cover the surface every time {@link #lockHardwareCanvas()} is
428 * called as the buffer is not preserved between frames. Partial updates
429 * are not supported.
John Reckbb2d0cc2014-10-21 10:09:36 -0700430 *
431 * @return A canvas for drawing into the surface.
432 *
433 * @throws IllegalStateException If the canvas cannot be locked.
434 */
435 public Canvas lockHardwareCanvas() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700436 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700437 checkNotReleasedLocked();
John Reckbb2d0cc2014-10-21 10:09:36 -0700438 if (mHwuiContext == null) {
Peiyong Lind8b68712018-03-06 18:34:21 -0800439 mHwuiContext = new HwuiContext(false);
440 }
441 return mHwuiContext.lockCanvas(
442 nativeGetWidth(mNativeObject),
443 nativeGetHeight(mNativeObject));
444 }
445 }
446
447 /**
448 * Gets a {@link Canvas} for drawing into this surface that supports wide color gamut.
449 *
450 * After drawing into the provided {@link Canvas}, the caller must
451 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
452 *
453 * Unlike {@link #lockCanvas(Rect)} and {@link #lockHardwareCanvas()},
454 * this will return a hardware-accelerated canvas that supports wide color gamut.
455 * See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
456 * unsupported drawing operations</a> for a list of what is and isn't
457 * supported in a hardware-accelerated canvas. It is also required to
458 * fully cover the surface every time {@link #lockHardwareCanvas()} is
459 * called as the buffer is not preserved between frames. Partial updates
460 * are not supported.
461 *
462 * @return A canvas for drawing into the surface.
463 *
464 * @throws IllegalStateException If the canvas cannot be locked.
465 *
466 * @hide
467 */
468 public Canvas lockHardwareWideColorGamutCanvas() {
469 synchronized (mLock) {
470 checkNotReleasedLocked();
471 if (mHwuiContext != null && !mHwuiContext.isWideColorGamut()) {
472 mHwuiContext.destroy();
473 mHwuiContext = null;
474 }
475 if (mHwuiContext == null) {
476 mHwuiContext = new HwuiContext(true);
Andy McFaddened55c8d2013-08-20 10:05:51 -0700477 }
John Reckb35c9602014-11-13 16:15:08 -0800478 return mHwuiContext.lockCanvas(
479 nativeGetWidth(mNativeObject),
480 nativeGetHeight(mNativeObject));
Mathias Agopian7c116b52013-03-18 20:27:02 -0700481 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700482 }
483
Andy McFaddened55c8d2013-08-20 10:05:51 -0700484 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700485 * @deprecated This API has been removed and is not supported. Do not use.
486 */
487 @Deprecated
488 public void unlockCanvas(Canvas canvas) {
489 throw new UnsupportedOperationException();
490 }
491
492 /**
493 * Sets the translator used to scale canvas's width/height in compatibility
494 * mode.
495 */
496 void setCompatibilityTranslator(Translator translator) {
497 if (translator != null) {
498 float appScale = translator.applicationScale;
499 mCompatibleMatrix = new Matrix();
500 mCompatibleMatrix.setScale(appScale, appScale);
501 }
502 }
503
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700504 /**
Mathias Agopianb9230662011-08-03 14:44:48 -0700505 * Copy another surface to this one. This surface now holds a reference
506 * to the same data as the original surface, and is -not- the owner.
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800507 * This is for use by the window manager when returning a window surface
508 * back from a client, converting it from the representation being managed
509 * by the window manager to the representation the client uses to draw
510 * in to it.
Bryce Lee02949f12017-06-16 07:20:34 -0700511 *
512 * @param other {@link SurfaceControl} to copy from.
Mathias Agopianb9230662011-08-03 14:44:48 -0700513 * @hide
514 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100515 @UnsupportedAppUsage
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800516 public void copyFrom(SurfaceControl other) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700517 if (other == null) {
518 throw new IllegalArgumentException("other must not be null");
519 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700520
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000521 long surfaceControlPtr = other.mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700522 if (surfaceControlPtr == 0) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800523 throw new NullPointerException(
Bryce Lee02949f12017-06-16 07:20:34 -0700524 "null SurfaceControl native object. Are you using a released SurfaceControl?");
525 }
Robert Carrd5686722019-01-25 14:30:52 -0800526 long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
Bryce Lee02949f12017-06-16 07:20:34 -0700527
528 synchronized (mLock) {
Robert Carrd5686722019-01-25 14:30:52 -0800529 if (newNativeObject == mNativeObject) {
530 return;
531 }
Bryce Lee02949f12017-06-16 07:20:34 -0700532 if (mNativeObject != 0) {
533 nativeRelease(mNativeObject);
534 }
535 setNativeObjectLocked(newNativeObject);
536 }
537 }
538
539 /**
540 * Gets a reference a surface created from this one. This surface now holds a reference
541 * to the same data as the original surface, and is -not- the owner.
542 * This is for use by the window manager when returning a window surface
543 * back from a client, converting it from the representation being managed
544 * by the window manager to the representation the client uses to draw
545 * in to it.
546 *
547 * @param other {@link SurfaceControl} to create surface from.
548 *
549 * @hide
550 */
551 public void createFrom(SurfaceControl other) {
552 if (other == null) {
553 throw new IllegalArgumentException("other must not be null");
554 }
555
556 long surfaceControlPtr = other.mNativeObject;
557 if (surfaceControlPtr == 0) {
558 throw new NullPointerException(
559 "null SurfaceControl native object. Are you using a released SurfaceControl?");
Jeff Brown64a55af2012-08-26 02:47:39 -0700560 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000561 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700562
563 synchronized (mLock) {
564 if (mNativeObject != 0) {
565 nativeRelease(mNativeObject);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700566 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700567 setNativeObjectLocked(newNativeObject);
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700568 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700569 }
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800570
571 /**
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700572 * This is intended to be used by {@link SurfaceView#updateWindow} only.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700573 * @param other access is not thread safe
574 * @hide
575 * @deprecated
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800576 */
Mathias Agopian7c116b52013-03-18 20:27:02 -0700577 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +0100578 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700579 public void transferFrom(Surface other) {
580 if (other == null) {
581 throw new IllegalArgumentException("other must not be null");
582 }
583 if (other != this) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000584 final long newPtr;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700585 synchronized (other.mLock) {
586 newPtr = other.mNativeObject;
587 other.setNativeObjectLocked(0);
588 }
589
590 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700591 if (mNativeObject != 0) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700592 nativeRelease(mNativeObject);
593 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700594 setNativeObjectLocked(newPtr);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800595 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700596 }
Mathias Agopianb9230662011-08-03 14:44:48 -0700597 }
598
Jeff Brown64a55af2012-08-26 02:47:39 -0700599 @Override
600 public int describeContents() {
601 return 0;
602 }
603
604 public void readFromParcel(Parcel source) {
605 if (source == null) {
606 throw new IllegalArgumentException("source must not be null");
607 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700608
609 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700610 // nativeReadFromParcel() will either return mNativeObject, or
611 // create a new native Surface and return it after reducing
612 // the reference count on mNativeObject. Either way, it is
613 // not necessary to call nativeRelease() here.
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700614 // NOTE: This must be kept synchronized with the native parceling code
615 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700616 mName = source.readString();
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700617 mIsSingleBuffered = source.readInt() != 0;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700618 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700619 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700620 }
621
622 @Override
623 public void writeToParcel(Parcel dest, int flags) {
624 if (dest == null) {
625 throw new IllegalArgumentException("dest must not be null");
626 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700627 synchronized (mLock) {
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700628 // NOTE: This must be kept synchronized with the native parceling code
629 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700630 dest.writeString(mName);
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700631 dest.writeInt(mIsSingleBuffered ? 1 : 0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700632 nativeWriteToParcel(mNativeObject, dest);
633 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700634 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
635 release();
636 }
637 }
638
639 @Override
640 public String toString() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700641 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700642 return "Surface(name=" + mName + ")/@0x" +
643 Integer.toHexString(System.identityHashCode(this));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700644 }
645 }
646
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000647 private void setNativeObjectLocked(long ptr) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700648 if (mNativeObject != ptr) {
649 if (mNativeObject == 0 && ptr != 0) {
650 mCloseGuard.open("release");
651 } else if (mNativeObject != 0 && ptr == 0) {
652 mCloseGuard.close();
653 }
654 mNativeObject = ptr;
655 mGenerationId += 1;
John Reckbb2d0cc2014-10-21 10:09:36 -0700656 if (mHwuiContext != null) {
657 mHwuiContext.updateSurface();
658 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700659 }
660 }
661
662 private void checkNotReleasedLocked() {
663 if (mNativeObject == 0) {
664 throw new IllegalStateException("Surface has already been released.");
665 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700666 }
667
Mathias Agopianc14bacf2012-04-23 18:23:08 -0700668 /**
Dan Stoza5795d642014-06-20 13:01:36 -0700669 * Allocate buffers ahead of time to avoid allocation delays during rendering
670 * @hide
671 */
672 public void allocateBuffers() {
673 synchronized (mLock) {
674 checkNotReleasedLocked();
675 nativeAllocateBuffers(mNativeObject);
676 }
677 }
678
679 /**
Robert Carrcd9a18c2015-12-16 18:16:21 -0800680 * Set the scaling mode to be used for this surfaces buffers
681 * @hide
682 */
683 void setScalingMode(@ScalingMode int scalingMode) {
684 synchronized (mLock) {
685 checkNotReleasedLocked();
686 int err = nativeSetScalingMode(mNativeObject, scalingMode);
687 if (err != 0) {
688 throw new IllegalArgumentException("Invalid scaling mode: " + scalingMode);
689 }
690 }
691 }
692
Robert Carr387838b2016-09-07 14:12:44 -0700693 void forceScopedDisconnect() {
694 synchronized (mLock) {
695 checkNotReleasedLocked();
696 int err = nativeForceScopedDisconnect(mNativeObject);
697 if (err != 0) {
698 throw new RuntimeException("Failed to disconnect Surface instance (bad object?)");
699 }
700 }
701 }
702
Robert Carrcd9a18c2015-12-16 18:16:21 -0800703 /**
Peiyong Linccc06b62019-06-25 17:31:09 -0700704 * Transfer ownership of buffer with a color space and present it on the Surface.
705 * The supported color spaces are SRGB and Display P3, other color spaces will be
706 * treated as SRGB.
707 * @hide
708 */
709 public void attachAndQueueBufferWithColorSpace(GraphicBuffer buffer, ColorSpace colorSpace) {
710 synchronized (mLock) {
711 checkNotReleasedLocked();
712 if (colorSpace == null) {
713 colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
714 }
715 int err = nativeAttachAndQueueBufferWithColorSpace(mNativeObject, buffer,
716 colorSpace.getId());
717 if (err != 0) {
718 throw new RuntimeException(
719 "Failed to attach and queue buffer to Surface (bad object?), "
720 + "native error: " + err);
721 }
722 }
723 }
724
725 /**
726 * Deprecated, use attachAndQueueBufferWithColorSpace instead.
Robert Carra35e5de2017-03-03 17:04:54 -0800727 * Transfer ownership of buffer and present it on the Surface.
Peiyong Linccc06b62019-06-25 17:31:09 -0700728 * The color space of the buffer is treated as SRGB.
Robert Carra35e5de2017-03-03 17:04:54 -0800729 * @hide
730 */
731 public void attachAndQueueBuffer(GraphicBuffer buffer) {
Peiyong Linccc06b62019-06-25 17:31:09 -0700732 attachAndQueueBufferWithColorSpace(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
Robert Carra35e5de2017-03-03 17:04:54 -0800733 }
734
735 /**
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700736 * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
737 * @hide
738 */
739 public boolean isSingleBuffered() {
740 return mIsSingleBuffered;
741 }
742
743 /**
Romain Guy0bbf0b42017-07-20 08:57:07 -0700744 * <p>The shared buffer mode allows both the application and the surface compositor
745 * (SurfaceFlinger) to concurrently access this surface's buffer. While the
746 * application is still required to issue a present request
747 * (see {@link #unlockCanvasAndPost(Canvas)}) to the compositor when an update is required,
748 * the compositor may trigger an update at any time. Since the surface's buffer is shared
749 * between the application and the compositor, updates triggered by the compositor may
750 * cause visible tearing.</p>
751 *
752 * <p>The shared buffer mode can be used with
753 * {@link #setAutoRefreshEnabled(boolean) auto-refresh} to avoid the overhead of
754 * issuing present requests.</p>
755 *
756 * <p>If the application uses the shared buffer mode to reduce latency, it is
757 * recommended to use software rendering (see {@link #lockCanvas(Rect)} to ensure
758 * the graphics workloads are not affected by other applications and/or the system
759 * using the GPU. When using software rendering, the application should update the
760 * smallest possible region of the surface required.</p>
761 *
762 * <p class="note">The shared buffer mode might not be supported by the underlying
763 * hardware. Enabling shared buffer mode on hardware that does not support it will
764 * not yield an error but the application will not benefit from lower latency (and
765 * tearing will not be visible).</p>
766 *
767 * <p class="note">Depending on how many and what kind of surfaces are visible, the
768 * surface compositor may need to copy the shared buffer before it is displayed. When
769 * this happens, the latency benefits of shared buffer mode will be reduced.</p>
770 *
771 * @param enabled True to enable the shared buffer mode on this surface, false otherwise
772 *
773 * @see #isSharedBufferModeEnabled()
774 * @see #setAutoRefreshEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700775 *
776 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700777 */
778 public void setSharedBufferModeEnabled(boolean enabled) {
779 if (mIsSharedBufferModeEnabled != enabled) {
780 int error = nativeSetSharedBufferModeEnabled(mNativeObject, enabled);
781 if (error != 0) {
782 throw new RuntimeException(
783 "Failed to set shared buffer mode on Surface (bad object?)");
784 } else {
785 mIsSharedBufferModeEnabled = enabled;
786 }
787 }
788 }
789
790 /**
791 * @return True if shared buffer mode is enabled on this surface, false otherwise
792 *
793 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700794 *
795 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700796 */
797 public boolean isSharedBufferModeEnabled() {
798 return mIsSharedBufferModeEnabled;
799 }
800
801 /**
802 * <p>When auto-refresh is enabled, the surface compositor (SurfaceFlinger)
803 * automatically updates the display on a regular refresh cycle. The application
804 * can continue to issue present requests but it is not required. Enabling
805 * auto-refresh may result in visible tearing.</p>
806 *
807 * <p>Auto-refresh has no effect if the {@link #setSharedBufferModeEnabled(boolean)
808 * shared buffer mode} is not enabled.</p>
809 *
810 * <p>Because auto-refresh will trigger continuous updates of the display, it is
811 * recommended to turn it on only when necessary. For example, in a drawing/painting
812 * application auto-refresh should be enabled on finger/pen down and disabled on
813 * finger/pen up.</p>
814 *
815 * @param enabled True to enable auto-refresh on this surface, false otherwise
816 *
817 * @see #isAutoRefreshEnabled()
818 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700819 *
820 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700821 */
822 public void setAutoRefreshEnabled(boolean enabled) {
823 if (mIsAutoRefreshEnabled != enabled) {
824 int error = nativeSetAutoRefreshEnabled(mNativeObject, enabled);
825 if (error != 0) {
826 throw new RuntimeException("Failed to set auto refresh on Surface (bad object?)");
827 } else {
828 mIsAutoRefreshEnabled = enabled;
829 }
830 }
831 }
832
833 /**
834 * @return True if auto-refresh is enabled on this surface, false otherwise
Romain Guy010f0822017-08-16 09:43:07 -0700835 *
836 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700837 */
838 public boolean isAutoRefreshEnabled() {
839 return mIsAutoRefreshEnabled;
840 }
841
842 /**
Igor Murashkina86ab6402013-08-30 12:58:36 -0700843 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
844 * when a SurfaceTexture could not successfully be allocated.
Jeff Brown64a55af2012-08-26 02:47:39 -0700845 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700846 @SuppressWarnings("serial")
847 public static class OutOfResourcesException extends RuntimeException {
Jeff Brown64a55af2012-08-26 02:47:39 -0700848 public OutOfResourcesException() {
849 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700850 public OutOfResourcesException(String name) {
851 super(name);
852 }
853 }
854
855 /**
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700856 * Returns a human readable representation of a rotation.
857 *
858 * @param rotation The rotation.
859 * @return The rotation symbolic name.
Svetoslav Ganov545252f2012-12-10 18:29:24 -0800860 *
861 * @hide
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700862 */
863 public static String rotationToString(int rotation) {
864 switch (rotation) {
865 case Surface.ROTATION_0: {
866 return "ROTATION_0";
867 }
868 case Surface.ROTATION_90: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700869 return "ROTATION_90";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700870 }
871 case Surface.ROTATION_180: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700872 return "ROTATION_180";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700873 }
874 case Surface.ROTATION_270: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700875 return "ROTATION_270";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700876 }
877 default: {
Michael Wright19859762017-09-18 20:57:58 +0100878 return Integer.toString(rotation);
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700879 }
880 }
881 }
882
883 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700884 * A Canvas class that can handle the compatibility mode.
885 * This does two things differently.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700886 * <ul>
Mathias Agopianb9230662011-08-03 14:44:48 -0700887 * <li>Returns the width and height of the target metrics, rather than
888 * native. For example, the canvas returns 320x480 even if an app is running
889 * in WVGA high density.
890 * <li>Scales the matrix in setMatrix by the application scale, except if
891 * the matrix looks like obtained from getMatrix. This is a hack to handle
892 * the case that an application uses getMatrix to keep the original matrix,
893 * set matrix of its own, then set the original matrix back. There is no
894 * perfect solution that works for all cases, and there are a lot of cases
895 * that this model does not work, but we hope this works for many apps.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700896 * </ul>
897 */
Jeff Brown64a55af2012-08-26 02:47:39 -0700898 private final class CompatibleCanvas extends Canvas {
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700899 // A temp matrix to remember what an application obtained via {@link getMatrix}
900 private Matrix mOrigMatrix = null;
901
902 @Override
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700903 public void setMatrix(Matrix matrix) {
904 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
905 // don't scale the matrix if it's not compatibility mode, or
906 // the matrix was obtained from getMatrix.
907 super.setMatrix(matrix);
908 } else {
909 Matrix m = new Matrix(mCompatibleMatrix);
910 m.preConcat(matrix);
911 super.setMatrix(m);
912 }
913 }
914
Romain Guy8b5aa482013-02-28 18:13:54 -0800915 @SuppressWarnings("deprecation")
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700916 @Override
917 public void getMatrix(Matrix m) {
918 super.getMatrix(m);
919 if (mOrigMatrix == null) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700920 mOrigMatrix = new Matrix();
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700921 }
922 mOrigMatrix.set(m);
923 }
Romain Guyd10cd572010-10-10 13:33:22 -0700924 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700925
926 private final class HwuiContext {
927 private final RenderNode mRenderNode;
928 private long mHwuiRenderer;
John Reck32f140aa62018-10-04 15:08:24 -0700929 private RecordingCanvas mCanvas;
Peiyong Lind8b68712018-03-06 18:34:21 -0800930 private final boolean mIsWideColorGamut;
John Reckbb2d0cc2014-10-21 10:09:36 -0700931
Peiyong Lind8b68712018-03-06 18:34:21 -0800932 HwuiContext(boolean isWideColorGamut) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700933 mRenderNode = RenderNode.create("HwuiCanvas", null);
934 mRenderNode.setClipToBounds(false);
John Recka2d20b42018-10-01 12:21:55 -0700935 mRenderNode.setForceDarkAllowed(false);
Peiyong Lind8b68712018-03-06 18:34:21 -0800936 mIsWideColorGamut = isWideColorGamut;
937 mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject,
938 isWideColorGamut);
John Reckbb2d0cc2014-10-21 10:09:36 -0700939 }
940
John Reckb35c9602014-11-13 16:15:08 -0800941 Canvas lockCanvas(int width, int height) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700942 if (mCanvas != null) {
943 throw new IllegalStateException("Surface was already locked!");
944 }
John Recke57475e2019-02-20 17:39:52 -0800945 mCanvas = mRenderNode.beginRecording(width, height);
John Reckbb2d0cc2014-10-21 10:09:36 -0700946 return mCanvas;
947 }
948
949 void unlockAndPost(Canvas canvas) {
950 if (canvas != mCanvas) {
951 throw new IllegalArgumentException("canvas object must be the same instance that "
952 + "was previously returned by lockCanvas");
953 }
John Recke57475e2019-02-20 17:39:52 -0800954 mRenderNode.endRecording();
John Reckbb2d0cc2014-10-21 10:09:36 -0700955 mCanvas = null;
956 nHwuiDraw(mHwuiRenderer);
957 }
958
959 void updateSurface() {
960 nHwuiSetSurface(mHwuiRenderer, mNativeObject);
961 }
962
963 void destroy() {
964 if (mHwuiRenderer != 0) {
965 nHwuiDestroy(mHwuiRenderer);
966 mHwuiRenderer = 0;
967 }
968 }
Peiyong Lind8b68712018-03-06 18:34:21 -0800969
970 boolean isWideColorGamut() {
971 return mIsWideColorGamut;
972 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700973 }
974
Peiyong Lind8b68712018-03-06 18:34:21 -0800975 private static native long nHwuiCreate(long rootNode, long surface, boolean isWideColorGamut);
John Reckbb2d0cc2014-10-21 10:09:36 -0700976 private static native void nHwuiSetSurface(long renderer, long surface);
977 private static native void nHwuiDraw(long renderer);
978 private static native void nHwuiDestroy(long renderer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979}