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.content.Context; 20 import android.graphics.Bitmap; 21 import android.graphics.Rect; 22 import android.view.Surface.OutOfResourcesException; 23 24 import java.io.File; 25 import java.io.FileDescriptor; 26 import java.io.PrintWriter; 27 28 /** 29 * Interface for rendering a view hierarchy using hardware acceleration. 30 * 31 * @hide 32 */ 33 public abstract class HardwareRenderer { 34 static final String LOG_TAG = "HardwareRenderer"; 35 36 /** 37 * Name of the file that holds the shaders cache. 38 */ 39 private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache"; 40 41 /** 42 * System property used to enable or disable dirty regions invalidation. 43 * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true. 44 * The default value of this property is assumed to be true. 45 * 46 * Possible values: 47 * "true", to enable partial invalidates 48 * "false", to disable partial invalidates 49 */ 50 static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions"; 51 52 /** 53 * System property used to enable or disable hardware rendering profiling. 54 * The default value of this property is assumed to be false. 55 * 56 * When profiling is enabled, the adb shell dumpsys gfxinfo command will 57 * output extra information about the time taken to execute by the last 58 * frames. 59 * 60 * Possible values: 61 * "true", to enable profiling 62 * "visual_bars", to enable profiling and visualize the results on screen 63 * "false", to disable profiling 64 * 65 * @see #PROFILE_PROPERTY_VISUALIZE_BARS 66 * 67 * @hide 68 */ 69 public static final String PROFILE_PROPERTY = "debug.hwui.profile"; 70 71 /** 72 * Value for {@link #PROFILE_PROPERTY}. When the property is set to this 73 * value, profiling data will be visualized on screen as a bar chart. 74 * 75 * @hide 76 */ 77 public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars"; 78 79 /** 80 * System property used to specify the number of frames to be used 81 * when doing hardware rendering profiling. 82 * The default value of this property is #PROFILE_MAX_FRAMES. 83 * 84 * When profiling is enabled, the adb shell dumpsys gfxinfo command will 85 * output extra information about the time taken to execute by the last 86 * frames. 87 * 88 * Possible values: 89 * "60", to set the limit of frames to 60 90 */ 91 static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes"; 92 93 /** 94 * System property used to debug EGL configuration choice. 95 * 96 * Possible values: 97 * "choice", print the chosen configuration only 98 * "all", print all possible configurations 99 */ 100 static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config"; 101 102 /** 103 * Turn on to draw dirty regions every other frame. 104 * 105 * Possible values: 106 * "true", to enable dirty regions debugging 107 * "false", to disable dirty regions debugging 108 * 109 * @hide 110 */ 111 public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions"; 112 113 /** 114 * Turn on to flash hardware layers when they update. 115 * 116 * Possible values: 117 * "true", to enable hardware layers updates debugging 118 * "false", to disable hardware layers updates debugging 119 * 120 * @hide 121 */ 122 public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY = 123 "debug.hwui.show_layers_updates"; 124 125 /** 126 * Controls overdraw debugging. 127 * 128 * Possible values: 129 * "false", to disable overdraw debugging 130 * "show", to show overdraw areas on screen 131 * "count", to display an overdraw counter 132 * 133 * @hide 134 */ 135 public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw"; 136 137 /** 138 * Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this 139 * value, overdraw will be shown on screen by coloring pixels. 140 * 141 * @hide 142 */ 143 public static final String OVERDRAW_PROPERTY_SHOW = "show"; 144 145 /** 146 * Turn on to debug non-rectangular clip operations. 147 * 148 * Possible values: 149 * "hide", to disable this debug mode 150 * "highlight", highlight drawing commands tested against a non-rectangular clip 151 * "stencil", renders the clip region on screen when set 152 * 153 * @hide 154 */ 155 public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY = 156 "debug.hwui.show_non_rect_clip"; 157 158 /** 159 * A process can set this flag to false to prevent the use of hardware 160 * rendering. 161 * 162 * @hide 163 */ 164 public static boolean sRendererDisabled = false; 165 166 /** 167 * Further hardware renderer disabling for the system process. 168 * 169 * @hide 170 */ 171 public static boolean sSystemRendererDisabled = false; 172 173 private boolean mEnabled; 174 private boolean mRequested = true; 175 176 /** 177 * Invoke this method to disable hardware rendering in the current process. 178 * 179 * @hide 180 */ disable(boolean system)181 public static void disable(boolean system) { 182 sRendererDisabled = true; 183 if (system) { 184 sSystemRendererDisabled = true; 185 } 186 } 187 188 public static boolean sTrimForeground = false; 189 190 /** 191 * Controls whether or not the hardware renderer should aggressively 192 * trim memory. Note that this must not be set for any process that 193 * uses WebView! This should be only used by system_process or similar 194 * that do not go into the background. 195 */ enableForegroundTrimming()196 public static void enableForegroundTrimming() { 197 sTrimForeground = true; 198 } 199 200 /** 201 * Indicates whether hardware acceleration is available under any form for 202 * the view hierarchy. 203 * 204 * @return True if the view hierarchy can potentially be hardware accelerated, 205 * false otherwise 206 */ isAvailable()207 public static boolean isAvailable() { 208 return DisplayListCanvas.isAvailable(); 209 } 210 211 /** 212 * Destroys the hardware rendering context. 213 */ destroy()214 abstract void destroy(); 215 216 /** 217 * Initializes the hardware renderer for the specified surface. 218 * 219 * @param surface The surface to hardware accelerate 220 * 221 * @return True if the initialization was successful, false otherwise. 222 */ initialize(Surface surface)223 abstract boolean initialize(Surface surface) throws OutOfResourcesException; 224 225 /** 226 * Updates the hardware renderer for the specified surface. 227 * 228 * @param surface The surface to hardware accelerate 229 */ updateSurface(Surface surface)230 abstract void updateSurface(Surface surface) throws OutOfResourcesException; 231 232 /** 233 * Stops any rendering into the surface. Use this if it is unclear whether 234 * or not the surface used by the HardwareRenderer will be changing. It 235 * Suspends any rendering into the surface, but will not do any destruction 236 */ pauseSurface(Surface surface)237 abstract boolean pauseSurface(Surface surface); 238 239 /** 240 * Destroys all hardware rendering resources associated with the specified 241 * view hierarchy. 242 * 243 * @param view The root of the view hierarchy 244 */ destroyHardwareResources(View view)245 abstract void destroyHardwareResources(View view); 246 247 /** 248 * This method should be invoked whenever the current hardware renderer 249 * context should be reset. 250 * 251 * @param surface The surface to hardware accelerate 252 */ invalidate(Surface surface)253 abstract void invalidate(Surface surface); 254 255 /** 256 * Detaches the layer's surface texture from the GL context and releases 257 * the texture id 258 */ detachSurfaceTexture(long hardwareLayer)259 abstract void detachSurfaceTexture(long hardwareLayer); 260 261 /** 262 * Gets the current width of the surface. This is the width that the surface 263 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. 264 * 265 * @return the current width of the surface 266 */ getWidth()267 abstract int getWidth(); 268 269 /** 270 * Gets the current height of the surface. This is the height that the surface 271 * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}. 272 * 273 * @return the current width of the surface 274 */ getHeight()275 abstract int getHeight(); 276 277 /** 278 * Outputs extra debugging information in the specified file descriptor. 279 */ dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args)280 abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args); 281 282 /** 283 * Loads system properties used by the renderer. This method is invoked 284 * whenever system properties are modified. Implementations can use this 285 * to trigger live updates of the renderer based on properties. 286 * 287 * @return True if a property has changed. 288 */ loadSystemProperties()289 abstract boolean loadSystemProperties(); 290 291 /** 292 * Sets the directory to use as a persistent storage for hardware rendering 293 * resources. 294 * 295 * @param cacheDir A directory the current process can write to 296 * 297 * @hide 298 */ setupDiskCache(File cacheDir)299 public static void setupDiskCache(File cacheDir) { 300 ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath()); 301 } 302 303 /** 304 * Indicates that the specified hardware layer needs to be updated 305 * as soon as possible. 306 * 307 * @param layer The hardware layer that needs an update 308 */ pushLayerUpdate(HardwareLayer layer)309 abstract void pushLayerUpdate(HardwareLayer layer); 310 311 /** 312 * Tells the HardwareRenderer that the layer is destroyed. The renderer 313 * should remove the layer from any update queues. 314 */ onLayerDestroyed(HardwareLayer layer)315 abstract void onLayerDestroyed(HardwareLayer layer); 316 317 /** 318 * Interface used to receive callbacks whenever a view is drawn by 319 * a hardware renderer instance. 320 */ 321 interface HardwareDrawCallbacks { 322 /** 323 * Invoked before a view is drawn by a hardware renderer. 324 * This method can be used to apply transformations to the 325 * canvas but no drawing command should be issued. 326 * 327 * @param canvas The Canvas used to render the view. 328 */ onHardwarePreDraw(DisplayListCanvas canvas)329 void onHardwarePreDraw(DisplayListCanvas canvas); 330 331 /** 332 * Invoked after a view is drawn by a hardware renderer. 333 * It is safe to invoke drawing commands from this method. 334 * 335 * @param canvas The Canvas used to render the view. 336 */ onHardwarePostDraw(DisplayListCanvas canvas)337 void onHardwarePostDraw(DisplayListCanvas canvas); 338 } 339 340 /** 341 * Indicates that the content drawn by HardwareDrawCallbacks needs to 342 * be updated, which will be done by the next call to draw() 343 */ invalidateRoot()344 abstract void invalidateRoot(); 345 346 /** 347 * Draws the specified view. 348 * 349 * @param view The view to draw. 350 * @param attachInfo AttachInfo tied to the specified view. 351 * @param callbacks Callbacks invoked when drawing happens. 352 */ draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks)353 abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks); 354 355 /** 356 * Creates a new hardware layer. A hardware layer built by calling this 357 * method will be treated as a texture layer, instead of as a render target. 358 * 359 * @return A hardware layer 360 */ createTextureLayer()361 abstract HardwareLayer createTextureLayer(); 362 buildLayer(RenderNode node)363 abstract void buildLayer(RenderNode node); 364 copyLayerInto(HardwareLayer layer, Bitmap bitmap)365 abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap); 366 367 /** 368 * Initializes the hardware renderer for the specified surface and setup the 369 * renderer for drawing, if needed. This is invoked when the ViewAncestor has 370 * potentially lost the hardware renderer. The hardware renderer should be 371 * reinitialized and setup when the render {@link #isRequested()} and 372 * {@link #isEnabled()}. 373 * 374 * @param width The width of the drawing surface. 375 * @param height The height of the drawing surface. 376 * @param attachInfo Information about the window. 377 * @param surface The surface to hardware accelerate 378 * @param surfaceInsets The drawing surface insets to apply 379 * 380 * @return true if the surface was initialized, false otherwise. Returning 381 * false might mean that the surface was already initialized. 382 */ initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, Surface surface, Rect surfaceInsets)383 boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, 384 Surface surface, Rect surfaceInsets) throws OutOfResourcesException { 385 if (isRequested()) { 386 // We lost the gl context, so recreate it. 387 if (!isEnabled()) { 388 if (initialize(surface)) { 389 setup(width, height, attachInfo, surfaceInsets); 390 return true; 391 } 392 } 393 } 394 return false; 395 } 396 397 /** 398 * Sets up the renderer for drawing. 399 * 400 * @param width The width of the drawing surface. 401 * @param height The height of the drawing surface. 402 * @param attachInfo Information about the window. 403 * @param surfaceInsets The drawing surface insets to apply 404 */ setup(int width, int height, View.AttachInfo attachInfo, Rect surfaceInsets)405 abstract void setup(int width, int height, View.AttachInfo attachInfo, Rect surfaceInsets); 406 407 /** 408 * Updates the light position based on the position of the window. 409 * 410 * @param attachInfo Information about the window. 411 */ setLightCenter(View.AttachInfo attachInfo)412 abstract void setLightCenter(View.AttachInfo attachInfo); 413 414 /** 415 * Optional, sets the name of the renderer. Useful for debugging purposes. 416 * 417 * @param name The name of this renderer, can be null 418 */ setName(String name)419 abstract void setName(String name); 420 421 /** 422 * Change the HardwareRenderer's opacity 423 */ setOpaque(boolean opaque)424 abstract void setOpaque(boolean opaque); 425 426 /** 427 * Creates a hardware renderer using OpenGL. 428 * 429 * @param translucent True if the surface is translucent, false otherwise 430 * 431 * @return A hardware renderer backed by OpenGL. 432 */ create(Context context, boolean translucent)433 static HardwareRenderer create(Context context, boolean translucent) { 434 HardwareRenderer renderer = null; 435 if (DisplayListCanvas.isAvailable()) { 436 renderer = new ThreadedRenderer(context, translucent); 437 } 438 return renderer; 439 } 440 441 /** 442 * Invoke this method when the system is running out of memory. This 443 * method will attempt to recover as much memory as possible, based on 444 * the specified hint. 445 * 446 * @param level Hint about the amount of memory that should be trimmed, 447 * see {@link android.content.ComponentCallbacks} 448 */ trimMemory(int level)449 static void trimMemory(int level) { 450 ThreadedRenderer.trimMemory(level); 451 } 452 453 /** 454 * Indicates whether hardware acceleration is currently enabled. 455 * 456 * @return True if hardware acceleration is in use, false otherwise. 457 */ isEnabled()458 boolean isEnabled() { 459 return mEnabled; 460 } 461 462 /** 463 * Indicates whether hardware acceleration is currently enabled. 464 * 465 * @param enabled True if the hardware renderer is in use, false otherwise. 466 */ setEnabled(boolean enabled)467 void setEnabled(boolean enabled) { 468 mEnabled = enabled; 469 } 470 471 /** 472 * Indicates whether hardware acceleration is currently request but not 473 * necessarily enabled yet. 474 * 475 * @return True if requested, false otherwise. 476 */ isRequested()477 boolean isRequested() { 478 return mRequested; 479 } 480 481 /** 482 * Indicates whether hardware acceleration is currently requested but not 483 * necessarily enabled yet. 484 * 485 * @return True to request hardware acceleration, false otherwise. 486 */ setRequested(boolean requested)487 void setRequested(boolean requested) { 488 mRequested = requested; 489 } 490 491 /** 492 * Blocks until all previously queued work has completed. 493 */ fence()494 abstract void fence(); 495 496 /** 497 * Prevents any further drawing until draw() is called. This is a signal 498 * that the contents of the RenderNode tree are no longer safe to play back. 499 * In practice this usually means that there are Functor pointers in the 500 * display list that are no longer valid. 501 */ stopDrawing()502 abstract void stopDrawing(); 503 504 /** 505 * Called by {@link ViewRootImpl} when a new performTraverals is scheduled. 506 */ notifyFramePending()507 abstract void notifyFramePending(); 508 registerAnimatingRenderNode(RenderNode animator)509 abstract void registerAnimatingRenderNode(RenderNode animator); 510 } 511