blob: edb3798844411d4671291861368674a8fc5695df [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.Surface.OutOfResourcesException;
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Interface for rendering a view hierarchy using hardware acceleration.
*
* @hide
*/
public abstract class HardwareRenderer {
static final String LOG_TAG = "HardwareRenderer";
/**
* Name of the file that holds the shaders cache.
*/
private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
/**
* System property used to enable or disable dirty regions invalidation.
* This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
* The default value of this property is assumed to be true.
*
* Possible values:
* "true", to enable partial invalidates
* "false", to disable partial invalidates
*/
static final String RENDER_DIRTY_REGIONS_PROPERTY = "debug.hwui.render_dirty_regions";
/**
* System property used to enable or disable hardware rendering profiling.
* The default value of this property is assumed to be false.
*
* When profiling is enabled, the adb shell dumpsys gfxinfo command will
* output extra information about the time taken to execute by the last
* frames.
*
* Possible values:
* "true", to enable profiling
* "visual_bars", to enable profiling and visualize the results on screen
* "false", to disable profiling
*
* @see #PROFILE_PROPERTY_VISUALIZE_BARS
*
* @hide
*/
public static final String PROFILE_PROPERTY = "debug.hwui.profile";
/**
* Value for {@link #PROFILE_PROPERTY}. When the property is set to this
* value, profiling data will be visualized on screen as a bar chart.
*
* @hide
*/
public static final String PROFILE_PROPERTY_VISUALIZE_BARS = "visual_bars";
/**
* System property used to specify the number of frames to be used
* when doing hardware rendering profiling.
* The default value of this property is #PROFILE_MAX_FRAMES.
*
* When profiling is enabled, the adb shell dumpsys gfxinfo command will
* output extra information about the time taken to execute by the last
* frames.
*
* Possible values:
* "60", to set the limit of frames to 60
*/
static final String PROFILE_MAXFRAMES_PROPERTY = "debug.hwui.profile.maxframes";
/**
* System property used to debug EGL configuration choice.
*
* Possible values:
* "choice", print the chosen configuration only
* "all", print all possible configurations
*/
static final String PRINT_CONFIG_PROPERTY = "debug.hwui.print_config";
/**
* Turn on to draw dirty regions every other frame.
*
* Possible values:
* "true", to enable dirty regions debugging
* "false", to disable dirty regions debugging
*
* @hide
*/
public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
/**
* Turn on to flash hardware layers when they update.
*
* Possible values:
* "true", to enable hardware layers updates debugging
* "false", to disable hardware layers updates debugging
*
* @hide
*/
public static final String DEBUG_SHOW_LAYERS_UPDATES_PROPERTY =
"debug.hwui.show_layers_updates";
/**
* Controls overdraw debugging.
*
* Possible values:
* "false", to disable overdraw debugging
* "show", to show overdraw areas on screen
* "count", to display an overdraw counter
*
* @hide
*/
public static final String DEBUG_OVERDRAW_PROPERTY = "debug.hwui.overdraw";
/**
* Value for {@link #DEBUG_OVERDRAW_PROPERTY}. When the property is set to this
* value, overdraw will be shown on screen by coloring pixels.
*
* @hide
*/
public static final String OVERDRAW_PROPERTY_SHOW = "show";
/**
* Turn on to debug non-rectangular clip operations.
*
* Possible values:
* "hide", to disable this debug mode
* "highlight", highlight drawing commands tested against a non-rectangular clip
* "stencil", renders the clip region on screen when set
*
* @hide
*/
public static final String DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY =
"debug.hwui.show_non_rect_clip";
/**
* A process can set this flag to false to prevent the use of hardware
* rendering.
*
* @hide
*/
public static boolean sRendererDisabled = false;
/**
* Further hardware renderer disabling for the system process.
*
* @hide
*/
public static boolean sSystemRendererDisabled = false;
private boolean mEnabled;
private boolean mRequested = true;
/**
* Invoke this method to disable hardware rendering in the current process.
*
* @hide
*/
public static void disable(boolean system) {
sRendererDisabled = true;
if (system) {
sSystemRendererDisabled = true;
}
}
/**
* Indicates whether hardware acceleration is available under any form for
* the view hierarchy.
*
* @return True if the view hierarchy can potentially be hardware accelerated,
* false otherwise
*/
public static boolean isAvailable() {
return GLES20Canvas.isAvailable();
}
/**
* Destroys the hardware rendering context.
*/
abstract void destroy();
/**
* Initializes the hardware renderer for the specified surface.
*
* @param surface The surface to hardware accelerate
*
* @return True if the initialization was successful, false otherwise.
*/
abstract boolean initialize(Surface surface) throws OutOfResourcesException;
/**
* Updates the hardware renderer for the specified surface.
*
* @param surface The surface to hardware accelerate
*/
abstract void updateSurface(Surface surface) throws OutOfResourcesException;
/**
* Stops any rendering into the surface. Use this if it is unclear whether
* or not the surface used by the HardwareRenderer will be changing. It
* Suspends any rendering into the surface, but will not do any destruction
*/
abstract void pauseSurface(Surface surface);
/**
* Destroys all hardware rendering resources associated with the specified
* view hierarchy.
*
* @param view The root of the view hierarchy
*/
abstract void destroyHardwareResources(View view);
/**
* This method should be invoked whenever the current hardware renderer
* context should be reset.
*
* @param surface The surface to hardware accelerate
*/
abstract void invalidate(Surface surface);
/**
* Detaches the layer's surface texture from the GL context and releases
* the texture id
*/
abstract void detachSurfaceTexture(long hardwareLayer);
/**
* Gets the current width of the surface. This is the width that the surface
* was last set to in a call to {@link #setup(int, int, Rect)}.
*
* @return the current width of the surface
*/
abstract int getWidth();
/**
* Gets the current height of the surface. This is the height that the surface
* was last set to in a call to {@link #setup(int, int, Rect)}.
*
* @return the current width of the surface
*/
abstract int getHeight();
/**
* Outputs extra debugging information in the specified file descriptor.
*/
abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd);
/**
* Loads system properties used by the renderer. This method is invoked
* whenever system properties are modified. Implementations can use this
* to trigger live updates of the renderer based on properties.
*
* @return True if a property has changed.
*/
abstract boolean loadSystemProperties();
/**
* Sets the directory to use as a persistent storage for hardware rendering
* resources.
*
* @param cacheDir A directory the current process can write to
*
* @hide
*/
public static void setupDiskCache(File cacheDir) {
ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
}
/**
* Indicates that the specified hardware layer needs to be updated
* as soon as possible.
*
* @param layer The hardware layer that needs an update
*/
abstract void pushLayerUpdate(HardwareLayer layer);
/**
* Tells the HardwareRenderer that the layer is destroyed. The renderer
* should remove the layer from any update queues.
*/
abstract void onLayerDestroyed(HardwareLayer layer);
/**
* Interface used to receive callbacks whenever a view is drawn by
* a hardware renderer instance.
*/
interface HardwareDrawCallbacks {
/**
* Invoked before a view is drawn by a hardware renderer.
* This method can be used to apply transformations to the
* canvas but no drawing command should be issued.
*
* @param canvas The Canvas used to render the view.
*/
void onHardwarePreDraw(HardwareCanvas canvas);
/**
* Invoked after a view is drawn by a hardware renderer.
* It is safe to invoke drawing commands from this method.
*
* @param canvas The Canvas used to render the view.
*/
void onHardwarePostDraw(HardwareCanvas canvas);
}
/**
* Indicates that the content drawn by HardwareDrawCallbacks needs to
* be updated, which will be done by the next call to draw()
*/
abstract void invalidateRoot();
/**
* Draws the specified view.
*
* @param view The view to draw.
* @param attachInfo AttachInfo tied to the specified view.
* @param callbacks Callbacks invoked when drawing happens.
*/
abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
/**
* Creates a new hardware layer. A hardware layer built by calling this
* method will be treated as a texture layer, instead of as a render target.
*
* @return A hardware layer
*/
abstract HardwareLayer createTextureLayer();
abstract void buildLayer(RenderNode node);
abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
/**
* Initializes the hardware renderer for the specified surface and setup the
* renderer for drawing, if needed. This is invoked when the ViewAncestor has
* potentially lost the hardware renderer. The hardware renderer should be
* reinitialized and setup when the render {@link #isRequested()} and
* {@link #isEnabled()}.
*
* @param width The width of the drawing surface.
* @param height The height of the drawing surface.
* @param surface The surface to hardware accelerate
* @param surfaceInsets The drawing surface insets to apply
*
* @return true if the surface was initialized, false otherwise. Returning
* false might mean that the surface was already initialized.
*/
boolean initializeIfNeeded(int width, int height, Surface surface, Rect surfaceInsets)
throws OutOfResourcesException {
if (isRequested()) {
// We lost the gl context, so recreate it.
if (!isEnabled()) {
if (initialize(surface)) {
setup(width, height, surfaceInsets);
return true;
}
}
}
return false;
}
/**
* Sets up the renderer for drawing.
*
* @param width The width of the drawing surface.
* @param height The height of the drawing surface.
* @param surfaceInsets The drawing surface insets to apply
*/
abstract void setup(int width, int height, Rect surfaceInsets);
/**
* Optional, sets the name of the renderer. Useful for debugging purposes.
*
* @param name The name of this renderer, can be null
*/
abstract void setName(String name);
/**
* Change the HardwareRenderer's opacity
*/
abstract void setOpaque(boolean opaque);
/**
* Creates a hardware renderer using OpenGL.
*
* @param translucent True if the surface is translucent, false otherwise
*
* @return A hardware renderer backed by OpenGL.
*/
static HardwareRenderer create(Context context, boolean translucent) {
HardwareRenderer renderer = null;
if (GLES20Canvas.isAvailable()) {
renderer = new ThreadedRenderer(context, translucent);
}
return renderer;
}
/**
* Invoke this method when the system is running out of memory. This
* method will attempt to recover as much memory as possible, based on
* the specified hint.
*
* @param level Hint about the amount of memory that should be trimmed,
* see {@link android.content.ComponentCallbacks}
*/
static void trimMemory(int level) {
ThreadedRenderer.trimMemory(level);
}
/**
* Indicates whether hardware acceleration is currently enabled.
*
* @return True if hardware acceleration is in use, false otherwise.
*/
boolean isEnabled() {
return mEnabled;
}
/**
* Indicates whether hardware acceleration is currently enabled.
*
* @param enabled True if the hardware renderer is in use, false otherwise.
*/
void setEnabled(boolean enabled) {
mEnabled = enabled;
}
/**
* Indicates whether hardware acceleration is currently request but not
* necessarily enabled yet.
*
* @return True if requested, false otherwise.
*/
boolean isRequested() {
return mRequested;
}
/**
* Indicates whether hardware acceleration is currently requested but not
* necessarily enabled yet.
*
* @return True to request hardware acceleration, false otherwise.
*/
void setRequested(boolean requested) {
mRequested = requested;
}
/**
* Blocks until all previously queued work has completed.
*/
abstract void fence();
/**
* Prevents any further drawing until draw() is called. This is a signal
* that the contents of the RenderNode tree are no longer safe to play back.
* In practice this usually means that there are Functor pointers in the
* display list that are no longer valid.
*/
abstract void stopDrawing();
/**
* Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
*/
abstract void notifyFramePending();
abstract void registerAnimatingRenderNode(RenderNode animator);
}