Bug 1961115 - Skip compositor-related work when rendering without presenting. r=gfx-reviewers,gw

Differential Revision: https://phabricator.services.mozilla.com/D245565
This commit is contained in:
Nicolas Silva
2025-04-18 12:56:23 +00:00
parent a7fed60e37
commit a1c5094586
2 changed files with 78 additions and 47 deletions

View File

@@ -169,31 +169,49 @@ RenderedFrameId RendererOGL::UpdateAndRender(
widgetContext.mGL = mCompositor->gl();
#endif
if (!mCompositor->GetWidget()->PreRender(&widgetContext)) {
// XXX This could cause oom in webrender since pending_texture_updates is
// not handled. It needs to be addressed.
return RenderedFrameId();
}
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
// If present is false, WebRender needs to render some offscreen content
// but we don't want to touch the window, so we avoid most interactions
// with mCompositor.
bool present = aFrameParams.present;
if (mThread->IsHandlingDeviceReset() || !mCompositor->BeginFrame()) {
LayoutDeviceIntSize size(0, 0);
auto bufferAge = 0;
bool fullRender = false;
bool beginFrame = !mThread->IsHandlingDeviceReset();
if (beginFrame && present) {
if (!mCompositor->GetWidget()->PreRender(&widgetContext)) {
// XXX This could cause oom in webrender since pending_texture_updates is
// not handled. It needs to be addressed.
return RenderedFrameId();
}
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
if (!mCompositor->BeginFrame()) {
beginFrame = false;
}
size = mCompositor->GetBufferSize();
bufferAge = mCompositor->GetBufferAge();
fullRender = mCompositor->RequestFullRender();
// When we're rendering to an external target, we want to render everything.
if (mCompositor->UsePartialPresent() &&
(aReadbackBuffer.isSome() ||
layers::ProfilerScreenshots::IsEnabled())) {
fullRender = true;
}
}
if (!beginFrame) {
CheckGraphicsResetStatus(gfx::DeviceResetDetectPlace::WR_BEGIN_FRAME,
/* aForce */ true);
mCompositor->GetWidget()->PostRender(&widgetContext);
return RenderedFrameId();
}
auto size = mCompositor->GetBufferSize();
auto bufferAge = mCompositor->GetBufferAge();
wr_renderer_update(mRenderer);
bool fullRender = mCompositor->RequestFullRender();
// When we're rendering to an external target, we want to render everything.
if (mCompositor->UsePartialPresent() &&
(aReadbackBuffer.isSome() || layers::ProfilerScreenshots::IsEnabled())) {
fullRender = true;
}
if (fullRender) {
wr_renderer_force_redraw(mRenderer);
}
@@ -203,42 +221,47 @@ RenderedFrameId RendererOGL::UpdateAndRender(
bufferAge, aOutStats, &dirtyRects);
FlushPipelineInfo();
if (!rendered) {
mCompositor->CancelFrame();
if (present) {
mCompositor->CancelFrame();
mCompositor->GetWidget()->PostRender(&widgetContext);
}
RenderThread::Get()->HandleWebRenderError(WebRenderError::RENDER);
mCompositor->GetWidget()->PostRender(&widgetContext);
return RenderedFrameId();
}
if (aReadbackBuffer.isSome()) {
MOZ_ASSERT(aReadbackSize.isSome());
MOZ_ASSERT(aReadbackFormat.isSome());
if (!mCompositor->MaybeReadback(aReadbackSize.ref(), aReadbackFormat.ref(),
aReadbackBuffer.ref(), aNeedsYFlip)) {
wr_renderer_readback(mRenderer, aReadbackSize.ref().width,
aReadbackSize.ref().height, aReadbackFormat.ref(),
&aReadbackBuffer.ref()[0],
aReadbackBuffer.ref().length());
if (aNeedsYFlip) {
*aNeedsYFlip = !mCompositor->SurfaceOriginIsTopLeft();
RenderedFrameId frameId;
if (present) {
if (aReadbackBuffer.isSome()) {
MOZ_ASSERT(aReadbackSize.isSome());
MOZ_ASSERT(aReadbackFormat.isSome());
if (!mCompositor->MaybeReadback(aReadbackSize.ref(),
aReadbackFormat.ref(),
aReadbackBuffer.ref(), aNeedsYFlip)) {
wr_renderer_readback(mRenderer, aReadbackSize.ref().width,
aReadbackSize.ref().height, aReadbackFormat.ref(),
&aReadbackBuffer.ref()[0],
aReadbackBuffer.ref().length());
if (aNeedsYFlip != nullptr) {
*aNeedsYFlip = !mCompositor->SurfaceOriginIsTopLeft();
}
}
}
}
if (size.Width() != 0 && size.Height() != 0) {
if (!mCompositor->MaybeGrabScreenshot(size.ToUnknownSize())) {
mScreenshotGrabber.MaybeGrabScreenshot(this, size.ToUnknownSize());
if (size.Width() != 0 && size.Height() != 0) {
if (!mCompositor->MaybeGrabScreenshot(size.ToUnknownSize())) {
mScreenshotGrabber.MaybeGrabScreenshot(this, size.ToUnknownSize());
}
}
// Frame recording must happen before EndFrame, as we must ensure we read
// the contents of the back buffer before any calls to SwapBuffers which
// might invalidate it.
MaybeRecordFrame(mLastPipelineInfo);
frameId = mCompositor->EndFrame(dirtyRects);
mCompositor->GetWidget()->PostRender(&widgetContext);
}
// Frame recording must happen before EndFrame, as we must ensure we read the
// contents of the back buffer before any calls to SwapBuffers which might
// invalidate it.
MaybeRecordFrame(mLastPipelineInfo);
RenderedFrameId frameId = mCompositor->EndFrame(dirtyRects);
mCompositor->GetWidget()->PostRender(&widgetContext);
#if defined(ENABLE_FRAME_LATENCY_LOG)
if (mFrameStartTime) {
uint32_t latencyMs =
@@ -249,8 +272,10 @@ RenderedFrameId RendererOGL::UpdateAndRender(
mFrameStartTime = TimeStamp();
#endif
if (!mCompositor->MaybeProcessScreenshotQueue()) {
mScreenshotGrabber.MaybeProcessQueue(this);
if (present) {
if (!mCompositor->MaybeProcessScreenshotQueue()) {
mScreenshotGrabber.MaybeProcessQueue(this);
}
}
// TODO: Flush pending actions such as texture deletions/unlocks and