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