1 /* 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 17 package android.view; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.app.ActivityManager; 22 import android.content.Context; 23 import android.content.res.TypedArray; 24 import android.graphics.Bitmap; 25 import android.graphics.Point; 26 import android.graphics.Rect; 27 import android.graphics.drawable.AnimatedVectorDrawable; 28 import android.os.IBinder; 29 import android.os.ParcelFileDescriptor; 30 import android.os.RemoteException; 31 import android.os.ServiceManager; 32 import android.os.Trace; 33 import android.util.Log; 34 import android.view.Surface.OutOfResourcesException; 35 import android.view.View.AttachInfo; 36 37 import com.android.internal.R; 38 import com.android.internal.util.VirtualRefBasePtr; 39 40 import java.io.File; 41 import java.io.FileDescriptor; 42 import java.io.PrintWriter; 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 46 /** 47 * Threaded renderer that proxies the rendering to a render thread. Most calls 48 * are currently synchronous. 49 * 50 * The UI thread can block on the RenderThread, but RenderThread must never 51 * block on the UI thread. 52 * 53 * ThreadedRenderer creates an instance of RenderProxy. RenderProxy in turn creates 54 * and manages a CanvasContext on the RenderThread. The CanvasContext is fully managed 55 * by the lifecycle of the RenderProxy. 56 * 57 * Note that although currently the EGL context & surfaces are created & managed 58 * by the render thread, the goal is to move that into a shared structure that can 59 * be managed by both threads. EGLSurface creation & deletion should ideally be 60 * done on the UI thread and not the RenderThread to avoid stalling the 61 * RenderThread with surface buffer allocation. 62 * 63 * @hide 64 */ 65 public final class ThreadedRenderer { 66 private static final String LOG_TAG = "ThreadedRenderer"; 67 68 /** 69 * Name of the file that holds the shaders cache. 70 */ 71 private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache"; 72 73 /** 74 * System property used to enable or disable threaded rendering profiling. 75 * The default value of this property is assumed to be false. 76 * 77 * When profiling is enabled, the adb shell dumpsys gfxinfo command will 78 * output extra information about the time taken to execute by the last 79 * frames. 80 * 81 * Possible values: 82 * "true", to enable profiling 83 * "visual_bars", to enable profiling and visualize the results on screen 84 * "false", to disable profiling 85 * 86 * @see #PROFILE_PROPERTY_VISUALIZE_BARS 87 * 88 * @hide 89 */ 90 public static final String PROFILE_PROPERTY = "debug.hwui.profile"; 91 92 /** 93 * Value for {@link #PROFILE_PROPERTY}. When the property is set to this 94 * value, profiling data will be visualized on screen as a bar chart. 95 * 96 * @hide 97 */ 98 public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars"; 99 100 /** 101 * System property used to specify the number of frames to be used 102 * when doing threaded rendering profiling. 103 * The default value of this property is #PROFILE_MAX_FRAMES. 104 * 105 * When profiling is enabled, the adb shell dumpsys gfxinfo command will 106 * output extra information about the time taken to execute by the last 107 * frames. 108 * 109 * Possible values: 110 * "60", to set the limit of frames to 60 111 */ 112 static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes"; 113 114 /** 115 * System property used to debug EGL configuration choice. 116 * 117 * Possible values: 118 * "choice", print the chosen configuration only 119 * "all", print all possible configurations 120 */ 121 static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config"; 122 123 /** 124 * Turn on to draw dirty regions every other frame. 125 * 126 * Possible values: 127 * "true", to enable dirty regions debugging 128 * "false", to disable dirty regions debugging 129 * 130 * @hide 131 */ 132 public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions"; 133 134 /** 135 * Turn on to flash hardware layers when they update. 136 * 137 * Possible values: 138 * "true", to enable hardware layers updates debugging 139 * "false", to disable hardware layers updates debugging 140 * 141 * @hide 142 */ 143 public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY = 144 "debug.hwui.show_layers_updates"; 145 146 /** 147 * Controls overdraw debugging. 148 * 149 * Possible values: 150 * "false", to disable overdraw debugging 151 * "show", to show overdraw areas on screen 152 * "count", to display an overdraw counter 153 * 154 * @hide 155 */ 156 public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw"; 157 158 /** 159 * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this 160 * value, overdraw will be shown on screen by coloring pixels. 161 * 162 * @hide 163 */ 164 public static final String OVERDRAW_PROPERTY_SHOW = "show"; 165 166 /** 167 * Defines the rendering pipeline to be used by the ThreadedRenderer. 168 * 169 * Possible values: 170 * "opengl", will use the existing OpenGL renderer 171 * "skiagl", will use Skia's OpenGL renderer 172 * "skiavk", will use Skia's Vulkan renderer 173 * 174 * @hide 175 */ 176 public static final String DEBUG_RENDERER_PROPERTY = "debug.hwui.renderer"; 177 178 /** 179 * Turn on to debug non-rectangular clip operations. 180 * 181 * Possible values: 182 * "hide", to disable this debug mode 183 * "highlight", highlight drawing commands tested against a non-rectangular clip 184 * "stencil", renders the clip region on screen when set 185 * 186 * @hide 187 */ 188 public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY = 189 "debug.hwui.show_non_rect_clip"; 190 191 /** 192 * A process can set this flag to false to prevent the use of threaded 193 * rendering. 194 * 195 * @hide 196 */ 197 public static boolean sRendererDisabled = false; 198 199 /** 200 * Further threaded renderer disabling for the system process. 201 * 202 * @hide 203 */ 204 public static boolean sSystemRendererDisabled = false; 205 206 /** 207 * Invoke this method to disable threaded rendering in the current process. 208 * 209 * @hide 210 */ disable(boolean system)211 public static void disable(boolean system) { 212 sRendererDisabled = true; 213 if (system) { 214 sSystemRendererDisabled = true; 215 } 216 } 217 218 public static boolean sTrimForeground = false; 219 220 /** 221 * Controls whether or not the renderer should aggressively trim 222 * memory. Note that this must not be set for any process that uses 223 * WebView! This should be only used by system_process or similar 224 * that do not go into the background. 225 */ enableForegroundTrimming()226 public static void enableForegroundTrimming() { 227 sTrimForeground = true; 228 } 229 nSupportsOpenGL()230 private static native boolean nSupportsOpenGL(); 231 private static boolean sSupportsOpenGL = nSupportsOpenGL(); 232 233 /** 234 * Indicates whether threaded rendering is available under any form for 235 * the view hierarchy. 236 * 237 * @return True if the view hierarchy can potentially be defer rendered, 238 * false otherwise 239 */ isAvailable()240 public static boolean isAvailable() { 241 return sSupportsOpenGL; 242 } 243 244 /** 245 * Sets the directory to use as a persistent storage for threaded rendering 246 * resources. 247 * 248 * @param cacheDir A directory the current process can write to 249 * 250 * @hide 251 */ setupDiskCache(File cacheDir)252 public static void setupDiskCache(File cacheDir) { 253 ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath()); 254 } 255 256 /** 257 * Creates a threaded renderer using OpenGL. 258 * 259 * @param translucent True if the surface is translucent, false otherwise 260 * 261 * @return A threaded renderer backed by OpenGL. 262 */ create(Context context, boolean translucent, String name)263 public static ThreadedRenderer create(Context context, boolean translucent, String name) { 264 ThreadedRenderer renderer = null; 265 if (isAvailable()) { 266 renderer = new ThreadedRenderer(context, translucent, name); 267 } 268 return renderer; 269 } 270 271 /** 272 * Invoke this method when the system is running out of memory. This 273 * method will attempt to recover as much memory as possible, based on 274 * the specified hint. 275 * 276 * @param level Hint about the amount of memory that should be trimmed, 277 * see {@link android.content.ComponentCallbacks} 278 */ trimMemory(int level)279 public static void trimMemory(int level) { 280 nTrimMemory(level); 281 } 282 overrideProperty(@onNull String name, @NonNull String value)283 public static void overrideProperty(@NonNull String name, @NonNull String value) { 284 if (name == null || value == null) { 285 throw new IllegalArgumentException("name and value must be non-null"); 286 } 287 nOverrideProperty(name, value); 288 } 289 290 // Keep in sync with DrawFrameTask.h SYNC_* flags 291 // Nothing interesting to report 292 private static final int SYNC_OK = 0; 293 // Needs a ViewRoot invalidate 294 private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0; 295 // Spoiler: the reward is GPU-accelerated drawing, better find that Surface! 296 private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1; 297 // setStopped is true, drawing is false 298 // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND? 299 // This flag isn't really used as there's nothing that we care to do 300 // in response, so it really just exists to differentiate from LOST_SURFACE 301 // but possibly both can just be deleted. 302 private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2; 303 304 private static final String[] VISUALIZERS = { 305 PROFILE_PROPERTY_VISUALIZE_BARS, 306 }; 307 308 private static final int FLAG_DUMP_FRAMESTATS = 1 << 0; 309 private static final int FLAG_DUMP_RESET = 1 << 1; 310 311 @IntDef(flag = true, value = { 312 FLAG_DUMP_FRAMESTATS, FLAG_DUMP_RESET }) 313 @Retention(RetentionPolicy.SOURCE) 314 public @interface DumpFlags {} 315 316 // Size of the rendered content. 317 private int mWidth, mHeight; 318 319 // Actual size of the drawing surface. 320 private int mSurfaceWidth, mSurfaceHeight; 321 322 // Insets between the drawing surface and rendered content. These are 323 // applied as translation when updating the root render node. 324 private int mInsetTop, mInsetLeft; 325 326 // Whether the surface has insets. Used to protect opacity. 327 private boolean mHasInsets; 328 329 // Light and shadow properties specified by the theme. 330 private final float mLightY; 331 private final float mLightZ; 332 private final float mLightRadius; 333 private final int mAmbientShadowAlpha; 334 private final int mSpotShadowAlpha; 335 336 private long mNativeProxy; 337 private boolean mInitialized = false; 338 private RenderNode mRootNode; 339 private Choreographer mChoreographer; 340 private boolean mRootNodeNeedsUpdate; 341 342 private boolean mEnabled; 343 private boolean mRequested = true; 344 private boolean mIsOpaque = false; 345 ThreadedRenderer(Context context, boolean translucent, String name)346 ThreadedRenderer(Context context, boolean translucent, String name) { 347 final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0); 348 mLightY = a.getDimension(R.styleable.Lighting_lightY, 0); 349 mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0); 350 mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0); 351 mAmbientShadowAlpha = 352 (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f); 353 mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f); 354 a.recycle(); 355 356 long rootNodePtr = nCreateRootRenderNode(); 357 mRootNode = RenderNode.adopt(rootNodePtr); 358 mRootNode.setClipToBounds(false); 359 mIsOpaque = !translucent; 360 mNativeProxy = nCreateProxy(translucent, rootNodePtr); 361 nSetName(mNativeProxy, name); 362 363 ProcessInitializer.sInstance.init(context, mNativeProxy); 364 365 loadSystemProperties(); 366 } 367 368 /** 369 * Destroys the threaded rendering context. 370 */ destroy()371 void destroy() { 372 mInitialized = false; 373 updateEnabledState(null); 374 nDestroy(mNativeProxy, mRootNode.mNativeRenderNode); 375 } 376 377 /** 378 * Indicates whether threaded rendering is currently enabled. 379 * 380 * @return True if threaded rendering is in use, false otherwise. 381 */ isEnabled()382 boolean isEnabled() { 383 return mEnabled; 384 } 385 386 /** 387 * Indicates whether threaded rendering is currently enabled. 388 * 389 * @param enabled True if the threaded renderer is in use, false otherwise. 390 */ setEnabled(boolean enabled)391 void setEnabled(boolean enabled) { 392 mEnabled = enabled; 393 } 394 395 /** 396 * Indicates whether threaded rendering is currently request but not 397 * necessarily enabled yet. 398 * 399 * @return True if requested, false otherwise. 400 */ isRequested()401 boolean isRequested() { 402 return mRequested; 403 } 404 405 /** 406 * Indicates whether threaded rendering is currently requested but not 407 * necessarily enabled yet. 408 * 409 * @return True to request threaded rendering, false otherwise. 410 */ setRequested(boolean requested)411 void setRequested(boolean requested) { 412 mRequested = requested; 413 } 414 updateEnabledState(Surface surface)415 private void updateEnabledState(Surface surface) { 416 if (surface == null || !surface.isValid()) { 417 setEnabled(false); 418 } else { 419 setEnabled(mInitialized); 420 } 421 } 422 423 /** 424 * Initializes the threaded renderer for the specified surface. 425 * 426 * @param surface The surface to render 427 * 428 * @return True if the initialization was successful, false otherwise. 429 */ initialize(Surface surface)430 boolean initialize(Surface surface) throws OutOfResourcesException { 431 boolean status = !mInitialized; 432 mInitialized = true; 433 updateEnabledState(surface); 434 nInitialize(mNativeProxy, surface); 435 return status; 436 } 437 438 /** 439 * Initializes the threaded renderer for the specified surface and setup the 440 * renderer for drawing, if needed. This is invoked when the ViewAncestor has 441 * potentially lost the threaded renderer. The threaded renderer should be 442 * reinitialized and setup when the render {@link #isRequested()} and 443 * {@link #isEnabled()}. 444 * 445 * @param width The width of the drawing surface. 446 * @param height The height of the drawing surface. 447 * @param attachInfo Information about the window. 448 * @param surface The surface to render 449 * @param surfaceInsets The drawing surface insets to apply 450 * 451 * @return true if the surface was initialized, false otherwise. Returning 452 * false might mean that the surface was already initialized. 453 */ initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, Surface surface, Rect surfaceInsets)454 boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, 455 Surface surface, Rect surfaceInsets) throws OutOfResourcesException { 456 if (isRequested()) { 457 // We lost the gl context, so recreate it. 458 if (!isEnabled()) { 459 if (initialize(surface)) { 460 setup(width, height, attachInfo, surfaceInsets); 461 return true; 462 } 463 } 464 } 465 return false; 466 } 467 468 /** 469 * Updates the threaded renderer for the specified surface. 470 * 471 * @param surface The surface to render 472 */ updateSurface(Surface surface)473 void updateSurface(Surface surface) throws OutOfResourcesException { 474 updateEnabledState(surface); 475 nUpdateSurface(mNativeProxy, surface); 476 } 477 478 /** 479 * Halts any current rendering into the surface. Use this if it is unclear whether 480 * or not the surface used by the ThreadedRenderer will be changing. It 481 * Suspends any rendering into the surface, but will not do any destruction. 482 * 483 * Any subsequent draws will override the pause, resuming normal operation. 484 */ pauseSurface(Surface surface)485 boolean pauseSurface(Surface surface) { 486 return nPauseSurface(mNativeProxy, surface); 487 } 488 489 /** 490 * Hard stops or resumes rendering into the surface. This flag is used to 491 * determine whether or not it is safe to use the given surface *at all* 492 */ setStopped(boolean stopped)493 void setStopped(boolean stopped) { 494 nSetStopped(mNativeProxy, stopped); 495 } 496 497 /** 498 * Destroys all hardware rendering resources associated with the specified 499 * view hierarchy. 500 * 501 * @param view The root of the view hierarchy 502 */ destroyHardwareResources(View view)503 void destroyHardwareResources(View view) { 504 destroyResources(view); 505 nDestroyHardwareResources(mNativeProxy); 506 } 507 destroyResources(View view)508 private static void destroyResources(View view) { 509 view.destroyHardwareResources(); 510 } 511 512 /** 513 * Detaches the layer's surface texture from the GL context and releases 514 * the texture id 515 */ detachSurfaceTexture(long hardwareLayer)516 void detachSurfaceTexture(long hardwareLayer) { 517 nDetachSurfaceTexture(mNativeProxy, hardwareLayer); 518 } 519 520 /** 521 * Sets up the renderer for drawing. 522 * 523 * @param width The width of the drawing surface. 524 * @param height The height of the drawing surface. 525 * @param attachInfo Information about the window. 526 * @param surfaceInsets The drawing surface insets to apply 527 */ setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets)528 void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) { 529 mWidth = width; 530 mHeight = height; 531 532 if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0 533 || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) { 534 mHasInsets = true; 535 mInsetLeft = surfaceInsets.left; 536 mInsetTop = surfaceInsets.top; 537 mSurfaceWidth = width + mInsetLeft + surfaceInsets.right; 538 mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom; 539 540 // If the surface has insets, it can't be opaque. 541 setOpaque(false); 542 } else { 543 mHasInsets = false; 544 mInsetLeft = 0; 545 mInsetTop = 0; 546 mSurfaceWidth = width; 547 mSurfaceHeight = height; 548 } 549 550 mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight); 551 nSetup(mNativeProxy, mLightRadius, 552 mAmbientShadowAlpha, mSpotShadowAlpha); 553 554 setLightCenter(attachInfo); 555 } 556 557 /** 558 * Updates the light position based on the position of the window. 559 * 560 * @param attachInfo Information about the window. 561 */ setLightCenter(AttachInfo attachInfo)562 void setLightCenter(AttachInfo attachInfo) { 563 // Adjust light position for window offsets. 564 final Point displaySize = attachInfo.mPoint; 565 attachInfo.mDisplay.getRealSize(displaySize); 566 final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft; 567 final float lightY = mLightY - attachInfo.mWindowTop; 568 569 nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ); 570 } 571 572 /** 573 * Change the ThreadedRenderer's opacity 574 */ setOpaque(boolean opaque)575 void setOpaque(boolean opaque) { 576 mIsOpaque = opaque && !mHasInsets; 577 nSetOpaque(mNativeProxy, mIsOpaque); 578 } 579 isOpaque()580 boolean isOpaque() { 581 return mIsOpaque; 582 } 583 584 /** 585 * Gets the current width of the surface. This is the width that the surface 586 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. 587 * 588 * @return the current width of the surface 589 */ getWidth()590 int getWidth() { 591 return mWidth; 592 } 593 594 /** 595 * Gets the current height of the surface. This is the height that the surface 596 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. 597 * 598 * @return the current width of the surface 599 */ getHeight()600 int getHeight() { 601 return mHeight; 602 } 603 604 /** 605 * Outputs extra debugging information in the specified file descriptor. 606 */ dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args)607 void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) { 608 pw.flush(); 609 int flags = 0; 610 for (int i = 0; i < args.length; i++) { 611 switch (args[i]) { 612 case "framestats": 613 flags |= FLAG_DUMP_FRAMESTATS; 614 break; 615 case "reset": 616 flags |= FLAG_DUMP_RESET; 617 break; 618 } 619 } 620 nDumpProfileInfo(mNativeProxy, fd, flags); 621 } 622 623 /** 624 * Loads system properties used by the renderer. This method is invoked 625 * whenever system properties are modified. Implementations can use this 626 * to trigger live updates of the renderer based on properties. 627 * 628 * @return True if a property has changed. 629 */ loadSystemProperties()630 boolean loadSystemProperties() { 631 boolean changed = nLoadSystemProperties(mNativeProxy); 632 if (changed) { 633 invalidateRoot(); 634 } 635 return changed; 636 } 637 updateViewTreeDisplayList(View view)638 private void updateViewTreeDisplayList(View view) { 639 view.mPrivateFlags |= View.PFLAG_DRAWN; 640 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) 641 == View.PFLAG_INVALIDATED; 642 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; 643 view.updateDisplayListIfDirty(); 644 view.mRecreateDisplayList = false; 645 } 646 updateRootDisplayList(View view, DrawCallbacks callbacks)647 private void updateRootDisplayList(View view, DrawCallbacks callbacks) { 648 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()"); 649 updateViewTreeDisplayList(view); 650 651 if (mRootNodeNeedsUpdate || !mRootNode.isValid()) { 652 DisplayListCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight); 653 try { 654 final int saveCount = canvas.save(); 655 canvas.translate(mInsetLeft, mInsetTop); 656 callbacks.onPreDraw(canvas); 657 658 canvas.insertReorderBarrier(); 659 canvas.drawRenderNode(view.updateDisplayListIfDirty()); 660 canvas.insertInorderBarrier(); 661 662 callbacks.onPostDraw(canvas); 663 canvas.restoreToCount(saveCount); 664 mRootNodeNeedsUpdate = false; 665 } finally { 666 mRootNode.end(canvas); 667 } 668 } 669 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 670 } 671 672 /** 673 * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the 674 * rendernode of the UI thread. 675 * @param node The node to add. 676 * @param placeFront If true, the render node will be placed in front of the content node, 677 * otherwise behind the content node. 678 */ addRenderNode(RenderNode node, boolean placeFront)679 public void addRenderNode(RenderNode node, boolean placeFront) { 680 nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront); 681 } 682 683 /** 684 * Only especially added render nodes can be removed. 685 * @param node The node which was added via addRenderNode which should get removed again. 686 */ removeRenderNode(RenderNode node)687 public void removeRenderNode(RenderNode node) { 688 nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode); 689 } 690 691 /** 692 * Draws a particular render node. If the node is not the content node, only the additional 693 * nodes will get drawn and the content remains untouched. 694 * @param node The node to be drawn. 695 */ drawRenderNode(RenderNode node)696 public void drawRenderNode(RenderNode node) { 697 nDrawRenderNode(mNativeProxy, node.mNativeRenderNode); 698 } 699 700 /** 701 * To avoid unnecessary overdrawing of the main content all additionally passed render nodes 702 * will be prevented to overdraw this area. It will be synchronized with the draw call. 703 * This should be updated in the content view's draw call. 704 * @param left The left side of the protected bounds. 705 * @param top The top side of the protected bounds. 706 * @param right The right side of the protected bounds. 707 * @param bottom The bottom side of the protected bounds. 708 */ setContentDrawBounds(int left, int top, int right, int bottom)709 public void setContentDrawBounds(int left, int top, int right, int bottom) { 710 nSetContentDrawBounds(mNativeProxy, left, top, right, bottom); 711 } 712 713 /** 714 * Interface used to receive callbacks whenever a view is drawn by 715 * a threaded renderer instance. 716 */ 717 interface DrawCallbacks { 718 /** 719 * Invoked before a view is drawn by a threaded renderer. 720 * This method can be used to apply transformations to the 721 * canvas but no drawing command should be issued. 722 * 723 * @param canvas The Canvas used to render the view. 724 */ onPreDraw(DisplayListCanvas canvas)725 void onPreDraw(DisplayListCanvas canvas); 726 727 /** 728 * Invoked after a view is drawn by a threaded renderer. 729 * It is safe to invoke drawing commands from this method. 730 * 731 * @param canvas The Canvas used to render the view. 732 */ onPostDraw(DisplayListCanvas canvas)733 void onPostDraw(DisplayListCanvas canvas); 734 } 735 736 /** 737 * Indicates that the content drawn by DrawCallbacks needs to 738 * be updated, which will be done by the next call to draw() 739 */ invalidateRoot()740 void invalidateRoot() { 741 mRootNodeNeedsUpdate = true; 742 } 743 744 /** 745 * Draws the specified view. 746 * 747 * @param view The view to draw. 748 * @param attachInfo AttachInfo tied to the specified view. 749 * @param callbacks Callbacks invoked when drawing happens. 750 */ draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks)751 void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) { 752 attachInfo.mIgnoreDirtyState = true; 753 754 final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer; 755 choreographer.mFrameInfo.markDrawStart(); 756 757 updateRootDisplayList(view, callbacks); 758 759 attachInfo.mIgnoreDirtyState = false; 760 761 // register animating rendernodes which started animating prior to renderer 762 // creation, which is typical for animators started prior to first draw 763 if (attachInfo.mPendingAnimatingRenderNodes != null) { 764 final int count = attachInfo.mPendingAnimatingRenderNodes.size(); 765 for (int i = 0; i < count; i++) { 766 registerAnimatingRenderNode( 767 attachInfo.mPendingAnimatingRenderNodes.get(i)); 768 } 769 attachInfo.mPendingAnimatingRenderNodes.clear(); 770 // We don't need this anymore as subsequent calls to 771 // ViewRootImpl#attachRenderNodeAnimator will go directly to us. 772 attachInfo.mPendingAnimatingRenderNodes = null; 773 } 774 775 final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo; 776 int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length); 777 if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) { 778 setEnabled(false); 779 attachInfo.mViewRootImpl.mSurface.release(); 780 // Invalidate since we failed to draw. This should fetch a Surface 781 // if it is still needed or do nothing if we are no longer drawing 782 attachInfo.mViewRootImpl.invalidate(); 783 } 784 if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) { 785 attachInfo.mViewRootImpl.invalidate(); 786 } 787 } 788 invokeFunctor(long functor, boolean waitForCompletion)789 static void invokeFunctor(long functor, boolean waitForCompletion) { 790 nInvokeFunctor(functor, waitForCompletion); 791 } 792 793 /** 794 * Creates a new hardware layer. A hardware layer built by calling this 795 * method will be treated as a texture layer, instead of as a render target. 796 * 797 * @return A hardware layer 798 */ createTextureLayer()799 HardwareLayer createTextureLayer() { 800 long layer = nCreateTextureLayer(mNativeProxy); 801 return HardwareLayer.adoptTextureLayer(this, layer); 802 } 803 804 buildLayer(RenderNode node)805 void buildLayer(RenderNode node) { 806 nBuildLayer(mNativeProxy, node.getNativeDisplayList()); 807 } 808 809 copyLayerInto(final HardwareLayer layer, final Bitmap bitmap)810 boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) { 811 return nCopyLayerInto(mNativeProxy, 812 layer.getDeferredLayerUpdater(), bitmap); 813 } 814 815 /** 816 * Indicates that the specified hardware layer needs to be updated 817 * as soon as possible. 818 * 819 * @param layer The hardware layer that needs an update 820 */ pushLayerUpdate(HardwareLayer layer)821 void pushLayerUpdate(HardwareLayer layer) { 822 nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); 823 } 824 825 /** 826 * Tells the HardwareRenderer that the layer is destroyed. The renderer 827 * should remove the layer from any update queues. 828 */ onLayerDestroyed(HardwareLayer layer)829 void onLayerDestroyed(HardwareLayer layer) { 830 nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater()); 831 } 832 833 /** 834 * Blocks until all previously queued work has completed. 835 */ fence()836 void fence() { 837 nFence(mNativeProxy); 838 } 839 840 /** 841 * Prevents any further drawing until draw() is called. This is a signal 842 * that the contents of the RenderNode tree are no longer safe to play back. 843 * In practice this usually means that there are Functor pointers in the 844 * display list that are no longer valid. 845 */ stopDrawing()846 void stopDrawing() { 847 nStopDrawing(mNativeProxy); 848 } 849 850 /** 851 * Called by {@link ViewRootImpl} when a new performTraverals is scheduled. 852 */ notifyFramePending()853 public void notifyFramePending() { 854 nNotifyFramePending(mNativeProxy); 855 } 856 857 registerAnimatingRenderNode(RenderNode animator)858 void registerAnimatingRenderNode(RenderNode animator) { 859 nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode); 860 } 861 registerVectorDrawableAnimator( AnimatedVectorDrawable.VectorDrawableAnimatorRT animator)862 void registerVectorDrawableAnimator( 863 AnimatedVectorDrawable.VectorDrawableAnimatorRT animator) { 864 nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode, 865 animator.getAnimatorNativePtr()); 866 } 867 serializeDisplayListTree()868 public void serializeDisplayListTree() { 869 nSerializeDisplayListTree(mNativeProxy); 870 } 871 copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap)872 public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) { 873 if (srcRect == null) { 874 // Empty rect means entire surface 875 return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap); 876 } else { 877 return nCopySurfaceInto(surface, srcRect.left, srcRect.top, 878 srcRect.right, srcRect.bottom, bitmap); 879 } 880 } 881 882 /** 883 * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given 884 * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and 885 * not the RenderNode from a View. 886 **/ createHardwareBitmap(RenderNode node, int width, int height)887 public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) { 888 return nCreateHardwareBitmap(node.getNativeDisplayList(), width, height); 889 } 890 891 @Override finalize()892 protected void finalize() throws Throwable { 893 try { 894 nDeleteProxy(mNativeProxy); 895 mNativeProxy = 0; 896 } finally { 897 super.finalize(); 898 } 899 } 900 901 private static class ProcessInitializer { 902 static ProcessInitializer sInstance = new ProcessInitializer(); 903 904 private boolean mInitialized = false; 905 906 private Context mAppContext; 907 private IGraphicsStats mGraphicsStatsService; 908 private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() { 909 @Override 910 public void onRotateGraphicsStatsBuffer() throws RemoteException { 911 rotateBuffer(); 912 } 913 }; 914 ProcessInitializer()915 private ProcessInitializer() {} 916 init(Context context, long renderProxy)917 synchronized void init(Context context, long renderProxy) { 918 if (mInitialized) return; 919 mInitialized = true; 920 mAppContext = context.getApplicationContext(); 921 initSched(context, renderProxy); 922 initGraphicsStats(); 923 } 924 initSched(Context context, long renderProxy)925 private void initSched(Context context, long renderProxy) { 926 try { 927 int tid = nGetRenderThreadTid(renderProxy); 928 ActivityManager.getService().setRenderThread(tid); 929 } catch (Throwable t) { 930 Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t); 931 } 932 } 933 initGraphicsStats()934 private void initGraphicsStats() { 935 try { 936 IBinder binder = ServiceManager.getService("graphicsstats"); 937 if (binder == null) return; 938 mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder); 939 requestBuffer(); 940 } catch (Throwable t) { 941 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t); 942 } 943 } 944 rotateBuffer()945 private void rotateBuffer() { 946 nRotateProcessStatsBuffer(); 947 requestBuffer(); 948 } 949 requestBuffer()950 private void requestBuffer() { 951 try { 952 final String pkg = mAppContext.getApplicationInfo().packageName; 953 ParcelFileDescriptor pfd = mGraphicsStatsService 954 .requestBufferForProcess(pkg, mGraphicsStatsCallback); 955 nSetProcessStatsBuffer(pfd.getFd()); 956 pfd.close(); 957 } catch (Throwable t) { 958 Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t); 959 } 960 } 961 } 962 addFrameMetricsObserver(FrameMetricsObserver observer)963 void addFrameMetricsObserver(FrameMetricsObserver observer) { 964 long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer); 965 observer.mNative = new VirtualRefBasePtr(nativeObserver); 966 } 967 removeFrameMetricsObserver(FrameMetricsObserver observer)968 void removeFrameMetricsObserver(FrameMetricsObserver observer) { 969 nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get()); 970 observer.mNative = null; 971 } 972 973 /** Not actually public - internal use only. This doc to make lint happy */ disableVsync()974 public static native void disableVsync(); 975 setupShadersDiskCache(String cacheFile)976 static native void setupShadersDiskCache(String cacheFile); 977 nRotateProcessStatsBuffer()978 private static native void nRotateProcessStatsBuffer(); nSetProcessStatsBuffer(int fd)979 private static native void nSetProcessStatsBuffer(int fd); nGetRenderThreadTid(long nativeProxy)980 private static native int nGetRenderThreadTid(long nativeProxy); 981 nCreateRootRenderNode()982 private static native long nCreateRootRenderNode(); nCreateProxy(boolean translucent, long rootRenderNode)983 private static native long nCreateProxy(boolean translucent, long rootRenderNode); nDeleteProxy(long nativeProxy)984 private static native void nDeleteProxy(long nativeProxy); 985 nLoadSystemProperties(long nativeProxy)986 private static native boolean nLoadSystemProperties(long nativeProxy); nSetName(long nativeProxy, String name)987 private static native void nSetName(long nativeProxy, String name); 988 nInitialize(long nativeProxy, Surface window)989 private static native void nInitialize(long nativeProxy, Surface window); nUpdateSurface(long nativeProxy, Surface window)990 private static native void nUpdateSurface(long nativeProxy, Surface window); nPauseSurface(long nativeProxy, Surface window)991 private static native boolean nPauseSurface(long nativeProxy, Surface window); nSetStopped(long nativeProxy, boolean stopped)992 private static native void nSetStopped(long nativeProxy, boolean stopped); nSetup(long nativeProxy, float lightRadius, int ambientShadowAlpha, int spotShadowAlpha)993 private static native void nSetup(long nativeProxy, 994 float lightRadius, int ambientShadowAlpha, int spotShadowAlpha); nSetLightCenter(long nativeProxy, float lightX, float lightY, float lightZ)995 private static native void nSetLightCenter(long nativeProxy, 996 float lightX, float lightY, float lightZ); nSetOpaque(long nativeProxy, boolean opaque)997 private static native void nSetOpaque(long nativeProxy, boolean opaque); nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size)998 private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size); nDestroy(long nativeProxy, long rootRenderNode)999 private static native void nDestroy(long nativeProxy, long rootRenderNode); nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode)1000 private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode); nRegisterVectorDrawableAnimator(long rootRenderNode, long animator)1001 private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator); 1002 nInvokeFunctor(long functor, boolean waitForCompletion)1003 private static native void nInvokeFunctor(long functor, boolean waitForCompletion); 1004 nCreateTextureLayer(long nativeProxy)1005 private static native long nCreateTextureLayer(long nativeProxy); nBuildLayer(long nativeProxy, long node)1006 private static native void nBuildLayer(long nativeProxy, long node); nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap)1007 private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap); nPushLayerUpdate(long nativeProxy, long layer)1008 private static native void nPushLayerUpdate(long nativeProxy, long layer); nCancelLayerUpdate(long nativeProxy, long layer)1009 private static native void nCancelLayerUpdate(long nativeProxy, long layer); nDetachSurfaceTexture(long nativeProxy, long layer)1010 private static native void nDetachSurfaceTexture(long nativeProxy, long layer); 1011 nDestroyHardwareResources(long nativeProxy)1012 private static native void nDestroyHardwareResources(long nativeProxy); nTrimMemory(int level)1013 private static native void nTrimMemory(int level); nOverrideProperty(String name, String value)1014 private static native void nOverrideProperty(String name, String value); 1015 nFence(long nativeProxy)1016 private static native void nFence(long nativeProxy); nStopDrawing(long nativeProxy)1017 private static native void nStopDrawing(long nativeProxy); nNotifyFramePending(long nativeProxy)1018 private static native void nNotifyFramePending(long nativeProxy); 1019 nSerializeDisplayListTree(long nativeProxy)1020 private static native void nSerializeDisplayListTree(long nativeProxy); 1021 nDumpProfileInfo(long nativeProxy, FileDescriptor fd, @DumpFlags int dumpFlags)1022 private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd, 1023 @DumpFlags int dumpFlags); 1024 nAddRenderNode(long nativeProxy, long rootRenderNode, boolean placeFront)1025 private static native void nAddRenderNode(long nativeProxy, long rootRenderNode, 1026 boolean placeFront); nRemoveRenderNode(long nativeProxy, long rootRenderNode)1027 private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode); nDrawRenderNode(long nativeProxy, long rootRenderNode)1028 private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode); nSetContentDrawBounds(long nativeProxy, int left, int top, int right, int bottom)1029 private static native void nSetContentDrawBounds(long nativeProxy, int left, 1030 int top, int right, int bottom); 1031 nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer)1032 private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer); nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver)1033 private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver); 1034 nCopySurfaceInto(Surface surface, int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap)1035 private static native int nCopySurfaceInto(Surface surface, 1036 int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap); 1037 nCreateHardwareBitmap(long renderNode, int width, int height)1038 private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height); 1039 } 1040