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,6 +169,18 @@ RenderedFrameId RendererOGL::UpdateAndRender(
widgetContext.mGL = mCompositor->gl();
#endif
// 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;
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.
@@ -176,24 +188,30 @@ RenderedFrameId RendererOGL::UpdateAndRender(
}
// XXX set clear color if MOZ_WIDGET_ANDROID is defined.
if (mThread->IsHandlingDeviceReset() || !mCompositor->BeginFrame()) {
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,22 +221,28 @@ RenderedFrameId RendererOGL::UpdateAndRender(
bufferAge, aOutStats, &dirtyRects);
FlushPipelineInfo();
if (!rendered) {
if (present) {
mCompositor->CancelFrame();
RenderThread::Get()->HandleWebRenderError(WebRenderError::RENDER);
mCompositor->GetWidget()->PostRender(&widgetContext);
}
RenderThread::Get()->HandleWebRenderError(WebRenderError::RENDER);
return RenderedFrameId();
}
RenderedFrameId frameId;
if (present) {
if (aReadbackBuffer.isSome()) {
MOZ_ASSERT(aReadbackSize.isSome());
MOZ_ASSERT(aReadbackFormat.isSome());
if (!mCompositor->MaybeReadback(aReadbackSize.ref(), aReadbackFormat.ref(),
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) {
if (aNeedsYFlip != nullptr) {
*aNeedsYFlip = !mCompositor->SurfaceOriginIsTopLeft();
}
}
@@ -230,14 +254,13 @@ RenderedFrameId RendererOGL::UpdateAndRender(
}
}
// 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.
// 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);
frameId = mCompositor->EndFrame(dirtyRects);
mCompositor->GetWidget()->PostRender(&widgetContext);
}
#if defined(ENABLE_FRAME_LATENCY_LOG)
if (mFrameStartTime) {
@@ -249,9 +272,11 @@ RenderedFrameId RendererOGL::UpdateAndRender(
mFrameStartTime = TimeStamp();
#endif
if (present) {
if (!mCompositor->MaybeProcessScreenshotQueue()) {
mScreenshotGrabber.MaybeProcessQueue(this);
}
}
// TODO: Flush pending actions such as texture deletions/unlocks and
// textureHosts recycling.

View File

@@ -1274,10 +1274,16 @@ impl Renderer {
.remove(&doc_id)
.unwrap();
let size = if !device_size.is_empty() {
Some(device_size)
} else {
None
};
let result = self.render_impl(
doc_id,
&mut doc,
Some(device_size),
size,
buffer_age,
);