Refactors and a potential public API for rendering
Split out the View/ViewRootImpl bits from the
hardware rendering bits.
Create a potential public API surface for
hardware rendering
Bug: 112709971
Test: builds & boots
Change-Id: I9e6f44b07a170574a905f42338282c4bb7e95f56
diff --git a/config/preloaded-classes b/config/preloaded-classes
index b6bff9c..22fc5e8 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -3240,7 +3240,7 @@
android.view.FocusFinder$FocusSorter
android.view.FocusFinder$UserSpecifiedFocusComparator
android.view.FocusFinder$UserSpecifiedFocusComparator$NextFocusGetter
-android.view.FrameInfo
+android.graphics.FrameInfo
android.view.FrameMetrics
android.view.FrameMetricsObserver
android.view.FrameStats
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9079f1a..805fb68 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -72,6 +72,7 @@
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.HardwareRenderer;
import android.graphics.ImageDecoder;
import android.hardware.display.DisplayManagerGlobal;
import android.net.ConnectivityManager;
@@ -5652,7 +5653,7 @@
int uid = Process.myUid();
String[] packages = getPackageManager().getPackagesForUid(uid);
if (packages != null) {
- ThreadedRenderer.setupDiskCache(codeCacheDir);
+ HardwareRenderer.setupDiskCache(codeCacheDir);
RenderScriptCacheDir.setupDiskCache(codeCacheDir);
}
} catch (RemoteException e) {
@@ -5887,7 +5888,8 @@
// Allow renderer debugging features if we're debuggable.
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
- ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+ HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+ HardwareRenderer.setPackageName(data.appInfo.packageName);
/**
* Initialize the default http proxy in this process for the reasons we set the time zone.
@@ -5954,7 +5956,7 @@
StrictMode.setThreadPolicyMask(oldMask);
}
} else {
- ThreadedRenderer.setIsolatedProcess(true);
+ HardwareRenderer.setIsolatedProcess(true);
}
// If we use profiles, setup the dex reporter to notify package manager
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a872776..96ef8ba 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -21,6 +21,7 @@
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.graphics.FrameInfo;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 597089b..0f38e84 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -40,8 +40,9 @@
@UnsupportedAppUsage
private FrameMetrics mFrameMetrics;
- /* package */ Window.OnFrameMetricsAvailableListener mListener;
- /* package */ VirtualRefBasePtr mNative;
+ /* pacage */ Window.OnFrameMetricsAvailableListener mListener;
+ /** @hide */
+ public VirtualRefBasePtr mNative;
/**
* Creates a FrameMetricsObserver
diff --git a/core/java/android/view/TextureLayer.java b/core/java/android/view/TextureLayer.java
index d89d634..46dd436 100644
--- a/core/java/android/view/TextureLayer.java
+++ b/core/java/android/view/TextureLayer.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.SurfaceTexture;
@@ -32,10 +33,10 @@
* @hide
*/
public final class TextureLayer {
- private ThreadedRenderer mRenderer;
+ private HardwareRenderer mRenderer;
private VirtualRefBasePtr mFinalizer;
- private TextureLayer(ThreadedRenderer renderer, long deferredUpdater) {
+ private TextureLayer(HardwareRenderer renderer, long deferredUpdater) {
if (renderer == null || deferredUpdater == 0) {
throw new IllegalArgumentException("Either hardware renderer: " + renderer
+ " or deferredUpdater: " + deferredUpdater + " is invalid");
@@ -139,7 +140,8 @@
mRenderer.pushLayerUpdate(this);
}
- static TextureLayer adoptTextureLayer(ThreadedRenderer renderer, long layer) {
+ /** @hide */
+ public static TextureLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
return new TextureLayer(renderer, layer);
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f0f4c1c..bac0154 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,36 +16,24 @@
package android.view;
-import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.app.ActivityManager;
import android.content.Context;
import android.content.res.TypedArray;
-import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
import android.graphics.Point;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RenderNode;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.Trace;
-import android.util.Log;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
import android.view.animation.AnimationUtils;
import com.android.internal.R;
-import com.android.internal.util.VirtualRefBasePtr;
-import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
/**
* Threaded renderer that proxies the rendering to a render thread. Most calls
@@ -66,15 +54,7 @@
*
* @hide
*/
-public final class ThreadedRenderer {
- private static final String LOG_TAG = "ThreadedRenderer";
-
- /**
- * Name of the file that holds the shaders cache.
- */
- private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
- private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
-
+public final class ThreadedRenderer extends HardwareRenderer {
/**
* System property used to enable or disable threaded rendering profiling.
* The default value of this property is assumed to be false.
@@ -271,21 +251,6 @@
}
/**
- * Sets the directory to use as a persistent storage for threaded rendering
- * resources.
- *
- * @param cacheDir A directory the current process can write to
- *
- * @hide
- */
- @UnsupportedAppUsage
- public static void setupDiskCache(File cacheDir) {
- ThreadedRenderer.setupShadersDiskCache(
- new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
- new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
- }
-
- /**
* Creates a threaded renderer using OpenGL.
*
* @param translucent True if the surface is translucent, false otherwise
@@ -300,55 +265,10 @@
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}
- */
- public static void trimMemory(int level) {
- nTrimMemory(level);
- }
-
- public static void overrideProperty(@NonNull String name, @NonNull String value) {
- if (name == null || value == null) {
- throw new IllegalArgumentException("name and value must be non-null");
- }
- nOverrideProperty(name, value);
- }
-
- // Keep in sync with DrawFrameTask.h SYNC_* flags
- // Nothing interesting to report
- private static final int SYNC_OK = 0;
- // Needs a ViewRoot invalidate
- private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
- // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
- private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
- // setStopped is true, drawing is false
- // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
- // This flag isn't really used as there's nothing that we care to do
- // in response, so it really just exists to differentiate from LOST_SURFACE
- // but possibly both can just be deleted.
- private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
- private static final int SYNC_FRAME_DROPPED = 1 << 3;
-
private static final String[] VISUALIZERS = {
PROFILE_PROPERTY_VISUALIZE_BARS,
};
- private static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
- private static final int FLAG_DUMP_RESET = 1 << 1;
- private static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
-
- @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
- FLAG_DUMP_FRAMESTATS,
- FLAG_DUMP_RESET
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface DumpFlags {}
-
// Size of the rendered content.
private int mWidth, mHeight;
@@ -362,51 +282,37 @@
// Whether the surface has insets. Used to protect opacity.
private boolean mHasInsets;
- // Light and shadow properties specified by the theme.
+ // Light properties specified by the theme.
private final float mLightY;
private final float mLightZ;
private final float mLightRadius;
- private final int mAmbientShadowAlpha;
- private final int mSpotShadowAlpha;
- private long mNativeProxy;
private boolean mInitialized = false;
- private RenderNode mRootNode;
private boolean mRootNodeNeedsUpdate;
private boolean mEnabled;
private boolean mRequested = true;
- private boolean mIsOpaque = false;
ThreadedRenderer(Context context, boolean translucent, String name) {
+ super();
+ setName(name);
+ setOpaque(!translucent);
+
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
- mAmbientShadowAlpha =
- (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
- mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+ float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+ float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
a.recycle();
-
- long rootNodePtr = nCreateRootRenderNode();
- mRootNode = RenderNode.adopt(rootNodePtr);
- mRootNode.setClipToBounds(false);
- mIsOpaque = !translucent;
- mNativeProxy = nCreateProxy(translucent, rootNodePtr);
- nSetName(mNativeProxy, name);
-
- ProcessInitializer.sInstance.init(context, mNativeProxy);
-
- loadSystemProperties();
+ setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
}
- /**
- * Destroys the threaded rendering context.
- */
- void destroy() {
+ @Override
+ public void destroy() {
mInitialized = false;
updateEnabledState(null);
- nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+ super.destroy();
}
/**
@@ -464,7 +370,7 @@
boolean status = !mInitialized;
mInitialized = true;
updateEnabledState(surface);
- nInitialize(mNativeProxy, surface);
+ setSurface(surface);
return status;
}
@@ -505,26 +411,18 @@
*/
void updateSurface(Surface surface) throws OutOfResourcesException {
updateEnabledState(surface);
- nUpdateSurface(mNativeProxy, surface);
+ setSurface(surface);
}
- /**
- * Halts any current rendering into the surface. Use this if it is unclear whether
- * or not the surface used by the ThreadedRenderer will be changing. It
- * Suspends any rendering into the surface, but will not do any destruction.
- *
- * Any subsequent draws will override the pause, resuming normal operation.
- */
- boolean pauseSurface(Surface surface) {
- return nPauseSurface(mNativeProxy, surface);
- }
-
- /**
- * Hard stops or resumes rendering into the surface. This flag is used to
- * determine whether or not it is safe to use the given surface *at all*
- */
- void setStopped(boolean stopped) {
- nSetStopped(mNativeProxy, stopped);
+ @Override
+ public void setSurface(Surface surface) {
+ // TODO: Do we ever pass a non-null but isValid() = false surface?
+ // This is here to be super conservative for ViewRootImpl
+ if (surface != null && surface.isValid()) {
+ super.setSurface(surface);
+ } else {
+ super.setSurface(null);
+ }
}
/**
@@ -535,7 +433,7 @@
*/
void destroyHardwareResources(View view) {
destroyResources(view);
- nDestroyHardwareResources(mNativeProxy);
+ destroyHardwareResources();
}
private static void destroyResources(View view) {
@@ -543,14 +441,6 @@
}
/**
- * Detaches the layer's surface texture from the GL context and releases
- * the texture id
- */
- void detachSurfaceTexture(long hardwareLayer) {
- nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
- }
-
- /**
* Sets up the renderer for drawing.
*
* @param width The width of the drawing surface.
@@ -581,8 +471,6 @@
}
mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
- nSetup(mNativeProxy, mLightRadius,
- mAmbientShadowAlpha, mSpotShadowAlpha);
setLightCenter(attachInfo);
}
@@ -598,27 +486,7 @@
attachInfo.mDisplay.getRealSize(displaySize);
final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
final float lightY = mLightY - attachInfo.mWindowTop;
-
- nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
- }
-
- /**
- * Change the ThreadedRenderer's opacity
- */
- void setOpaque(boolean opaque) {
- mIsOpaque = opaque && !mHasInsets;
- nSetOpaque(mNativeProxy, mIsOpaque);
- }
-
- boolean isOpaque() {
- return mIsOpaque;
- }
-
- /**
- * Enable/disable wide gamut rendering on this renderer.
- */
- void setWideGamut(boolean wideGamut) {
- nSetWideGamut(mNativeProxy, wideGamut);
+ setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
}
/**
@@ -663,18 +531,12 @@
break;
}
}
- nDumpProfileInfo(mNativeProxy, fd, flags);
+ dumpProfileInfo(fd, flags);
}
- /**
- * 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.
- */
- boolean loadSystemProperties() {
- boolean changed = nLoadSystemProperties(mNativeProxy);
+ @Override
+ public boolean loadSystemProperties() {
+ boolean changed = super.loadSystemProperties();
if (changed) {
invalidateRoot();
}
@@ -695,72 +557,27 @@
updateViewTreeDisplayList(view);
if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
- RecordingCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+ RecordingCanvas canvas = mRootNode.startRecording(mSurfaceWidth, mSurfaceHeight);
try {
final int saveCount = canvas.save();
canvas.translate(mInsetLeft, mInsetTop);
callbacks.onPreDraw(canvas);
- canvas.insertReorderBarrier();
+ canvas.enableZ();
canvas.drawRenderNode(view.updateDisplayListIfDirty());
- canvas.insertInorderBarrier();
+ canvas.disableZ();
callbacks.onPostDraw(canvas);
canvas.restoreToCount(saveCount);
mRootNodeNeedsUpdate = false;
} finally {
- mRootNode.end(canvas);
+ mRootNode.endRecording();
}
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
/**
- * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
- * rendernode of the UI thread.
- * @param node The node to add.
- * @param placeFront If true, the render node will be placed in front of the content node,
- * otherwise behind the content node.
- */
- @UnsupportedAppUsage
- public void addRenderNode(RenderNode node, boolean placeFront) {
- nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
- }
-
- /**
- * Only especially added render nodes can be removed.
- * @param node The node which was added via addRenderNode which should get removed again.
- */
- @UnsupportedAppUsage
- public void removeRenderNode(RenderNode node) {
- nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
- }
-
- /**
- * Draws a particular render node. If the node is not the content node, only the additional
- * nodes will get drawn and the content remains untouched.
- * @param node The node to be drawn.
- */
- @UnsupportedAppUsage
- public void drawRenderNode(RenderNode node) {
- nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
- }
-
- /**
- * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
- * will be prevented to overdraw this area. It will be synchronized with the draw call.
- * This should be updated in the content view's draw call.
- * @param left The left side of the protected bounds.
- * @param top The top side of the protected bounds.
- * @param right The right side of the protected bounds.
- * @param bottom The bottom side of the protected bounds.
- */
- @UnsupportedAppUsage
- public void setContentDrawBounds(int left, int top, int right, int bottom) {
- nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
- }
-
- /**
* Interface used to receive callbacks whenever a view is drawn by
* a threaded renderer instance.
*/
@@ -819,11 +636,10 @@
attachInfo.mPendingAnimatingRenderNodes = null;
}
- final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
if (frameDrawingCallback != null) {
- nSetFrameCallback(mNativeProxy, frameDrawingCallback);
+ setFrameCallback(frameDrawingCallback);
}
- int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
+ int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
setEnabled(false);
attachInfo.mViewRootImpl.mSurface.release();
@@ -831,207 +647,40 @@
// if it is still needed or do nothing if we are no longer drawing
attachInfo.mViewRootImpl.invalidate();
}
- if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
+ if ((syncResult & SYNC_REDRAW_REQUESTED) != 0) {
attachInfo.mViewRootImpl.invalidate();
}
}
- void setFrameCompleteCallback(FrameCompleteCallback callback) {
- nSetFrameCompleteCallback(mNativeProxy, callback);
- }
-
- static void invokeFunctor(long functor, boolean waitForCompletion) {
- nInvokeFunctor(functor, waitForCompletion);
- }
-
- /**
- * 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
- */
- TextureLayer createTextureLayer() {
- long layer = nCreateTextureLayer(mNativeProxy);
- return TextureLayer.adoptTextureLayer(this, layer);
- }
-
-
- void buildLayer(RenderNode node) {
- if (node.hasDisplayList()) {
- nBuildLayer(mNativeProxy, node.mNativeRenderNode);
- }
- }
-
-
- boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
- return nCopyLayerInto(mNativeProxy,
- layer.getDeferredLayerUpdater(), bitmap);
- }
-
- /**
- * Indicates that the specified hardware layer needs to be updated
- * as soon as possible.
- *
- * @param layer The hardware layer that needs an update
- */
- void pushLayerUpdate(TextureLayer layer) {
- nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
- }
-
- /**
- * Tells the HardwareRenderer that the layer is destroyed. The renderer
- * should remove the layer from any update queues.
- */
- void onLayerDestroyed(TextureLayer layer) {
- nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
- }
-
- /**
- * Blocks until all previously queued work has completed.
- */
- void fence() {
- nFence(mNativeProxy);
- }
-
- /**
- * 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.
- */
- void stopDrawing() {
- nStopDrawing(mNativeProxy);
- }
-
- /**
- * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
- */
- public void notifyFramePending() {
- nNotifyFramePending(mNativeProxy);
- }
-
-
- void registerAnimatingRenderNode(RenderNode animator) {
- nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
- }
-
- void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
- nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
- animator.getAnimatorNativePtr());
- }
-
- public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
- if (srcRect == null) {
- // Empty rect means entire surface
- return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
- } else {
- return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
- srcRect.right, srcRect.bottom, bitmap);
- }
- }
-
- /**
- * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
- * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
- * not the RenderNode from a View.
- **/
- @UnsupportedAppUsage
- public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
- return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
- }
-
- /**
- * Sets whether or not high contrast text rendering is enabled. The setting is global
- * but only affects content rendered after the change is made.
- */
- public static void setHighContrastText(boolean highContrastText) {
- nSetHighContrastText(highContrastText);
- }
-
- /**
- * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
- */
- public static void setIsolatedProcess(boolean isIsolated) {
- nSetIsolatedProcess(isIsolated);
- }
-
- /**
- * If set extra graphics debugging abilities will be enabled such as dumping skp
- */
- public static void setDebuggingEnabled(boolean enable) {
- nSetDebuggingEnabled(enable);
- }
-
- void allocateBuffers(Surface surface) {
- nAllocateBuffers(mNativeProxy, surface);
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- nDeleteProxy(mNativeProxy);
- mNativeProxy = 0;
- } finally {
- super.finalize();
- }
- }
-
/** The root of everything */
public @NonNull RenderNode getRootNode() {
return mRootNode;
}
- private boolean mForceDark = false;
-
- /**
- * Whether or not the force-dark feature should be used for this renderer.
- */
- public boolean setForceDark(boolean enable) {
- if (mForceDark != enable) {
- mForceDark = enable;
- nSetForceDark(mNativeProxy, enable);
- return true;
- }
- return false;
- }
-
/**
* Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
* TODO: deduplicate against ThreadedRenderer.
*
* @hide
*/
- public static class SimpleRenderer {
- private final RenderNode mRootNode;
- private long mNativeProxy;
- private final float mLightY, mLightZ;
- private Surface mSurface;
- private final FrameInfo mFrameInfo = new FrameInfo();
+ public static class SimpleRenderer extends HardwareRenderer {
+ private final float mLightY, mLightZ, mLightRadius;
public SimpleRenderer(final Context context, final String name, final Surface surface) {
+ super();
+ setName(name);
+ setOpaque(false);
+ setSurface(surface);
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
- final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
+ mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
final int ambientShadowAlpha =
(int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
final int spotShadowAlpha =
(int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
a.recycle();
-
- final long rootNodePtr = nCreateRootRenderNode();
- mRootNode = RenderNode.adopt(rootNodePtr);
- mRootNode.setClipToBounds(false);
- mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr);
- nSetName(mNativeProxy, name);
-
- ProcessInitializer.sInstance.init(context, mNativeProxy);
- nLoadSystemProperties(mNativeProxy);
-
- nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha);
-
- mSurface = surface;
- nUpdateSurface(mNativeProxy, surface);
+ setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
}
/**
@@ -1045,7 +694,7 @@
final float lightX = displaySize.x / 2f - windowLeft;
final float lightY = mLightY - windowTop;
- nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
+ setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
}
public RenderNode getRootNode() {
@@ -1057,222 +706,10 @@
*/
public void draw(final FrameDrawingCallback callback) {
final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
- mFrameInfo.setVsync(vsync, vsync);
- mFrameInfo.addFlags(1 << 2 /* VSYNC */);
if (callback != null) {
- nSetFrameCallback(mNativeProxy, callback);
+ setFrameCallback(callback);
}
- nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length);
- }
-
- /**
- * Destroy the renderer.
- */
- public void destroy() {
- mSurface = null;
- nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- nDeleteProxy(mNativeProxy);
- mNativeProxy = 0;
- } finally {
- super.finalize();
- }
+ syncAndDrawFrame(vsync);
}
}
-
- /**
- * Interface used to receive callbacks when a frame is being drawn.
- */
- public interface FrameDrawingCallback {
- /**
- * Invoked during a frame drawing.
- *
- * @param frame The id of the frame being drawn.
- */
- void onFrameDraw(long frame);
- }
-
- /**
- * Interface used to be notified when a frame has finished rendering
- */
- public interface FrameCompleteCallback {
- /**
- * Invoked after a frame draw
- *
- * @param frameNr The id of the frame that was drawn.
- */
- void onFrameComplete(long frameNr);
- }
-
- private static class ProcessInitializer {
- static ProcessInitializer sInstance = new ProcessInitializer();
-
- private boolean mInitialized = false;
-
- private Context mAppContext;
- private IGraphicsStats mGraphicsStatsService;
- private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
- @Override
- public void onRotateGraphicsStatsBuffer() throws RemoteException {
- rotateBuffer();
- }
- };
-
- private ProcessInitializer() {}
-
- synchronized void init(Context context, long renderProxy) {
- if (mInitialized) return;
- mInitialized = true;
- mAppContext = context.getApplicationContext();
-
- initSched(renderProxy);
-
- if (mAppContext != null) {
- initGraphicsStats();
- }
- }
-
- private void initSched(long renderProxy) {
- try {
- int tid = nGetRenderThreadTid(renderProxy);
- ActivityManager.getService().setRenderThread(tid);
- } catch (Throwable t) {
- Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
- }
- }
-
- private void initGraphicsStats() {
- try {
- IBinder binder = ServiceManager.getService("graphicsstats");
- if (binder == null) return;
- mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
- requestBuffer();
- } catch (Throwable t) {
- Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
- }
- }
-
- private void rotateBuffer() {
- nRotateProcessStatsBuffer();
- requestBuffer();
- }
-
- private void requestBuffer() {
- try {
- final String pkg = mAppContext.getApplicationInfo().packageName;
- ParcelFileDescriptor pfd = mGraphicsStatsService
- .requestBufferForProcess(pkg, mGraphicsStatsCallback);
- nSetProcessStatsBuffer(pfd.getFd());
- pfd.close();
- } catch (Throwable t) {
- Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
- }
- }
- }
-
- void addFrameMetricsObserver(FrameMetricsObserver observer) {
- long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
- observer.mNative = new VirtualRefBasePtr(nativeObserver);
- }
-
- void removeFrameMetricsObserver(FrameMetricsObserver observer) {
- nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
- observer.mNative = null;
- }
-
- /** b/68769804: For low FPS experiments. */
- public static void setFPSDivisor(int divisor) {
- nHackySetRTAnimationsEnabled(divisor <= 1);
- }
-
- /**
- * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
- * called before any OpenGL context is created.
- *
- * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
- */
- public static void setContextPriority(int priority) {
- nSetContextPriority(priority);
- }
-
- /** Not actually public - internal use only. This doc to make lint happy */
- public static native void disableVsync();
-
- static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
-
- private static native void nRotateProcessStatsBuffer();
- private static native void nSetProcessStatsBuffer(int fd);
- private static native int nGetRenderThreadTid(long nativeProxy);
-
- private static native long nCreateRootRenderNode();
- private static native long nCreateProxy(boolean translucent, long rootRenderNode);
- private static native void nDeleteProxy(long nativeProxy);
-
- private static native boolean nLoadSystemProperties(long nativeProxy);
- private static native void nSetName(long nativeProxy, String name);
-
- private static native void nInitialize(long nativeProxy, Surface window);
- private static native void nUpdateSurface(long nativeProxy, Surface window);
- private static native boolean nPauseSurface(long nativeProxy, Surface window);
- private static native void nSetStopped(long nativeProxy, boolean stopped);
- private static native void nSetup(long nativeProxy,
- float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
- private static native void nSetLightCenter(long nativeProxy,
- float lightX, float lightY, float lightZ);
- private static native void nSetOpaque(long nativeProxy, boolean opaque);
- private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
- private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
- private static native void nDestroy(long nativeProxy, long rootRenderNode);
- private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
- private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
-
- private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
-
- private static native long nCreateTextureLayer(long nativeProxy);
- private static native void nBuildLayer(long nativeProxy, long node);
- private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
- private static native void nPushLayerUpdate(long nativeProxy, long layer);
- private static native void nCancelLayerUpdate(long nativeProxy, long layer);
- private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
-
- private static native void nDestroyHardwareResources(long nativeProxy);
- private static native void nTrimMemory(int level);
- private static native void nOverrideProperty(String name, String value);
-
- private static native void nFence(long nativeProxy);
- private static native void nStopDrawing(long nativeProxy);
- private static native void nNotifyFramePending(long nativeProxy);
-
- private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
- @DumpFlags int dumpFlags);
-
- private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
- boolean placeFront);
- private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
- private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
- private static native void nSetContentDrawBounds(long nativeProxy, int left,
- int top, int right, int bottom);
- private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
- private static native void nSetFrameCompleteCallback(long nativeProxy,
- FrameCompleteCallback callback);
-
- private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
- private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
-
- private static native int nCopySurfaceInto(Surface surface,
- int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
-
- private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
- private static native void nSetHighContrastText(boolean enabled);
- // For temporary experimentation b/66945974
- private static native void nHackySetRTAnimationsEnabled(boolean enabled);
- private static native void nSetDebuggingEnabled(boolean enabled);
- private static native void nSetIsolatedProcess(boolean enabled);
- private static native void nSetContextPriority(int priority);
- private static native void nAllocateBuffers(long nativeProxy, Surface window);
- private static native void nSetForceDark(long nativeProxy, boolean enabled);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index dd1f640..a23d68b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -46,6 +46,8 @@
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.FrameInfo;
+import android.graphics.HardwareRenderer.FrameDrawingCallback;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -84,7 +86,6 @@
import android.util.TypedValue;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl.Transaction;
-import android.view.ThreadedRenderer.FrameDrawingCallback;
import android.view.View.AttachInfo;
import android.view.View.FocusDirection;
import android.view.View.MeasureSpec;
@@ -2148,7 +2149,7 @@
// relayoutWindow may decide to destroy mSurface. As that decision
// happens in WindowManager service, we need to be defensive here
// and stop using the surface in case it gets destroyed.
- if (mAttachInfo.mThreadedRenderer.pauseSurface(mSurface)) {
+ if (mAttachInfo.mThreadedRenderer.pause()) {
// Animations were running so we need to push a frame
// to resume them
mDirty.set(0, 0, mWidth, mHeight);
@@ -2266,7 +2267,7 @@
& View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
// Don't pre-allocate if transparent regions
// are requested as they may not be needed
- mAttachInfo.mThreadedRenderer.allocateBuffers(mSurface);
+ mAttachInfo.mThreadedRenderer.allocateBuffers();
}
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f512ce4..b8139a7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -556,18 +556,18 @@
proxy->setWideGamut(true);
}
proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
- proxy->initialize(surface);
+ proxy->setSurface(surface);
// Shadows can't be used via this interface, so just set the light source
// to all 0s.
- proxy->setup(0, 0, 0);
- proxy->setLightCenter((Vector3){0, 0, 0});
+ proxy->setLightAlpha(0, 0);
+ proxy->setLightGeometry((Vector3){0, 0, 0}, 0);
return (jlong) proxy;
}
static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
- proxy->updateSurface(surface);
+ proxy->setSurface(surface);
}
static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7a5b604..702741e 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -686,31 +686,20 @@
env->ReleaseStringUTFChars(jname, name);
}
-static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject jsurface) {
- RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
- proxy->initialize(surface);
-}
-
-static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject jsurface) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
sp<Surface> surface;
if (jsurface) {
surface = android_view_Surface_getSurface(env, jsurface);
}
- proxy->updateSurface(surface);
+ proxy->setSurface(surface);
}
-static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject jsurface) {
+static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
+ jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- sp<Surface> surface;
- if (jsurface) {
- surface = android_view_Surface_getSurface(env, jsurface);
- }
- return proxy->pauseSurface(surface);
+ return proxy->pause();
}
static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
@@ -719,16 +708,16 @@
proxy->setStopped(stopped);
}
-static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
- jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
+static void android_view_ThreadedRenderer_setLightAlpha(JNIEnv* env, jobject clazz, jlong proxyPtr,
+ jfloat ambientShadowAlpha, jfloat spotShadowAlpha) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
+ proxy->setLightAlpha((uint8_t) (255 * ambientShadowAlpha), (uint8_t) (255 * spotShadowAlpha));
}
-static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
+static void android_view_ThreadedRenderer_setLightGeometry(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
+ proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
}
static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -990,13 +979,12 @@
{
ContextFactory factory;
RenderProxy proxy{true, renderNode, &factory};
- proxy.loadSystemProperties();
proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
- proxy.initialize(surface);
+ proxy.setSurface(surface);
// Shadows can't be used via this interface, so just set the light source
// to all 0s.
- proxy.setup(0, 0, 0);
- proxy.setLightCenter((Vector3){0, 0, 0});
+ proxy.setLightAlpha(0, 0);
+ proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
UiFrameInfoBuilder(proxy.frameInfo())
.setVsync(vsync, vsync)
@@ -1058,10 +1046,9 @@
}
static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jobject jsurface) {
+ jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
- proxy->allocateBuffers(surface);
+ proxy->allocateBuffers();
}
static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
@@ -1118,7 +1105,7 @@
// JNI Glue
// ----------------------------------------------------------------------------
-const char* const kClassPathName = "android/view/ThreadedRenderer";
+const char* const kClassPathName = "android/graphics/HardwareRenderer";
static const JNINativeMethod gMethods[] = {
{ "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
@@ -1129,12 +1116,11 @@
{ "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
{ "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
{ "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
- { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
- { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
- { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
+ { "nSetSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_setSurface },
+ { "nPause", "(J)Z", (void*) android_view_ThreadedRenderer_pause },
{ "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
- { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
- { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
+ { "nSetLightAlpha", "(JFF)V", (void*) android_view_ThreadedRenderer_setLightAlpha },
+ { "nSetLightGeometry", "(JFFFF)V", (void*) android_view_ThreadedRenderer_setLightGeometry },
{ "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
{ "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
{ "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
@@ -1161,9 +1147,9 @@
{ "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
{ "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
- { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
+ { "nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCallback},
- { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
+ { "nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
{ "nAddFrameMetricsObserver",
"(JLandroid/view/FrameMetricsObserver;)J",
@@ -1182,7 +1168,7 @@
{ "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
{ "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
{ "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
- { "nAllocateBuffers", "(JLandroid/view/Surface;)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
+ { "nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
{ "nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark },
};
@@ -1215,12 +1201,12 @@
env, metricsClass, "mTimingData", "[J");
jclass frameCallbackClass = FindClassOrDie(env,
- "android/view/ThreadedRenderer$FrameDrawingCallback");
+ "android/graphics/HardwareRenderer$FrameDrawingCallback");
gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
"onFrameDraw", "(J)V");
jclass frameCompleteClass = FindClassOrDie(env,
- "android/view/ThreadedRenderer$FrameCompleteCallback");
+ "android/graphics/HardwareRenderer$FrameCompleteCallback");
gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
"onFrameComplete", "(J)V");
diff --git a/core/java/android/view/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
similarity index 70%
rename from core/java/android/view/FrameInfo.java
rename to graphics/java/android/graphics/FrameInfo.java
index 6c5e048..42a5cc4 100644
--- a/core/java/android/view/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.view;
+package android.graphics;
import android.annotation.LongDef;
@@ -33,14 +33,14 @@
* long layout & measure took it's displayListRecordStart - performTraversalsStart.
*
* These constants must be kept in sync with FrameInfo.h in libhwui and are
- * used for indexing into AttachInfo's mFrameInfo long[], which is intended
+ * used for indexing into AttachInfo's frameInfo long[], which is intended
* to be quick to pass down to native via JNI, hence a pre-packed format
*
* @hide
*/
-final class FrameInfo {
+public final class FrameInfo {
- long[] mFrameInfo = new long[9];
+ public long[] frameInfo = new long[9];
// Various flags set to provide extra metadata about the current frame
private static final int FLAGS = 0;
@@ -48,8 +48,11 @@
// Is this the first-draw following a window layout?
public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
+ // A renderer associated with just a Surface, not with a ViewRootImpl instance.
+ public static final long FLAG_SURFACE_CANVAS = 1 << 2;
+
@LongDef(flag = true, value = {
- FLAG_WINDOW_LAYOUT_CHANGED })
+ FLAG_WINDOW_LAYOUT_CHANGED, FLAG_SURFACE_CANVAS })
@Retention(RetentionPolicy.SOURCE)
public @interface FrameInfoFlags {}
@@ -78,41 +81,48 @@
// When View:draw() started
private static final int DRAW_START = 8;
+ /** checkstyle */
public void setVsync(long intendedVsync, long usedVsync) {
- mFrameInfo[INTENDED_VSYNC] = intendedVsync;
- mFrameInfo[VSYNC] = usedVsync;
- mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
- mFrameInfo[NEWEST_INPUT_EVENT] = 0;
- mFrameInfo[FLAGS] = 0;
+ frameInfo[INTENDED_VSYNC] = intendedVsync;
+ frameInfo[VSYNC] = usedVsync;
+ frameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
+ frameInfo[NEWEST_INPUT_EVENT] = 0;
+ frameInfo[FLAGS] = 0;
}
+ /** checkstyle */
public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
- if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
- mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
+ if (inputEventOldestTime < frameInfo[OLDEST_INPUT_EVENT]) {
+ frameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
}
- if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
- mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
+ if (inputEventTime > frameInfo[NEWEST_INPUT_EVENT]) {
+ frameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
}
}
+ /** checkstyle */
public void markInputHandlingStart() {
- mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
+ frameInfo[HANDLE_INPUT_START] = System.nanoTime();
}
+ /** checkstyle */
public void markAnimationsStart() {
- mFrameInfo[ANIMATION_START] = System.nanoTime();
+ frameInfo[ANIMATION_START] = System.nanoTime();
}
+ /** checkstyle */
public void markPerformTraversalsStart() {
- mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
+ frameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
}
+ /** checkstyle */
public void markDrawStart() {
- mFrameInfo[DRAW_START] = System.nanoTime();
+ frameInfo[DRAW_START] = System.nanoTime();
}
+ /** checkstyle */
public void addFlags(@FrameInfoFlags long flags) {
- mFrameInfo[FLAGS] |= flags;
+ frameInfo[FLAGS] |= flags;
}
}
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
new file mode 100644
index 0000000..e402055
--- /dev/null
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (C) 2018 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.graphics;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.FrameMetricsObserver;
+import android.view.IGraphicsStats;
+import android.view.IGraphicsStatsCallback;
+import android.view.NativeVectorDrawableAnimator;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.TextureLayer;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import sun.misc.Cleaner;
+
+/**
+ * <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
+ * from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
+ * HardwareRenderer instances as desired.</p>
+ *
+ * <h3>Threading</h3>
+ * <p>HardwareRenderer is not thread safe. An instance of a HardwareRenderer must only be
+ * created & used from a single thread. It does not matter what thread is used, however
+ * it must have a {@link android.os.Looper}. Multiple instances do not have to share the same
+ * thread, although they can.</p>
+ *
+ * <h3>Resources & lifecycle</h3>
+ * <p>All HardwareRenderer instances share a common render thread. The render thread contains
+ * the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
+ * HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
+ * however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
+ * is to have a HardwareRenderer instance for every active {@link Surface}. For example
+ * when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
+ * of which may be drawing at the same time.</p>
+ * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+ * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+ * consumers such as {@link android.view.SurfaceView},
+ * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+ * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+ * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+ * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+ * Failure to do so will cause the render thread to stall on that surface, blocking all
+ * HardwareRenderer instances.</p>
+ *
+ * @hide
+ */
+public class HardwareRenderer {
+ private static final String LOG_TAG = "HardwareRenderer";
+
+ // Keep in sync with DrawFrameTask.h SYNC_* flags
+ /**
+ * Nothing interesting to report. Sync & draw kicked off
+ */
+ public static final int SYNC_OK = 0;
+
+ /**
+ * The renderer is requesting a redraw. This can occur if there's an animation that's running
+ * in the RenderNode tree and the hardware renderer is unable to self-animate.
+ *
+ * If this is returned from syncAndDrawFrame the expectation is that syncAndDrawFrame
+ * will be called again on the next vsync signal.
+ */
+ public static final int SYNC_REDRAW_REQUESTED = 1 << 0;
+
+ /**
+ * The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
+ * This can happen if {@link Surface#destroy()} was called. The user should no longer
+ * attempt to call syncAndDrawFrame until a new surface has been provided by calling
+ * setSurface.
+ *
+ * Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
+ */
+ public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
+
+ /**
+ * The hardware renderer has been set to a "stopped" state. If this is returned then the
+ * rendering content has been synced, however a frame was not produced.
+ */
+ public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
+
+ /**
+ * The content was synced but the renderer has declined to produce a frame in this vsync
+ * interval. This can happen if a frame was already drawn in this vsync or if the renderer
+ * is outrunning the frame consumer. The renderer will internally re-schedule itself
+ * to render a frame in the next vsync signal, so the caller does not need to do anything
+ * in response to this signal.
+ */
+ public static final int SYNC_FRAME_DROPPED = 1 << 3;
+
+ @IntDef(value = {
+ SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
+ SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SyncAndDrawResult {
+ }
+
+ /** @hide */
+ public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
+ /** @hide */
+ public static final int FLAG_DUMP_RESET = 1 << 1;
+ /** @hide */
+ public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
+ FLAG_DUMP_FRAMESTATS,
+ FLAG_DUMP_RESET
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DumpFlags {
+ }
+
+ /**
+ * Name of the file that holds the shaders cache.
+ */
+ private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
+ private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
+
+ private final long mNativeProxy;
+ /** @hide */
+ protected RenderNode mRootNode;
+ private boolean mOpaque = true;
+ private boolean mForceDark = false;
+ private FrameInfo mScratchInfo;
+
+ /**
+ * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
+ * to opaque with no light source configured.
+ */
+ public HardwareRenderer() {
+ mRootNode = RenderNode.adopt(nCreateRootRenderNode());
+ mRootNode.setClipToBounds(false);
+ mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
+ if (mNativeProxy == 0) {
+ throw new OutOfMemoryError("Unable to create hardware renderer");
+ }
+ Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
+ ProcessInitializer.sInstance.init(mNativeProxy);
+ }
+
+ /**
+ * Destroys the rendering context of this HardwareRenderer. This destroys the resources
+ * associated with this renderer and releases the currently set {@link Surface}.
+ *
+ * The renderer may be restored from this state by setting a new {@link Surface}, setting
+ * new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
+ * rendering with {@link #syncAndDrawFrame(long)}.
+ *
+ * It is suggested to call this in response to callbacks such as
+ * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
+ *
+ * Note that if there are any outstanding frame commit callbacks they may end up never being
+ * invoked if the frame was deferred to a later vsync.
+ */
+ public void destroy() {
+ nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+ }
+
+ /**
+ * Sets a name for this renderer. This is used to identify this renderer instance
+ * when reporting debug information such as the per-window frame time metrics
+ * reported by 'adb shell dumpsys gfxinfo [package] framestats'
+ *
+ * @param name The debug name to use for this HardwareRenderer instance
+ */
+ public void setName(String name) {
+ nSetName(mNativeProxy, name);
+ }
+
+ /**
+ * Sets the center of the light source. The light source point controls the directionality
+ * and shape of shadows rendered by RenderNode Z & elevation.
+ *
+ * The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
+ * lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
+ *
+ * The light source should be setup both as part of initial configuration, and whenever
+ * the window moves to ensure the light source stays anchored in display space instead
+ * of in window space.
+ *
+ * This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
+ * before shadows will work.
+ *
+ * @param lightX The X position of the light source
+ * @param lightY The Y position of the light source
+ * @param lightZ The Z position of the light source. Must be >= 0.
+ * @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
+ * larger radius will have softer shadows.
+ */
+ public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
+ float lightRadius) {
+ validateFinite(lightX, "lightX");
+ validateFinite(lightY, "lightY");
+ validatePositive(lightZ, "lightZ");
+ validatePositive(lightRadius, "lightRadius");
+ nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
+ }
+
+ /**
+ * Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
+ * has max alpha, and ramps down from the values provided to zero.
+ *
+ * These values are typically provided by the current theme, see
+ * {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
+ *
+ * This must be set at least once along with
+ * {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
+ *
+ * @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
+ * is 0.039f.
+ * @param spotShadowAlpha The alpha for the spot shadow. If unsure, a reasonable default is
+ * 0.19f.
+ */
+ public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
+ @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
+ validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
+ validateAlpha(spotShadowAlpha, "spotShadowAlpha");
+ nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
+ }
+
+ /**
+ * Sets the content root to render. It is not necessary to call this whenever the content
+ * recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
+ * contained within the content node, will be applied whenever {@link #syncAndDrawFrame(long)}
+ * is called.
+ *
+ * @param content The content to set as the root RenderNode. If null the content root is removed
+ * and the renderer will draw nothing.
+ */
+ public void setContentRoot(@Nullable RenderNode content) {
+ RecordingCanvas canvas = mRootNode.startRecording();
+ if (content != null) {
+ canvas.drawRenderNode(content);
+ }
+ mRootNode.endRecording();
+ }
+
+ /**
+ * <p>The surface to render into. The surface is assumed to be associated with the display and
+ * as such is still driven by vsync signals such as those from
+ * {@link android.view.Choreographer} and that it has a native refresh rate matching that of
+ * the display's (typically 60hz).</p>
+ *
+ * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+ * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+ * consumers such as {@link android.view.SurfaceView},
+ * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+ * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+ * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+ * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+ * Failure to do so will cause the render thread to stall on that surface, blocking all
+ * HardwareRenderer instances.</p>
+ *
+ * @param surface The surface to render into. If null then rendering will be stopped. If
+ * non-null then {@link Surface#isValid()} must be true.
+ */
+ public void setSurface(@Nullable Surface surface) {
+ if (surface != null && !surface.isValid()) {
+ throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
+ }
+ nSetSurface(mNativeProxy, surface);
+ }
+
+ /**
+ * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+ *
+ * @hide
+ */
+ @SyncAndDrawResult
+ public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
+ return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
+ }
+
+ /**
+ * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+ *
+ * @param vsyncTime The vsync timestamp for this frame. Typically this comes from
+ * {@link android.view.Choreographer.FrameCallback}. Must be set and be valid
+ * as the renderer uses this time internally to drive animations.
+ * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+ */
+ @SyncAndDrawResult
+ public int syncAndDrawFrame(long vsyncTime) {
+ if (mScratchInfo == null) {
+ mScratchInfo = new FrameInfo();
+ }
+ mScratchInfo.setVsync(vsyncTime, vsyncTime);
+ mScratchInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
+ return syncAndDrawFrame(mScratchInfo);
+ }
+
+ /**
+ * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+ * frameCommitCallback callback will be invoked when the current rendering content has been
+ * rendered into a frame and submitted to the swap chain.
+ *
+ * @param vsyncTime The vsync timestamp for this frame. Typically this comes from
+ * {@link android.view.Choreographer.FrameCallback}. Must be set and
+ * be valid as the renderer uses this time internally to drive
+ * animations.
+ * @param frameCommitCallback The callback to invoke when the frame content has been drawn.
+ * Will be invoked on the current {@link android.os.Looper} thread.
+ * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+ */
+ @SyncAndDrawResult
+ public int syncAndDrawFrame(long vsyncTime,
+ @Nullable Runnable frameCommitCallback) {
+ if (frameCommitCallback != null) {
+ setFrameCompleteCallback(frameNr -> frameCommitCallback.run());
+ }
+ return syncAndDrawFrame(vsyncTime);
+ }
+
+ /**
+ * Suspends any current rendering into the surface but do not do any destruction. This
+ * is useful to temporarily suspend using the active Surface in order to do any Surface
+ * mutations necessary.
+ *
+ * Any subsequent draws will override the pause, resuming normal operation.
+ *
+ * @return true if there was an outstanding render request, false otherwise. If this is true
+ * the caller should ensure that {@link #syncAndDrawFrame(long)} is called at the soonest
+ * possible time to resume normal operation.
+ *
+ * TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
+ * Surface before getting a new one. However things like SurfaceView will ensure that
+ * the old surface remains un-destroyed until after a new frame has been produced with
+ * the new surface.
+ * @hide
+ */
+ public boolean pause() {
+ return nPause(mNativeProxy);
+ }
+
+ /**
+ * Hard stops rendering into the surface. If the renderer is stopped it will
+ * block any attempt to render. Calls to {@link #syncAndDrawFrame(long)} will still
+ * sync over the latest rendering content, however they will not render and instead
+ * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
+ *
+ * If false is passed then rendering will resume as normal. Any pending rendering requests
+ * will produce a new frame at the next vsync signal.
+ *
+ * This is useful in combination with lifecycle events such as {@link Activity#onStop()}
+ * and {@link Activity#onStart()}.
+ *
+ * @param stopped true to stop all rendering, false to resume
+ */
+ public void setStopped(boolean stopped) {
+ nSetStopped(mNativeProxy, stopped);
+ }
+
+ /**
+ * Destroys all hardware rendering resources associated with the current rendering content.
+ * This includes releasing a reference to the current content root RenderNode. It will
+ * therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
+ * rendering after calling this.
+ *
+ * It is recommended, but not necessary, to use this in combination with lifecycle events
+ * such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
+ * {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
+ * {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
+ *
+ * See also {@link #setStopped(boolean)}
+ */
+ public void destroyHardwareResources() {
+ nDestroyHardwareResources(mNativeProxy);
+ }
+
+ /**
+ * Whether or not the force-dark feature should be used for this renderer.
+ */
+ public boolean setForceDark(boolean enable) {
+ if (mForceDark != enable) {
+ mForceDark = enable;
+ nSetForceDark(mNativeProxy, enable);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Allocate buffers ahead of time to avoid allocation delays during rendering.
+ *
+ * Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
+ * memory usage of Surfaces that render rarely or never hit triple buffering. However
+ * for UI it can result in a slight bit of jank on first launch. This hint will
+ * tell the HardwareRenderer that now is a good time to allocate the 3 buffers
+ * necessary for typical rendering.
+ *
+ * Must be called after a {@link Surface} has been set.
+ */
+ public void allocateBuffers() {
+ nAllocateBuffers(mNativeProxy);
+ }
+
+ /**
+ * Notifies the hardware renderer that a call to {@link #syncAndDrawFrame(long)} will
+ * be coming soon. This is used to help schedule when RenderThread-driven animations will
+ * happen as the renderer wants to avoid producing more than one frame per vsync signal.
+ */
+ public void notifyFramePending() {
+ nNotifyFramePending(mNativeProxy);
+ }
+
+ /**
+ * Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
+ *
+ * If the renderer is set to opaque it is the app's responsibility to ensure that the
+ * content renders to every pixel of the Surface, otherwise corruption may result. Note that
+ * this includes ensuring that the first draw of any given pixel does not attempt to blend
+ * against the destination. If this is false then the hardware renderer will clear to
+ * transparent at the start of every frame.
+ *
+ * @param opaque true if the content rendered is opaque, false if the renderer should clear
+ * to transparent before rendering
+ */
+ public void setOpaque(boolean opaque) {
+ if (mOpaque != opaque) {
+ mOpaque = opaque;
+ nSetOpaque(mNativeProxy, mOpaque);
+ }
+ }
+
+ /**
+ * Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
+ *
+ * @return true if the renderer is opaque, false otherwise
+ */
+ public boolean isOpaque() {
+ return mOpaque;
+ }
+
+ /** @hide */
+ public void setFrameCompleteCallback(FrameCompleteCallback callback) {
+ nSetFrameCompleteCallback(mNativeProxy, callback);
+ }
+
+ /**
+ * TODO: Public API this?
+ *
+ * @hide
+ */
+ public void addFrameMetricsObserver(FrameMetricsObserver observer) {
+ long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
+ observer.mNative = new VirtualRefBasePtr(nativeObserver);
+ }
+
+ /**
+ * TODO: Public API this?
+ *
+ * @hide
+ */
+ public void removeFrameMetricsObserver(FrameMetricsObserver observer) {
+ nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
+ observer.mNative = null;
+ }
+
+ /**
+ * Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
+ * will be wide gamut depends on the hardware support for such rendering.
+ *
+ * @param wideGamut true if this renderer should render in wide gamut, false if it should
+ * render in sRGB
+ * TODO: Figure out color...
+ * @hide
+ */
+ public void setWideGamut(boolean wideGamut) {
+ nSetWideGamut(mNativeProxy, wideGamut);
+ }
+
+ /**
+ * Blocks until all previously queued work has completed.
+ *
+ * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
+ * better
+ *
+ * @hide
+ */
+ public void fence() {
+ nFence(mNativeProxy);
+ }
+
+ /** @hide */
+ public void registerAnimatingRenderNode(RenderNode animator) {
+ nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
+ }
+
+ /** @hide */
+ public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
+ nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
+ animator.getAnimatorNativePtr());
+ }
+
+ /**
+ * Prevents any further drawing until {@link #syncAndDrawFrame(long)} 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.
+ *
+ * TODO: Can we get webview off of this?
+ *
+ * @hide
+ */
+ public void stopDrawing() {
+ nStopDrawing(mNativeProxy);
+ }
+
+ /**
+ * 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
+ * @hide
+ */
+ public TextureLayer createTextureLayer() {
+ long layer = nCreateTextureLayer(mNativeProxy);
+ return TextureLayer.adoptTextureLayer(this, layer);
+ }
+
+ /**
+ * Detaches the layer's surface texture from the GL context and releases
+ * the texture id
+ *
+ * @hide
+ */
+ public void detachSurfaceTexture(long hardwareLayer) {
+ nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
+ }
+
+
+ /** @hide */
+ public void buildLayer(RenderNode node) {
+ if (node.hasDisplayList()) {
+ nBuildLayer(mNativeProxy, node.mNativeRenderNode);
+ }
+ }
+
+ /** @hide */
+ public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
+ return nCopyLayerInto(mNativeProxy,
+ layer.getDeferredLayerUpdater(), bitmap);
+ }
+
+ /**
+ * Indicates that the specified hardware layer needs to be updated
+ * as soon as possible.
+ *
+ * @param layer The hardware layer that needs an update
+ * @hide
+ */
+ public void pushLayerUpdate(TextureLayer layer) {
+ nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+ }
+
+ /**
+ * Tells the HardwareRenderer that the layer is destroyed. The renderer
+ * should remove the layer from any update queues.
+ *
+ * @hide
+ */
+ public void onLayerDestroyed(TextureLayer layer) {
+ nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+ }
+
+ /** @hide */
+ public void setFrameCallback(FrameDrawingCallback callback) {
+ nSetFrameCallback(mNativeProxy, callback);
+ }
+
+ /**
+ * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
+ * rendernode of the UI thread.
+ *
+ * @param node The node to add.
+ * @param placeFront If true, the render node will be placed in front of the content node,
+ * otherwise behind the content node.
+ * @hide
+ */
+ public void addRenderNode(RenderNode node, boolean placeFront) {
+ nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
+ }
+
+ /**
+ * Only especially added render nodes can be removed.
+ *
+ * @param node The node which was added via addRenderNode which should get removed again.
+ * @hide
+ */
+ public void removeRenderNode(RenderNode node) {
+ nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
+ }
+
+ /**
+ * Draws a particular render node. If the node is not the content node, only the additional
+ * nodes will get drawn and the content remains untouched.
+ *
+ * @param node The node to be drawn.
+ * @hide
+ */
+ public void drawRenderNode(RenderNode node) {
+ nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
+ }
+
+ /**
+ * 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.
+ * @hide
+ */
+ public boolean loadSystemProperties() {
+ return nLoadSystemProperties(mNativeProxy);
+ }
+
+ /**
+ * @hide
+ */
+ public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
+ nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
+ }
+
+ /**
+ * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
+ * will be prevented to overdraw this area. It will be synchronized with the draw call.
+ * This should be updated in the content view's draw call.
+ *
+ * @param left The left side of the protected bounds.
+ * @param top The top side of the protected bounds.
+ * @param right The right side of the protected bounds.
+ * @param bottom The bottom side of the protected bounds.
+ * @hide
+ */
+ public void setContentDrawBounds(int left, int top, int right, int bottom) {
+ nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
+ }
+
+ /**
+ * Interface used to receive callbacks when a frame is being drawn.
+ *
+ * @hide
+ */
+ public interface FrameDrawingCallback {
+ /**
+ * Invoked during a frame drawing.
+ *
+ * @param frame The id of the frame being drawn.
+ */
+ void onFrameDraw(long frame);
+ }
+
+ /**
+ * Interface used to be notified when a frame has finished rendering
+ *
+ * @hide
+ */
+ public interface FrameCompleteCallback {
+ /**
+ * Invoked after a frame draw
+ *
+ * @param frameNr The id of the frame that was drawn.
+ */
+ void onFrameComplete(long frameNr);
+ }
+
+ private static void validateAlpha(float alpha, String argumentName) {
+ if (!(alpha >= 0.0f && alpha <= 1.0f)) {
+ throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
+ + alpha + " is not in the range of 0.0f to 1.0f");
+ }
+ }
+
+ private static void validatePositive(float f, String argumentName) {
+ if (!(Float.isFinite(f) && f >= 0.0f)) {
+ throw new IllegalArgumentException(argumentName
+ + " must be a finite positive, given=" + f);
+ }
+ }
+
+ private static void validateFinite(float f, String argumentName) {
+ if (!Float.isFinite(f)) {
+ throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
+ }
+ }
+
+ /** @hide */
+ public static void invokeFunctor(long functor, boolean waitForCompletion) {
+ nInvokeFunctor(functor, waitForCompletion);
+ }
+
+ /**
+ * b/68769804: For low FPS experiments.
+ *
+ * @hide
+ */
+ public static void setFPSDivisor(int divisor) {
+ nHackySetRTAnimationsEnabled(divisor <= 1);
+ }
+
+ /**
+ * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
+ * called before any OpenGL context is created.
+ *
+ * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
+ * @hide
+ */
+ public static void setContextPriority(int priority) {
+ nSetContextPriority(priority);
+ }
+
+ /**
+ * Sets whether or not high contrast text rendering is enabled. The setting is global
+ * but only affects content rendered after the change is made.
+ *
+ * @hide
+ */
+ public static void setHighContrastText(boolean highContrastText) {
+ nSetHighContrastText(highContrastText);
+ }
+
+ /**
+ * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
+ *
+ * @hide
+ */
+ public static void setIsolatedProcess(boolean isIsolated) {
+ nSetIsolatedProcess(isIsolated);
+ }
+
+ /**
+ * If set extra graphics debugging abilities will be enabled such as dumping skp
+ *
+ * @hide
+ */
+ public static void setDebuggingEnabled(boolean enable) {
+ nSetDebuggingEnabled(enable);
+ }
+
+ /** @hide */
+ public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
+ if (srcRect == null) {
+ // Empty rect means entire surface
+ return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
+ } else {
+ return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
+ srcRect.right, srcRect.bottom, bitmap);
+ }
+ }
+
+ /**
+ * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
+ * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
+ * not the RenderNode from a View.
+ *
+ * @hide
+ **/
+ public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
+ return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
+ }
+
+ /**
+ * 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}
+ * @hide
+ */
+ public static void trimMemory(int level) {
+ nTrimMemory(level);
+ }
+
+ /** @hide */
+ public static void overrideProperty(@NonNull String name, @NonNull String value) {
+ if (name == null || value == null) {
+ throw new IllegalArgumentException("name and value must be non-null");
+ }
+ nOverrideProperty(name, value);
+ }
+
+ /**
+ * Sets the directory to use as a persistent storage for threaded rendering
+ * resources.
+ *
+ * @param cacheDir A directory the current process can write to
+ * @hide
+ */
+ public static void setupDiskCache(File cacheDir) {
+ setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
+ new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
+ }
+
+ /** @hide */
+ public static void setPackageName(String packageName) {
+ ProcessInitializer.sInstance.setPackageName(packageName);
+ }
+
+ private static final class DestroyContextRunnable implements Runnable {
+ private final long mNativeInstance;
+
+ DestroyContextRunnable(long nativeInstance) {
+ mNativeInstance = nativeInstance;
+ }
+
+ @Override
+ public void run() {
+ nDeleteProxy(mNativeInstance);
+ }
+ }
+
+ private static class ProcessInitializer {
+ static ProcessInitializer sInstance = new ProcessInitializer();
+
+ private boolean mInitialized = false;
+
+ private String mPackageName;
+ private IGraphicsStats mGraphicsStatsService;
+ private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
+ @Override
+ public void onRotateGraphicsStatsBuffer() throws RemoteException {
+ rotateBuffer();
+ }
+ };
+
+ private ProcessInitializer() {
+ }
+
+ synchronized void setPackageName(String name) {
+ if (mInitialized) return;
+ mPackageName = name;
+ }
+
+ synchronized void init(long renderProxy) {
+ if (mInitialized) return;
+ mInitialized = true;
+
+ initSched(renderProxy);
+ initGraphicsStats();
+ }
+
+ private void initSched(long renderProxy) {
+ try {
+ int tid = nGetRenderThreadTid(renderProxy);
+ ActivityManager.getService().setRenderThread(tid);
+ } catch (Throwable t) {
+ Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
+ }
+ }
+
+ private void initGraphicsStats() {
+ if (mPackageName == null) return;
+
+ try {
+ IBinder binder = ServiceManager.getService("graphicsstats");
+ if (binder == null) return;
+ mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+ requestBuffer();
+ } catch (Throwable t) {
+ Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+ }
+ }
+
+ private void rotateBuffer() {
+ nRotateProcessStatsBuffer();
+ requestBuffer();
+ }
+
+ private void requestBuffer() {
+ try {
+ ParcelFileDescriptor pfd = mGraphicsStatsService
+ .requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
+ nSetProcessStatsBuffer(pfd.getFd());
+ pfd.close();
+ } catch (Throwable t) {
+ Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public static native void disableVsync();
+
+ /** @hide */
+ protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
+
+ private static native void nRotateProcessStatsBuffer();
+
+ private static native void nSetProcessStatsBuffer(int fd);
+
+ private static native int nGetRenderThreadTid(long nativeProxy);
+
+ private static native long nCreateRootRenderNode();
+
+ private static native long nCreateProxy(boolean translucent, long rootRenderNode);
+
+ private static native void nDeleteProxy(long nativeProxy);
+
+ private static native boolean nLoadSystemProperties(long nativeProxy);
+
+ private static native void nSetName(long nativeProxy, String name);
+
+ private static native void nSetSurface(long nativeProxy, Surface window);
+
+ private static native boolean nPause(long nativeProxy);
+
+ private static native void nSetStopped(long nativeProxy, boolean stopped);
+
+ private static native void nSetLightGeometry(long nativeProxy,
+ float lightX, float lightY, float lightZ, float lightRadius);
+
+ private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
+ float spotShadowAlpha);
+
+ private static native void nSetOpaque(long nativeProxy, boolean opaque);
+
+ private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
+
+ private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
+
+ private static native void nDestroy(long nativeProxy, long rootRenderNode);
+
+ private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
+ long animatingNode);
+
+ private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
+
+ private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
+
+ private static native long nCreateTextureLayer(long nativeProxy);
+
+ private static native void nBuildLayer(long nativeProxy, long node);
+
+ private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
+
+ private static native void nPushLayerUpdate(long nativeProxy, long layer);
+
+ private static native void nCancelLayerUpdate(long nativeProxy, long layer);
+
+ private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
+
+ private static native void nDestroyHardwareResources(long nativeProxy);
+
+ private static native void nTrimMemory(int level);
+
+ private static native void nOverrideProperty(String name, String value);
+
+ private static native void nFence(long nativeProxy);
+
+ private static native void nStopDrawing(long nativeProxy);
+
+ private static native void nNotifyFramePending(long nativeProxy);
+
+ private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
+ @DumpFlags int dumpFlags);
+
+ private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
+ boolean placeFront);
+
+ private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
+
+ private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
+
+ private static native void nSetContentDrawBounds(long nativeProxy, int left,
+ int top, int right, int bottom);
+
+ private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
+
+ private static native void nSetFrameCompleteCallback(long nativeProxy,
+ FrameCompleteCallback callback);
+
+ private static native long nAddFrameMetricsObserver(long nativeProxy,
+ FrameMetricsObserver observer);
+
+ private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
+
+ private static native int nCopySurfaceInto(Surface surface,
+ int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
+
+ private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
+
+ private static native void nSetHighContrastText(boolean enabled);
+
+ // For temporary experimentation b/66945974
+ private static native void nHackySetRTAnimationsEnabled(boolean enabled);
+
+ private static native void nSetDebuggingEnabled(boolean enabled);
+
+ private static native void nSetIsolatedProcess(boolean enabled);
+
+ private static native void nSetContextPriority(int priority);
+
+ private static native void nAllocateBuffers(long nativeProxy);
+
+ private static native void nSetForceDark(long nativeProxy, boolean enabled);
+}
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 236a6b6..b04c774 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -66,6 +66,7 @@
FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
setDensity(1);
+ consumeProperties();
}
FrameInfoVisualizer::~FrameInfoVisualizer() {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 92a749f..f1a522e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -180,14 +180,20 @@
}
}
-void CanvasContext::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
- mLightGeometry.radius = lightRadius;
+void CanvasContext::allocateBuffers() {
+ if (mNativeSurface) {
+ mNativeSurface->allocateBuffers();
+ }
+}
+
+void CanvasContext::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
mLightInfo.spotShadowAlpha = spotShadowAlpha;
}
-void CanvasContext::setLightCenter(const Vector3& lightCenter) {
+void CanvasContext::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
mLightGeometry.center = lightCenter;
+ mLightGeometry.radius = lightRadius;
}
void CanvasContext::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2307ee4..70be4a6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -113,9 +113,10 @@
bool pauseSurface();
void setStopped(bool stopped);
bool hasSurface() { return mNativeSurface.get(); }
+ void allocateBuffers();
- void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
- void setLightCenter(const Vector3& lightCenter);
+ void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ void setLightGeometry(const Vector3& lightCenter, float lightRadius);
void setOpaque(bool opaque);
void setWideGamut(bool wideGamut);
bool makeCurrent();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 54219b5..085812a0 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -80,22 +80,16 @@
mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
}
-void RenderProxy::initialize(const sp<Surface>& surface) {
+void RenderProxy::setSurface(const sp<Surface>& surface) {
mRenderThread.queue().post(
[ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
}
-void RenderProxy::allocateBuffers(const sp<Surface>& surface) {
- mRenderThread.queue().post(
- [ surf = surface ]() mutable { surf->allocateBuffers(); });
+void RenderProxy::allocateBuffers() {
+ mRenderThread.queue().post([=]() { mContext->allocateBuffers(); });
}
-void RenderProxy::updateSurface(const sp<Surface>& surface) {
- mRenderThread.queue().post(
- [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
-}
-
-bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
+bool RenderProxy::pause() {
return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
}
@@ -103,13 +97,13 @@
mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
}
-void RenderProxy::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+void RenderProxy::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
mRenderThread.queue().post(
- [=]() { mContext->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); });
+ [=]() { mContext->setLightAlpha(ambientShadowAlpha, spotShadowAlpha); });
}
-void RenderProxy::setLightCenter(const Vector3& lightCenter) {
- mRenderThread.queue().post([=]() { mContext->setLightCenter(lightCenter); });
+void RenderProxy::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
+ mRenderThread.queue().post([=]() { mContext->setLightGeometry(lightCenter, lightRadius); });
}
void RenderProxy::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d29fcc4..6668c584 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,13 +69,12 @@
ANDROID_API bool loadSystemProperties();
ANDROID_API void setName(const char* name);
- ANDROID_API void initialize(const sp<Surface>& surface);
- ANDROID_API void allocateBuffers(const sp<Surface>& surface);
- ANDROID_API void updateSurface(const sp<Surface>& surface);
- ANDROID_API bool pauseSurface(const sp<Surface>& surface);
+ ANDROID_API void setSurface(const sp<Surface>& surface);
+ ANDROID_API void allocateBuffers();
+ ANDROID_API bool pause();
ANDROID_API void setStopped(bool stopped);
- ANDROID_API void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
- ANDROID_API void setLightCenter(const Vector3& lightCenter);
+ ANDROID_API void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+ ANDROID_API void setLightGeometry(const Vector3& lightCenter, float lightRadius);
ANDROID_API void setOpaque(bool opaque);
ANDROID_API void setWideGamut(bool wideGamut);
ANDROID_API int64_t* frameInfo();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 62f704b..2384f95 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -74,7 +74,7 @@
PREVENT_COPY_AND_ASSIGN(RenderThread);
public:
- // Sets a callback that fires before any RenderThread setup has occured.
+ // Sets a callback that fires before any RenderThread setup has occurred.
ANDROID_API static void setOnStartHook(void (*onStartHook)());
WorkQueue& queue() { return ThreadBase::queue(); }
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 5f5a92e..5fa008b 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -132,10 +132,10 @@
ContextFactory factory;
std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode.get(), &factory));
proxy->loadSystemProperties();
- proxy->initialize(surface);
+ proxy->setSurface(surface);
float lightX = width / 2.0;
- proxy->setup(dp(800.0f), 255 * 0.075, 255 * 0.15);
- proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
+ proxy->setLightAlpha(255 * 0.075, 255 * 0.15);
+ proxy->setLightGeometry((Vector3){lightX, dp(-200.0f), dp(800.0f)}, dp(800.0f));
// Do a few cold runs then reset the stats so that the caches are all hot
int warmupFrameCount = 5;