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      */
disable(boolean system)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      */
enableForegroundTrimming()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      */
isAvailable()207     public static boolean isAvailable() {
208         return DisplayListCanvas.isAvailable();
209     }
210 
211     /**
212      * Destroys the hardware rendering context.
213      */
destroy()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      */
initialize(Surface surface)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      */
updateSurface(Surface surface)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      */
pauseSurface(Surface surface)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      */
destroyHardwareResources(View view)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      */
invalidate(Surface surface)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      */
detachSurfaceTexture(long hardwareLayer)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      */
getWidth()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      */
getHeight()275     abstract int getHeight();
276 
277     /**
278      * Outputs extra debugging information in the specified file descriptor.
279      */
dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args)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      */
loadSystemProperties()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      */
setupDiskCache(File cacheDir)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      */
pushLayerUpdate(HardwareLayer layer)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      */
onLayerDestroyed(HardwareLayer layer)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          */
onHardwarePreDraw(DisplayListCanvas canvas)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          */
onHardwarePostDraw(DisplayListCanvas canvas)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      */
invalidateRoot()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      */
draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks)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      */
createTextureLayer()361     abstract HardwareLayer createTextureLayer();
362 
buildLayer(RenderNode node)363     abstract void buildLayer(RenderNode node);
364 
copyLayerInto(HardwareLayer layer, Bitmap bitmap)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      */
initializeIfNeeded(int width, int height, View.AttachInfo attachInfo, Surface surface, Rect surfaceInsets)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      */
setup(int width, int height, View.AttachInfo attachInfo, Rect surfaceInsets)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      */
setLightCenter(View.AttachInfo attachInfo)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      */
setName(String name)419     abstract void setName(String name);
420 
421     /**
422      * Change the HardwareRenderer's opacity
423      */
setOpaque(boolean opaque)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      */
create(Context context, boolean translucent)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      */
trimMemory(int level)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      */
isEnabled()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      */
setEnabled(boolean enabled)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      */
isRequested()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      */
setRequested(boolean requested)487     void setRequested(boolean requested) {
488         mRequested = requested;
489     }
490 
491     /**
492      * Blocks until all previously queued work has completed.
493      */
fence()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      */
stopDrawing()502     abstract void stopDrawing();
503 
504     /**
505      * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
506      */
notifyFramePending()507     abstract void notifyFramePending();
508 
registerAnimatingRenderNode(RenderNode animator)509     abstract void registerAnimatingRenderNode(RenderNode animator);
510 }
511