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