hwui: send TextureView hint to SF
So that SF could use this hint when choosing the refresh rate. SF would only try to heuristically calculate the frame rate of a layer when TextureView is updating. This fixes a bug where SF tries to heuristically calculate the frame rate for UI animations but fails due to long frames. Bug: 280249265 Test: Playing a video on Facebook and observe refresh rate Test: go/cb-pcmark Change-Id: I0d54d62b97ff48583fbe3cc0da188fe85810fd5e
This commit is contained in:
@@ -206,6 +206,7 @@ public class TextureView extends View {
|
||||
*/
|
||||
public TextureView(@NonNull Context context) {
|
||||
super(context);
|
||||
mRenderNode.setIsTextureView();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,6 +217,7 @@ public class TextureView extends View {
|
||||
*/
|
||||
public TextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mRenderNode.setIsTextureView();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,6 +231,7 @@ public class TextureView extends View {
|
||||
*/
|
||||
public TextureView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mRenderNode.setIsTextureView();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,6 +250,7 @@ public class TextureView extends View {
|
||||
public TextureView(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
mRenderNode.setIsTextureView();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1561,6 +1561,16 @@ public final class RenderNode {
|
||||
return nGetUniqueId(mNativeRenderNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures whether this RenderNote represents a TextureView
|
||||
* TODO(b/281695725): Clean this up once TextureView use setFrameRate API
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void setIsTextureView() {
|
||||
nSetIsTextureView(mNativeRenderNode);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Animations
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -1891,4 +1901,7 @@ public final class RenderNode {
|
||||
|
||||
@CriticalNative
|
||||
private static native long nGetUniqueId(long renderNode);
|
||||
|
||||
@CriticalNative
|
||||
private static native void nSetIsTextureView(long renderNode);
|
||||
}
|
||||
|
||||
@@ -152,6 +152,9 @@ void RenderNode::damageSelf(TreeInfo& info) {
|
||||
// TODO: Get this from the display list ops or something
|
||||
info.damageAccumulator->dirty(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX);
|
||||
}
|
||||
if (!mIsTextureView) {
|
||||
info.out.solelyTextureViewUpdates = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -221,6 +221,8 @@ public:
|
||||
|
||||
int64_t uniqueId() const { return mUniqueId; }
|
||||
|
||||
void setIsTextureView() { mIsTextureView = true; }
|
||||
|
||||
void markDrawStart(SkCanvas& canvas);
|
||||
void markDrawEnd(SkCanvas& canvas);
|
||||
|
||||
@@ -290,6 +292,8 @@ private:
|
||||
bool mHasHolePunches;
|
||||
StretchMask mStretchMask;
|
||||
|
||||
bool mIsTextureView = false;
|
||||
|
||||
// METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -123,6 +123,10 @@ public:
|
||||
// This is used to post a message to redraw when it is time to draw the
|
||||
// next frame of an AnimatedImageDrawable.
|
||||
nsecs_t animatedImageDelay = kNoAnimatedImageDelay;
|
||||
// This is used to determine if there were only TextureView updates in this frame.
|
||||
// This info is passed to SurfaceFlinger to determine whether it should use vsyncIds
|
||||
// for refresh rate selection.
|
||||
bool solelyTextureViewUpdates = true;
|
||||
} out;
|
||||
|
||||
// This flag helps to disable projection for receiver nodes that do not have any backward
|
||||
|
||||
@@ -526,6 +526,11 @@ static jlong android_view_RenderNode_getUniqueId(CRITICAL_JNI_PARAMS_COMMA jlong
|
||||
return reinterpret_cast<RenderNode*>(renderNodePtr)->uniqueId();
|
||||
}
|
||||
|
||||
static void android_view_RenderNode_setIsTextureView(
|
||||
CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
|
||||
reinterpret_cast<RenderNode*>(renderNodePtr)->setIsTextureView();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// RenderProperties - Animations
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -844,6 +849,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"nSetAllowForceDark", "(JZ)Z", (void*)android_view_RenderNode_setAllowForceDark},
|
||||
{"nGetAllowForceDark", "(J)Z", (void*)android_view_RenderNode_getAllowForceDark},
|
||||
{"nGetUniqueId", "(J)J", (void*)android_view_RenderNode_getUniqueId},
|
||||
{"nSetIsTextureView", "(J)V", (void*)android_view_RenderNode_setIsTextureView},
|
||||
};
|
||||
|
||||
int register_android_view_RenderNode(JNIEnv* env) {
|
||||
|
||||
@@ -531,7 +531,7 @@ Frame CanvasContext::getFrame() {
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasContext::draw() {
|
||||
void CanvasContext::draw(bool solelyTextureViewUpdates) {
|
||||
if (auto grContext = getGrContext()) {
|
||||
if (grContext->abandoned()) {
|
||||
LOG_ALWAYS_FATAL("GrContext is abandoned/device lost at start of CanvasContext::draw");
|
||||
@@ -604,7 +604,8 @@ void CanvasContext::draw() {
|
||||
static_cast<int32_t>(mCurrentFrameInfo->get(FrameInfoIndex::InputEventId));
|
||||
native_window_set_frame_timeline_info(
|
||||
mNativeSurface->getNativeWindow(), frameCompleteNr, vsyncId, inputEventId,
|
||||
mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime));
|
||||
mCurrentFrameInfo->get(FrameInfoIndex::FrameStartTime),
|
||||
solelyTextureViewUpdates);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,7 +886,7 @@ void CanvasContext::prepareAndDraw(RenderNode* node) {
|
||||
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
|
||||
prepareTree(info, frameInfo, systemTime(SYSTEM_TIME_MONOTONIC), node);
|
||||
if (info.out.canDrawThisFrame) {
|
||||
draw();
|
||||
draw(info.out.solelyTextureViewUpdates);
|
||||
} else {
|
||||
// wait on fences so tasks don't overlap next frame
|
||||
waitOnFences();
|
||||
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
bool makeCurrent();
|
||||
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
|
||||
// Returns the DequeueBufferDuration.
|
||||
void draw();
|
||||
void draw(bool solelyTextureViewUpdates);
|
||||
void destroy();
|
||||
|
||||
// IFrameCallback, Choreographer-driven frame callback entry point
|
||||
|
||||
@@ -98,12 +98,14 @@ void DrawFrameTask::run() {
|
||||
IRenderPipeline* pipeline = mContext->getRenderPipeline();
|
||||
bool canUnblockUiThread;
|
||||
bool canDrawThisFrame;
|
||||
bool solelyTextureViewUpdates;
|
||||
{
|
||||
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
|
||||
info.forceDrawFrame = mForceDrawFrame;
|
||||
mForceDrawFrame = false;
|
||||
canUnblockUiThread = syncFrameState(info);
|
||||
canDrawThisFrame = info.out.canDrawThisFrame;
|
||||
solelyTextureViewUpdates = info.out.solelyTextureViewUpdates;
|
||||
|
||||
if (mFrameCommitCallback) {
|
||||
mContext->addFrameCommitListener(std::move(mFrameCommitCallback));
|
||||
@@ -136,7 +138,7 @@ void DrawFrameTask::run() {
|
||||
}
|
||||
|
||||
if (CC_LIKELY(canDrawThisFrame)) {
|
||||
context->draw();
|
||||
context->draw(solelyTextureViewUpdates);
|
||||
} else {
|
||||
// Do a flush in case syncFrameState performed any texture uploads. Since we skipped
|
||||
// the draw() call, those uploads (or deletes) will end up sitting in the queue.
|
||||
@@ -179,6 +181,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
|
||||
mLayers[i]->apply();
|
||||
}
|
||||
}
|
||||
|
||||
mLayers.clear();
|
||||
mContext->setContentDrawBounds(mContentDrawBounds);
|
||||
mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
|
||||
|
||||
Reference in New Issue
Block a user