blob: 3d3d5dc7db325a001ad8e7799d2c65bbafda4f30 [file] [log] [blame]
John Reckcec24ae2013-11-05 13:27:50 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
Chris Craik2507c342015-05-04 14:36:49 -070019import android.annotation.NonNull;
John Reckb8802b12014-06-16 15:28:50 -070020import android.content.Context;
Alan Viverette58c42c32014-07-12 20:33:45 -070021import android.content.res.TypedArray;
John Reck8785ceb2018-10-29 16:45:58 -070022import android.graphics.HardwareRenderer;
John Reck5cca8f22018-12-10 17:06:22 -080023import android.graphics.Picture;
Alan Viverette50210d92015-05-14 18:05:36 -070024import android.graphics.Point;
John Reck32f140aa62018-10-04 15:08:24 -070025import android.graphics.RecordingCanvas;
Alan Viveretteccb11e12014-07-08 16:04:02 -070026import android.graphics.Rect;
John Reck32f140aa62018-10-04 15:08:24 -070027import android.graphics.RenderNode;
Jaesung Chung9a89d832017-05-16 01:54:17 +090028import android.os.SystemProperties;
John Reckcec24ae2013-11-05 13:27:50 -080029import android.os.Trace;
John Reckcec24ae2013-11-05 13:27:50 -080030import android.view.Surface.OutOfResourcesException;
31import android.view.View.AttachInfo;
Mihai Popa4bcd4d402018-02-07 17:13:51 +000032import android.view.animation.AnimationUtils;
John Reckcec24ae2013-11-05 13:27:50 -080033
John Reckba6adf62015-02-19 14:36:50 -080034import com.android.internal.R;
35
John Reckfe5e7b72014-05-23 17:42:28 -070036import java.io.FileDescriptor;
John Reckcec24ae2013-11-05 13:27:50 -080037import java.io.PrintWriter;
John Reckcec24ae2013-11-05 13:27:50 -080038
39/**
Stan Iliev45faba52016-06-28 13:33:15 -040040 * Threaded renderer that proxies the rendering to a render thread. Most calls
John Reck4f02bf42014-01-03 18:09:17 -080041 * are currently synchronous.
John Reckcec24ae2013-11-05 13:27:50 -080042 *
43 * The UI thread can block on the RenderThread, but RenderThread must never
44 * block on the UI thread.
45 *
John Reck4f02bf42014-01-03 18:09:17 -080046 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
47 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
48 * by the lifecycle of the RenderProxy.
49 *
John Reckcec24ae2013-11-05 13:27:50 -080050 * Note that although currently the EGL context & surfaces are created & managed
51 * by the render thread, the goal is to move that into a shared structure that can
52 * be managed by both threads. EGLSurface creation & deletion should ideally be
53 * done on the UI thread and not the RenderThread to avoid stalling the
54 * RenderThread with surface buffer allocation.
55 *
56 * @hide
57 */
John Reck8785ceb2018-10-29 16:45:58 -070058public final class ThreadedRenderer extends HardwareRenderer {
John Reck51aaf902015-12-02 15:08:07 -080059 /**
Stan Iliev45faba52016-06-28 13:33:15 -040060 * System property used to enable or disable threaded rendering profiling.
John Reck51aaf902015-12-02 15:08:07 -080061 * The default value of this property is assumed to be false.
62 *
63 * When profiling is enabled, the adb shell dumpsys gfxinfo command will
64 * output extra information about the time taken to execute by the last
65 * frames.
66 *
67 * Possible values:
68 * "true", to enable profiling
69 * "visual_bars", to enable profiling and visualize the results on screen
70 * "false", to disable profiling
71 *
72 * @see #PROFILE_PROPERTY_VISUALIZE_BARS
73 *
74 * @hide
75 */
76 public static final String PROFILE_PROPERTY = "debug.hwui.profile";
77
78 /**
79 * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
80 * value, profiling data will be visualized on screen as a bar chart.
81 *
82 * @hide
83 */
84 public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
85
86 /**
87 * System property used to specify the number of frames to be used
Stan Iliev45faba52016-06-28 13:33:15 -040088 * when doing threaded rendering profiling.
John Reck51aaf902015-12-02 15:08:07 -080089 * The default value of this property is #PROFILE_MAX_FRAMES.
90 *
91 * When profiling is enabled, the adb shell dumpsys gfxinfo command will
92 * output extra information about the time taken to execute by the last
93 * frames.
94 *
95 * Possible values:
96 * "60", to set the limit of frames to 60
97 */
98 static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
99
100 /**
101 * System property used to debug EGL configuration choice.
102 *
103 * Possible values:
104 * "choice", print the chosen configuration only
105 * "all", print all possible configurations
106 */
107 static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
108
109 /**
110 * Turn on to draw dirty regions every other frame.
111 *
112 * Possible values:
113 * "true", to enable dirty regions debugging
114 * "false", to disable dirty regions debugging
115 *
116 * @hide
117 */
118 public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
119
120 /**
121 * Turn on to flash hardware layers when they update.
122 *
123 * Possible values:
124 * "true", to enable hardware layers updates debugging
125 * "false", to disable hardware layers updates debugging
126 *
127 * @hide
128 */
129 public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
130 "debug.hwui.show_layers_updates";
131
132 /**
133 * Controls overdraw debugging.
134 *
135 * Possible values:
136 * "false", to disable overdraw debugging
137 * "show", to show overdraw areas on screen
138 * "count", to display an overdraw counter
139 *
140 * @hide
141 */
142 public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
143
144 /**
145 * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
146 * value, overdraw will be shown on screen by coloring pixels.
147 *
148 * @hide
149 */
150 public static final String OVERDRAW_PROPERTY_SHOW = "show";
151
152 /**
153 * Turn on to debug non-rectangular clip operations.
154 *
155 * Possible values:
156 * "hide", to disable this debug mode
157 * "highlight", highlight drawing commands tested against a non-rectangular clip
158 * "stencil", renders the clip region on screen when set
159 *
160 * @hide
161 */
162 public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
163 "debug.hwui.show_non_rect_clip";
164
John Reck9f516442017-09-25 10:27:21 -0700165 /**
166 * Sets the FPS devisor to lower the FPS.
167 *
168 * Sets a positive integer as a divisor. 1 (the default value) menas the full FPS, and 2
169 * means half the full FPS.
170 *
171 *
172 * @hide
173 */
174 public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
175
John Reckde20c572018-10-26 15:47:55 -0700176 /**
177 * Forces smart-dark to be always on.
178 * @hide
179 */
John Reck0b5db0e2019-05-02 12:59:40 -0700180 public static final String DEBUG_FORCE_DARK = "debug.hwui.force_dark";
John Reckde20c572018-10-26 15:47:55 -0700181
Jorim Jaggi767e25e2018-04-04 23:07:35 +0200182 public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
183 public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
184 public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
185
Jaesung Chung9a89d832017-05-16 01:54:17 +0900186 static {
187 // Try to check OpenGL support early if possible.
188 isAvailable();
189 }
190
John Reck51aaf902015-12-02 15:08:07 -0800191 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400192 * A process can set this flag to false to prevent the use of threaded
John Reck51aaf902015-12-02 15:08:07 -0800193 * rendering.
194 *
195 * @hide
196 */
197 public static boolean sRendererDisabled = false;
198
199 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400200 * Further threaded renderer disabling for the system process.
John Reck51aaf902015-12-02 15:08:07 -0800201 *
202 * @hide
203 */
204 public static boolean sSystemRendererDisabled = false;
205
206 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400207 * Invoke this method to disable threaded rendering in the current process.
John Reck51aaf902015-12-02 15:08:07 -0800208 *
209 * @hide
210 */
211 public static void disable(boolean system) {
212 sRendererDisabled = true;
213 if (system) {
214 sSystemRendererDisabled = true;
215 }
216 }
217
218 public static boolean sTrimForeground = false;
219
220 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400221 * Controls whether or not the renderer should aggressively trim
222 * memory. Note that this must not be set for any process that uses
223 * WebView! This should be only used by system_process or similar
John Reck51aaf902015-12-02 15:08:07 -0800224 * that do not go into the background.
225 */
226 public static void enableForegroundTrimming() {
227 sTrimForeground = true;
228 }
229
Jaesung Chung9a89d832017-05-16 01:54:17 +0900230 private static Boolean sSupportsOpenGL;
Derek Sollenbergerf64c34e2016-06-28 16:39:13 -0400231
John Reck51aaf902015-12-02 15:08:07 -0800232 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400233 * Indicates whether threaded rendering is available under any form for
John Reck51aaf902015-12-02 15:08:07 -0800234 * the view hierarchy.
235 *
Stan Iliev45faba52016-06-28 13:33:15 -0400236 * @return True if the view hierarchy can potentially be defer rendered,
John Reck51aaf902015-12-02 15:08:07 -0800237 * false otherwise
238 */
239 public static boolean isAvailable() {
Jaesung Chung9a89d832017-05-16 01:54:17 +0900240 if (sSupportsOpenGL != null) {
241 return sSupportsOpenGL.booleanValue();
242 }
243 if (SystemProperties.getInt("ro.kernel.qemu", 0) == 0) {
244 // Device is not an emulator.
245 sSupportsOpenGL = true;
246 return true;
247 }
248 int qemu_gles = SystemProperties.getInt("qemu.gles", -1);
249 if (qemu_gles == -1) {
250 // In this case, the value of the qemu.gles property is not ready
251 // because the SurfaceFlinger service may not start at this point.
252 return false;
253 }
254 // In the emulator this property will be set > 0 when OpenGL ES 2.0 is
255 // enabled, 0 otherwise. On old emulator versions it will be undefined.
256 sSupportsOpenGL = qemu_gles > 0;
257 return sSupportsOpenGL.booleanValue();
John Reck51aaf902015-12-02 15:08:07 -0800258 }
259
260 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400261 * Creates a threaded renderer using OpenGL.
John Reck51aaf902015-12-02 15:08:07 -0800262 *
263 * @param translucent True if the surface is translucent, false otherwise
264 *
Stan Iliev45faba52016-06-28 13:33:15 -0400265 * @return A threaded renderer backed by OpenGL.
John Reck51aaf902015-12-02 15:08:07 -0800266 */
John Reckdf1742e2017-01-19 15:56:21 -0800267 public static ThreadedRenderer create(Context context, boolean translucent, String name) {
John Reck51aaf902015-12-02 15:08:07 -0800268 ThreadedRenderer renderer = null;
Derek Sollenbergerf64c34e2016-06-28 16:39:13 -0400269 if (isAvailable()) {
John Reckdf1742e2017-01-19 15:56:21 -0800270 renderer = new ThreadedRenderer(context, translucent, name);
John Reck51aaf902015-12-02 15:08:07 -0800271 }
272 return renderer;
273 }
274
John Reckfe5e7b72014-05-23 17:42:28 -0700275 private static final String[] VISUALIZERS = {
276 PROFILE_PROPERTY_VISUALIZE_BARS,
277 };
278
Alan Viveretteccb11e12014-07-08 16:04:02 -0700279 // Size of the rendered content.
John Reckcec24ae2013-11-05 13:27:50 -0800280 private int mWidth, mHeight;
Alan Viveretteccb11e12014-07-08 16:04:02 -0700281
282 // Actual size of the drawing surface.
283 private int mSurfaceWidth, mSurfaceHeight;
284
285 // Insets between the drawing surface and rendered content. These are
286 // applied as translation when updating the root render node.
287 private int mInsetTop, mInsetLeft;
288
Alan Viverette57774a82014-07-15 15:49:55 -0700289 // Whether the surface has insets. Used to protect opacity.
290 private boolean mHasInsets;
291
John Reck8785ceb2018-10-29 16:45:58 -0700292 // Light properties specified by the theme.
Alan Viverette58c42c32014-07-12 20:33:45 -0700293 private final float mLightY;
294 private final float mLightZ;
295 private final float mLightRadius;
Alan Viverette58c42c32014-07-12 20:33:45 -0700296
John Reckf7d9c1d2014-04-09 10:01:03 -0700297 private boolean mInitialized = false;
John Reck0a973302014-07-16 13:29:45 -0700298 private boolean mRootNodeNeedsUpdate;
John Reckcec24ae2013-11-05 13:27:50 -0800299
John Reck51aaf902015-12-02 15:08:07 -0800300 private boolean mEnabled;
301 private boolean mRequested = true;
302
Winson Chungf2131112018-12-10 16:11:28 -0800303 private FrameDrawingCallback mNextRtFrameCallback;
304
John Reckdf1742e2017-01-19 15:56:21 -0800305 ThreadedRenderer(Context context, boolean translucent, String name) {
John Reck8785ceb2018-10-29 16:45:58 -0700306 super();
307 setName(name);
308 setOpaque(!translucent);
309
Alan Viveretteed6f14a2014-08-26 14:53:28 -0700310 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
Alan Viverette58c42c32014-07-12 20:33:45 -0700311 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
312 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
313 mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
John Reck8785ceb2018-10-29 16:45:58 -0700314 float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
315 float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
Alan Viverette58c42c32014-07-12 20:33:45 -0700316 a.recycle();
John Reck8785ceb2018-10-29 16:45:58 -0700317 setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
John Reckcec24ae2013-11-05 13:27:50 -0800318 }
319
John Reck8785ceb2018-10-29 16:45:58 -0700320 @Override
321 public void destroy() {
John Reckf7d9c1d2014-04-09 10:01:03 -0700322 mInitialized = false;
323 updateEnabledState(null);
John Reck8785ceb2018-10-29 16:45:58 -0700324 super.destroy();
John Reckcec24ae2013-11-05 13:27:50 -0800325 }
326
John Reck51aaf902015-12-02 15:08:07 -0800327 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400328 * Indicates whether threaded rendering is currently enabled.
John Reck51aaf902015-12-02 15:08:07 -0800329 *
Stan Iliev45faba52016-06-28 13:33:15 -0400330 * @return True if threaded rendering is in use, false otherwise.
John Reck51aaf902015-12-02 15:08:07 -0800331 */
332 boolean isEnabled() {
333 return mEnabled;
334 }
335
336 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400337 * Indicates whether threaded rendering is currently enabled.
John Reck51aaf902015-12-02 15:08:07 -0800338 *
Stan Iliev45faba52016-06-28 13:33:15 -0400339 * @param enabled True if the threaded renderer is in use, false otherwise.
John Reck51aaf902015-12-02 15:08:07 -0800340 */
341 void setEnabled(boolean enabled) {
342 mEnabled = enabled;
343 }
344
345 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400346 * Indicates whether threaded rendering is currently request but not
John Reck51aaf902015-12-02 15:08:07 -0800347 * necessarily enabled yet.
348 *
349 * @return True if requested, false otherwise.
350 */
351 boolean isRequested() {
352 return mRequested;
353 }
354
355 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400356 * Indicates whether threaded rendering is currently requested but not
John Reck51aaf902015-12-02 15:08:07 -0800357 * necessarily enabled yet.
John Reck51aaf902015-12-02 15:08:07 -0800358 */
359 void setRequested(boolean requested) {
360 mRequested = requested;
361 }
362
John Reckf7d9c1d2014-04-09 10:01:03 -0700363 private void updateEnabledState(Surface surface) {
364 if (surface == null || !surface.isValid()) {
365 setEnabled(false);
366 } else {
367 setEnabled(mInitialized);
368 }
369 }
370
John Reck51aaf902015-12-02 15:08:07 -0800371 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400372 * Initializes the threaded renderer for the specified surface.
John Reck51aaf902015-12-02 15:08:07 -0800373 *
Stan Iliev45faba52016-06-28 13:33:15 -0400374 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800375 *
376 * @return True if the initialization was successful, false otherwise.
377 */
John Reckcec24ae2013-11-05 13:27:50 -0800378 boolean initialize(Surface surface) throws OutOfResourcesException {
Thomas Buhot0bcd0cb2015-12-04 12:18:03 +0100379 boolean status = !mInitialized;
John Reckf7d9c1d2014-04-09 10:01:03 -0700380 mInitialized = true;
381 updateEnabledState(surface);
John Reck8785ceb2018-10-29 16:45:58 -0700382 setSurface(surface);
Dan Stoza5795d642014-06-20 13:01:36 -0700383 return status;
John Reckcec24ae2013-11-05 13:27:50 -0800384 }
385
John Reck51aaf902015-12-02 15:08:07 -0800386 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400387 * Initializes the threaded renderer for the specified surface and setup the
John Reck51aaf902015-12-02 15:08:07 -0800388 * renderer for drawing, if needed. This is invoked when the ViewAncestor has
Stan Iliev45faba52016-06-28 13:33:15 -0400389 * potentially lost the threaded renderer. The threaded renderer should be
John Reck51aaf902015-12-02 15:08:07 -0800390 * reinitialized and setup when the render {@link #isRequested()} and
391 * {@link #isEnabled()}.
392 *
393 * @param width The width of the drawing surface.
394 * @param height The height of the drawing surface.
395 * @param attachInfo Information about the window.
Stan Iliev45faba52016-06-28 13:33:15 -0400396 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800397 * @param surfaceInsets The drawing surface insets to apply
398 *
399 * @return true if the surface was initialized, false otherwise. Returning
400 * false might mean that the surface was already initialized.
401 */
402 boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
403 Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
404 if (isRequested()) {
405 // We lost the gl context, so recreate it.
406 if (!isEnabled()) {
407 if (initialize(surface)) {
408 setup(width, height, attachInfo, surfaceInsets);
409 return true;
410 }
411 }
412 }
413 return false;
414 }
415
416 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400417 * Updates the threaded renderer for the specified surface.
John Reck51aaf902015-12-02 15:08:07 -0800418 *
Stan Iliev45faba52016-06-28 13:33:15 -0400419 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800420 */
John Reckcec24ae2013-11-05 13:27:50 -0800421 void updateSurface(Surface surface) throws OutOfResourcesException {
John Reckf7d9c1d2014-04-09 10:01:03 -0700422 updateEnabledState(surface);
John Reck8785ceb2018-10-29 16:45:58 -0700423 setSurface(surface);
John Reckcec24ae2013-11-05 13:27:50 -0800424 }
425
John Reck8785ceb2018-10-29 16:45:58 -0700426 @Override
427 public void setSurface(Surface surface) {
428 // TODO: Do we ever pass a non-null but isValid() = false surface?
429 // This is here to be super conservative for ViewRootImpl
430 if (surface != null && surface.isValid()) {
431 super.setSurface(surface);
432 } else {
433 super.setSurface(null);
434 }
John Reck8afcc762016-04-13 10:24:06 -0700435 }
436
437 /**
Winson Chungf2131112018-12-10 16:11:28 -0800438 * Registers a callback to be executed when the next frame is being drawn on RenderThread. This
439 * callback will be executed on a RenderThread worker thread, and only used for the next frame
440 * and thus it will only fire once.
441 *
442 * @param callback The callback to register.
443 */
444 void registerRtFrameCallback(FrameDrawingCallback callback) {
445 mNextRtFrameCallback = callback;
446 }
447
448 /**
John Reck51aaf902015-12-02 15:08:07 -0800449 * Destroys all hardware rendering resources associated with the specified
450 * view hierarchy.
451 *
452 * @param view The root of the view hierarchy
453 */
John Reckcec24ae2013-11-05 13:27:50 -0800454 void destroyHardwareResources(View view) {
John Reck4f02bf42014-01-03 18:09:17 -0800455 destroyResources(view);
John Reckfe5dfca2019-01-17 17:01:32 -0800456 clearContent();
John Reck4f02bf42014-01-03 18:09:17 -0800457 }
458
459 private static void destroyResources(View view) {
460 view.destroyHardwareResources();
John Reckcec24ae2013-11-05 13:27:50 -0800461 }
462
John Reck51aaf902015-12-02 15:08:07 -0800463 /**
John Reck51aaf902015-12-02 15:08:07 -0800464 * Sets up the renderer for drawing.
465 *
466 * @param width The width of the drawing surface.
467 * @param height The height of the drawing surface.
468 * @param attachInfo Information about the window.
469 * @param surfaceInsets The drawing surface insets to apply
470 */
Alan Viverette50210d92015-05-14 18:05:36 -0700471 void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
John Reckcec24ae2013-11-05 13:27:50 -0800472 mWidth = width;
473 mHeight = height;
Alan Viverette50210d92015-05-14 18:05:36 -0700474
Alan Viverette3aa1ffb2014-10-30 12:22:08 -0700475 if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
476 || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
Alan Viverette57774a82014-07-15 15:49:55 -0700477 mHasInsets = true;
Alan Viveretteccb11e12014-07-08 16:04:02 -0700478 mInsetLeft = surfaceInsets.left;
479 mInsetTop = surfaceInsets.top;
480 mSurfaceWidth = width + mInsetLeft + surfaceInsets.right;
481 mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom;
Alan Viverette57774a82014-07-15 15:49:55 -0700482
483 // If the surface has insets, it can't be opaque.
484 setOpaque(false);
Alan Viveretteccb11e12014-07-08 16:04:02 -0700485 } else {
Alan Viverette57774a82014-07-15 15:49:55 -0700486 mHasInsets = false;
Alan Viveretteccb11e12014-07-08 16:04:02 -0700487 mInsetLeft = 0;
488 mInsetTop = 0;
489 mSurfaceWidth = width;
490 mSurfaceHeight = height;
491 }
Alan Viverette50210d92015-05-14 18:05:36 -0700492
Alan Viveretteccb11e12014-07-08 16:04:02 -0700493 mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
Alan Viverette50210d92015-05-14 18:05:36 -0700494
495 setLightCenter(attachInfo);
496 }
497
John Reck51aaf902015-12-02 15:08:07 -0800498 /**
499 * Updates the light position based on the position of the window.
500 *
501 * @param attachInfo Information about the window.
502 */
Alan Viverette50210d92015-05-14 18:05:36 -0700503 void setLightCenter(AttachInfo attachInfo) {
504 // Adjust light position for window offsets.
505 final Point displaySize = attachInfo.mPoint;
506 attachInfo.mDisplay.getRealSize(displaySize);
507 final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
508 final float lightY = mLightY - attachInfo.mWindowTop;
John Reck8785ceb2018-10-29 16:45:58 -0700509 setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
Romain Guy26a2b972017-04-17 09:39:51 -0700510 }
511
512 /**
John Reck51aaf902015-12-02 15:08:07 -0800513 * Gets the current width of the surface. This is the width that the surface
514 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
515 *
516 * @return the current width of the surface
517 */
John Reckcec24ae2013-11-05 13:27:50 -0800518 int getWidth() {
519 return mWidth;
520 }
521
John Reck51aaf902015-12-02 15:08:07 -0800522 /**
523 * Gets the current height of the surface. This is the height that the surface
524 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
525 *
526 * @return the current width of the surface
527 */
John Reckcec24ae2013-11-05 13:27:50 -0800528 int getHeight() {
529 return mHeight;
530 }
531
John Reck51aaf902015-12-02 15:08:07 -0800532 /**
533 * Outputs extra debugging information in the specified file descriptor.
534 */
John Reckba6adf62015-02-19 14:36:50 -0800535 void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
John Reckfe5e7b72014-05-23 17:42:28 -0700536 pw.flush();
John Reck184264d2018-02-12 16:21:21 -0800537 // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
538 // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
539 // dump the summary information
540 int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
John Reckba6adf62015-02-19 14:36:50 -0800541 for (int i = 0; i < args.length; i++) {
542 switch (args[i]) {
543 case "framestats":
544 flags |= FLAG_DUMP_FRAMESTATS;
545 break;
546 case "reset":
547 flags |= FLAG_DUMP_RESET;
548 break;
John Reck184264d2018-02-12 16:21:21 -0800549 case "-a": // magic option passed when dumping a bugreport.
550 flags = FLAG_DUMP_ALL;
551 break;
John Reckba6adf62015-02-19 14:36:50 -0800552 }
John Reckfe5e7b72014-05-23 17:42:28 -0700553 }
John Reck8785ceb2018-10-29 16:45:58 -0700554 dumpProfileInfo(fd, flags);
John Reckcec24ae2013-11-05 13:27:50 -0800555 }
556
John Reck5cca8f22018-12-10 17:06:22 -0800557 Picture captureRenderingCommands() {
558 return null;
559 }
560
John Reck8785ceb2018-10-29 16:45:58 -0700561 @Override
562 public boolean loadSystemProperties() {
563 boolean changed = super.loadSystemProperties();
John Reck23d307c2014-10-27 12:38:48 -0700564 if (changed) {
565 invalidateRoot();
566 }
John Reckfe5e7b72014-05-23 17:42:28 -0700567 return changed;
John Reckcec24ae2013-11-05 13:27:50 -0800568 }
569
John Reck0a973302014-07-16 13:29:45 -0700570 private void updateViewTreeDisplayList(View view) {
John Reckcec24ae2013-11-05 13:27:50 -0800571 view.mPrivateFlags |= View.PFLAG_DRAWN;
John Reckcec24ae2013-11-05 13:27:50 -0800572 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
573 == View.PFLAG_INVALIDATED;
574 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
Chris Craik31a2d062015-05-01 14:22:47 -0700575 view.updateDisplayListIfDirty();
John Reckcec24ae2013-11-05 13:27:50 -0800576 view.mRecreateDisplayList = false;
John Reckbc0cc022014-04-11 16:08:14 -0700577 }
578
Stan Iliev45faba52016-06-28 13:33:15 -0400579 private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
Chris Craik70850ea2014-11-18 10:49:23 -0800580 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
John Reck0a973302014-07-16 13:29:45 -0700581 updateViewTreeDisplayList(view);
582
Winson Chungf2131112018-12-10 16:11:28 -0800583 // Consume and set the frame callback after we dispatch draw to the view above, but before
584 // onPostDraw below which may reset the callback for the next frame. This ensures that
585 // updates to the frame callback during scroll handling will also apply in this frame.
586 final FrameDrawingCallback callback = mNextRtFrameCallback;
587 mNextRtFrameCallback = null;
588 if (callback != null) {
589 setFrameCallback(callback);
590 }
591
John Reckc7ddcf32018-10-25 13:56:17 -0700592 if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
John Recke57475e2019-02-20 17:39:52 -0800593 RecordingCanvas canvas = mRootNode.beginRecording(mSurfaceWidth, mSurfaceHeight);
John Reck0a973302014-07-16 13:29:45 -0700594 try {
Alan Viverettedbed8932014-08-06 17:54:52 -0700595 final int saveCount = canvas.save();
John Reck0a973302014-07-16 13:29:45 -0700596 canvas.translate(mInsetLeft, mInsetTop);
Stan Iliev45faba52016-06-28 13:33:15 -0400597 callbacks.onPreDraw(canvas);
Chris Craikabedca32014-08-28 15:03:55 -0700598
John Reck8785ceb2018-10-29 16:45:58 -0700599 canvas.enableZ();
Chris Craik31a2d062015-05-01 14:22:47 -0700600 canvas.drawRenderNode(view.updateDisplayListIfDirty());
John Reck8785ceb2018-10-29 16:45:58 -0700601 canvas.disableZ();
Chris Craikabedca32014-08-28 15:03:55 -0700602
Stan Iliev45faba52016-06-28 13:33:15 -0400603 callbacks.onPostDraw(canvas);
Alan Viverettedbed8932014-08-06 17:54:52 -0700604 canvas.restoreToCount(saveCount);
John Reck0a973302014-07-16 13:29:45 -0700605 mRootNodeNeedsUpdate = false;
606 } finally {
John Reck8785ceb2018-10-29 16:45:58 -0700607 mRootNode.endRecording();
John Reck0a973302014-07-16 13:29:45 -0700608 }
609 }
610 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
611 }
612
Skuhneea7a7fb2015-08-28 07:10:31 -0700613 /**
John Reck51aaf902015-12-02 15:08:07 -0800614 * Interface used to receive callbacks whenever a view is drawn by
Stan Iliev45faba52016-06-28 13:33:15 -0400615 * a threaded renderer instance.
John Reck51aaf902015-12-02 15:08:07 -0800616 */
Stan Iliev45faba52016-06-28 13:33:15 -0400617 interface DrawCallbacks {
John Reck51aaf902015-12-02 15:08:07 -0800618 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400619 * Invoked before a view is drawn by a threaded renderer.
John Reck51aaf902015-12-02 15:08:07 -0800620 * This method can be used to apply transformations to the
621 * canvas but no drawing command should be issued.
622 *
623 * @param canvas The Canvas used to render the view.
624 */
John Reck32f140aa62018-10-04 15:08:24 -0700625 void onPreDraw(RecordingCanvas canvas);
John Reck51aaf902015-12-02 15:08:07 -0800626
627 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400628 * Invoked after a view is drawn by a threaded renderer.
John Reck51aaf902015-12-02 15:08:07 -0800629 * It is safe to invoke drawing commands from this method.
630 *
631 * @param canvas The Canvas used to render the view.
632 */
John Reck32f140aa62018-10-04 15:08:24 -0700633 void onPostDraw(RecordingCanvas canvas);
John Reck51aaf902015-12-02 15:08:07 -0800634 }
635
636 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400637 * Indicates that the content drawn by DrawCallbacks needs to
John Reck51aaf902015-12-02 15:08:07 -0800638 * be updated, which will be done by the next call to draw()
639 */
John Reck0a973302014-07-16 13:29:45 -0700640 void invalidateRoot() {
641 mRootNodeNeedsUpdate = true;
642 }
643
John Reck51aaf902015-12-02 15:08:07 -0800644 /**
645 * Draws the specified view.
646 *
647 * @param view The view to draw.
648 * @param attachInfo AttachInfo tied to the specified view.
John Reck51aaf902015-12-02 15:08:07 -0800649 */
Winson Chungf2131112018-12-10 16:11:28 -0800650 void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
John Reckba6adf62015-02-19 14:36:50 -0800651 final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
652 choreographer.mFrameInfo.markDrawStart();
John Reckfe5e7b72014-05-23 17:42:28 -0700653
John Reck61375a82014-09-18 19:27:48 +0000654 updateRootDisplayList(view, callbacks);
John Reckcec24ae2013-11-05 13:27:50 -0800655
John Reck119907c2014-08-14 09:02:01 -0700656 // register animating rendernodes which started animating prior to renderer
657 // creation, which is typical for animators started prior to first draw
658 if (attachInfo.mPendingAnimatingRenderNodes != null) {
659 final int count = attachInfo.mPendingAnimatingRenderNodes.size();
660 for (int i = 0; i < count; i++) {
661 registerAnimatingRenderNode(
662 attachInfo.mPendingAnimatingRenderNodes.get(i));
663 }
664 attachInfo.mPendingAnimatingRenderNodes.clear();
665 // We don't need this anymore as subsequent calls to
666 // ViewRootImpl#attachRenderNodeAnimator will go directly to us.
667 attachInfo.mPendingAnimatingRenderNodes = null;
668 }
669
John Reck8785ceb2018-10-29 16:45:58 -0700670 int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
John Reckaa95a882014-11-07 11:02:07 -0800671 if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
672 setEnabled(false);
John Reckb13de072014-11-19 16:33:47 -0800673 attachInfo.mViewRootImpl.mSurface.release();
John Reckaa95a882014-11-07 11:02:07 -0800674 // Invalidate since we failed to draw. This should fetch a Surface
675 // if it is still needed or do nothing if we are no longer drawing
676 attachInfo.mViewRootImpl.invalidate();
677 }
John Reck8785ceb2018-10-29 16:45:58 -0700678 if ((syncResult & SYNC_REDRAW_REQUESTED) != 0) {
John Reckf9be7792014-05-02 18:21:16 -0700679 attachInfo.mViewRootImpl.invalidate();
680 }
John Reckcec24ae2013-11-05 13:27:50 -0800681 }
682
John Reckbb3a3582018-09-26 11:21:08 -0700683 /** The root of everything */
684 public @NonNull RenderNode getRootNode() {
685 return mRootNode;
686 }
687
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000688 /**
689 * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
690 * TODO: deduplicate against ThreadedRenderer.
691 *
692 * @hide
693 */
John Reck8785ceb2018-10-29 16:45:58 -0700694 public static class SimpleRenderer extends HardwareRenderer {
695 private final float mLightY, mLightZ, mLightRadius;
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000696
697 public SimpleRenderer(final Context context, final String name, final Surface surface) {
John Reck8785ceb2018-10-29 16:45:58 -0700698 super();
699 setName(name);
700 setOpaque(false);
701 setSurface(surface);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000702 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
703 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
704 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
John Reck8785ceb2018-10-29 16:45:58 -0700705 mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
Mihai Popa6dcd7282018-11-13 13:25:02 +0000706 final float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
707 final float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000708 a.recycle();
John Reck8785ceb2018-10-29 16:45:58 -0700709 setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000710 }
711
712 /**
713 * Set the light center.
714 */
715 public void setLightCenter(final Display display,
716 final int windowLeft, final int windowTop) {
717 // Adjust light position for window offsets.
718 final Point displaySize = new Point();
719 display.getRealSize(displaySize);
720 final float lightX = displaySize.x / 2f - windowLeft;
721 final float lightY = mLightY - windowTop;
722
John Reck8785ceb2018-10-29 16:45:58 -0700723 setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000724 }
725
726 public RenderNode getRootNode() {
727 return mRootNode;
728 }
729
730 /**
731 * Draw the surface.
732 */
733 public void draw(final FrameDrawingCallback callback) {
734 final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000735 if (callback != null) {
John Reck8785ceb2018-10-29 16:45:58 -0700736 setFrameCallback(callback);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000737 }
John Reckfe5dfca2019-01-17 17:01:32 -0800738 createRenderRequest()
739 .setVsyncTime(vsync)
740 .syncAndDraw();
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000741 }
742 }
John Reckcec24ae2013-11-05 13:27:50 -0800743}