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.view.Surface.OutOfResourcesException;
23
24import java.io.File;
25import java.io.FileDescriptor;
26import java.io.PrintWriter;
27
28/**
29 * Interface for rendering a view hierarchy using hardware acceleration.
30 *
31 * @hide
32 */
33public 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