Loading core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java +94 −15 Original line number Diff line number Diff line Loading @@ -699,6 +699,7 @@ public class CoreDocument { } op.markNotDirty(); op.apply(context); context.incrementOpCount(); } } Loading Loading @@ -1000,6 +1001,16 @@ public class CoreDocument { private final float[] mScaleOutput = new float[2]; private final float[] mTranslateOutput = new float[2]; private int mRepaintNext = -1; // delay to next repaint -1 = don't 1 = asap private int mLastOpCount; /** * This is the number of ops used to calculate the last frame. * * @return number of ops */ public int getOpsPerFrame() { return mLastOpCount; } /** * Returns > 0 if it needs to repaint Loading @@ -1017,6 +1028,7 @@ public class CoreDocument { * @param theme the theme we want to use for this document. */ public void paint(@NonNull RemoteContext context, int theme) { context.getLastOpCount(); context.getPaintContext().clearNeedsRepaint(); context.loadFloat(RemoteContext.ID_DENSITY, context.getDensity()); context.mMode = RemoteContext.ContextMode.UNSET; Loading @@ -1027,21 +1039,24 @@ public class CoreDocument { context.mRemoteComposeState = mRemoteComposeState; context.mRemoteComposeState.setContext(context); // If we have a content sizing set, we are going to take the original document // dimension into account and apply scale+translate according to the RootContentBehavior // rules. if (mContentSizing == RootContentBehavior.SIZING_SCALE) { // we need to add canvas transforms ops here computeScale(context.mWidth, context.mHeight, mScaleOutput); computeTranslate( context.mWidth, context.mHeight, mScaleOutput[0], mScaleOutput[1], mTranslateOutput); float sw = mScaleOutput[0]; float sh = mScaleOutput[1]; computeTranslate(context.mWidth, context.mHeight, sw, sh, mTranslateOutput); context.mPaintContext.translate(mTranslateOutput[0], mTranslateOutput[1]); context.mPaintContext.scale(mScaleOutput[0], mScaleOutput[1]); context.mPaintContext.scale(sw, sh); } else { // If not, we set the document width and height to be the current context width and // height. setWidth((int) context.mWidth); setHeight((int) context.mHeight); } mTimeVariables.updateTime(context); context.loadFloat(RemoteContext.ID_WINDOW_WIDTH, context.mWidth); context.loadFloat(RemoteContext.ID_WINDOW_HEIGHT, context.mHeight); mRepaintNext = context.updateOps(); if (mRootLayoutComponent != null) { if (context.mWidth != mRootLayoutComponent.getWidth() Loading @@ -1051,11 +1066,11 @@ public class CoreDocument { if (mRootLayoutComponent.needsMeasure()) { mRootLayoutComponent.layout(context); } // TODO -- this should be specifically about applying animation, not paint mRootLayoutComponent.paint(context.getPaintContext()); context.mPaintContext.reset(); // TODO -- should be able to remove this mRootLayoutComponent.updateVariables(context); if (mRootLayoutComponent.needsBoundsAnimation()) { mRepaintNext = 1; mRootLayoutComponent.clearNeedsBoundsAnimation(); mRootLayoutComponent.animatingBounds(context); } if (DEBUG) { String hierarchy = mRootLayoutComponent.displayHierarchy(); System.out.println(hierarchy); Loading @@ -1081,6 +1096,7 @@ public class CoreDocument { op.markNotDirty(); ((VariableSupport) op).updateVariables(context); } context.incrementOpCount(); op.apply(context); } } Loading @@ -1093,6 +1109,38 @@ public class CoreDocument { if (DEBUG && mRootLayoutComponent != null) { System.out.println(mRootLayoutComponent.displayHierarchy()); } mLastOpCount = context.getLastOpCount(); } /** * Get an estimated number of operations executed in a paint * * @return number of operations */ public int getNumberOfOps() { int count = mOperations.size(); for (Operation mOperation : mOperations) { if (mOperation instanceof Component) { count += getChildOps((Component) mOperation); } } return count; } private int getChildOps(@NonNull Component base) { int count = base.mList.size(); for (Operation mOperation : base.mList) { if (mOperation instanceof Component) { int mult = 1; if (mOperation instanceof LoopOperation) { mult = ((LoopOperation) mOperation).estimateIterations(); } count += mult * getChildOps((Component) mOperation); } } return count; } @NonNull Loading @@ -1116,6 +1164,9 @@ public class CoreDocument { if (mOperation instanceof Component) { Component com = (Component) mOperation; count += addChildren(com, map, buffer); } else if (mOperation instanceof LoopOperation) { LoopOperation com = (LoopOperation) mOperation; count += addChildren(com, map, buffer); } } Loading Loading @@ -1153,6 +1204,35 @@ public class CoreDocument { if (mOperation instanceof Component) { count += addChildren((Component) mOperation, map, tmp); } if (mOperation instanceof LoopOperation) { count += addChildren((LoopOperation) mOperation, map, tmp); } } return count; } private int addChildren( @NonNull LoopOperation base, @NonNull HashMap<String, int[]> map, @NonNull WireBuffer tmp) { int count = base.mList.size(); for (Operation mOperation : base.mList) { Class<? extends Operation> c = mOperation.getClass(); int[] values; if (map.containsKey(c.getSimpleName())) { values = map.get(c.getSimpleName()); } else { values = new int[2]; map.put(c.getSimpleName(), values); } values[0] += 1; values[1] += sizeOfComponent(mOperation, tmp); if (mOperation instanceof Component) { count += addChildren((Component) mOperation, map, tmp); } if (mOperation instanceof LoopOperation) { count += addChildren((LoopOperation) mOperation, map, tmp); } } return count; } Loading Loading @@ -1198,7 +1278,6 @@ public class CoreDocument { * @param ctl the call back to allow evaluation of shaders */ public void checkShaders(RemoteContext context, ShaderControl ctl) { int count = 0; for (Operation op : mOperations) { if (op instanceof TextData) { op.apply(context); Loading core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java +21 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.time.ZoneOffset; * <p>We also contain a PaintContext, so that any operation can draw as needed. */ public abstract class RemoteContext { private static final int MAX_OP_COUNT = 100_000; // Maximum cmds per frame protected @NonNull CoreDocument mDocument = new CoreDocument(); // todo: is this a valid way to initialize? bbade@ public @NonNull RemoteComposeState mRemoteComposeState = Loading @@ -52,6 +53,7 @@ public abstract class RemoteContext { int mDebug = 0; private int mOpCount; private int mTheme = Theme.UNSPECIFIED; public float mWidth = 0f; Loading Loading @@ -631,4 +633,23 @@ public abstract class RemoteContext { float right, float bottom, int metadataId); /** increments the count of operations executed in a pass */ public void incrementOpCount() { mOpCount++; if (mOpCount > MAX_OP_COUNT) { throw new RuntimeException("Too many operations executed"); } } /** * Get the last Op Count and clear the count. * * @return the number of ops executed. */ public int getLastOpCount() { int count = mOpCount; mOpCount = 0; return count; } } core/java/com/android/internal/widget/remotecompose/core/TimeVariables.java +1 −1 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ import java.time.ZoneOffset; /** This generates the standard system variables for time. */ public class TimeVariables { private static final float BUILD = 0.01f; private static final float BUILD = 0.02f; /** * This class populates all time variables in the system Loading core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java +1 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ public class ClickModifierOperation extends PaintOperation for (Operation op : mList) { if (op instanceof TextData) { op.apply(context); context.incrementOpCount(); } } } Loading core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java +62 −7 Original line number Diff line number Diff line Loading @@ -66,6 +66,34 @@ public class Component extends PaintOperation implements Measurable, Serializabl protected float mZIndex = 0f; private boolean mNeedsBoundsAnimation = false; /** * Mark the component as needing a bounds animation pass */ public void markNeedsBoundsAnimation() { mNeedsBoundsAnimation = true; if (mParent != null && !mParent.mNeedsBoundsAnimation) { mParent.markNeedsBoundsAnimation(); } } /** * Clear the bounds animation pass flag */ public void clearNeedsBoundsAnimation() { mNeedsBoundsAnimation = false; } /** * True if needs a bounds animation * * @return true if needs a bounds animation pass */ public boolean needsBoundsAnimation() { return mNeedsBoundsAnimation; } public float getZIndex() { return mZIndex; } Loading Loading @@ -382,12 +410,40 @@ public class Component extends PaintOperation implements Measurable, Serializabl } else { mVisibility = m.getVisibility(); } if (mAnimateMeasure == null) { setWidth(m.getW()); setHeight(m.getH()); setLayoutPosition(m.getX(), m.getY()); updateComponentValues(context); clearNeedsBoundsAnimation(); } else { mAnimateMeasure.apply(context); updateComponentValues(context); markNeedsBoundsAnimation(); } mFirstLayout = false; } /** * Animate the bounds of the component as needed * @param context */ public void animatingBounds(@NonNull RemoteContext context) { if (mAnimateMeasure != null) { mAnimateMeasure.apply(context); updateComponentValues(context); markNeedsBoundsAnimation(); } else { clearNeedsBoundsAnimation(); } for (Operation op : mList) { if (op instanceof Measurable) { Measurable m = (Measurable) op; m.animatingBounds(context); } } } @NonNull public float[] locationInWindow = new float[2]; public boolean contains(float x, float y) { Loading Loading @@ -698,9 +754,6 @@ public class Component extends PaintOperation implements Measurable, Serializabl } public void paintingComponent(@NonNull PaintContext context) { if (!mComponentValues.isEmpty()) { updateComponentValues(context.getContext()); } if (mPreTranslate != null) { mPreTranslate.paint(context); } Loading @@ -718,8 +771,10 @@ public class Component extends PaintOperation implements Measurable, Serializabl } if (op instanceof PaintOperation) { ((PaintOperation) op).paint(context); context.getContext().incrementOpCount(); } else { op.apply(context.getContext()); context.getContext().incrementOpCount(); } } context.restore(); Loading @@ -728,7 +783,7 @@ public class Component extends PaintOperation implements Measurable, Serializabl public boolean applyAnimationAsNeeded(@NonNull PaintContext context) { if (context.isAnimationEnabled() && mAnimateMeasure != null) { mAnimateMeasure.apply(context); mAnimateMeasure.paint(context); context.needsRepaint(); return true; } Loading Loading
core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java +94 −15 Original line number Diff line number Diff line Loading @@ -699,6 +699,7 @@ public class CoreDocument { } op.markNotDirty(); op.apply(context); context.incrementOpCount(); } } Loading Loading @@ -1000,6 +1001,16 @@ public class CoreDocument { private final float[] mScaleOutput = new float[2]; private final float[] mTranslateOutput = new float[2]; private int mRepaintNext = -1; // delay to next repaint -1 = don't 1 = asap private int mLastOpCount; /** * This is the number of ops used to calculate the last frame. * * @return number of ops */ public int getOpsPerFrame() { return mLastOpCount; } /** * Returns > 0 if it needs to repaint Loading @@ -1017,6 +1028,7 @@ public class CoreDocument { * @param theme the theme we want to use for this document. */ public void paint(@NonNull RemoteContext context, int theme) { context.getLastOpCount(); context.getPaintContext().clearNeedsRepaint(); context.loadFloat(RemoteContext.ID_DENSITY, context.getDensity()); context.mMode = RemoteContext.ContextMode.UNSET; Loading @@ -1027,21 +1039,24 @@ public class CoreDocument { context.mRemoteComposeState = mRemoteComposeState; context.mRemoteComposeState.setContext(context); // If we have a content sizing set, we are going to take the original document // dimension into account and apply scale+translate according to the RootContentBehavior // rules. if (mContentSizing == RootContentBehavior.SIZING_SCALE) { // we need to add canvas transforms ops here computeScale(context.mWidth, context.mHeight, mScaleOutput); computeTranslate( context.mWidth, context.mHeight, mScaleOutput[0], mScaleOutput[1], mTranslateOutput); float sw = mScaleOutput[0]; float sh = mScaleOutput[1]; computeTranslate(context.mWidth, context.mHeight, sw, sh, mTranslateOutput); context.mPaintContext.translate(mTranslateOutput[0], mTranslateOutput[1]); context.mPaintContext.scale(mScaleOutput[0], mScaleOutput[1]); context.mPaintContext.scale(sw, sh); } else { // If not, we set the document width and height to be the current context width and // height. setWidth((int) context.mWidth); setHeight((int) context.mHeight); } mTimeVariables.updateTime(context); context.loadFloat(RemoteContext.ID_WINDOW_WIDTH, context.mWidth); context.loadFloat(RemoteContext.ID_WINDOW_HEIGHT, context.mHeight); mRepaintNext = context.updateOps(); if (mRootLayoutComponent != null) { if (context.mWidth != mRootLayoutComponent.getWidth() Loading @@ -1051,11 +1066,11 @@ public class CoreDocument { if (mRootLayoutComponent.needsMeasure()) { mRootLayoutComponent.layout(context); } // TODO -- this should be specifically about applying animation, not paint mRootLayoutComponent.paint(context.getPaintContext()); context.mPaintContext.reset(); // TODO -- should be able to remove this mRootLayoutComponent.updateVariables(context); if (mRootLayoutComponent.needsBoundsAnimation()) { mRepaintNext = 1; mRootLayoutComponent.clearNeedsBoundsAnimation(); mRootLayoutComponent.animatingBounds(context); } if (DEBUG) { String hierarchy = mRootLayoutComponent.displayHierarchy(); System.out.println(hierarchy); Loading @@ -1081,6 +1096,7 @@ public class CoreDocument { op.markNotDirty(); ((VariableSupport) op).updateVariables(context); } context.incrementOpCount(); op.apply(context); } } Loading @@ -1093,6 +1109,38 @@ public class CoreDocument { if (DEBUG && mRootLayoutComponent != null) { System.out.println(mRootLayoutComponent.displayHierarchy()); } mLastOpCount = context.getLastOpCount(); } /** * Get an estimated number of operations executed in a paint * * @return number of operations */ public int getNumberOfOps() { int count = mOperations.size(); for (Operation mOperation : mOperations) { if (mOperation instanceof Component) { count += getChildOps((Component) mOperation); } } return count; } private int getChildOps(@NonNull Component base) { int count = base.mList.size(); for (Operation mOperation : base.mList) { if (mOperation instanceof Component) { int mult = 1; if (mOperation instanceof LoopOperation) { mult = ((LoopOperation) mOperation).estimateIterations(); } count += mult * getChildOps((Component) mOperation); } } return count; } @NonNull Loading @@ -1116,6 +1164,9 @@ public class CoreDocument { if (mOperation instanceof Component) { Component com = (Component) mOperation; count += addChildren(com, map, buffer); } else if (mOperation instanceof LoopOperation) { LoopOperation com = (LoopOperation) mOperation; count += addChildren(com, map, buffer); } } Loading Loading @@ -1153,6 +1204,35 @@ public class CoreDocument { if (mOperation instanceof Component) { count += addChildren((Component) mOperation, map, tmp); } if (mOperation instanceof LoopOperation) { count += addChildren((LoopOperation) mOperation, map, tmp); } } return count; } private int addChildren( @NonNull LoopOperation base, @NonNull HashMap<String, int[]> map, @NonNull WireBuffer tmp) { int count = base.mList.size(); for (Operation mOperation : base.mList) { Class<? extends Operation> c = mOperation.getClass(); int[] values; if (map.containsKey(c.getSimpleName())) { values = map.get(c.getSimpleName()); } else { values = new int[2]; map.put(c.getSimpleName(), values); } values[0] += 1; values[1] += sizeOfComponent(mOperation, tmp); if (mOperation instanceof Component) { count += addChildren((Component) mOperation, map, tmp); } if (mOperation instanceof LoopOperation) { count += addChildren((LoopOperation) mOperation, map, tmp); } } return count; } Loading Loading @@ -1198,7 +1278,6 @@ public class CoreDocument { * @param ctl the call back to allow evaluation of shaders */ public void checkShaders(RemoteContext context, ShaderControl ctl) { int count = 0; for (Operation op : mOperations) { if (op instanceof TextData) { op.apply(context); Loading
core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java +21 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import java.time.ZoneOffset; * <p>We also contain a PaintContext, so that any operation can draw as needed. */ public abstract class RemoteContext { private static final int MAX_OP_COUNT = 100_000; // Maximum cmds per frame protected @NonNull CoreDocument mDocument = new CoreDocument(); // todo: is this a valid way to initialize? bbade@ public @NonNull RemoteComposeState mRemoteComposeState = Loading @@ -52,6 +53,7 @@ public abstract class RemoteContext { int mDebug = 0; private int mOpCount; private int mTheme = Theme.UNSPECIFIED; public float mWidth = 0f; Loading Loading @@ -631,4 +633,23 @@ public abstract class RemoteContext { float right, float bottom, int metadataId); /** increments the count of operations executed in a pass */ public void incrementOpCount() { mOpCount++; if (mOpCount > MAX_OP_COUNT) { throw new RuntimeException("Too many operations executed"); } } /** * Get the last Op Count and clear the count. * * @return the number of ops executed. */ public int getLastOpCount() { int count = mOpCount; mOpCount = 0; return count; } }
core/java/com/android/internal/widget/remotecompose/core/TimeVariables.java +1 −1 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ import java.time.ZoneOffset; /** This generates the standard system variables for time. */ public class TimeVariables { private static final float BUILD = 0.01f; private static final float BUILD = 0.02f; /** * This class populates all time variables in the system Loading
core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java +1 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ public class ClickModifierOperation extends PaintOperation for (Operation op : mList) { if (op instanceof TextData) { op.apply(context); context.incrementOpCount(); } } } Loading
core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java +62 −7 Original line number Diff line number Diff line Loading @@ -66,6 +66,34 @@ public class Component extends PaintOperation implements Measurable, Serializabl protected float mZIndex = 0f; private boolean mNeedsBoundsAnimation = false; /** * Mark the component as needing a bounds animation pass */ public void markNeedsBoundsAnimation() { mNeedsBoundsAnimation = true; if (mParent != null && !mParent.mNeedsBoundsAnimation) { mParent.markNeedsBoundsAnimation(); } } /** * Clear the bounds animation pass flag */ public void clearNeedsBoundsAnimation() { mNeedsBoundsAnimation = false; } /** * True if needs a bounds animation * * @return true if needs a bounds animation pass */ public boolean needsBoundsAnimation() { return mNeedsBoundsAnimation; } public float getZIndex() { return mZIndex; } Loading Loading @@ -382,12 +410,40 @@ public class Component extends PaintOperation implements Measurable, Serializabl } else { mVisibility = m.getVisibility(); } if (mAnimateMeasure == null) { setWidth(m.getW()); setHeight(m.getH()); setLayoutPosition(m.getX(), m.getY()); updateComponentValues(context); clearNeedsBoundsAnimation(); } else { mAnimateMeasure.apply(context); updateComponentValues(context); markNeedsBoundsAnimation(); } mFirstLayout = false; } /** * Animate the bounds of the component as needed * @param context */ public void animatingBounds(@NonNull RemoteContext context) { if (mAnimateMeasure != null) { mAnimateMeasure.apply(context); updateComponentValues(context); markNeedsBoundsAnimation(); } else { clearNeedsBoundsAnimation(); } for (Operation op : mList) { if (op instanceof Measurable) { Measurable m = (Measurable) op; m.animatingBounds(context); } } } @NonNull public float[] locationInWindow = new float[2]; public boolean contains(float x, float y) { Loading Loading @@ -698,9 +754,6 @@ public class Component extends PaintOperation implements Measurable, Serializabl } public void paintingComponent(@NonNull PaintContext context) { if (!mComponentValues.isEmpty()) { updateComponentValues(context.getContext()); } if (mPreTranslate != null) { mPreTranslate.paint(context); } Loading @@ -718,8 +771,10 @@ public class Component extends PaintOperation implements Measurable, Serializabl } if (op instanceof PaintOperation) { ((PaintOperation) op).paint(context); context.getContext().incrementOpCount(); } else { op.apply(context.getContext()); context.getContext().incrementOpCount(); } } context.restore(); Loading @@ -728,7 +783,7 @@ public class Component extends PaintOperation implements Measurable, Serializabl public boolean applyAnimationAsNeeded(@NonNull PaintContext context) { if (context.isAnimationEnabled() && mAnimateMeasure != null) { mAnimateMeasure.apply(context); mAnimateMeasure.paint(context); context.needsRepaint(); return true; } Loading