Add forceDrawNextFrame function for HardwareRenderer
The forceDraw flag in HardwareRenderer will ensure a frame is drawn when requested even if it would end up drawing multiple frames in a single vsync. This is to help blast sync when we want to synchronize the buffer. We want to make sure we are guaranteed a callback since we don't want to wait for retries, especially in the case when trying to synchronize multiple buffers. There was already a global flag to handle this, but would use the flag for all draws. This new function is set per draw so once a frame is drawn it's unset. The global flag was only used for tests so updated the test to set the flag before every draw and deleted the global property. Test: Underlying code was in place. This is just piping a new setter. No usages yet. Test: TestSceneRunner Bug: 200284684 Change-Id: Ie1c9950cabb7331cfed1721564a51a1a15cd1624
This commit is contained in:
@@ -849,6 +849,14 @@ public class HardwareRenderer {
|
||||
nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the new frame to draw, ensuring the UI draw request will attempt a draw this vsync.
|
||||
* @hide
|
||||
*/
|
||||
public void forceDrawNextFrame() {
|
||||
nForceDrawNextFrame(mNativeProxy);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setPictureCaptureCallback(@Nullable PictureCapturedCallback callback) {
|
||||
nSetPictureCaptureCallback(mNativeProxy, callback);
|
||||
@@ -1423,6 +1431,8 @@ public class HardwareRenderer {
|
||||
private static native void nSetContentDrawBounds(long nativeProxy, int left,
|
||||
int top, int right, int bottom);
|
||||
|
||||
private static native void nForceDrawNextFrame(long nativeProxy);
|
||||
|
||||
private static native void nSetPictureCaptureCallback(long nativeProxy,
|
||||
PictureCapturedCallback callback);
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ RenderPipelineType Properties::sRenderPipelineType = RenderPipelineType::NotInit
|
||||
bool Properties::enableHighContrastText = false;
|
||||
|
||||
bool Properties::waitForGpuCompletion = false;
|
||||
bool Properties::forceDrawFrame = false;
|
||||
|
||||
bool Properties::filterOutTestOverhead = false;
|
||||
bool Properties::disableVsync = false;
|
||||
|
||||
@@ -100,6 +100,8 @@ public:
|
||||
|
||||
int stretchEffectCount = 0;
|
||||
|
||||
bool forceDrawFrame = false;
|
||||
|
||||
struct Out {
|
||||
bool hasFunctors = false;
|
||||
// This is only updated if evaluateAnimations is true
|
||||
|
||||
@@ -259,7 +259,8 @@ static void android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv* env, jobject c
|
||||
}
|
||||
|
||||
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
|
||||
jlong proxyPtr, jlongArray frameInfo,
|
||||
jint frameInfoSize) {
|
||||
LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
|
||||
"Mismatched size expectations, given %d expected %zu", frameInfoSize,
|
||||
UI_THREAD_FRAME_INFO_SIZE);
|
||||
@@ -413,6 +414,12 @@ static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
|
||||
proxy->setContentDrawBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_forceDrawNextFrame(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
proxy->forceDrawNextFrame();
|
||||
}
|
||||
|
||||
class JGlobalRefHolder {
|
||||
public:
|
||||
JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
|
||||
@@ -935,6 +942,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"nDrawRenderNode", "(JJ)V", (void*)android_view_ThreadedRendererd_drawRenderNode},
|
||||
{"nSetContentDrawBounds", "(JIIII)V",
|
||||
(void*)android_view_ThreadedRenderer_setContentDrawBounds},
|
||||
{"nForceDrawNextFrame", "(J)V", (void*)android_view_ThreadedRenderer_forceDrawNextFrame},
|
||||
{"nSetPictureCaptureCallback",
|
||||
"(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V",
|
||||
(void*)android_view_ThreadedRenderer_setPictureCapturedCallbackJNI},
|
||||
|
||||
@@ -390,7 +390,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
|
||||
return;
|
||||
}
|
||||
|
||||
if (CC_LIKELY(mSwapHistory.size() && !Properties::forceDrawFrame)) {
|
||||
if (CC_LIKELY(mSwapHistory.size() && !info.forceDrawFrame)) {
|
||||
nsecs_t latestVsync = mRenderThread.timeLord().latestVsync();
|
||||
SwapHistory& lastSwap = mSwapHistory.back();
|
||||
nsecs_t vsyncDelta = std::abs(lastSwap.vsyncTime - latestVsync);
|
||||
|
||||
@@ -148,6 +148,8 @@ void DrawFrameTask::run() {
|
||||
bool canDrawThisFrame;
|
||||
{
|
||||
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
|
||||
info.forceDrawFrame = mForceDrawFrame;
|
||||
mForceDrawFrame = false;
|
||||
canUnblockUiThread = syncFrameState(info);
|
||||
canDrawThisFrame = info.out.canDrawThisFrame;
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ public:
|
||||
mFrameCompleteCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void forceDrawNextFrame() { mForceDrawFrame = true; }
|
||||
|
||||
private:
|
||||
class HintSessionWrapper {
|
||||
public:
|
||||
@@ -132,6 +134,8 @@ private:
|
||||
nsecs_t mLastDequeueBufferDuration = 0;
|
||||
nsecs_t mLastTargetWorkDuration = 0;
|
||||
std::optional<HintSessionWrapper> mHintSessionWrapper;
|
||||
|
||||
bool mForceDrawFrame = false;
|
||||
};
|
||||
|
||||
} /* namespace renderthread */
|
||||
|
||||
@@ -133,6 +133,10 @@ int64_t* RenderProxy::frameInfo() {
|
||||
return mDrawFrameTask.frameInfo();
|
||||
}
|
||||
|
||||
void RenderProxy::forceDrawNextFrame() {
|
||||
mDrawFrameTask.forceDrawNextFrame();
|
||||
}
|
||||
|
||||
int RenderProxy::syncAndDrawFrame() {
|
||||
return mDrawFrameTask.drawFrame();
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
void setOpaque(bool opaque);
|
||||
void setColorMode(ColorMode mode);
|
||||
int64_t* frameInfo();
|
||||
void forceDrawNextFrame();
|
||||
int syncAndDrawFrame();
|
||||
void destroy();
|
||||
|
||||
|
||||
@@ -104,7 +104,6 @@ static void doRun(const TestScene::Info& info, const TestScene::Options& opts, i
|
||||
// If we're reporting GPU memory usage we need to first start with a clean slate
|
||||
RenderProxy::purgeCaches();
|
||||
}
|
||||
Properties::forceDrawFrame = true;
|
||||
TestContext testContext;
|
||||
testContext.setRenderOffscreen(opts.renderOffscreen);
|
||||
|
||||
@@ -144,6 +143,7 @@ static void doRun(const TestScene::Info& info, const TestScene::Options& opts, i
|
||||
.setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
|
||||
UiFrameInfoBuilder::UNKNOWN_DEADLINE,
|
||||
UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL);
|
||||
proxy->forceDrawNextFrame();
|
||||
proxy->syncAndDrawFrame();
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@ static void doRun(const TestScene::Info& info, const TestScene::Options& opts, i
|
||||
UiFrameInfoBuilder::UNKNOWN_DEADLINE,
|
||||
UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL);
|
||||
scene->doFrame(i);
|
||||
proxy->forceDrawNextFrame();
|
||||
proxy->syncAndDrawFrame();
|
||||
}
|
||||
if (opts.reportFrametimeWeight) {
|
||||
|
||||
Reference in New Issue
Block a user