blob: cb64ab1fd921d8d3f1c87117c6c460f1f6b58010 [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;
Robert Carra35e5de2017-03-03 17:04:54 -080024import android.graphics.GraphicBuffer;
Jeff Brown0b722fe2012-08-24 22:40:14 -070025import android.graphics.Matrix;
John Reck32f140aa62018-10-04 15:08:24 -070026import android.graphics.RecordingCanvas;
Jeff Brown0b722fe2012-08-24 22:40:14 -070027import android.graphics.Rect;
John Reck32f140aa62018-10-04 15:08:24 -070028import android.graphics.RenderNode;
Jeff Brown0b722fe2012-08-24 22:40:14 -070029import android.graphics.SurfaceTexture;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.os.Parcel;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080031import android.os.Parcelable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.util.Log;
Tor Norbyed9273d62013-05-30 15:59:53 -070033
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070034import dalvik.system.CloseGuard;
35
Tor Norbyed9273d62013-05-30 15:59:53 -070036import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
38
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039/**
Glenn Kasten334031c2010-11-09 21:54:38 -080040 * Handle onto a raw buffer that is being managed by the screen compositor.
Eino-Ville Talvalac4faf0c2016-09-16 13:34:52 -070041 *
42 * <p>A Surface is generally created by or from a consumer of image buffers (such as a
43 * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
44 * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
45 * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
46 * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
47 * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
48 * into.</p>
49 *
50 * <p><strong>Note:</strong> A Surface acts like a
51 * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By
52 * itself it will not keep its parent consumer from being reclaimed.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 */
54public class Surface implements Parcelable {
Jeff Brown64a55af2012-08-26 02:47:39 -070055 private static final String TAG = "Surface";
Mathias Agopianb9230662011-08-03 14:44:48 -070056
Ashok Bhat36bef0b2014-01-20 20:08:01 +000057 private static native long nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
Mathias Agopian29479eb2013-02-14 14:36:04 -080058 throws OutOfResourcesException;
Bryce Lee02949f12017-06-16 07:20:34 -070059
Ashok Bhat36bef0b2014-01-20 20:08:01 +000060 private static native long nativeCreateFromSurfaceControl(long surfaceControlNativeObject);
Robert Carrd5686722019-01-25 14:30:52 -080061 private static native long nativeGetFromSurfaceControl(long surfaceObject,
62 long surfaceControlNativeObject);
Mathias Agopian52800612013-02-14 17:11:20 -080063
Ashok Bhat36bef0b2014-01-20 20:08:01 +000064 private static native long nativeLockCanvas(long nativeObject, Canvas canvas, Rect dirty)
Jeff Brownfc0ebd72013-04-30 16:33:00 -070065 throws OutOfResourcesException;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000066 private static native void nativeUnlockCanvasAndPost(long nativeObject, Canvas canvas);
Mathias Agopian29479eb2013-02-14 14:36:04 -080067
Mathew Inwooda570dee2018-08-17 14:56:00 +010068 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +000069 private static native void nativeRelease(long nativeObject);
70 private static native boolean nativeIsValid(long nativeObject);
71 private static native boolean nativeIsConsumerRunningBehind(long nativeObject);
72 private static native long nativeReadFromParcel(long nativeObject, Parcel source);
73 private static native void nativeWriteToParcel(long nativeObject, Parcel dest);
Mathias Agopian29479eb2013-02-14 14:36:04 -080074
Dan Stoza5795d642014-06-20 13:01:36 -070075 private static native void nativeAllocateBuffers(long nativeObject);
76
John Reckb35c9602014-11-13 16:15:08 -080077 private static native int nativeGetWidth(long nativeObject);
78 private static native int nativeGetHeight(long nativeObject);
79
Rob Carr64e516f2015-10-29 00:20:45 +000080 private static native long nativeGetNextFrameNumber(long nativeObject);
Robert Carrcd9a18c2015-12-16 18:16:21 -080081 private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
Robert Carr387838b2016-09-07 14:12:44 -070082 private static native int nativeForceScopedDisconnect(long nativeObject);
Robert Carra35e5de2017-03-03 17:04:54 -080083 private static native int nativeAttachAndQueueBuffer(long nativeObject, GraphicBuffer buffer);
Rob Carr64e516f2015-10-29 00:20:45 +000084
Romain Guy0bbf0b42017-07-20 08:57:07 -070085 private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
86 private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
87
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -070088 public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
Jeff Brown64a55af2012-08-26 02:47:39 -070089 new Parcelable.Creator<Surface>() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -070090 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -070091 public Surface createFromParcel(Parcel source) {
92 try {
93 Surface s = new Surface();
94 s.readFromParcel(source);
95 return s;
96 } catch (Exception e) {
97 Log.e(TAG, "Exception creating surface from parcel", e);
98 return null;
99 }
Kevin Hesterb85c9332012-03-08 17:06:56 -0800100 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700101
102 @Override
Jeff Brown64a55af2012-08-26 02:47:39 -0700103 public Surface[] newArray(int size) {
104 return new Surface[size];
105 }
106 };
Kevin Hesterb85c9332012-03-08 17:06:56 -0800107
Jeff Brown64a55af2012-08-26 02:47:39 -0700108 private final CloseGuard mCloseGuard = CloseGuard.get();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700109
110 // Guarded state.
Mathew Inwooda570dee2018-08-17 14:56:00 +0100111 @UnsupportedAppUsage
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700112 final Object mLock = new Object(); // protects the native state
Mathew Inwooda570dee2018-08-17 14:56:00 +0100113 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700114 private String mName;
Mathew Inwooda570dee2018-08-17 14:56:00 +0100115 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000116 long mNativeObject; // package scope only for SurfaceControl access
Mathew Inwooda570dee2018-08-17 14:56:00 +0100117 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000118 private long mLockedObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700119 private int mGenerationId; // incremented each time mNativeObject changes
Jeff Brown64a55af2012-08-26 02:47:39 -0700120 private final Canvas mCanvas = new CompatibleCanvas();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700122 // A matrix to scale the matrix set by application. This is set to null for
123 // non compatibility mode.
124 private Matrix mCompatibleMatrix;
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700125
John Reckbb2d0cc2014-10-21 10:09:36 -0700126 private HwuiContext mHwuiContext;
127
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700128 private boolean mIsSingleBuffered;
Romain Guy0bbf0b42017-07-20 08:57:07 -0700129 private boolean mIsSharedBufferModeEnabled;
130 private boolean mIsAutoRefreshEnabled;
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700131
Tor Norbyed9273d62013-05-30 15:59:53 -0700132 /** @hide */
Robert Carrcd9a18c2015-12-16 18:16:21 -0800133 @Retention(RetentionPolicy.SOURCE)
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700134 @IntDef(prefix = { "SCALING_MODE_" }, value = {
135 SCALING_MODE_FREEZE,
136 SCALING_MODE_SCALE_TO_WINDOW,
137 SCALING_MODE_SCALE_CROP,
138 SCALING_MODE_NO_SCALE_CROP
139 })
Robert Carrcd9a18c2015-12-16 18:16:21 -0800140 public @interface ScalingMode {}
141 // From system/window.h
142 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700143 public static final int SCALING_MODE_FREEZE = 0;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800144 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700145 public static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800146 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700147 public static final int SCALING_MODE_SCALE_CROP = 2;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800148 /** @hide */
Robert Carr1ca6a332016-04-11 18:00:43 -0700149 public static final int SCALING_MODE_NO_SCALE_CROP = 3;
Robert Carrcd9a18c2015-12-16 18:16:21 -0800150
151 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700152 @IntDef(prefix = { "ROTATION_" }, value = {
153 ROTATION_0,
154 ROTATION_90,
155 ROTATION_180,
156 ROTATION_270
157 })
Tor Norbyed9273d62013-05-30 15:59:53 -0700158 @Retention(RetentionPolicy.SOURCE)
159 public @interface Rotation {}
160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 /**
Mathias Agopian29479eb2013-02-14 14:36:04 -0800162 * Rotation constant: 0 degree rotation (natural orientation)
163 */
164 public static final int ROTATION_0 = 0;
165
166 /**
167 * Rotation constant: 90 degree rotation.
168 */
169 public static final int ROTATION_90 = 1;
170
171 /**
172 * Rotation constant: 180 degree rotation.
173 */
174 public static final int ROTATION_180 = 2;
175
176 /**
177 * Rotation constant: 270 degree rotation.
178 */
179 public static final int ROTATION_270 = 3;
180
Mathias Agopian29479eb2013-02-14 14:36:04 -0800181 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700182 * Create an empty surface, which will later be filled in by readFromParcel().
Mathias Agopianb9230662011-08-03 14:44:48 -0700183 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100185 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 public Surface() {
Jeff Brown64a55af2012-08-26 02:47:39 -0700187 }
188
189 /**
Robert Carr76907ee2019-01-11 13:38:19 -0800190 * Create a Surface assosciated with a given {@link SurfaceControl}. Buffers submitted to this
191 * surface will be displayed by the system compositor according to the parameters
192 * specified by the control. Multiple surfaces may be constructed from one SurfaceControl,
193 * but only one can be connected (e.g. have an active EGL context) at a time.
194 *
195 * @param from The SurfaceControl to assosciate this Surface with
196 */
Robert Carrda1d2422019-03-07 15:54:37 -0800197 public Surface(@NonNull SurfaceControl from) {
Robert Carr76907ee2019-01-11 13:38:19 -0800198 copyFrom(from);
199 }
200
201 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700202 * Create Surface from a {@link SurfaceTexture}.
203 *
204 * Images drawn to the Surface will be made available to the {@link
205 * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
206 * SurfaceTexture#updateTexImage}.
207 *
Eino-Ville Talvalaec99efa2017-11-29 15:35:42 -0800208 * Please note that holding onto the Surface created here is not enough to
209 * keep the provided SurfaceTexture from being reclaimed. In that sense,
210 * the Surface will act like a
211 * {@link java.lang.ref.WeakReference weak reference} to the SurfaceTexture.
212 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700213 * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
214 * Surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700215 * @throws OutOfResourcesException if the surface could not be created.
Jeff Brown64a55af2012-08-26 02:47:39 -0700216 */
217 public Surface(SurfaceTexture surfaceTexture) {
218 if (surfaceTexture == null) {
219 throw new IllegalArgumentException("surfaceTexture must not be null");
220 }
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700221 mIsSingleBuffered = surfaceTexture.isSingleBuffered();
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700222 synchronized (mLock) {
223 mName = surfaceTexture.toString();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700224 setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
Jeff Brown64a55af2012-08-26 02:47:39 -0700225 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700226 }
227
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700228 /* called from android_view_Surface_createFromIGraphicBufferProducer() */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100229 @UnsupportedAppUsage
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000230 private Surface(long nativeObject) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700231 synchronized (mLock) {
232 setNativeObjectLocked(nativeObject);
233 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800234 }
235
Jeff Brown64a55af2012-08-26 02:47:39 -0700236 @Override
237 protected void finalize() throws Throwable {
238 try {
239 if (mCloseGuard != null) {
240 mCloseGuard.warnIfOpen();
241 }
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700242 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700243 } finally {
244 super.finalize();
245 }
246 }
247
248 /**
249 * Release the local reference to the server-side surface.
250 * Always call release() when you're done with a Surface.
251 * This will make the surface invalid.
252 */
253 public void release() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700254 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700255 if (mNativeObject != 0) {
256 nativeRelease(mNativeObject);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700257 setNativeObjectLocked(0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700258 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700259 if (mHwuiContext != null) {
260 mHwuiContext.destroy();
261 mHwuiContext = null;
262 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800263 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700264 }
265
266 /**
267 * Free all server-side state associated with this surface and
268 * release this object's reference. This method can only be
269 * called from the process that created the service.
270 * @hide
271 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100272 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700273 public void destroy() {
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700274 release();
Jeff Brown64a55af2012-08-26 02:47:39 -0700275 }
276
277 /**
Lucas Dupin41c25ce2018-03-27 09:50:19 -0700278 * Destroys the HwuiContext without completely
279 * releasing the Surface.
280 * @hide
281 */
282 public void hwuiDestroy() {
283 if (mHwuiContext != null) {
284 mHwuiContext.destroy();
285 mHwuiContext = null;
286 }
287 }
288
289 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700290 * Returns true if this object holds a valid surface.
291 *
292 * @return True if it holds a physical surface, so lockCanvas() will succeed.
293 * Otherwise returns false.
294 */
295 public boolean isValid() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700296 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700297 if (mNativeObject == 0) return false;
298 return nativeIsValid(mNativeObject);
299 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700300 }
301
302 /**
303 * Gets the generation number of this surface, incremented each time
304 * the native surface contained within this object changes.
305 *
306 * @return The current generation number.
307 * @hide
308 */
309 public int getGenerationId() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700310 synchronized (mLock) {
311 return mGenerationId;
312 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700313 }
314
315 /**
Rob Carr64e516f2015-10-29 00:20:45 +0000316 * Returns the next frame number which will be dequeued for rendering.
317 * Intended for use with SurfaceFlinger's deferred transactions API.
318 *
319 * @hide
320 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100321 @UnsupportedAppUsage
Rob Carr64e516f2015-10-29 00:20:45 +0000322 public long getNextFrameNumber() {
323 synchronized (mLock) {
Jorim Jaggi388090f2018-01-22 17:03:59 +0100324 checkNotReleasedLocked();
Rob Carr64e516f2015-10-29 00:20:45 +0000325 return nativeGetNextFrameNumber(mNativeObject);
326 }
327 }
328
329 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700330 * Returns true if the consumer of this Surface is running behind the producer.
331 *
332 * @return True if the consumer is more than one buffer ahead of the producer.
333 * @hide
334 */
335 public boolean isConsumerRunningBehind() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700336 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700337 checkNotReleasedLocked();
338 return nativeIsConsumerRunningBehind(mNativeObject);
339 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700340 }
341
342 /**
343 * Gets a {@link Canvas} for drawing into this surface.
344 *
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700345 * After drawing into the provided {@link Canvas}, the caller must
Jeff Brown64a55af2012-08-26 02:47:39 -0700346 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
347 *
Mathias Agopian30d7ab92013-02-14 15:38:40 -0800348 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
Jeff Brown64a55af2012-08-26 02:47:39 -0700349 * to redraw. This function may choose to expand the dirty rectangle if for example
350 * the surface has been resized or if the previous contents of the surface were
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700351 * not available. The caller must redraw the entire dirty region as represented
352 * by the contents of the inOutDirty rectangle upon return from this function.
Jeff Brown64a55af2012-08-26 02:47:39 -0700353 * The caller may also pass <code>null</code> instead, in the case where the
354 * entire surface should be redrawn.
355 * @return A canvas for drawing into the surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700356 *
357 * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
358 * @throws OutOfResourcesException If the canvas cannot be locked.
Jeff Brown64a55af2012-08-26 02:47:39 -0700359 */
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800360 public Canvas lockCanvas(Rect inOutDirty)
Igor Murashkina86ab6402013-08-30 12:58:36 -0700361 throws Surface.OutOfResourcesException, IllegalArgumentException {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700362 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700363 checkNotReleasedLocked();
Andy McFaddened55c8d2013-08-20 10:05:51 -0700364 if (mLockedObject != 0) {
365 // Ideally, nativeLockCanvas() would throw in this situation and prevent the
366 // double-lock, but that won't happen if mNativeObject was updated. We can't
367 // abandon the old mLockedObject because it might still be in use, so instead
368 // we just refuse to re-lock the Surface.
Jesse Halld7e55962014-10-13 11:01:15 -0700369 throw new IllegalArgumentException("Surface was already locked");
Andy McFaddened55c8d2013-08-20 10:05:51 -0700370 }
371 mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700372 return mCanvas;
Mathias Agopian7c116b52013-03-18 20:27:02 -0700373 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700374 }
375
376 /**
377 * Posts the new contents of the {@link Canvas} to the surface and
378 * releases the {@link Canvas}.
379 *
380 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
381 */
382 public void unlockCanvasAndPost(Canvas canvas) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700383 synchronized (mLock) {
384 checkNotReleasedLocked();
385
386 if (mHwuiContext != null) {
387 mHwuiContext.unlockAndPost(canvas);
388 } else {
389 unlockSwCanvasAndPost(canvas);
390 }
391 }
392 }
393
394 private void unlockSwCanvasAndPost(Canvas canvas) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700395 if (canvas != mCanvas) {
396 throw new IllegalArgumentException("canvas object must be the same instance that "
397 + "was previously returned by lockCanvas");
398 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700399 if (mNativeObject != mLockedObject) {
400 Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
401 Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
402 Long.toHexString(mLockedObject) +")");
403 }
404 if (mLockedObject == 0) {
405 throw new IllegalStateException("Surface was not locked");
406 }
407 try {
408 nativeUnlockCanvasAndPost(mLockedObject, canvas);
409 } finally {
410 nativeRelease(mLockedObject);
411 mLockedObject = 0;
412 }
413 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700414
John Reckbb2d0cc2014-10-21 10:09:36 -0700415 /**
416 * Gets a {@link Canvas} for drawing into this surface.
417 *
418 * After drawing into the provided {@link Canvas}, the caller must
419 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
420 *
421 * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated
422 * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
423 * unsupported drawing operations</a> for a list of what is and isn't
John Reck43a53282014-10-23 13:56:03 -0700424 * supported in a hardware-accelerated canvas. It is also required to
425 * fully cover the surface every time {@link #lockHardwareCanvas()} is
426 * called as the buffer is not preserved between frames. Partial updates
427 * are not supported.
John Reckbb2d0cc2014-10-21 10:09:36 -0700428 *
429 * @return A canvas for drawing into the surface.
430 *
431 * @throws IllegalStateException If the canvas cannot be locked.
432 */
433 public Canvas lockHardwareCanvas() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700434 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700435 checkNotReleasedLocked();
John Reckbb2d0cc2014-10-21 10:09:36 -0700436 if (mHwuiContext == null) {
Peiyong Lind8b68712018-03-06 18:34:21 -0800437 mHwuiContext = new HwuiContext(false);
438 }
439 return mHwuiContext.lockCanvas(
440 nativeGetWidth(mNativeObject),
441 nativeGetHeight(mNativeObject));
442 }
443 }
444
445 /**
446 * Gets a {@link Canvas} for drawing into this surface that supports wide color gamut.
447 *
448 * After drawing into the provided {@link Canvas}, the caller must
449 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
450 *
451 * Unlike {@link #lockCanvas(Rect)} and {@link #lockHardwareCanvas()},
452 * this will return a hardware-accelerated canvas that supports wide color gamut.
453 * See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
454 * unsupported drawing operations</a> for a list of what is and isn't
455 * supported in a hardware-accelerated canvas. It is also required to
456 * fully cover the surface every time {@link #lockHardwareCanvas()} is
457 * called as the buffer is not preserved between frames. Partial updates
458 * are not supported.
459 *
460 * @return A canvas for drawing into the surface.
461 *
462 * @throws IllegalStateException If the canvas cannot be locked.
463 *
464 * @hide
465 */
466 public Canvas lockHardwareWideColorGamutCanvas() {
467 synchronized (mLock) {
468 checkNotReleasedLocked();
469 if (mHwuiContext != null && !mHwuiContext.isWideColorGamut()) {
470 mHwuiContext.destroy();
471 mHwuiContext = null;
472 }
473 if (mHwuiContext == null) {
474 mHwuiContext = new HwuiContext(true);
Andy McFaddened55c8d2013-08-20 10:05:51 -0700475 }
John Reckb35c9602014-11-13 16:15:08 -0800476 return mHwuiContext.lockCanvas(
477 nativeGetWidth(mNativeObject),
478 nativeGetHeight(mNativeObject));
Mathias Agopian7c116b52013-03-18 20:27:02 -0700479 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700480 }
481
Andy McFaddened55c8d2013-08-20 10:05:51 -0700482 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700483 * @deprecated This API has been removed and is not supported. Do not use.
484 */
485 @Deprecated
486 public void unlockCanvas(Canvas canvas) {
487 throw new UnsupportedOperationException();
488 }
489
490 /**
491 * Sets the translator used to scale canvas's width/height in compatibility
492 * mode.
493 */
494 void setCompatibilityTranslator(Translator translator) {
495 if (translator != null) {
496 float appScale = translator.applicationScale;
497 mCompatibleMatrix = new Matrix();
498 mCompatibleMatrix.setScale(appScale, appScale);
499 }
500 }
501
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700502 /**
Mathias Agopianb9230662011-08-03 14:44:48 -0700503 * Copy another surface to this one. This surface now holds a reference
504 * to the same data as the original surface, and is -not- the owner.
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800505 * This is for use by the window manager when returning a window surface
506 * back from a client, converting it from the representation being managed
507 * by the window manager to the representation the client uses to draw
508 * in to it.
Bryce Lee02949f12017-06-16 07:20:34 -0700509 *
510 * @param other {@link SurfaceControl} to copy from.
Mathias Agopianb9230662011-08-03 14:44:48 -0700511 * @hide
512 */
Mathew Inwooda570dee2018-08-17 14:56:00 +0100513 @UnsupportedAppUsage
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800514 public void copyFrom(SurfaceControl other) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700515 if (other == null) {
516 throw new IllegalArgumentException("other must not be null");
517 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700518
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000519 long surfaceControlPtr = other.mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700520 if (surfaceControlPtr == 0) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800521 throw new NullPointerException(
Bryce Lee02949f12017-06-16 07:20:34 -0700522 "null SurfaceControl native object. Are you using a released SurfaceControl?");
523 }
Robert Carrd5686722019-01-25 14:30:52 -0800524 long newNativeObject = nativeGetFromSurfaceControl(mNativeObject, surfaceControlPtr);
Bryce Lee02949f12017-06-16 07:20:34 -0700525
526 synchronized (mLock) {
Robert Carrd5686722019-01-25 14:30:52 -0800527 if (newNativeObject == mNativeObject) {
528 return;
529 }
Bryce Lee02949f12017-06-16 07:20:34 -0700530 if (mNativeObject != 0) {
531 nativeRelease(mNativeObject);
532 }
533 setNativeObjectLocked(newNativeObject);
534 }
535 }
536
537 /**
538 * Gets a reference a surface created from this one. This surface now holds a reference
539 * to the same data as the original surface, and is -not- the owner.
540 * This is for use by the window manager when returning a window surface
541 * back from a client, converting it from the representation being managed
542 * by the window manager to the representation the client uses to draw
543 * in to it.
544 *
545 * @param other {@link SurfaceControl} to create surface from.
546 *
547 * @hide
548 */
549 public void createFrom(SurfaceControl other) {
550 if (other == null) {
551 throw new IllegalArgumentException("other must not be null");
552 }
553
554 long surfaceControlPtr = other.mNativeObject;
555 if (surfaceControlPtr == 0) {
556 throw new NullPointerException(
557 "null SurfaceControl native object. Are you using a released SurfaceControl?");
Jeff Brown64a55af2012-08-26 02:47:39 -0700558 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000559 long newNativeObject = nativeCreateFromSurfaceControl(surfaceControlPtr);
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700560
561 synchronized (mLock) {
562 if (mNativeObject != 0) {
563 nativeRelease(mNativeObject);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700564 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700565 setNativeObjectLocked(newNativeObject);
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700566 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700567 }
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800568
569 /**
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700570 * This is intended to be used by {@link SurfaceView#updateWindow} only.
Mathias Agopian7c116b52013-03-18 20:27:02 -0700571 * @param other access is not thread safe
572 * @hide
573 * @deprecated
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800574 */
Mathias Agopian7c116b52013-03-18 20:27:02 -0700575 @Deprecated
Mathew Inwooda570dee2018-08-17 14:56:00 +0100576 @UnsupportedAppUsage
Jeff Brown64a55af2012-08-26 02:47:39 -0700577 public void transferFrom(Surface other) {
578 if (other == null) {
579 throw new IllegalArgumentException("other must not be null");
580 }
581 if (other != this) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000582 final long newPtr;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700583 synchronized (other.mLock) {
584 newPtr = other.mNativeObject;
585 other.setNativeObjectLocked(0);
586 }
587
588 synchronized (mLock) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700589 if (mNativeObject != 0) {
Mathias Agopian7c116b52013-03-18 20:27:02 -0700590 nativeRelease(mNativeObject);
591 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700592 setNativeObjectLocked(newPtr);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800593 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700594 }
Mathias Agopianb9230662011-08-03 14:44:48 -0700595 }
596
Jeff Brown64a55af2012-08-26 02:47:39 -0700597 @Override
598 public int describeContents() {
599 return 0;
600 }
601
602 public void readFromParcel(Parcel source) {
603 if (source == null) {
604 throw new IllegalArgumentException("source must not be null");
605 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700606
607 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700608 // nativeReadFromParcel() will either return mNativeObject, or
609 // create a new native Surface and return it after reducing
610 // the reference count on mNativeObject. Either way, it is
611 // not necessary to call nativeRelease() here.
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700612 // NOTE: This must be kept synchronized with the native parceling code
613 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700614 mName = source.readString();
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700615 mIsSingleBuffered = source.readInt() != 0;
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700616 setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
Mathias Agopian86e1bc72013-03-13 17:48:22 -0700617 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700618 }
619
620 @Override
621 public void writeToParcel(Parcel dest, int flags) {
622 if (dest == null) {
623 throw new IllegalArgumentException("dest must not be null");
624 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700625 synchronized (mLock) {
Eino-Ville Talvalaf005f5e2016-08-29 17:51:23 -0700626 // NOTE: This must be kept synchronized with the native parceling code
627 // in frameworks/native/libs/Surface.cpp
Mathias Agopian7c116b52013-03-18 20:27:02 -0700628 dest.writeString(mName);
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700629 dest.writeInt(mIsSingleBuffered ? 1 : 0);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700630 nativeWriteToParcel(mNativeObject, dest);
631 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700632 if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
633 release();
634 }
635 }
636
637 @Override
638 public String toString() {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700639 synchronized (mLock) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700640 return "Surface(name=" + mName + ")/@0x" +
641 Integer.toHexString(System.identityHashCode(this));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700642 }
643 }
644
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000645 private void setNativeObjectLocked(long ptr) {
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700646 if (mNativeObject != ptr) {
647 if (mNativeObject == 0 && ptr != 0) {
648 mCloseGuard.open("release");
649 } else if (mNativeObject != 0 && ptr == 0) {
650 mCloseGuard.close();
651 }
652 mNativeObject = ptr;
653 mGenerationId += 1;
John Reckbb2d0cc2014-10-21 10:09:36 -0700654 if (mHwuiContext != null) {
655 mHwuiContext.updateSurface();
656 }
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700657 }
658 }
659
660 private void checkNotReleasedLocked() {
661 if (mNativeObject == 0) {
662 throw new IllegalStateException("Surface has already been released.");
663 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700664 }
665
Mathias Agopianc14bacf2012-04-23 18:23:08 -0700666 /**
Dan Stoza5795d642014-06-20 13:01:36 -0700667 * Allocate buffers ahead of time to avoid allocation delays during rendering
668 * @hide
669 */
670 public void allocateBuffers() {
671 synchronized (mLock) {
672 checkNotReleasedLocked();
673 nativeAllocateBuffers(mNativeObject);
674 }
675 }
676
677 /**
Robert Carrcd9a18c2015-12-16 18:16:21 -0800678 * Set the scaling mode to be used for this surfaces buffers
679 * @hide
680 */
681 void setScalingMode(@ScalingMode int scalingMode) {
682 synchronized (mLock) {
683 checkNotReleasedLocked();
684 int err = nativeSetScalingMode(mNativeObject, scalingMode);
685 if (err != 0) {
686 throw new IllegalArgumentException("Invalid scaling mode: " + scalingMode);
687 }
688 }
689 }
690
Robert Carr387838b2016-09-07 14:12:44 -0700691 void forceScopedDisconnect() {
692 synchronized (mLock) {
693 checkNotReleasedLocked();
694 int err = nativeForceScopedDisconnect(mNativeObject);
695 if (err != 0) {
696 throw new RuntimeException("Failed to disconnect Surface instance (bad object?)");
697 }
698 }
699 }
700
Robert Carrcd9a18c2015-12-16 18:16:21 -0800701 /**
Robert Carra35e5de2017-03-03 17:04:54 -0800702 * Transfer ownership of buffer and present it on the Surface.
703 * @hide
704 */
705 public void attachAndQueueBuffer(GraphicBuffer buffer) {
706 synchronized (mLock) {
707 checkNotReleasedLocked();
708 int err = nativeAttachAndQueueBuffer(mNativeObject, buffer);
709 if (err != 0) {
710 throw new RuntimeException(
711 "Failed to attach and queue buffer to Surface (bad object?)");
712 }
713 }
714 }
715
716 /**
Pablo Ceballosaff2f942016-07-29 14:49:55 -0700717 * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
718 * @hide
719 */
720 public boolean isSingleBuffered() {
721 return mIsSingleBuffered;
722 }
723
724 /**
Romain Guy0bbf0b42017-07-20 08:57:07 -0700725 * <p>The shared buffer mode allows both the application and the surface compositor
726 * (SurfaceFlinger) to concurrently access this surface's buffer. While the
727 * application is still required to issue a present request
728 * (see {@link #unlockCanvasAndPost(Canvas)}) to the compositor when an update is required,
729 * the compositor may trigger an update at any time. Since the surface's buffer is shared
730 * between the application and the compositor, updates triggered by the compositor may
731 * cause visible tearing.</p>
732 *
733 * <p>The shared buffer mode can be used with
734 * {@link #setAutoRefreshEnabled(boolean) auto-refresh} to avoid the overhead of
735 * issuing present requests.</p>
736 *
737 * <p>If the application uses the shared buffer mode to reduce latency, it is
738 * recommended to use software rendering (see {@link #lockCanvas(Rect)} to ensure
739 * the graphics workloads are not affected by other applications and/or the system
740 * using the GPU. When using software rendering, the application should update the
741 * smallest possible region of the surface required.</p>
742 *
743 * <p class="note">The shared buffer mode might not be supported by the underlying
744 * hardware. Enabling shared buffer mode on hardware that does not support it will
745 * not yield an error but the application will not benefit from lower latency (and
746 * tearing will not be visible).</p>
747 *
748 * <p class="note">Depending on how many and what kind of surfaces are visible, the
749 * surface compositor may need to copy the shared buffer before it is displayed. When
750 * this happens, the latency benefits of shared buffer mode will be reduced.</p>
751 *
752 * @param enabled True to enable the shared buffer mode on this surface, false otherwise
753 *
754 * @see #isSharedBufferModeEnabled()
755 * @see #setAutoRefreshEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700756 *
757 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700758 */
759 public void setSharedBufferModeEnabled(boolean enabled) {
760 if (mIsSharedBufferModeEnabled != enabled) {
761 int error = nativeSetSharedBufferModeEnabled(mNativeObject, enabled);
762 if (error != 0) {
763 throw new RuntimeException(
764 "Failed to set shared buffer mode on Surface (bad object?)");
765 } else {
766 mIsSharedBufferModeEnabled = enabled;
767 }
768 }
769 }
770
771 /**
772 * @return True if shared buffer mode is enabled on this surface, false otherwise
773 *
774 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700775 *
776 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700777 */
778 public boolean isSharedBufferModeEnabled() {
779 return mIsSharedBufferModeEnabled;
780 }
781
782 /**
783 * <p>When auto-refresh is enabled, the surface compositor (SurfaceFlinger)
784 * automatically updates the display on a regular refresh cycle. The application
785 * can continue to issue present requests but it is not required. Enabling
786 * auto-refresh may result in visible tearing.</p>
787 *
788 * <p>Auto-refresh has no effect if the {@link #setSharedBufferModeEnabled(boolean)
789 * shared buffer mode} is not enabled.</p>
790 *
791 * <p>Because auto-refresh will trigger continuous updates of the display, it is
792 * recommended to turn it on only when necessary. For example, in a drawing/painting
793 * application auto-refresh should be enabled on finger/pen down and disabled on
794 * finger/pen up.</p>
795 *
796 * @param enabled True to enable auto-refresh on this surface, false otherwise
797 *
798 * @see #isAutoRefreshEnabled()
799 * @see #setSharedBufferModeEnabled(boolean)
Romain Guy010f0822017-08-16 09:43:07 -0700800 *
801 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700802 */
803 public void setAutoRefreshEnabled(boolean enabled) {
804 if (mIsAutoRefreshEnabled != enabled) {
805 int error = nativeSetAutoRefreshEnabled(mNativeObject, enabled);
806 if (error != 0) {
807 throw new RuntimeException("Failed to set auto refresh on Surface (bad object?)");
808 } else {
809 mIsAutoRefreshEnabled = enabled;
810 }
811 }
812 }
813
814 /**
815 * @return True if auto-refresh is enabled on this surface, false otherwise
Romain Guy010f0822017-08-16 09:43:07 -0700816 *
817 * @hide
Romain Guy0bbf0b42017-07-20 08:57:07 -0700818 */
819 public boolean isAutoRefreshEnabled() {
820 return mIsAutoRefreshEnabled;
821 }
822
823 /**
Igor Murashkina86ab6402013-08-30 12:58:36 -0700824 * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
825 * when a SurfaceTexture could not successfully be allocated.
Jeff Brown64a55af2012-08-26 02:47:39 -0700826 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700827 @SuppressWarnings("serial")
828 public static class OutOfResourcesException extends RuntimeException {
Jeff Brown64a55af2012-08-26 02:47:39 -0700829 public OutOfResourcesException() {
830 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700831 public OutOfResourcesException(String name) {
832 super(name);
833 }
834 }
835
836 /**
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700837 * Returns a human readable representation of a rotation.
838 *
839 * @param rotation The rotation.
840 * @return The rotation symbolic name.
Svetoslav Ganov545252f2012-12-10 18:29:24 -0800841 *
842 * @hide
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700843 */
844 public static String rotationToString(int rotation) {
845 switch (rotation) {
846 case Surface.ROTATION_0: {
847 return "ROTATION_0";
848 }
849 case Surface.ROTATION_90: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700850 return "ROTATION_90";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700851 }
852 case Surface.ROTATION_180: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700853 return "ROTATION_180";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700854 }
855 case Surface.ROTATION_270: {
Romain Guy0bbf0b42017-07-20 08:57:07 -0700856 return "ROTATION_270";
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700857 }
858 default: {
Michael Wright19859762017-09-18 20:57:58 +0100859 return Integer.toString(rotation);
Svetoslav Ganov152e9bb2012-10-12 20:15:29 -0700860 }
861 }
862 }
863
864 /**
Jeff Brown64a55af2012-08-26 02:47:39 -0700865 * A Canvas class that can handle the compatibility mode.
866 * This does two things differently.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700867 * <ul>
Mathias Agopianb9230662011-08-03 14:44:48 -0700868 * <li>Returns the width and height of the target metrics, rather than
869 * native. For example, the canvas returns 320x480 even if an app is running
870 * in WVGA high density.
871 * <li>Scales the matrix in setMatrix by the application scale, except if
872 * the matrix looks like obtained from getMatrix. This is a hack to handle
873 * the case that an application uses getMatrix to keep the original matrix,
874 * set matrix of its own, then set the original matrix back. There is no
875 * perfect solution that works for all cases, and there are a lot of cases
876 * that this model does not work, but we hope this works for many apps.
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700877 * </ul>
878 */
Jeff Brown64a55af2012-08-26 02:47:39 -0700879 private final class CompatibleCanvas extends Canvas {
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700880 // A temp matrix to remember what an application obtained via {@link getMatrix}
881 private Matrix mOrigMatrix = null;
882
883 @Override
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700884 public void setMatrix(Matrix matrix) {
885 if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
886 // don't scale the matrix if it's not compatibility mode, or
887 // the matrix was obtained from getMatrix.
888 super.setMatrix(matrix);
889 } else {
890 Matrix m = new Matrix(mCompatibleMatrix);
891 m.preConcat(matrix);
892 super.setMatrix(m);
893 }
894 }
895
Romain Guy8b5aa482013-02-28 18:13:54 -0800896 @SuppressWarnings("deprecation")
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700897 @Override
898 public void getMatrix(Matrix m) {
899 super.getMatrix(m);
900 if (mOrigMatrix == null) {
Andy McFaddened55c8d2013-08-20 10:05:51 -0700901 mOrigMatrix = new Matrix();
Mitsuru Oshima240f8a72009-07-22 20:39:14 -0700902 }
903 mOrigMatrix.set(m);
904 }
Romain Guyd10cd572010-10-10 13:33:22 -0700905 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700906
907 private final class HwuiContext {
908 private final RenderNode mRenderNode;
909 private long mHwuiRenderer;
John Reck32f140aa62018-10-04 15:08:24 -0700910 private RecordingCanvas mCanvas;
Peiyong Lind8b68712018-03-06 18:34:21 -0800911 private final boolean mIsWideColorGamut;
John Reckbb2d0cc2014-10-21 10:09:36 -0700912
Peiyong Lind8b68712018-03-06 18:34:21 -0800913 HwuiContext(boolean isWideColorGamut) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700914 mRenderNode = RenderNode.create("HwuiCanvas", null);
915 mRenderNode.setClipToBounds(false);
John Recka2d20b42018-10-01 12:21:55 -0700916 mRenderNode.setForceDarkAllowed(false);
Peiyong Lind8b68712018-03-06 18:34:21 -0800917 mIsWideColorGamut = isWideColorGamut;
918 mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject,
919 isWideColorGamut);
John Reckbb2d0cc2014-10-21 10:09:36 -0700920 }
921
John Reckb35c9602014-11-13 16:15:08 -0800922 Canvas lockCanvas(int width, int height) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700923 if (mCanvas != null) {
924 throw new IllegalStateException("Surface was already locked!");
925 }
John Recke57475e2019-02-20 17:39:52 -0800926 mCanvas = mRenderNode.beginRecording(width, height);
John Reckbb2d0cc2014-10-21 10:09:36 -0700927 return mCanvas;
928 }
929
930 void unlockAndPost(Canvas canvas) {
931 if (canvas != mCanvas) {
932 throw new IllegalArgumentException("canvas object must be the same instance that "
933 + "was previously returned by lockCanvas");
934 }
John Recke57475e2019-02-20 17:39:52 -0800935 mRenderNode.endRecording();
John Reckbb2d0cc2014-10-21 10:09:36 -0700936 mCanvas = null;
937 nHwuiDraw(mHwuiRenderer);
938 }
939
940 void updateSurface() {
941 nHwuiSetSurface(mHwuiRenderer, mNativeObject);
942 }
943
944 void destroy() {
945 if (mHwuiRenderer != 0) {
946 nHwuiDestroy(mHwuiRenderer);
947 mHwuiRenderer = 0;
948 }
949 }
Peiyong Lind8b68712018-03-06 18:34:21 -0800950
951 boolean isWideColorGamut() {
952 return mIsWideColorGamut;
953 }
John Reckbb2d0cc2014-10-21 10:09:36 -0700954 }
955
Peiyong Lind8b68712018-03-06 18:34:21 -0800956 private static native long nHwuiCreate(long rootNode, long surface, boolean isWideColorGamut);
John Reckbb2d0cc2014-10-21 10:09:36 -0700957 private static native void nHwuiSetSurface(long renderer, long surface);
958 private static native void nHwuiDraw(long renderer);
959 private static native void nHwuiDestroy(long renderer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960}