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.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      */
    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      */
    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      */
    207     public static boolean isAvailable() {
    208         return DisplayListCanvas.isAvailable();
    209     }
    210 
    211     /**
    212      * Destroys the hardware rendering context.
    213      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    275     abstract int getHeight();
    276 
    277     /**
    278      * Outputs extra debugging information in the specified file descriptor.
    279      */
    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      */
    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      */
    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      */
    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      */
    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          */
    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          */
    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      */
    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      */
    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      */
    361     abstract HardwareLayer createTextureLayer();
    362 
    363     abstract void buildLayer(RenderNode node);
    364 
    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      */
    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      */
    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      */
    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      */
    419     abstract void setName(String name);
    420 
    421     /**
    422      * Change the HardwareRenderer's opacity
    423      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    487     void setRequested(boolean requested) {
    488         mRequested = requested;
    489     }
    490 
    491     /**
    492      * Blocks until all previously queued work has completed.
    493      */
    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      */
    502     abstract void stopDrawing();
    503 
    504     /**
    505      * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
    506      */
    507     abstract void notifyFramePending();
    508 
    509     abstract void registerAnimatingRenderNode(RenderNode animator);
    510 }
    511