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