HardwareRenderer.java revision 3e8249568cc428296ac76c7ddce3f0382d40fe5b
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
17package android.view;
18
19import android.content.Context;
20import android.graphics.Bitmap;
21import android.graphics.Rect;
22import android.util.DisplayMetrics;
23import android.view.Surface.OutOfResourcesException;
24
25import java.io.File;
26import java.io.FileDescriptor;
27import java.io.PrintWriter;
28
29/**
30 * Interface for rendering a view hierarchy using hardware acceleration.
31 *
32 * @hide
33 */
34public 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    /**
190     * Indicates whether hardware acceleration is available under any form for
191     * the view hierarchy.
192     *
193     * @return True if the view hierarchy can potentially be hardware accelerated,
194     *         false otherwise
195     */
196    public static boolean isAvailable() {
197        return GLES20Canvas.isAvailable();
198    }
199
200    /**
201     * Destroys the hardware rendering context.
202     */
203    abstract void destroy();
204
205    /**
206     * Initializes the hardware renderer for the specified surface.
207     *
208     * @param surface The surface to hardware accelerate
209     *
210     * @return True if the initialization was successful, false otherwise.
211     */
212    abstract boolean initialize(Surface surface) throws OutOfResourcesException;
213
214    /**
215     * Updates the hardware renderer for the specified surface.
216     *
217     * @param surface The surface to hardware accelerate
218     */
219    abstract void updateSurface(Surface surface) throws OutOfResourcesException;
220
221    /**
222     * Stops any rendering into the surface. Use this if it is unclear whether
223     * or not the surface used by the HardwareRenderer will be changing. It
224     * Suspends any rendering into the surface, but will not do any destruction
225     */
226    abstract void pauseSurface(Surface surface);
227
228    /**
229     * Destroys all hardware rendering resources associated with the specified
230     * view hierarchy.
231     *
232     * @param view The root of the view hierarchy
233     */
234    abstract void destroyHardwareResources(View view);
235
236    /**
237     * This method should be invoked whenever the current hardware renderer
238     * context should be reset.
239     *
240     * @param surface The surface to hardware accelerate
241     */
242    abstract void invalidate(Surface surface);
243
244    /**
245     * Detaches the layer's surface texture from the GL context and releases
246     * the texture id
247     */
248    abstract void detachSurfaceTexture(long hardwareLayer);
249
250    /**
251     * Gets the current width of the surface. This is the width that the surface
252     * was last set to in a call to {@link #setup(int, int, Rect)}.
253     *
254     * @return the current width of the surface
255     */
256    abstract int getWidth();
257
258    /**
259     * Gets the current height of the surface. This is the height that the surface
260     * was last set to in a call to {@link #setup(int, int, Rect)}.
261     *
262     * @return the current width of the surface
263     */
264    abstract int getHeight();
265
266    /**
267     * Outputs extra debugging information in the specified file descriptor.
268     */
269    abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd);
270
271    /**
272     * Loads system properties used by the renderer. This method is invoked
273     * whenever system properties are modified. Implementations can use this
274     * to trigger live updates of the renderer based on properties.
275     *
276     * @return True if a property has changed.
277     */
278    abstract boolean loadSystemProperties();
279
280    /**
281     * Sets the directory to use as a persistent storage for hardware rendering
282     * resources.
283     *
284     * @param cacheDir A directory the current process can write to
285     *
286     * @hide
287     */
288    public static void setupDiskCache(File cacheDir) {
289        ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
290    }
291
292    /**
293     * Indicates that the specified hardware layer needs to be updated
294     * as soon as possible.
295     *
296     * @param layer The hardware layer that needs an update
297     */
298    abstract void pushLayerUpdate(HardwareLayer layer);
299
300    /**
301     * Tells the HardwareRenderer that the layer is destroyed. The renderer
302     * should remove the layer from any update queues.
303     */
304    abstract void onLayerDestroyed(HardwareLayer layer);
305
306    /**
307     * Interface used to receive callbacks whenever a view is drawn by
308     * a hardware renderer instance.
309     */
310    interface HardwareDrawCallbacks {
311        /**
312         * Invoked before a view is drawn by a hardware renderer.
313         * This method can be used to apply transformations to the
314         * canvas but no drawing command should be issued.
315         *
316         * @param canvas The Canvas used to render the view.
317         */
318        void onHardwarePreDraw(HardwareCanvas canvas);
319
320        /**
321         * Invoked after a view is drawn by a hardware renderer.
322         * It is safe to invoke drawing commands from this method.
323         *
324         * @param canvas The Canvas used to render the view.
325         */
326        void onHardwarePostDraw(HardwareCanvas canvas);
327    }
328
329    /**
330     *  Indicates that the content drawn by HardwareDrawCallbacks needs to
331     *  be updated, which will be done by the next call to draw()
332     */
333    abstract void invalidateRoot();
334
335    /**
336     * Draws the specified view.
337     *
338     * @param view The view to draw.
339     * @param attachInfo AttachInfo tied to the specified view.
340     * @param callbacks Callbacks invoked when drawing happens.
341     */
342    abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
343
344    /**
345     * Creates a new hardware layer. A hardware layer built by calling this
346     * method will be treated as a texture layer, instead of as a render target.
347     *
348     * @return A hardware layer
349     */
350    abstract HardwareLayer createTextureLayer();
351
352    abstract void buildLayer(RenderNode node);
353
354    abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
355
356    /**
357     * Initializes the hardware renderer for the specified surface and setup the
358     * renderer for drawing, if needed. This is invoked when the ViewAncestor has
359     * potentially lost the hardware renderer. The hardware renderer should be
360     * reinitialized and setup when the render {@link #isRequested()} and
361     * {@link #isEnabled()}.
362     *
363     * @param width The width of the drawing surface.
364     * @param height The height of the drawing surface.
365     * @param surface The surface to hardware accelerate
366     * @param surfaceInsets The drawing surface insets to apply
367     *
368     * @return true if the surface was initialized, false otherwise. Returning
369     *         false might mean that the surface was already initialized.
370     */
371    boolean initializeIfNeeded(int width, int height, Surface surface, Rect surfaceInsets)
372            throws OutOfResourcesException {
373        if (isRequested()) {
374            // We lost the gl context, so recreate it.
375            if (!isEnabled()) {
376                if (initialize(surface)) {
377                    setup(width, height, surfaceInsets);
378                    return true;
379                }
380            }
381        }
382        return false;
383    }
384
385    /**
386     * Sets up the renderer for drawing.
387     *
388     * @param width The width of the drawing surface.
389     * @param height The height of the drawing surface.
390     * @param surfaceInsets The drawing surface insets to apply
391     */
392    abstract void setup(int width, int height, Rect surfaceInsets);
393
394    /**
395     * Optional, sets the name of the renderer. Useful for debugging purposes.
396     *
397     * @param name The name of this renderer, can be null
398     */
399    abstract void setName(String name);
400
401    /**
402     * Change the HardwareRenderer's opacity
403     */
404    abstract void setOpaque(boolean opaque);
405
406    /**
407     * Creates a hardware renderer using OpenGL.
408     *
409     * @param translucent True if the surface is translucent, false otherwise
410     *
411     * @return A hardware renderer backed by OpenGL.
412     */
413    static HardwareRenderer create(Context context, boolean translucent) {
414        HardwareRenderer renderer = null;
415        if (GLES20Canvas.isAvailable()) {
416            renderer = new ThreadedRenderer(context, translucent);
417        }
418        return renderer;
419    }
420
421    /**
422     * Invoke this method when the system is running out of memory. This
423     * method will attempt to recover as much memory as possible, based on
424     * the specified hint.
425     *
426     * @param level Hint about the amount of memory that should be trimmed,
427     *              see {@link android.content.ComponentCallbacks}
428     */
429    static void trimMemory(int level) {
430        ThreadedRenderer.trimMemory(level);
431    }
432
433    /**
434     * Indicates whether hardware acceleration is currently enabled.
435     *
436     * @return True if hardware acceleration is in use, false otherwise.
437     */
438    boolean isEnabled() {
439        return mEnabled;
440    }
441
442    /**
443     * Indicates whether hardware acceleration is currently enabled.
444     *
445     * @param enabled True if the hardware renderer is in use, false otherwise.
446     */
447    void setEnabled(boolean enabled) {
448        mEnabled = enabled;
449    }
450
451    /**
452     * Indicates whether hardware acceleration is currently request but not
453     * necessarily enabled yet.
454     *
455     * @return True if requested, false otherwise.
456     */
457    boolean isRequested() {
458        return mRequested;
459    }
460
461    /**
462     * Indicates whether hardware acceleration is currently requested but not
463     * necessarily enabled yet.
464     *
465     * @return True to request hardware acceleration, false otherwise.
466     */
467    void setRequested(boolean requested) {
468        mRequested = requested;
469    }
470
471    /**
472     * Blocks until all previously queued work has completed.
473     */
474    abstract void fence();
475
476    /**
477     * Prevents any further drawing until draw() is called. This is a signal
478     * that the contents of the RenderNode tree are no longer safe to play back.
479     * In practice this usually means that there are Functor pointers in the
480     * display list that are no longer valid.
481     */
482    abstract void stopDrawing();
483
484    /**
485     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
486     */
487    abstract void notifyFramePending();
488}
489