blob: 14a324dc3abed3cd3bc6d239de44d5aca022f4cf [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;
Issei Suzuki93593562019-06-27 12:29:30 +020020import android.annotation.Nullable;
John Reckb8802b12014-06-16 15:28:50 -070021import android.content.Context;
Alan Viverette58c42c32014-07-12 20:33:45 -070022import android.content.res.TypedArray;
John Reck8785ceb2018-10-29 16:45:58 -070023import android.graphics.HardwareRenderer;
John Reck5cca8f22018-12-10 17:06:22 -080024import android.graphics.Picture;
Alan Viverette50210d92015-05-14 18:05:36 -070025import android.graphics.Point;
John Reck32f140aa62018-10-04 15:08:24 -070026import android.graphics.RecordingCanvas;
Alan Viveretteccb11e12014-07-08 16:04:02 -070027import android.graphics.Rect;
John Reck32f140aa62018-10-04 15:08:24 -070028import android.graphics.RenderNode;
Jaesung Chung9a89d832017-05-16 01:54:17 +090029import android.os.SystemProperties;
John Reckcec24ae2013-11-05 13:27:50 -080030import android.os.Trace;
John Reck59dd2ea2019-07-26 16:51:08 -070031import android.util.Log;
John Reckcec24ae2013-11-05 13:27:50 -080032import android.view.Surface.OutOfResourcesException;
33import android.view.View.AttachInfo;
Mihai Popa4bcd4d402018-02-07 17:13:51 +000034import android.view.animation.AnimationUtils;
John Reckcec24ae2013-11-05 13:27:50 -080035
John Reckba6adf62015-02-19 14:36:50 -080036import com.android.internal.R;
37
John Reckfe5e7b72014-05-23 17:42:28 -070038import java.io.FileDescriptor;
John Reckcec24ae2013-11-05 13:27:50 -080039import java.io.PrintWriter;
Issei Suzuki93593562019-06-27 12:29:30 +020040import java.util.ArrayList;
John Reckcec24ae2013-11-05 13:27:50 -080041
42/**
Stan Iliev45faba52016-06-28 13:33:15 -040043 * Threaded renderer that proxies the rendering to a render thread. Most calls
John Reck4f02bf42014-01-03 18:09:17 -080044 * are currently synchronous.
John Reckcec24ae2013-11-05 13:27:50 -080045 *
46 * The UI thread can block on the RenderThread, but RenderThread must never
47 * block on the UI thread.
48 *
John Reck4f02bf42014-01-03 18:09:17 -080049 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
50 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
51 * by the lifecycle of the RenderProxy.
52 *
John Reckcec24ae2013-11-05 13:27:50 -080053 * Note that although currently the EGL context & surfaces are created & managed
54 * by the render thread, the goal is to move that into a shared structure that can
55 * be managed by both threads. EGLSurface creation & deletion should ideally be
56 * done on the UI thread and not the RenderThread to avoid stalling the
57 * RenderThread with surface buffer allocation.
58 *
59 * @hide
60 */
John Reck8785ceb2018-10-29 16:45:58 -070061public final class ThreadedRenderer extends HardwareRenderer {
John Reck51aaf902015-12-02 15:08:07 -080062 /**
Stan Iliev45faba52016-06-28 13:33:15 -040063 * System property used to enable or disable threaded rendering profiling.
John Reck51aaf902015-12-02 15:08:07 -080064 * The default value of this property is assumed to be false.
65 *
66 * When profiling is enabled, the adb shell dumpsys gfxinfo command will
67 * output extra information about the time taken to execute by the last
68 * frames.
69 *
70 * Possible values:
71 * "true", to enable profiling
72 * "visual_bars", to enable profiling and visualize the results on screen
73 * "false", to disable profiling
74 *
75 * @see #PROFILE_PROPERTY_VISUALIZE_BARS
76 *
77 * @hide
78 */
79 public static final String PROFILE_PROPERTY = "debug.hwui.profile";
80
81 /**
82 * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
83 * value, profiling data will be visualized on screen as a bar chart.
84 *
85 * @hide
86 */
87 public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
88
89 /**
90 * System property used to specify the number of frames to be used
Stan Iliev45faba52016-06-28 13:33:15 -040091 * when doing threaded rendering profiling.
John Reck51aaf902015-12-02 15:08:07 -080092 * The default value of this property is #PROFILE_MAX_FRAMES.
93 *
94 * When profiling is enabled, the adb shell dumpsys gfxinfo command will
95 * output extra information about the time taken to execute by the last
96 * frames.
97 *
98 * Possible values:
99 * "60", to set the limit of frames to 60
100 */
101 static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
102
103 /**
104 * System property used to debug EGL configuration choice.
105 *
106 * Possible values:
107 * "choice", print the chosen configuration only
108 * "all", print all possible configurations
109 */
110 static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
111
112 /**
113 * Turn on to draw dirty regions every other frame.
114 *
115 * Possible values:
116 * "true", to enable dirty regions debugging
117 * "false", to disable dirty regions debugging
118 *
119 * @hide
120 */
121 public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
122
123 /**
124 * Turn on to flash hardware layers when they update.
125 *
126 * Possible values:
127 * "true", to enable hardware layers updates debugging
128 * "false", to disable hardware layers updates debugging
129 *
130 * @hide
131 */
132 public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
133 "debug.hwui.show_layers_updates";
134
135 /**
136 * Controls overdraw debugging.
137 *
138 * Possible values:
139 * "false", to disable overdraw debugging
140 * "show", to show overdraw areas on screen
141 * "count", to display an overdraw counter
142 *
143 * @hide
144 */
145 public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
146
147 /**
148 * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
149 * value, overdraw will be shown on screen by coloring pixels.
150 *
151 * @hide
152 */
153 public static final String OVERDRAW_PROPERTY_SHOW = "show";
154
155 /**
156 * Turn on to debug non-rectangular clip operations.
157 *
158 * Possible values:
159 * "hide", to disable this debug mode
160 * "highlight", highlight drawing commands tested against a non-rectangular clip
161 * "stencil", renders the clip region on screen when set
162 *
163 * @hide
164 */
165 public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
166 "debug.hwui.show_non_rect_clip";
167
John Reck9f516442017-09-25 10:27:21 -0700168 /**
169 * Sets the FPS devisor to lower the FPS.
170 *
171 * Sets a positive integer as a divisor. 1 (the default value) menas the full FPS, and 2
172 * means half the full FPS.
173 *
174 *
175 * @hide
176 */
177 public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
178
John Reckde20c572018-10-26 15:47:55 -0700179 /**
180 * Forces smart-dark to be always on.
181 * @hide
182 */
John Reck0b5db0e2019-05-02 12:59:40 -0700183 public static final String DEBUG_FORCE_DARK = "debug.hwui.force_dark";
John Reckde20c572018-10-26 15:47:55 -0700184
Jorim Jaggi767e25e2018-04-04 23:07:35 +0200185 public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
186 public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
187 public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
188
Jaesung Chung9a89d832017-05-16 01:54:17 +0900189 static {
190 // Try to check OpenGL support early if possible.
191 isAvailable();
192 }
193
John Reck51aaf902015-12-02 15:08:07 -0800194 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400195 * A process can set this flag to false to prevent the use of threaded
John Reck51aaf902015-12-02 15:08:07 -0800196 * rendering.
197 *
198 * @hide
199 */
200 public static boolean sRendererDisabled = false;
201
202 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400203 * Further threaded renderer disabling for the system process.
John Reck51aaf902015-12-02 15:08:07 -0800204 *
205 * @hide
206 */
207 public static boolean sSystemRendererDisabled = false;
208
209 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400210 * Invoke this method to disable threaded rendering in the current process.
John Reck51aaf902015-12-02 15:08:07 -0800211 *
212 * @hide
213 */
214 public static void disable(boolean system) {
215 sRendererDisabled = true;
216 if (system) {
217 sSystemRendererDisabled = true;
218 }
219 }
220
221 public static boolean sTrimForeground = false;
222
223 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400224 * Controls whether or not the renderer should aggressively trim
225 * memory. Note that this must not be set for any process that uses
226 * WebView! This should be only used by system_process or similar
John Reck51aaf902015-12-02 15:08:07 -0800227 * that do not go into the background.
228 */
229 public static void enableForegroundTrimming() {
230 sTrimForeground = true;
231 }
232
Derek Sollenbergerf64c34e2016-06-28 16:39:13 -0400233
John Reck51aaf902015-12-02 15:08:07 -0800234 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400235 * Indicates whether threaded rendering is available under any form for
John Reck51aaf902015-12-02 15:08:07 -0800236 * the view hierarchy.
237 *
Stan Iliev45faba52016-06-28 13:33:15 -0400238 * @return True if the view hierarchy can potentially be defer rendered,
John Reck51aaf902015-12-02 15:08:07 -0800239 * false otherwise
240 */
241 public static boolean isAvailable() {
bohu677595f2019-08-25 19:15:31 -0700242 return true;
John Reck51aaf902015-12-02 15:08:07 -0800243 }
244
245 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400246 * Creates a threaded renderer using OpenGL.
John Reck51aaf902015-12-02 15:08:07 -0800247 *
248 * @param translucent True if the surface is translucent, false otherwise
249 *
Stan Iliev45faba52016-06-28 13:33:15 -0400250 * @return A threaded renderer backed by OpenGL.
John Reck51aaf902015-12-02 15:08:07 -0800251 */
John Reckdf1742e2017-01-19 15:56:21 -0800252 public static ThreadedRenderer create(Context context, boolean translucent, String name) {
John Reck51aaf902015-12-02 15:08:07 -0800253 ThreadedRenderer renderer = null;
Derek Sollenbergerf64c34e2016-06-28 16:39:13 -0400254 if (isAvailable()) {
John Reckdf1742e2017-01-19 15:56:21 -0800255 renderer = new ThreadedRenderer(context, translucent, name);
John Reck51aaf902015-12-02 15:08:07 -0800256 }
257 return renderer;
258 }
259
John Reckfe5e7b72014-05-23 17:42:28 -0700260 private static final String[] VISUALIZERS = {
261 PROFILE_PROPERTY_VISUALIZE_BARS,
262 };
263
Alan Viveretteccb11e12014-07-08 16:04:02 -0700264 // Size of the rendered content.
John Reckcec24ae2013-11-05 13:27:50 -0800265 private int mWidth, mHeight;
Alan Viveretteccb11e12014-07-08 16:04:02 -0700266
267 // Actual size of the drawing surface.
268 private int mSurfaceWidth, mSurfaceHeight;
269
270 // Insets between the drawing surface and rendered content. These are
271 // applied as translation when updating the root render node.
272 private int mInsetTop, mInsetLeft;
273
John Reck8785ceb2018-10-29 16:45:58 -0700274 // Light properties specified by the theme.
Alan Viverette58c42c32014-07-12 20:33:45 -0700275 private final float mLightY;
276 private final float mLightZ;
277 private final float mLightRadius;
Alan Viverette58c42c32014-07-12 20:33:45 -0700278
John Reckf7d9c1d2014-04-09 10:01:03 -0700279 private boolean mInitialized = false;
John Reck0a973302014-07-16 13:29:45 -0700280 private boolean mRootNodeNeedsUpdate;
John Reckcec24ae2013-11-05 13:27:50 -0800281
John Reck51aaf902015-12-02 15:08:07 -0800282 private boolean mEnabled;
283 private boolean mRequested = true;
284
Issei Suzuki93593562019-06-27 12:29:30 +0200285 @Nullable
286 private ArrayList<FrameDrawingCallback> mNextRtFrameCallbacks;
Winson Chungf2131112018-12-10 16:11:28 -0800287
John Reckdf1742e2017-01-19 15:56:21 -0800288 ThreadedRenderer(Context context, boolean translucent, String name) {
John Reck8785ceb2018-10-29 16:45:58 -0700289 super();
290 setName(name);
291 setOpaque(!translucent);
292
Alan Viveretteed6f14a2014-08-26 14:53:28 -0700293 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
Alan Viverette58c42c32014-07-12 20:33:45 -0700294 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
295 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
296 mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
John Reck8785ceb2018-10-29 16:45:58 -0700297 float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
298 float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
Alan Viverette58c42c32014-07-12 20:33:45 -0700299 a.recycle();
John Reck8785ceb2018-10-29 16:45:58 -0700300 setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
John Reckcec24ae2013-11-05 13:27:50 -0800301 }
302
John Reck8785ceb2018-10-29 16:45:58 -0700303 @Override
304 public void destroy() {
John Reckf7d9c1d2014-04-09 10:01:03 -0700305 mInitialized = false;
306 updateEnabledState(null);
John Reck8785ceb2018-10-29 16:45:58 -0700307 super.destroy();
John Reckcec24ae2013-11-05 13:27:50 -0800308 }
309
John Reck51aaf902015-12-02 15:08:07 -0800310 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400311 * Indicates whether threaded rendering is currently enabled.
John Reck51aaf902015-12-02 15:08:07 -0800312 *
Stan Iliev45faba52016-06-28 13:33:15 -0400313 * @return True if threaded rendering is in use, false otherwise.
John Reck51aaf902015-12-02 15:08:07 -0800314 */
315 boolean isEnabled() {
316 return mEnabled;
317 }
318
319 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400320 * Indicates whether threaded rendering is currently enabled.
John Reck51aaf902015-12-02 15:08:07 -0800321 *
Stan Iliev45faba52016-06-28 13:33:15 -0400322 * @param enabled True if the threaded renderer is in use, false otherwise.
John Reck51aaf902015-12-02 15:08:07 -0800323 */
324 void setEnabled(boolean enabled) {
325 mEnabled = enabled;
326 }
327
328 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400329 * Indicates whether threaded rendering is currently request but not
John Reck51aaf902015-12-02 15:08:07 -0800330 * necessarily enabled yet.
331 *
332 * @return True if requested, false otherwise.
333 */
334 boolean isRequested() {
335 return mRequested;
336 }
337
338 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400339 * Indicates whether threaded rendering is currently requested but not
John Reck51aaf902015-12-02 15:08:07 -0800340 * necessarily enabled yet.
John Reck51aaf902015-12-02 15:08:07 -0800341 */
342 void setRequested(boolean requested) {
343 mRequested = requested;
344 }
345
John Reckf7d9c1d2014-04-09 10:01:03 -0700346 private void updateEnabledState(Surface surface) {
347 if (surface == null || !surface.isValid()) {
348 setEnabled(false);
349 } else {
350 setEnabled(mInitialized);
351 }
352 }
353
John Reck51aaf902015-12-02 15:08:07 -0800354 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400355 * Initializes the threaded renderer for the specified surface.
John Reck51aaf902015-12-02 15:08:07 -0800356 *
Stan Iliev45faba52016-06-28 13:33:15 -0400357 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800358 *
359 * @return True if the initialization was successful, false otherwise.
360 */
John Reckcec24ae2013-11-05 13:27:50 -0800361 boolean initialize(Surface surface) throws OutOfResourcesException {
Thomas Buhot0bcd0cb2015-12-04 12:18:03 +0100362 boolean status = !mInitialized;
John Reckf7d9c1d2014-04-09 10:01:03 -0700363 mInitialized = true;
364 updateEnabledState(surface);
John Reck8785ceb2018-10-29 16:45:58 -0700365 setSurface(surface);
Dan Stoza5795d642014-06-20 13:01:36 -0700366 return status;
John Reckcec24ae2013-11-05 13:27:50 -0800367 }
368
John Reck51aaf902015-12-02 15:08:07 -0800369 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400370 * Initializes the threaded renderer for the specified surface and setup the
John Reck51aaf902015-12-02 15:08:07 -0800371 * renderer for drawing, if needed. This is invoked when the ViewAncestor has
Stan Iliev45faba52016-06-28 13:33:15 -0400372 * potentially lost the threaded renderer. The threaded renderer should be
John Reck51aaf902015-12-02 15:08:07 -0800373 * reinitialized and setup when the render {@link #isRequested()} and
374 * {@link #isEnabled()}.
375 *
376 * @param width The width of the drawing surface.
377 * @param height The height of the drawing surface.
378 * @param attachInfo Information about the window.
Stan Iliev45faba52016-06-28 13:33:15 -0400379 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800380 * @param surfaceInsets The drawing surface insets to apply
381 *
382 * @return true if the surface was initialized, false otherwise. Returning
383 * false might mean that the surface was already initialized.
384 */
385 boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
386 Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
387 if (isRequested()) {
388 // We lost the gl context, so recreate it.
389 if (!isEnabled()) {
390 if (initialize(surface)) {
391 setup(width, height, attachInfo, surfaceInsets);
392 return true;
393 }
394 }
395 }
396 return false;
397 }
398
399 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400400 * Updates the threaded renderer for the specified surface.
John Reck51aaf902015-12-02 15:08:07 -0800401 *
Stan Iliev45faba52016-06-28 13:33:15 -0400402 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800403 */
John Reckcec24ae2013-11-05 13:27:50 -0800404 void updateSurface(Surface surface) throws OutOfResourcesException {
John Reckf7d9c1d2014-04-09 10:01:03 -0700405 updateEnabledState(surface);
John Reck8785ceb2018-10-29 16:45:58 -0700406 setSurface(surface);
John Reckcec24ae2013-11-05 13:27:50 -0800407 }
408
John Reck8785ceb2018-10-29 16:45:58 -0700409 @Override
410 public void setSurface(Surface surface) {
411 // TODO: Do we ever pass a non-null but isValid() = false surface?
412 // This is here to be super conservative for ViewRootImpl
413 if (surface != null && surface.isValid()) {
414 super.setSurface(surface);
415 } else {
416 super.setSurface(null);
417 }
John Reck8afcc762016-04-13 10:24:06 -0700418 }
419
420 /**
Winson Chungf2131112018-12-10 16:11:28 -0800421 * Registers a callback to be executed when the next frame is being drawn on RenderThread. This
422 * callback will be executed on a RenderThread worker thread, and only used for the next frame
423 * and thus it will only fire once.
424 *
425 * @param callback The callback to register.
426 */
Issei Suzuki93593562019-06-27 12:29:30 +0200427 void registerRtFrameCallback(@NonNull FrameDrawingCallback callback) {
428 if (mNextRtFrameCallbacks == null) {
429 mNextRtFrameCallbacks = new ArrayList<>();
430 }
431 mNextRtFrameCallbacks.add(callback);
Winson Chungf2131112018-12-10 16:11:28 -0800432 }
433
434 /**
John Reck51aaf902015-12-02 15:08:07 -0800435 * Destroys all hardware rendering resources associated with the specified
436 * view hierarchy.
437 *
438 * @param view The root of the view hierarchy
439 */
John Reckcec24ae2013-11-05 13:27:50 -0800440 void destroyHardwareResources(View view) {
John Reck4f02bf42014-01-03 18:09:17 -0800441 destroyResources(view);
John Reckfe5dfca2019-01-17 17:01:32 -0800442 clearContent();
John Reck4f02bf42014-01-03 18:09:17 -0800443 }
444
445 private static void destroyResources(View view) {
446 view.destroyHardwareResources();
John Reckcec24ae2013-11-05 13:27:50 -0800447 }
448
John Reck51aaf902015-12-02 15:08:07 -0800449 /**
John Reck51aaf902015-12-02 15:08:07 -0800450 * Sets up the renderer for drawing.
451 *
452 * @param width The width of the drawing surface.
453 * @param height The height of the drawing surface.
454 * @param attachInfo Information about the window.
455 * @param surfaceInsets The drawing surface insets to apply
456 */
Alan Viverette50210d92015-05-14 18:05:36 -0700457 void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
John Reckcec24ae2013-11-05 13:27:50 -0800458 mWidth = width;
459 mHeight = height;
Alan Viverette50210d92015-05-14 18:05:36 -0700460
Alan Viverette3aa1ffb2014-10-30 12:22:08 -0700461 if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
462 || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
Alan Viveretteccb11e12014-07-08 16:04:02 -0700463 mInsetLeft = surfaceInsets.left;
464 mInsetTop = surfaceInsets.top;
465 mSurfaceWidth = width + mInsetLeft + surfaceInsets.right;
466 mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom;
Alan Viverette57774a82014-07-15 15:49:55 -0700467
468 // If the surface has insets, it can't be opaque.
469 setOpaque(false);
Alan Viveretteccb11e12014-07-08 16:04:02 -0700470 } else {
471 mInsetLeft = 0;
472 mInsetTop = 0;
473 mSurfaceWidth = width;
474 mSurfaceHeight = height;
475 }
Alan Viverette50210d92015-05-14 18:05:36 -0700476
Alan Viveretteccb11e12014-07-08 16:04:02 -0700477 mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
Alan Viverette50210d92015-05-14 18:05:36 -0700478
479 setLightCenter(attachInfo);
480 }
481
John Reck51aaf902015-12-02 15:08:07 -0800482 /**
483 * Updates the light position based on the position of the window.
484 *
485 * @param attachInfo Information about the window.
486 */
Alan Viverette50210d92015-05-14 18:05:36 -0700487 void setLightCenter(AttachInfo attachInfo) {
488 // Adjust light position for window offsets.
489 final Point displaySize = attachInfo.mPoint;
490 attachInfo.mDisplay.getRealSize(displaySize);
491 final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
492 final float lightY = mLightY - attachInfo.mWindowTop;
John Reck8785ceb2018-10-29 16:45:58 -0700493 setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
Romain Guy26a2b972017-04-17 09:39:51 -0700494 }
495
496 /**
John Reck51aaf902015-12-02 15:08:07 -0800497 * Gets the current width of the surface. This is the width that the surface
498 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
499 *
500 * @return the current width of the surface
501 */
John Reckcec24ae2013-11-05 13:27:50 -0800502 int getWidth() {
503 return mWidth;
504 }
505
John Reck51aaf902015-12-02 15:08:07 -0800506 /**
507 * Gets the current height of the surface. This is the height that the surface
508 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
509 *
510 * @return the current width of the surface
511 */
John Reckcec24ae2013-11-05 13:27:50 -0800512 int getHeight() {
513 return mHeight;
514 }
515
John Reck51aaf902015-12-02 15:08:07 -0800516 /**
517 * Outputs extra debugging information in the specified file descriptor.
518 */
John Reckba6adf62015-02-19 14:36:50 -0800519 void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
John Reckfe5e7b72014-05-23 17:42:28 -0700520 pw.flush();
John Reck184264d2018-02-12 16:21:21 -0800521 // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
522 // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
523 // dump the summary information
524 int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
John Reckba6adf62015-02-19 14:36:50 -0800525 for (int i = 0; i < args.length; i++) {
526 switch (args[i]) {
527 case "framestats":
528 flags |= FLAG_DUMP_FRAMESTATS;
529 break;
530 case "reset":
531 flags |= FLAG_DUMP_RESET;
532 break;
John Reck184264d2018-02-12 16:21:21 -0800533 case "-a": // magic option passed when dumping a bugreport.
534 flags = FLAG_DUMP_ALL;
535 break;
John Reckba6adf62015-02-19 14:36:50 -0800536 }
John Reckfe5e7b72014-05-23 17:42:28 -0700537 }
John Reck8785ceb2018-10-29 16:45:58 -0700538 dumpProfileInfo(fd, flags);
John Reckcec24ae2013-11-05 13:27:50 -0800539 }
540
John Reck5cca8f22018-12-10 17:06:22 -0800541 Picture captureRenderingCommands() {
542 return null;
543 }
544
John Reck8785ceb2018-10-29 16:45:58 -0700545 @Override
546 public boolean loadSystemProperties() {
547 boolean changed = super.loadSystemProperties();
John Reck23d307c2014-10-27 12:38:48 -0700548 if (changed) {
549 invalidateRoot();
550 }
John Reckfe5e7b72014-05-23 17:42:28 -0700551 return changed;
John Reckcec24ae2013-11-05 13:27:50 -0800552 }
553
John Reck0a973302014-07-16 13:29:45 -0700554 private void updateViewTreeDisplayList(View view) {
John Reckcec24ae2013-11-05 13:27:50 -0800555 view.mPrivateFlags |= View.PFLAG_DRAWN;
John Reckcec24ae2013-11-05 13:27:50 -0800556 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
557 == View.PFLAG_INVALIDATED;
558 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
Chris Craik31a2d062015-05-01 14:22:47 -0700559 view.updateDisplayListIfDirty();
John Reckcec24ae2013-11-05 13:27:50 -0800560 view.mRecreateDisplayList = false;
John Reckbc0cc022014-04-11 16:08:14 -0700561 }
562
Stan Iliev45faba52016-06-28 13:33:15 -0400563 private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
Chris Craik70850ea2014-11-18 10:49:23 -0800564 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
John Reck0a973302014-07-16 13:29:45 -0700565 updateViewTreeDisplayList(view);
566
Winson Chungf2131112018-12-10 16:11:28 -0800567 // Consume and set the frame callback after we dispatch draw to the view above, but before
568 // onPostDraw below which may reset the callback for the next frame. This ensures that
569 // updates to the frame callback during scroll handling will also apply in this frame.
Issei Suzuki93593562019-06-27 12:29:30 +0200570 if (mNextRtFrameCallbacks != null) {
571 final ArrayList<FrameDrawingCallback> frameCallbacks = mNextRtFrameCallbacks;
572 mNextRtFrameCallbacks = null;
573 setFrameCallback(frame -> {
574 for (int i = 0; i < frameCallbacks.size(); ++i) {
575 frameCallbacks.get(i).onFrameDraw(frame);
576 }
577 });
Winson Chungf2131112018-12-10 16:11:28 -0800578 }
579
John Reckc7ddcf32018-10-25 13:56:17 -0700580 if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
John Recke57475e2019-02-20 17:39:52 -0800581 RecordingCanvas canvas = mRootNode.beginRecording(mSurfaceWidth, mSurfaceHeight);
John Reck0a973302014-07-16 13:29:45 -0700582 try {
Alan Viverettedbed8932014-08-06 17:54:52 -0700583 final int saveCount = canvas.save();
John Reck0a973302014-07-16 13:29:45 -0700584 canvas.translate(mInsetLeft, mInsetTop);
Stan Iliev45faba52016-06-28 13:33:15 -0400585 callbacks.onPreDraw(canvas);
Chris Craikabedca32014-08-28 15:03:55 -0700586
John Reck8785ceb2018-10-29 16:45:58 -0700587 canvas.enableZ();
Chris Craik31a2d062015-05-01 14:22:47 -0700588 canvas.drawRenderNode(view.updateDisplayListIfDirty());
John Reck8785ceb2018-10-29 16:45:58 -0700589 canvas.disableZ();
Chris Craikabedca32014-08-28 15:03:55 -0700590
Stan Iliev45faba52016-06-28 13:33:15 -0400591 callbacks.onPostDraw(canvas);
Alan Viverettedbed8932014-08-06 17:54:52 -0700592 canvas.restoreToCount(saveCount);
John Reck0a973302014-07-16 13:29:45 -0700593 mRootNodeNeedsUpdate = false;
594 } finally {
John Reck8785ceb2018-10-29 16:45:58 -0700595 mRootNode.endRecording();
John Reck0a973302014-07-16 13:29:45 -0700596 }
597 }
598 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
599 }
600
Skuhneea7a7fb2015-08-28 07:10:31 -0700601 /**
John Reck51aaf902015-12-02 15:08:07 -0800602 * Interface used to receive callbacks whenever a view is drawn by
Stan Iliev45faba52016-06-28 13:33:15 -0400603 * a threaded renderer instance.
John Reck51aaf902015-12-02 15:08:07 -0800604 */
Stan Iliev45faba52016-06-28 13:33:15 -0400605 interface DrawCallbacks {
John Reck51aaf902015-12-02 15:08:07 -0800606 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400607 * Invoked before a view is drawn by a threaded renderer.
John Reck51aaf902015-12-02 15:08:07 -0800608 * This method can be used to apply transformations to the
609 * canvas but no drawing command should be issued.
610 *
611 * @param canvas The Canvas used to render the view.
612 */
John Reck32f140aa62018-10-04 15:08:24 -0700613 void onPreDraw(RecordingCanvas canvas);
John Reck51aaf902015-12-02 15:08:07 -0800614
615 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400616 * Invoked after a view is drawn by a threaded renderer.
John Reck51aaf902015-12-02 15:08:07 -0800617 * It is safe to invoke drawing commands from this method.
618 *
619 * @param canvas The Canvas used to render the view.
620 */
John Reck32f140aa62018-10-04 15:08:24 -0700621 void onPostDraw(RecordingCanvas canvas);
John Reck51aaf902015-12-02 15:08:07 -0800622 }
623
624 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400625 * Indicates that the content drawn by DrawCallbacks needs to
John Reck51aaf902015-12-02 15:08:07 -0800626 * be updated, which will be done by the next call to draw()
627 */
John Reck0a973302014-07-16 13:29:45 -0700628 void invalidateRoot() {
629 mRootNodeNeedsUpdate = true;
630 }
631
John Reck51aaf902015-12-02 15:08:07 -0800632 /**
633 * Draws the specified view.
634 *
635 * @param view The view to draw.
636 * @param attachInfo AttachInfo tied to the specified view.
John Reck51aaf902015-12-02 15:08:07 -0800637 */
Winson Chungf2131112018-12-10 16:11:28 -0800638 void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
John Reckba6adf62015-02-19 14:36:50 -0800639 final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
640 choreographer.mFrameInfo.markDrawStart();
John Reckfe5e7b72014-05-23 17:42:28 -0700641
John Reck61375a82014-09-18 19:27:48 +0000642 updateRootDisplayList(view, callbacks);
John Reckcec24ae2013-11-05 13:27:50 -0800643
John Reck119907c2014-08-14 09:02:01 -0700644 // register animating rendernodes which started animating prior to renderer
645 // creation, which is typical for animators started prior to first draw
646 if (attachInfo.mPendingAnimatingRenderNodes != null) {
647 final int count = attachInfo.mPendingAnimatingRenderNodes.size();
648 for (int i = 0; i < count; i++) {
649 registerAnimatingRenderNode(
650 attachInfo.mPendingAnimatingRenderNodes.get(i));
651 }
652 attachInfo.mPendingAnimatingRenderNodes.clear();
653 // We don't need this anymore as subsequent calls to
654 // ViewRootImpl#attachRenderNodeAnimator will go directly to us.
655 attachInfo.mPendingAnimatingRenderNodes = null;
656 }
657
John Reck8785ceb2018-10-29 16:45:58 -0700658 int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
John Reckaa95a882014-11-07 11:02:07 -0800659 if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
John Reck59dd2ea2019-07-26 16:51:08 -0700660 Log.w("OpenGLRenderer", "Surface lost, forcing relayout");
661 // We lost our surface. For a relayout next frame which should give us a new
662 // surface from WindowManager, which hopefully will work.
663 attachInfo.mViewRootImpl.mForceNextWindowRelayout = true;
664 attachInfo.mViewRootImpl.requestLayout();
John Reckaa95a882014-11-07 11:02:07 -0800665 }
John Reck8785ceb2018-10-29 16:45:58 -0700666 if ((syncResult & SYNC_REDRAW_REQUESTED) != 0) {
John Reckf9be7792014-05-02 18:21:16 -0700667 attachInfo.mViewRootImpl.invalidate();
668 }
John Reckcec24ae2013-11-05 13:27:50 -0800669 }
670
John Reckbb3a3582018-09-26 11:21:08 -0700671 /** The root of everything */
672 public @NonNull RenderNode getRootNode() {
673 return mRootNode;
674 }
675
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000676 /**
677 * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
678 * TODO: deduplicate against ThreadedRenderer.
679 *
680 * @hide
681 */
John Reck8785ceb2018-10-29 16:45:58 -0700682 public static class SimpleRenderer extends HardwareRenderer {
683 private final float mLightY, mLightZ, mLightRadius;
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000684
685 public SimpleRenderer(final Context context, final String name, final Surface surface) {
John Reck8785ceb2018-10-29 16:45:58 -0700686 super();
687 setName(name);
688 setOpaque(false);
689 setSurface(surface);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000690 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
691 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
692 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
John Reck8785ceb2018-10-29 16:45:58 -0700693 mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
Mihai Popa6dcd7282018-11-13 13:25:02 +0000694 final float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
695 final float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000696 a.recycle();
John Reck8785ceb2018-10-29 16:45:58 -0700697 setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000698 }
699
700 /**
701 * Set the light center.
702 */
703 public void setLightCenter(final Display display,
704 final int windowLeft, final int windowTop) {
705 // Adjust light position for window offsets.
706 final Point displaySize = new Point();
707 display.getRealSize(displaySize);
708 final float lightX = displaySize.x / 2f - windowLeft;
709 final float lightY = mLightY - windowTop;
710
John Reck8785ceb2018-10-29 16:45:58 -0700711 setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000712 }
713
714 public RenderNode getRootNode() {
715 return mRootNode;
716 }
717
718 /**
719 * Draw the surface.
720 */
721 public void draw(final FrameDrawingCallback callback) {
722 final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000723 if (callback != null) {
John Reck8785ceb2018-10-29 16:45:58 -0700724 setFrameCallback(callback);
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000725 }
John Reckfe5dfca2019-01-17 17:01:32 -0800726 createRenderRequest()
727 .setVsyncTime(vsync)
728 .syncAndDraw();
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000729 }
730 }
John Reckcec24ae2013-11-05 13:27:50 -0800731}