Home | History | Annotate | Download | only in view
      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      */
    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      */
    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      */
    208     public static boolean isAvailable() {
    209         return GLES20Canvas.isAvailable();
    210     }
    211 
    212     /**
    213      * Destroys the hardware rendering context.
    214      */
    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      */
    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      */
    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      */
    238     abstract void 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      */
    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      */
    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      */
    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      */
    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      */
    276     abstract int getHeight();
    277 
    278     /**
    279      * Outputs extra debugging information in the specified file descriptor.
    280      */
    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      */
    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      */
    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      */
    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      */
    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          */
    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          */
    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      */
    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      */
    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      */
    362     abstract HardwareLayer createTextureLayer();
    363 
    364     abstract void buildLayer(RenderNode node);
    365 
    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      */
    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      */
    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      */
    411     abstract void setName(String name);
    412 
    413     /**
    414      * Change the HardwareRenderer's opacity
    415      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    479     void setRequested(boolean requested) {
    480         mRequested = requested;
    481     }
    482 
    483     /**
    484      * Blocks until all previously queued work has completed.
    485      */
    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      */
    494     abstract void stopDrawing();
    495 
    496     /**
    497      * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
    498      */
    499     abstract void notifyFramePending();
    500 
    501     abstract void registerAnimatingRenderNode(RenderNode animator);
    502 }
    503