blob: 6ff699e54dd1b74eebd2befef1ce7ce3e3129ce2 [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;
Mathew Inwooda570dee2018-08-17 14:56:00 +010020import android.annotation.UnsupportedAppUsage;
Mitsuru Oshima240f8a72009-07-22 20:39:14 -070021import android.content.res.CompatibilityInfo.Translator;
Jeff Brown0b722fe2012-08-24 22:40:14 -070022import android.graphics.Canvas;
Robert Carra35e5de2017-03-03 17:04:54 -080023import android.graphics.GraphicBuffer;
Jeff Brown0b722fe2012-08-24 22:40:14 -070024import android.graphics.Matrix;
John Reck32f140aa62018-10-04 15:08:24 -070025import android.graphics.RecordingCanvas;
Jeff Brown0b722fe2012-08-24 22:40:14 -070026import android.graphics.Rect;
John Reck32f140aa62018-10-04 15:08:24 -070027import android.graphics.RenderNode;
Jeff Brown0b722fe2012-08-24 22:40:14 -070028import android.graphics.SurfaceTexture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.Parcel;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080030import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.util.Log;
Tor Norbyed9273d62013-05-30 15:59:53 -070032
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070033import dalvik.system.CloseGuard;
34
Tor Norbyed9273d62013-05-30 15:59:53 -070035import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
37
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038/**
Glenn Kasten334031c2010-11-09 21:54:38 -080039 * Handle onto a raw buffer that is being managed by the screen compositor.
Eino-Ville Talvalac4faf0c2016-09-16 13:34:52 -070040 *
41 * <p>A Surface is generally created by or from a consumer of image buffers (such as a
42 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
43 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
44 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
45 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
46 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
47 * into.</p>
48 *
49 * <p><strong>Note:</strong> A Surface acts like a
50 * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By
51 * itself it will not keep its parent consumer from being reclaimed.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 */
53public class Surface implements Parcelable {
Jeff Brown64a55af2012-08-26 02:47:39 -070054 private static final String TAG = "Surface";
Mathias Agopianb9230662011-08-03 14:44:48 -070055
Ashok Bhat36bef0b2014-01-20 20:08:01 +000056 private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
Mathias Agopian29479eb2013-02-14 14:36:04 -080057 throws OutOfResourcesException;
Bryce Lee02949f12017-06-16 07:20:34 -070058
Ashok Bhat36bef0b2014-01-20 20:08:01 +000059 private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject);
Robert Carrd5686722019-01-25 14:30:52 -080060 private static native long nativeGetFromSurfaceControl(long surfaceObject,
61 long surfaceControlNativeObject);
Mathias Agopian52800612013-02-14 17:11:20 -080062
Ashok Bhat36bef0b2014-01-20 20:08:01 +000063 private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)
Jeff Brownfc0ebd72013-04-30 16:33:00 -070064 throws OutOfResourcesException;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000065 private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);
Mathias Agopian29479eb2013-02-14 14:36:04 -080066
Mathew Inwooda570dee2018-08-17 14:56:00 +010067 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +000068 private static native void nativeRelease(long nativeObject);
69 private static native boolean nativeIsValid(long nativeObject);
70 private static native boolean nativeIsConsumerRunningBehind(long nativeObject);
71 private static native long nativeReadFromParcel(long nativeObject, Parcel source);
72 private static native void nativeWriteToParcel(long nativeObject, Parcel dest);
Mathias Agopian29479eb2013-02-14 14:36:04 -080073
Dan Stoza5795d642014-06-20 13:01:36 -070074 private static native void nativeAllocateBuffers(long nativeObject);
75
John Reckb35c9602014-11-13 16:15:08 -080076 private static native int nativeGetWidth(long nativeObject);
77 private static native int nativeGetHeight(long nativeObject);
78
Rob Carr64e516f2015-10-29 00:20:45 +000079 private static native long nativeGetNextFrameNumber(long nativeObject);
Robert Carrcd9a18c2015-12-16 18:16:21 -080080 private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
Robert Carr387838b2016-09-07 14:12:44 -070081 private static native int nativeForceScopedDisconnect(long nativeObject);
Robert Carra35e5de2017-03-03 17:04:54 -080082 private static native int nativeAttachAndQueueBuffer(long nativeObject, GraphicBuffer buffer);
Rob Carr64e516f2015-10-29 00:20:45 +000083
Romain Guy0bbf0b42017-07-20 08:57:07 -070084 private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
85 private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
86
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -070087 public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
Jeff Brown64a55af2012-08-26 02:47:39 -070088 new Parcelable.Creator<Surface>() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -070089 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070090 public Surface createFromParcel(Parcel source) {
91 try {
92 Surface s = new Surface();
93 s.readFromParcel(source);
94 return s;
95 } catch (Exception e) {
96 Log.e(TAG, "Exception creating surface from parcel", e);
97 return null;
98 }
Kevin Hesterb85c9332012-03-08 17:06:56 -080099 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700100
101 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -0700102 public Surface[] newArray(int size) {
103 return new Surface[size];
104 }
105 };
Kevin Hesterb85c9332012-03-08 17:06:56 -0800106
Jeff Brown64a55af2012-08-26 02:47:39 -0700107 private final CloseGuard mCloseGuard = CloseGuard.get();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700108
109 // Guarded state.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100110 @UnsupportedAppUsage
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700111 final Object mLock = new Object(); // protects the native state
Mathew Inwooda570dee2018-08-17 14:56:00 +0100112 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700113 private String mName;
Mathew Inwooda570dee2018-08-17 14:56:00 +0100114 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000115 long mNativeObject; // package scope only for SurfaceControl access
Mathew Inwooda570dee2018-08-17 14:56:00 +0100116 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000117 private long mLockedObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700118 private int mGenerationId; // incremented each time mNativeObject changes
Jeff Brown64a55af2012-08-26 02:47:39 -0700119 private final Canvas mCanvas = new CompatibleCanvas();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700121 // A matrix to scale the matrix set by application. This is set to null for
122 // non compatibility mode.
123 private Matrix mCompatibleMatrix;
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700124
John Reckbb2d0cc2014-10-21 10:09:36 -0700125 private HwuiContext mHwuiContext;
126
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700127 private boolean mIsSingleBuffered;
Romain Guy0bbf0b42017-07-20 08:57:07 -0700128 private boolean mIsSharedBufferModeEnabled;
129 private boolean mIsAutoRefreshEnabled;
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700130
Tor Norbyed9273d62013-05-30 15:59:53 -0700131 /** @hide */
Robert Carrcd9a18c2015-12-16 18:16:21 -0800132 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700133 @IntDef(prefix = { "SCALING_MODE_" }, value = {
134 SCALING_MODE_FREEZE,
135 SCALING_MODE_SCALE_TO_WINDOW,
136 SCALING_MODE_SCALE_CROP,
137 SCALING_MODE_NO_SCALE_CROP
138 })
Robert Carrcd9a18c2015-12-16 18:16:21 -0800139 public @interface ScalingMode {}
140 // From system/window.h
141 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700142 public static final int SCALING_MODE_FREEZE = 0;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800143 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700144 public static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800145 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700146 public static final int SCALING_MODE_SCALE_CROP = 2;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800147 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700148 public static final int SCALING_MODE_NO_SCALE_CROP = 3;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800149
150 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700151 @IntDef(prefix = { "ROTATION_" }, value = {
152 ROTATION_0,
153 ROTATION_90,
154 ROTATION_180,
155 ROTATION_270
156 })
Tor Norbyed9273d62013-05-30 15:59:53 -0700157 @Retention(RetentionPolicy.SOURCE)
158 public @interface Rotation {}
159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 /**
Mathias Agopian29479eb2013-02-14 14:36:04 -0800161 * Rotation constant: 0 degree rotation (natural orientation)
162 */
163 public static final int ROTATION_0 = 0;
164
165 /**
166 * Rotation constant: 90 degree rotation.
167 */
168 public static final int ROTATION_90 = 1;
169
170 /**
171 * Rotation constant: 180 degree rotation.
172 */
173 public static final int ROTATION_180 = 2;
174
175 /**
176 * Rotation constant: 270 degree rotation.
177 */
178 public static final int ROTATION_270 = 3;
179
Mathias Agopian29479eb2013-02-14 14:36:04 -0800180 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700181 * Create an empty surface, which will later be filled in by readFromParcel().
Mathias Agopianb9230662011-08-03 14:44:48 -0700182 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100184 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 public Surface() {
Jeff Brown64a55af2012-08-26 02:47:39 -0700186 }
187
188 /**
Robert Carr76907ee2019-01-11 13:38:19 -0800189 * Create a Surface assosciated with a given {@link SurfaceControl}. Buffers submitted to this
190 * surface will be displayed by the system compositor according to the parameters
191 * specified by the control. Multiple surfaces may be constructed from one SurfaceControl,
192 * but only one can be connected (e.g. have an active EGL context) at a time.
193 *
194 * @param from The SurfaceControl to assosciate this Surface with
195 */
196 public Surface(SurfaceControl from) {
197 copyFrom(from);
198 }
199
200 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700201 * Create Surface from a {@link SurfaceTexture}.
202 *
203 * Images drawn to the Surface will be made available to the {@link
204 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
205 * SurfaceTexture#updateTexImage}.
206 *
Eino-Ville Talvalaec99efa2017-11-29 15:35:42 -0800207 * Please note that holding onto the Surface created here is not enough to
208 * keep the provided SurfaceTexture from being reclaimed. In that sense,
209 * the Surface will act like a
210 * {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture.
211 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700212 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
213 * Surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700214 * @throws OutOfResourcesException if the surface could not be created.
Jeff Brown64a55af2012-08-26 02:47:39 -0700215 */
216 public Surface(SurfaceTexture surfaceTexture) {
217 if (surfaceTexture == null) {
218 throw new IllegalArgumentException("surfaceTexture must not be null");
219 }
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700220 mIsSingleBuffered = surfaceTexture.isSingleBuffered();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700221 synchronized (mLock) {
222 mName = surfaceTexture.toString();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700223 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Jeff Brown64a55af2012-08-26 02:47:39 -0700224 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700225 }
226
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700227 /* called from android_view_Surface_createFromIGraphicBufferProducer() */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100228 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000229 private Surface(long nativeObject) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700230 synchronized (mLock) {
231 setNativeObjectLocked(nativeObject);
232 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800233 }
234
Jeff Brown64a55af2012-08-26 02:47:39 -0700235 @Override
236 protected void finalize() throws Throwable {
237 try {
238 if (mCloseGuard != null) {
239 mCloseGuard.warnIfOpen();
240 }
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700241 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700242 } finally {
243 super.finalize();
244 }
245 }
246
247 /**
248 * Release the local reference to the server-side surface.
249 * Always call release() when you're done with a Surface.
250 * This will make the surface invalid.
251 */
252 public void release() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700253 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700254 if (mNativeObject != 0) {
255 nativeRelease(mNativeObject);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700256 setNativeObjectLocked(0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700257 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700258 if (mHwuiContext != null) {
259 mHwuiContext.destroy();
260 mHwuiContext = null;
261 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800262 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700263 }
264
265 /**
266 * Free all server-side state associated with this surface and
267 * release this object's reference. This method can only be
268 * called from the process that created the service.
269 * @hide
270 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100271 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700272 public void destroy() {
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700273 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700274 }
275
276 /**
Lucas Dupin41c25ce2018-03-27 09:50:19 -0700277 * Destroys the HwuiContext without completely
278 * releasing the Surface.
279 * @hide
280 */
281 public void hwuiDestroy() {
282 if (mHwuiContext != null) {
283 mHwuiContext.destroy();
284 mHwuiContext = null;
285 }
286 }
287
288 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700289 * Returns true if this object holds a valid surface.
290 *
291 * @return True if it holds a physical surface, so lockCanvas() will succeed.
292 * Otherwise returns false.
293 */
294 public boolean isValid() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700295 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700296 if (mNativeObject == 0) return false;
297 return nativeIsValid(mNativeObject);
298 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700299 }
300
301 /**
302 * Gets the generation number of this surface, incremented each time
303 * the native surface contained within this object changes.
304 *
305 * @return The current generation number.
306 * @hide
307 */
308 public int getGenerationId() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700309 synchronized (mLock) {
310 return mGenerationId;
311 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700312 }
313
314 /**
Rob Carr64e516f2015-10-29 00:20:45 +0000315 * Returns the next frame number which will be dequeued for rendering.
316 * Intended for use with SurfaceFlinger's deferred transactions API.
317 *
318 * @hide
319 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100320 @UnsupportedAppUsage
Rob Carr64e516f2015-10-29 00:20:45 +0000321 public long getNextFrameNumber() {
322 synchronized (mLock) {
Jorim Jaggi388090f2018-01-22 17:03:59 +0100323 checkNotReleasedLocked();
Rob Carr64e516f2015-10-29 00:20:45 +0000324 return nativeGetNextFrameNumber(mNativeObject);
325 }
326 }
327
328 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700329 * Returns true if the consumer of this Surface is running behind the producer.
330 *
331 * @return True if the consumer is more than one buffer ahead of the producer.
332 * @hide
333 */
334 public boolean isConsumerRunningBehind() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700335 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700336 checkNotReleasedLocked();
337 return nativeIsConsumerRunningBehind(mNativeObject);
338 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700339 }
340
341 /**
342 * Gets a {@link Canvas} for drawing into this surface.
343 *
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700344 * After drawing into the provided {@link Canvas}, the caller must
Jeff Brown64a55af2012-08-26 02:47:39 -0700345 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
346 *
Mathias Agopian30d7ab92013-02-14 15:38:40 -0800347 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
Jeff Brown64a55af2012-08-26 02:47:39 -0700348 * to redraw. This function may choose to expand the dirty rectangle if for example
349 * the surface has been resized or if the previous contents of the surface were
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700350 * not available. The caller must redraw the entire dirty region as represented
351 * by the contents of the inOutDirty rectangle upon return from this function.
Jeff Brown64a55af2012-08-26 02:47:39 -0700352 * The caller may also pass <code>null</code> instead, in the case where the
353 * entire surface should be redrawn.
354 * @return A canvas for drawing into the surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700355 *
356 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
357 * @throws OutOfResourcesException If the canvas cannot be locked.
Jeff Brown64a55af2012-08-26 02:47:39 -0700358 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800359 public Canvas lockCanvas(Rect inOutDirty)
Igor Murashkina86ab6402013-08-30 12:58:36 -0700360 throws Surface.OutOfResourcesException, IllegalArgumentException {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700361 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700362 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700363 if (mLockedObject != 0) {
364 // Ideally, nativeLockCanvas() would throw in this situation and prevent the
365 // double-lock, but that won't happen if mNativeObject was updated. We can't
366 // abandon the old mLockedObject because it might still be in use, so instead
367 // we just refuse to re-lock the Surface.
Jesse Halld7e55962014-10-13 11:01:15 -0700368 throw new IllegalArgumentException("Surface was already locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700369 }
370 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700371 return mCanvas;
Mathias Agopian7c116b52013-03-18 20:27:02 -0700372 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700373 }
374
375 /**
376 * Posts the new contents of the {@link Canvas} to the surface and
377 * releases the {@link Canvas}.
378 *
379 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
380 */
381 public void unlockCanvasAndPost(Canvas canvas) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700382 synchronized (mLock) {
383 checkNotReleasedLocked();
384
385 if (mHwuiContext != null) {
386 mHwuiContext.unlockAndPost(canvas);
387 } else {
388 unlockSwCanvasAndPost(canvas);
389 }
390 }
391 }
392
393 private void unlockSwCanvasAndPost(Canvas canvas) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700394 if (canvas != mCanvas) {
395 throw new IllegalArgumentException("canvas object must be the same instance that "
396 + "was previously returned by lockCanvas");
397 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700398 if (mNativeObject != mLockedObject) {
399 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
400 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
401 Long.toHexString(mLockedObject) +")");
402 }
403 if (mLockedObject == 0) {
404 throw new IllegalStateException("Surface was not locked");
405 }
406 try {
407 nativeUnlockCanvasAndPost(mLockedObject, canvas);
408 } finally {
409 nativeRelease(mLockedObject);
410 mLockedObject = 0;
411 }
412 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700413
John Reckbb2d0cc2014-10-21 10:09:36 -0700414 /**
415 * Gets a {@link Canvas} for drawing into this surface.
416 *
417 * After drawing into the provided {@link Canvas}, the caller must
418 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
419 *
420 * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated
421 * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
422 * unsupported drawing operations</a> for a list of what is and isn't
John Reck43a53282014-10-23 13:56:03 -0700423 * supported in a hardware-accelerated canvas. It is also required to
424 * fully cover the surface every time {@link #lockHardwareCanvas()} is
425 * called as the buffer is not preserved between frames. Partial updates
426 * are not supported.
John Reckbb2d0cc2014-10-21 10:09:36 -0700427 *
428 * @return A canvas for drawing into the surface.
429 *
430 * @throws IllegalStateException If the canvas cannot be locked.
431 */
432 public Canvas lockHardwareCanvas() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700433 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700434 checkNotReleasedLocked();
John Reckbb2d0cc2014-10-21 10:09:36 -0700435 if (mHwuiContext == null) {
Peiyong Lind8b68712018-03-06 18:34:21 -0800436 mHwuiContext = new HwuiContext(false);
437 }
438 return mHwuiContext.lockCanvas(
439 nativeGetWidth(mNativeObject),
440 nativeGetHeight(mNativeObject));
441 }
442 }
443
444 /**
445 * Gets a {@link Canvas} for drawing into this surface that supports wide color gamut.
446 *
447 * After drawing into the provided {@link Canvas}, the caller must
448 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
449 *
450 * Unlike {@link #lockCanvas(Rect)} and {@link #lockHardwareCanvas()},
451 * this will return a hardware-accelerated canvas that supports wide color gamut.
452 * See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
453 * unsupported drawing operations</a> for a list of what is and isn't
454 * supported in a hardware-accelerated canvas. It is also required to
455 * fully cover the surface every time {@link #lockHardwareCanvas()} is
456 * called as the buffer is not preserved between frames. Partial updates
457 * are not supported.
458 *
459 * @return A canvas for drawing into the surface.
460 *
461 * @throws IllegalStateException If the canvas cannot be locked.
462 *
463 * @hide
464 */
465 public Canvas lockHardwareWideColorGamutCanvas() {
466 synchronized (mLock) {
467 checkNotReleasedLocked();
468 if (mHwuiContext != null && !mHwuiContext.isWideColorGamut()) {
469 mHwuiContext.destroy();
470 mHwuiContext = null;
471 }
472 if (mHwuiContext == null) {
473 mHwuiContext = new HwuiContext(true);
Andy McFaddened55c8d2013-08-20 10:05:51 -0700474 }
John Reckb35c9602014-11-13 16:15:08 -0800475 return mHwuiContext.lockCanvas(
476 nativeGetWidth(mNativeObject),
477 nativeGetHeight(mNativeObject));
Mathias Agopian7c116b52013-03-18 20:27:02 -0700478 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700479 }
480
Andy McFaddened55c8d2013-08-20 10:05:51 -0700481 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700482 * @deprecated This API has been removed and is not supported. Do not use.
483 */
484 @Deprecated
485 public void unlockCanvas(Canvas canvas) {
486 throw new UnsupportedOperationException();
487 }
488
489 /**
490 * Sets the translator used to scale canvas's width/height in compatibility
491 * mode.
492 */
493 void setCompatibilityTranslator(Translator translator) {
494 if (translator != null) {
495 float appScale = translator.applicationScale;
496 mCompatibleMatrix = new Matrix();
497 mCompatibleMatrix.setScale(appScale, appScale);
498 }
499 }
500
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700501 /**
Mathias Agopianb9230662011-08-03 14:44:48 -0700502 * Copy another surface to this one. This surface now holds a reference
503 * to the same data as the original surface, and is -not- the owner.
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800504 * This is for use by the window manager when returning a window surface
505 * back from a client, converting it from the representation being managed
506 * by the window manager to the representation the client uses to draw
507 * in to it.
Bryce Lee02949f12017-06-16 07:20:34 -0700508 *
509 * @param other {@link SurfaceControl} to copy from.
Mathias Agopianb9230662011-08-03 14:44:48 -0700510 * @hide
511 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100512 @UnsupportedAppUsage
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800513 public void copyFrom(SurfaceControl other) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700514 if (other == null) {
515 throw new IllegalArgumentException("other must not be null");
516 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700517
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000518 long surfaceControlPtr = other.mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700519 if (surfaceControlPtr == 0) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800520 throw new NullPointerException(
Bryce Lee02949f12017-06-16 07:20:34 -0700521 "null SurfaceControl native object. Are you using a released SurfaceControl?");
522 }
Robert Carrd5686722019-01-25 14:30:52 -0800523 long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
Bryce Lee02949f12017-06-16 07:20:34 -0700524
525 synchronized (mLock) {
Robert Carrd5686722019-01-25 14:30:52 -0800526 if (newNativeObject == mNativeObject) {
527 return;
528 }
Bryce Lee02949f12017-06-16 07:20:34 -0700529 if (mNativeObject != 0) {
530 nativeRelease(mNativeObject);
531 }
532 setNativeObjectLocked(newNativeObject);
533 }
534 }
535
536 /**
537 * Gets a reference a surface created from this one. This surface now holds a reference
538 * to the same data as the original surface, and is -not- the owner.
539 * This is for use by the window manager when returning a window surface
540 * back from a client, converting it from the representation being managed
541 * by the window manager to the representation the client uses to draw
542 * in to it.
543 *
544 * @param other {@link SurfaceControl} to create surface from.
545 *
546 * @hide
547 */
548 public void createFrom(SurfaceControl other) {
549 if (other == null) {
550 throw new IllegalArgumentException("other must not be null");
551 }
552
553 long surfaceControlPtr = other.mNativeObject;
554 if (surfaceControlPtr == 0) {
555 throw new NullPointerException(
556 "null SurfaceControl native object. Are you using a released SurfaceControl?");
Jeff Brown64a55af2012-08-26 02:47:39 -0700557 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000558 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700559
560 synchronized (mLock) {
561 if (mNativeObject != 0) {
562 nativeRelease(mNativeObject);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700563 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700564 setNativeObjectLocked(newNativeObject);
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700565 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700566 }
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800567
568 /**
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700569 * This is intended to be used by {@link SurfaceView#updateWindow} only.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700570 * @param other access is not thread safe
571 * @hide
572 * @deprecated
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800573 */
Mathias Agopian7c116b52013-03-18 20:27:02 -0700574 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +0100575 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700576 public void transferFrom(Surface other) {
577 if (other == null) {
578 throw new IllegalArgumentException("other must not be null");
579 }
580 if (other != this) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000581 final long newPtr;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700582 synchronized (other.mLock) {
583 newPtr = other.mNativeObject;
584 other.setNativeObjectLocked(0);
585 }
586
587 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700588 if (mNativeObject != 0) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700589 nativeRelease(mNativeObject);
590 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700591 setNativeObjectLocked(newPtr);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800592 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700593 }
Mathias Agopianb9230662011-08-03 14:44:48 -0700594 }
595
Jeff Brown64a55af2012-08-26 02:47:39 -0700596 @Override
597 public int describeContents() {
598 return 0;
599 }
600
601 public void readFromParcel(Parcel source) {
602 if (source == null) {
603 throw new IllegalArgumentException("source must not be null");
604 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700605
606 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700607 // nativeReadFromParcel() will either return mNativeObject, or
608 // create a new native Surface and return it after reducing
609 // the reference count on mNativeObject. Either way, it is
610 // not necessary to call nativeRelease() here.
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700611 // NOTE: This must be kept synchronized with the native parceling code
612 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700613 mName = source.readString();
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700614 mIsSingleBuffered = source.readInt() != 0;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700615 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700616 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700617 }
618
619 @Override
620 public void writeToParcel(Parcel dest, int flags) {
621 if (dest == null) {
622 throw new IllegalArgumentException("dest must not be null");
623 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700624 synchronized (mLock) {
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700625 // NOTE: This must be kept synchronized with the native parceling code
626 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700627 dest.writeString(mName);
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700628 dest.writeInt(mIsSingleBuffered ? 1 : 0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700629 nativeWriteToParcel(mNativeObject, dest);
630 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700631 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
632 release();
633 }
634 }
635
636 @Override
637 public String toString() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700638 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700639 return "Surface(name=" + mName + ")/@0x" +
640 Integer.toHexString(System.identityHashCode(this));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700641 }
642 }
643
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000644 private void setNativeObjectLocked(long ptr) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700645 if (mNativeObject != ptr) {
646 if (mNativeObject == 0 && ptr != 0) {
647 mCloseGuard.open("release");
648 } else if (mNativeObject != 0 && ptr == 0) {
649 mCloseGuard.close();
650 }
651 mNativeObject = ptr;
652 mGenerationId += 1;
John Reckbb2d0cc2014-10-21 10:09:36 -0700653 if (mHwuiContext != null) {
654 mHwuiContext.updateSurface();
655 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700656 }
657 }
658
659 private void checkNotReleasedLocked() {
660 if (mNativeObject == 0) {
661 throw new IllegalStateException("Surface has already been released.");
662 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700663 }
664
Mathias Agopianc14bacf2012-04-23 18:23:08 -0700665 /**
Dan Stoza5795d642014-06-20 13:01:36 -0700666 * Allocate buffers ahead of time to avoid allocation delays during rendering
667 * @hide
668 */
669 public void allocateBuffers() {
670 synchronized (mLock) {
671 checkNotReleasedLocked();
672 nativeAllocateBuffers(mNativeObject);
673 }
674 }
675
676 /**
Robert Carrcd9a18c2015-12-16 18:16:21 -0800677 * Set the scaling mode to be used for this surfaces buffers
678 * @hide
679 */
680 void setScalingMode(@ScalingMode int scalingMode) {
681 synchronized (mLock) {
682 checkNotReleasedLocked();
683 int err = nativeSetScalingMode(mNativeObject, scalingMode);
684 if (err != 0) {
685 throw new IllegalArgumentException("Invalid scaling mode: " + scalingMode);
686 }
687 }
688 }
689
Robert Carr387838b2016-09-07 14:12:44 -0700690 void forceScopedDisconnect() {
691 synchronized (mLock) {
692 checkNotReleasedLocked();
693 int err = nativeForceScopedDisconnect(mNativeObject);
694 if (err != 0) {
695 throw new RuntimeException("Failed to disconnect Surface instance (bad object?)");
696 }
697 }
698 }
699
Robert Carrcd9a18c2015-12-16 18:16:21 -0800700 /**
Robert Carra35e5de2017-03-03 17:04:54 -0800701 * Transfer ownership of buffer and present it on the Surface.
702 * @hide
703 */
704 public void attachAndQueueBuffer(GraphicBuffer buffer) {
705 synchronized (mLock) {
706 checkNotReleasedLocked();
707 int err = nativeAttachAndQueueBuffer(mNativeObject, buffer);
708 if (err != 0) {
709 throw new RuntimeException(
710 "Failed to attach and queue buffer to Surface (bad object?)");
711 }
712 }
713 }
714
715 /**
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700716 * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
717 * @hide
718 */
719 public boolean isSingleBuffered() {
720 return mIsSingleBuffered;
721 }
722
723 /**
Romain Guy0bbf0b42017-07-20 08:57:07 -0700724 * <p>The shared buffer mode allows both the application and the surface compositor
725 * (SurfaceFlinger) to concurrently access this surface's buffer. While the
726 * application is still required to issue a present request
727 * (see {@link #unlockCanvasAndPost(Canvas)}) to the compositor when an update is required,
728 * the compositor may trigger an update at any time. Since the surface's buffer is shared
729 * between the application and the compositor, updates triggered by the compositor may
730 * cause visible tearing.</p>
731 *
732 * <p>The shared buffer mode can be used with
733 * {@link #setAutoRefreshEnabled(boolean) auto-refresh} to avoid the overhead of
734 * issuing present requests.</p>
735 *
736 * <p>If the application uses the shared buffer mode to reduce latency, it is
737 * recommended to use software rendering (see {@link #lockCanvas(Rect)} to ensure
738 * the graphics workloads are not affected by other applications and/or the system
739 * using the GPU. When using software rendering, the application should update the
740 * smallest possible region of the surface required.</p>
741 *
742 * <p class="note">The shared buffer mode might not be supported by the underlying
743 * hardware. Enabling shared buffer mode on hardware that does not support it will
744 * not yield an error but the application will not benefit from lower latency (and
745 * tearing will not be visible).</p>
746 *
747 * <p class="note">Depending on how many and what kind of surfaces are visible, the
748 * surface compositor may need to copy the shared buffer before it is displayed. When
749 * this happens, the latency benefits of shared buffer mode will be reduced.</p>
750 *
751 * @param enabled True to enable the shared buffer mode on this surface, false otherwise
752 *
753 * @see #isSharedBufferModeEnabled()
754 * @see #setAutoRefreshEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700755 *
756 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700757 */
758 public void setSharedBufferModeEnabled(boolean enabled) {
759 if (mIsSharedBufferModeEnabled != enabled) {
760 int error = nativeSetSharedBufferModeEnabled(mNativeObject, enabled);
761 if (error != 0) {
762 throw new RuntimeException(
763 "Failed to set shared buffer mode on Surface (bad object?)");
764 } else {
765 mIsSharedBufferModeEnabled = enabled;
766 }
767 }
768 }
769
770 /**
771 * @return True if shared buffer mode is enabled on this surface, false otherwise
772 *
773 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700774 *
775 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700776 */
777 public boolean isSharedBufferModeEnabled() {
778 return mIsSharedBufferModeEnabled;
779 }
780
781 /**
782 * <p>When auto-refresh is enabled, the surface compositor (SurfaceFlinger)
783 * automatically updates the display on a regular refresh cycle. The application
784 * can continue to issue present requests but it is not required. Enabling
785 * auto-refresh may result in visible tearing.</p>
786 *
787 * <p>Auto-refresh has no effect if the {@link #setSharedBufferModeEnabled(boolean)
788 * shared buffer mode} is not enabled.</p>
789 *
790 * <p>Because auto-refresh will trigger continuous updates of the display, it is
791 * recommended to turn it on only when necessary. For example, in a drawing/painting
792 * application auto-refresh should be enabled on finger/pen down and disabled on
793 * finger/pen up.</p>
794 *
795 * @param enabled True to enable auto-refresh on this surface, false otherwise
796 *
797 * @see #isAutoRefreshEnabled()
798 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700799 *
800 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700801 */
802 public void setAutoRefreshEnabled(boolean enabled) {
803 if (mIsAutoRefreshEnabled != enabled) {
804 int error = nativeSetAutoRefreshEnabled(mNativeObject, enabled);
805 if (error != 0) {
806 throw new RuntimeException("Failed to set auto refresh on Surface (bad object?)");
807 } else {
808 mIsAutoRefreshEnabled = enabled;
809 }
810 }
811 }
812
813 /**
814 * @return True if auto-refresh is enabled on this surface, false otherwise
Romain Guy010f0822017-08-16 09:43:07 -0700815 *
816 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700817 */
818 public boolean isAutoRefreshEnabled() {
819 return mIsAutoRefreshEnabled;
820 }
821
822 /**
Igor Murashkina86ab6402013-08-30 12:58:36 -0700823 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
824 * when a SurfaceTexture could not successfully be allocated.
Jeff Brown64a55af2012-08-26 02:47:39 -0700825 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700826 @SuppressWarnings("serial")
827 public static class OutOfResourcesException extends RuntimeException {
Jeff Brown64a55af2012-08-26 02:47:39 -0700828 public OutOfResourcesException() {
829 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700830 public OutOfResourcesException(String name) {
831 super(name);
832 }
833 }
834
835 /**
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700836 * Returns a human readable representation of a rotation.
837 *
838 * @param rotation The rotation.
839 * @return The rotation symbolic name.
Svetoslav Ganov545252f2012-12-10 18:29:24 -0800840 *
841 * @hide
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700842 */
843 public static String rotationToString(int rotation) {
844 switch (rotation) {
845 case Surface.ROTATION_0: {
846 return "ROTATION_0";
847 }
848 case Surface.ROTATION_90: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700849 return "ROTATION_90";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700850 }
851 case Surface.ROTATION_180: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700852 return "ROTATION_180";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700853 }
854 case Surface.ROTATION_270: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700855 return "ROTATION_270";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700856 }
857 default: {
Michael Wright19859762017-09-18 20:57:58 +0100858 return Integer.toString(rotation);
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700859 }
860 }
861 }
862
863 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700864 * A Canvas class that can handle the compatibility mode.
865 * This does two things differently.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700866 * <ul>
Mathias Agopianb9230662011-08-03 14:44:48 -0700867 * <li>Returns the width and height of the target metrics, rather than
868 * native. For example, the canvas returns 320x480 even if an app is running
869 * in WVGA high density.
870 * <li>Scales the matrix in setMatrix by the application scale, except if
871 * the matrix looks like obtained from getMatrix. This is a hack to handle
872 * the case that an application uses getMatrix to keep the original matrix,
873 * set matrix of its own, then set the original matrix back. There is no
874 * perfect solution that works for all cases, and there are a lot of cases
875 * that this model does not work, but we hope this works for many apps.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700876 * </ul>
877 */
Jeff Brown64a55af2012-08-26 02:47:39 -0700878 private final class CompatibleCanvas extends Canvas {
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700879 // A temp matrix to remember what an application obtained via {@link getMatrix}
880 private Matrix mOrigMatrix = null;
881
882 @Override
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700883 public void setMatrix(Matrix matrix) {
884 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
885 // don't scale the matrix if it's not compatibility mode, or
886 // the matrix was obtained from getMatrix.
887 super.setMatrix(matrix);
888 } else {
889 Matrix m = new Matrix(mCompatibleMatrix);
890 m.preConcat(matrix);
891 super.setMatrix(m);
892 }
893 }
894
Romain Guy8b5aa482013-02-28 18:13:54 -0800895 @SuppressWarnings("deprecation")
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700896 @Override
897 public void getMatrix(Matrix m) {
898 super.getMatrix(m);
899 if (mOrigMatrix == null) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700900 mOrigMatrix = new Matrix();
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700901 }
902 mOrigMatrix.set(m);
903 }
Romain Guyd10cd572010-10-10 13:33:22 -0700904 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700905
906 private final class HwuiContext {
907 private final RenderNode mRenderNode;
908 private long mHwuiRenderer;
John Reck32f140aa62018-10-04 15:08:24 -0700909 private RecordingCanvas mCanvas;
Peiyong Lind8b68712018-03-06 18:34:21 -0800910 private final boolean mIsWideColorGamut;
John Reckbb2d0cc2014-10-21 10:09:36 -0700911
Peiyong Lind8b68712018-03-06 18:34:21 -0800912 HwuiContext(boolean isWideColorGamut) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700913 mRenderNode = RenderNode.create("HwuiCanvas", null);
914 mRenderNode.setClipToBounds(false);
John Recka2d20b42018-10-01 12:21:55 -0700915 mRenderNode.setForceDarkAllowed(false);
Peiyong Lind8b68712018-03-06 18:34:21 -0800916 mIsWideColorGamut = isWideColorGamut;
917 mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject,
918 isWideColorGamut);
John Reckbb2d0cc2014-10-21 10:09:36 -0700919 }
920
John Reckb35c9602014-11-13 16:15:08 -0800921 Canvas lockCanvas(int width, int height) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700922 if (mCanvas != null) {
923 throw new IllegalStateException("Surface was already locked!");
924 }
John Recke57475e2019-02-20 17:39:52 -0800925 mCanvas = mRenderNode.beginRecording(width, height);
John Reckbb2d0cc2014-10-21 10:09:36 -0700926 return mCanvas;
927 }
928
929 void unlockAndPost(Canvas canvas) {
930 if (canvas != mCanvas) {
931 throw new IllegalArgumentException("canvas object must be the same instance that "
932 + "was previously returned by lockCanvas");
933 }
John Recke57475e2019-02-20 17:39:52 -0800934 mRenderNode.endRecording();
John Reckbb2d0cc2014-10-21 10:09:36 -0700935 mCanvas = null;
936 nHwuiDraw(mHwuiRenderer);
937 }
938
939 void updateSurface() {
940 nHwuiSetSurface(mHwuiRenderer, mNativeObject);
941 }
942
943 void destroy() {
944 if (mHwuiRenderer != 0) {
945 nHwuiDestroy(mHwuiRenderer);
946 mHwuiRenderer = 0;
947 }
948 }
Peiyong Lind8b68712018-03-06 18:34:21 -0800949
950 boolean isWideColorGamut() {
951 return mIsWideColorGamut;
952 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700953 }
954
Peiyong Lind8b68712018-03-06 18:34:21 -0800955 private static native long nHwuiCreate(long rootNode, long surface, boolean isWideColorGamut);
John Reckbb2d0cc2014-10-21 10:09:36 -0700956 private static native void nHwuiSetSurface(long renderer, long surface);
957 private static native void nHwuiDraw(long renderer);
958 private static native void nHwuiDestroy(long renderer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959}