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