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    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 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     */
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