blob: e03f5faa26f2094bcf13944895fe89a6b40e4097 [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
John Reckba6adf62015-02-19 14:36:50 -080019import android.annotation.IntDef;
Chris Craik2507c342015-05-04 14:36:49 -070020import android.annotation.NonNull;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080021import android.app.ActivityManager;
John Reckb8802b12014-06-16 15:28:50 -070022import android.content.Context;
Alan Viverette58c42c32014-07-12 20:33:45 -070023import android.content.res.TypedArray;
John Reck04fc5832014-02-05 16:38:25 -080024import android.graphics.Bitmap;
Alan Viverette50210d92015-05-14 18:05:36 -070025import android.graphics.Point;
Alan Viveretteccb11e12014-07-08 16:04:02 -070026import android.graphics.Rect;
Doris Liu67ce99b2016-05-17 16:50:31 -070027import android.graphics.drawable.AnimatedVectorDrawable;
John Reck66f0be62014-05-13 13:39:31 -070028import android.os.IBinder;
John Reckedc524c2015-03-18 15:24:33 -070029import android.os.ParcelFileDescriptor;
John Reckdf1742e2017-01-19 15:56:21 -080030import android.os.RemoteException;
John Reck66f0be62014-05-13 13:39:31 -070031import android.os.ServiceManager;
Jaesung Chung9a89d832017-05-16 01:54:17 +090032import android.os.SystemProperties;
John Reckcec24ae2013-11-05 13:27:50 -080033import android.os.Trace;
John Reck66f0be62014-05-13 13:39:31 -070034import android.util.Log;
John Reckcec24ae2013-11-05 13:27:50 -080035import android.view.Surface.OutOfResourcesException;
36import android.view.View.AttachInfo;
Mihai Popa4bcd4d402018-02-07 17:13:51 +000037import android.view.animation.AnimationUtils;
John Reckcec24ae2013-11-05 13:27:50 -080038
John Reckba6adf62015-02-19 14:36:50 -080039import com.android.internal.R;
Andres Morales06f5bc72015-12-15 15:21:31 -080040import com.android.internal.util.VirtualRefBasePtr;
John Reckba6adf62015-02-19 14:36:50 -080041
John Reck51aaf902015-12-02 15:08:07 -080042import java.io.File;
John Reckfe5e7b72014-05-23 17:42:28 -070043import java.io.FileDescriptor;
John Reckcec24ae2013-11-05 13:27:50 -080044import java.io.PrintWriter;
John Reckba6adf62015-02-19 14:36:50 -080045import java.lang.annotation.Retention;
46import java.lang.annotation.RetentionPolicy;
John Reckcec24ae2013-11-05 13:27:50 -080047
48/**
Stan Iliev45faba52016-06-28 13:33:15 -040049 * Threaded renderer that proxies the rendering to a render thread. Most calls
John Reck4f02bf42014-01-03 18:09:17 -080050 * are currently synchronous.
John Reckcec24ae2013-11-05 13:27:50 -080051 *
52 * The UI thread can block on the RenderThread, but RenderThread must never
53 * block on the UI thread.
54 *
John Reck4f02bf42014-01-03 18:09:17 -080055 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates
56 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed
57 * by the lifecycle of the RenderProxy.
58 *
John Reckcec24ae2013-11-05 13:27:50 -080059 * Note that although currently the EGL context & surfaces are created & managed
60 * by the render thread, the goal is to move that into a shared structure that can
61 * be managed by both threads. EGLSurface creation & deletion should ideally be
62 * done on the UI thread and not the RenderThread to avoid stalling the
63 * RenderThread with surface buffer allocation.
64 *
65 * @hide
66 */
John Reck51aaf902015-12-02 15:08:07 -080067public final class ThreadedRenderer {
68 private static final String LOG_TAG = "ThreadedRenderer";
69
70 /**
71 * Name of the file that holds the shaders cache.
72 */
73 private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
Stan Ilievd495f432017-10-09 15:49:32 -040074 private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
John Reck51aaf902015-12-02 15:08:07 -080075
76 /**
Stan Iliev45faba52016-06-28 13:33:15 -040077 * System property used to enable or disable threaded rendering profiling.
John Reck51aaf902015-12-02 15:08:07 -080078 * The default value of this property is assumed to be false.
79 *
80 * When profiling is enabled, the adb shell dumpsys gfxinfo command will
81 * output extra information about the time taken to execute by the last
82 * frames.
83 *
84 * Possible values:
85 * "true", to enable profiling
86 * "visual_bars", to enable profiling and visualize the results on screen
87 * "false", to disable profiling
88 *
89 * @see #PROFILE_PROPERTY_VISUALIZE_BARS
90 *
91 * @hide
92 */
93 public static final String PROFILE_PROPERTY = "debug.hwui.profile";
94
95 /**
96 * Value for {@link #PROFILE_PROPERTY}. When the property is set to this
97 * value, profiling data will be visualized on screen as a bar chart.
98 *
99 * @hide
100 */
101 public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
102
103 /**
104 * System property used to specify the number of frames to be used
Stan Iliev45faba52016-06-28 13:33:15 -0400105 * when doing threaded rendering profiling.
John Reck51aaf902015-12-02 15:08:07 -0800106 * The default value of this property is #PROFILE_MAX_FRAMES.
107 *
108 * When profiling is enabled, the adb shell dumpsys gfxinfo command will
109 * output extra information about the time taken to execute by the last
110 * frames.
111 *
112 * Possible values:
113 * "60", to set the limit of frames to 60
114 */
115 static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
116
117 /**
118 * System property used to debug EGL configuration choice.
119 *
120 * Possible values:
121 * "choice", print the chosen configuration only
122 * "all", print all possible configurations
123 */
124 static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
125
126 /**
127 * Turn on to draw dirty regions every other frame.
128 *
129 * Possible values:
130 * "true", to enable dirty regions debugging
131 * "false", to disable dirty regions debugging
132 *
133 * @hide
134 */
135 public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
136
137 /**
138 * Turn on to flash hardware layers when they update.
139 *
140 * Possible values:
141 * "true", to enable hardware layers updates debugging
142 * "false", to disable hardware layers updates debugging
143 *
144 * @hide
145 */
146 public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
147 "debug.hwui.show_layers_updates";
148
149 /**
150 * Controls overdraw debugging.
151 *
152 * Possible values:
153 * "false", to disable overdraw debugging
154 * "show", to show overdraw areas on screen
155 * "count", to display an overdraw counter
156 *
157 * @hide
158 */
159 public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
160
161 /**
162 * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
163 * value, overdraw will be shown on screen by coloring pixels.
164 *
165 * @hide
166 */
167 public static final String OVERDRAW_PROPERTY_SHOW = "show";
168
169 /**
170 * Turn on to debug non-rectangular clip operations.
171 *
172 * Possible values:
173 * "hide", to disable this debug mode
174 * "highlight", highlight drawing commands tested against a non-rectangular clip
175 * "stencil", renders the clip region on screen when set
176 *
177 * @hide
178 */
179 public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
180 "debug.hwui.show_non_rect_clip";
181
John Reck9f516442017-09-25 10:27:21 -0700182 /**
183 * Sets the FPS devisor to lower the FPS.
184 *
185 * Sets a positive integer as a divisor. 1 (the default value) menas the full FPS, and 2
186 * means half the full FPS.
187 *
188 *
189 * @hide
190 */
191 public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
192
Jorim Jaggi767e25e2018-04-04 23:07:35 +0200193 public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
194 public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
195 public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
196
Jaesung Chung9a89d832017-05-16 01:54:17 +0900197 static {
198 // Try to check OpenGL support early if possible.
199 isAvailable();
200 }
201
John Reck51aaf902015-12-02 15:08:07 -0800202 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400203 * A process can set this flag to false to prevent the use of threaded
John Reck51aaf902015-12-02 15:08:07 -0800204 * rendering.
205 *
206 * @hide
207 */
208 public static boolean sRendererDisabled = false;
209
210 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400211 * Further threaded renderer disabling for the system process.
John Reck51aaf902015-12-02 15:08:07 -0800212 *
213 * @hide
214 */
215 public static boolean sSystemRendererDisabled = false;
216
217 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400218 * Invoke this method to disable threaded rendering in the current process.
John Reck51aaf902015-12-02 15:08:07 -0800219 *
220 * @hide
221 */
222 public static void disable(boolean system) {
223 sRendererDisabled = true;
224 if (system) {
225 sSystemRendererDisabled = true;
226 }
227 }
228
229 public static boolean sTrimForeground = false;
230
231 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400232 * Controls whether or not the renderer should aggressively trim
233 * memory. Note that this must not be set for any process that uses
234 * WebView! This should be only used by system_process or similar
John Reck51aaf902015-12-02 15:08:07 -0800235 * that do not go into the background.
236 */
237 public static void enableForegroundTrimming() {
238 sTrimForeground = true;
239 }
240
Jaesung Chung9a89d832017-05-16 01:54:17 +0900241 private static Boolean sSupportsOpenGL;
Derek Sollenbergerf64c34e2016-06-28 16:39:13 -0400242
John Reck51aaf902015-12-02 15:08:07 -0800243 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400244 * Indicates whether threaded rendering is available under any form for
John Reck51aaf902015-12-02 15:08:07 -0800245 * the view hierarchy.
246 *
Stan Iliev45faba52016-06-28 13:33:15 -0400247 * @return True if the view hierarchy can potentially be defer rendered,
John Reck51aaf902015-12-02 15:08:07 -0800248 * false otherwise
249 */
250 public static boolean isAvailable() {
Jaesung Chung9a89d832017-05-16 01:54:17 +0900251 if (sSupportsOpenGL != null) {
252 return sSupportsOpenGL.booleanValue();
253 }
254 if (SystemProperties.getInt("ro.kernel.qemu", 0) == 0) {
255 // Device is not an emulator.
256 sSupportsOpenGL = true;
257 return true;
258 }
259 int qemu_gles = SystemProperties.getInt("qemu.gles", -1);
260 if (qemu_gles == -1) {
261 // In this case, the value of the qemu.gles property is not ready
262 // because the SurfaceFlinger service may not start at this point.
263 return false;
264 }
265 // In the emulator this property will be set > 0 when OpenGL ES 2.0 is
266 // enabled, 0 otherwise. On old emulator versions it will be undefined.
267 sSupportsOpenGL = qemu_gles > 0;
268 return sSupportsOpenGL.booleanValue();
John Reck51aaf902015-12-02 15:08:07 -0800269 }
270
271 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400272 * Sets the directory to use as a persistent storage for threaded rendering
John Reck51aaf902015-12-02 15:08:07 -0800273 * resources.
274 *
275 * @param cacheDir A directory the current process can write to
276 *
277 * @hide
278 */
279 public static void setupDiskCache(File cacheDir) {
Stan Ilievd495f432017-10-09 15:49:32 -0400280 ThreadedRenderer.setupShadersDiskCache(
281 new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
282 new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
John Reck51aaf902015-12-02 15:08:07 -0800283 }
284
285 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400286 * Creates a threaded renderer using OpenGL.
John Reck51aaf902015-12-02 15:08:07 -0800287 *
288 * @param translucent True if the surface is translucent, false otherwise
289 *
Stan Iliev45faba52016-06-28 13:33:15 -0400290 * @return A threaded renderer backed by OpenGL.
John Reck51aaf902015-12-02 15:08:07 -0800291 */
John Reckdf1742e2017-01-19 15:56:21 -0800292 public static ThreadedRenderer create(Context context, boolean translucent, String name) {
John Reck51aaf902015-12-02 15:08:07 -0800293 ThreadedRenderer renderer = null;
Derek Sollenbergerf64c34e2016-06-28 16:39:13 -0400294 if (isAvailable()) {
John Reckdf1742e2017-01-19 15:56:21 -0800295 renderer = new ThreadedRenderer(context, translucent, name);
John Reck51aaf902015-12-02 15:08:07 -0800296 }
297 return renderer;
298 }
299
300 /**
301 * Invoke this method when the system is running out of memory. This
302 * method will attempt to recover as much memory as possible, based on
303 * the specified hint.
304 *
305 * @param level Hint about the amount of memory that should be trimmed,
306 * see {@link android.content.ComponentCallbacks}
307 */
308 public static void trimMemory(int level) {
309 nTrimMemory(level);
310 }
311
312 public static void overrideProperty(@NonNull String name, @NonNull String value) {
313 if (name == null || value == null) {
314 throw new IllegalArgumentException("name and value must be non-null");
315 }
316 nOverrideProperty(name, value);
317 }
318
John Reckf9be7792014-05-02 18:21:16 -0700319 // Keep in sync with DrawFrameTask.h SYNC_* flags
320 // Nothing interesting to report
John Reckcd028f32014-06-24 08:44:29 -0700321 private static final int SYNC_OK = 0;
John Reckf9be7792014-05-02 18:21:16 -0700322 // Needs a ViewRoot invalidate
John Reckcd028f32014-06-24 08:44:29 -0700323 private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
John Reckaa95a882014-11-07 11:02:07 -0800324 // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
325 private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
John Reck9a17da82016-04-18 11:17:52 -0700326 // setStopped is true, drawing is false
327 // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
328 // This flag isn't really used as there's nothing that we care to do
329 // in response, so it really just exists to differentiate from LOST_SURFACE
330 // but possibly both can just be deleted.
331 private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
John Reckf9be7792014-05-02 18:21:16 -0700332
John Reckfe5e7b72014-05-23 17:42:28 -0700333 private static final String[] VISUALIZERS = {
334 PROFILE_PROPERTY_VISUALIZE_BARS,
335 };
336
John Reckba6adf62015-02-19 14:36:50 -0800337 private static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
338 private static final int FLAG_DUMP_RESET = 1 << 1;
John Reck184264d2018-02-12 16:21:21 -0800339 private static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
John Reckba6adf62015-02-19 14:36:50 -0800340
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700341 @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
342 FLAG_DUMP_FRAMESTATS,
343 FLAG_DUMP_RESET
344 })
John Reckba6adf62015-02-19 14:36:50 -0800345 @Retention(RetentionPolicy.SOURCE)
346 public @interface DumpFlags {}
347
Alan Viveretteccb11e12014-07-08 16:04:02 -0700348 // Size of the rendered content.
John Reckcec24ae2013-11-05 13:27:50 -0800349 private int mWidth, mHeight;
Alan Viveretteccb11e12014-07-08 16:04:02 -0700350
351 // Actual size of the drawing surface.
352 private int mSurfaceWidth, mSurfaceHeight;
353
354 // Insets between the drawing surface and rendered content. These are
355 // applied as translation when updating the root render node.
356 private int mInsetTop, mInsetLeft;
357
Alan Viverette57774a82014-07-15 15:49:55 -0700358 // Whether the surface has insets. Used to protect opacity.
359 private boolean mHasInsets;
360
Alan Viverette58c42c32014-07-12 20:33:45 -0700361 // Light and shadow properties specified by the theme.
362 private final float mLightY;
363 private final float mLightZ;
364 private final float mLightRadius;
Chris Craik058fc642014-07-23 18:19:28 -0700365 private final int mAmbientShadowAlpha;
366 private final int mSpotShadowAlpha;
Alan Viverette58c42c32014-07-12 20:33:45 -0700367
John Reck4f02bf42014-01-03 18:09:17 -0800368 private long mNativeProxy;
John Reckf7d9c1d2014-04-09 10:01:03 -0700369 private boolean mInitialized = false;
John Reckbc0cc022014-04-11 16:08:14 -0700370 private RenderNode mRootNode;
John Reck0a973302014-07-16 13:29:45 -0700371 private boolean mRootNodeNeedsUpdate;
John Reckcec24ae2013-11-05 13:27:50 -0800372
John Reck51aaf902015-12-02 15:08:07 -0800373 private boolean mEnabled;
374 private boolean mRequested = true;
John Reck3e04f092017-06-02 15:50:09 -0700375 private boolean mIsOpaque = false;
John Reck51aaf902015-12-02 15:08:07 -0800376
John Reckdf1742e2017-01-19 15:56:21 -0800377 ThreadedRenderer(Context context, boolean translucent, String name) {
Alan Viveretteed6f14a2014-08-26 14:53:28 -0700378 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
Alan Viverette58c42c32014-07-12 20:33:45 -0700379 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
380 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
381 mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
Alan Viveretteed6f14a2014-08-26 14:53:28 -0700382 mAmbientShadowAlpha =
383 (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
384 mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
Alan Viverette58c42c32014-07-12 20:33:45 -0700385 a.recycle();
386
John Recke45b1fd2014-04-15 09:50:16 -0700387 long rootNodePtr = nCreateRootRenderNode();
388 mRootNode = RenderNode.adopt(rootNodePtr);
John Reckbc0cc022014-04-11 16:08:14 -0700389 mRootNode.setClipToBounds(false);
John Reck3e04f092017-06-02 15:50:09 -0700390 mIsOpaque = !translucent;
John Recke45b1fd2014-04-15 09:50:16 -0700391 mNativeProxy = nCreateProxy(translucent, rootNodePtr);
John Reckdf1742e2017-01-19 15:56:21 -0800392 nSetName(mNativeProxy, name);
John Reck18f16e62014-05-02 16:46:41 -0700393
John Reckedc524c2015-03-18 15:24:33 -0700394 ProcessInitializer.sInstance.init(context, mNativeProxy);
John Reck3b202512014-06-23 13:13:08 -0700395
John Reckfe5e7b72014-05-23 17:42:28 -0700396 loadSystemProperties();
John Reckcec24ae2013-11-05 13:27:50 -0800397 }
398
John Reck51aaf902015-12-02 15:08:07 -0800399 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400400 * Destroys the threaded rendering context.
John Reck51aaf902015-12-02 15:08:07 -0800401 */
John Reckf47a5942014-06-30 16:20:04 -0700402 void destroy() {
John Reckf7d9c1d2014-04-09 10:01:03 -0700403 mInitialized = false;
404 updateEnabledState(null);
Doris Liu350e6522016-02-19 14:20:37 -0800405 nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
John Reckcec24ae2013-11-05 13:27:50 -0800406 }
407
John Reck51aaf902015-12-02 15:08:07 -0800408 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400409 * Indicates whether threaded rendering is currently enabled.
John Reck51aaf902015-12-02 15:08:07 -0800410 *
Stan Iliev45faba52016-06-28 13:33:15 -0400411 * @return True if threaded rendering is in use, false otherwise.
John Reck51aaf902015-12-02 15:08:07 -0800412 */
413 boolean isEnabled() {
414 return mEnabled;
415 }
416
417 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400418 * Indicates whether threaded rendering is currently enabled.
John Reck51aaf902015-12-02 15:08:07 -0800419 *
Stan Iliev45faba52016-06-28 13:33:15 -0400420 * @param enabled True if the threaded renderer is in use, false otherwise.
John Reck51aaf902015-12-02 15:08:07 -0800421 */
422 void setEnabled(boolean enabled) {
423 mEnabled = enabled;
424 }
425
426 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400427 * Indicates whether threaded rendering is currently request but not
John Reck51aaf902015-12-02 15:08:07 -0800428 * necessarily enabled yet.
429 *
430 * @return True if requested, false otherwise.
431 */
432 boolean isRequested() {
433 return mRequested;
434 }
435
436 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400437 * Indicates whether threaded rendering is currently requested but not
John Reck51aaf902015-12-02 15:08:07 -0800438 * necessarily enabled yet.
John Reck51aaf902015-12-02 15:08:07 -0800439 */
440 void setRequested(boolean requested) {
441 mRequested = requested;
442 }
443
John Reckf7d9c1d2014-04-09 10:01:03 -0700444 private void updateEnabledState(Surface surface) {
445 if (surface == null || !surface.isValid()) {
446 setEnabled(false);
447 } else {
448 setEnabled(mInitialized);
449 }
450 }
451
John Reck51aaf902015-12-02 15:08:07 -0800452 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400453 * Initializes the threaded renderer for the specified surface.
John Reck51aaf902015-12-02 15:08:07 -0800454 *
Stan Iliev45faba52016-06-28 13:33:15 -0400455 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800456 *
457 * @return True if the initialization was successful, false otherwise.
458 */
John Reckcec24ae2013-11-05 13:27:50 -0800459 boolean initialize(Surface surface) throws OutOfResourcesException {
Thomas Buhot0bcd0cb2015-12-04 12:18:03 +0100460 boolean status = !mInitialized;
John Reckf7d9c1d2014-04-09 10:01:03 -0700461 mInitialized = true;
462 updateEnabledState(surface);
Thomas Buhot0bcd0cb2015-12-04 12:18:03 +0100463 nInitialize(mNativeProxy, surface);
Dan Stoza5795d642014-06-20 13:01:36 -0700464 return status;
John Reckcec24ae2013-11-05 13:27:50 -0800465 }
466
John Reck51aaf902015-12-02 15:08:07 -0800467 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400468 * Initializes the threaded renderer for the specified surface and setup the
John Reck51aaf902015-12-02 15:08:07 -0800469 * renderer for drawing, if needed. This is invoked when the ViewAncestor has
Stan Iliev45faba52016-06-28 13:33:15 -0400470 * potentially lost the threaded renderer. The threaded renderer should be
John Reck51aaf902015-12-02 15:08:07 -0800471 * reinitialized and setup when the render {@link #isRequested()} and
472 * {@link #isEnabled()}.
473 *
474 * @param width The width of the drawing surface.
475 * @param height The height of the drawing surface.
476 * @param attachInfo Information about the window.
Stan Iliev45faba52016-06-28 13:33:15 -0400477 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800478 * @param surfaceInsets The drawing surface insets to apply
479 *
480 * @return true if the surface was initialized, false otherwise. Returning
481 * false might mean that the surface was already initialized.
482 */
483 boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
484 Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
485 if (isRequested()) {
486 // We lost the gl context, so recreate it.
487 if (!isEnabled()) {
488 if (initialize(surface)) {
489 setup(width, height, attachInfo, surfaceInsets);
490 return true;
491 }
492 }
493 }
494 return false;
495 }
496
497 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400498 * Updates the threaded renderer for the specified surface.
John Reck51aaf902015-12-02 15:08:07 -0800499 *
Stan Iliev45faba52016-06-28 13:33:15 -0400500 * @param surface The surface to render
John Reck51aaf902015-12-02 15:08:07 -0800501 */
John Reckcec24ae2013-11-05 13:27:50 -0800502 void updateSurface(Surface surface) throws OutOfResourcesException {
John Reckf7d9c1d2014-04-09 10:01:03 -0700503 updateEnabledState(surface);
John Reck4f02bf42014-01-03 18:09:17 -0800504 nUpdateSurface(mNativeProxy, surface);
John Reckcec24ae2013-11-05 13:27:50 -0800505 }
506
John Reck51aaf902015-12-02 15:08:07 -0800507 /**
John Reck8afcc762016-04-13 10:24:06 -0700508 * Halts any current rendering into the surface. Use this if it is unclear whether
Stan Iliev45faba52016-06-28 13:33:15 -0400509 * or not the surface used by the ThreadedRenderer will be changing. It
John Reck8afcc762016-04-13 10:24:06 -0700510 * Suspends any rendering into the surface, but will not do any destruction.
511 *
512 * Any subsequent draws will override the pause, resuming normal operation.
John Reck51aaf902015-12-02 15:08:07 -0800513 */
John Reck01a5ea32014-12-03 13:01:07 -0800514 boolean pauseSurface(Surface surface) {
515 return nPauseSurface(mNativeProxy, surface);
John Reckf7d9c1d2014-04-09 10:01:03 -0700516 }
517
John Reck51aaf902015-12-02 15:08:07 -0800518 /**
John Reck8afcc762016-04-13 10:24:06 -0700519 * Hard stops or resumes rendering into the surface. This flag is used to
520 * determine whether or not it is safe to use the given surface *at all*
521 */
522 void setStopped(boolean stopped) {
523 nSetStopped(mNativeProxy, stopped);
524 }
525
526 /**
John Reck51aaf902015-12-02 15:08:07 -0800527 * Destroys all hardware rendering resources associated with the specified
528 * view hierarchy.
529 *
530 * @param view The root of the view hierarchy
531 */
John Reckcec24ae2013-11-05 13:27:50 -0800532 void destroyHardwareResources(View view) {
John Reck4f02bf42014-01-03 18:09:17 -0800533 destroyResources(view);
John Reckf47a5942014-06-30 16:20:04 -0700534 nDestroyHardwareResources(mNativeProxy);
John Reck4f02bf42014-01-03 18:09:17 -0800535 }
536
537 private static void destroyResources(View view) {
538 view.destroyHardwareResources();
John Reckcec24ae2013-11-05 13:27:50 -0800539 }
540
John Reck51aaf902015-12-02 15:08:07 -0800541 /**
John Reck51aaf902015-12-02 15:08:07 -0800542 * Detaches the layer's surface texture from the GL context and releases
543 * the texture id
544 */
John Reck918ad522014-06-27 14:45:25 -0700545 void detachSurfaceTexture(long hardwareLayer) {
546 nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
John Reckcec24ae2013-11-05 13:27:50 -0800547 }
548
John Reck51aaf902015-12-02 15:08:07 -0800549 /**
550 * Sets up the renderer for drawing.
551 *
552 * @param width The width of the drawing surface.
553 * @param height The height of the drawing surface.
554 * @param attachInfo Information about the window.
555 * @param surfaceInsets The drawing surface insets to apply
556 */
Alan Viverette50210d92015-05-14 18:05:36 -0700557 void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
John Reckcec24ae2013-11-05 13:27:50 -0800558 mWidth = width;
559 mHeight = height;
Alan Viverette50210d92015-05-14 18:05:36 -0700560
Alan Viverette3aa1ffb2014-10-30 12:22:08 -0700561 if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
562 || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
Alan Viverette57774a82014-07-15 15:49:55 -0700563 mHasInsets = true;
Alan Viveretteccb11e12014-07-08 16:04:02 -0700564 mInsetLeft = surfaceInsets.left;
565 mInsetTop = surfaceInsets.top;
566 mSurfaceWidth = width + mInsetLeft + surfaceInsets.right;
567 mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom;
Alan Viverette57774a82014-07-15 15:49:55 -0700568
569 // If the surface has insets, it can't be opaque.
570 setOpaque(false);
Alan Viveretteccb11e12014-07-08 16:04:02 -0700571 } else {
Alan Viverette57774a82014-07-15 15:49:55 -0700572 mHasInsets = false;
Alan Viveretteccb11e12014-07-08 16:04:02 -0700573 mInsetLeft = 0;
574 mInsetTop = 0;
575 mSurfaceWidth = width;
576 mSurfaceHeight = height;
577 }
Alan Viverette50210d92015-05-14 18:05:36 -0700578
Alan Viveretteccb11e12014-07-08 16:04:02 -0700579 mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
John Reckab1080c2016-06-21 16:24:20 -0700580 nSetup(mNativeProxy, mLightRadius,
John Reckb36016c2015-03-11 08:50:53 -0700581 mAmbientShadowAlpha, mSpotShadowAlpha);
Alan Viverette50210d92015-05-14 18:05:36 -0700582
583 setLightCenter(attachInfo);
584 }
585
John Reck51aaf902015-12-02 15:08:07 -0800586 /**
587 * Updates the light position based on the position of the window.
588 *
589 * @param attachInfo Information about the window.
590 */
Alan Viverette50210d92015-05-14 18:05:36 -0700591 void setLightCenter(AttachInfo attachInfo) {
592 // Adjust light position for window offsets.
593 final Point displaySize = attachInfo.mPoint;
594 attachInfo.mDisplay.getRealSize(displaySize);
595 final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
596 final float lightY = mLightY - attachInfo.mWindowTop;
597
598 nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
John Reckcec24ae2013-11-05 13:27:50 -0800599 }
600
John Reck51aaf902015-12-02 15:08:07 -0800601 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400602 * Change the ThreadedRenderer's opacity
John Reck51aaf902015-12-02 15:08:07 -0800603 */
John Reck63a06672014-05-07 13:45:54 -0700604 void setOpaque(boolean opaque) {
John Reck3e04f092017-06-02 15:50:09 -0700605 mIsOpaque = opaque && !mHasInsets;
606 nSetOpaque(mNativeProxy, mIsOpaque);
607 }
608
609 boolean isOpaque() {
610 return mIsOpaque;
John Reck63a06672014-05-07 13:45:54 -0700611 }
612
John Reck51aaf902015-12-02 15:08:07 -0800613 /**
Romain Guy26a2b972017-04-17 09:39:51 -0700614 * Enable/disable wide gamut rendering on this renderer.
615 */
616 void setWideGamut(boolean wideGamut) {
617 nSetWideGamut(mNativeProxy, wideGamut);
618 }
619
620 /**
John Reck51aaf902015-12-02 15:08:07 -0800621 * Gets the current width of the surface. This is the width that the surface
622 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
623 *
624 * @return the current width of the surface
625 */
John Reckcec24ae2013-11-05 13:27:50 -0800626 int getWidth() {
627 return mWidth;
628 }
629
John Reck51aaf902015-12-02 15:08:07 -0800630 /**
631 * Gets the current height of the surface. This is the height that the surface
632 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
633 *
634 * @return the current width of the surface
635 */
John Reckcec24ae2013-11-05 13:27:50 -0800636 int getHeight() {
637 return mHeight;
638 }
639
John Reck51aaf902015-12-02 15:08:07 -0800640 /**
641 * Outputs extra debugging information in the specified file descriptor.
642 */
John Reckba6adf62015-02-19 14:36:50 -0800643 void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
John Reckfe5e7b72014-05-23 17:42:28 -0700644 pw.flush();
John Reck184264d2018-02-12 16:21:21 -0800645 // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
646 // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
647 // dump the summary information
648 int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
John Reckba6adf62015-02-19 14:36:50 -0800649 for (int i = 0; i < args.length; i++) {
650 switch (args[i]) {
651 case "framestats":
652 flags |= FLAG_DUMP_FRAMESTATS;
653 break;
654 case "reset":
655 flags |= FLAG_DUMP_RESET;
656 break;
John Reck184264d2018-02-12 16:21:21 -0800657 case "-a": // magic option passed when dumping a bugreport.
658 flags = FLAG_DUMP_ALL;
659 break;
John Reckba6adf62015-02-19 14:36:50 -0800660 }
John Reckfe5e7b72014-05-23 17:42:28 -0700661 }
John Reckba6adf62015-02-19 14:36:50 -0800662 nDumpProfileInfo(mNativeProxy, fd, flags);
John Reckcec24ae2013-11-05 13:27:50 -0800663 }
664
John Reck51aaf902015-12-02 15:08:07 -0800665 /**
666 * Loads system properties used by the renderer. This method is invoked
667 * whenever system properties are modified. Implementations can use this
668 * to trigger live updates of the renderer based on properties.
669 *
670 * @return True if a property has changed.
671 */
John Reckcec24ae2013-11-05 13:27:50 -0800672 boolean loadSystemProperties() {
John Reckfe5e7b72014-05-23 17:42:28 -0700673 boolean changed = nLoadSystemProperties(mNativeProxy);
John Reck23d307c2014-10-27 12:38:48 -0700674 if (changed) {
675 invalidateRoot();
676 }
John Reckfe5e7b72014-05-23 17:42:28 -0700677 return changed;
John Reckcec24ae2013-11-05 13:27:50 -0800678 }
679
John Reck0a973302014-07-16 13:29:45 -0700680 private void updateViewTreeDisplayList(View view) {
John Reckcec24ae2013-11-05 13:27:50 -0800681 view.mPrivateFlags |= View.PFLAG_DRAWN;
John Reckcec24ae2013-11-05 13:27:50 -0800682 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
683 == View.PFLAG_INVALIDATED;
684 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
Chris Craik31a2d062015-05-01 14:22:47 -0700685 view.updateDisplayListIfDirty();
John Reckcec24ae2013-11-05 13:27:50 -0800686 view.mRecreateDisplayList = false;
John Reckbc0cc022014-04-11 16:08:14 -0700687 }
688
Stan Iliev45faba52016-06-28 13:33:15 -0400689 private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
Chris Craik70850ea2014-11-18 10:49:23 -0800690 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
John Reck0a973302014-07-16 13:29:45 -0700691 updateViewTreeDisplayList(view);
692
693 if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
Chris Craikf6829a02015-03-10 10:28:59 -0700694 DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
John Reck0a973302014-07-16 13:29:45 -0700695 try {
Alan Viverettedbed8932014-08-06 17:54:52 -0700696 final int saveCount = canvas.save();
John Reck0a973302014-07-16 13:29:45 -0700697 canvas.translate(mInsetLeft, mInsetTop);
Stan Iliev45faba52016-06-28 13:33:15 -0400698 callbacks.onPreDraw(canvas);
Chris Craikabedca32014-08-28 15:03:55 -0700699
700 canvas.insertReorderBarrier();
Chris Craik31a2d062015-05-01 14:22:47 -0700701 canvas.drawRenderNode(view.updateDisplayListIfDirty());
Chris Craikabedca32014-08-28 15:03:55 -0700702 canvas.insertInorderBarrier();
703
Stan Iliev45faba52016-06-28 13:33:15 -0400704 callbacks.onPostDraw(canvas);
Alan Viverettedbed8932014-08-06 17:54:52 -0700705 canvas.restoreToCount(saveCount);
John Reck0a973302014-07-16 13:29:45 -0700706 mRootNodeNeedsUpdate = false;
707 } finally {
708 mRootNode.end(canvas);
709 }
710 }
711 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
712 }
713
Skuhneea7a7fb2015-08-28 07:10:31 -0700714 /**
715 * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
716 * rendernode of the UI thread.
717 * @param node The node to add.
718 * @param placeFront If true, the render node will be placed in front of the content node,
719 * otherwise behind the content node.
720 */
721 public void addRenderNode(RenderNode node, boolean placeFront) {
722 nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
723 }
724
725 /**
726 * Only especially added render nodes can be removed.
727 * @param node The node which was added via addRenderNode which should get removed again.
728 */
729 public void removeRenderNode(RenderNode node) {
730 nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
731 }
732
733 /**
734 * Draws a particular render node. If the node is not the content node, only the additional
735 * nodes will get drawn and the content remains untouched.
736 * @param node The node to be drawn.
737 */
738 public void drawRenderNode(RenderNode node) {
739 nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
740 }
741
742 /**
743 * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
744 * will be prevented to overdraw this area. It will be synchronized with the draw call.
745 * This should be updated in the content view's draw call.
746 * @param left The left side of the protected bounds.
747 * @param top The top side of the protected bounds.
748 * @param right The right side of the protected bounds.
749 * @param bottom The bottom side of the protected bounds.
750 */
Skuhneb8160872015-09-22 09:51:39 -0700751 public void setContentDrawBounds(int left, int top, int right, int bottom) {
Jorim Jaggie85ce992016-05-09 19:05:22 -0700752 nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
Skuhneea7a7fb2015-08-28 07:10:31 -0700753 }
754
John Reck51aaf902015-12-02 15:08:07 -0800755 /**
756 * Interface used to receive callbacks whenever a view is drawn by
Stan Iliev45faba52016-06-28 13:33:15 -0400757 * a threaded renderer instance.
John Reck51aaf902015-12-02 15:08:07 -0800758 */
Stan Iliev45faba52016-06-28 13:33:15 -0400759 interface DrawCallbacks {
John Reck51aaf902015-12-02 15:08:07 -0800760 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400761 * Invoked before a view is drawn by a threaded renderer.
John Reck51aaf902015-12-02 15:08:07 -0800762 * This method can be used to apply transformations to the
763 * canvas but no drawing command should be issued.
764 *
765 * @param canvas The Canvas used to render the view.
766 */
Stan Iliev45faba52016-06-28 13:33:15 -0400767 void onPreDraw(DisplayListCanvas canvas);
John Reck51aaf902015-12-02 15:08:07 -0800768
769 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400770 * Invoked after a view is drawn by a threaded renderer.
John Reck51aaf902015-12-02 15:08:07 -0800771 * It is safe to invoke drawing commands from this method.
772 *
773 * @param canvas The Canvas used to render the view.
774 */
Stan Iliev45faba52016-06-28 13:33:15 -0400775 void onPostDraw(DisplayListCanvas canvas);
John Reck51aaf902015-12-02 15:08:07 -0800776 }
777
778 /**
Stan Iliev45faba52016-06-28 13:33:15 -0400779 * Indicates that the content drawn by DrawCallbacks needs to
John Reck51aaf902015-12-02 15:08:07 -0800780 * be updated, which will be done by the next call to draw()
781 */
John Reck0a973302014-07-16 13:29:45 -0700782 void invalidateRoot() {
783 mRootNodeNeedsUpdate = true;
784 }
785
John Reck51aaf902015-12-02 15:08:07 -0800786 /**
787 * Draws the specified view.
788 *
789 * @param view The view to draw.
790 * @param attachInfo AttachInfo tied to the specified view.
791 * @param callbacks Callbacks invoked when drawing happens.
792 */
Stan Iliev45faba52016-06-28 13:33:15 -0400793 void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
John Reckbc0cc022014-04-11 16:08:14 -0700794 attachInfo.mIgnoreDirtyState = true;
John Reckbc0cc022014-04-11 16:08:14 -0700795
John Reckba6adf62015-02-19 14:36:50 -0800796 final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
797 choreographer.mFrameInfo.markDrawStart();
John Reckfe5e7b72014-05-23 17:42:28 -0700798
John Reck61375a82014-09-18 19:27:48 +0000799 updateRootDisplayList(view, callbacks);
John Reckcec24ae2013-11-05 13:27:50 -0800800
John Reck6313b922014-04-16 18:59:21 -0700801 attachInfo.mIgnoreDirtyState = false;
802
John Reck119907c2014-08-14 09:02:01 -0700803 // register animating rendernodes which started animating prior to renderer
804 // creation, which is typical for animators started prior to first draw
805 if (attachInfo.mPendingAnimatingRenderNodes != null) {
806 final int count = attachInfo.mPendingAnimatingRenderNodes.size();
807 for (int i = 0; i < count; i++) {
808 registerAnimatingRenderNode(
809 attachInfo.mPendingAnimatingRenderNodes.get(i));
810 }
811 attachInfo.mPendingAnimatingRenderNodes.clear();
812 // We don't need this anymore as subsequent calls to
813 // ViewRootImpl#attachRenderNodeAnimator will go directly to us.
814 attachInfo.mPendingAnimatingRenderNodes = null;
815 }
816
John Reckba6adf62015-02-19 14:36:50 -0800817 final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
John Reck51f2d602016-04-06 07:50:47 -0700818 int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
John Reckaa95a882014-11-07 11:02:07 -0800819 if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
820 setEnabled(false);
John Reckb13de072014-11-19 16:33:47 -0800821 attachInfo.mViewRootImpl.mSurface.release();
John Reckaa95a882014-11-07 11:02:07 -0800822 // Invalidate since we failed to draw. This should fetch a Surface
823 // if it is still needed or do nothing if we are no longer drawing
824 attachInfo.mViewRootImpl.invalidate();
825 }
John Reckf9be7792014-05-02 18:21:16 -0700826 if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
827 attachInfo.mViewRootImpl.invalidate();
828 }
John Reckcec24ae2013-11-05 13:27:50 -0800829 }
830
John Reck3b202512014-06-23 13:13:08 -0700831 static void invokeFunctor(long functor, boolean waitForCompletion) {
832 nInvokeFunctor(functor, waitForCompletion);
John Reck0d1f6342014-03-28 20:30:27 -0700833 }
834
John Reck51aaf902015-12-02 15:08:07 -0800835 /**
836 * Creates a new hardware layer. A hardware layer built by calling this
837 * method will be treated as a texture layer, instead of as a render target.
838 *
839 * @return A hardware layer
840 */
John Reck9d8d99d2018-02-21 12:55:41 -0800841 TextureLayer createTextureLayer() {
John Reck19b6bcf2014-02-14 20:03:38 -0800842 long layer = nCreateTextureLayer(mNativeProxy);
John Reck9d8d99d2018-02-21 12:55:41 -0800843 return TextureLayer.adoptTextureLayer(this, layer);
John Reck19b6bcf2014-02-14 20:03:38 -0800844 }
845
John Reck51aaf902015-12-02 15:08:07 -0800846
John Reck3e824952014-08-20 10:08:39 -0700847 void buildLayer(RenderNode node) {
848 nBuildLayer(mNativeProxy, node.getNativeDisplayList());
849 }
850
John Reck51aaf902015-12-02 15:08:07 -0800851
John Reck9d8d99d2018-02-21 12:55:41 -0800852 boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
John Reck19b6bcf2014-02-14 20:03:38 -0800853 return nCopyLayerInto(mNativeProxy,
John Reck3731dc22015-04-13 15:20:29 -0700854 layer.getDeferredLayerUpdater(), bitmap);
John Reck19b6bcf2014-02-14 20:03:38 -0800855 }
856
John Reck51aaf902015-12-02 15:08:07 -0800857 /**
858 * Indicates that the specified hardware layer needs to be updated
859 * as soon as possible.
860 *
861 * @param layer The hardware layer that needs an update
862 */
John Reck9d8d99d2018-02-21 12:55:41 -0800863 void pushLayerUpdate(TextureLayer layer) {
John Reckd72e0a32014-05-29 18:56:11 -0700864 nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
John Reck19b6bcf2014-02-14 20:03:38 -0800865 }
866
John Reck51aaf902015-12-02 15:08:07 -0800867 /**
868 * Tells the HardwareRenderer that the layer is destroyed. The renderer
869 * should remove the layer from any update queues.
870 */
John Reck9d8d99d2018-02-21 12:55:41 -0800871 void onLayerDestroyed(TextureLayer layer) {
John Reckd72e0a32014-05-29 18:56:11 -0700872 nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
John Reck19b6bcf2014-02-14 20:03:38 -0800873 }
874
John Reck51aaf902015-12-02 15:08:07 -0800875 /**
John Reck51aaf902015-12-02 15:08:07 -0800876 * Blocks until all previously queued work has completed.
877 */
John Reck28ad7b52014-04-07 16:59:25 -0700878 void fence() {
879 nFence(mNativeProxy);
880 }
881
John Reck51aaf902015-12-02 15:08:07 -0800882 /**
883 * Prevents any further drawing until draw() is called. This is a signal
884 * that the contents of the RenderNode tree are no longer safe to play back.
885 * In practice this usually means that there are Functor pointers in the
886 * display list that are no longer valid.
887 */
John Reckf47a5942014-06-30 16:20:04 -0700888 void stopDrawing() {
889 nStopDrawing(mNativeProxy);
890 }
891
John Reck51aaf902015-12-02 15:08:07 -0800892 /**
893 * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
894 */
John Recka5dda642014-05-22 15:43:54 -0700895 public void notifyFramePending() {
896 nNotifyFramePending(mNativeProxy);
897 }
898
John Reck51aaf902015-12-02 15:08:07 -0800899
John Reck119907c2014-08-14 09:02:01 -0700900 void registerAnimatingRenderNode(RenderNode animator) {
901 nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
902 }
903
Doris Liu67ce99b2016-05-17 16:50:31 -0700904 void registerVectorDrawableAnimator(
905 AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) {
906 nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
907 animator.getAnimatorNativePtr());
908 }
909
John Recke248bd12015-08-05 13:53:53 -0700910 public void serializeDisplayListTree() {
911 nSerializeDisplayListTree(mNativeProxy);
912 }
913
John Reck95801462016-09-01 09:44:09 -0700914 public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
915 if (srcRect == null) {
916 // Empty rect means entire surface
917 return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
918 } else {
919 return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
920 srcRect.right, srcRect.bottom, bitmap);
921 }
John Reck10dd0582016-03-31 16:36:16 -0700922 }
923
John Reck1fedd912017-05-23 14:45:22 -0700924 /**
925 * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
926 * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
927 * not the RenderNode from a View.
928 **/
929 public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
930 return nCreateHardwareBitmap(node.getNativeDisplayList(), width, height);
931 }
932
John Reck938e8842017-08-24 13:41:59 -0700933 /**
934 * Sets whether or not high contrast text rendering is enabled. The setting is global
935 * but only affects content rendered after the change is made.
936 */
937 public static void setHighContrastText(boolean highContrastText) {
938 nSetHighContrastText(highContrastText);
939 }
940
John Reck56428472018-03-16 17:27:17 -0700941 /**
942 * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
943 */
944 public static void setIsolatedProcess(boolean isIsolated) {
945 nSetIsolatedProcess(isIsolated);
946 }
947
948 /**
949 * If set extra graphics debugging abilities will be enabled such as dumping skp
950 */
951 public static void setDebuggingEnabled(boolean enable) {
952 nSetDebuggingEnabled(enable);
953 }
954
John Reck119907c2014-08-14 09:02:01 -0700955 @Override
John Reck4f02bf42014-01-03 18:09:17 -0800956 protected void finalize() throws Throwable {
957 try {
958 nDeleteProxy(mNativeProxy);
John Reck0ed751d2014-04-08 14:10:17 -0700959 mNativeProxy = 0;
John Reck4f02bf42014-01-03 18:09:17 -0800960 } finally {
961 super.finalize();
John Reckcec24ae2013-11-05 13:27:50 -0800962 }
963 }
964
Mihai Popa4bcd4d402018-02-07 17:13:51 +0000965 /**
966 * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
967 * TODO: deduplicate against ThreadedRenderer.
968 *
969 * @hide
970 */
971 public static class SimpleRenderer {
972 private final RenderNode mRootNode;
973 private long mNativeProxy;
974 private final float mLightY, mLightZ;
975 private Surface mSurface;
976 private final FrameInfo mFrameInfo = new FrameInfo();
977
978 public SimpleRenderer(final Context context, final String name, final Surface surface) {
979 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
980 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
981 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
982 final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
983 final int ambientShadowAlpha =
984 (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
985 final int spotShadowAlpha =
986 (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
987 a.recycle();
988
989 final long rootNodePtr = nCreateRootRenderNode();
990 mRootNode = RenderNode.adopt(rootNodePtr);
991 mRootNode.setClipToBounds(false);
992 mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr);
993 nSetName(mNativeProxy, name);
994
995 ProcessInitializer.sInstance.init(context, mNativeProxy);
996 nLoadSystemProperties(mNativeProxy);
997
998 nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha);
999
1000 mSurface = surface;
1001 nUpdateSurface(mNativeProxy, surface);
1002 }
1003
1004 /**
1005 * Set the light center.
1006 */
1007 public void setLightCenter(final Display display,
1008 final int windowLeft, final int windowTop) {
1009 // Adjust light position for window offsets.
1010 final Point displaySize = new Point();
1011 display.getRealSize(displaySize);
1012 final float lightX = displaySize.x / 2f - windowLeft;
1013 final float lightY = mLightY - windowTop;
1014
1015 nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
1016 }
1017
1018 public RenderNode getRootNode() {
1019 return mRootNode;
1020 }
1021
1022 /**
1023 * Draw the surface.
1024 */
1025 public void draw(final FrameDrawingCallback callback) {
1026 final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
1027 mFrameInfo.setVsync(vsync, vsync);
1028 mFrameInfo.addFlags(1 << 2 /* VSYNC */);
1029 if (callback != null) {
Mihai Popa95688002018-02-23 16:10:11 +00001030 nSetFrameCallback(mNativeProxy, callback);
Mihai Popa4bcd4d402018-02-07 17:13:51 +00001031 }
1032 nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length);
1033 }
1034
1035 /**
1036 * Destroy the renderer.
1037 */
1038 public void destroy() {
1039 mSurface = null;
1040 nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
1041 }
1042
1043 @Override
1044 protected void finalize() throws Throwable {
1045 try {
1046 nDeleteProxy(mNativeProxy);
1047 mNativeProxy = 0;
1048 } finally {
1049 super.finalize();
1050 }
1051 }
1052 }
1053
1054 /**
1055 * Interface used to receive callbacks when a frame is being drawn.
1056 */
1057 public interface FrameDrawingCallback {
1058 /**
1059 * Invoked during a frame drawing.
1060 *
1061 * @param frame The id of the frame being drawn.
1062 */
1063 void onFrameDraw(long frame);
1064 }
1065
John Reckedc524c2015-03-18 15:24:33 -07001066 private static class ProcessInitializer {
1067 static ProcessInitializer sInstance = new ProcessInitializer();
John Reck66f0be62014-05-13 13:39:31 -07001068
1069 private boolean mInitialized = false;
1070
John Reckdf1742e2017-01-19 15:56:21 -08001071 private Context mAppContext;
1072 private IGraphicsStats mGraphicsStatsService;
1073 private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
1074 @Override
1075 public void onRotateGraphicsStatsBuffer() throws RemoteException {
1076 rotateBuffer();
1077 }
1078 };
1079
John Reckedc524c2015-03-18 15:24:33 -07001080 private ProcessInitializer() {}
John Reck66f0be62014-05-13 13:39:31 -07001081
John Reck3b202512014-06-23 13:13:08 -07001082 synchronized void init(Context context, long renderProxy) {
John Reck66f0be62014-05-13 13:39:31 -07001083 if (mInitialized) return;
John Reckedc524c2015-03-18 15:24:33 -07001084 mInitialized = true;
John Reckdf1742e2017-01-19 15:56:21 -08001085 mAppContext = context.getApplicationContext();
John Reck9f516442017-09-25 10:27:21 -07001086
Romain Guy26a2b972017-04-17 09:39:51 -07001087 initSched(renderProxy);
John Reckf1b96102018-03-07 11:06:41 -08001088
1089 if (mAppContext != null) {
John Reckf1b96102018-03-07 11:06:41 -08001090 initGraphicsStats();
1091 }
John Reckedc524c2015-03-18 15:24:33 -07001092 }
1093
Romain Guy26a2b972017-04-17 09:39:51 -07001094 private void initSched(long renderProxy) {
Tim Murray33eb07f2016-06-10 10:03:20 -07001095 try {
1096 int tid = nGetRenderThreadTid(renderProxy);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001097 ActivityManager.getService().setRenderThread(tid);
Tim Murray33eb07f2016-06-10 10:03:20 -07001098 } catch (Throwable t) {
1099 Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
1100 }
1101 }
1102
John Reckdf1742e2017-01-19 15:56:21 -08001103 private void initGraphicsStats() {
John Reckedc524c2015-03-18 15:24:33 -07001104 try {
John Reck828698b2015-06-30 12:56:03 -07001105 IBinder binder = ServiceManager.getService("graphicsstats");
1106 if (binder == null) return;
John Reckdf1742e2017-01-19 15:56:21 -08001107 mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
1108 requestBuffer();
1109 } catch (Throwable t) {
1110 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
1111 }
1112 }
1113
1114 private void rotateBuffer() {
1115 nRotateProcessStatsBuffer();
1116 requestBuffer();
1117 }
1118
1119 private void requestBuffer() {
1120 try {
1121 final String pkg = mAppContext.getApplicationInfo().packageName;
1122 ParcelFileDescriptor pfd = mGraphicsStatsService
1123 .requestBufferForProcess(pkg, mGraphicsStatsCallback);
1124 nSetProcessStatsBuffer(pfd.getFd());
John Reckedc524c2015-03-18 15:24:33 -07001125 pfd.close();
John Reck828698b2015-06-30 12:56:03 -07001126 } catch (Throwable t) {
1127 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
John Reckedc524c2015-03-18 15:24:33 -07001128 }
1129 }
John Reck66f0be62014-05-13 13:39:31 -07001130 }
1131
Andres Morales910beb82016-02-02 16:19:40 -08001132 void addFrameMetricsObserver(FrameMetricsObserver observer) {
1133 long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
1134 observer.mNative = new VirtualRefBasePtr(nativeObserver);
Andres Morales06f5bc72015-12-15 15:21:31 -08001135 }
1136
Andres Morales910beb82016-02-02 16:19:40 -08001137 void removeFrameMetricsObserver(FrameMetricsObserver observer) {
1138 nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
1139 observer.mNative = null;
Andres Morales06f5bc72015-12-15 15:21:31 -08001140 }
1141
John Reck9f516442017-09-25 10:27:21 -07001142 /** b/68769804: For low FPS experiments. */
1143 public static void setFPSDivisor(int divisor) {
Makoto Onukib708cbe2018-01-09 12:35:06 -08001144 nHackySetRTAnimationsEnabled(divisor <= 1);
John Reck9f516442017-09-25 10:27:21 -07001145 }
1146
Jorim Jaggi767e25e2018-04-04 23:07:35 +02001147 /**
1148 * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
1149 * called before any OpenGL context is created.
1150 *
1151 * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
1152 */
1153 public static void setContextPriority(int priority) {
1154 nSetContextPriority(priority);
1155 }
1156
John Recka8963062017-06-14 10:47:50 -07001157 /** Not actually public - internal use only. This doc to make lint happy */
1158 public static native void disableVsync();
1159
Stan Ilievd495f432017-10-09 15:49:32 -04001160 static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
John Reck84a4c882014-05-30 14:34:03 -07001161
John Reckdf1742e2017-01-19 15:56:21 -08001162 private static native void nRotateProcessStatsBuffer();
1163 private static native void nSetProcessStatsBuffer(int fd);
Tim Murray33eb07f2016-06-10 10:03:20 -07001164 private static native int nGetRenderThreadTid(long nativeProxy);
John Reck4f02bf42014-01-03 18:09:17 -08001165
John Recke45b1fd2014-04-15 09:50:16 -07001166 private static native long nCreateRootRenderNode();
1167 private static native long nCreateProxy(boolean translucent, long rootRenderNode);
John Reck4f02bf42014-01-03 18:09:17 -08001168 private static native void nDeleteProxy(long nativeProxy);
1169
John Recke4280ba2014-05-05 16:39:37 -07001170 private static native boolean nLoadSystemProperties(long nativeProxy);
John Reckb36016c2015-03-11 08:50:53 -07001171 private static native void nSetName(long nativeProxy, String name);
John Reck18f16e62014-05-02 16:46:41 -07001172
Thomas Buhot0bcd0cb2015-12-04 12:18:03 +01001173 private static native void nInitialize(long nativeProxy, Surface window);
John Reck4f02bf42014-01-03 18:09:17 -08001174 private static native void nUpdateSurface(long nativeProxy, Surface window);
John Reck01a5ea32014-12-03 13:01:07 -08001175 private static native boolean nPauseSurface(long nativeProxy, Surface window);
John Reck8afcc762016-04-13 10:24:06 -07001176 private static native void nSetStopped(long nativeProxy, boolean stopped);
John Reckab1080c2016-06-21 16:24:20 -07001177 private static native void nSetup(long nativeProxy,
Alan Viverette50210d92015-05-14 18:05:36 -07001178 float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
1179 private static native void nSetLightCenter(long nativeProxy,
1180 float lightX, float lightY, float lightZ);
John Reck63a06672014-05-07 13:45:54 -07001181 private static native void nSetOpaque(long nativeProxy, boolean opaque);
Romain Guy26a2b972017-04-17 09:39:51 -07001182 private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
John Reck51f2d602016-04-06 07:50:47 -07001183 private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
Doris Liu350e6522016-02-19 14:20:37 -08001184 private static native void nDestroy(long nativeProxy, long rootRenderNode);
John Reck119907c2014-08-14 09:02:01 -07001185 private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
Doris Liu67ce99b2016-05-17 16:50:31 -07001186 private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
John Reck4f02bf42014-01-03 18:09:17 -08001187
John Reck3b202512014-06-23 13:13:08 -07001188 private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
John Reck19b6bcf2014-02-14 20:03:38 -08001189
John Reck19b6bcf2014-02-14 20:03:38 -08001190 private static native long nCreateTextureLayer(long nativeProxy);
John Reck3e824952014-08-20 10:08:39 -07001191 private static native void nBuildLayer(long nativeProxy, long node);
John Reck3731dc22015-04-13 15:20:29 -07001192 private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
John Reckd72e0a32014-05-29 18:56:11 -07001193 private static native void nPushLayerUpdate(long nativeProxy, long layer);
1194 private static native void nCancelLayerUpdate(long nativeProxy, long layer);
John Reck918ad522014-06-27 14:45:25 -07001195 private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
John Reck28ad7b52014-04-07 16:59:25 -07001196
John Reckf47a5942014-06-30 16:20:04 -07001197 private static native void nDestroyHardwareResources(long nativeProxy);
1198 private static native void nTrimMemory(int level);
Chris Craik2507c342015-05-04 14:36:49 -07001199 private static native void nOverrideProperty(String name, String value);
John Recke1628b72014-05-23 15:11:19 -07001200
John Reck28ad7b52014-04-07 16:59:25 -07001201 private static native void nFence(long nativeProxy);
John Reckf47a5942014-06-30 16:20:04 -07001202 private static native void nStopDrawing(long nativeProxy);
John Recka5dda642014-05-22 15:43:54 -07001203 private static native void nNotifyFramePending(long nativeProxy);
John Reckfe5e7b72014-05-23 17:42:28 -07001204
John Recke248bd12015-08-05 13:53:53 -07001205 private static native void nSerializeDisplayListTree(long nativeProxy);
1206
John Reckba6adf62015-02-19 14:36:50 -08001207 private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
1208 @DumpFlags int dumpFlags);
Skuhneea7a7fb2015-08-28 07:10:31 -07001209
1210 private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
1211 boolean placeFront);
1212 private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
1213 private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
Skuhneb8160872015-09-22 09:51:39 -07001214 private static native void nSetContentDrawBounds(long nativeProxy, int left,
Skuhneea7a7fb2015-08-28 07:10:31 -07001215 int top, int right, int bottom);
Mihai Popa95688002018-02-23 16:10:11 +00001216 private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
Andres Morales06f5bc72015-12-15 15:21:31 -08001217
Andres Morales910beb82016-02-02 16:19:40 -08001218 private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
1219 private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
John Reck10dd0582016-03-31 16:36:16 -07001220
John Reck95801462016-09-01 09:44:09 -07001221 private static native int nCopySurfaceInto(Surface surface,
1222 int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
John Reck1fedd912017-05-23 14:45:22 -07001223
1224 private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
John Reck938e8842017-08-24 13:41:59 -07001225 private static native void nSetHighContrastText(boolean enabled);
John Reck9f516442017-09-25 10:27:21 -07001226 // For temporary experimentation b/66945974
1227 private static native void nHackySetRTAnimationsEnabled(boolean enabled);
John Reck6afa0092018-03-01 17:28:35 -08001228 private static native void nSetDebuggingEnabled(boolean enabled);
John Reck56428472018-03-16 17:27:17 -07001229 private static native void nSetIsolatedProcess(boolean enabled);
Jorim Jaggi767e25e2018-04-04 23:07:35 +02001230 private static native void nSetContextPriority(int priority);
John Reckcec24ae2013-11-05 13:27:50 -08001231}